diff --git a/lib/pinchflat/utils/number_utils.ex b/lib/pinchflat/utils/number_utils.ex new file mode 100644 index 0000000..fcfb296 --- /dev/null +++ b/lib/pinchflat/utils/number_utils.ex @@ -0,0 +1,12 @@ +defmodule Pinchflat.Utils.NumberUtils do + @moduledoc """ + Utility methods for working with numbers + """ + + # TODO: test + def clamp(num, minimum, maximum) do + num + |> max(minimum) + |> min(maximum) + end +end diff --git a/lib/pinchflat_web/components/custom_components/table_components.ex b/lib/pinchflat_web/components/custom_components/table_components.ex index fbe897c..c1bdc09 100644 --- a/lib/pinchflat_web/components/custom_components/table_components.ex +++ b/lib/pinchflat_web/components/custom_components/table_components.ex @@ -2,6 +2,8 @@ defmodule PinchflatWeb.CustomComponents.TableComponents do @moduledoc false use Phoenix.Component + alias PinchflatWeb.CoreComponents + @doc """ Renders a table component with the given rows and columns. @@ -50,4 +52,45 @@ defmodule PinchflatWeb.CustomComponents.TableComponents do """ end + + attr :page_number, :integer, default: 1 + attr :total_pages, :integer, default: 1 + + def pagination_controls(assigns) do + ~H""" + + """ + end end diff --git a/lib/pinchflat_web/controllers/sources/source_html/pending_table_live.ex b/lib/pinchflat_web/controllers/sources/source_html/pending_table_live.ex new file mode 100644 index 0000000..bc4512f --- /dev/null +++ b/lib/pinchflat_web/controllers/sources/source_html/pending_table_live.ex @@ -0,0 +1,83 @@ +defmodule Pinchflat.PendingTableLive do + use PinchflatWeb, :live_view + import Ecto.Query, warn: false + + alias Pinchflat.Repo + alias Pinchflat.Sources + alias Pinchflat.Media.MediaQuery + alias Pinchflat.Utils.NumberUtils + + @limit 10 + + def render(%{records: []} = assigns) do + ~H""" +

Nothing Here!

+ """ + end + + def render(assigns) do + ~H""" +
+ + Showing <%= length(@records) %> of <%= @total_record_count %> + + <.table rows={@records} table_class="text-black dark:text-white"> + <:col :let={media_item} label="Title"> + <.subtle_link href={~p"/sources/#{@source.id}/media/#{media_item.id}"}> + <%= StringUtils.truncate(media_item.title, 50) %> + + + <:col :let={media_item} label="" class="flex place-content-evenly"> + <.icon_link href={~p"/sources/#{@source.id}/media/#{media_item.id}"} icon="hero-eye" class="mx-1" /> + <.icon_link href={~p"/sources/#{@source.id}/media/#{media_item.id}/edit"} icon="hero-pencil-square" class="mx-1" /> + + +
+ <.pagination_controls page_number={@page} total_pages={@total_pages} /> +
+
+ """ + end + + def mount(_params, session, socket) do + page = 1 + source = Sources.get_source!(session["source_id"]) + base_query = generate_base_query(source) + pagination_attrs = fetch_pagination_attributes(base_query, page) + + {:ok, assign(socket, Map.merge(pagination_attrs, %{base_query: base_query, source: source}))} + end + + def handle_event("page_change", %{"direction" => direction}, %{assigns: assigns} = socket) do + direction = if direction == "inc", do: 1, else: -1 + new_page = assigns.page + direction + new_assigns = fetch_pagination_attributes(assigns.base_query, new_page) + + {:noreply, assign(socket, new_assigns)} + end + + defp fetch_pagination_attributes(base_query, page) do + total_record_count = Repo.aggregate(base_query, :count, :id) + total_pages = ceil(total_record_count / @limit) + page = NumberUtils.clamp(page, 1, total_pages) + records = fetch_records(base_query, page) + + %{page: page, total_pages: total_pages, records: records, total_record_count: total_record_count} + end + + defp generate_base_query(source) do + MediaQuery.new() + |> MediaQuery.for_source(source) + |> MediaQuery.where_pending_download() + |> order_by(desc: :id) + end + + defp fetch_records(base_query, page) do + offset = (page - 1) * @limit + + base_query + |> limit(^@limit) + |> offset(^offset) + |> Repo.all() + end +end diff --git a/lib/pinchflat_web/controllers/sources/source_html/show.html.heex b/lib/pinchflat_web/controllers/sources/source_html/show.html.heex index d9687a1..3c4bc7f 100644 --- a/lib/pinchflat_web/controllers/sources/source_html/show.html.heex +++ b/lib/pinchflat_web/controllers/sources/source_html/show.html.heex @@ -37,26 +37,7 @@ <:tab title="Pending Media"> - <%= if match?([_|_], @pending_media) do %> -

Shows a maximum of 100 media items

- <.table rows={@pending_media} table_class="text-black dark:text-white"> - <:col :let={media_item} label="Title"> - <.subtle_link href={~p"/sources/#{@source.id}/media/#{media_item.id}"}> - <%= StringUtils.truncate(media_item.title, 50) %> - - - <:col :let={media_item} label="" class="flex place-content-evenly"> - <.icon_link href={~p"/sources/#{@source.id}/media/#{media_item.id}"} icon="hero-eye" class="mx-1" /> - <.icon_link - href={~p"/sources/#{@source.id}/media/#{media_item.id}/edit"} - icon="hero-pencil-square" - class="mx-1" - /> - - - <% else %> -

Nothing Here!

- <% end %> + <%= live_render(@conn, Pinchflat.PendingTableLive, session: %{"source_id" => @source.id}) %> <:tab title="Downloaded Media"> <%= if match?([_|_], @downloaded_media) do %>