Add Top 20 Release Years widget

This commit is contained in:
Claudio Ortolina
2026-03-21 09:02:25 +00:00
parent 55aa7aa9d3
commit 5a27fc46ac
5 changed files with 120 additions and 1 deletions
+17
View File
@@ -161,6 +161,23 @@ defmodule MusicLibrary.Collection do
Repo.all(q)
end
@spec count_records_by_release_year(keyword()) :: [{String.t(), non_neg_integer()}]
def count_records_by_release_year(opts \\ []) do
limit = Keyword.get(opts, :limit, @pagination[:stats_limit])
q =
from r in Record,
where: not is_nil(r.purchased_at),
where: not is_nil(r.release_date),
where: r.release_date != "",
group_by: fragment("substr(?, 1, 4)", r.release_date),
order_by: [desc: fragment("count(1)")],
select: {fragment("substr(?, 1, 4)", r.release_date), fragment("count(1)")},
limit: ^limit
Repo.all(q)
end
@spec collected_releases_query() :: Ecto.Query.t()
def collected_releases_query do
from rr in RecordRelease,
+20 -1
View File
@@ -292,7 +292,7 @@ defmodule MusicLibraryWeb.StatsLive.Index do
</.tabs>
</div>
<div class="mt-5 grid grid-cols-1 gap-5 lg:grid-cols-2">
<div class="mt-5 grid grid-cols-1 gap-5 lg:grid-cols-3">
<div>
<h1 class="text-base font-semibold text-zinc-900 lg:text-2xl dark:text-zinc-200">
{gettext("Top %{n} Collection Artists", %{n: length(@records_by_artist)})}
@@ -336,6 +336,23 @@ defmodule MusicLibraryWeb.StatsLive.Index do
/>
</div>
</div>
<div>
<h1 class="text-base font-semibold text-zinc-900 lg:text-2xl dark:text-zinc-200">
{gettext("Top 20 Release Years")}
</h1>
<div class="mt-5 rounded-md bg-white shadow-sm dark:bg-zinc-800">
<.vertical_bar_chart
data={@records_by_release_year}
width={600}
height={26 * length(@records_by_release_year)}
color_class="fill-red-500"
label_fn={fn {year, _count} -> year end}
value_fn={fn {_year, count} -> count end}
class="w-full"
/>
</div>
</div>
</div>
</Layouts.app>
"""
@@ -347,6 +364,7 @@ defmodule MusicLibraryWeb.StatsLive.Index do
latest_record = Collection.get_latest_record()
records_by_artists = Collection.count_records_by_artist(limit: 20)
records_by_genre = Collection.count_records_by_genre(limit: 20)
records_by_release_year = Collection.count_records_by_release_year(limit: 20)
records_on_this_day =
current_date
@@ -375,6 +393,7 @@ defmodule MusicLibraryWeb.StatsLive.Index do
current_section: :stats,
records_by_artist: records_by_artists,
records_by_genre: records_by_genre,
records_by_release_year: records_by_release_year,
records_on_this_day: records_on_this_day
)}
end
+5
View File
@@ -2336,3 +2336,8 @@ msgstr ""
#, elixir-autogen, elixir-format
msgid "Track ID"
msgstr ""
#: lib/music_library_web/live/stats_live/index.ex
#, elixir-autogen, elixir-format
msgid "Top 20 Release Years"
msgstr ""
+5
View File
@@ -2336,3 +2336,8 @@ msgstr ""
#, elixir-autogen, elixir-format, fuzzy
msgid "Track ID"
msgstr ""
#: lib/music_library_web/live/stats_live/index.ex
#, elixir-autogen, elixir-format
msgid "Top 20 Release Years"
msgstr ""
+73
View File
@@ -156,6 +156,79 @@ defmodule MusicLibrary.CollectionTest do
end
end
describe "count_records_by_release_year/1" do
test "returns counts grouped by release year, ordered by count descending" do
record_with_artist("Artist A", %{
release_date: "1994-09-13",
purchased_at: ~U[2024-12-27 16:50:57Z]
})
record_with_artist("Artist B", %{
release_date: "1994-03-01",
purchased_at: ~U[2024-12-28 16:50:57Z]
})
record_with_artist("Artist C", %{
release_date: "2020",
purchased_at: ~U[2024-12-29 16:50:57Z]
})
assert [{"1994", 2}, {"2020", 1}] = Collection.count_records_by_release_year()
end
test "excludes wishlisted records" do
record_with_artist("Artist A", %{
release_date: "2020",
purchased_at: ~U[2024-12-27 16:50:57Z]
})
record_with_artist("Artist B", %{
release_date: "2020",
purchased_at: nil
})
assert [{"2020", 1}] = Collection.count_records_by_release_year()
end
test "excludes records without a release date" do
record_with_artist("Artist A", %{
release_date: "2020",
purchased_at: ~U[2024-12-27 16:50:57Z]
})
record_with_artist("Artist B", %{
release_date: nil,
purchased_at: ~U[2024-12-28 16:50:57Z]
})
record_with_artist("Artist C", %{
release_date: "",
purchased_at: ~U[2024-12-29 16:50:57Z]
})
assert [{"2020", 1}] = Collection.count_records_by_release_year()
end
test "respects limit" do
record_with_artist("Artist A", %{
release_date: "1994",
purchased_at: ~U[2024-12-27 16:50:57Z]
})
record_with_artist("Artist B", %{
release_date: "1994",
purchased_at: ~U[2024-12-28 16:50:57Z]
})
record_with_artist("Artist C", %{
release_date: "2020",
purchased_at: ~U[2024-12-29 16:50:57Z]
})
assert [{"1994", 2}] = Collection.count_records_by_release_year(limit: 1)
end
end
describe "collected_artist_ids/0" do
setup [:fill_collection]