diff --git a/lib/music_library_web/components/add_record_component.ex b/lib/music_library_web/components/add_record_component.ex index 948808ea..0ebd3326 100644 --- a/lib/music_library_web/components/add_record_component.ex +++ b/lib/music_library_web/components/add_record_component.ex @@ -147,8 +147,27 @@ defmodule MusicLibraryWeb.AddRecordComponent do |> stream_configure(:release_groups, dom_id: fn rg -> "musicbrainz_#{rg.id}" end ) - |> stream(:release_groups, []) - |> assign(:form, to_form(%{"mb_query" => ""}))} + |> stream(:release_groups, [])} + end + + @impl true + def update(assigns, socket) do + mb_query = assigns.initial_query || "" + + socket = + if mb_query != "" do + {:ok, release_groups} = search(mb_query) + + stream(socket, :release_groups, release_groups, reset: true) + else + socket + end + + {:ok, + assign(socket, + icon_name: assigns.icon_name, + form: to_form(%{"mb_query" => mb_query}) + )} end @impl true diff --git a/lib/music_library_web/components/core_components.ex b/lib/music_library_web/components/core_components.ex index e5bff4e8..8fc8bb7e 100644 --- a/lib/music_library_web/components/core_components.ex +++ b/lib/music_library_web/components/core_components.ex @@ -631,6 +631,7 @@ defmodule MusicLibraryWeb.CoreComponents do Renders a round badge. """ attr :text, :string, required: true + attr :class, :string, default: nil def round_badge(assigns) do ~H""" @@ -640,7 +641,8 @@ defmodule MusicLibraryWeb.CoreComponents do "ring-1 ring-inset", "bg-zinc-50 dark:bg-zinc-500/10", "text-zinc-700 dark:text-zinc-400", - "ring-zinc-600/20 dark:ring-zinc-500/20" + "ring-zinc-600/20 dark:ring-zinc-500/20", + @class ]}> {assigns.text} diff --git a/lib/music_library_web/live/artist_live/show.ex b/lib/music_library_web/live/artist_live/show.ex index bbf13d73..a6becae7 100644 --- a/lib/music_library_web/live/artist_live/show.ex +++ b/lib/music_library_web/live/artist_live/show.ex @@ -10,7 +10,40 @@ defmodule MusicLibraryWeb.ArtistLive.Show do end @impl true - def handle_params(%{"musicbrainz_id" => musicbrainz_id}, _, socket) do + def handle_params(params, _url, socket) do + {:noreply, apply_action(socket, socket.assigns.live_action, params)} + end + + @impl true + def handle_event("import", %{"id" => musicbrainz_id, "format" => format}, socket) do + case Records.import_from_musicbrainz_release_group(musicbrainz_id, + format: format, + purchased_at: nil + ) do + {:ok, _record} -> + {:noreply, + socket + |> put_flash(:info, gettext("Record imported successfully")) + |> push_navigate(to: ~p"/artists/#{socket.assigns.artist.musicbrainz_id}")} + + {:error, %Ecto.Changeset{} = changeset} -> + {:noreply, + socket + |> put_flash( + :error, + gettext("Error importing record") <> "," <> inspect(changeset.errors) + ) + |> push_patch(to: ~p"/artists/#{socket.assigns.artist.musicbrainz_id}")} + + {:error, reason} -> + {:noreply, + socket + |> put_flash(:error, gettext("Error importing record") <> "," <> inspect(reason)) + |> push_patch(to: ~p"/artists/#{socket.assigns.artist.musicbrainz_id}")} + end + end + + defp apply_action(socket, :show, %{"musicbrainz_id" => musicbrainz_id}) do artist = Artists.get_artist!(musicbrainz_id) %{collection: collection_records, wishlist: wishlist_records} = @@ -18,25 +51,39 @@ defmodule MusicLibraryWeb.ArtistLive.Show do |> Records.get_artist_records() |> group_and_sort() - {:noreply, - socket - |> assign(:nav_section, :artists) - |> assign(:artist, artist) - |> stream(:collection_records, collection_records, reset: true) - |> stream(:wishlist_records, wishlist_records, reset: true) - |> assign(:collection_records_count, Enum.count(collection_records)) - |> assign(:wishlist_records_count, Enum.count(wishlist_records)) - |> assign_async(:artist_info, fn -> - with {:ok, artist_info} <- LastFm.get_artist_info(artist.musicbrainz_id, artist.name) do - {:ok, %{artist_info: artist_info}} - end - end) - |> assign_async(:similar_artists, fn -> - with {:ok, similar_artists} <- Artists.get_similar_artists(artist) do - {:ok, %{similar_artists: similar_artists}} - end - end) - |> assign(:page_title, page_title(socket.assigns.live_action, artist))} + socket + |> assign(:nav_section, :artists) + |> assign(:artist, artist) + |> stream(:collection_records, collection_records, reset: true) + |> stream(:wishlist_records, wishlist_records, reset: true) + |> assign(:collection_records_count, Enum.count(collection_records)) + |> assign(:wishlist_records_count, Enum.count(wishlist_records)) + |> assign_async(:artist_info, fn -> + with {:ok, artist_info} <- LastFm.get_artist_info(artist.musicbrainz_id, artist.name) do + {:ok, %{artist_info: artist_info}} + end + end) + |> assign_async(:similar_artists, fn -> + with {:ok, similar_artists} <- Artists.get_similar_artists(artist) do + {:ok, %{similar_artists: similar_artists}} + end + end) + |> assign(:page_title, page_title(socket.assigns.live_action, artist)) + end + + defp apply_action(socket, :import, params) do + socket = + if get_in(socket.assigns, [:streams, :collection_records]) == nil do + socket + |> apply_action(:show, params) + else + socket + end + + socket + |> assign(:page_title, gettext("Add more · Artist")) + |> assign(:initial_query, "arid:#{socket.assigns.artist.musicbrainz_id}") + |> assign(:record, nil) end defp page_title(:show, artist) do @@ -50,6 +97,17 @@ defmodule MusicLibraryWeb.ArtistLive.Show do ) end + defp page_title(:import, artist) do + Enum.join( + [ + artist.name, + "·", + gettext("Add more") + ], + " " + ) + end + defp group_and_sort(records) do {collection, wishlist} = Enum.split_with(records, fn r -> r.purchased_at end) diff --git a/lib/music_library_web/live/artist_live/show.html.heex b/lib/music_library_web/live/artist_live/show.html.heex index bbda7ef8..f91b9d28 100644 --- a/lib/music_library_web/live/artist_live/show.html.heex +++ b/lib/music_library_web/live/artist_live/show.html.heex @@ -1,39 +1,55 @@
-
+

{@artist.name}

- <.async_result :let={artist_info} assign={@artist_info}> - <:loading> -
- {gettext("Loading play count")} - <.icon - name="hero-arrow-path" - class="-mt-1 h-5 w-5 animate-spin" - aria-hidden="true" - data-slot="icon" - /> -
- - <:failed :let={_failure}> -
- <.icon - name="hero-exclamation-triangle" - class="-mt-1 mr-1 ml-2 h-5 w-5" - aria-hidden="true" - data-slot="icon" - /> - {gettext("Error loading play count")} -
- - <.round_badge :if={artist_info.on_tour} text={gettext("On Tour")} /> - 0} - class="ml-2 text-sm font-normal text-zinc-700 dark:text-zinc-300 grow text-right" +
+ <.async_result :let={artist_info} assign={@artist_info}> + <:loading> +
+ {gettext("Loading play count")} + <.icon + name="hero-arrow-path" + class="-mt-1 h-5 w-5 animate-spin" + aria-hidden="true" + data-slot="icon" + /> +
+ + <:failed :let={_failure}> +
+ <.icon + name="hero-exclamation-triangle" + class="-mt-1 mr-1 ml-2 h-5 w-5" + aria-hidden="true" + data-slot="icon" + /> + {gettext("Error loading play count")} +
+ + <.round_badge :if={artist_info.on_tour} text={gettext("On Tour")} class="mr-2" /> + 0} + class="text-xs font-medium text-zinc-700 dark:text-zinc-300 grow" + > + {ngettext("1 scrobble", "%{count} scrobbles", artist_info.play_count)} + + + <.link + class={[ + "relative inline-flex items-center rounded-md", + "px-3 py-2 text-xs sm:text-sm font-semibold", + "bg-zinc-900 hover:bg-zinc-800 dark:bg-zinc-100 dark:hover:bg-zinc-200", + "disabled:bg-zinc-300 dark:disabled:bg-zinc-300 disabled:active:text-white", + "text-white active:text-white/80 dark:text-zinc-900 dark:active:text-zinc-900/80", + "focus-visible:outline focus-visible:outline-offset-2 focus-visible:outline-zinc-600" + ]} + patch={~p"/artists/#{@artist.musicbrainz_id}/import"} > - {ngettext("1 scrobble", "%{count} scrobbles", artist_info.play_count)} - - + <.icon name="hero-plus" class="h-4 w-4 mr-2" aria-hidden="true" data-slot="icon" /> + {gettext("Add more")} + +
@@ -120,3 +136,21 @@
+ +<.modal + :if={@live_action == :import} + id="record-modal" + show + on_cancel={JS.patch(~p"/artists/#{@artist.musicbrainz_id}")} +> + <.live_component + module={MusicLibraryWeb.AddRecordComponent} + id={:search} + title={@page_title} + action={@live_action} + record={@record} + patch={~p"/artists/#{@artist.musicbrainz_id}"} + initial_query={"arid:#{@artist.musicbrainz_id}"} + icon_name="hero-plus" + /> + diff --git a/lib/music_library_web/router.ex b/lib/music_library_web/router.ex index ebefdb6c..b421e215 100644 --- a/lib/music_library_web/router.ex +++ b/lib/music_library_web/router.ex @@ -53,6 +53,7 @@ defmodule MusicLibraryWeb.Router do live "/wishlist/:id/show/edit", WishlistLive.Show, :edit live "/artists/:musicbrainz_id", ArtistLive.Show, :show + live "/artists/:musicbrainz_id/import", ArtistLive.Show, :import end end diff --git a/priv/gettext/default.pot b/priv/gettext/default.pot index 636e4a95..6c70204d 100644 --- a/priv/gettext/default.pot +++ b/priv/gettext/default.pot @@ -57,6 +57,7 @@ msgstr "" msgid "Edit" msgstr "" +#: lib/music_library_web/live/artist_live/show.ex #: lib/music_library_web/live/collection_live/index.ex #: lib/music_library_web/live/stats_live/index.ex #: lib/music_library_web/live/wishlist_live/index.ex @@ -167,6 +168,7 @@ msgstr "" msgid "Purchased on" msgstr "" +#: lib/music_library_web/live/artist_live/show.ex #: lib/music_library_web/live/collection_live/index.ex #: lib/music_library_web/live/stats_live/index.ex #: lib/music_library_web/live/wishlist_live/index.ex @@ -701,3 +703,14 @@ msgstr "" #, elixir-autogen, elixir-format msgid "Collection records by Genre" msgstr "" + +#: lib/music_library_web/live/artist_live/show.ex +#: lib/music_library_web/live/artist_live/show.html.heex +#, elixir-autogen, elixir-format +msgid "Add more" +msgstr "" + +#: lib/music_library_web/live/artist_live/show.ex +#, elixir-autogen, elixir-format +msgid "Add more · Artist" +msgstr ""