Enable new actions menu on wishlist detail page

This commit is contained in:
Claudio Ortolina
2024-12-12 20:23:48 +03:00
parent c3f973b1e1
commit ed86ef7b5a
4 changed files with 187 additions and 116 deletions
@@ -118,17 +118,6 @@
{gettext("Populate genres")}
</.link>
<.link
:if={!@record.purchased_at}
class="block px-3 py-1 text-sm leading-6 text-zinc-900 dark:text-zinc-400 hover:bg-zinc-50 dark:hover:text-zinc-300 dark:hover:bg-zinc-700"
role="menuitem"
tabindex="-1"
id={"actions-#{@record.id}-purchase"}
phx-click={JS.push("purchase", value: %{id: @record.id})}
>
{gettext("Purchase")}
</.link>
<.link
class="block px-3 py-1 text-sm leading-6 text-red-900 hover:bg-red-50 dark:text-red-700 dark:hover:bg-red-900/30 dark:hover:text-red-600"
role="menuitem"
@@ -103,6 +103,22 @@ defmodule MusicLibraryWeb.WishlistLive.Show do
end
end
def handle_event("purchase", %{"id" => id}, socket) do
record = Records.get_record!(id)
current_time = DateTime.utc_now()
case Records.update_record(record, %{"purchased_at" => current_time}) do
{:ok, _} ->
{:noreply,
socket
|> put_flash(:info, gettext("Record updated successfully"))
|> push_navigate(to: ~p"/wishlist")}
{:error, %Ecto.Changeset{} = changeset} ->
{:noreply, assign(socket, form: to_form(changeset))}
end
end
@impl true
def handle_info({MusicLibraryWeb.RecordLive.FormComponent, {:saved, record}}, socket) do
{:noreply, assign(socket, :record, record)}
@@ -131,4 +147,14 @@ defmodule MusicLibraryWeb.WishlistLive.Show do
defp human_datetime(dt) do
"#{dt.day}/#{dt.month}/#{dt.year}"
end
defp toggle_actions_menu(record_id) do
JS.toggle(to: "#actions-#{record_id}")
|> JS.toggle_class("pointer-events-none", to: "#records > li")
end
defp close_actions_menu(record_id) do
JS.hide(to: "#actions-#{record_id}")
|> JS.remove_class("pointer-events-none", to: "#records > li")
end
end
@@ -7,79 +7,152 @@
/>
</div>
<div class="mt-4 md:mt-0">
<h1 class="text-base font-medium leading-6 text-zinc-700">
<.link
:for={artist <- @record.artists}
class="text-zinc-700 hover:text-zinc-500 dark:text-zinc-400 dark:hover:text-zinc-300"
navigate={~p"/artists/#{artist.musicbrainz_id}"}
<div class="mt-4 md:mt-0 flex justify-between">
<div>
<h1 class="text-base font-medium leading-6 text-zinc-700">
<.link
:for={artist <- @record.artists}
class="text-zinc-700 hover:text-zinc-500 dark:text-zinc-400 dark:hover:text-zinc-300"
navigate={~p"/artists/#{artist.musicbrainz_id}"}
>
{artist.name}
</.link>
</h1>
<h2 class="mt-1 flex font-semibold text-base sm:text-lg leading-5 text-zinc-700 dark:text-zinc-300 text-wrap">
{@record.title}
</h2>
<p class="mt-2 text-sm leading-5 text-zinc-500 dark:text-zinc-400">
{Records.Record.format_release(@record.release)} · {Records.Record.format_long_label(
@record.format
)} · {Records.Record.type_long_label(@record.type)}
</p>
</div>
<div class="relative flex-none">
<button
type="button"
class="text-zinc-500 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-300"
aria-expanded="false"
aria-haspopup="true"
phx-click={toggle_actions_menu(@record.id)}
>
{artist.name}
</.link>
</h1>
<h2 class="mt-1 flex font-semibold text-base sm:text-lg leading-5 text-zinc-700 dark:text-zinc-300 text-wrap">
{@record.title}
</h2>
<p class="mt-2 text-sm leading-5 text-zinc-500 dark:text-zinc-400">
{Records.Record.format_release(@record.release)} · {Records.Record.format_long_label(
@record.format
)} · {Records.Record.type_long_label(@record.type)}
</p>
<!-- TODO: extract to a component -->
<nav class="mt-3 sm:mt-5 isolate inline-flex rounded-md shadow-sm">
<.link patch={~p"/wishlist/#{@record}/show/edit"} phx-click={JS.push_focus()}>
<.button type="button" class="relative inline-flex items-center rounded-r-none">
<span class="sr-only">{gettext("Open options")}</span>
<.icon
name="hero-ellipsis-vertical"
class="-mt-1 h-5 w-5"
aria-hidden="true"
data-slot="icon"
/>
</button>
<.focus_wrap
id={"actions-#{@record.id}"}
class={[
"hidden pointer-events-auto absolute right-0 z-10 mt-2 w-48 origin-top-right rounded-md bg-white dark:bg-zinc-800 py-2 shadow-lg ring-1 ring-zinc-900/5 focus:outline-none"
]}
role="menu"
aria-orientation="vertical"
aria-labelledby="options-menu-0-button"
tabindex="-1"
phx-click-away={close_actions_menu(@record.id)}
>
<.link
class="block px-3 py-1 text-sm leading-6 text-zinc-900 dark:text-zinc-400 hover:bg-zinc-50 dark:hover:text-zinc-300 dark:hover:bg-zinc-700"
role="menuitem"
tabindex="-1"
id={"actions-#{@record.id}-edit"}
patch={~p"/wishlist/#{@record}/show/edit"}
>
<.icon
name="hero-pencil-square"
class="h-4 w-4 mr-1 phx-click-loading:animate-spin"
aria-hidden="true"
data-slot="icon"
/>
{gettext("Edit")}
</.button>
</.link>
<.link phx-click={JS.push("refresh_cover", value: %{id: @record.id})}>
<.button type="button" class="relative -ml-px inline-flex items-center rounded-none">
<span class="sr-only">{gettext("Refresh")}</span>
</.link>
<.link
class="block px-3 py-1 text-sm leading-6 text-zinc-900 dark:text-zinc-400 hover:bg-zinc-50 dark:hover:text-zinc-300 dark:hover:bg-zinc-700"
role="menuitem"
tabindex="-1"
id={"actions-#{@record.id}-refresh-cover"}
phx-click={JS.push("refresh_cover", value: %{id: @record.id})}
>
<.icon
name="hero-photo"
class="h-4 w-4 mr-1 phx-click-loading:animate-bounce"
aria-hidden="true"
data-slot="icon"
/>
{gettext("Refresh cover")}
</.link>
<.link
class="block px-3 py-1 text-sm leading-6 text-zinc-900 dark:text-zinc-400 hover:bg-zinc-50 dark:hover:text-zinc-300 dark:hover:bg-zinc-700"
role="menuitem"
tabindex="-1"
id={"actions-#{@record.id}-refresh-mb-data"}
phx-click={JS.push("refresh_musicbrainz_data", value: %{id: @record.id})}
>
<.icon
name="hero-arrow-path"
class="h-4 w-4 mr-1 phx-click-loading:animate-spin"
aria-hidden="true"
data-slot="icon"
/>
{gettext("Cover")}
</.button>
</.link>
<.link phx-click={JS.push("refresh_musicbrainz_data", value: %{id: @record.id})}>
<.button type="button" class="relative -ml-px inline-flex items-center rounded-none">
<span class="sr-only">{gettext("Refresh")}</span>
<.icon
name="hero-arrow-path"
class="h-4 w-4 mr-1 phx-click-loading:animate-spin"
aria-hidden="true"
data-slot="icon"
/>
{gettext("MB Data")}
</.button>
</.link>
<.link phx-click={JS.push("populate_genres", value: %{id: @record.id})}>
<.button type="button" class="relative -ml-px inline-flex items-center rounded-none">
<span class="sr-only">{gettext("Populate")}</span>
{gettext("Refresh MB data")}
</.link>
<.link
class="block px-3 py-1 text-sm leading-6 text-zinc-900 dark:text-zinc-400 hover:bg-zinc-50 dark:hover:text-zinc-300 dark:hover:bg-zinc-700"
role="menuitem"
tabindex="-1"
id={"actions-#{@record.id}-populate-genres"}
phx-click={JS.push("populate_genres", value: %{id: @record.id})}
>
<.icon
name="hero-sparkles"
class="h-4 w-4 mr-1 phx-click-loading:animate-shake"
aria-hidden="true"
data-slot="icon"
/>
{gettext("Genres")}
</.button>
</.link>
<.link
phx-click={JS.push("delete", value: %{id: @record.id})}
data-confirm={gettext("Are you sure?")}
>
<.button
type="button"
class="relative -ml-px inline-flex items-center rounded-l-none !text-red-600 hover:!text-red-500 dark:!text-red-700 hover:dark:!text-red-500"
{gettext("Populate genres")}
</.link>
<.link
:if={!@record.purchased_at}
class="block px-3 py-1 text-sm leading-6 text-zinc-900 dark:text-zinc-400 hover:bg-zinc-50 dark:hover:text-zinc-300 dark:hover:bg-zinc-700"
role="menuitem"
tabindex="-1"
id={"actions-#{@record.id}-purchase"}
phx-click={JS.push("purchase", value: %{id: @record.id})}
>
<.icon
name="hero-banknotes"
class="h-4 w-4 mr-1 phx-click-loading:animate-shake"
aria-hidden="true"
data-slot="icon"
/>
{gettext("Purchase")}
</.link>
<.link
class="block px-3 py-1 text-sm leading-6 text-red-900 hover:bg-red-50 dark:text-red-700 dark:hover:bg-red-900/30 dark:hover:text-red-600"
role="menuitem"
tabindex="-1"
id={"actions-#{@record.id}-delete"}
phx-click={JS.push("delete", value: %{id: @record.id})}
data-confirm={gettext("Are you sure?")}
>
<.icon
name="hero-trash"
class="h-4 w-4 mr-1 phx-click-loading:animate-spin"
aria-hidden="true"
data-slot="icon"
/>
{gettext("Delete")}
</.button>
</.link>
</nav>
</.link>
</.focus_wrap>
</div>
</div>
<div>
+31 -48
View File
@@ -17,8 +17,8 @@ msgid "Actions"
msgstr ""
#: lib/music_library_web/components/record_components.ex:179
#: lib/music_library_web/live/collection_live/show.html.heex:138
#: lib/music_library_web/live/wishlist_live/show.html.heex:73
#: lib/music_library_web/live/collection_live/show.html.heex:127
#: lib/music_library_web/live/wishlist_live/show.html.heex:144
#, elixir-autogen, elixir-format
msgid "Are you sure?"
msgstr ""
@@ -28,12 +28,12 @@ msgstr ""
msgid "Attempting to reconnect"
msgstr ""
#: lib/music_library_web/live/collection_live/show.html.heex:240
#: lib/music_library_web/live/collection_live/show.html.heex:229
#, elixir-autogen, elixir-format
msgid "Back to records"
msgstr ""
#: lib/music_library_web/live/wishlist_live/show.html.heex:166
#: lib/music_library_web/live/wishlist_live/show.html.heex:239
#, elixir-autogen, elixir-format
msgid "Back to wishlist"
msgstr ""
@@ -64,8 +64,8 @@ msgid "Cover art"
msgstr ""
#: lib/music_library_web/components/record_components.ex:181
#: lib/music_library_web/live/collection_live/show.html.heex:146
#: lib/music_library_web/live/wishlist_live/show.html.heex:79
#: lib/music_library_web/live/collection_live/show.html.heex:135
#: lib/music_library_web/live/wishlist_live/show.html.heex:152
#, elixir-autogen, elixir-format
msgid "Delete"
msgstr ""
@@ -73,8 +73,8 @@ msgstr ""
#: lib/music_library_web/components/record_components.ex:159
#: lib/music_library_web/live/collection_live/show.ex:148
#: lib/music_library_web/live/collection_live/show.html.heex:70
#: lib/music_library_web/live/wishlist_live/show.ex:129
#: lib/music_library_web/live/wishlist_live/show.html.heex:32
#: lib/music_library_web/live/wishlist_live/show.ex:145
#: lib/music_library_web/live/wishlist_live/show.html.heex:70
#, elixir-autogen, elixir-format
msgid "Edit"
msgstr ""
@@ -102,9 +102,8 @@ msgstr ""
msgid "Formats"
msgstr ""
#: lib/music_library_web/live/collection_live/show.html.heex:156
#: lib/music_library_web/live/wishlist_live/show.html.heex:68
#: lib/music_library_web/live/wishlist_live/show.html.heex:90
#: lib/music_library_web/live/collection_live/show.html.heex:145
#: lib/music_library_web/live/wishlist_live/show.html.heex:163
#, elixir-autogen, elixir-format
msgid "Genres"
msgstr ""
@@ -120,8 +119,8 @@ msgstr ""
msgid "Import"
msgstr ""
#: lib/music_library_web/live/collection_live/show.html.heex:215
#: lib/music_library_web/live/wishlist_live/show.html.heex:141
#: lib/music_library_web/live/collection_live/show.html.heex:204
#: lib/music_library_web/live/wishlist_live/show.html.heex:214
#, elixir-autogen, elixir-format
msgid "Inserted at"
msgstr ""
@@ -147,9 +146,9 @@ msgstr ""
msgid "Logout"
msgstr ""
#: lib/music_library_web/live/collection_live/show.html.heex:170
#: lib/music_library_web/live/collection_live/show.html.heex:159
#: lib/music_library_web/live/record_live/form_component.ex:47
#: lib/music_library_web/live/wishlist_live/show.html.heex:104
#: lib/music_library_web/live/wishlist_live/show.html.heex:177
#, elixir-autogen, elixir-format
msgid "MusicBrainz ID"
msgstr ""
@@ -172,6 +171,7 @@ msgstr ""
#: lib/music_library_web/components/record_components.ex:104
#: lib/music_library_web/live/collection_live/show.html.heex:38
#: lib/music_library_web/live/wishlist_live/show.html.heex:38
#, elixir-autogen, elixir-format
msgid "Open options"
msgstr ""
@@ -188,7 +188,7 @@ msgid "Previous"
msgstr ""
#: lib/music_library_web/components/record_components.ex:170
#: lib/music_library_web/live/collection_live/show.html.heex:129
#: lib/music_library_web/live/wishlist_live/show.html.heex:135
#, elixir-autogen, elixir-format
msgid "Purchase"
msgstr ""
@@ -198,7 +198,7 @@ msgstr ""
msgid "Purchased at"
msgstr ""
#: lib/music_library_web/live/collection_live/show.html.heex:192
#: lib/music_library_web/live/collection_live/show.html.heex:181
#, elixir-autogen, elixir-format
msgid "Purchased on"
msgstr ""
@@ -211,6 +211,7 @@ msgstr ""
#: lib/music_library_web/live/record_live/form_component.ex:123
#: lib/music_library_web/live/wishlist_live/index.ex:141
#: lib/music_library_web/live/wishlist_live/show.ex:114
#, elixir-autogen, elixir-format
msgid "Record updated successfully"
msgstr ""
@@ -248,7 +249,7 @@ msgstr ""
#: lib/music_library_web/components/record_components.ex:139
#: lib/music_library_web/live/collection_live/show.ex:147
#: lib/music_library_web/live/wishlist_live/show.ex:128
#: lib/music_library_web/live/wishlist_live/show.ex:144
#, elixir-autogen, elixir-format
msgid "Show"
msgstr ""
@@ -303,8 +304,8 @@ msgstr ""
msgid "Types"
msgstr ""
#: lib/music_library_web/live/collection_live/show.html.heex:223
#: lib/music_library_web/live/wishlist_live/show.html.heex:149
#: lib/music_library_web/live/collection_live/show.html.heex:212
#: lib/music_library_web/live/wishlist_live/show.html.heex:222
#, elixir-autogen, elixir-format
msgid "Updated at"
msgstr ""
@@ -327,7 +328,7 @@ msgstr ""
#: lib/music_library_web/components/layouts/app.html.heex:20
#: lib/music_library_web/live/artist_live/show.html.heex:100
#: lib/music_library_web/live/wishlist_live/index.ex:76
#: lib/music_library_web/live/wishlist_live/show.ex:122
#: lib/music_library_web/live/wishlist_live/show.ex:138
#, elixir-autogen, elixir-format
msgid "Wishlist"
msgstr ""
@@ -343,14 +344,14 @@ msgstr ""
msgid "close"
msgstr ""
#: lib/music_library_web/live/collection_live/show.html.heex:180
#: lib/music_library_web/live/wishlist_live/show.html.heex:114
#: lib/music_library_web/live/collection_live/show.html.heex:169
#: lib/music_library_web/live/wishlist_live/show.html.heex:187
#, elixir-autogen, elixir-format
msgid "Copy MusicBrainz ID to clipboard"
msgstr ""
#: lib/music_library_web/live/collection_live/show.html.heex:234
#: lib/music_library_web/live/wishlist_live/show.html.heex:160
#: lib/music_library_web/live/collection_live/show.html.heex:223
#: lib/music_library_web/live/wishlist_live/show.html.heex:233
#, elixir-autogen, elixir-format
msgid "MusicBrainz data"
msgstr ""
@@ -382,8 +383,8 @@ msgstr ""
msgid "Number of included records"
msgstr ""
#: lib/music_library_web/live/collection_live/show.html.heex:203
#: lib/music_library_web/live/wishlist_live/show.html.heex:129
#: lib/music_library_web/live/collection_live/show.html.heex:192
#: lib/music_library_web/live/wishlist_live/show.html.heex:202
#, elixir-autogen, elixir-format
msgid "Includes"
msgstr ""
@@ -411,22 +412,6 @@ msgstr ""
msgid "Cover refreshed successfully"
msgstr ""
#: lib/music_library_web/live/wishlist_live/show.html.heex:44
#, elixir-autogen, elixir-format
msgid "Cover"
msgstr ""
#: lib/music_library_web/live/wishlist_live/show.html.heex:56
#, elixir-autogen, elixir-format
msgid "MB Data"
msgstr ""
#: lib/music_library_web/live/wishlist_live/show.html.heex:37
#: lib/music_library_web/live/wishlist_live/show.html.heex:49
#, elixir-autogen, elixir-format
msgid "Refresh"
msgstr ""
#: lib/music_library_web/live/wishlist_live/show.ex:81
#, elixir-autogen, elixir-format
msgid "Error refreshing Cover"
@@ -516,22 +501,20 @@ msgstr ""
msgid "Genres populated successfully"
msgstr ""
#: lib/music_library_web/live/wishlist_live/show.html.heex:61
#, elixir-autogen, elixir-format
msgid "Populate"
msgstr ""
#: lib/music_library_web/live/collection_live/show.html.heex:118
#: lib/music_library_web/live/wishlist_live/show.html.heex:118
#, elixir-autogen, elixir-format
msgid "Populate genres"
msgstr ""
#: lib/music_library_web/live/collection_live/show.html.heex:102
#: lib/music_library_web/live/wishlist_live/show.html.heex:102
#, elixir-autogen, elixir-format
msgid "Refresh MB data"
msgstr ""
#: lib/music_library_web/live/collection_live/show.html.heex:86
#: lib/music_library_web/live/wishlist_live/show.html.heex:86
#, elixir-autogen, elixir-format
msgid "Refresh cover"
msgstr ""