Hooked up pagination for downloaded media

This commit is contained in:
Kieran Eglin 2024-04-17 10:15:06 -07:00
parent 9f491d4774
commit 4e1b18dfed
No known key found for this signature in database
GPG key ID: 193984967FCF432D
7 changed files with 122 additions and 66 deletions

View file

@ -3,7 +3,11 @@ defmodule Pinchflat.Utils.NumberUtils do
Utility methods for working with numbers
"""
# TODO: test
@doc """
Clamps a number between a minimum and maximum value
Returns integer() | float()
"""
def clamp(num, minimum, maximum) do
num
|> max(minimum)

View file

@ -53,10 +53,17 @@ 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 pagination_controls(assigns) do
def live_pagination_controls(assigns) do
~H"""
<nav>
<ul class="flex flex-wrap items-center">

View file

@ -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}

View file

@ -1,4 +1,4 @@
defmodule Pinchflat.PendingTableLive do
defmodule Pinchflat.Sources.MediaItemTableLive do
use PinchflatWeb, :live_view
import Ecto.Query, warn: false
@ -33,7 +33,7 @@ defmodule Pinchflat.PendingTableLive do
</:col>
</.table>
<section class="flex justify-center mt-5">
<.pagination_controls page_number={@page} total_pages={@total_pages} />
<.live_pagination_controls page_number={@page} total_pages={@total_pages} />
</section>
</div>
"""
@ -41,8 +41,9 @@ defmodule Pinchflat.PendingTableLive do
def mount(_params, session, socket) do
page = 1
media_state = session["media_state"]
source = Sources.get_source!(session["source_id"])
base_query = generate_base_query(source)
base_query = generate_base_query(source, media_state)
pagination_attrs = fetch_pagination_attributes(base_query, page)
{:ok, assign(socket, Map.merge(pagination_attrs, %{base_query: base_query, source: source}))}
@ -58,20 +59,13 @@ defmodule Pinchflat.PendingTableLive do
defp fetch_pagination_attributes(base_query, page) do
total_record_count = Repo.aggregate(base_query, :count, :id)
total_pages = ceil(total_record_count / @limit)
total_pages = max(ceil(total_record_count / @limit), 1)
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
@ -80,4 +74,18 @@ defmodule Pinchflat.PendingTableLive do
|> offset(^offset)
|> Repo.all()
end
defp generate_base_query(source, "pending") do
MediaQuery.new()
|> MediaQuery.for_source(source)
|> MediaQuery.where_pending_download()
|> order_by(desc: :id)
end
defp generate_base_query(source, "downloaded") do
MediaQuery.new()
|> MediaQuery.for_source(source)
|> MediaQuery.with_media_filepath()
|> order_by(desc: :id)
end
end

View file

@ -37,29 +37,18 @@
</div>
</:tab>
<:tab title="Pending Media">
<%= live_render(@conn, Pinchflat.PendingTableLive, session: %{"source_id" => @source.id}) %>
<%= live_render(
@conn,
Pinchflat.Sources.MediaItemTableLive,
session: %{"source_id" => @source.id, "media_state" => "pending"}
) %>
</:tab>
<:tab title="Downloaded Media">
<%= if match?([_|_], @downloaded_media) do %>
<h4 class="text-white text-lg mb-6">Shows a maximum of 100 media items (<%= @total_downloaded %> total)</h4>
<.table rows={@downloaded_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) %>
</.subtle_link>
</:col>
<: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"
/>
</:col>
</.table>
<% else %>
<p class="text-black dark:text-white">Nothing Here!</p>
<% end %>
<%= live_render(
@conn,
Pinchflat.Sources.MediaItemTableLive,
session: %{"source_id" => @source.id, "media_state" => "downloaded"}
) %>
</:tab>
<:tab title="Pending Tasks">
<%= if match?([_|_], @pending_tasks) do %>

View file

@ -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

View file

@ -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