Display tracks for records with a selected release

This commit is contained in:
Claudio Ortolina
2025-05-04 21:10:40 +01:00
parent 0952bcd399
commit f4fe638a95
7 changed files with 450 additions and 42 deletions
+50
View File
@@ -0,0 +1,50 @@
defmodule MusicBrainz.Release do
@enforce_keys [:id, :date, :barcode, :media]
defstruct [:id, :date, :barcode, :media]
defmodule Medium do
@enforce_keys [:format, :number, :track_count, :tracks]
defstruct [:format, :number, :track_count, :tracks]
end
defmodule Track do
@enforce_keys [:id, :title, :length, :number, :position]
defstruct [:id, :title, :length, :number, :position]
end
def media_count(release) do
Enum.count(release.media)
end
def from_api_response(r) do
%__MODULE__{
id: r["id"],
date: r["date"],
barcode: r["barcode"],
media: parse_media(r["media"])
}
end
defp parse_media(media) do
Enum.map(media, fn m ->
%Medium{
format: m["format"],
number: m["position"],
track_count: m["track-count"],
tracks: parse_tracks(m["tracks"])
}
end)
end
defp parse_tracks(tracks) do
Enum.map(tracks, fn t ->
%Track{
id: t["id"],
title: t["title"],
length: t["length"],
number: t["number"],
position: t["position"]
}
end)
end
end
@@ -33,6 +33,18 @@ defmodule MusicLibraryWeb.CollectionLive.Show do
def handle_params(%{"id" => id}, _, socket) do
record = Records.get_record!(id)
socket =
if record.selected_release_id do
socket
|> assign_async(:release_with_tracks, fn ->
with {:ok, release} <- MusicBrainz.get_release(record.selected_release_id) do
{:ok, %{release_with_tracks: MusicBrainz.Release.from_api_response(release)}}
end
end)
else
socket
end
{:noreply,
socket
|> assign(:nav_section, :records)
@@ -216,8 +216,21 @@
<dt class="text-xs md:text-sm font-medium leading-6 text-zinc-900 dark:text-zinc-400">
{gettext("Collected release")}
</dt>
<dd class="mt-1 text-xs md:text-sm leading-6 text-zinc-700 dark:text-zinc-300 sm:col-span-2 sm:mt-0">
{selected_release_label(@record)}
<dd class="mt-1 text-xs md:text-sm flex justify-between leading-6 text-zinc-700 dark:text-zinc-300 sm:col-span-2 sm:mt-0">
<span>{selected_release_label(@record)}</span>
<button
:if={@record.selected_release_id}
phx-click={Fluxon.open_dialog("tracks-sheet")}
>
<span class="sr-only">{gettext("Show Tracks")}</span>
<.icon
name="hero-numbered-list"
class="-mt-1 h-5 w-5"
aria-hidden="true"
data-slot="icon"
/>
</button>
</dd>
</div>
<div
@@ -261,6 +274,51 @@
<pre><code class="text-xs sm:text-sm"><%= Jason.encode!(@record.musicbrainz_data, pretty: true) %></code></pre>
</details>
<Fluxon.Components.Sheet.sheet
:if={@record.selected_release_id}
id="tracks-sheet"
placement="right"
open
>
<h3 class="text-lg font-semibold mb-4">{gettext("Tracks")}</h3>
<div class="space-y-4">
<.async_result :let={release_with_tracks} assign={@release_with_tracks}>
<:loading>
<span class="sr-only">{gettext("Loading release with tracks")}</span>
<Fluxon.Components.Loading.loading />
</:loading>
<:failed :let={_failure}>
<div class="mt-4 text-sm leading-5 text-zinc-500 dark:text-zinc-400">
<.icon
name="hero-exclamation-triangle"
class="-mt-1 mr-1 h-5 w-5"
aria-hidden="true"
data-slot="icon"
/>
{gettext("Error loading tracks")}
</div>
</:failed>
<div :for={medium <- release_with_tracks.media} class="space-y-4">
<h4
:if={MusicBrainz.Release.media_count(release_with_tracks) > 1}
class="text-sm font-semibold"
>
{medium.number}
</h4>
<ul class="list-disc pl-6">
<li
:for={track <- medium.tracks}
class="text-sm leading-5 text-zinc-700 dark:text-zinc-300"
>
{track.position} - {track.title}
</li>
</ul>
</div>
</.async_result>
</div>
</Fluxon.Components.Sheet.sheet>
<.modal
:if={@live_action == :edit}
id="record-modal"