Add pagination for scrobble rules

This commit is contained in:
Claudio Ortolina
2025-12-14 09:21:13 +03:00
parent b890e5cffe
commit 0df348ae19
6 changed files with 167 additions and 11 deletions
+55
View File
@@ -45,9 +45,64 @@ defmodule MusicLibrary.ScrobbleRules do
where: r.enabled == ^enabled
end
query =
case Keyword.get(opts, :offset) do
nil ->
query
offset ->
from r in query,
offset: ^offset
end
query =
case Keyword.get(opts, :limit) do
nil ->
query
limit ->
from r in query,
limit: ^limit
end
Repo.all(query)
end
@doc """
Returns the count of scrobble_rules.
## Examples
iex> count_scrobble_rules()
42
"""
def count_scrobble_rules(opts \\ []) do
query = from(r in ScrobbleRule)
query =
case Keyword.get(opts, :type) do
nil ->
query
type ->
from r in query,
where: r.type == ^type
end
query =
case Keyword.get(opts, :enabled) do
nil ->
query
enabled ->
from r in query,
where: r.enabled == ^enabled
end
Repo.aggregate(query, :count)
end
@doc """
Gets a single scrobble_rule.
@@ -1,9 +1,18 @@
defmodule MusicLibraryWeb.ScrobbleRulesLive.Index do
use MusicLibraryWeb, :live_view
import MusicLibraryWeb.Components.Pagination
alias MusicLibrary.ScrobbleRules
alias MusicLibrary.ScrobbleRules.ScrobbleRule
@default_list_params %{
page: 1,
page_size: 20,
query: "",
order: :inserted_at
}
@impl true
def mount(_params, _session, socket) do
{:ok, assign(socket, :current_section, :scrobble_rules)}
@@ -28,11 +37,14 @@ defmodule MusicLibraryWeb.ScrobbleRulesLive.Index do
|> assign(:scrobble_rule, %ScrobbleRule{})
end
defp apply_action(socket, :index, _params) do
socket
|> assign(:page_title, gettext("Scrobble Rules"))
|> assign(:scrobble_rule, nil)
|> stream(:scrobble_rules, ScrobbleRules.list_scrobble_rules(), reset: true)
defp apply_action(socket, :index, params) do
total_rules = ScrobbleRules.count_scrobble_rules()
list_params =
@default_list_params
|> merge_pagination(params, total_rules)
load_and_assign_rules(socket, list_params)
end
def apply_fallback_index(socket, params) do
@@ -44,12 +56,74 @@ defmodule MusicLibraryWeb.ScrobbleRulesLive.Index do
end
end
defp merge_pagination(params, url_params, total_records) do
page = parse_page(url_params["page"])
page_size = parse_page_size(url_params["page_size"])
params
|> Map.put(:page, page)
|> Map.put(:page_size, page_size)
|> Map.put(:total_records, total_records)
end
defp parse_page(nil), do: 1
defp parse_page(page) when is_binary(page) do
case Integer.parse(page) do
{num, ""} when num > 0 -> num
_ -> 1
end
end
defp parse_page(_), do: 1
defp parse_page_size(nil), do: 20
defp parse_page_size(page_size) when is_binary(page_size) do
case Integer.parse(page_size) do
{num, ""} when num in [20, 50, 100] -> num
_ -> 20
end
end
defp parse_page_size(_), do: 20
defp load_and_assign_rules(socket, list_params) do
offset = page_to_offset(list_params.page, list_params.page_size)
rules =
ScrobbleRules.list_scrobble_rules(
offset: offset,
limit: list_params.page_size
)
list_params_with_total =
Map.put(list_params, :total_entries, list_params.total_records)
socket
|> assign(:list_params, list_params_with_total)
|> assign(:page_title, gettext("Scrobble Rules"))
|> assign(:scrobble_rule, nil)
|> stream(:scrobble_rules, rules, reset: true)
end
def back_path(list_params) do
qs =
list_params
|> Map.take([:page, :page_size])
~p"/scrobble-rules?#{qs}"
end
@impl true
def handle_info(
{MusicLibraryWeb.ScrobbleRulesLive.Form, {:created, scrobble_rule}},
socket
) do
{:noreply, stream_insert(socket, :scrobble_rules, scrobble_rule, at: 0)}
{:noreply,
socket
|> stream_insert(:scrobble_rules, scrobble_rule, at: 0)
|> load_and_assign_rules(socket.assigns.list_params)}
end
def handle_info(
@@ -64,7 +138,10 @@ defmodule MusicLibraryWeb.ScrobbleRulesLive.Index do
scrobble_rule = ScrobbleRules.get_scrobble_rule!(id)
{:ok, _} = ScrobbleRules.delete_scrobble_rule(scrobble_rule)
{:noreply, stream_delete(socket, :scrobble_rules, scrobble_rule)}
{:noreply,
socket
|> stream_delete(:scrobble_rules, scrobble_rule)
|> load_and_assign_rules(socket.assigns.list_params)}
end
@impl true
@@ -31,6 +31,16 @@
<div class="mt-6 space-y-4">
<ul phx-update="stream" id="scrobble-rules-list" class="space-y-4">
<li
id="no-scrobble-rules"
class="hidden only:block p-8 text-center bg-zinc-50 dark:bg-zinc-800 rounded-lg"
>
<.icon name="hero-beaker" class="h-12 w-12 text-zinc-400 mx-auto mb-4" />
<p class="text-zinc-600 dark:text-zinc-400">
{gettext("No scrobble rules found")}
</p>
</li>
<li
:for={{dom_id, scrobble_rule} <- @streams.scrobble_rules}
id={dom_id}
@@ -79,7 +89,9 @@
</.dropdown_button>
<.dropdown_link
id={"actions-#{scrobble_rule.id}-edit"}
patch={~p"/scrobble-rules/#{scrobble_rule}/edit"}
patch={
~p"/scrobble-rules/#{scrobble_rule}/edit?#{Map.take(@list_params, [:page, :page_size])}"
}
>
{gettext("Edit")}
</.dropdown_link>
@@ -98,12 +110,14 @@
</div>
</li>
</ul>
<.pagination id={:bottom_pagination} pagination_params={@list_params} />
</div>
<.structured_modal
:if={@live_action in [:new, :edit]}
id="scrobble_rule-modal"
on_close={JS.patch(~p"/scrobble-rules")}
on_close={JS.patch(back_path(@list_params))}
>
<.live_component
module={MusicLibraryWeb.ScrobbleRulesLive.Form}
@@ -111,7 +125,7 @@
title={@page_title}
action={@live_action}
scrobble_rule={@scrobble_rule}
patch={~p"/scrobble-rules"}
patch={back_path(@list_params)}
/>
</.structured_modal>
</Layouts.app>
+5
View File
@@ -1667,3 +1667,8 @@ msgstr ""
#, elixir-autogen, elixir-format
msgid "Artist MusicBrainz ID"
msgstr ""
#: lib/music_library_web/live/scrobble_rules_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "No scrobble rules found"
msgstr ""
+5
View File
@@ -1667,3 +1667,8 @@ msgstr ""
#, elixir-autogen, elixir-format
msgid "Artist MusicBrainz ID"
msgstr ""
#: lib/music_library_web/live/scrobble_rules_live/index.html.heex
#, elixir-autogen, elixir-format, fuzzy
msgid "No scrobble rules found"
msgstr ""
@@ -66,7 +66,7 @@ defmodule MusicLibraryWeb.ScrobbleRulesLiveTest do
|> render_click() =~
"Edit Scrobble Rule"
assert_patch(index_live, ~p"/scrobble-rules/#{scrobble_rule}/edit")
assert_patch(index_live, ~p"/scrobble-rules/#{scrobble_rule}/edit?page=1&page_size=20")
assert index_live
|> form("#scrobble_rule-form", scrobble_rule: @invalid_attrs)