Split ScrobbleActivity into focused modules
Move track CRUD/listing to ListeningStats and diagnostics to Maintenance, leaving ScrobbleActivity for scrobbling only. Closes #111
This commit is contained in:
@@ -37,7 +37,7 @@ defmodule Mix.Tasks.Scrobble.Audit do
|
||||
import Ecto.Query
|
||||
|
||||
alias LastFm.Track
|
||||
alias MusicLibrary.{Repo, ScrobbleActivity}
|
||||
alias MusicLibrary.{ListeningStats, Maintenance, Repo}
|
||||
|
||||
@impl Mix.Task
|
||||
def run(args) do
|
||||
@@ -102,7 +102,7 @@ defmodule Mix.Tasks.Scrobble.Audit do
|
||||
|
||||
defp generate_audit_report(:all, verbose) do
|
||||
%{
|
||||
total_tracks: ScrobbleActivity.count_tracks(),
|
||||
total_tracks: ListeningStats.scrobble_count(),
|
||||
artist_issues: audit_artist_musicbrainz_ids(verbose),
|
||||
album_issues: audit_album_musicbrainz_ids(verbose)
|
||||
}
|
||||
@@ -110,20 +110,20 @@ defmodule Mix.Tasks.Scrobble.Audit do
|
||||
|
||||
defp generate_audit_report(:artist, verbose) do
|
||||
%{
|
||||
total_tracks: ScrobbleActivity.count_tracks(),
|
||||
total_tracks: ListeningStats.scrobble_count(),
|
||||
artist_issues: audit_artist_musicbrainz_ids(verbose)
|
||||
}
|
||||
end
|
||||
|
||||
defp generate_audit_report(:album, verbose) do
|
||||
%{
|
||||
total_tracks: ScrobbleActivity.count_tracks(),
|
||||
total_tracks: ListeningStats.scrobble_count(),
|
||||
album_issues: audit_album_musicbrainz_ids(verbose)
|
||||
}
|
||||
end
|
||||
|
||||
defp audit_artist_musicbrainz_ids(verbose) do
|
||||
results = ScrobbleActivity.get_artists_missing_musicbrainz_id()
|
||||
results = Maintenance.get_artists_missing_musicbrainz_id()
|
||||
|
||||
total_tracks_affected =
|
||||
Enum.reduce(results, 0, fn %{track_count: count}, acc -> acc + count end)
|
||||
@@ -145,7 +145,7 @@ defmodule Mix.Tasks.Scrobble.Audit do
|
||||
end
|
||||
|
||||
defp audit_album_musicbrainz_ids(verbose) do
|
||||
results = ScrobbleActivity.get_albums_missing_musicbrainz_id()
|
||||
results = Maintenance.get_albums_missing_musicbrainz_id()
|
||||
|
||||
total_tracks_affected =
|
||||
Enum.reduce(results, 0, fn %{track_count: count}, acc -> acc + count end)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
defmodule MusicLibrary.ListeningStats do
|
||||
@moduledoc """
|
||||
Read-only listening analytics derived from Last.fm scrobble data.
|
||||
Listening analytics and track management derived from Last.fm scrobble data.
|
||||
|
||||
Provides scrobble counts, recent activity feeds, and top albums/artists
|
||||
by time period. All queries are read-only joins across LastFm.Track,
|
||||
Collection, Wishlist, and ArtistInfo.
|
||||
Provides scrobble counts, recent activity feeds, top albums/artists
|
||||
by time period, and track CRUD/search/listing. All queries join across
|
||||
LastFm.Track, Collection, Wishlist, and ArtistInfo.
|
||||
"""
|
||||
|
||||
import Ecto.Query
|
||||
@@ -36,27 +36,10 @@ defmodule MusicLibrary.ListeningStats do
|
||||
# not have the necessary information. In that case we can go from
|
||||
# track -> album -> record -> artist
|
||||
|
||||
all_artists_query =
|
||||
from ar in ArtistRecord,
|
||||
distinct: true
|
||||
|
||||
tracks_query =
|
||||
from t in Track,
|
||||
left_join: cr in subquery(Collection.collected_releases_query()),
|
||||
on: cr.release_id == fragment("? ->> '$.musicbrainz_id'", t.album),
|
||||
left_join: wr in subquery(Wishlist.wishlisted_releases_query()),
|
||||
on: wr.release_id == fragment("? ->> '$.musicbrainz_id'", t.album),
|
||||
left_join: ar in subquery(all_artists_query),
|
||||
on: wr.record_id == ar.record_id or cr.record_id == ar.record_id,
|
||||
from [t, cr, wr, ar] in tracks_with_record_info_query(),
|
||||
order_by: [desc: t.scrobbled_at_uts],
|
||||
limit: ^limit,
|
||||
select: %{
|
||||
track: t,
|
||||
collected_record_id: cr.record_id,
|
||||
wishlisted_record_id: wr.record_id,
|
||||
artist_id: ar.musicbrainz_id,
|
||||
cover_hash: coalesce(cr.cover_hash, wr.cover_hash)
|
||||
}
|
||||
limit: ^limit
|
||||
|
||||
recent_tracks = Repo.all(tracks_query)
|
||||
|
||||
@@ -100,6 +83,99 @@ defmodule MusicLibrary.ListeningStats do
|
||||
Calendar.strftime(ldt, "%d/%m/%Y %X")
|
||||
end
|
||||
|
||||
# Track CRUD + listing
|
||||
|
||||
@spec list_tracks(map()) :: [map()]
|
||||
def list_tracks(params \\ %{}) do
|
||||
query = Map.get(params, :query, "")
|
||||
page = Map.get(params, :page, 1)
|
||||
page_size = Map.get(params, :page_size, @pagination[:tracks_page_size])
|
||||
order = Map.get(params, :order, :scrobbled_at)
|
||||
|
||||
base_query = tracks_with_record_info_query()
|
||||
|
||||
search_query =
|
||||
if query == "" do
|
||||
base_query
|
||||
else
|
||||
query_term = "%#{String.downcase(query)}%"
|
||||
|
||||
from [t, cr, wr, ar] in base_query,
|
||||
where:
|
||||
like(fragment("lower(?)", t.title), ^query_term) or
|
||||
like(fragment("lower(json_extract(?, '$.name'))", t.artist), ^query_term) or
|
||||
like(fragment("lower(json_extract(?, '$.title'))", t.album), ^query_term)
|
||||
end
|
||||
|
||||
ordered_query =
|
||||
case order do
|
||||
:scrobbled_at ->
|
||||
from [t] in search_query, order_by: [desc: t.scrobbled_at_uts]
|
||||
|
||||
:title ->
|
||||
from [t] in search_query, order_by: [asc: t.title]
|
||||
|
||||
:artist ->
|
||||
from [t] in search_query,
|
||||
order_by: [asc: fragment("json_extract(?, '$.name')", t.artist)]
|
||||
|
||||
:album ->
|
||||
from [t] in search_query,
|
||||
order_by: [asc: fragment("json_extract(?, '$.title')", t.album)]
|
||||
end
|
||||
|
||||
offset = (page - 1) * page_size
|
||||
|
||||
from(t in ordered_query, limit: ^page_size, offset: ^offset)
|
||||
|> Repo.all()
|
||||
end
|
||||
|
||||
@spec get_track!(integer() | String.t()) :: LastFm.Track.t()
|
||||
def get_track!(scrobbled_at_uts) when is_integer(scrobbled_at_uts) do
|
||||
Repo.get!(Track, scrobbled_at_uts)
|
||||
end
|
||||
|
||||
def get_track!(scrobbled_at_uts) when is_binary(scrobbled_at_uts) do
|
||||
case Integer.parse(scrobbled_at_uts) do
|
||||
{id, ""} -> get_track!(id)
|
||||
_ -> raise Ecto.NoResultsError, queryable: Track
|
||||
end
|
||||
end
|
||||
|
||||
@spec update_track(LastFm.Track.t(), map()) ::
|
||||
{:ok, LastFm.Track.t()} | {:error, Ecto.Changeset.t()}
|
||||
def update_track(%Track{} = track, attrs) do
|
||||
changeset = Track.changeset(track, attrs)
|
||||
Repo.update(changeset)
|
||||
end
|
||||
|
||||
@spec delete_track(LastFm.Track.t()) :: {:ok, LastFm.Track.t()} | {:error, Ecto.Changeset.t()}
|
||||
def delete_track(%Track{} = track) do
|
||||
Repo.delete(track)
|
||||
end
|
||||
|
||||
@spec search_tracks_count(String.t()) :: non_neg_integer()
|
||||
def search_tracks_count(query \\ "") do
|
||||
base_query = from(t in Track)
|
||||
|
||||
search_query =
|
||||
if query == "" do
|
||||
base_query
|
||||
else
|
||||
query_term = "%#{String.downcase(query)}%"
|
||||
|
||||
from t in base_query,
|
||||
where:
|
||||
like(fragment("lower(?)", t.title), ^query_term) or
|
||||
like(fragment("lower(json_extract(artist, '$.name'))"), ^query_term) or
|
||||
like(fragment("lower(json_extract(album, '$.title'))"), ^query_term)
|
||||
end
|
||||
|
||||
Repo.aggregate(search_query, :count, :scrobbled_at_uts)
|
||||
end
|
||||
|
||||
# Top albums/artists by period
|
||||
|
||||
@doc """
|
||||
Gets top albums for the specified time periods (7, 30, 90, 365 days) and all
|
||||
time. Returns a list of maps with album information and play counts.
|
||||
@@ -187,6 +263,27 @@ defmodule MusicLibrary.ListeningStats do
|
||||
|
||||
# Shared base queries
|
||||
|
||||
defp tracks_with_record_info_query do
|
||||
all_artists_query =
|
||||
from ar in ArtistRecord,
|
||||
distinct: true
|
||||
|
||||
from t in Track,
|
||||
left_join: cr in subquery(Collection.collected_releases_query()),
|
||||
on: cr.release_id == fragment("? ->> '$.musicbrainz_id'", t.album),
|
||||
left_join: wr in subquery(Wishlist.wishlisted_releases_query()),
|
||||
on: wr.release_id == fragment("? ->> '$.musicbrainz_id'", t.album),
|
||||
left_join: ar in subquery(all_artists_query),
|
||||
on: wr.record_id == ar.record_id or cr.record_id == ar.record_id,
|
||||
select: %{
|
||||
track: t,
|
||||
collected_record_id: cr.record_id,
|
||||
wishlisted_record_id: wr.record_id,
|
||||
artist_id: ar.musicbrainz_id,
|
||||
cover_hash: coalesce(cr.cover_hash, wr.cover_hash)
|
||||
}
|
||||
end
|
||||
|
||||
defp top_albums_base_query do
|
||||
from t in Track,
|
||||
left_join: cr in subquery(Collection.collected_releases_query()),
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
defmodule MusicLibrary.Maintenance do
|
||||
@moduledoc """
|
||||
Context for database maintenance operations and background job monitoring.
|
||||
Context for database maintenance operations, background job monitoring,
|
||||
and scrobble data quality diagnostics.
|
||||
"""
|
||||
|
||||
import Ecto.Query
|
||||
|
||||
alias LastFm.Track
|
||||
alias MusicLibrary.BackgroundRepo
|
||||
alias MusicLibrary.Repo
|
||||
|
||||
@@ -39,4 +41,96 @@ defmodule MusicLibrary.Maintenance do
|
||||
def optimize do
|
||||
Repo.optimize()
|
||||
end
|
||||
|
||||
# Scrobble data quality diagnostics
|
||||
|
||||
@spec count_tracks_missing_artist_musicbrainz_id() :: non_neg_integer()
|
||||
def count_tracks_missing_artist_musicbrainz_id do
|
||||
query =
|
||||
from t in Track,
|
||||
where:
|
||||
fragment("json_extract(?, '$.musicbrainz_id') IS NULL", t.artist) or
|
||||
fragment("json_extract(?, '$.musicbrainz_id') = ''", t.artist),
|
||||
select: count(t.scrobbled_at_uts)
|
||||
|
||||
Repo.one(query) || 0
|
||||
end
|
||||
|
||||
@spec count_tracks_missing_album_musicbrainz_id() :: non_neg_integer()
|
||||
def count_tracks_missing_album_musicbrainz_id do
|
||||
query =
|
||||
from t in Track,
|
||||
where:
|
||||
fragment("json_extract(?, '$.musicbrainz_id') IS NULL", t.album) or
|
||||
fragment("json_extract(?, '$.musicbrainz_id') = ''", t.album),
|
||||
select: count(t.scrobbled_at_uts)
|
||||
|
||||
Repo.one(query) || 0
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets artists with missing MusicBrainz IDs, grouped by artist name.
|
||||
|
||||
Returns a list of maps with artist name and track count.
|
||||
"""
|
||||
@spec get_artists_missing_musicbrainz_id(keyword()) :: [map()]
|
||||
def get_artists_missing_musicbrainz_id(opts \\ []) do
|
||||
limit = Keyword.get(opts, :limit)
|
||||
|
||||
query =
|
||||
from t in Track,
|
||||
where:
|
||||
fragment("json_extract(?, '$.musicbrainz_id') IS NULL", t.artist) or
|
||||
fragment("json_extract(?, '$.musicbrainz_id') = ''", t.artist),
|
||||
select: %{
|
||||
artist_name: fragment("json_extract(?, '$.name')", t.artist),
|
||||
track_count: count(t.scrobbled_at_uts)
|
||||
},
|
||||
group_by: fragment("json_extract(?, '$.name')", t.artist),
|
||||
order_by: [desc: count(t.scrobbled_at_uts)]
|
||||
|
||||
query =
|
||||
if limit do
|
||||
from q in query, limit: ^limit
|
||||
else
|
||||
query
|
||||
end
|
||||
|
||||
Repo.all(query)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets albums with missing MusicBrainz IDs, grouped by album title and artist.
|
||||
|
||||
Returns a list of maps with album title, artist name, and track count.
|
||||
"""
|
||||
@spec get_albums_missing_musicbrainz_id(keyword()) :: [map()]
|
||||
def get_albums_missing_musicbrainz_id(opts \\ []) do
|
||||
limit = Keyword.get(opts, :limit)
|
||||
|
||||
query =
|
||||
from t in Track,
|
||||
where:
|
||||
fragment("json_extract(?, '$.musicbrainz_id') IS NULL", t.album) or
|
||||
fragment("json_extract(?, '$.musicbrainz_id') = ''", t.album),
|
||||
select: %{
|
||||
album_title: fragment("json_extract(?, '$.title')", t.album),
|
||||
artist_name: fragment("json_extract(?, '$.name')", t.artist),
|
||||
track_count: count(t.scrobbled_at_uts)
|
||||
},
|
||||
group_by: [
|
||||
fragment("json_extract(?, '$.title')", t.album),
|
||||
fragment("json_extract(?, '$.name')", t.artist)
|
||||
],
|
||||
order_by: [desc: count(t.scrobbled_at_uts)]
|
||||
|
||||
query =
|
||||
if limit do
|
||||
from q in query, limit: ^limit
|
||||
else
|
||||
query
|
||||
end
|
||||
|
||||
Repo.all(query)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
defmodule MusicLibrary.ScrobbleActivity do
|
||||
import Ecto.Query
|
||||
|
||||
alias LastFm.{Scrobble, Track}
|
||||
alias LastFm.Scrobble
|
||||
alias MusicBrainz.Release
|
||||
alias MusicLibrary.{Collection, Records.ArtistRecord, Repo, Secrets, Wishlist}
|
||||
|
||||
@pagination Application.compile_env!(:music_library, :pagination)
|
||||
alias MusicLibrary.Secrets
|
||||
|
||||
@spec can_scrobble?() :: boolean()
|
||||
def can_scrobble? do
|
||||
@@ -200,204 +196,4 @@ defmodule MusicLibrary.ScrobbleActivity do
|
||||
|
||||
defp main_artist_name([]), do: nil
|
||||
defp main_artist_name([artist | _rest]), do: artist.name
|
||||
|
||||
@spec list_tracks(map()) :: [map()]
|
||||
def list_tracks(params \\ %{}) do
|
||||
query = Map.get(params, :query, "")
|
||||
page = Map.get(params, :page, 1)
|
||||
page_size = Map.get(params, :page_size, @pagination[:tracks_page_size])
|
||||
order = Map.get(params, :order, :scrobbled_at)
|
||||
|
||||
all_artists_query =
|
||||
from ar in ArtistRecord,
|
||||
distinct: true
|
||||
|
||||
base_query =
|
||||
from t in Track,
|
||||
left_join: cr in subquery(Collection.collected_releases_query()),
|
||||
on: cr.release_id == fragment("? ->> '$.musicbrainz_id'", t.album),
|
||||
left_join: wr in subquery(Wishlist.wishlisted_releases_query()),
|
||||
on: wr.release_id == fragment("? ->> '$.musicbrainz_id'", t.album),
|
||||
left_join: ar in subquery(all_artists_query),
|
||||
on: wr.record_id == ar.record_id or cr.record_id == ar.record_id,
|
||||
select: %{
|
||||
track: t,
|
||||
collected_record_id: cr.record_id,
|
||||
wishlisted_record_id: wr.record_id,
|
||||
artist_id: ar.musicbrainz_id,
|
||||
cover_hash: coalesce(cr.cover_hash, wr.cover_hash)
|
||||
}
|
||||
|
||||
search_query =
|
||||
if query == "" do
|
||||
base_query
|
||||
else
|
||||
query_term = "%#{String.downcase(query)}%"
|
||||
|
||||
from t in base_query,
|
||||
where:
|
||||
like(fragment("lower(?)", t.title), ^query_term) or
|
||||
like(fragment("lower(json_extract(?, '$.name'))", t.artist), ^query_term) or
|
||||
like(fragment("lower(json_extract(?, '$.title'))", t.album), ^query_term)
|
||||
end
|
||||
|
||||
ordered_query =
|
||||
case order do
|
||||
:scrobbled_at ->
|
||||
from t in search_query, order_by: [desc: t.scrobbled_at_uts]
|
||||
|
||||
:title ->
|
||||
from t in search_query, order_by: [asc: t.title]
|
||||
|
||||
:artist ->
|
||||
from t in search_query, order_by: [asc: fragment("json_extract(?, '$.name')", t.artist)]
|
||||
|
||||
:album ->
|
||||
from t in search_query, order_by: [asc: fragment("json_extract(?, '$.title')", t.album)]
|
||||
end
|
||||
|
||||
offset = (page - 1) * page_size
|
||||
|
||||
from(t in ordered_query, limit: ^page_size, offset: ^offset)
|
||||
|> Repo.all()
|
||||
end
|
||||
|
||||
@spec count_tracks() :: non_neg_integer()
|
||||
def count_tracks do
|
||||
Repo.aggregate(Track, :count, :scrobbled_at_uts)
|
||||
end
|
||||
|
||||
@spec get_track!(integer() | String.t()) :: LastFm.Track.t()
|
||||
def get_track!(scrobbled_at_uts) when is_integer(scrobbled_at_uts) do
|
||||
Repo.get!(Track, scrobbled_at_uts)
|
||||
end
|
||||
|
||||
def get_track!(scrobbled_at_uts) when is_binary(scrobbled_at_uts) do
|
||||
case Integer.parse(scrobbled_at_uts) do
|
||||
{id, ""} -> get_track!(id)
|
||||
_ -> raise Ecto.NoResultsError, queryable: Track
|
||||
end
|
||||
end
|
||||
|
||||
@spec update_track(LastFm.Track.t(), map()) ::
|
||||
{:ok, LastFm.Track.t()} | {:error, Ecto.Changeset.t()}
|
||||
def update_track(%Track{} = track, attrs) do
|
||||
changeset = Track.changeset(track, attrs)
|
||||
Repo.update(changeset)
|
||||
end
|
||||
|
||||
@spec delete_track(LastFm.Track.t()) :: {:ok, LastFm.Track.t()} | {:error, Ecto.Changeset.t()}
|
||||
def delete_track(%Track{} = track) do
|
||||
Repo.delete(track)
|
||||
end
|
||||
|
||||
@spec search_tracks_count(String.t()) :: non_neg_integer()
|
||||
def search_tracks_count(query \\ "") do
|
||||
base_query = from(t in Track)
|
||||
|
||||
search_query =
|
||||
if query == "" do
|
||||
base_query
|
||||
else
|
||||
query_term = "%#{String.downcase(query)}%"
|
||||
|
||||
from t in base_query,
|
||||
where:
|
||||
like(fragment("lower(?)", t.title), ^query_term) or
|
||||
like(fragment("lower(json_extract(artist, '$.name'))"), ^query_term) or
|
||||
like(fragment("lower(json_extract(album, '$.title'))"), ^query_term)
|
||||
end
|
||||
|
||||
Repo.aggregate(search_query, :count, :scrobbled_at_uts)
|
||||
end
|
||||
|
||||
@spec count_tracks_missing_artist_musicbrainz_id() :: non_neg_integer()
|
||||
def count_tracks_missing_artist_musicbrainz_id do
|
||||
query =
|
||||
from t in Track,
|
||||
where:
|
||||
fragment("json_extract(?, '$.musicbrainz_id') IS NULL", t.artist) or
|
||||
fragment("json_extract(?, '$.musicbrainz_id') = ''", t.artist),
|
||||
select: count(t.scrobbled_at_uts)
|
||||
|
||||
Repo.one(query) || 0
|
||||
end
|
||||
|
||||
@spec count_tracks_missing_album_musicbrainz_id() :: non_neg_integer()
|
||||
def count_tracks_missing_album_musicbrainz_id do
|
||||
query =
|
||||
from t in Track,
|
||||
where:
|
||||
fragment("json_extract(?, '$.musicbrainz_id') IS NULL", t.album) or
|
||||
fragment("json_extract(?, '$.musicbrainz_id') = ''", t.album),
|
||||
select: count(t.scrobbled_at_uts)
|
||||
|
||||
Repo.one(query) || 0
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets artists with missing MusicBrainz IDs, grouped by artist name.
|
||||
|
||||
Returns a list of maps with artist name and track count.
|
||||
"""
|
||||
@spec get_artists_missing_musicbrainz_id(keyword()) :: [map()]
|
||||
def get_artists_missing_musicbrainz_id(opts \\ []) do
|
||||
limit = Keyword.get(opts, :limit)
|
||||
|
||||
query =
|
||||
from t in Track,
|
||||
where:
|
||||
fragment("json_extract(?, '$.musicbrainz_id') IS NULL", t.artist) or
|
||||
fragment("json_extract(?, '$.musicbrainz_id') = ''", t.artist),
|
||||
select: %{
|
||||
artist_name: fragment("json_extract(?, '$.name')", t.artist),
|
||||
track_count: count(t.scrobbled_at_uts)
|
||||
},
|
||||
group_by: fragment("json_extract(?, '$.name')", t.artist),
|
||||
order_by: [desc: count(t.scrobbled_at_uts)]
|
||||
|
||||
query =
|
||||
if limit do
|
||||
from q in query, limit: ^limit
|
||||
else
|
||||
query
|
||||
end
|
||||
|
||||
Repo.all(query)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets albums with missing MusicBrainz IDs, grouped by album title and artist.
|
||||
|
||||
Returns a list of maps with album title, artist name, and track count.
|
||||
"""
|
||||
@spec get_albums_missing_musicbrainz_id(keyword()) :: [map()]
|
||||
def get_albums_missing_musicbrainz_id(opts \\ []) do
|
||||
limit = Keyword.get(opts, :limit)
|
||||
|
||||
query =
|
||||
from t in Track,
|
||||
where:
|
||||
fragment("json_extract(?, '$.musicbrainz_id') IS NULL", t.album) or
|
||||
fragment("json_extract(?, '$.musicbrainz_id') = ''", t.album),
|
||||
select: %{
|
||||
album_title: fragment("json_extract(?, '$.title')", t.album),
|
||||
artist_name: fragment("json_extract(?, '$.name')", t.artist),
|
||||
track_count: count(t.scrobbled_at_uts)
|
||||
},
|
||||
group_by: [
|
||||
fragment("json_extract(?, '$.title')", t.album),
|
||||
fragment("json_extract(?, '$.name')", t.artist)
|
||||
],
|
||||
order_by: [desc: count(t.scrobbled_at_uts)]
|
||||
|
||||
query =
|
||||
if limit do
|
||||
from q in query, limit: ^limit
|
||||
else
|
||||
query
|
||||
end
|
||||
|
||||
Repo.all(query)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,7 +2,7 @@ defmodule MusicLibraryWeb.ScrobbledTracksLive.Form do
|
||||
use MusicLibraryWeb, :live_component
|
||||
|
||||
alias LastFm.Track
|
||||
alias MusicLibrary.ScrobbleActivity
|
||||
alias MusicLibrary.ListeningStats
|
||||
|
||||
@impl true
|
||||
def render(assigns) do
|
||||
@@ -104,7 +104,7 @@ defmodule MusicLibraryWeb.ScrobbledTracksLive.Form do
|
||||
end
|
||||
|
||||
defp save_track(socket, track_params) do
|
||||
case ScrobbleActivity.update_track(socket.assigns.track, track_params) do
|
||||
case ListeningStats.update_track(socket.assigns.track, track_params) do
|
||||
{:ok, track} ->
|
||||
notify_parent({:saved, track})
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ defmodule MusicLibraryWeb.ScrobbledTracksLive.Index do
|
||||
|
||||
alias LastFm.Track
|
||||
alias MusicLibrary.Assets.Transform
|
||||
alias MusicLibrary.ScrobbleActivity
|
||||
alias MusicLibrary.ListeningStats
|
||||
|
||||
@default_tracks_list_params %{
|
||||
query: "",
|
||||
@@ -229,7 +229,7 @@ defmodule MusicLibraryWeb.ScrobbledTracksLive.Index do
|
||||
end
|
||||
|
||||
defp apply_action(socket, :edit, %{"scrobbled_at_uts" => id} = params) do
|
||||
track = ScrobbleActivity.get_track!(id)
|
||||
track = ListeningStats.get_track!(id)
|
||||
|
||||
socket
|
||||
|> apply_fallback_index(params, :tracks, &apply_action/3)
|
||||
@@ -241,7 +241,7 @@ defmodule MusicLibraryWeb.ScrobbledTracksLive.Index do
|
||||
defp apply_action(socket, :index, params) do
|
||||
query = params["query"] || ""
|
||||
order = parse_order(params["order"] || "scrobbled_at")
|
||||
total_tracks = ScrobbleActivity.search_tracks_count(query)
|
||||
total_tracks = ListeningStats.search_tracks_count(query)
|
||||
|
||||
track_list_params =
|
||||
@default_tracks_list_params
|
||||
@@ -267,8 +267,8 @@ defmodule MusicLibraryWeb.ScrobbledTracksLive.Index do
|
||||
|
||||
@impl true
|
||||
def handle_event("delete", %{"scrobbled-at-uts" => scrobbled_at_uts}, socket) do
|
||||
track = ScrobbleActivity.get_track!(scrobbled_at_uts)
|
||||
{:ok, _} = ScrobbleActivity.delete_track(track)
|
||||
track = ListeningStats.get_track!(scrobbled_at_uts)
|
||||
{:ok, _} = ListeningStats.delete_track(track)
|
||||
|
||||
{:noreply, stream_delete(socket, :tracks, %{track: track})}
|
||||
end
|
||||
@@ -294,7 +294,7 @@ defmodule MusicLibraryWeb.ScrobbledTracksLive.Index do
|
||||
defp parse_order(_), do: :scrobbled_at
|
||||
|
||||
defp load_and_assign_tracks(socket, track_list_params) do
|
||||
tracks = ScrobbleActivity.list_tracks(track_list_params)
|
||||
tracks = ListeningStats.list_tracks(track_list_params)
|
||||
tracks_empty? = tracks == []
|
||||
|
||||
socket
|
||||
|
||||
Reference in New Issue
Block a user