Remove drop down from record set items

Have just a bin icon, and rely on drag and drop.

This solves a massive performance issue with the page, which is
traceable to the Fluxon dropdowns, particularly the Class.merge logic
used to merge Tailwind classes
This commit is contained in:
Claudio Ortolina
2026-03-08 13:21:33 +00:00
parent d76471b03e
commit 4584b7bcb8
6 changed files with 27 additions and 190 deletions
@@ -228,20 +228,6 @@ defmodule MusicLibraryWeb.RecordSetLive.Index do
{:noreply, update_record_set_in_list(socket, updated_set)}
end
def handle_event("move_up", %{"set-id" => set_id, "record-id" => record_id}, socket) do
record_set = RecordSets.get_record_set!(set_id)
{:ok, updated_set} = RecordSets.move_record_in_set(record_set, record_id, :up)
{:noreply, update_record_set_in_list(socket, updated_set)}
end
def handle_event("move_down", %{"set-id" => set_id, "record-id" => record_id}, socket) do
record_set = RecordSets.get_record_set!(set_id)
{:ok, updated_set} = RecordSets.move_record_in_set(record_set, record_id, :down)
{:noreply, update_record_set_in_list(socket, updated_set)}
end
def handle_event("reorder", %{"set_id" => set_id, "record_ids" => record_ids}, socket) do
record_set = RecordSets.get_record_set!(set_id)
{:ok, updated_set} = RecordSets.reorder_records_in_set(record_set, record_ids)
@@ -387,50 +373,20 @@ defmodule MusicLibraryWeb.RecordSetLive.Index do
aria-hidden="true"
/>
</div>
<div class="absolute top-1 right-1 rounded-full bg-zinc-100/50 hover:bg-zinc-100/75 dark:bg-zinc-700/50 dark:hover:bg-zinc-700/75 size-5">
<.dropdown
id={"item-actions-#{@record_set.id}-#{item.record.id}"}
placement="bottom-end"
>
<:toggle>
<span class="sr-only">{gettext("Actions")}</span>
<.icon
name="hero-ellipsis-vertical"
class="size-5 text-zinc-800 dark:text-zinc-200 cursor-pointer"
aria-hidden="true"
data-slot="icon"
/>
</:toggle>
<.dropdown_button
:if={item.position > 0}
phx-click="move_up"
phx-value-set-id={@record_set.id}
phx-value-record-id={item.record.id}
>
{gettext("Move left")}
</.dropdown_button>
<.dropdown_button
:if={item.position < length(@record_set.items) - 1}
phx-click="move_down"
phx-value-set-id={@record_set.id}
phx-value-record-id={item.record.id}
>
{gettext("Move right")}
</.dropdown_button>
<.separator />
<.dropdown_button
phx-click="remove_record"
phx-value-set-id={@record_set.id}
phx-value-record-id={item.record.id}
data-confirm={gettext("Remove this record from the set?")}
class={[
"text-red-900! hover:bg-red-50! dark:text-red-500! dark:hover:bg-red-900/30! dark:hover:text-red-600!"
]}
>
{gettext("Remove")}
</.dropdown_button>
</.dropdown>
</div>
<button
phx-click="remove_record"
phx-value-set-id={@record_set.id}
phx-value-record-id={item.record.id}
data-confirm={gettext("Remove this record from the set?")}
class="absolute top-1 right-1 flex items-center justify-center rounded-full bg-zinc-100/50 hover:bg-red-100/75 dark:bg-zinc-700/50 dark:hover:bg-red-900/50 size-8 sm:size-5 cursor-pointer"
>
<span class="sr-only">{gettext("Remove")}</span>
<.icon
name="hero-trash"
class="size-3.5 text-zinc-800 hover:text-red-700 dark:text-zinc-200 dark:hover:text-red-400"
aria-hidden="true"
/>
</button>
<h1 class="mt-1 text-sm sm:text-sm leading-6 text-zinc-700">
<.artist_links joinphrase_class="text-sm" artists={item.record.artists} />
</h1>
@@ -109,47 +109,19 @@ defmodule MusicLibraryWeb.RecordSetLive.Show do
aria-hidden="true"
/>
</div>
<div class="absolute top-1 right-1 rounded-full bg-zinc-100/50 hover:bg-zinc-100/75 dark:bg-zinc-700/50 dark:hover:bg-zinc-700/75 size-5">
<.dropdown
id={"item-actions-#{item.record.id}"}
placement="bottom-end"
>
<:toggle>
<span class="sr-only">{gettext("Actions")}</span>
<.icon
name="hero-ellipsis-vertical"
class="size-5 text-zinc-800 dark:text-zinc-200 cursor-pointer"
aria-hidden="true"
data-slot="icon"
/>
</:toggle>
<.dropdown_button
:if={item.position > 0}
phx-click="move_up"
phx-value-record-id={item.record.id}
>
{gettext("Move left")}
</.dropdown_button>
<.dropdown_button
:if={item.position < length(@record_set.items) - 1}
phx-click="move_down"
phx-value-record-id={item.record.id}
>
{gettext("Move right")}
</.dropdown_button>
<.separator />
<.dropdown_button
phx-click="remove_record"
phx-value-record-id={item.record.id}
data-confirm={gettext("Remove this record from the set?")}
class={[
"text-red-900! hover:bg-red-50! dark:text-red-500! dark:hover:bg-red-900/30! dark:hover:text-red-600!"
]}
>
{gettext("Remove")}
</.dropdown_button>
</.dropdown>
</div>
<button
phx-click="remove_record"
phx-value-record-id={item.record.id}
data-confirm={gettext("Remove this record from the set?")}
class="absolute top-1 right-1 flex items-center justify-center rounded-full bg-zinc-100/50 hover:bg-red-100/75 dark:bg-zinc-700/50 dark:hover:bg-red-900/50 size-8 sm:size-5 cursor-pointer"
>
<span class="sr-only">{gettext("Remove")}</span>
<.icon
name="hero-trash"
class="size-3.5 text-zinc-800 hover:text-red-700 dark:text-zinc-200 dark:hover:text-red-400"
aria-hidden="true"
/>
</button>
<h1 class="mt-1 text-sm sm:text-sm leading-6 text-zinc-700">
<.artist_links joinphrase_class="text-sm" artists={item.record.artists} />
</h1>
@@ -277,20 +249,6 @@ defmodule MusicLibraryWeb.RecordSetLive.Show do
{:noreply, assign(socket, :record_set, updated_set)}
end
def handle_event("move_up", %{"record-id" => record_id}, socket) do
{:ok, updated_set} =
RecordSets.move_record_in_set(socket.assigns.record_set, record_id, :up)
{:noreply, assign(socket, :record_set, updated_set)}
end
def handle_event("move_down", %{"record-id" => record_id}, socket) do
{:ok, updated_set} =
RecordSets.move_record_in_set(socket.assigns.record_set, record_id, :down)
{:noreply, assign(socket, :record_set, updated_set)}
end
def handle_event("reorder", %{"record_ids" => record_ids}, socket) do
{:ok, updated_set} =
RecordSets.reorder_records_in_set(socket.assigns.record_set, record_ids)
-12
View File
@@ -1614,18 +1614,6 @@ msgstr ""
msgid "Edit Set"
msgstr ""
#: lib/music_library_web/live/record_set_live/index.ex
#: lib/music_library_web/live/record_set_live/show.ex
#, elixir-autogen, elixir-format
msgid "Move left"
msgstr ""
#: lib/music_library_web/live/record_set_live/index.ex
#: lib/music_library_web/live/record_set_live/show.ex
#, elixir-autogen, elixir-format
msgid "Move right"
msgstr ""
#: lib/music_library_web/live/record_set_live/form.ex
#, elixir-autogen, elixir-format
msgid "Name"
-12
View File
@@ -1614,18 +1614,6 @@ msgstr ""
msgid "Edit Set"
msgstr ""
#: lib/music_library_web/live/record_set_live/index.ex
#: lib/music_library_web/live/record_set_live/show.ex
#, elixir-autogen, elixir-format
msgid "Move left"
msgstr ""
#: lib/music_library_web/live/record_set_live/index.ex
#: lib/music_library_web/live/record_set_live/show.ex
#, elixir-autogen, elixir-format
msgid "Move right"
msgstr ""
#: lib/music_library_web/live/record_set_live/form.ex
#, elixir-autogen, elixir-format
msgid "Name"
@@ -135,40 +135,4 @@ defmodule MusicLibraryWeb.RecordSetLive.IndexTest do
assert ids_in_order == [r3.id, r1.id, r2.id]
end
end
describe "Reorder records" do
test "moves a record left (up)", %{conn: conn} do
{set, [r1, r2 | _]} = record_set_with_records(3)
{:ok, view, _html} = live(conn, ~p"/record-sets")
view
|> element(
"button[phx-click='move_up'][phx-value-set-id='#{set.id}'][phx-value-record-id='#{r2.id}']"
)
|> render_click()
updated = RecordSets.get_record_set!(set.id)
ids_in_order = Enum.map(updated.items, & &1.record.id)
assert Enum.at(ids_in_order, 0) == r2.id
assert Enum.at(ids_in_order, 1) == r1.id
end
test "moves a record right (down)", %{conn: conn} do
{set, [r1, r2 | _]} = record_set_with_records(3)
{:ok, view, _html} = live(conn, ~p"/record-sets")
view
|> element(
"button[phx-click='move_down'][phx-value-set-id='#{set.id}'][phx-value-record-id='#{r1.id}']"
)
|> render_click()
updated = RecordSets.get_record_set!(set.id)
ids_in_order = Enum.map(updated.items, & &1.record.id)
assert Enum.at(ids_in_order, 0) == r2.id
assert Enum.at(ids_in_order, 1) == r1.id
end
end
end
@@ -64,23 +64,6 @@ defmodule MusicLibraryWeb.RecordSetLive.ShowTest do
end
end
describe "Reorder records" do
test "moves a record right (down)", %{conn: conn} do
{set, [r1, r2 | _]} = record_set_with_records(3)
{:ok, view, _html} = live(conn, ~p"/record-sets/#{set}")
view
|> element("button[phx-click='move_down'][phx-value-record-id='#{r1.id}']")
|> render_click()
updated = RecordSets.get_record_set!(set.id)
ids_in_order = Enum.map(updated.items, & &1.record.id)
assert Enum.at(ids_in_order, 0) == r2.id
assert Enum.at(ids_in_order, 1) == r1.id
end
end
describe "Drag-and-drop reorder" do
test "reorders records via reorder event", %{conn: conn} do
{set, [r1, r2, r3]} = record_set_with_records(3)