Packages
phoenix_kit
1.2.7
1.7.210
1.7.209
1.7.208
1.7.207
1.7.206
1.7.205
1.7.204
1.7.203
1.7.202
1.7.201
1.7.200
1.7.199
1.7.198
1.7.197
1.7.196
1.7.194
1.7.193
1.7.192
1.7.191
1.7.190
1.7.189
1.7.187
1.7.186
1.7.185
1.7.184
1.7.183
1.7.182
1.7.181
1.7.180
1.7.179
1.7.178
1.7.177
1.7.176
1.7.175
1.7.174
1.7.173
1.7.172
1.7.171
1.7.170
1.7.169
1.7.168
1.7.167
1.7.166
1.7.165
1.7.164
1.7.162
1.7.161
1.7.160
1.7.159
1.7.157
1.7.156
1.7.155
1.7.154
1.7.153
1.7.152
1.7.151
1.7.150
1.7.149
1.7.146
1.7.145
1.7.144
1.7.143
1.7.138
1.7.133
1.7.132
1.7.131
1.7.130
1.7.128
1.7.126
1.7.125
1.7.121
1.7.120
1.7.119
1.7.118
1.7.117
1.7.116
1.7.115
1.7.114
1.7.113
1.7.112
1.7.111
1.7.110
1.7.109
1.7.108
1.7.107
1.7.106
1.7.105
1.7.104
1.7.103
1.7.102
1.7.101
1.7.100
1.7.99
1.7.98
1.7.97
1.7.96
1.7.95
1.7.94
1.7.93
1.7.92
1.7.91
1.7.90
1.7.89
1.7.88
1.7.87
1.7.86
1.7.85
1.7.84
1.7.83
1.7.82
1.7.81
1.7.80
1.7.79
1.7.78
1.7.77
1.7.76
1.7.75
1.7.74
1.7.71
1.7.70
1.7.69
1.7.66
1.7.65
1.7.64
1.7.63
1.7.62
1.7.61
1.7.59
1.7.58
1.7.57
1.7.56
1.7.55
1.7.54
1.7.53
1.7.52
1.7.51
1.7.49
1.7.44
1.7.43
1.7.42
1.7.41
1.7.39
1.7.38
1.7.37
1.7.36
1.7.34
1.7.33
1.7.31
1.7.30
1.7.29
1.7.28
1.7.27
1.7.26
1.7.25
1.7.24
1.7.23
1.7.22
1.7.21
1.7.20
1.7.19
1.7.18
1.7.17
1.7.16
1.7.15
1.7.14
1.7.13
1.7.12
1.7.11
1.7.10
1.7.9
1.7.8
1.7.7
1.7.6
1.7.5
1.7.4
1.7.3
1.7.2
1.7.1
1.7.0
1.6.20
1.6.19
1.6.18
1.6.17
1.6.16
1.6.15
1.6.14
1.6.13
1.6.12
1.6.11
1.6.10
1.6.9
1.6.8
1.6.7
1.6.6
1.6.5
1.6.4
1.6.3
1.5.2
1.5.1
1.5.0
1.4.9
1.4.8
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.2
1.3.1
1.3.0
1.2.10
1.2.9
1.2.8
1.2.7
1.2.5
1.2.4
1.2.2
1.2.1
1.2.0
1.1.0
1.0.0
A foundation for building Elixir Phoenix apps — SaaS, social networks, ERP systems, marketplaces, and more
Current section
Files
Jump to
Current section
Files
lib/phoenix_kit_web/live/roles_live.ex
defmodule PhoenixKitWeb.Live.RolesLive do
use PhoenixKitWeb, :live_view
alias PhoenixKit.Admin.Events
alias PhoenixKit.Settings
alias PhoenixKit.Users.{Role, Roles}
alias PhoenixKit.Utils.Routes
def mount(_params, _session, socket) do
# Subscribe to role events for live updates
if connected?(socket) do
Events.subscribe_to_roles()
Events.subscribe_to_stats()
end
# Get current path for navigation
current_path = get_current_path()
# Load optimized role statistics once
role_stats = load_role_statistics()
# Get project title from settings
project_title = Settings.get_setting("project_title", "PhoenixKit")
socket =
socket
|> assign(:roles, [])
|> assign(:editing_role, nil)
|> assign(:show_form, false)
|> assign(:form_data, %{"name" => "", "description" => ""})
|> assign(:current_path, current_path)
|> assign(:page_title, "Roles")
|> assign(:role_stats, role_stats)
|> assign(:project_title, project_title)
|> load_roles()
{:ok, socket}
end
defp get_current_path do
# For RolesLive, always return roles path
Routes.path("/admin/roles")
end
def handle_event("show_create_form", _params, socket) do
socket =
socket
|> assign(:show_form, true)
|> assign(:editing_role, nil)
|> assign(:form_data, %{"name" => "", "description" => ""})
{:noreply, socket}
end
def handle_event("hide_form", _params, socket) do
socket =
socket
|> assign(:show_form, false)
|> assign(:editing_role, nil)
|> assign(:form_data, %{"name" => "", "description" => ""})
{:noreply, socket}
end
def handle_event("edit_role", %{"role_id" => role_id}, socket) do
role = Enum.find(socket.assigns.roles, &(&1.id == String.to_integer(role_id)))
if role && !role.is_system_role do
socket =
socket
|> assign(:show_form, true)
|> assign(:editing_role, role)
|> assign(:form_data, %{"name" => role.name, "description" => role.description || ""})
{:noreply, socket}
else
socket = put_flash(socket, :error, "System roles cannot be edited")
{:noreply, socket}
end
end
def handle_event("create_role", %{"role" => role_params}, socket) do
case Roles.create_role(role_params) do
{:ok, _role} ->
socket =
socket
|> put_flash(:info, "Role created successfully")
|> assign(:show_form, false)
|> assign(:form_data, %{"name" => "", "description" => ""})
|> load_roles()
{:noreply, socket}
{:error, changeset} ->
errors = extract_changeset_errors(changeset)
socket = put_flash(socket, :error, "Failed to create role: #{errors}")
{:noreply, socket}
end
end
def handle_event("update_role", %{"role" => role_params}, socket) do
editing_role = socket.assigns.editing_role
case Roles.update_role(editing_role, role_params) do
{:ok, _role} ->
socket =
socket
|> put_flash(:info, "Role updated successfully")
|> assign(:show_form, false)
|> assign(:editing_role, nil)
|> assign(:form_data, %{"name" => "", "description" => ""})
|> load_roles()
{:noreply, socket}
{:error, changeset} ->
errors = extract_changeset_errors(changeset)
socket = put_flash(socket, :error, "Failed to update role: #{errors}")
{:noreply, socket}
end
end
def handle_event("delete_role", %{"role_id" => role_id}, socket) do
role = Enum.find(socket.assigns.roles, &(&1.id == String.to_integer(role_id)))
if role && !role.is_system_role do
case Roles.delete_role(role) do
{:ok, _role} ->
socket =
socket
|> put_flash(:info, "Role deleted successfully")
|> load_roles()
{:noreply, socket}
{:error, :role_in_use} ->
socket =
put_flash(socket, :error, "Cannot delete role: it is currently assigned to users")
{:noreply, socket}
{:error, _changeset} ->
socket = put_flash(socket, :error, "Failed to delete role")
{:noreply, socket}
end
else
socket = put_flash(socket, :error, "System roles cannot be deleted")
{:noreply, socket}
end
end
defp load_roles(socket) do
roles = Roles.list_roles()
assign(socket, :roles, roles)
end
defp extract_changeset_errors(changeset) do
Enum.map_join(changeset.errors, ", ", fn {field, {message, _}} -> "#{field} #{message}" end)
end
defp role_badge_class(%Role{is_system_role: true, name: "Owner"}), do: "badge-error"
defp role_badge_class(%Role{is_system_role: true, name: "Admin"}), do: "badge-warning"
defp role_badge_class(%Role{is_system_role: true, name: "User"}), do: "badge-info"
defp role_badge_class(%Role{is_system_role: true}), do: "badge-accent"
defp role_badge_class(%Role{is_system_role: false}), do: "badge-primary"
# Load role statistics using optimized extended stats
defp load_role_statistics do
stats = Roles.get_extended_stats()
# Create lookup map for fast role count access
%{
"Owner" => stats.owner_count,
"Admin" => stats.admin_count,
"User" => stats.user_count
}
end
# Optimized function using cached statistics
defp users_count_for_role(role, role_stats) do
# Use cached stats for system roles, fallback to DB query for custom roles
case role_stats[role.name] do
nil ->
# Custom role - query database (only for non-system roles)
Roles.count_users_with_role(role.name)
count ->
# System role - use cached count
count
end
end
## Live Event Handlers
def handle_info({:role_created, _role}, socket) do
socket =
socket
|> load_roles()
|> assign(:role_stats, load_role_statistics())
{:noreply, socket}
end
def handle_info({:role_updated, _role}, socket) do
socket =
socket
|> load_roles()
|> assign(:role_stats, load_role_statistics())
{:noreply, socket}
end
def handle_info({:role_deleted, _role}, socket) do
socket =
socket
|> load_roles()
|> assign(:role_stats, load_role_statistics())
{:noreply, socket}
end
def handle_info({:stats_updated, _stats}, socket) do
socket =
socket
|> assign(:role_stats, load_role_statistics())
{:noreply, socket}
end
end