From 5959c9f5453af2784b189fc467e2816255278840 Mon Sep 17 00:00:00 2001 From: Moritz Date: Tue, 22 Jul 2025 19:57:18 +0200 Subject: [PATCH] feat: use layout from memberlist --- lib/mv_web/live/user_live/index.ex | 113 +++++++++++++--------- lib/mv_web/live/user_live/index.html.heex | 75 ++++++++++++++ priv/gettext/de/LC_MESSAGES/default.po | 18 +++- 3 files changed, 158 insertions(+), 48 deletions(-) create mode 100644 lib/mv_web/live/user_live/index.html.heex diff --git a/lib/mv_web/live/user_live/index.ex b/lib/mv_web/live/user_live/index.ex index d3c2dcd..39ced23 100644 --- a/lib/mv_web/live/user_live/index.ex +++ b/lib/mv_web/live/user_live/index.ex @@ -1,54 +1,19 @@ defmodule MvWeb.UserLive.Index do use MvWeb, :live_view - - @impl true - def render(assigns) do - ~H""" - - <.header> - {gettext("Listing Users")} - <:actions> - <.button variant="primary" navigate={~p"/users/new"}> - <.icon name="hero-plus" /> {gettext("New User")} - - - - - <.table - id="users" - rows={@streams.users} - row_click={fn {_id, user} -> JS.navigate(~p"/users/#{user}") end} - > - <:col :let={{_id, user}} label={gettext("Email")}>{user.email} - <:col :let={{_id, user}} label={gettext("OIDC ID")}>{user.oidc_id} - - <:action :let={{_id, user}}> -
- <.link navigate={~p"/users/#{user}"}>{gettext("Show")} -
- - <.link navigate={~p"/users/#{user}/edit"}>{gettext("Edit")} - - - <:action :let={{id, user}}> - <.link - phx-click={JS.push("delete", value: %{id: user.id}) |> hide("##{id}")} - data-confirm={gettext("Are you sure?")} - > - {gettext("Delete")} - - - -
- """ - end + import MvWeb.TableComponents @impl true def mount(_params, _session, socket) do + users = Ash.read!(Mv.Accounts.User, domain: Mv.Accounts) + sorted = Enum.sort_by(users, & &1.email) + {:ok, socket |> assign(:page_title, gettext("Listing Users")) - |> stream(:users, Ash.read!(Mv.Accounts.User, domain: Mv.Accounts))} + |> assign(:sort_field, :email) + |> assign(:sort_order, :asc) + |> assign(:users, sorted) + |> assign(:selected_users, [])} end @impl true @@ -56,6 +21,66 @@ defmodule MvWeb.UserLive.Index do user = Ash.get!(Mv.Accounts.User, id, domain: Mv.Accounts) Ash.destroy!(user, domain: Mv.Accounts) - {:noreply, stream_delete(socket, :users, user)} + updated_users = Enum.reject(socket.assigns.users, &(&1.id == id)) + {:noreply, assign(socket, :users, updated_users)} end + + # Selects one user in the list of users + @impl true + def handle_event("select_user", %{"id" => id}, socket) do + selected = + if id in socket.assigns.selected_users do + List.delete(socket.assigns.selected_users, id) + else + [id | socket.assigns.selected_users] + end + + {:noreply, assign(socket, :selected_users, selected)} + end + + # Sorts the list of users according to a field, when you click on the column header + @impl true + def handle_event("sort", %{"field" => field_str}, socket) do + users = socket.assigns.users + field = String.to_existing_atom(field_str) + + new_order = + if socket.assigns.sort_field == field do + toggle_order(socket.assigns.sort_order) + else + :asc + end + + sorted_users = + users + |> Enum.sort_by(&Map.get(&1, field), sort_fun(new_order)) + + {:noreply, + socket + |> assign(:sort_field, field) + |> assign(:sort_order, new_order) + |> assign(:users, sorted_users)} + end + + # Selects all users in the list of users + @impl true + def handle_event("select_all", _params, socket) do + users = socket.assigns.users + + all_ids = Enum.map(users, & &1.id) + + selected = + if Enum.sort(socket.assigns.selected_users) == Enum.sort(all_ids) do + [] + else + all_ids + end + + {:noreply, assign(socket, :selected_users, selected)} + end + + defp toggle_order(:asc), do: :desc + defp toggle_order(:desc), do: :asc + defp sort_fun(:asc), do: &<=/2 + defp sort_fun(:desc), do: &>=/2 end diff --git a/lib/mv_web/live/user_live/index.html.heex b/lib/mv_web/live/user_live/index.html.heex new file mode 100644 index 0000000..5b313f0 --- /dev/null +++ b/lib/mv_web/live/user_live/index.html.heex @@ -0,0 +1,75 @@ + + <.header> + {gettext("Listing Users")} + <:actions> + <.button variant="primary" navigate={~p"/users/new"}> + <.icon name="hero-plus" /> {gettext("New User")} + + + + + <.table + id="users" + rows={@users} + row_click={fn user -> JS.navigate(~p"/users/#{user}") end} + > + <:col + :let={user} + label={ + ~H""" + <.input + type="checkbox" + name="select_all" + phx-click="select_all" + checked={Enum.sort(@selected_users) == Enum.map(@users, & &1.id) |> Enum.sort()} + aria-label={gettext("Select all users")} + role="checkbox" + /> + """ + } + > + <.input + type="checkbox" + name={user.id} + phx-click="select_user" + phx-value-id={user.id} + checked={user.id in @selected_users} + phx-capture-click + phx-stop-propagation + aria-label={gettext("Select user")} + role="checkbox" + /> + + <:col + :let={user} + label={ + sort_button(%{ + field: :email, + label: gettext("Email"), + sort_field: @sort_field, + sort_order: @sort_order + }) + } + > + {user.email} + + <:col :let={user} label={gettext("OIDC ID")}>{user.oidc_id} + + <:action :let={user}> +
+ <.link navigate={~p"/users/#{user}"}>{gettext("Show")} +
+ + <.link navigate={~p"/users/#{user}/edit"}>{gettext("Edit")} + + + <:action :let={user}> + <.link + phx-click={JS.push("delete", value: %{id: user.id}) |> hide("#row-#{user.id}")} + data-confirm={gettext("Are you sure?")} + > + {gettext("Delete")} + + + +
\ No newline at end of file diff --git a/priv/gettext/de/LC_MESSAGES/default.po b/priv/gettext/de/LC_MESSAGES/default.po index 2f36e27..d466469 100644 --- a/priv/gettext/de/LC_MESSAGES/default.po +++ b/priv/gettext/de/LC_MESSAGES/default.po @@ -410,12 +410,12 @@ msgstr "" #: lib/mv_web/live/member_live/index.html.heex:27 #, elixir-autogen, elixir-format msgid "Select all members" -msgstr "" +msgstr "Alle Mitglieder auswählen" #: lib/mv_web/live/member_live/index.html.heex:41 #, elixir-autogen, elixir-format msgid "Select member" -msgstr "" +msgstr "Mitglied auswählen" #: lib/mv_web/components/layouts/navbar.ex:72 #, elixir-autogen, elixir-format @@ -476,12 +476,12 @@ msgstr "" #: lib/mv_web/components/table_components.ex:30 #, elixir-autogen, elixir-format msgid "ascending" -msgstr "" +msgstr "aufsteigend" #: lib/mv_web/components/table_components.ex:30 #, elixir-autogen, elixir-format msgid "descending" -msgstr "" +msgstr "absteigend" #: lib/mv_web/live/user_live/form.ex:51 #, elixir-autogen, elixir-format @@ -492,3 +492,13 @@ msgstr "Neuer" #, elixir-autogen, elixir-format msgid "Users created here will need to set their password through the authentication system." msgstr "Hier erstellte Benutzer müssen ihr Passwort über das Authentifizierungssystem setzen." + +#: lib/mv_web/live/user_live/index.html.heex:15 +#, elixir-autogen, elixir-format +msgid "Select all users" +msgstr "Alle Benutzer auswählen" + +#: lib/mv_web/live/user_live/index.html.heex:29 +#, elixir-autogen, elixir-format +msgid "Select user" +msgstr "Benutzer auswählen"