refactor: extract shared helpers for RoleLive modules
Extract format_error and permission_set_badge_class functions into MvWeb.RoleLive.Helpers module to eliminate code duplication between Index and Show LiveViews.
This commit is contained in:
parent
715801eb9d
commit
cf220b9730
4 changed files with 44 additions and 34 deletions
|
|
@ -15,6 +15,8 @@ defmodule MvWeb.RoleLive.Form do
|
||||||
|
|
||||||
alias Mv.Authorization.PermissionSets
|
alias Mv.Authorization.PermissionSets
|
||||||
|
|
||||||
|
import MvWeb.RoleLive.Helpers
|
||||||
|
|
||||||
on_mount {MvWeb.LiveHelpers, :ensure_user_role_loaded}
|
on_mount {MvWeb.LiveHelpers, :ensure_user_role_loaded}
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
|
|
@ -134,6 +136,7 @@ defmodule MvWeb.RoleLive.Form do
|
||||||
end
|
end
|
||||||
rescue
|
rescue
|
||||||
e in [Ash.Error.Invalid] ->
|
e in [Ash.Error.Invalid] ->
|
||||||
|
# Handle exceptions that Ash.get might throw (e.g., policy violations)
|
||||||
case e do
|
case e do
|
||||||
%Ash.Error.Invalid{errors: [%Ash.Error.Query.NotFound{} | _]} ->
|
%Ash.Error.Invalid{errors: [%Ash.Error.Query.NotFound{} | _]} ->
|
||||||
{:ok,
|
{:ok,
|
||||||
|
|
@ -231,11 +234,4 @@ defmodule MvWeb.RoleLive.Form do
|
||||||
defp return_path("show", _role), do: ~p"/admin/roles"
|
defp return_path("show", _role), do: ~p"/admin/roles"
|
||||||
defp return_path(_, role) when not is_nil(role), do: ~p"/admin/roles/#{role.id}"
|
defp return_path(_, role) when not is_nil(role), do: ~p"/admin/roles/#{role.id}"
|
||||||
defp return_path(_, _role), do: ~p"/admin/roles"
|
defp return_path(_, _role), do: ~p"/admin/roles"
|
||||||
|
|
||||||
defp format_error(%Ash.Error.Invalid{} = error) do
|
|
||||||
Enum.map_join(error.errors, ", ", fn e -> e.message end)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp format_error(error) when is_binary(error), do: error
|
|
||||||
defp format_error(_error), do: gettext("An error occurred")
|
|
||||||
end
|
end
|
||||||
|
|
|
||||||
27
lib/mv_web/live/role_live/helpers.ex
Normal file
27
lib/mv_web/live/role_live/helpers.ex
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
defmodule MvWeb.RoleLive.Helpers do
|
||||||
|
@moduledoc """
|
||||||
|
Shared helper functions for RoleLive modules.
|
||||||
|
"""
|
||||||
|
use Gettext, backend: MvWeb.Gettext
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Formats an error for display to the user.
|
||||||
|
"""
|
||||||
|
@spec format_error(Ash.Error.Invalid.t() | String.t() | any()) :: String.t()
|
||||||
|
def format_error(%Ash.Error.Invalid{} = error) do
|
||||||
|
Enum.map_join(error.errors, ", ", fn e -> e.message end)
|
||||||
|
end
|
||||||
|
|
||||||
|
def format_error(error) when is_binary(error), do: error
|
||||||
|
def format_error(_error), do: gettext("An error occurred")
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Returns the CSS badge class for a permission set name.
|
||||||
|
"""
|
||||||
|
@spec permission_set_badge_class(String.t()) :: String.t()
|
||||||
|
def permission_set_badge_class("own_data"), do: "badge badge-neutral badge-sm"
|
||||||
|
def permission_set_badge_class("read_only"), do: "badge badge-info badge-sm"
|
||||||
|
def permission_set_badge_class("normal_user"), do: "badge badge-success badge-sm"
|
||||||
|
def permission_set_badge_class("admin"), do: "badge badge-error badge-sm"
|
||||||
|
def permission_set_badge_class(_), do: "badge badge-ghost badge-sm"
|
||||||
|
end
|
||||||
|
|
@ -21,6 +21,8 @@ defmodule MvWeb.RoleLive.Index do
|
||||||
|
|
||||||
require Ash.Query
|
require Ash.Query
|
||||||
|
|
||||||
|
import MvWeb.RoleLive.Helpers
|
||||||
|
|
||||||
on_mount {MvWeb.LiveHelpers, :ensure_user_role_loaded}
|
on_mount {MvWeb.LiveHelpers, :ensure_user_role_loaded}
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
|
|
@ -113,6 +115,7 @@ defmodule MvWeb.RoleLive.Index do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@spec load_roles(map() | nil) :: [Mv.Authorization.Role.t()]
|
||||||
defp load_roles(actor) do
|
defp load_roles(actor) do
|
||||||
opts = if actor, do: [actor: actor], else: []
|
opts = if actor, do: [actor: actor], else: []
|
||||||
|
|
||||||
|
|
@ -123,6 +126,7 @@ defmodule MvWeb.RoleLive.Index do
|
||||||
end
|
end
|
||||||
|
|
||||||
# Loads all user counts for roles in a single query to avoid N+1 queries
|
# Loads all user counts for roles in a single query to avoid N+1 queries
|
||||||
|
@spec load_user_counts([Mv.Authorization.Role.t()], map() | nil) :: %{Ecto.UUID.t() => non_neg_integer()}
|
||||||
defp load_user_counts(roles, actor) do
|
defp load_user_counts(roles, actor) do
|
||||||
role_ids = Enum.map(roles, & &1.id)
|
role_ids = Enum.map(roles, & &1.id)
|
||||||
|
|
||||||
|
|
@ -149,11 +153,13 @@ defmodule MvWeb.RoleLive.Index do
|
||||||
end
|
end
|
||||||
|
|
||||||
# Gets user count from preloaded assigns map
|
# Gets user count from preloaded assigns map
|
||||||
|
@spec get_user_count(Mv.Authorization.Role.t(), %{Ecto.UUID.t() => non_neg_integer()}) :: non_neg_integer()
|
||||||
defp get_user_count(role, user_counts) do
|
defp get_user_count(role, user_counts) do
|
||||||
Map.get(user_counts, role.id, 0)
|
Map.get(user_counts, role.id, 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Recalculates user count for a specific role (used before deletion)
|
# Recalculates user count for a specific role (used before deletion)
|
||||||
|
@spec recalculate_user_count(Mv.Authorization.Role.t(), map() | nil) :: non_neg_integer()
|
||||||
defp recalculate_user_count(role, actor) do
|
defp recalculate_user_count(role, actor) do
|
||||||
opts = [domain: Mv.Accounts]
|
opts = [domain: Mv.Accounts]
|
||||||
opts = if actor, do: Keyword.put(opts, :actor, actor), else: opts
|
opts = if actor, do: Keyword.put(opts, :actor, actor), else: opts
|
||||||
|
|
@ -164,16 +170,4 @@ defmodule MvWeb.RoleLive.Index do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp format_error(%Ash.Error.Invalid{} = error) do
|
|
||||||
Enum.map_join(error.errors, ", ", fn e -> e.message end)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp format_error(error) when is_binary(error), do: error
|
|
||||||
defp format_error(_error), do: gettext("An error occurred")
|
|
||||||
|
|
||||||
defp permission_set_badge_class("own_data"), do: "badge badge-neutral badge-sm"
|
|
||||||
defp permission_set_badge_class("read_only"), do: "badge badge-info badge-sm"
|
|
||||||
defp permission_set_badge_class("normal_user"), do: "badge badge-success badge-sm"
|
|
||||||
defp permission_set_badge_class("admin"), do: "badge badge-error badge-sm"
|
|
||||||
defp permission_set_badge_class(_), do: "badge badge-ghost badge-sm"
|
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@ defmodule MvWeb.RoleLive.Show do
|
||||||
|
|
||||||
require Ash.Query
|
require Ash.Query
|
||||||
|
|
||||||
|
import MvWeb.RoleLive.Helpers
|
||||||
|
|
||||||
on_mount {MvWeb.LiveHelpers, :ensure_user_role_loaded}
|
on_mount {MvWeb.LiveHelpers, :ensure_user_role_loaded}
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
|
|
@ -27,10 +29,10 @@ defmodule MvWeb.RoleLive.Show do
|
||||||
domain: Mv.Authorization,
|
domain: Mv.Authorization,
|
||||||
actor: socket.assigns[:current_user]
|
actor: socket.assigns[:current_user]
|
||||||
) do
|
) do
|
||||||
{:ok, role} ->
|
{:ok, role} ->
|
||||||
user_count = load_user_count(role, socket.assigns[:current_user])
|
user_count = load_user_count(role, socket.assigns[:current_user])
|
||||||
|
|
||||||
{:ok,
|
{:ok,
|
||||||
socket
|
socket
|
||||||
|> assign(:page_title, gettext("Show Role"))
|
|> assign(:page_title, gettext("Show Role"))
|
||||||
|> assign(:role, role)
|
|> assign(:role, role)
|
||||||
|
|
@ -50,6 +52,7 @@ defmodule MvWeb.RoleLive.Show do
|
||||||
end
|
end
|
||||||
rescue
|
rescue
|
||||||
e in [Ash.Error.Invalid] ->
|
e in [Ash.Error.Invalid] ->
|
||||||
|
# Handle exceptions that Ash.get might throw (e.g., policy violations)
|
||||||
case e do
|
case e do
|
||||||
%Ash.Error.Invalid{errors: [%Ash.Error.Query.NotFound{} | _]} ->
|
%Ash.Error.Invalid{errors: [%Ash.Error.Query.NotFound{} | _]} ->
|
||||||
{:ok,
|
{:ok,
|
||||||
|
|
@ -138,6 +141,7 @@ defmodule MvWeb.RoleLive.Show do
|
||||||
end
|
end
|
||||||
|
|
||||||
# Recalculates user count for a specific role (used before deletion)
|
# Recalculates user count for a specific role (used before deletion)
|
||||||
|
@spec recalculate_user_count(Mv.Authorization.Role.t(), map() | nil) :: non_neg_integer()
|
||||||
defp recalculate_user_count(role, actor) do
|
defp recalculate_user_count(role, actor) do
|
||||||
opts = [domain: Mv.Accounts]
|
opts = [domain: Mv.Accounts]
|
||||||
opts = if actor, do: Keyword.put(opts, :actor, actor), else: opts
|
opts = if actor, do: Keyword.put(opts, :actor, actor), else: opts
|
||||||
|
|
@ -149,6 +153,7 @@ defmodule MvWeb.RoleLive.Show do
|
||||||
end
|
end
|
||||||
|
|
||||||
# Loads user count for initial display (uses same logic as recalculate)
|
# Loads user count for initial display (uses same logic as recalculate)
|
||||||
|
@spec load_user_count(Mv.Authorization.Role.t(), map() | nil) :: non_neg_integer()
|
||||||
defp load_user_count(role, actor) do
|
defp load_user_count(role, actor) do
|
||||||
recalculate_user_count(role, actor)
|
recalculate_user_count(role, actor)
|
||||||
end
|
end
|
||||||
|
|
@ -209,16 +214,4 @@ defmodule MvWeb.RoleLive.Show do
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
||||||
defp format_error(%Ash.Error.Invalid{} = error) do
|
|
||||||
Enum.map_join(error.errors, ", ", fn e -> e.message end)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp format_error(error) when is_binary(error), do: error
|
|
||||||
defp format_error(_error), do: gettext("An error occurred")
|
|
||||||
|
|
||||||
defp permission_set_badge_class("own_data"), do: "badge badge-neutral badge-sm"
|
|
||||||
defp permission_set_badge_class("read_only"), do: "badge badge-info badge-sm"
|
|
||||||
defp permission_set_badge_class("normal_user"), do: "badge badge-success badge-sm"
|
|
||||||
defp permission_set_badge_class("admin"), do: "badge badge-error badge-sm"
|
|
||||||
defp permission_set_badge_class(_), do: "badge badge-ghost badge-sm"
|
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue