All checks were successful
continuous-integration/drone/push Build is passing
Complete refactoring of resources, database tables, code references, tests, and documentation for improved naming consistency.
139 lines
4.4 KiB
Elixir
139 lines
4.4 KiB
Elixir
defmodule MvWeb.CustomFieldLive.Form do
|
|
@moduledoc """
|
|
LiveView form for creating and editing custom fields (admin).
|
|
|
|
## Features
|
|
- Create new custom field definitions
|
|
- Edit existing custom fields
|
|
- Select value type from supported types
|
|
- Set immutable and required flags
|
|
- Real-time validation
|
|
|
|
## Form Fields
|
|
**Required:**
|
|
- name - Unique identifier (e.g., "phone_mobile", "emergency_contact")
|
|
- value_type - Data type (:string, :integer, :boolean, :date, :email)
|
|
|
|
**Optional:**
|
|
- description - Human-readable explanation
|
|
- immutable - If true, values cannot be changed after creation (default: false)
|
|
- required - If true, all members must have this custom field (default: false)
|
|
|
|
## Value Type Selection
|
|
- `:string` - Text data (unlimited length)
|
|
- `:integer` - Numeric data
|
|
- `:boolean` - True/false flags
|
|
- `:date` - Date values
|
|
- `:email` - Validated email addresses
|
|
|
|
## Events
|
|
- `validate` - Real-time form validation
|
|
- `save` - Submit form (create or update custom field)
|
|
|
|
## Security
|
|
Custom field management is restricted to admin users.
|
|
"""
|
|
use MvWeb, :live_view
|
|
|
|
@impl true
|
|
def render(assigns) do
|
|
~H"""
|
|
<Layouts.app flash={@flash} current_user={@current_user}>
|
|
<.header>
|
|
{@page_title}
|
|
<:subtitle>
|
|
{gettext("Use this form to manage custom_field records in your database.")}
|
|
</:subtitle>
|
|
</.header>
|
|
|
|
<.form for={@form} id="custom_field-form" phx-change="validate" phx-submit="save">
|
|
<.input field={@form[:name]} type="text" label={gettext("Name")} />
|
|
<.input
|
|
field={@form[:value_type]}
|
|
type="select"
|
|
label={gettext("Value type")}
|
|
options={
|
|
Ash.Resource.Info.attribute(Mv.Membership.CustomField, :value_type).constraints[:one_of]
|
|
}
|
|
/>
|
|
<.input field={@form[:description]} type="text" label={gettext("Description")} />
|
|
<.input field={@form[:immutable]} type="checkbox" label={gettext("Immutable")} />
|
|
<.input field={@form[:required]} type="checkbox" label={gettext("Required")} />
|
|
|
|
<.button phx-disable-with={gettext("Saving...")} variant="primary">
|
|
{gettext("Save Custom field")}
|
|
</.button>
|
|
<.button navigate={return_path(@return_to, @custom_field)}>{gettext("Cancel")}</.button>
|
|
</.form>
|
|
</Layouts.app>
|
|
"""
|
|
end
|
|
|
|
@impl true
|
|
def mount(params, _session, socket) do
|
|
custom_field =
|
|
case params["id"] do
|
|
nil -> nil
|
|
id -> Ash.get!(Mv.Membership.CustomField, id)
|
|
end
|
|
|
|
action = if is_nil(custom_field), do: "New", else: "Edit"
|
|
page_title = action <> " " <> "Custom field"
|
|
|
|
{:ok,
|
|
socket
|
|
|> assign(:return_to, return_to(params["return_to"]))
|
|
|> assign(custom_field: custom_field)
|
|
|> assign(:page_title, page_title)
|
|
|> assign_form()}
|
|
end
|
|
|
|
defp return_to("show"), do: "show"
|
|
defp return_to(_), do: "index"
|
|
|
|
@impl true
|
|
def handle_event("validate", %{"custom_field" => custom_field_params}, socket) do
|
|
{:noreply,
|
|
assign(socket, form: AshPhoenix.Form.validate(socket.assigns.form, custom_field_params))}
|
|
end
|
|
|
|
def handle_event("save", %{"custom_field" => custom_field_params}, socket) do
|
|
case AshPhoenix.Form.submit(socket.assigns.form, params: custom_field_params) do
|
|
{:ok, custom_field} ->
|
|
notify_parent({:saved, custom_field})
|
|
|
|
action =
|
|
case socket.assigns.form.source.type do
|
|
:create -> gettext("create")
|
|
:update -> gettext("update")
|
|
other -> to_string(other)
|
|
end
|
|
|
|
socket =
|
|
socket
|
|
|> put_flash(:info, gettext("Custom field %{action} successfully", action: action))
|
|
|> push_navigate(to: return_path(socket.assigns.return_to, custom_field))
|
|
|
|
{:noreply, socket}
|
|
|
|
{:error, form} ->
|
|
{:noreply, assign(socket, form: form)}
|
|
end
|
|
end
|
|
|
|
defp notify_parent(msg), do: send(self(), {__MODULE__, msg})
|
|
|
|
defp assign_form(%{assigns: %{custom_field: custom_field}} = socket) do
|
|
form =
|
|
if custom_field do
|
|
AshPhoenix.Form.for_update(custom_field, :update, as: "custom_field")
|
|
else
|
|
AshPhoenix.Form.for_create(Mv.Membership.CustomField, :create, as: "custom_field")
|
|
end
|
|
|
|
assign(socket, form: to_form(form))
|
|
end
|
|
|
|
defp return_path("index", _custom_field), do: ~p"/custom_fields"
|
|
defp return_path("show", custom_field), do: ~p"/custom_fields/#{custom_field.id}"
|
|
end
|