From b65b5a376bf30b9e153937657c378d296871499a Mon Sep 17 00:00:00 2001 From: Moritz Date: Thu, 8 Jan 2026 11:42:29 +0100 Subject: [PATCH] feat: add user count display for each role - Add Users column showing number of users assigned to each role - Load user counts efficiently in single query to avoid N+1 - Similar implementation to membership fee types member count --- lib/mv_web/live/role_live/index.ex | 30 ++++++++++++++++++++++- lib/mv_web/live/role_live/index.html.heex | 4 +++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/lib/mv_web/live/role_live/index.ex b/lib/mv_web/live/role_live/index.ex index 879f236..9f1de40 100644 --- a/lib/mv_web/live/role_live/index.ex +++ b/lib/mv_web/live/role_live/index.ex @@ -17,16 +17,21 @@ defmodule MvWeb.RoleLive.Index do use MvWeb, :live_view alias Mv.Authorization + alias Mv.Accounts + + require Ash.Query @impl true def mount(_params, _session, socket) do socket = ensure_user_role_loaded(socket) roles = load_roles() + user_counts = load_user_counts(roles) {:ok, socket |> assign(:page_title, gettext("Listing Roles")) - |> assign(:roles, roles)} + |> assign(:roles, roles) + |> assign(:user_counts, user_counts)} end defp ensure_user_role_loaded(socket) do @@ -86,6 +91,29 @@ defmodule MvWeb.RoleLive.Index do end end + # Loads all user counts for roles in a single query to avoid N+1 queries + defp load_user_counts(roles) do + role_ids = Enum.map(roles, & &1.id) + + # Load all users with role_id in a single query + users = + Accounts.User + |> Ash.Query.filter(role_id in ^role_ids) + |> Ash.Query.select([:role_id]) + |> Ash.read!(domain: Mv.Accounts) + + # Group by role_id and count + users + |> Enum.group_by(& &1.role_id) + |> Enum.map(fn {role_id, users_list} -> {role_id, length(users_list)} end) + |> Map.new() + end + + # Gets user count from preloaded assigns map + defp get_user_count(role, user_counts) do + Map.get(user_counts, role.id, 0) + end + defp format_error(%Ash.Error.Invalid{} = error) do Enum.map_join(error.errors, ", ", fn e -> e.message end) end diff --git a/lib/mv_web/live/role_live/index.html.heex b/lib/mv_web/live/role_live/index.html.heex index 6981594..f863abb 100644 --- a/lib/mv_web/live/role_live/index.html.heex +++ b/lib/mv_web/live/role_live/index.html.heex @@ -49,6 +49,10 @@ <% end %> + <:col :let={role} label={gettext("Users")}> + {get_user_count(role, @user_counts)} + + <:action :let={role}>
<.link navigate={~p"/admin/roles/#{role}"}>{gettext("Show")}