93b347ad8d
Includes a small optimization that removes "" release IDs from the list of IDs checked against releases in the database.
138 lines
4.0 KiB
Elixir
138 lines
4.0 KiB
Elixir
defmodule MusicLibraryWeb.StatsLive.Index do
|
|
use MusicLibraryWeb, :live_view
|
|
|
|
import MusicLibraryWeb.StatsLive.DataComponents
|
|
|
|
alias MusicLibrary.{Collection, Records, Wishlist}
|
|
alias Records.Record
|
|
|
|
def mount(_params, _session, socket) do
|
|
collection_count_by_format = Collection.count_records_by_format()
|
|
|
|
collection_count_by_type = Collection.count_records_by_type()
|
|
|
|
collection_count =
|
|
Enum.reduce(collection_count_by_format, 0, fn {_, count}, acc -> acc + count end)
|
|
|
|
wishlist_count = Wishlist.count()
|
|
|
|
latest_record = Collection.get_latest_record!()
|
|
|
|
recent_tracks = LastFm.Feed.all()
|
|
|
|
release_ids = release_ids(recent_tracks)
|
|
|
|
collected_release_ids = Collection.collected_release_ids(release_ids)
|
|
wishlisted_release_ids = Wishlist.wishlisted_release_ids(release_ids)
|
|
|
|
if connected?(socket) do
|
|
LastFm.Feed.subscribe()
|
|
end
|
|
|
|
{:ok,
|
|
socket
|
|
|> stream_configure(:recent_tracks,
|
|
dom_id: fn track -> "track-#{track.scrobbled_at_uts}" end
|
|
)
|
|
|> stream(:recent_tracks, recent_tracks)
|
|
|> assign(
|
|
page_title: gettext("Stats"),
|
|
collection_count_by_format: collection_count_by_format,
|
|
collection_count_by_type: collection_count_by_type,
|
|
collection_count: collection_count,
|
|
wishlist_count: wishlist_count,
|
|
latest_record: latest_record,
|
|
collected_release_ids: collected_release_ids,
|
|
wishlisted_release_ids: wishlisted_release_ids,
|
|
nav_section: :stats
|
|
)}
|
|
end
|
|
|
|
def handle_event("import", %{"id" => musicbrainz_id, "format" => format}, socket) do
|
|
case Records.import_from_musicbrainz_release(musicbrainz_id,
|
|
format: format,
|
|
purchased_at: nil
|
|
) do
|
|
{:ok, record} ->
|
|
{:noreply,
|
|
socket
|
|
|> put_flash(:info, gettext("Record imported successfully"))
|
|
|> push_navigate(to: ~p"/wishlist/#{record.id}")}
|
|
|
|
{:error, %Ecto.Changeset{} = changeset} ->
|
|
{:noreply,
|
|
socket
|
|
|> put_flash(
|
|
:error,
|
|
gettext("Error importing record") <> "," <> inspect(changeset.errors)
|
|
)}
|
|
|
|
{:error, reason} ->
|
|
{:noreply,
|
|
socket
|
|
|> put_flash(:error, gettext("Error importing record") <> "," <> inspect(reason))}
|
|
end
|
|
end
|
|
|
|
def handle_event("refresh_lastfm_feed", _, socket) do
|
|
LastFm.Refresh.refresh()
|
|
{:noreply, socket}
|
|
end
|
|
|
|
def handle_info(%{tracks: recent_tracks}, socket) do
|
|
release_ids = release_ids(recent_tracks)
|
|
|
|
collected_release_ids = Collection.collected_release_ids(release_ids)
|
|
wishlisted_release_ids = Wishlist.wishlisted_release_ids(release_ids)
|
|
|
|
{:noreply,
|
|
socket
|
|
|> assign(
|
|
collected_release_ids: collected_release_ids,
|
|
wishlisted_release_ids: wishlisted_release_ids
|
|
)
|
|
|> stream(:recent_tracks, recent_tracks, reset: true)}
|
|
end
|
|
|
|
defp release_ids(recent_tracks) do
|
|
recent_tracks
|
|
|> Enum.map(fn t -> t.album.musicbrainz_id end)
|
|
|> Enum.uniq()
|
|
|> Enum.reject(fn musicbrainz_id -> musicbrainz_id == "" end)
|
|
end
|
|
|
|
# The Tailwind build step requires all needed classes to be explicitly referenced
|
|
# in the source code, and not dynamically generated. This implies that one cannot
|
|
# (for example) interpolate a number in a class name.
|
|
defp stats_class(collection) do
|
|
case Enum.count(collection) do
|
|
1 -> "grid-cols-1"
|
|
2 -> "grid-cols-2"
|
|
3 -> "grid-cols-3"
|
|
4 -> "grid-cols-4"
|
|
5 -> "grid-cols-5"
|
|
6 -> "grid-cols-6"
|
|
7 -> "grid-cols-7"
|
|
8 -> "grid-cols-8"
|
|
9 -> "grid-cols-9"
|
|
_other -> ""
|
|
end
|
|
end
|
|
|
|
defp format_scrobbled_at_uts(uts) do
|
|
uts
|
|
|> DateTime.from_unix!()
|
|
|> DateTime.to_iso8601()
|
|
end
|
|
|
|
defp toggle_actions_menu(track_id) do
|
|
JS.toggle(to: "#actions-#{track_id}")
|
|
|> JS.toggle_class("pointer-events-none", to: "#scrobble-activity > li")
|
|
end
|
|
|
|
def close_actions_menu(track_id) do
|
|
JS.hide(to: "#actions-#{track_id}")
|
|
|> JS.remove_class("pointer-events-none", to: "#scrobble-activity > li")
|
|
end
|
|
end
|