Enable searching across record sets

This commit is contained in:
Claudio Ortolina
2026-02-06 17:03:21 +00:00
parent 990d9f4c7e
commit 635bffc9fe
3 changed files with 70 additions and 4 deletions
+48
View File
@@ -21,6 +21,23 @@ defmodule MusicLibrary.RecordSets do
Repo.aggregate(RecordSet, :count)
end
def count_record_sets(query) do
record_sets_search_query(query)
|> Repo.aggregate(:count)
end
def search_record_sets(query, opts \\ []) do
offset = Keyword.get(opts, :offset, 0)
limit = Keyword.get(opts, :limit, 20)
record_sets_search_query(query)
|> order_by([rs], desc: rs.updated_at)
|> offset(^offset)
|> limit(^limit)
|> preload(items: :record)
|> Repo.all()
end
def get_record_set!(id) do
RecordSet
|> Repo.get!(id)
@@ -125,6 +142,37 @@ defmodule MusicLibrary.RecordSets do
{:ok, get_record_set!(record_set.id)}
end
defp record_sets_search_query(""), do: from(rs in RecordSet)
defp record_sets_search_query(query) do
like_query = "%#{query}%"
from(rs in RecordSet,
where:
like(rs.name, ^like_query) or
like(rs.description, ^like_query) or
fragment(
"""
EXISTS (
SELECT 1 FROM record_set_items AS i
JOIN records AS r ON r.id = i.record_id
WHERE i.record_set_id = ?
AND (
r.title LIKE ?
OR EXISTS (
SELECT 1 FROM json_each(r.artists)
WHERE json_extract(value, '$.name') LIKE ?
)
)
)
""",
rs.id,
^like_query,
^like_query
)
)
end
defp recompact_positions(record_set_id) do
items =
from(i in RecordSetItem,
@@ -47,10 +47,12 @@ defmodule MusicLibraryWeb.RecordSetLive.Index do
end
defp apply_action(socket, :index, params) do
total_sets = RecordSets.count_record_sets()
query = params["query"] || ""
total_sets = RecordSets.count_record_sets(query)
list_params =
@default_list_params
|> merge_query(query)
|> merge_pagination(params, total_sets)
load_and_assign_sets(socket, list_params)
@@ -75,6 +77,10 @@ defmodule MusicLibraryWeb.RecordSetLive.Index do
|> Map.put(:total_records, total_records)
end
defp merge_query(params, query) do
Map.put(params, :query, query)
end
defp parse_page(nil), do: 1
defp parse_page(page) when is_binary(page) do
@@ -101,7 +107,7 @@ defmodule MusicLibraryWeb.RecordSetLive.Index do
offset = page_to_offset(list_params.page, list_params.page_size)
sets =
RecordSets.list_record_sets(
RecordSets.search_record_sets(list_params.query,
offset: offset,
limit: list_params.page_size
)
@@ -119,7 +125,8 @@ defmodule MusicLibraryWeb.RecordSetLive.Index do
def back_path(list_params) do
qs =
list_params
|> Map.take([:page, :page_size])
|> Map.take([:query, :page, :page_size])
|> Enum.filter(fn {_, v} -> v not in ["", nil] end)
~p"/record-sets?#{qs}"
end
@@ -152,6 +159,15 @@ defmodule MusicLibraryWeb.RecordSetLive.Index do
end
@impl true
def handle_event("search", %{"query" => query}, socket) do
qs =
@default_list_params
|> Map.put(:query, query)
|> Map.take([:query, :page, :page_size])
{:noreply, push_patch(socket, to: ~p"/record-sets?#{qs}")}
end
def handle_event("delete_set", %{"id" => id}, socket) do
record_set = RecordSets.get_record_set!(id)
{:ok, _} = RecordSets.delete_record_set(record_set)
@@ -19,6 +19,8 @@
</div>
</header>
<.search_form query={@list_params.query} />
<div class="mt-6 space-y-6">
<ul phx-update="stream" id="record-sets-list" class="space-y-6">
<li
@@ -69,7 +71,7 @@
<.dropdown_link
id={"set-actions-#{record_set.id}-edit"}
patch={
~p"/record-sets/#{record_set}/edit?#{Map.take(@list_params, [:page, :page_size])}"
~p"/record-sets/#{record_set}/edit?#{Map.take(@list_params, [:query, :page, :page_size]) |> Enum.filter(fn {_, v} -> v not in ["", nil] end)}"
}
>
{gettext("Edit")}