-
-

-
-
- {album.artist.name}
-
- <.link
- :if={artist_id(album, artist_id)}
- class="block text-sm font-semibold text-zinc-700 hover:text-zinc-500 dark:text-zinc-400 dark:hover:text-zinc-300"
- navigate={~p"/artists/#{artist_id(album, artist_id)}"}
- >
- {album.artist.name}
-
-
- {album.metadata.title}
-
-
- <.album_metadata_tooltip album={album} />
+
+
+
+
+
+
+

+
+
+ {album.artist.name}
+
+ <.link
+ :if={artist_id(album, artist_id)}
+ class="block text-sm font-semibold text-zinc-700 hover:text-zinc-500 dark:text-zinc-400 dark:hover:text-zinc-300"
+ navigate={~p"/artists/#{artist_id(album, artist_id)}"}
+ >
+ {album.artist.name}
+
+
+ {album.metadata.title}
+
+
+ <.album_metadata_tooltip album={album} />
+
-
- <.record_status_badges
- musicbrainz_id={album.metadata.musicbrainz_id}
- collected_record_id={collected_record_id}
- wishlisted_record_id={wishlisted_record_id}
- />
-
- <.import_format_dropdown
- :if={
- album.metadata.musicbrainz_id !== "" and !collected_record_id and
- !wishlisted_record_id
- }
- id={"actions-#{album.scrobbled_at_uts}-albums"}
- musicbrainz_id={album.metadata.musicbrainz_id}
- />
-
-
-
-
-
- <.tabs_panel name="tracks" active={@scrobble_activity_mode == "tracks"}>
-
- -
-
-
-
-
-
-

+
+ <.import_format_dropdown
+ :if={
+ album.metadata.musicbrainz_id !== "" and !collected_record_id and
+ !wishlisted_record_id
+ }
+ id={"actions-#{album.scrobbled_at_uts}-albums"}
+ musicbrainz_id={album.metadata.musicbrainz_id}
/>
-
-
- {track.artist.name}
-
- <.link
- :if={artist_id(track, artist_id)}
- class="block text-sm font-semibold text-zinc-700 hover:text-zinc-500 dark:text-zinc-400 dark:hover:text-zinc-300"
- navigate={~p"/artists/#{artist_id(track, artist_id)}"}
- >
- {track.artist.name}
-
-
- {track.title}
-
-
- {track.album.title}
-
-
- <.track_metadata_tooltip track={track} />
-
-
- <.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}
- />
-
-
-
-
+
+
+
+ <.tabs_panel name="tracks" active={@scrobble_activity_mode == "tracks"}>
+
+ -
+
+
+
+
+
+

+
+
+ {track.artist.name}
+
+ <.link
+ :if={artist_id(track, artist_id)}
+ class="block text-sm font-semibold text-zinc-700 hover:text-zinc-500 dark:text-zinc-400 dark:hover:text-zinc-300"
+ navigate={~p"/artists/#{artist_id(track, artist_id)}"}
+ >
+ {track.artist.name}
+
+
+ {track.title}
+
+
+ {track.album.title}
+
+
+ <.track_metadata_tooltip track={track} />
+
+
+
+ <.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}
+ />
+
+
+
+
+
+
"""
@@ -516,25 +516,6 @@ defmodule MusicLibraryWeb.StatsLive.Index do
"""
end
- attr :container_class, :string, default: nil
- slot :title, required: true
- slot :side_actions
- slot :inner_block, required: true
-
- defp section(assigns) do
- ~H"""
-
-
-
- {render_slot(@title)}
-
- {render_slot(@side_actions)}
-
- {render_slot(@inner_block)}
-
- """
- end
-
defp assign_counts(socket) do
collection_count_by_format = Collection.count_records_by_format()
diff --git a/lib/music_library_web/live/stats_live/top_by_period.ex b/lib/music_library_web/live/stats_live/top_by_period.ex
index 909dbf45..3ca27081 100644
--- a/lib/music_library_web/live/stats_live/top_by_period.ex
+++ b/lib/music_library_web/live/stats_live/top_by_period.ex
@@ -1,6 +1,8 @@
defmodule MusicLibraryWeb.StatsLive.TopByPeriod do
use MusicLibraryWeb, :live_component
+ import MusicLibraryWeb.StatsComponents, only: [section: 1]
+
attr :id, :string, required: true
attr :title, :string, required: true
attr :key, :atom, required: true
@@ -19,67 +21,67 @@ defmodule MusicLibraryWeb.StatsLive.TopByPeriod do
@impl true
def render(assigns) do
~H"""
-
+
<.tabs>
-
-
- {@title}
-
- <.tabs_list active_tab={name_from_period(@key, @period)} variant="segmented" size="xs">
- <:tab
- class="flex-1"
- name={"#{@key}_last_7_days"}
- phx-click={JS.push("set_period", value: %{period: "last_7_days"})}
- phx-target={@myself}
- >
- {gettext("7d")}
-
- <:tab
- class="flex-1"
- name={"#{@key}_last_30_days"}
- phx-click={JS.push("set_period", value: %{period: "last_30_days"})}
- phx-target={@myself}
- >
- {gettext("30d")}
-
- <:tab
- class="flex-1"
- name={"#{@key}_last_90_days"}
- phx-click={JS.push("set_period", value: %{period: "last_90_days"})}
- phx-target={@myself}
- >
- {gettext("90d")}
-
- <:tab
- class="flex-1"
- name={"#{@key}_last_365_days"}
- phx-click={JS.push("set_period", value: %{period: "last_365_days"})}
- phx-target={@myself}
- >
- {gettext("1y")}
-
- <:tab
- class="flex-1"
- name={"#{@key}_all_time"}
- phx-click={JS.push("set_period", value: %{period: "all_time"})}
- phx-target={@myself}
- >
- {gettext("∞")}
-
-
-
- <.async_result :let={items} assign={assigns[@key]}>
- <:loading>
-
- <.loading />
+ <.section>
+ <:title>{@title}
+ <:side_actions>
+ <.tabs_list active_tab={name_from_period(@key, @period)} variant="segmented" size="xs">
+ <:tab
+ class="flex-1"
+ name={"#{@key}_last_7_days"}
+ phx-click={JS.push("set_period", value: %{period: "last_7_days"})}
+ phx-target={@myself}
+ >
+ {gettext("7d")}
+
+ <:tab
+ class="flex-1"
+ name={"#{@key}_last_30_days"}
+ phx-click={JS.push("set_period", value: %{period: "last_30_days"})}
+ phx-target={@myself}
+ >
+ {gettext("30d")}
+
+ <:tab
+ class="flex-1"
+ name={"#{@key}_last_90_days"}
+ phx-click={JS.push("set_period", value: %{period: "last_90_days"})}
+ phx-target={@myself}
+ >
+ {gettext("90d")}
+
+ <:tab
+ class="flex-1"
+ name={"#{@key}_last_365_days"}
+ phx-click={JS.push("set_period", value: %{period: "last_365_days"})}
+ phx-target={@myself}
+ >
+ {gettext("1y")}
+
+ <:tab
+ class="flex-1"
+ name={"#{@key}_all_time"}
+ phx-click={JS.push("set_period", value: %{period: "all_time"})}
+ phx-target={@myself}
+ >
+ {gettext("∞")}
+
+
+
+ <.async_result :let={items} assign={assigns[@key]}>
+ <:loading>
+
+ <.loading />
+
+
+
+
+ {render_slot(@item, items)}
+
-
-
-
- {render_slot(@item, items)}
-
-
-
+
+
"""