Add universal search support for record sets
This commit is contained in:
@@ -11,7 +11,7 @@ defmodule MusicLibrary.Search do
|
|||||||
import Ecto.Query, warn: false
|
import Ecto.Query, warn: false
|
||||||
|
|
||||||
alias MusicLibrary.Artists.ArtistInfo
|
alias MusicLibrary.Artists.ArtistInfo
|
||||||
alias MusicLibrary.{Collection, Repo, Wishlist}
|
alias MusicLibrary.{Collection, RecordSets, Repo, Wishlist}
|
||||||
alias MusicLibrary.Records.ArtistRecord
|
alias MusicLibrary.Records.ArtistRecord
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
@@ -31,7 +31,8 @@ defmodule MusicLibrary.Search do
|
|||||||
%{
|
%{
|
||||||
collection: search_collection(query, limit),
|
collection: search_collection(query, limit),
|
||||||
wishlist: search_wishlist(query, limit),
|
wishlist: search_wishlist(query, limit),
|
||||||
artists: search_artists(query, limit)
|
artists: search_artists(query, limit),
|
||||||
|
record_sets: search_record_sets(query, limit)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -90,10 +91,18 @@ defmodule MusicLibrary.Search do
|
|||||||
%{
|
%{
|
||||||
collection_count: Collection.search_records_count(query),
|
collection_count: Collection.search_records_count(query),
|
||||||
wishlist_count: Wishlist.search_records_count(query),
|
wishlist_count: Wishlist.search_records_count(query),
|
||||||
artists_count: search_artists_count(query)
|
artists_count: search_artists_count(query),
|
||||||
|
record_sets_count: RecordSets.count_record_sets(query)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Searches record sets by name, description, and contained records.
|
||||||
|
"""
|
||||||
|
def search_record_sets(query, limit \\ 5) do
|
||||||
|
RecordSets.search_record_sets(query, limit: limit)
|
||||||
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Gets the count of artists matching the search query.
|
Gets the count of artists matching the search query.
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ defmodule MusicLibraryWeb.SearchComponents do
|
|||||||
import MusicLibraryWeb.ArtistComponents, only: [artist_image: 1]
|
import MusicLibraryWeb.ArtistComponents, only: [artist_image: 1]
|
||||||
|
|
||||||
alias MusicLibrary.Records.Record
|
alias MusicLibrary.Records.Record
|
||||||
|
alias MusicLibraryWeb.Markdown
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Renders a search result item for records.
|
Renders a search result item for records.
|
||||||
@@ -102,6 +103,47 @@ defmodule MusicLibraryWeb.SearchComponents do
|
|||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Renders a search result item for record sets.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
<.search_result_record_set record_set={record_set} />
|
||||||
|
"""
|
||||||
|
attr :record_set, :map, required: true
|
||||||
|
attr :rest, :global, include: ~w(phx-click phx-value-id)
|
||||||
|
|
||||||
|
def search_result_record_set(assigns) do
|
||||||
|
~H"""
|
||||||
|
<div
|
||||||
|
class={[
|
||||||
|
"p-3 rounded-lg cursor-pointer transition-colors",
|
||||||
|
"hover:bg-zinc-50 dark:hover:bg-zinc-700",
|
||||||
|
"aria-selected:bg-zinc-200 dark:aria-selected:bg-zinc-700"
|
||||||
|
]}
|
||||||
|
role="option"
|
||||||
|
{@rest}
|
||||||
|
>
|
||||||
|
<div class="flex items-center space-x-3">
|
||||||
|
<div class="shrink-0 w-12 h-12 rounded-md bg-zinc-100 dark:bg-zinc-700 flex items-center justify-center">
|
||||||
|
<.icon name="hero-queue-list" class="h-6 w-6 text-zinc-400 dark:text-zinc-500" />
|
||||||
|
</div>
|
||||||
|
<div class="min-w-0 flex-1">
|
||||||
|
<p class="text-sm font-medium text-zinc-900 dark:text-zinc-100 truncate">
|
||||||
|
{@record_set.name}
|
||||||
|
</p>
|
||||||
|
<div
|
||||||
|
:if={@record_set.description}
|
||||||
|
class="prose prose-zinc dark:prose-invert prose-sm"
|
||||||
|
>
|
||||||
|
{render_description(@record_set.description)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
"""
|
||||||
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Renders a search result group with a title and items.
|
Renders a search result group with a title and items.
|
||||||
|
|
||||||
@@ -249,4 +291,11 @@ defmodule MusicLibraryWeb.SearchComponents do
|
|||||||
</div>
|
</div>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp render_description(description) do
|
||||||
|
description
|
||||||
|
|> String.slice(0, 100)
|
||||||
|
|> Markdown.to_html()
|
||||||
|
|> raw()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -79,7 +79,8 @@ defmodule MusicLibraryWeb.UniversalSearchLive.Index do
|
|||||||
total_results =
|
total_results =
|
||||||
length(search_results.collection) +
|
length(search_results.collection) +
|
||||||
length(search_results.wishlist) +
|
length(search_results.wishlist) +
|
||||||
length(search_results.artists)
|
length(search_results.artists) +
|
||||||
|
length(search_results.record_sets)
|
||||||
|
|
||||||
{:noreply,
|
{:noreply,
|
||||||
socket
|
socket
|
||||||
@@ -145,11 +146,32 @@ defmodule MusicLibraryWeb.UniversalSearchLive.Index do
|
|||||||
|> push_navigate(to: ~p"/wishlist?query=#{query}")}
|
|> push_navigate(to: ~p"/wishlist?query=#{query}")}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def handle_event("navigate_to_record_set", %{"id" => id}, socket) do
|
||||||
|
{:noreply,
|
||||||
|
socket
|
||||||
|
|> assign(:show_modal, false)
|
||||||
|
|> push_navigate(to: ~p"/record-sets/#{id}")}
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def handle_event("navigate_to_record_sets", %{"query" => query}, socket) do
|
||||||
|
{:noreply,
|
||||||
|
socket
|
||||||
|
|> assign(:show_modal, false)
|
||||||
|
|> push_navigate(to: ~p"/record-sets?query=#{query}")}
|
||||||
|
end
|
||||||
|
|
||||||
defp reset(socket) do
|
defp reset(socket) do
|
||||||
socket
|
socket
|
||||||
|> assign(:search_query, "")
|
|> assign(:search_query, "")
|
||||||
|> assign(:search_results, %{collection: [], wishlist: [], artists: []})
|
|> assign(:search_results, %{collection: [], wishlist: [], artists: [], record_sets: []})
|
||||||
|> assign(:search_counts, %{collection_count: 0, wishlist_count: 0, artists_count: 0})
|
|> assign(:search_counts, %{
|
||||||
|
collection_count: 0,
|
||||||
|
wishlist_count: 0,
|
||||||
|
artists_count: 0,
|
||||||
|
record_sets_count: 0
|
||||||
|
})
|
||||||
|> assign(:total_results, 0)
|
|> assign(:total_results, 0)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -96,6 +96,30 @@
|
|||||||
/>
|
/>
|
||||||
</:actions>
|
</:actions>
|
||||||
</.search_result_group>
|
</.search_result_group>
|
||||||
|
<.search_result_group
|
||||||
|
:if={length(@search_results.record_sets) > 0}
|
||||||
|
title="Record Sets"
|
||||||
|
count={length(@search_results.record_sets)}
|
||||||
|
total_count={@search_counts.record_sets_count}
|
||||||
|
>
|
||||||
|
<.search_result_record_set
|
||||||
|
:for={record_set <- @search_results.record_sets}
|
||||||
|
record_set={record_set}
|
||||||
|
phx-click="navigate_to_record_set"
|
||||||
|
phx-value-id={record_set.id}
|
||||||
|
phx-target={@myself}
|
||||||
|
/>
|
||||||
|
<:actions>
|
||||||
|
<.view_all_button
|
||||||
|
:if={@search_counts.record_sets_count > length(@search_results.record_sets)}
|
||||||
|
count={@search_counts.record_sets_count}
|
||||||
|
target="record set"
|
||||||
|
phx-click="navigate_to_record_sets"
|
||||||
|
phx-value-query={@search_query}
|
||||||
|
phx-target={@myself}
|
||||||
|
/>
|
||||||
|
</:actions>
|
||||||
|
</.search_result_group>
|
||||||
<.results_footer total_results={@total_results} />
|
<.results_footer total_results={@total_results} />
|
||||||
</.structured_modal>
|
</.structured_modal>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user