Render scrobble rules list with Fluxon table

This commit is contained in:
Claudio Ortolina
2025-07-04 14:05:08 +01:00
parent 6518a4b10e
commit 81f0ec8830
4 changed files with 97 additions and 158 deletions
@@ -118,20 +118,4 @@ defmodule MusicLibraryWeb.ScrobbleRulesLive.Index do
"Disabled" "Disabled"
end end
end end
defp enabled_badge_class(enabled) do
if enabled do
"text-green-800 bg-green-100 dark:bg-green-900 dark:text-green-300"
else
"text-red-800 bg-red-100 dark:bg-red-900 dark:text-red-300"
end
end
defp type_badge_class(type) do
case type do
"album" -> "text-blue-800 bg-blue-100 dark:bg-blue-900 dark:text-blue-300"
"artist" -> "text-purple-800 bg-purple-100 dark:bg-purple-900 dark:text-purple-300"
_ -> "text-gray-800 bg-gray-100 dark:bg-gray-900 dark:text-gray-300"
end
end
end end
@@ -14,136 +14,75 @@
<.icon name="hero-plus" class="h-4 w-4 mr-2" /> <.icon name="hero-plus" class="h-4 w-4 mr-2" />
{gettext("New Rule")} {gettext("New Rule")}
</.button> </.button>
<.button phx-click="apply_all_rules" class="!bg-green-600 hover:!bg-green-700">
<.icon name="hero-play" class="h-4 w-4 mr-2" />
{gettext("Apply All Rules")}
</.button>
</.link> </.link>
</div> </div>
</div> </div>
</header> </header>
<div class="mt-6 space-y-4"> <div class="mt-6 space-y-4">
<div class="flex justify-between items-center"> <.table>
<p class="text-sm text-zinc-600 dark:text-zinc-400"> <.table_head>
{gettext( <:col>{gettext("Type")}</:col>
"Rules are applied automatically by the background worker, or you can apply them manually." <:col>{gettext("Match Value")}</:col>
)} <:col>{gettext("Target MusicBrainz ID")}</:col>
</p> <:col>{gettext("Status")}</:col>
<.button phx-click="apply_all_rules" class="!bg-green-600 hover:!bg-green-700"> <:col>{gettext("Description")}</:col>
<.icon name="hero-play" class="h-4 w-4 mr-2" /> <:col>{gettext("Created")}</:col>
{gettext("Apply All Rules")} <:col></:col>
</.button> </.table_head>
</div> <.table_body>
<.table_row :for={{dom_id, scrobble_rule} <- @streams.scrobble_rules} id={dom_id}>
<div class="bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-zinc-200/10 sm:rounded-lg overflow-hidden"> <:cell>{rule_type_badge(scrobble_rule.type)}</:cell>
<div class="overflow-x-auto"> <:cell>{scrobble_rule.match_value}</:cell>
<table class="min-w-full divide-y divide-zinc-200 dark:divide-zinc-800"> <:cell class="whitespace-nowrap font-mono">{scrobble_rule.target_musicbrainz_id}</:cell>
<thead class="bg-zinc-50 dark:bg-zinc-800"> <:cell>{enabled_badge(scrobble_rule.enabled)}</:cell>
<tr> <:cell>{scrobble_rule.description}</:cell>
<th class="px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider"> <:cell>{Calendar.strftime(scrobble_rule.inserted_at, "%Y-%m-%d")}</:cell>
{gettext("Type")} <:cell>
</th> <.dropdown id={"actions-#{scrobble_rule.id}"} placement="bottom-end">
<th class="px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider"> <:toggle>
{gettext("Match Value")} <div>
</th> <span class="sr-only">{gettext("Actions")}</span>
<th class="px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">
{gettext("Target MusicBrainz ID")}
</th>
<th class="px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">
{gettext("Status")}
</th>
<th class="px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">
{gettext("Description")}
</th>
<th class="px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">
{gettext("Created")}
</th>
<th class="px-6 py-3 text-right text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">
{gettext("Actions")}
</th>
</tr>
</thead>
<tbody
id="scrobble_rules"
phx-update="stream"
class="bg-white dark:bg-zinc-900 divide-y divide-zinc-200 dark:divide-zinc-800"
>
<tr
:for={{dom_id, scrobble_rule} <- @streams.scrobble_rules}
id={dom_id}
class="hover:bg-zinc-50 dark:hover:bg-zinc-800"
>
<td class="px-6 py-4 whitespace-nowrap">
<span class={[
"inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium",
type_badge_class(scrobble_rule.type)
]}>
{rule_type_badge(scrobble_rule.type)}
</span>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-zinc-900 dark:text-zinc-100 font-medium">
{scrobble_rule.match_value}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-zinc-500 dark:text-zinc-400 font-mono">
{scrobble_rule.target_musicbrainz_id}
</td>
<td class="px-6 py-4 whitespace-nowrap">
<span class={[
"inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium",
enabled_badge_class(scrobble_rule.enabled)
]}>
{enabled_badge(scrobble_rule.enabled)}
</span>
</td>
<td class="px-6 py-4 text-sm text-zinc-500 dark:text-zinc-400">
{scrobble_rule.description}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-zinc-500 dark:text-zinc-400">
{Calendar.strftime(scrobble_rule.inserted_at, "%Y-%m-%d")}
</td>
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium space-x-2">
<.button
phx-click="apply_rule"
phx-value-id={scrobble_rule.id}
class="!bg-green-600 hover:!bg-green-700 !text-white !text-xs !px-2 !py-1"
>
<.icon name="hero-play" class="h-3 w-3" />
</.button>
<.button
phx-click="toggle_enabled"
phx-value-id={scrobble_rule.id}
class={[
"!text-white !text-xs !px-2 !py-1",
if(scrobble_rule.enabled,
do: "!bg-yellow-600 hover:!bg-yellow-700",
else: "!bg-green-600 hover:!bg-green-700"
)
]}
>
<.icon <.icon
name={if scrobble_rule.enabled, do: "hero-pause", else: "hero-play"} name="hero-ellipsis-vertical"
class="h-3 w-3" class="-mt-1 h-5 w-5 text-zinc-500 dark:text-zinc-400 cursor-pointer"
aria-hidden="true"
data-slot="icon"
/> />
</.button> </div>
</:toggle>
<.link patch={~p"/scrobble-rules/#{scrobble_rule}/edit"}> <.dropdown_button phx-click="apply_rule" phx-value-id={scrobble_rule.id}>
<.button class="!bg-blue-600 hover:!bg-blue-700 !text-white !text-xs !px-2 !py-1"> {gettext("Apply rule")}
<.icon name="hero-pencil" class="h-3 w-3" /> </.dropdown_button>
</.button> <.dropdown_button phx-click="toggle_enabled" phx-value-id={scrobble_rule.id}>
</.link> {if scrobble_rule.enabled, do: gettext("Disable rule"), else: gettext("Enable rule")}
</.dropdown_button>
<.button <.dropdown_link
phx-click="delete" id={"actions-#{scrobble_rule.id}-edit"}
phx-value-id={scrobble_rule.id} patch={~p"/scrobble-rules/#{scrobble_rule}/edit"}
data-confirm={gettext("Are you sure you want to delete this rule?")} >
class="!bg-red-600 hover:!bg-red-700 !text-white !text-xs !px-2 !py-1" {gettext("Edit")}
> </.dropdown_link>
<.icon name="hero-trash" class="h-3 w-3" /> <.separator />
</.button> <.dropdown_button
</td> phx-click="delete"
</tr> phx-value-id={scrobble_rule.id}
</tbody> data-confirm={gettext("Are you sure?")}
</table> class={[
</div> "text-red-900! hover:bg-red-50! dark:text-red-500! dark:hover:bg-red-900/30! dark:hover:text-red-600!"
</div> ]}
>
{gettext("Delete")}
</.dropdown_button>
</.dropdown>
</:cell>
</.table_row>
</.table_body>
</.table>
</div> </div>
<.modal <.modal
+18 -10
View File
@@ -13,6 +13,7 @@ msgstr ""
#: lib/music_library_web/components/record_components.ex #: lib/music_library_web/components/record_components.ex
#: lib/music_library_web/live/collection_live/show.html.heex #: lib/music_library_web/live/collection_live/show.html.heex
#: lib/music_library_web/live/scrobble_rules_live/index.html.heex
#: lib/music_library_web/live/wishlist_live/show.html.heex #: lib/music_library_web/live/wishlist_live/show.html.heex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Are you sure?" msgid "Are you sure?"
@@ -33,6 +34,7 @@ msgstr ""
#: lib/music_library_web/components/record_components.ex #: lib/music_library_web/components/record_components.ex
#: lib/music_library_web/live/collection_live/show.html.heex #: lib/music_library_web/live/collection_live/show.html.heex
#: lib/music_library_web/live/scrobble_rules_live/index.html.heex
#: lib/music_library_web/live/wishlist_live/show.html.heex #: lib/music_library_web/live/wishlist_live/show.html.heex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Delete" msgid "Delete"
@@ -41,6 +43,7 @@ msgstr ""
#: lib/music_library_web/components/record_components.ex #: lib/music_library_web/components/record_components.ex
#: lib/music_library_web/live/collection_live/show.ex #: lib/music_library_web/live/collection_live/show.ex
#: lib/music_library_web/live/collection_live/show.html.heex #: lib/music_library_web/live/collection_live/show.html.heex
#: lib/music_library_web/live/scrobble_rules_live/index.html.heex
#: lib/music_library_web/live/wishlist_live/show.ex #: lib/music_library_web/live/wishlist_live/show.ex
#: lib/music_library_web/live/wishlist_live/show.html.heex #: lib/music_library_web/live/wishlist_live/show.html.heex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
@@ -974,11 +977,6 @@ msgstr ""
msgid "Apply All Rules" msgid "Apply All Rules"
msgstr "" msgstr ""
#: lib/music_library_web/live/scrobble_rules_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "Are you sure you want to delete this rule?"
msgstr ""
#: lib/music_library_web/live/scrobble_rules_live/form_component.ex #: lib/music_library_web/live/scrobble_rules_live/form_component.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Artist" msgid "Artist"
@@ -1055,11 +1053,6 @@ msgstr ""
msgid "Rule applied successfully. Updated %{count} tracks." msgid "Rule applied successfully. Updated %{count} tracks."
msgstr "" msgstr ""
#: lib/music_library_web/live/scrobble_rules_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "Rules are applied automatically by the background worker, or you can apply them manually."
msgstr ""
#: lib/music_library_web/live/scrobble_rules_live/form_component.ex #: lib/music_library_web/live/scrobble_rules_live/form_component.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Save Rule" msgid "Save Rule"
@@ -1107,3 +1100,18 @@ msgstr ""
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "e.g. The Dark Side of the Moon" msgid "e.g. The Dark Side of the Moon"
msgstr "" msgstr ""
#: lib/music_library_web/live/scrobble_rules_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "Apply rule"
msgstr ""
#: lib/music_library_web/live/scrobble_rules_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "Disable rule"
msgstr ""
#: lib/music_library_web/live/scrobble_rules_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "Enable rule"
msgstr ""
+18 -10
View File
@@ -13,6 +13,7 @@ msgstr ""
#: lib/music_library_web/components/record_components.ex #: lib/music_library_web/components/record_components.ex
#: lib/music_library_web/live/collection_live/show.html.heex #: lib/music_library_web/live/collection_live/show.html.heex
#: lib/music_library_web/live/scrobble_rules_live/index.html.heex
#: lib/music_library_web/live/wishlist_live/show.html.heex #: lib/music_library_web/live/wishlist_live/show.html.heex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Are you sure?" msgid "Are you sure?"
@@ -33,6 +34,7 @@ msgstr ""
#: lib/music_library_web/components/record_components.ex #: lib/music_library_web/components/record_components.ex
#: lib/music_library_web/live/collection_live/show.html.heex #: lib/music_library_web/live/collection_live/show.html.heex
#: lib/music_library_web/live/scrobble_rules_live/index.html.heex
#: lib/music_library_web/live/wishlist_live/show.html.heex #: lib/music_library_web/live/wishlist_live/show.html.heex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Delete" msgid "Delete"
@@ -41,6 +43,7 @@ msgstr ""
#: lib/music_library_web/components/record_components.ex #: lib/music_library_web/components/record_components.ex
#: lib/music_library_web/live/collection_live/show.ex #: lib/music_library_web/live/collection_live/show.ex
#: lib/music_library_web/live/collection_live/show.html.heex #: lib/music_library_web/live/collection_live/show.html.heex
#: lib/music_library_web/live/scrobble_rules_live/index.html.heex
#: lib/music_library_web/live/wishlist_live/show.ex #: lib/music_library_web/live/wishlist_live/show.ex
#: lib/music_library_web/live/wishlist_live/show.html.heex #: lib/music_library_web/live/wishlist_live/show.html.heex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
@@ -974,11 +977,6 @@ msgstr ""
msgid "Apply All Rules" msgid "Apply All Rules"
msgstr "" msgstr ""
#: lib/music_library_web/live/scrobble_rules_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "Are you sure you want to delete this rule?"
msgstr ""
#: lib/music_library_web/live/scrobble_rules_live/form_component.ex #: lib/music_library_web/live/scrobble_rules_live/form_component.ex
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format, fuzzy
msgid "Artist" msgid "Artist"
@@ -1055,11 +1053,6 @@ msgstr ""
msgid "Rule applied successfully. Updated %{count} tracks." msgid "Rule applied successfully. Updated %{count} tracks."
msgstr "" msgstr ""
#: lib/music_library_web/live/scrobble_rules_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "Rules are applied automatically by the background worker, or you can apply them manually."
msgstr ""
#: lib/music_library_web/live/scrobble_rules_live/form_component.ex #: lib/music_library_web/live/scrobble_rules_live/form_component.ex
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format, fuzzy
msgid "Save Rule" msgid "Save Rule"
@@ -1107,3 +1100,18 @@ msgstr ""
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "e.g. The Dark Side of the Moon" msgid "e.g. The Dark Side of the Moon"
msgstr "" msgstr ""
#: lib/music_library_web/live/scrobble_rules_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "Apply rule"
msgstr ""
#: lib/music_library_web/live/scrobble_rules_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "Disable rule"
msgstr ""
#: lib/music_library_web/live/scrobble_rules_live/index.html.heex
#, elixir-autogen, elixir-format, fuzzy
msgid "Enable rule"
msgstr ""