From a3b515533746a52bef117076c63a19ac264ab01d Mon Sep 17 00:00:00 2001 From: KKlochko Date: Thu, 17 Apr 2025 12:18:15 +0300 Subject: [PATCH] Add the search for Users Index LiveView. --- lib/decentralised_book_index/accounts/user.ex | 1 + .../components/my_components.ex | 1 + .../my_components/just_search_resources.ex | 50 +++++++++ .../live/user_live/index.ex | 104 ++++++++++++++---- 4 files changed, 135 insertions(+), 21 deletions(-) create mode 100644 lib/decentralised_book_index_web/components/my_components/just_search_resources.ex diff --git a/lib/decentralised_book_index/accounts/user.ex b/lib/decentralised_book_index/accounts/user.ex index 1507668..b2dcb96 100644 --- a/lib/decentralised_book_index/accounts/user.ex +++ b/lib/decentralised_book_index/accounts/user.ex @@ -282,6 +282,7 @@ defmodule DecentralisedBookIndex.Accounts.User do attribute :role, DecentralisedBookIndex.Accounts.Role do allow_nil? false default :user + public? true end end diff --git a/lib/decentralised_book_index_web/components/my_components.ex b/lib/decentralised_book_index_web/components/my_components.ex index 3cab065..1330ad7 100644 --- a/lib/decentralised_book_index_web/components/my_components.ex +++ b/lib/decentralised_book_index_web/components/my_components.ex @@ -10,6 +10,7 @@ defmodule DecentralisedBookIndexWeb.Components.MyComponents do import MyComponents.AuthorSearch, only: [author_search: 1] import MyComponents.SearchResources, only: [search_resources: 1] + import MyComponents.JustSearchResources, only: [just_search_resources: 1] import MyComponents.Pagination, only: [pagination: 1] import MyComponents.Buttons, only: [ diff --git a/lib/decentralised_book_index_web/components/my_components/just_search_resources.ex b/lib/decentralised_book_index_web/components/my_components/just_search_resources.ex new file mode 100644 index 0000000..c8c639a --- /dev/null +++ b/lib/decentralised_book_index_web/components/my_components/just_search_resources.ex @@ -0,0 +1,50 @@ +defmodule DecentralisedBookIndexWeb.Components.MyComponents.JustSearchResources do + use Phoenix.Component + use DecentralisedBookIndexWeb, :verified_routes + + alias DecentralisedBookIndex.Accounts.Role + + attr :search_query, :string, default: "" + attr :select_options, :list, required: true + attr :selected_option, :string, required: true + attr :current_user, :map, default: nil + + attr :search_placeholder, :string, default: "Search by name" + + def just_search_resources(assigns) do + ~H""" +
+
+
+
+ +
+
+ +
+ +
+
+
+
+
+
+ +
+
+
+
+
+ """ + end +end diff --git a/lib/decentralised_book_index_web/live/user_live/index.ex b/lib/decentralised_book_index_web/live/user_live/index.ex index 5c9447f..b5901fe 100644 --- a/lib/decentralised_book_index_web/live/user_live/index.ex +++ b/lib/decentralised_book_index_web/live/user_live/index.ex @@ -11,35 +11,64 @@ defmodule DecentralisedBookIndexWeb.UserLive.Index do
- <.table - id="users" - rows={@users} - row_click={fn {_id, user} -> JS.navigate(~p"/users/#{user}") end} - > - <:col :let={{_id, user}} label="Email">{user.email} - - <:col :let={{_id, user}} label="Role">{user.role} - - <:action :let={{_id, user}}> -
- <.link navigate={~p"/users/#{user}"}>Show -
- - <.link patch={~p"/users/#{user}/edit"}>Edit Role - - + <.just_search_resources + search_query={@search_query} + select_options={@select_options} + selected_option={@sort_by} + current_user={@current_user} + search_placeholder="Search by email" + />
+ + <%= if Enum.empty?(@page.results) do %> +
+
+

+ No Users +

+
+
+ <% else %> +
+ <.table + id="users" + rows={@users} + row_click={fn user -> JS.navigate(~p"/users/#{user}") end} + > + <:col :let={user} label="Email">{user.email} + + <:col :let={user} label="Role">{user.role} + + <:action :let={user}> +
+ <.link navigate={~p"/users/#{user}"}>Show +
+ + <.link patch={~p"/users/#{user}/edit"}>Edit Role + + + + <.pagination + endpoint={~p"/servers"} + page={@page} + page_params={@page_params} + params={@params} + /> +
+ <% end %> + """ end @impl true def mount(params, _session, socket) do search_query = Map.get(params, "query", "") - sort_by = Map.get(params, "sort_by", "name") + sort_by = Map.get(params, "sort_by", "name") |> validate_sort_by() page_params = AshPhoenix.LiveView.page_from_params(params, 10) page = User.search!( search_query, + query: [sort_input: sort_by], page: page_params ++ [count: true], actor: socket.assigns.current_user ) @@ -48,9 +77,10 @@ defmodule DecentralisedBookIndexWeb.UserLive.Index do socket |> assign(:sort_by, sort_by) |> assign(:search_query, search_query) + |> assign(:select_options, sort_options()) |> assign(:page_params, page_params) |> assign(:page, page) - |> assign(:users, user_row(page.results)) + |> assign(:users, page.results) |> assign(:params, params) |> apply_action(socket.assigns.live_action, params) @@ -67,7 +97,39 @@ defmodule DecentralisedBookIndexWeb.UserLive.Index do |> assign(:page_title, "Listing Users") end - defp user_row(users) do - Enum.map(users, fn user -> {user.id, user} end) + defp sort_options do + [ + {"Sort by email", "email"}, + {"Sort by role", "role"}, + {"Sort by role desc", "-role"}, + ] + end + + def validate_sort_by(key) do + valid_keys = Enum.map(sort_options(), &elem(&1, 1)) + + if key in valid_keys do + key + else + List.first(valid_keys) + end + end + + @impl true + def handle_event("change-sort", %{"sort_by" => sort_by}, socket) do + params = + socket.assigns.params + |> Map.put("sort_by", sort_by) + + {:noreply, push_patch(socket, to: ~p"/users?#{params}")} + end + + @impl true + def handle_event("search", %{"query" => query}, socket) do + params = + socket.assigns.params + |> Map.put("query", query) + + {:noreply, push_patch(socket, to: ~p"/users?#{params}")} end end