From a76ae7169f96cff3f44988b106120ce76d91a0c6 Mon Sep 17 00:00:00 2001 From: Claudio Ortolina Date: Thu, 26 Feb 2026 15:10:40 +0000 Subject: [PATCH] Enable universal navigation --- .../components/search_components.ex | 39 +++++++ .../live/universal_search_live/index.ex | 108 +++++++++++++++++- priv/gettext/default.pot | 10 ++ priv/gettext/en/LC_MESSAGES/default.po | 10 ++ 4 files changed, 166 insertions(+), 1 deletion(-) diff --git a/lib/music_library_web/components/search_components.ex b/lib/music_library_web/components/search_components.ex index 3dcbc90d..e1b80a53 100644 --- a/lib/music_library_web/components/search_components.ex +++ b/lib/music_library_web/components/search_components.ex @@ -159,6 +159,45 @@ defmodule MusicLibraryWeb.SearchComponents do """ end + @doc """ + Renders a search result item for navigation links. + + ## Examples + + <.search_result_navigation label="Collection" icon="hero-circle-stack" /> + """ + attr :label, :string, required: true + attr :icon, :string, required: true + attr :rest, :global, include: ~w(phx-click phx-value-path) + + def search_result_navigation(assigns) do + ~H""" +
+
+
+ <.icon name={@icon} class="h-4 w-4 text-zinc-500 dark:text-zinc-400" /> +
+
+

+ {@label} +

+
+ + {gettext("Go to →")} + +
+
+ """ + end + @doc """ Renders a search result group with a title and items. diff --git a/lib/music_library_web/live/universal_search_live/index.ex b/lib/music_library_web/live/universal_search_live/index.ex index e25bef60..41d2f859 100644 --- a/lib/music_library_web/live/universal_search_live/index.ex +++ b/lib/music_library_web/live/universal_search_live/index.ex @@ -39,6 +39,20 @@ defmodule MusicLibraryWeb.UniversalSearchLive.Index do <.no_results :if={@search_query != "" and @total_results == 0} query={@search_query} />
0} class="max-h-148 md:max-h-164 overflow-y-auto mt-4"> + <.search_result_group + :if={length(@navigation_links_results) > 0} + title={gettext("Go to")} + count={length(@navigation_links_results)} + > + <.search_result_navigation + :for={link <- @navigation_links_results} + label={link.label} + icon={link.icon} + phx-click="navigate_to_link" + phx-value-path={link.path} + phx-target={@myself} + /> + <.search_result_group :if={length(@search_results.artists) > 0} title="Artists" @@ -206,9 +220,11 @@ defmodule MusicLibraryWeb.UniversalSearchLive.Index do query -> search_results = Search.universal_search(query, limit: 5) search_counts = Search.search_counts(query) + navigation_links_results = filter_navigation_links(query) total_results = - length(search_results.collection) + + length(navigation_links_results) + + length(search_results.collection) + length(search_results.wishlist) + length(search_results.artists) + length(search_results.record_sets) @@ -218,6 +234,7 @@ defmodule MusicLibraryWeb.UniversalSearchLive.Index do |> assign(:search_query, query) |> assign(:search_results, search_results) |> assign(:search_counts, search_counts) + |> assign(:navigation_links_results, navigation_links_results) |> assign(:total_results, total_results)} end end @@ -293,6 +310,14 @@ defmodule MusicLibraryWeb.UniversalSearchLive.Index do |> push_navigate(to: ~p"/record-sets?query=#{query}")} end + @impl true + def handle_event("navigate_to_link", %{"path" => path}, socket) do + {:noreply, + socket + |> assign(:show_modal, false) + |> push_navigate(to: path)} + end + defp reset(socket) do socket |> assign(:search_query, "") @@ -303,6 +328,87 @@ defmodule MusicLibraryWeb.UniversalSearchLive.Index do artists_count: 0, record_sets_count: 0 }) + |> assign(:navigation_links_results, []) |> assign(:total_results, 0) end + + defp filter_navigation_links(query) do + downcased = String.downcase(query) + + Enum.filter(navigation_links(), fn link -> + String.contains?(String.downcase(link.label), downcased) or + Enum.any?(link.keywords, &String.contains?(&1, downcased)) + end) + end + + defp navigation_links do + [ + %{ + label: "Stats", + path: ~p"/", + icon: "hero-chart-pie", + keywords: ["stats", "dashboard", "home"] + }, + %{ + label: "Collection", + path: ~p"/collection", + icon: "hero-circle-stack", + keywords: ["collection", "collected", "records"] + }, + %{ + label: "Wishlist", + path: ~p"/wishlist", + icon: "hero-star", + keywords: ["wishlist", "wish", "want"] + }, + %{ + label: "Sets", + path: ~p"/record-sets", + icon: "hero-rectangle-stack", + keywords: ["sets", "record sets", "groups"] + }, + %{ + label: "Scrobble Anything", + path: ~p"/scrobble", + icon: "hero-play", + keywords: ["scrobble", "play"] + }, + %{ + label: "Scrobbled Tracks", + path: ~p"/scrobbled-tracks", + icon: "hero-musical-note", + keywords: ["scrobbled", "tracks", "history", "listening"] + }, + %{ + label: "Scrobble Rules", + path: ~p"/scrobble-rules", + icon: "hero-adjustments-horizontal", + keywords: ["scrobble rules", "rules", "remap"] + }, + %{ + label: "Online Store Templates", + path: ~p"/online-store-templates", + icon: "hero-building-storefront", + keywords: ["store", "templates", "online", "buy"] + }, + %{ + label: "Live Dashboard", + path: ~p"/dev/dashboard", + icon: "hero-chart-bar", + keywords: ["live dashboard", "telemetry", "metrics"] + }, + %{ + label: "Oban", + path: ~p"/dev/oban", + icon: "hero-cog", + keywords: ["oban", "jobs", "workers", "queue"] + }, + %{ + label: "Maintenance", + path: ~p"/dev/maintenance", + icon: "hero-wrench-screwdriver", + keywords: ["maintenance", "admin", "vacuum"] + } + ] + end end diff --git a/priv/gettext/default.pot b/priv/gettext/default.pot index 640e3859..be53a25b 100644 --- a/priv/gettext/default.pot +++ b/priv/gettext/default.pot @@ -2021,3 +2021,13 @@ msgstr "" #, elixir-autogen, elixir-format msgid "Wikipedia" msgstr "" + +#: lib/music_library_web/live/universal_search_live/index.ex +#, elixir-autogen, elixir-format +msgid "Go to" +msgstr "" + +#: lib/music_library_web/components/search_components.ex +#, elixir-autogen, elixir-format +msgid "Go to →" +msgstr "" diff --git a/priv/gettext/en/LC_MESSAGES/default.po b/priv/gettext/en/LC_MESSAGES/default.po index 6aa1b64d..6639b769 100644 --- a/priv/gettext/en/LC_MESSAGES/default.po +++ b/priv/gettext/en/LC_MESSAGES/default.po @@ -2021,3 +2021,13 @@ msgstr "" #, elixir-autogen, elixir-format, fuzzy msgid "Wikipedia" msgstr "" + +#: lib/music_library_web/live/universal_search_live/index.ex +#, elixir-autogen, elixir-format +msgid "Go to" +msgstr "" + +#: lib/music_library_web/components/search_components.ex +#, elixir-autogen, elixir-format +msgid "Go to →" +msgstr ""