24319b1bff
To open source the project down the line, it makes sense to have either everything custom or using OSS components in order to keep licensing as simple as possible.
181 lines
6.8 KiB
Plaintext
181 lines
6.8 KiB
Plaintext
<div class="md:columns-2 mt-4 px-4">
|
|
<div class="drop-shadow md:max-w-[38rem]">
|
|
<img
|
|
class="w-full rounded-lg drop-shadow"
|
|
src={~p"/covers/#{@record.id}?vsn=#{@record.cover_hash || ""}"}
|
|
alt={@record.title}
|
|
/>
|
|
</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}"}
|
|
>
|
|
{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-5 isolate inline-flex rounded-md shadow-sm">
|
|
<.link patch={~p"/collection/#{@record}/show/edit"} phx-click={JS.push_focus()}>
|
|
<.button type="button" class="relative inline-flex items-center rounded-r-none">
|
|
{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>
|
|
<.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("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("Delete")}
|
|
</.button>
|
|
</.link>
|
|
</nav>
|
|
</div>
|
|
<div>
|
|
<%!-- TODO: replace with OSS version --%>
|
|
<dl class="mt-4 divide-y divide-zinc-100 dark:divide-slate-300/30">
|
|
<div class="py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
|
|
<dt class="text-sm font-medium leading-6 text-zinc-900 dark:text-zinc-400">
|
|
{gettext("Genres")}
|
|
</dt>
|
|
<dd class="mt-1 text-sm leading-6 text-zinc-700 dark:text-zinc-300 sm:col-span-2 sm:mt-0">
|
|
<.link
|
|
:for={genre <- @record.genres}
|
|
class="mr-2 text-zinc-700 hover:text-zinc-500 dark:text-zinc-400 dark:hover:text-zinc-300"
|
|
patch={~p"/collection?#{%{query: ~s(genre:"#{genre}")}}"}
|
|
>
|
|
{genre}
|
|
</.link>
|
|
</dd>
|
|
</div>
|
|
<div class="py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
|
|
<dt class="text-sm font-medium leading-6 text-zinc-900 dark:text-zinc-400">
|
|
{gettext("MusicBrainz ID")}
|
|
</dt>
|
|
<dd class="mt-1 text-sm flex justify-between leading-6 text-zinc-700 dark:text-zinc-300 sm:col-span-2 sm:mt-0">
|
|
<a href={musicbrainz_url(@record)}>
|
|
<code id={"mb-#{@record.musicbrainz_id}"}>{@record.musicbrainz_id}</code>
|
|
</a>
|
|
<button phx-click={
|
|
JS.dispatch("music_library:clipcopy", to: "#mb-" <> @record.musicbrainz_id)
|
|
|> JS.transition("animate-shake")
|
|
}>
|
|
<span class="sr-only">{gettext("Copy MusicBrainz ID to clipboard")}</span>
|
|
<.icon
|
|
name="hero-clipboard-document"
|
|
class="-mt-1 h-5 w-5"
|
|
aria-hidden="true"
|
|
data-slot="icon"
|
|
/>
|
|
</button>
|
|
</dd>
|
|
</div>
|
|
<div class="py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
|
|
<dt class="text-sm font-medium leading-6 text-zinc-900 dark:text-zinc-400">
|
|
{gettext("Purchased on")}
|
|
</dt>
|
|
<dd class="mt-1 text-sm leading-6 text-zinc-700 dark:text-zinc-300 sm:col-span-2 sm:mt-0">
|
|
{human_datetime(@record.purchased_at)}
|
|
</dd>
|
|
</div>
|
|
<div
|
|
:if={Records.Record.child_release_groups_count(@record) > 0}
|
|
class="py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"
|
|
>
|
|
<dt class="text-sm font-medium leading-6 text-zinc-900 dark:text-zinc-400">
|
|
{gettext("Includes")}
|
|
</dt>
|
|
<dd class="mt-1 text-sm leading-6 text-zinc-700 dark:text-zinc-300 sm:col-span-2 sm:mt-0">
|
|
<ul>
|
|
<li :for={child_release_group <- Records.Record.child_release_groups(@record)}>
|
|
{child_release_group.artists} - {child_release_group.title}
|
|
</li>
|
|
</ul>
|
|
</dd>
|
|
</div>
|
|
<div class="py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
|
|
<dt class="text-sm font-medium leading-6 text-zinc-900 dark:text-zinc-400">
|
|
{gettext("Inserted at")}
|
|
</dt>
|
|
<dd class="mt-1 text-sm leading-6 text-zinc-700 dark:text-zinc-300 sm:col-span-2 sm:mt-0">
|
|
{human_datetime(@record.inserted_at)}
|
|
</dd>
|
|
</div>
|
|
<div class="py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
|
|
<dt class="text-sm font-medium leading-6 text-zinc-900 dark:text-zinc-400">
|
|
{gettext("Updated at")}
|
|
</dt>
|
|
<dd class="mt-1 text-sm leading-6 text-zinc-700 dark:text-zinc-300 sm:col-span-2 sm:mt-0">
|
|
{human_datetime(@record.updated_at)}
|
|
</dd>
|
|
</div>
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
<!-- TODO: extract to a component -->
|
|
<details class="mt-4 px-4 text-zinc-700 hover:text-zinc-500 dark:text-zinc-400 dark:hover:text-zinc-300">
|
|
<summary class="text-xs sm:text-sm">{gettext("MusicBrainz data")}</summary>
|
|
<pre><code class="text-xs sm:text-sm"><%= Jason.encode!(@record.musicbrainz_data, pretty: true) %></code></pre>
|
|
</details>
|
|
|
|
<div class="mt-4">
|
|
<.back navigate={@back_url}>
|
|
{gettext("Back to records")}
|
|
</.back>
|
|
</div>
|
|
|
|
<.modal
|
|
:if={@live_action == :edit}
|
|
id="record-modal"
|
|
show
|
|
on_cancel={JS.patch(~p"/collection/#{@record}")}
|
|
>
|
|
<.live_component
|
|
module={MusicLibraryWeb.RecordLive.FormComponent}
|
|
id={@record.id}
|
|
title={@page_title}
|
|
action={@live_action}
|
|
show_purchased_at={true}
|
|
record={@record}
|
|
patch={~p"/collection/#{@record}"}
|
|
/>
|
|
</.modal>
|