Can sort wishlisted records by insertion

This commit is contained in:
Claudio Ortolina
2025-05-26 23:12:34 +01:00
parent 6cb2b41a67
commit 423d1e7764
6 changed files with 370 additions and 0 deletions
+7
View File
@@ -70,6 +70,13 @@ defmodule MusicLibrary.Records do
{:desc, r.purchased_at},
order_alphabetically()
])
:insertion ->
initial_search
|> order_by([r], [
{:desc, r.inserted_at},
order_alphabetically()
])
end
Enum.reduce(parsed_query, search_with_order, fn
@@ -47,11 +47,13 @@ defmodule MusicLibraryWeb.WishlistLive.Index do
defp apply_action(socket, :index, params) do
query = params["query"] || ""
order = parse_order(params["order"] || "insertion")
total_records = Wishlist.search_records_count(query)
record_list_params =
@default_records_list_params
|> merge_query(query)
|> merge_order(order)
|> merge_pagination(params, total_records)
load_and_assign_records(socket, record_list_params)
@@ -154,6 +156,10 @@ defmodule MusicLibraryWeb.WishlistLive.Index do
Map.put(record_list_params, :query, query)
end
defp merge_order(record_list_params, order) do
Map.put(record_list_params, :order, order)
end
defp merge_pagination(record_list_params, params, total_records) do
record_list_params
|> Map.put(:page, parse_int_or_default(params["page"], record_list_params.page))
@@ -170,6 +176,19 @@ defmodule MusicLibraryWeb.WishlistLive.Index do
String.to_integer(value)
end
defp parse_order("alphabetical"), do: :alphabetical
defp parse_order("insertion"), do: :insertion
defp order_path(record_list_params, order) do
qs =
record_list_params
|> Map.take([:query])
|> Map.put(:order, order)
|> Enum.filter(fn {_, v} -> v not in ["", nil] end)
~p"/wishlist?#{qs}"
end
defp back_path(record_list_params) do
qs =
record_list_params
@@ -18,6 +18,35 @@
</.link>
</div>
</header>
<div class="flex items-end justify-between gap-6 mt-8">
<span class="isolate inline-flex rounded-md shadow-xs">
<.button
patch={order_path(@record_list_params, :insertion)}
as="link"
size="sm"
class={[
"rounded-l-md rounded-r-none",
@record_list_params.order == :insertion && "!bg-zinc-100 dark:!bg-zinc-700"
]}
>
<.icon name="hero-star" class="mr-1 h-4 w-4" aria-hidden="true" data-slot="icon" />
{gettext("Insertion")}
</.button>
<.button
patch={order_path(@record_list_params, :alphabetical)}
as="link"
size="sm"
class={[
"-ml-px rounded-r-md rounded-l-none",
@record_list_params.order == :alphabetical && "!bg-zinc-100 dark:!bg-zinc-700"
]}
>
<.icon name="hero-user-solid" class="mr-1 h-4 w-4" aria-hidden="true" data-slot="icon" />
{gettext("A->Z")}
</.button>
</span>
</div>
</div>
<.record_list
+6
View File
@@ -418,6 +418,7 @@ msgid "Error loading play count"
msgstr ""
#: lib/music_library_web/live/collection_live/index.html.heex
#: lib/music_library_web/live/wishlist_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "A->Z"
msgstr ""
@@ -876,3 +877,8 @@ msgstr ""
#, elixir-autogen, elixir-format
msgid "Download"
msgstr ""
#: lib/music_library_web/live/wishlist_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "Insertion"
msgstr ""
+6
View File
@@ -418,6 +418,7 @@ msgid "Error loading play count"
msgstr ""
#: lib/music_library_web/live/collection_live/index.html.heex
#: lib/music_library_web/live/wishlist_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "A->Z"
msgstr ""
@@ -876,3 +877,8 @@ msgstr ""
#, elixir-autogen, elixir-format
msgid "Download"
msgstr ""
#: lib/music_library_web/live/wishlist_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "Insertion"
msgstr ""
@@ -0,0 +1,303 @@
defmodule MusicLibrary.Repo.Migrations.AddTimestampsToRecordsSearchIndex do
use Ecto.Migration
def up do
execute "DROP TRIGGER IF EXISTS records_after_update"
execute "DROP TRIGGER IF EXISTS records_after_insert"
execute "DROP TABLE records_search_index"
flush()
execute """
CREATE VIRTUAL TABLE records_search_index USING fts5(
id UNINDEXED,
type,
format,
title,
normalized_title,
artists,
normalized_artists,
genres,
musicbrainz_id,
release_ids UNINDEXED,
included_release_group_ids UNINDEXED,
cover_hash UNINDEXED,
purchased_at UNINDEXED,
release_date,
inserted_at UNINDEXED,
updated_at UNINDEXED
);
"""
flush()
execute """
CREATE TRIGGER records_after_insert
AFTER INSERT ON records
BEGIN
INSERT INTO records_search_index(
id,
type,
format,
title,
normalized_title,
artists,
normalized_artists,
genres,
musicbrainz_id,
release_ids,
included_release_group_ids,
cover_hash,
purchased_at,
release_date,
inserted_at,
updated_at
) SELECT
id,
type,
format,
title,
unaccent(title),
artists,
unaccent(artists),
genres,
musicbrainz_id,
release_ids,
included_release_group_ids,
cover_hash,
purchased_at,
release_date,
inserted_at,
updated_at
FROM records
WHERE NEW.id = records.id;
END;
"""
execute """
CREATE TRIGGER records_after_update
AFTER UPDATE ON records
BEGIN
INSERT INTO records_search_index(
id,
type,
format,
title,
normalized_title,
artists,
normalized_artists,
genres,
musicbrainz_id,
release_ids,
included_release_group_ids,
cover_hash,
purchased_at,
release_date,
inserted_at,
updated_at
) SELECT
id,
type,
format,
title,
unaccent(title),
artists,
unaccent(artists),
genres,
musicbrainz_id,
release_ids,
included_release_group_ids,
cover_hash,
purchased_at,
release_date,
inserted_at,
updated_at
FROM records
WHERE NEW.id = records.id;
END;
"""
flush()
execute """
INSERT INTO records_search_index(
id,
type,
format,
title,
normalized_title,
artists,
normalized_artists,
genres,
musicbrainz_id,
release_ids,
included_release_group_ids,
cover_hash,
purchased_at,
release_date,
inserted_at,
updated_at
) SELECT
id,
type,
format,
title,
unaccent(title),
artists,
unaccent(artists),
genres,
musicbrainz_id,
release_ids,
included_release_group_ids,
cover_hash,
purchased_at,
release_date,
inserted_at,
updated_at
FROM records;
"""
end
def down do
execute "DROP TRIGGER IF EXISTS records_after_update"
execute "DROP TRIGGER IF EXISTS records_after_insert"
execute "DROP TABLE records_search_index"
flush()
execute """
CREATE VIRTUAL TABLE records_search_index USING fts5(
id UNINDEXED,
type,
format,
title,
normalized_title,
artists,
normalized_artists,
genres,
musicbrainz_id,
release_ids UNINDEXED,
included_release_group_ids UNINDEXED,
cover_hash UNINDEXED,
purchased_at UNINDEXED,
release_date
);
"""
flush()
execute """
CREATE TRIGGER records_after_insert
AFTER INSERT ON records
BEGIN
INSERT INTO records_search_index(
id,
type,
format,
title,
normalized_title,
artists,
normalized_artists,
genres,
musicbrainz_id,
release_ids,
included_release_group_ids,
cover_hash,
purchased_at,
release_date
) SELECT
id,
type,
format,
title,
unaccent(title),
artists,
unaccent(artists),
genres,
musicbrainz_id,
release_ids,
included_release_group_ids,
cover_hash,
purchased_at,
release_date
FROM records
WHERE NEW.id = records.id;
END;
"""
execute """
CREATE TRIGGER records_after_update
AFTER UPDATE ON records
BEGIN
INSERT INTO records_search_index(
id,
type,
format,
title,
normalized_title,
artists,
normalized_artists,
genres,
musicbrainz_id,
release_ids,
included_release_group_ids,
cover_hash,
purchased_at,
release_date
) SELECT
id,
type,
format,
title,
unaccent(title),
artists,
unaccent(artists),
genres,
musicbrainz_id,
release_ids,
included_release_group_ids,
cover_hash,
purchased_at,
release_date
FROM records
WHERE NEW.id = records.id;
END;
"""
flush()
execute """
INSERT INTO records_search_index(
id,
type,
format,
title,
normalized_title,
artists,
normalized_artists,
genres,
musicbrainz_id,
release_ids,
included_release_group_ids,
cover_hash,
purchased_at,
release_date
) SELECT
id,
type,
format,
title,
unaccent(title),
artists,
unaccent(artists),
genres,
musicbrainz_id,
release_ids,
included_release_group_ids,
cover_hash,
purchased_at,
release_date
FROM records;
"""
end
end