diff --git a/lib/pinchflat/utils/number_utils.ex b/lib/pinchflat/utils/number_utils.ex new file mode 100644 index 0000000..4a8404b --- /dev/null +++ b/lib/pinchflat/utils/number_utils.ex @@ -0,0 +1,16 @@ +defmodule Pinchflat.Utils.NumberUtils do + @moduledoc """ + Utility methods for working with numbers + """ + + @doc """ + Clamps a number between a minimum and maximum value + + Returns integer() | float() + """ + 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..532fba1 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,52 @@ defmodule PinchflatWeb.CustomComponents.TableComponents do """ end + + @doc """ + Renders simple pagination controls for a table in a liveview. + + ## Examples + + <.live_pagination_controls page_number={@page} total_pages={@total_pages} /> + """ + attr :page_number, :integer, default: 1 + attr :total_pages, :integer, default: 1 + + def live_pagination_controls(assigns) do + ~H""" + + """ + end end diff --git a/lib/pinchflat_web/controllers/sources/source_controller.ex b/lib/pinchflat_web/controllers/sources/source_controller.ex index ff12534..6e4b215 100644 --- a/lib/pinchflat_web/controllers/sources/source_controller.ex +++ b/lib/pinchflat_web/controllers/sources/source_controller.ex @@ -6,9 +6,7 @@ defmodule PinchflatWeb.Sources.SourceController do alias Pinchflat.Repo alias Pinchflat.Tasks alias Pinchflat.Sources - alias Pinchflat.MediaQuery alias Pinchflat.Sources.Source - alias Pinchflat.Media.MediaQuery alias Pinchflat.Profiles.MediaProfile alias Pinchflat.Downloading.DownloadingHelpers alias Pinchflat.SlowIndexing.SlowIndexingHelpers @@ -60,29 +58,7 @@ defmodule PinchflatWeb.Sources.SourceController do |> Tasks.list_tasks_for(nil, [:executing, :available, :scheduled, :retryable]) |> Repo.preload(:job) - pending_media = - MediaQuery.new() - |> MediaQuery.for_source(source) - |> MediaQuery.where_pending_download() - |> order_by(desc: :id) - |> limit(100) - |> Repo.all() - - downloaded_media = - MediaQuery.new() - |> MediaQuery.for_source(source) - |> MediaQuery.with_media_filepath() - |> order_by(desc: :id) - |> limit(100) - |> Repo.all() - - render(conn, :show, - source: source, - pending_tasks: pending_tasks, - pending_media: pending_media, - downloaded_media: downloaded_media, - total_downloaded: total_downloaded_for(source) - ) + render(conn, :show, source: source, pending_tasks: pending_tasks) end def edit(conn, %{"id" => id}) do @@ -151,13 +127,6 @@ defmodule PinchflatWeb.Sources.SourceController do |> Repo.all() end - defp total_downloaded_for(source) do - MediaQuery.new() - |> MediaQuery.for_source(source) - |> MediaQuery.with_media_filepath() - |> Repo.aggregate(:count, :id) - end - defp get_onboarding_layout do if Settings.get!(:onboarding) do {Layouts, :onboarding} diff --git a/lib/pinchflat_web/controllers/sources/source_html/media_item_table_live.ex b/lib/pinchflat_web/controllers/sources/source_html/media_item_table_live.ex new file mode 100644 index 0000000..bc2705c --- /dev/null +++ b/lib/pinchflat_web/controllers/sources/source_html/media_item_table_live.ex @@ -0,0 +1,91 @@ +defmodule Pinchflat.Sources.MediaItemTableLive 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""" +Nothing Here!
- <% end %> + <%= live_render( + @conn, + Pinchflat.Sources.MediaItemTableLive, + session: %{"source_id" => @source.id, "media_state" => "pending"} + ) %> <:tab title="Downloaded Media"> - <%= if match?([_|_], @downloaded_media) do %> -Nothing Here!
- <% end %> + <%= live_render( + @conn, + Pinchflat.Sources.MediaItemTableLive, + session: %{"source_id" => @source.id, "media_state" => "downloaded"} + ) %> <:tab title="Pending Tasks"> <%= if match?([_|_], @pending_tasks) do %> diff --git a/test/pinchflat/utils/number_utils_test.exs b/test/pinchflat/utils/number_utils_test.exs new file mode 100644 index 0000000..48efe41 --- /dev/null +++ b/test/pinchflat/utils/number_utils_test.exs @@ -0,0 +1,19 @@ +defmodule Pinchflat.Utils.NumberUtilsTest do + use ExUnit.Case, async: true + + alias Pinchflat.Utils.NumberUtils + + describe "clamp/3" do + test "returns the minimum when the number is less than the minimum" do + assert NumberUtils.clamp(1, 2, 3) == 2 + end + + test "returns the maximum when the number is greater than the maximum" do + assert NumberUtils.clamp(4, 2, 3) == 3 + end + + test "returns the number when it is between the minimum and maximum" do + assert NumberUtils.clamp(2, 1, 3) == 2 + end + end +end diff --git a/test/pinchflat_web/controllers/sources/media_item_table_live_test.exs b/test/pinchflat_web/controllers/sources/media_item_table_live_test.exs new file mode 100644 index 0000000..555738f --- /dev/null +++ b/test/pinchflat_web/controllers/sources/media_item_table_live_test.exs @@ -0,0 +1,60 @@ +defmodule PinchflatWeb.Sources.MediaItemTableLiveTest do + use PinchflatWeb.ConnCase + + import Phoenix.LiveViewTest + import Pinchflat.MediaFixtures + import Pinchflat.SourcesFixtures + + alias Pinchflat.Sources.MediaItemTableLive + + setup do + source = source_fixture() + + {:ok, source: source} + end + + describe "initial rendering" do + test "shows message when no records", %{conn: conn, source: source} do + {:ok, _view, html} = live_isolated(conn, MediaItemTableLive, session: create_session(source)) + + assert html =~ "Nothing Here!" + refute html =~ "Showing" + end + + test "shows records when present", %{conn: conn, source: source} do + media_item = media_item_fixture(source_id: source.id, media_filepath: nil) + + {:ok, _view, html} = live_isolated(conn, MediaItemTableLive, session: create_session(source)) + + assert html =~ "Showing 1 of 1" + assert html =~ "Title" + assert html =~ media_item.title + end + end + + describe "media_state" do + test "shows pending media when pending", %{conn: conn, source: source} do + downloaded_media_item = media_item_fixture(source_id: source.id) + pending_media_item = media_item_fixture(source_id: source.id, media_filepath: nil) + + {:ok, _view, html} = live_isolated(conn, MediaItemTableLive, session: create_session(source, "pending")) + + assert html =~ pending_media_item.title + refute html =~ downloaded_media_item.title + end + + test "shows downloaded media when downloaded", %{conn: conn, source: source} do + downloaded_media_item = media_item_fixture(source_id: source.id) + pending_media_item = media_item_fixture(source_id: source.id, media_filepath: nil) + + {:ok, _view, html} = live_isolated(conn, MediaItemTableLive, session: create_session(source, "downloaded")) + + assert html =~ downloaded_media_item.title + refute html =~ pending_media_item.title + end + end + + defp create_session(source, media_state \\ "pending") do + %{"source_id" => source.id, "media_state" => media_state} + end +end