Add pagination for scrobble rules
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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 ""
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user