Hooked up pagination for downloaded media
This commit is contained in:
parent
9f491d4774
commit
4e1b18dfed
7 changed files with 122 additions and 66 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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">
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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 %>
|
||||
|
|
|
|||
19
test/pinchflat/utils/number_utils_test.exs
Normal file
19
test/pinchflat/utils/number_utils_test.exs
Normal 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
|
||||
|
|
@ -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
|
||||
Loading…
Reference in a new issue