Inline templates inside LV modules
This commit is contained in:
@@ -16,6 +16,197 @@ defmodule MusicLibraryWeb.ScrobbledTracksLive.Index do
|
||||
order: :scrobbled_at
|
||||
}
|
||||
|
||||
@impl true
|
||||
def render(assigns) do
|
||||
~H"""
|
||||
<Layouts.app flash={@flash} current_section={@current_section} socket={@socket}>
|
||||
<div>
|
||||
<header class="gap-6">
|
||||
<div class="mb-2 mt-2">
|
||||
<.search_form query={@track_list_params.query} />
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="flex items-end gap-6 mt-8 justify-between">
|
||||
<.button_group>
|
||||
<.button
|
||||
patch={order_path(@track_list_params, :scrobbled_at)}
|
||||
size="xs"
|
||||
class={[
|
||||
@track_list_params.order == :scrobbled_at && "bg-zinc-100! dark:bg-zinc-700!"
|
||||
]}
|
||||
>
|
||||
<.icon
|
||||
name="hero-clock-solid"
|
||||
class="icon"
|
||||
aria-hidden="true"
|
||||
data-slot="icon"
|
||||
/>
|
||||
{gettext("Scrobbled")}
|
||||
</.button>
|
||||
<.button
|
||||
patch={order_path(@track_list_params, :title)}
|
||||
size="xs"
|
||||
class={[
|
||||
@track_list_params.order == :title && "bg-zinc-100! dark:bg-zinc-700!"
|
||||
]}
|
||||
>
|
||||
<.icon name="hero-musical-note-solid" class="icon" aria-hidden="true" data-slot="icon" />
|
||||
{gettext("Title")}
|
||||
</.button>
|
||||
<.button
|
||||
patch={order_path(@track_list_params, :artist)}
|
||||
size="xs"
|
||||
class={[
|
||||
@track_list_params.order == :artist && "bg-zinc-100! dark:bg-zinc-700!"
|
||||
]}
|
||||
>
|
||||
<.icon name="hero-user-solid" class="icon" aria-hidden="true" data-slot="icon" />
|
||||
{gettext("Artist")}
|
||||
</.button>
|
||||
<.button
|
||||
patch={order_path(@track_list_params, :album)}
|
||||
size="xs"
|
||||
class={[
|
||||
@track_list_params.order == :album && "bg-zinc-100! dark:bg-zinc-700!"
|
||||
]}
|
||||
>
|
||||
<.icon name="hero-musical-note-solid" class="icon" aria-hidden="true" data-slot="icon" />
|
||||
{gettext("Album")}
|
||||
</.button>
|
||||
</.button_group>
|
||||
<.refresh_lastfm_feed_button />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-6">
|
||||
<ul
|
||||
class="divide-y divide-zinc-100 dark:divide-zinc-300/20 mt-5"
|
||||
role="list"
|
||||
id="tracks"
|
||||
phx-update="stream"
|
||||
>
|
||||
<li
|
||||
id="no-scrobbled-tracks"
|
||||
class="hidden only:block p-8 text-center bg-zinc-50 dark:bg-zinc-800 rounded-lg"
|
||||
>
|
||||
<.icon name="hero-musical-note" class="h-12 w-12 text-zinc-400 mx-auto mb-4" />
|
||||
<p class="text-zinc-600 dark:text-zinc-400">
|
||||
{gettext("No scrobbled tracks found")}
|
||||
</p>
|
||||
</li>
|
||||
|
||||
<li
|
||||
:for={
|
||||
{id,
|
||||
%{
|
||||
track: track,
|
||||
artist_id: artist_id,
|
||||
collected_record_id: collected_record_id,
|
||||
wishlisted_record_id: wishlisted_record_id,
|
||||
cover_hash: cover_hash
|
||||
}} <- @streams.tracks
|
||||
}
|
||||
id={id}
|
||||
class="flex justify-between gap-x-6 py-5 hover:bg-zinc-50 dark:hover:bg-zinc-800 px-2 -mx-2 md:px-4 md:-mx-4 cursor-pointer"
|
||||
>
|
||||
<div class="flex items-center space-x-4 flex-1 min-w-0">
|
||||
<div class="shrink-0">
|
||||
<img
|
||||
class="h-12 w-12 rounded-md shadow-sm"
|
||||
src={track_cover_url(track, cover_hash)}
|
||||
alt={track.title}
|
||||
onerror={"this.src = '" <> ~p"/images/cover-not-found.png" <> "';"}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="min-w-0 flex-1">
|
||||
<p class="text-sm font-medium text-zinc-900 dark:text-zinc-100 truncate">
|
||||
{track.title}
|
||||
</p>
|
||||
<p class="text-sm text-zinc-600 dark:text-zinc-400 truncate">
|
||||
{track.artist.name}
|
||||
</p>
|
||||
<p class="text-sm text-zinc-500 dark:text-zinc-500 truncate">
|
||||
{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>
|
||||
<.track_metadata_tooltip track={track} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<.record_status_badges
|
||||
musicbrainz_id={track.album.musicbrainz_id}
|
||||
collected_record_id={collected_record_id}
|
||||
wishlisted_record_id={wishlisted_record_id}
|
||||
/>
|
||||
|
||||
<.import_format_dropdown
|
||||
:if={
|
||||
track.album.musicbrainz_id !== "" and !collected_record_id and
|
||||
!wishlisted_record_id
|
||||
}
|
||||
id={"actions-#{track.scrobbled_at_uts}-tracks"}
|
||||
musicbrainz_id={track.album.musicbrainz_id}
|
||||
/>
|
||||
<.dropdown id={"actions-#{track.scrobbled_at_uts}"} placement="bottom-end">
|
||||
<:toggle>
|
||||
<.button variant="ghost">
|
||||
<span class="sr-only">{gettext("Actions")}</span>
|
||||
<.icon
|
||||
name="hero-ellipsis-vertical"
|
||||
class="h-5 w-5 text-zinc-500 dark:text-zinc-400 cursor-pointer"
|
||||
aria-hidden="true"
|
||||
data-slot="icon"
|
||||
/>
|
||||
</.button>
|
||||
</:toggle>
|
||||
<.dropdown_link patch={~p"/scrobbled-tracks/#{track.scrobbled_at_uts}/edit"}>
|
||||
{gettext("Edit")}
|
||||
</.dropdown_link>
|
||||
<.dropdown_button
|
||||
phx-click={
|
||||
JS.push("delete", value: %{"scrobbled-at-uts": track.scrobbled_at_uts})
|
||||
|> JS.hide(to: "##{id}")
|
||||
}
|
||||
data-confirm={gettext("Are you sure?")}
|
||||
class={[
|
||||
"text-red-900! hover:bg-red-50! dark:text-red-500! dark:hover:bg-red-900/30! dark:hover:text-red-600!"
|
||||
]}
|
||||
>
|
||||
{gettext("Delete")}
|
||||
</.dropdown_button>
|
||||
</.dropdown>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<.pagination id={:bottom_pagination} pagination_params={@track_list_params} />
|
||||
</div>
|
||||
|
||||
<.structured_modal
|
||||
:if={@live_action == :edit}
|
||||
id="track-modal"
|
||||
on_close={JS.patch(back_path(@track_list_params))}
|
||||
>
|
||||
<.live_component
|
||||
module={MusicLibraryWeb.ScrobbledTracksLive.Form}
|
||||
id={@track.scrobbled_at_uts}
|
||||
action={@live_action}
|
||||
track={@track}
|
||||
patch={back_path(@track_list_params)}
|
||||
/>
|
||||
</.structured_modal>
|
||||
</Layouts.app>
|
||||
"""
|
||||
end
|
||||
|
||||
@impl true
|
||||
def mount(_params, _session, socket) do
|
||||
socket =
|
||||
|
||||
@@ -1,185 +0,0 @@
|
||||
<Layouts.app flash={@flash} current_section={@current_section} socket={@socket}>
|
||||
<div>
|
||||
<header class="gap-6">
|
||||
<div class="mb-2 mt-2">
|
||||
<.search_form query={@track_list_params.query} />
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="flex items-end gap-6 mt-8 justify-between">
|
||||
<.button_group>
|
||||
<.button
|
||||
patch={order_path(@track_list_params, :scrobbled_at)}
|
||||
size="xs"
|
||||
class={[
|
||||
@track_list_params.order == :scrobbled_at && "bg-zinc-100! dark:bg-zinc-700!"
|
||||
]}
|
||||
>
|
||||
<.icon
|
||||
name="hero-clock-solid"
|
||||
class="icon"
|
||||
aria-hidden="true"
|
||||
data-slot="icon"
|
||||
/>
|
||||
{gettext("Scrobbled")}
|
||||
</.button>
|
||||
<.button
|
||||
patch={order_path(@track_list_params, :title)}
|
||||
size="xs"
|
||||
class={[
|
||||
@track_list_params.order == :title && "bg-zinc-100! dark:bg-zinc-700!"
|
||||
]}
|
||||
>
|
||||
<.icon name="hero-musical-note-solid" class="icon" aria-hidden="true" data-slot="icon" />
|
||||
{gettext("Title")}
|
||||
</.button>
|
||||
<.button
|
||||
patch={order_path(@track_list_params, :artist)}
|
||||
size="xs"
|
||||
class={[
|
||||
@track_list_params.order == :artist && "bg-zinc-100! dark:bg-zinc-700!"
|
||||
]}
|
||||
>
|
||||
<.icon name="hero-user-solid" class="icon" aria-hidden="true" data-slot="icon" />
|
||||
{gettext("Artist")}
|
||||
</.button>
|
||||
<.button
|
||||
patch={order_path(@track_list_params, :album)}
|
||||
size="xs"
|
||||
class={[
|
||||
@track_list_params.order == :album && "bg-zinc-100! dark:bg-zinc-700!"
|
||||
]}
|
||||
>
|
||||
<.icon name="hero-musical-note-solid" class="icon" aria-hidden="true" data-slot="icon" />
|
||||
{gettext("Album")}
|
||||
</.button>
|
||||
</.button_group>
|
||||
<.refresh_lastfm_feed_button />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-6">
|
||||
<ul
|
||||
class="divide-y divide-zinc-100 dark:divide-zinc-300/20 mt-5"
|
||||
role="list"
|
||||
id="tracks"
|
||||
phx-update="stream"
|
||||
>
|
||||
<li
|
||||
id="no-scrobbled-tracks"
|
||||
class="hidden only:block p-8 text-center bg-zinc-50 dark:bg-zinc-800 rounded-lg"
|
||||
>
|
||||
<.icon name="hero-musical-note" class="h-12 w-12 text-zinc-400 mx-auto mb-4" />
|
||||
<p class="text-zinc-600 dark:text-zinc-400">
|
||||
{gettext("No scrobbled tracks found")}
|
||||
</p>
|
||||
</li>
|
||||
|
||||
<li
|
||||
:for={
|
||||
{id,
|
||||
%{
|
||||
track: track,
|
||||
artist_id: artist_id,
|
||||
collected_record_id: collected_record_id,
|
||||
wishlisted_record_id: wishlisted_record_id,
|
||||
cover_hash: cover_hash
|
||||
}} <- @streams.tracks
|
||||
}
|
||||
id={id}
|
||||
class="flex justify-between gap-x-6 py-5 hover:bg-zinc-50 dark:hover:bg-zinc-800 px-2 -mx-2 md:px-4 md:-mx-4 cursor-pointer"
|
||||
>
|
||||
<div class="flex items-center space-x-4 flex-1 min-w-0">
|
||||
<div class="shrink-0">
|
||||
<img
|
||||
class="h-12 w-12 rounded-md shadow-sm"
|
||||
src={track_cover_url(track, cover_hash)}
|
||||
alt={track.title}
|
||||
onerror={"this.src = '" <> ~p"/images/cover-not-found.png" <> "';"}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="min-w-0 flex-1">
|
||||
<p class="text-sm font-medium text-zinc-900 dark:text-zinc-100 truncate">
|
||||
{track.title}
|
||||
</p>
|
||||
<p class="text-sm text-zinc-600 dark:text-zinc-400 truncate">
|
||||
{track.artist.name}
|
||||
</p>
|
||||
<p class="text-sm text-zinc-500 dark:text-zinc-500 truncate">
|
||||
{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>
|
||||
<.track_metadata_tooltip track={track} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<.record_status_badges
|
||||
musicbrainz_id={track.album.musicbrainz_id}
|
||||
collected_record_id={collected_record_id}
|
||||
wishlisted_record_id={wishlisted_record_id}
|
||||
/>
|
||||
|
||||
<.import_format_dropdown
|
||||
:if={
|
||||
track.album.musicbrainz_id !== "" and !collected_record_id and
|
||||
!wishlisted_record_id
|
||||
}
|
||||
id={"actions-#{track.scrobbled_at_uts}-tracks"}
|
||||
musicbrainz_id={track.album.musicbrainz_id}
|
||||
/>
|
||||
<.dropdown id={"actions-#{track.scrobbled_at_uts}"} placement="bottom-end">
|
||||
<:toggle>
|
||||
<.button variant="ghost">
|
||||
<span class="sr-only">{gettext("Actions")}</span>
|
||||
<.icon
|
||||
name="hero-ellipsis-vertical"
|
||||
class="h-5 w-5 text-zinc-500 dark:text-zinc-400 cursor-pointer"
|
||||
aria-hidden="true"
|
||||
data-slot="icon"
|
||||
/>
|
||||
</.button>
|
||||
</:toggle>
|
||||
<.dropdown_link patch={~p"/scrobbled-tracks/#{track.scrobbled_at_uts}/edit"}>
|
||||
{gettext("Edit")}
|
||||
</.dropdown_link>
|
||||
<.dropdown_button
|
||||
phx-click={
|
||||
JS.push("delete", value: %{"scrobbled-at-uts": track.scrobbled_at_uts})
|
||||
|> JS.hide(to: "##{id}")
|
||||
}
|
||||
data-confirm={gettext("Are you sure?")}
|
||||
class={[
|
||||
"text-red-900! hover:bg-red-50! dark:text-red-500! dark:hover:bg-red-900/30! dark:hover:text-red-600!"
|
||||
]}
|
||||
>
|
||||
{gettext("Delete")}
|
||||
</.dropdown_button>
|
||||
</.dropdown>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<.pagination id={:bottom_pagination} pagination_params={@track_list_params} />
|
||||
</div>
|
||||
|
||||
<.structured_modal
|
||||
:if={@live_action == :edit}
|
||||
id="track-modal"
|
||||
on_close={JS.patch(back_path(@track_list_params))}
|
||||
>
|
||||
<.live_component
|
||||
module={MusicLibraryWeb.ScrobbledTracksLive.Form}
|
||||
id={@track.scrobbled_at_uts}
|
||||
action={@live_action}
|
||||
track={@track}
|
||||
patch={back_path(@track_list_params)}
|
||||
/>
|
||||
</.structured_modal>
|
||||
</Layouts.app>
|
||||
Reference in New Issue
Block a user