Packages

phoenix_kit

1.7.87
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
phoenix_kit lib phoenix_kit_web live settings users.ex
Raw

lib/phoenix_kit_web/live/settings/users.ex

defmodule PhoenixKitWeb.Live.Settings.Users do
@moduledoc """
User-related settings management LiveView for PhoenixKit.
Consolidates user configuration including:
- Registration settings
- New user defaults (role and status)
- Custom user fields management
"""
use PhoenixKitWeb, :live_view
use Gettext, backend: PhoenixKitWeb.Gettext
alias PhoenixKit.Settings
alias PhoenixKit.Users.CustomFields
alias PhoenixKit.Users.CustomFields.Events, as: CustomFieldsEvents
def mount(_params, _session, socket) do
# Set locale for LiveView process
# Load current settings
current_settings = Settings.list_all_settings()
defaults = Settings.get_defaults()
setting_options = Settings.get_setting_options()
# Merge defaults with current settings
merged_settings = Map.merge(defaults, current_settings)
# Load custom fields
field_definitions = CustomFields.list_field_definitions()
# Create form changeset
changeset = Settings.change_settings(merged_settings)
socket =
socket
|> assign(:page_title, "User Settings")
|> assign(:settings, merged_settings)
|> assign(:saved_settings, merged_settings)
|> assign(:setting_options, setting_options)
|> assign(:changeset, changeset)
|> assign(:saving, false)
|> assign(
:project_title,
merged_settings["project_title"] || PhoenixKit.Config.get(:project_title, "PhoenixKit")
)
|> assign(:field_definitions, field_definitions)
|> assign(:editing_field, nil)
|> assign(:show_field_form, false)
# Options management for select/radio/checkbox fields
|> assign(:field_form_type, "text")
|> assign(:field_form_options, [])
|> assign(:new_option_value, "")
{:ok, socket}
end
def handle_params(_params, _url, socket) do
{:noreply, socket}
end
def handle_event("validate_settings", %{"settings" => settings_params}, socket) do
changeset = Settings.validate_settings(settings_params)
socket =
socket
|> assign(:settings, settings_params)
|> assign(:changeset, changeset)
{:noreply, socket}
end
def handle_event("save_settings", %{"settings" => settings_params}, socket) do
socket = assign(socket, :saving, true)
case Settings.update_settings(settings_params) do
{:ok, updated_settings} ->
changeset = Settings.change_settings(updated_settings)
socket =
socket
|> assign(:settings, updated_settings)
|> assign(:saved_settings, updated_settings)
|> assign(:changeset, changeset)
|> assign(:saving, false)
|> put_flash(:info, "User settings updated successfully")
{:noreply, socket}
{:error, errors} ->
error_msg = format_error_message(errors)
socket =
socket
|> assign(:saving, false)
|> put_flash(:error, error_msg)
{:noreply, socket}
end
end
# Custom Fields Events
def handle_event("show_add_field_form", _params, socket) do
socket =
socket
|> assign(:show_field_form, true)
|> assign(:editing_field, nil)
|> assign(:field_form_type, "text")
|> assign(:field_form_options, [])
|> assign(:new_option_value, "")
{:noreply, socket}
end
def handle_event("show_edit_field_form", %{"key" => key}, socket) do
field = CustomFields.get_field_definition(key)
socket =
socket
|> assign(:show_field_form, true)
|> assign(:editing_field, field)
|> assign(:field_form_type, (field && field["type"]) || "text")
|> assign(:field_form_options, (field && field["options"]) || [])
|> assign(:new_option_value, "")
{:noreply, socket}
end
def handle_event("hide_field_form", _params, socket) do
socket =
socket
|> assign(:show_field_form, false)
|> assign(:editing_field, nil)
|> assign(:field_form_type, "text")
|> assign(:field_form_options, [])
|> assign(:new_option_value, "")
{:noreply, socket}
end
def handle_event("save_field", %{"field" => field_params}, socket) do
# Include options from socket assigns for select/radio/checkbox types
field_params =
if socket.assigns.field_form_type in ~w(select radio checkbox) do
Map.put(field_params, "options", socket.assigns.field_form_options)
else
field_params
end
result =
if socket.assigns.editing_field do
# Update existing field
key = socket.assigns.editing_field["key"]
CustomFields.update_field_definition(key, field_params)
else
# Add new field
CustomFields.add_field_definition(field_params)
end
case result do
{:ok, _setting} ->
field_definitions = CustomFields.list_field_definitions()
socket =
socket
|> assign(:field_definitions, field_definitions)
|> assign(:show_field_form, false)
|> assign(:editing_field, nil)
|> assign(:field_form_type, "text")
|> assign(:field_form_options, [])
|> assign(:new_option_value, "")
|> put_flash(:info, "Custom field saved successfully")
{:noreply, socket}
{:error, message} when is_binary(message) ->
socket = put_flash(socket, :error, message)
{:noreply, socket}
{:error, changeset} ->
# Handle Ecto changeset errors with detailed messages
error_msg =
case changeset do
%Ecto.Changeset{} -> format_error_message(changeset)
_ -> "Failed to save custom field"
end
socket = put_flash(socket, :error, error_msg)
{:noreply, socket}
end
end
# Options management for select/radio/checkbox fields
def handle_event("field_type_changed", %{"field" => %{"type" => type}}, socket) do
{:noreply, assign(socket, :field_form_type, type)}
end
def handle_event("update_new_option", %{"key" => "Enter", "value" => value}, socket) do
# Enter key pressed - add the option
trimmed = String.trim(value || "")
if trimmed != "" and trimmed not in socket.assigns.field_form_options do
socket =
socket
|> assign(:field_form_options, socket.assigns.field_form_options ++ [trimmed])
|> assign(:new_option_value, "")
{:noreply, socket}
else
{:noreply, socket}
end
end
def handle_event("update_new_option", %{"value" => value}, socket) do
{:noreply, assign(socket, :new_option_value, value)}
end
def handle_event("add_field_option", _params, socket) do
value = socket.assigns.new_option_value
trimmed = String.trim(value || "")
if trimmed != "" and trimmed not in socket.assigns.field_form_options do
socket =
socket
|> assign(:field_form_options, socket.assigns.field_form_options ++ [trimmed])
|> assign(:new_option_value, "")
{:noreply, socket}
else
{:noreply, socket}
end
end
def handle_event("remove_field_option", %{"index" => index_str}, socket) do
index = String.to_integer(index_str)
options = List.delete_at(socket.assigns.field_form_options, index)
{:noreply, assign(socket, :field_form_options, options)}
end
def handle_event("delete_field", %{"key" => key}, socket) do
case CustomFields.delete_field_definition(key) do
{:ok, _setting} ->
# Broadcast field deletion to other LiveViews (e.g., users table)
CustomFieldsEvents.broadcast_field_deleted(key)
field_definitions = CustomFields.list_field_definitions()
socket =
socket
|> assign(:field_definitions, field_definitions)
|> put_flash(:info, "Custom field deleted successfully")
{:noreply, socket}
{:error, _changeset} ->
socket = put_flash(socket, :error, "Failed to delete custom field")
{:noreply, socket}
end
end
def handle_event("toggle_field_enabled", %{"key" => key}, socket) do
field = CustomFields.get_field_definition(key)
if field do
new_enabled = !field["enabled"]
case CustomFields.update_field_definition(key, %{"enabled" => new_enabled}) do
{:ok, _setting} ->
field_definitions = CustomFields.list_field_definitions()
socket =
socket
|> assign(:field_definitions, field_definitions)
|> put_flash(
:info,
if(new_enabled,
do: "Field '#{field["label"]}' enabled",
else: "Field '#{field["label"]}' disabled"
)
)
{:noreply, socket}
{:error, _changeset} ->
socket = put_flash(socket, :error, "Failed to update field")
{:noreply, socket}
end
else
{:noreply, put_flash(socket, :error, "Field not found")}
end
end
# Helper functions
defp format_error_message(%Ecto.Changeset{} = changeset) do
changeset
|> Ecto.Changeset.traverse_errors(fn {msg, opts} ->
Enum.reduce(opts, msg, fn {key, value}, acc ->
String.replace(acc, "%{#{key}}", to_string(value))
end)
end)
|> Map.values()
|> List.flatten()
|> Enum.join(", ")
end
def get_option_label(value, options) do
Settings.get_option_label(value, options)
end
end