mitgliederverwaltung/lib/mv_web/live/user_live/index.ex

107 lines
2.9 KiB
Elixir

defmodule MvWeb.UserLive.Index do
@moduledoc """
LiveView for displaying and managing the user list.
## Features
- List all users with email and linked member
- Sort users by email (default)
- Delete users
- Navigate to user details and edit forms
- Bulk selection for future batch operations
## Relationships
Displays linked member information when a user is connected to a member account.
## Events
- `delete` - Remove a user from the database
- `select_user` - Toggle individual user selection
- `select_all` - Toggle selection of all visible users
## Security
User deletion requires admin permissions (enforced by Ash policies).
"""
use MvWeb, :live_view
import MvWeb.TableComponents
@impl true
def mount(_params, _session, socket) do
users = Ash.read!(Mv.Accounts.User, domain: Mv.Accounts, load: [:member])
sorted = Enum.sort_by(users, & &1.email)
{:ok,
socket
|> assign(:page_title, gettext("Listing Users"))
|> assign(:sort_field, :email)
|> assign(:sort_order, :asc)
|> assign(:users, sorted)
|> assign(:selected_users, [])}
end
@impl true
def handle_event("delete", %{"id" => id}, socket) do
user = Ash.get!(Mv.Accounts.User, id, domain: Mv.Accounts)
Ash.destroy!(user, domain: Mv.Accounts)
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