Enable searching across record sets
This commit is contained in:
@@ -21,6 +21,23 @@ defmodule MusicLibrary.RecordSets do
|
|||||||
Repo.aggregate(RecordSet, :count)
|
Repo.aggregate(RecordSet, :count)
|
||||||
end
|
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
|
def get_record_set!(id) do
|
||||||
RecordSet
|
RecordSet
|
||||||
|> Repo.get!(id)
|
|> Repo.get!(id)
|
||||||
@@ -125,6 +142,37 @@ defmodule MusicLibrary.RecordSets do
|
|||||||
{:ok, get_record_set!(record_set.id)}
|
{:ok, get_record_set!(record_set.id)}
|
||||||
end
|
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
|
defp recompact_positions(record_set_id) do
|
||||||
items =
|
items =
|
||||||
from(i in RecordSetItem,
|
from(i in RecordSetItem,
|
||||||
|
|||||||
@@ -47,10 +47,12 @@ defmodule MusicLibraryWeb.RecordSetLive.Index do
|
|||||||
end
|
end
|
||||||
|
|
||||||
defp apply_action(socket, :index, params) do
|
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 =
|
list_params =
|
||||||
@default_list_params
|
@default_list_params
|
||||||
|
|> merge_query(query)
|
||||||
|> merge_pagination(params, total_sets)
|
|> merge_pagination(params, total_sets)
|
||||||
|
|
||||||
load_and_assign_sets(socket, list_params)
|
load_and_assign_sets(socket, list_params)
|
||||||
@@ -75,6 +77,10 @@ defmodule MusicLibraryWeb.RecordSetLive.Index do
|
|||||||
|> Map.put(:total_records, total_records)
|
|> Map.put(:total_records, total_records)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp merge_query(params, query) do
|
||||||
|
Map.put(params, :query, query)
|
||||||
|
end
|
||||||
|
|
||||||
defp parse_page(nil), do: 1
|
defp parse_page(nil), do: 1
|
||||||
|
|
||||||
defp parse_page(page) when is_binary(page) do
|
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)
|
offset = page_to_offset(list_params.page, list_params.page_size)
|
||||||
|
|
||||||
sets =
|
sets =
|
||||||
RecordSets.list_record_sets(
|
RecordSets.search_record_sets(list_params.query,
|
||||||
offset: offset,
|
offset: offset,
|
||||||
limit: list_params.page_size
|
limit: list_params.page_size
|
||||||
)
|
)
|
||||||
@@ -119,7 +125,8 @@ defmodule MusicLibraryWeb.RecordSetLive.Index do
|
|||||||
def back_path(list_params) do
|
def back_path(list_params) do
|
||||||
qs =
|
qs =
|
||||||
list_params
|
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}"
|
~p"/record-sets?#{qs}"
|
||||||
end
|
end
|
||||||
@@ -152,6 +159,15 @@ defmodule MusicLibraryWeb.RecordSetLive.Index do
|
|||||||
end
|
end
|
||||||
|
|
||||||
@impl true
|
@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
|
def handle_event("delete_set", %{"id" => id}, socket) do
|
||||||
record_set = RecordSets.get_record_set!(id)
|
record_set = RecordSets.get_record_set!(id)
|
||||||
{:ok, _} = RecordSets.delete_record_set(record_set)
|
{:ok, _} = RecordSets.delete_record_set(record_set)
|
||||||
|
|||||||
@@ -19,6 +19,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
<.search_form query={@list_params.query} />
|
||||||
|
|
||||||
<div class="mt-6 space-y-6">
|
<div class="mt-6 space-y-6">
|
||||||
<ul phx-update="stream" id="record-sets-list" class="space-y-6">
|
<ul phx-update="stream" id="record-sets-list" class="space-y-6">
|
||||||
<li
|
<li
|
||||||
@@ -69,7 +71,7 @@
|
|||||||
<.dropdown_link
|
<.dropdown_link
|
||||||
id={"set-actions-#{record_set.id}-edit"}
|
id={"set-actions-#{record_set.id}-edit"}
|
||||||
patch={
|
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")}
|
{gettext("Edit")}
|
||||||
|
|||||||
Reference in New Issue
Block a user