372 lines
14 KiB
Plaintext
372 lines
14 KiB
Plaintext
<div>
|
|
<h1 class="mt-5 text-base lg:text-2xl text-zinc-900 dark:text-zinc-200 font-semibold">
|
|
{gettext("Records")}
|
|
</h1>
|
|
<%!-- TODO: replace with OSS version --%>
|
|
<dl class="mt-5 grid grid-cols-2 gap-5 sm:grid-cols-5">
|
|
<.album_preview
|
|
record={@latest_record}
|
|
title={gettext("Latest purchase")}
|
|
class="col-span-2 sm:col-span-3"
|
|
/>
|
|
<.counter
|
|
title={gettext("Total collection")}
|
|
count={@collection_count}
|
|
path={~p"/collection"}
|
|
/>
|
|
<.counter title={gettext("Total wishlist")} count={@wishlist_count} path={~p"/wishlist"} />
|
|
</dl>
|
|
</div>
|
|
|
|
<div>
|
|
<h1 class="mt-5 text-base lg:text-2xl text-zinc-900 dark:text-zinc-200 font-semibold">
|
|
{gettext("Formats")}
|
|
</h1>
|
|
<%!-- TODO: replace with OSS version --%>
|
|
<dl class={[
|
|
"mt-5 grid divide-zinc-200 dark:divide-zinc-900 overflow-hidden rounded-md bg-white dark:bg-zinc-800 shadow-sm divide-x-2",
|
|
stats_class(@collection_count_by_format)
|
|
]}>
|
|
<div :for={{format, count} <- @collection_count_by_format} class="px-2 py-5 sm:px-4">
|
|
<dt class="text-sm font-medium text-zinc-500 dark:text-zinc-400 text-center max-sm:text-xs break-keep">
|
|
{format_label(format)}
|
|
</dt>
|
|
<dd class="mt-1 text-center">
|
|
<.link
|
|
class="text-xl lg:text-2xl font-semibold hover:text-zinc-500 dark:text-zinc-300 dark:hover:text-zinc-200"
|
|
navigate={~p"/collection?query=format:#{format}"}
|
|
>
|
|
{count}
|
|
</.link>
|
|
</dd>
|
|
</div>
|
|
</dl>
|
|
</div>
|
|
|
|
<div>
|
|
<h1 class="mt-5 text-base lg:text-2xl text-zinc-900 dark:text-zinc-200 font-semibold">
|
|
{gettext("Types")}
|
|
</h1>
|
|
<%!-- TODO: replace with OSS version --%>
|
|
<dl class={[
|
|
"mt-5 grid divide-zinc-200 dark:divide-zinc-900 overflow-hidden rounded-md bg-white dark:bg-zinc-800 shadow-sm divide-x-2",
|
|
stats_class(@collection_count_by_type)
|
|
]}>
|
|
<div :for={{type, count} <- @collection_count_by_type} class="px-2 py-5 sm:px-4">
|
|
<dt class="text-sm font-medium text-zinc-500 dark:text-zinc-400 text-center max-sm:text-xs break-keep">
|
|
{type_label(type)}
|
|
</dt>
|
|
<dd class="mt-1 text-center">
|
|
<.link
|
|
class="text-xl lg:text-2xl font-semibold hover:text-zinc-500 dark:text-zinc-300 dark:hover:text-zinc-200"
|
|
navigate={~p"/collection?query=type:#{type}"}
|
|
>
|
|
{count}
|
|
</.link>
|
|
</dd>
|
|
</div>
|
|
</dl>
|
|
</div>
|
|
|
|
<div class="flow-root">
|
|
<div class="mt-5 flex justify-between items-center">
|
|
<h1 class="text-base lg:text-2xl text-zinc-900 dark:text-zinc-200 font-semibold">
|
|
{gettext("Scrobble activity")}
|
|
</h1>
|
|
<button
|
|
type="button"
|
|
class="phx-click-loading:animate-spin text-zinc-500 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-300"
|
|
phx-click={JS.push("refresh_lastfm_feed")}
|
|
>
|
|
<span class="sr-only">{gettext("Refresh LastFm Feed")}</span>
|
|
<.icon name="hero-arrow-path" class="-mt-1 h-5 w-5" aria-hidden="true" data-slot="icon" />
|
|
</button>
|
|
</div>
|
|
<%!-- TODO: replace with OSS version --%>
|
|
<span class="mt-5 isolate inline-flex rounded-md shadow-xs">
|
|
<button
|
|
phx-click={JS.push("set_scrobble_activity_mode", value: %{"mode" => :albums})}
|
|
class={[
|
|
"relative inline-flex items-center rounded-l-md",
|
|
"px-3 py-2 text-xs sm:text-sm font-semibold",
|
|
"ring-1 ring-inset focus:z-10",
|
|
"bg-white dark:bg-zinc-900 text-zinc-900 dark:text-zinc-300 hover:bg-zinc-100 dark:hover:bg-zinc-700 ring-zinc-300",
|
|
@scrobble_activity_mode == :albums && "!bg-zinc-100 dark:!bg-zinc-700"
|
|
]}
|
|
>
|
|
{gettext("Albums")}
|
|
</button>
|
|
<button
|
|
phx-click={JS.push("set_scrobble_activity_mode", value: %{"mode" => :tracks})}
|
|
class={[
|
|
"relative -ml-px inline-flex items-center rounded-r-md",
|
|
"px-3 py-2 text-xs sm:text-sm font-semibold",
|
|
"ring-1 ring-inset focus:z-10",
|
|
"bg-white dark:bg-zinc-900 text-zinc-900 dark:text-zinc-300 hover:bg-zinc-100 dark:hover:bg-zinc-700 ring-zinc-300",
|
|
@scrobble_activity_mode == :tracks && "!bg-zinc-100 dark:!bg-zinc-700"
|
|
]}
|
|
>
|
|
{gettext("Tracks")}
|
|
</button>
|
|
</span>
|
|
<ul
|
|
:if={@scrobble_activity_mode == :albums}
|
|
id="scrobble-activity-albums"
|
|
role="list"
|
|
class="mt-5 rounded-md px-4 py-5 shadow-sm"
|
|
phx-update="stream"
|
|
>
|
|
<li :for={{id, album} <- @streams.recent_albums} id={id} class="group">
|
|
<div class="relative pb-8 group-last:pb-0">
|
|
<span
|
|
class="group-last:hidden absolute left-6 top-6 -ml-px h-full w-0.5 bg-zinc-200"
|
|
aria-hidden="true"
|
|
>
|
|
</span>
|
|
<div class="relative flex space-x-3 items-center justify-between">
|
|
<div class="flex min-w-0 justify-between space-x-4 items-center">
|
|
<img
|
|
class="h-12 w-12 rounded-md shadow-sm"
|
|
src={album.cover_url}
|
|
alt={album.metadata.title}
|
|
/>
|
|
<div>
|
|
<p
|
|
:if={album.artist.musicbrainz_id not in @artist_ids}
|
|
class="font-semibold text-sm block text-zinc-500 dark:text-zinc-400"
|
|
>
|
|
{album.artist.name}
|
|
</p>
|
|
<.link
|
|
:if={album.artist.musicbrainz_id in @artist_ids}
|
|
class="font-semibold text-sm block text-zinc-700 hover:text-zinc-500 dark:text-zinc-400 dark:hover:text-zinc-300"
|
|
navigate={~p"/artists/#{album.artist.musicbrainz_id}"}
|
|
>
|
|
{album.artist.name}
|
|
</.link>
|
|
<p class="font-semibold text-sm md:text-base text-zinc-700 dark:text-zinc-300">
|
|
{album.metadata.title}
|
|
</p>
|
|
<time
|
|
datetime={format_scrobbled_at_uts(album.scrobbled_at_uts)}
|
|
class="whitespace-nowrap text-right text-xs sm:text-sm text-zinc-500 dark:text-zinc-400"
|
|
>
|
|
{album.scrobbled_at_label}
|
|
</time>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="flex gap-1 flex-col text-right">
|
|
<.badge
|
|
:if={album.metadata.musicbrainz_id == ""}
|
|
color={:gray}
|
|
text={gettext("No MB ID")}
|
|
/>
|
|
<.link
|
|
:if={
|
|
record_id = tracked_record?(@collected_releases, album.metadata.musicbrainz_id)
|
|
}
|
|
navigate={~p"/collection/#{record_id}"}
|
|
>
|
|
<.badge color={:green} text={gettext("Collected")} />
|
|
</.link>
|
|
<.link
|
|
:if={
|
|
record_id = tracked_record?(@wishlisted_releases, album.metadata.musicbrainz_id)
|
|
}
|
|
navigate={~p"/wishlist/#{record_id}"}
|
|
>
|
|
<.badge color={:yellow} text={gettext("Wishlisted")} />
|
|
</.link>
|
|
</div>
|
|
|
|
<div
|
|
:if={
|
|
album.metadata.musicbrainz_id !== "" and
|
|
!tracked_record?(
|
|
@collected_releases ++ @wishlisted_releases,
|
|
album.metadata.musicbrainz_id
|
|
)
|
|
}
|
|
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(album.scrobbled_at_uts)}
|
|
phx-click-away={close_actions_menu(album.scrobbled_at_uts)}
|
|
>
|
|
<span class="sr-only">{gettext("Choose which format to import")}</span>
|
|
<.icon name="hero-star" class="-mt-1 h-5 w-5" aria-hidden="true" data-slot="icon" />
|
|
</button>
|
|
<!--
|
|
Dropdown menu, show/hide based on menu state.
|
|
|
|
Entering: "transition ease-out duration-100"
|
|
From: "transform opacity-0 scale-95"
|
|
To: "transform opacity-100 scale-100"
|
|
Leaving: "transition ease-in duration-75"
|
|
From: "transform opacity-100 scale-100"
|
|
To: "transform opacity-0 scale-95"
|
|
-->
|
|
<.focus_wrap
|
|
id={"actions-#{album.scrobbled_at_uts}"}
|
|
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-hidden"
|
|
]}
|
|
role="menu"
|
|
aria-orientation="vertical"
|
|
aria-labelledby="options-menu-0-button"
|
|
>
|
|
<.link
|
|
:for={format <- Records.Record.formats()}
|
|
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="0"
|
|
id={"actions-#{album.scrobbled_at_uts}-#{format}-import"}
|
|
phx-click={
|
|
JS.push("import",
|
|
value: %{id: album.metadata.musicbrainz_id, format: format},
|
|
page_loading: true
|
|
)
|
|
}
|
|
>
|
|
{format_label(format)}
|
|
</.link>
|
|
</.focus_wrap>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
<ul
|
|
:if={@scrobble_activity_mode == :tracks}
|
|
id="scrobble-activity-tracks"
|
|
role="list"
|
|
class="mt-5 rounded-md px-4 py-5 shadow-sm"
|
|
phx-update="stream"
|
|
>
|
|
<li :for={{id, track} <- @streams.recent_tracks} id={id} class="group">
|
|
<div class="relative pb-8 group-last:pb-0">
|
|
<span
|
|
class="group-last:hidden absolute left-6 top-6 -ml-px h-full w-0.5 bg-zinc-200"
|
|
aria-hidden="true"
|
|
>
|
|
</span>
|
|
<div class="relative flex space-x-3 items-center justify-between">
|
|
<div class="flex min-w-0 justify-between space-x-4 items-center">
|
|
<img class="h-12 w-12 rounded-md shadow-sm" src={track.cover_url} alt={track.title} />
|
|
<div>
|
|
<p
|
|
:if={track.artist.musicbrainz_id not in @artist_ids}
|
|
class="font-semibold text-sm block text-zinc-500 dark:text-zinc-400"
|
|
>
|
|
{track.artist.name}
|
|
</p>
|
|
<.link
|
|
:if={track.artist.musicbrainz_id in @artist_ids}
|
|
class="font-semibold text-sm block text-zinc-700 hover:text-zinc-500 dark:text-zinc-400 dark:hover:text-zinc-300"
|
|
navigate={~p"/artists/#{track.artist.musicbrainz_id}"}
|
|
>
|
|
{track.artist.name}
|
|
</.link>
|
|
<p class="font-semibold text-sm md:text-base text-zinc-700 dark:text-zinc-300">
|
|
{track.title}
|
|
</p>
|
|
<p class="font-semibold text-sm text-zinc-500 dark:text-zinc-400">
|
|
{track.album.title}
|
|
</p>
|
|
<time
|
|
datetime={format_scrobbled_at_uts(track.scrobbled_at_uts)}
|
|
class="whitespace-nowrap text-right text-xs sm:text-sm text-zinc-500 dark:text-zinc-400"
|
|
>
|
|
{track.scrobbled_at_label}
|
|
</time>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="flex gap-1 flex-col text-right">
|
|
<.badge
|
|
:if={track.album.musicbrainz_id == ""}
|
|
color={:gray}
|
|
text={gettext("No MB ID")}
|
|
/>
|
|
<.link
|
|
:if={record_id = tracked_record?(@collected_releases, track.album.musicbrainz_id)}
|
|
navigate={~p"/collection/#{record_id}"}
|
|
>
|
|
<.badge color={:green} text={gettext("Collected")} />
|
|
</.link>
|
|
<.link
|
|
:if={record_id = tracked_record?(@wishlisted_releases, track.album.musicbrainz_id)}
|
|
navigate={~p"/wishlist/#{record_id}"}
|
|
>
|
|
<.badge color={:yellow} text={gettext("Wishlisted")} />
|
|
</.link>
|
|
</div>
|
|
|
|
<div
|
|
:if={
|
|
track.album.musicbrainz_id !== "" and
|
|
!tracked_record?(
|
|
@collected_releases ++ @wishlisted_releases,
|
|
track.album.musicbrainz_id
|
|
)
|
|
}
|
|
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(track.scrobbled_at_uts)}
|
|
phx-click-away={close_actions_menu(track.scrobbled_at_uts)}
|
|
>
|
|
<span class="sr-only">{gettext("Choose which format to import")}</span>
|
|
<.icon name="hero-star" class="-mt-1 h-5 w-5" aria-hidden="true" data-slot="icon" />
|
|
</button>
|
|
<!--
|
|
Dropdown menu, show/hide based on menu state.
|
|
|
|
Entering: "transition ease-out duration-100"
|
|
From: "transform opacity-0 scale-95"
|
|
To: "transform opacity-100 scale-100"
|
|
Leaving: "transition ease-in duration-75"
|
|
From: "transform opacity-100 scale-100"
|
|
To: "transform opacity-0 scale-95"
|
|
-->
|
|
<.focus_wrap
|
|
id={"actions-#{track.scrobbled_at_uts}"}
|
|
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-hidden"
|
|
]}
|
|
role="menu"
|
|
aria-orientation="vertical"
|
|
aria-labelledby="options-menu-0-button"
|
|
>
|
|
<.link
|
|
:for={format <- Records.Record.formats()}
|
|
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="0"
|
|
id={"actions-#{track.scrobbled_at_uts}-#{format}-import"}
|
|
phx-click={
|
|
JS.push("import",
|
|
value: %{id: track.album.musicbrainz_id, format: format},
|
|
page_loading: true
|
|
)
|
|
}
|
|
>
|
|
{format_label(format)}
|
|
</.link>
|
|
</.focus_wrap>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|