Merge pull request 'Refactor admin UI structure' (#244) from refactor-admin-settings-ui into main
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #244 Reviewed-by: carla <carla@noreply.git.local-it.org>
This commit is contained in:
commit
a68a15be6a
15 changed files with 727 additions and 568 deletions
2
Justfile
2
Justfile
|
|
@ -90,7 +90,7 @@ clean:
|
|||
remove-gettext-conflicts:
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
find priv/gettext -type f -exec sed -i '/^<<<<<<</d; /^=======$/d; /^>>>>>>>/d; /^%%%%%%%/d; /^++++++/d; s/^+//' {} \;
|
||||
find priv/gettext -type f -exec sed -i '/^<<<<<<</d; /^=======$/d; /^>>>>>>>/d; /^%%%%%%%/d; /^++++++/d; s/^+//; s/^-//' {} \;
|
||||
|
||||
# Production environment commands
|
||||
# ================================
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ defmodule MvWeb.Layouts.Navbar do
|
|||
<a class="btn btn-ghost text-xl">{@club_name}</a>
|
||||
<ul class="menu menu-horizontal bg-base-200">
|
||||
<li><.link navigate="/members">{gettext("Members")}</.link></li>
|
||||
<li><.link navigate="/custom_fields">{gettext("Custom Fields")}</.link></li>
|
||||
<li><.link navigate="/settings">{gettext("Settings")}</.link></li>
|
||||
<li><.link navigate="/users">{gettext("Users")}</.link></li>
|
||||
<li>
|
||||
<details>
|
||||
|
|
|
|||
|
|
@ -1,142 +0,0 @@
|
|||
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)
|
||||
- show_in_overview - If true, this custom field will be displayed in the member overview table (default: true)
|
||||
|
||||
## 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")} />
|
||||
<.input field={@form[:show_in_overview]} type="checkbox" label={gettext("Show in overview")} />
|
||||
|
||||
<.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
|
||||
127
lib/mv_web/live/custom_field_live/form_component.ex
Normal file
127
lib/mv_web/live/custom_field_live/form_component.ex
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
defmodule MvWeb.CustomFieldLive.FormComponent do
|
||||
@moduledoc """
|
||||
LiveComponent form for creating and editing custom fields (embedded in settings).
|
||||
|
||||
## Features
|
||||
- Create new custom field definitions
|
||||
- Edit existing custom fields
|
||||
- Select value type from supported types
|
||||
- Set immutable and required flags
|
||||
- Real-time validation
|
||||
|
||||
## Props
|
||||
- `custom_field` - The custom field to edit (nil for new)
|
||||
- `on_save` - Callback function to call when form is saved
|
||||
- `on_cancel` - Callback function to call when form is cancelled
|
||||
"""
|
||||
use MvWeb, :live_component
|
||||
|
||||
@impl true
|
||||
def render(assigns) do
|
||||
~H"""
|
||||
<div id={@id} class="mb-8 border shadow-xl card border-base-300">
|
||||
<div class="card-body">
|
||||
<div class="flex items-center gap-4 mb-4">
|
||||
<.button
|
||||
type="button"
|
||||
phx-click="cancel"
|
||||
phx-target={@myself}
|
||||
aria-label={gettext("Back to custom field overview")}
|
||||
>
|
||||
<.icon name="hero-arrow-left" class="w-4 h-4" />
|
||||
</.button>
|
||||
<h3 class="card-title">
|
||||
{if @custom_field, do: gettext("Edit Custom Field"), else: gettext("New Custom Field")}
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<.form
|
||||
for={@form}
|
||||
id={@id <> "-form"}
|
||||
phx-change="validate"
|
||||
phx-submit="save"
|
||||
phx-target={@myself}
|
||||
>
|
||||
<.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")} />
|
||||
<.input
|
||||
field={@form[:show_in_overview]}
|
||||
type="checkbox"
|
||||
label={gettext("Show in overview")}
|
||||
/>
|
||||
|
||||
<div class="justify-end mt-4 card-actions">
|
||||
<.button type="button" phx-click="cancel" phx-target={@myself}>
|
||||
{gettext("Cancel")}
|
||||
</.button>
|
||||
<.button phx-disable-with={gettext("Saving...")} variant="primary">
|
||||
{gettext("Save Custom field")}
|
||||
</.button>
|
||||
</div>
|
||||
</.form>
|
||||
</div>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
||||
@impl true
|
||||
def update(assigns, socket) do
|
||||
{:ok,
|
||||
socket
|
||||
|> assign(assigns)
|
||||
|> assign_form()}
|
||||
end
|
||||
|
||||
@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
|
||||
|
||||
@impl true
|
||||
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} ->
|
||||
action =
|
||||
case socket.assigns.form.source.type do
|
||||
:create -> gettext("create")
|
||||
:update -> gettext("update")
|
||||
other -> to_string(other)
|
||||
end
|
||||
|
||||
socket.assigns.on_save.(custom_field, action)
|
||||
{:noreply, socket}
|
||||
|
||||
{:error, form} ->
|
||||
{:noreply, assign(socket, form: form)}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event("cancel", _params, socket) do
|
||||
socket.assigns.on_cancel.()
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
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
|
||||
end
|
||||
|
|
@ -1,199 +0,0 @@
|
|||
defmodule MvWeb.CustomFieldLive.Index do
|
||||
@moduledoc """
|
||||
LiveView for managing custom field definitions (admin).
|
||||
|
||||
## Features
|
||||
- List all custom fields
|
||||
- Display type information (name, value type, description)
|
||||
- Show immutable and required flags
|
||||
- Create new custom fields
|
||||
- Edit existing custom fields
|
||||
- Delete custom fields with confirmation (cascades to all custom field values)
|
||||
|
||||
## Displayed Information
|
||||
- Name: Unique identifier for the custom field
|
||||
- Value type: Data type constraint (string, integer, boolean, date, email)
|
||||
- Description: Human-readable explanation
|
||||
- Immutable: Whether custom field values can be changed after creation
|
||||
- Required: Whether all members must have this custom field (future feature)
|
||||
|
||||
## Events
|
||||
- `prepare_delete` - Opens deletion confirmation modal with member count
|
||||
- `confirm_delete` - Executes deletion after slug verification
|
||||
- `cancel_delete` - Cancels deletion and closes modal
|
||||
- `update_slug_confirmation` - Updates slug input state
|
||||
|
||||
## Security
|
||||
Custom field management is restricted to admin users.
|
||||
Deletion requires entering the custom field's slug to prevent accidental deletions.
|
||||
"""
|
||||
use MvWeb, :live_view
|
||||
|
||||
@impl true
|
||||
def render(assigns) do
|
||||
~H"""
|
||||
<Layouts.app flash={@flash} current_user={@current_user}>
|
||||
<.header>
|
||||
Listing Custom fields
|
||||
<:actions>
|
||||
<.button variant="primary" navigate={~p"/custom_fields/new"}>
|
||||
<.icon name="hero-plus" /> New Custom field
|
||||
</.button>
|
||||
</:actions>
|
||||
</.header>
|
||||
|
||||
<.table
|
||||
id="custom_fields"
|
||||
rows={@streams.custom_fields}
|
||||
row_click={fn {_id, custom_field} -> JS.navigate(~p"/custom_fields/#{custom_field}") end}
|
||||
>
|
||||
<:col :let={{_id, custom_field}} label="Name">{custom_field.name}</:col>
|
||||
|
||||
<:col :let={{_id, custom_field}} label="Description">{custom_field.description}</:col>
|
||||
|
||||
<:action :let={{_id, custom_field}}>
|
||||
<div class="sr-only">
|
||||
<.link navigate={~p"/custom_fields/#{custom_field}"}>Show</.link>
|
||||
</div>
|
||||
|
||||
<.link navigate={~p"/custom_fields/#{custom_field}/edit"}>Edit</.link>
|
||||
</:action>
|
||||
|
||||
<:action :let={{_id, custom_field}}>
|
||||
<.link phx-click={JS.push("prepare_delete", value: %{id: custom_field.id})}>
|
||||
Delete
|
||||
</.link>
|
||||
</:action>
|
||||
</.table>
|
||||
|
||||
<%!-- Delete Confirmation Modal --%>
|
||||
<dialog :if={@show_delete_modal} id="delete-custom-field-modal" class="modal modal-open">
|
||||
<div class="modal-box">
|
||||
<h3 class="font-bold text-lg">{gettext("Delete Custom Field")}</h3>
|
||||
|
||||
<div class="py-4 space-y-4">
|
||||
<div class="alert alert-warning">
|
||||
<.icon name="hero-exclamation-triangle" class="h-5 w-5" />
|
||||
<div>
|
||||
<p class="font-semibold">
|
||||
{ngettext(
|
||||
"%{count} member has a value assigned for this custom field.",
|
||||
"%{count} members have values assigned for this custom field.",
|
||||
@custom_field_to_delete.assigned_members_count,
|
||||
count: @custom_field_to_delete.assigned_members_count
|
||||
)}
|
||||
</p>
|
||||
<p class="text-sm mt-2">
|
||||
{gettext(
|
||||
"All custom field values will be permanently deleted when you delete this custom field."
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="slug-confirmation" class="label">
|
||||
<span class="label-text">
|
||||
{gettext("To confirm deletion, please enter this text:")}
|
||||
</span>
|
||||
</label>
|
||||
<div class="font-mono font-bold text-lg mb-2 p-2 bg-base-200 rounded break-all">
|
||||
{@custom_field_to_delete.slug}
|
||||
</div>
|
||||
<form phx-change="update_slug_confirmation">
|
||||
<input
|
||||
id="slug-confirmation"
|
||||
name="slug"
|
||||
type="text"
|
||||
value={@slug_confirmation}
|
||||
placeholder={gettext("Enter the text above to confirm")}
|
||||
autocomplete="off"
|
||||
phx-mounted={JS.focus()}
|
||||
class="input input-bordered w-full"
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-action">
|
||||
<button phx-click="cancel_delete" class="btn">
|
||||
{gettext("Cancel")}
|
||||
</button>
|
||||
<button
|
||||
phx-click="confirm_delete"
|
||||
class="btn btn-error"
|
||||
disabled={@slug_confirmation != @custom_field_to_delete.slug}
|
||||
>
|
||||
{gettext("Delete Custom Field and All Values")}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</dialog>
|
||||
</Layouts.app>
|
||||
"""
|
||||
end
|
||||
|
||||
@impl true
|
||||
def mount(_params, _session, socket) do
|
||||
{:ok,
|
||||
socket
|
||||
|> assign(:page_title, "Listing Custom fields")
|
||||
|> assign(:show_delete_modal, false)
|
||||
|> assign(:custom_field_to_delete, nil)
|
||||
|> assign(:slug_confirmation, "")
|
||||
|> stream(:custom_fields, Ash.read!(Mv.Membership.CustomField))}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event("prepare_delete", %{"id" => id}, socket) do
|
||||
custom_field = Ash.get!(Mv.Membership.CustomField, id, load: [:assigned_members_count])
|
||||
|
||||
{:noreply,
|
||||
socket
|
||||
|> assign(:custom_field_to_delete, custom_field)
|
||||
|> assign(:show_delete_modal, true)
|
||||
|> assign(:slug_confirmation, "")}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event("update_slug_confirmation", %{"slug" => slug}, socket) do
|
||||
{:noreply, assign(socket, :slug_confirmation, slug)}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event("confirm_delete", _params, socket) do
|
||||
custom_field = socket.assigns.custom_field_to_delete
|
||||
|
||||
if socket.assigns.slug_confirmation == custom_field.slug do
|
||||
# Delete the custom field (CASCADE will handle custom field values)
|
||||
case Ash.destroy(custom_field) do
|
||||
:ok ->
|
||||
{:noreply,
|
||||
socket
|
||||
|> put_flash(:info, "Custom field deleted successfully")
|
||||
|> assign(:show_delete_modal, false)
|
||||
|> assign(:custom_field_to_delete, nil)
|
||||
|> assign(:slug_confirmation, "")
|
||||
|> stream_delete(:custom_fields, custom_field)}
|
||||
|
||||
{:error, error} ->
|
||||
{:noreply,
|
||||
socket
|
||||
|> put_flash(:error, "Failed to delete custom field: #{inspect(error)}")}
|
||||
end
|
||||
else
|
||||
{:noreply,
|
||||
socket
|
||||
|> put_flash(:error, "Slug does not match. Deletion cancelled.")}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event("cancel_delete", _params, socket) do
|
||||
{:noreply,
|
||||
socket
|
||||
|> assign(:show_delete_modal, false)
|
||||
|> assign(:custom_field_to_delete, nil)
|
||||
|> assign(:slug_confirmation, "")}
|
||||
end
|
||||
end
|
||||
261
lib/mv_web/live/custom_field_live/index_component.ex
Normal file
261
lib/mv_web/live/custom_field_live/index_component.ex
Normal file
|
|
@ -0,0 +1,261 @@
|
|||
defmodule MvWeb.CustomFieldLive.IndexComponent do
|
||||
@moduledoc """
|
||||
LiveComponent for managing custom field definitions (embedded in settings).
|
||||
|
||||
## Features
|
||||
- List all custom fields
|
||||
- Display type information (name, value type, description)
|
||||
- Show immutable and required flags
|
||||
- Create new custom fields
|
||||
- Edit existing custom fields
|
||||
- Delete custom fields with confirmation (cascades to all custom field values)
|
||||
"""
|
||||
use MvWeb, :live_component
|
||||
|
||||
@impl true
|
||||
def render(assigns) do
|
||||
~H"""
|
||||
<div id={@id}>
|
||||
<.header>
|
||||
{gettext("Custom Fields")}
|
||||
<:subtitle>
|
||||
{gettext("These will appear in addition to other data when adding new members.")}
|
||||
</:subtitle>
|
||||
<:actions>
|
||||
<.button variant="primary" phx-click="new_custom_field" phx-target={@myself}>
|
||||
<.icon name="hero-plus" /> {gettext("New Custom field")}
|
||||
</.button>
|
||||
</:actions>
|
||||
</.header>
|
||||
|
||||
<%!-- Show form when creating or editing --%>
|
||||
<div :if={@show_form} class="mb-8">
|
||||
<.live_component
|
||||
module={MvWeb.CustomFieldLive.FormComponent}
|
||||
id={@form_id}
|
||||
custom_field={@editing_custom_field}
|
||||
on_save={
|
||||
fn custom_field, action -> send(self(), {:custom_field_saved, custom_field, action}) end
|
||||
}
|
||||
on_cancel={fn -> send_update(__MODULE__, id: @id, show_form: false) end}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<%!-- Hide table when form is visible --%>
|
||||
<.table
|
||||
:if={!@show_form}
|
||||
id="custom_fields"
|
||||
rows={@streams.custom_fields}
|
||||
row_click={
|
||||
fn {_id, custom_field} ->
|
||||
JS.push("edit_custom_field", value: %{id: custom_field.id}, target: @myself)
|
||||
end
|
||||
}
|
||||
>
|
||||
<:col :let={{_id, custom_field}} label={gettext("Name")}>{custom_field.name}</:col>
|
||||
|
||||
<:col :let={{_id, custom_field}} label={gettext("Value Type")}>
|
||||
{custom_field.value_type}
|
||||
</:col>
|
||||
|
||||
<:col :let={{_id, custom_field}} label={gettext("Description")}>
|
||||
{custom_field.description}
|
||||
</:col>
|
||||
|
||||
<:col :let={{_id, custom_field}} label={gettext("Show in Overview")}>
|
||||
<span :if={custom_field.show_in_overview} class="badge badge-success">
|
||||
{gettext("Yes")}
|
||||
</span>
|
||||
<span :if={!custom_field.show_in_overview} class="badge badge-ghost">
|
||||
{gettext("No")}
|
||||
</span>
|
||||
</:col>
|
||||
|
||||
<:action :let={{_id, custom_field}}>
|
||||
<.link phx-click={
|
||||
JS.push("edit_custom_field", value: %{id: custom_field.id}, target: @myself)
|
||||
}>
|
||||
{gettext("Edit")}
|
||||
</.link>
|
||||
</:action>
|
||||
|
||||
<:action :let={{_id, custom_field}}>
|
||||
<.link phx-click={JS.push("prepare_delete", value: %{id: custom_field.id}, target: @myself)}>
|
||||
{gettext("Delete")}
|
||||
</.link>
|
||||
</:action>
|
||||
</.table>
|
||||
|
||||
<%!-- Delete Confirmation Modal --%>
|
||||
<dialog :if={@show_delete_modal} id="delete-custom-field-modal" class="modal modal-open">
|
||||
<div class="modal-box">
|
||||
<h3 class="text-lg font-bold">{gettext("Delete Custom Field")}</h3>
|
||||
|
||||
<div class="py-4 space-y-4">
|
||||
<div class="alert alert-warning">
|
||||
<.icon name="hero-exclamation-triangle" class="w-5 h-5" />
|
||||
<div>
|
||||
<p class="font-semibold">
|
||||
{ngettext(
|
||||
"%{count} member has a value assigned for this custom field.",
|
||||
"%{count} members have values assigned for this custom field.",
|
||||
@custom_field_to_delete.assigned_members_count,
|
||||
count: @custom_field_to_delete.assigned_members_count
|
||||
)}
|
||||
</p>
|
||||
<p class="mt-2 text-sm">
|
||||
{gettext(
|
||||
"All custom field values will be permanently deleted when you delete this custom field."
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="slug-confirmation" class="label">
|
||||
<span class="label-text">
|
||||
{gettext("To confirm deletion, please enter this text:")}
|
||||
</span>
|
||||
</label>
|
||||
<div class="p-2 mb-2 font-mono text-lg font-bold break-all rounded bg-base-200">
|
||||
{@custom_field_to_delete.slug}
|
||||
</div>
|
||||
<form phx-change="update_slug_confirmation" phx-target={@myself}>
|
||||
<input
|
||||
id="slug-confirmation"
|
||||
name="slug"
|
||||
type="text"
|
||||
value={@slug_confirmation}
|
||||
placeholder={gettext("Enter the text above to confirm")}
|
||||
autocomplete="off"
|
||||
phx-mounted={JS.focus()}
|
||||
class="w-full input input-bordered"
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-action">
|
||||
<button phx-click="cancel_delete" phx-target={@myself} class="btn">
|
||||
{gettext("Cancel")}
|
||||
</button>
|
||||
<button
|
||||
phx-click="confirm_delete"
|
||||
phx-target={@myself}
|
||||
class="btn btn-error"
|
||||
disabled={@slug_confirmation != @custom_field_to_delete.slug}
|
||||
>
|
||||
{gettext("Delete Custom Field and All Values")}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</dialog>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
||||
@impl true
|
||||
def update(assigns, socket) do
|
||||
# If show_form is explicitly provided in assigns, reset editing state
|
||||
socket =
|
||||
if Map.has_key?(assigns, :show_form) and assigns.show_form == false do
|
||||
socket
|
||||
|> assign(:editing_custom_field, nil)
|
||||
|> assign(:form_id, "custom-field-form-new")
|
||||
else
|
||||
socket
|
||||
end
|
||||
|
||||
{:ok,
|
||||
socket
|
||||
|> assign(assigns)
|
||||
|> assign_new(:show_form, fn -> false end)
|
||||
|> assign_new(:form_id, fn -> "custom-field-form-new" end)
|
||||
|> assign_new(:editing_custom_field, fn -> nil end)
|
||||
|> assign_new(:show_delete_modal, fn -> false end)
|
||||
|> assign_new(:custom_field_to_delete, fn -> nil end)
|
||||
|> assign_new(:slug_confirmation, fn -> "" end)
|
||||
|> stream(:custom_fields, Ash.read!(Mv.Membership.CustomField), reset: true)}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event("new_custom_field", _params, socket) do
|
||||
{:noreply,
|
||||
socket
|
||||
|> assign(:show_form, true)
|
||||
|> assign(:editing_custom_field, nil)
|
||||
|> assign(:form_id, "custom-field-form-new")}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event("edit_custom_field", %{"id" => id}, socket) do
|
||||
custom_field = Ash.get!(Mv.Membership.CustomField, id)
|
||||
|
||||
{:noreply,
|
||||
socket
|
||||
|> assign(:show_form, true)
|
||||
|> assign(:editing_custom_field, custom_field)
|
||||
|> assign(:form_id, "custom-field-form-#{id}")}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event("prepare_delete", %{"id" => id}, socket) do
|
||||
custom_field = Ash.get!(Mv.Membership.CustomField, id, load: [:assigned_members_count])
|
||||
|
||||
{:noreply,
|
||||
socket
|
||||
|> assign(:custom_field_to_delete, custom_field)
|
||||
|> assign(:show_delete_modal, true)
|
||||
|> assign(:slug_confirmation, "")}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event("update_slug_confirmation", %{"slug" => slug}, socket) do
|
||||
{:noreply, assign(socket, :slug_confirmation, slug)}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event("confirm_delete", _params, socket) do
|
||||
custom_field = socket.assigns.custom_field_to_delete
|
||||
|
||||
if socket.assigns.slug_confirmation == custom_field.slug do
|
||||
case Ash.destroy(custom_field) do
|
||||
:ok ->
|
||||
send(self(), {:custom_field_deleted, custom_field})
|
||||
|
||||
{:noreply,
|
||||
socket
|
||||
|> assign(:show_delete_modal, false)
|
||||
|> assign(:custom_field_to_delete, nil)
|
||||
|> assign(:slug_confirmation, "")
|
||||
|> stream_delete(:custom_fields, custom_field)}
|
||||
|
||||
{:error, error} ->
|
||||
send(self(), {:custom_field_delete_error, error})
|
||||
|
||||
{:noreply,
|
||||
socket
|
||||
|> assign(:show_delete_modal, false)
|
||||
|> assign(:custom_field_to_delete, nil)
|
||||
|> assign(:slug_confirmation, "")}
|
||||
end
|
||||
else
|
||||
send(self(), :custom_field_slug_mismatch)
|
||||
|
||||
{:noreply,
|
||||
socket
|
||||
|> assign(:show_delete_modal, false)
|
||||
|> assign(:custom_field_to_delete, nil)
|
||||
|> assign(:slug_confirmation, "")}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event("cancel_delete", _params, socket) do
|
||||
{:noreply,
|
||||
socket
|
||||
|> assign(:show_delete_modal, false)
|
||||
|> assign(:custom_field_to_delete, nil)
|
||||
|> assign(:slug_confirmation, "")}
|
||||
end
|
||||
end
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
defmodule MvWeb.CustomFieldLive.Show do
|
||||
@moduledoc """
|
||||
LiveView for displaying a single custom field's details (admin).
|
||||
|
||||
## Features
|
||||
- Display custom field definition
|
||||
- Show all attributes (name, value type, description, flags)
|
||||
- Navigate to edit form
|
||||
- Return to custom field list
|
||||
|
||||
## Displayed Information
|
||||
- ID: Internal UUID identifier
|
||||
- Slug: URL-friendly identifier (auto-generated, immutable)
|
||||
- Name: Unique identifier
|
||||
- Value type: Data type constraint
|
||||
- Description: Optional explanation
|
||||
- Immutable flag: Whether values can be changed
|
||||
- Required flag: Whether all members need this custom field
|
||||
|
||||
## Navigation
|
||||
- Back to custom field list
|
||||
- Edit custom field
|
||||
|
||||
## Security
|
||||
Custom field details are restricted to admin users.
|
||||
"""
|
||||
use MvWeb, :live_view
|
||||
|
||||
@impl true
|
||||
def render(assigns) do
|
||||
~H"""
|
||||
<Layouts.app flash={@flash} current_user={@current_user}>
|
||||
<.header>
|
||||
Custom field {@custom_field.slug}
|
||||
<:subtitle>This is a custom_field record from your database.</:subtitle>
|
||||
|
||||
<:actions>
|
||||
<.button navigate={~p"/custom_fields"}>
|
||||
<.icon name="hero-arrow-left" />
|
||||
</.button>
|
||||
<.button
|
||||
variant="primary"
|
||||
navigate={~p"/custom_fields/#{@custom_field}/edit?return_to=show"}
|
||||
>
|
||||
<.icon name="hero-pencil-square" /> Edit Custom field
|
||||
</.button>
|
||||
</:actions>
|
||||
</.header>
|
||||
|
||||
<.list>
|
||||
<:item title="Id">{@custom_field.id}</:item>
|
||||
|
||||
<:item title="Slug">
|
||||
{@custom_field.slug}
|
||||
<p class="mt-2 text-sm leading-6 text-zinc-600">
|
||||
{gettext("Auto-generated identifier (immutable)")}
|
||||
</p>
|
||||
</:item>
|
||||
|
||||
<:item title="Name">{@custom_field.name}</:item>
|
||||
|
||||
<:item title="Description">{@custom_field.description}</:item>
|
||||
</.list>
|
||||
</Layouts.app>
|
||||
"""
|
||||
end
|
||||
|
||||
@impl true
|
||||
def mount(%{"id" => id}, _session, socket) do
|
||||
{:ok,
|
||||
socket
|
||||
|> assign(:page_title, "Show Custom field")
|
||||
|> assign(:custom_field, Ash.get!(Mv.Membership.CustomField, id))}
|
||||
end
|
||||
end
|
||||
|
|
@ -4,6 +4,7 @@ defmodule MvWeb.GlobalSettingsLive do
|
|||
|
||||
## Features
|
||||
- Edit the association/club name
|
||||
- Manage custom fields
|
||||
- Real-time form validation
|
||||
- Success/error feedback
|
||||
|
||||
|
|
@ -28,7 +29,7 @@ defmodule MvWeb.GlobalSettingsLive do
|
|||
|
||||
{:ok,
|
||||
socket
|
||||
|> assign(:page_title, gettext("Club Settings"))
|
||||
|> assign(:page_title, gettext("Settings"))
|
||||
|> assign(:settings, settings)
|
||||
|> assign_form()}
|
||||
end
|
||||
|
|
@ -38,12 +39,16 @@ defmodule MvWeb.GlobalSettingsLive do
|
|||
~H"""
|
||||
<Layouts.app flash={@flash} current_user={@current_user}>
|
||||
<.header>
|
||||
{gettext("Club Settings")}
|
||||
{gettext("Settings")}
|
||||
<:subtitle>
|
||||
{gettext("Manage global settings for the association.")}
|
||||
</:subtitle>
|
||||
</.header>
|
||||
|
||||
<%!-- Club Settings Section --%>
|
||||
<.header>
|
||||
{gettext("Club Settings")}
|
||||
</.header>
|
||||
<.form for={@form} id="settings-form" phx-change="validate" phx-submit="save">
|
||||
<.input
|
||||
field={@form[:club_name]}
|
||||
|
|
@ -56,6 +61,12 @@ defmodule MvWeb.GlobalSettingsLive do
|
|||
{gettext("Save Settings")}
|
||||
</.button>
|
||||
</.form>
|
||||
|
||||
<%!-- Custom Fields Section --%>
|
||||
<.live_component
|
||||
module={MvWeb.CustomFieldLive.IndexComponent}
|
||||
id="custom-fields-component"
|
||||
/>
|
||||
</Layouts.app>
|
||||
"""
|
||||
end
|
||||
|
|
@ -66,6 +77,7 @@ defmodule MvWeb.GlobalSettingsLive do
|
|||
assign(socket, form: AshPhoenix.Form.validate(socket.assigns.form, setting_params))}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event("save", %{"setting" => setting_params}, socket) do
|
||||
case AshPhoenix.Form.submit(socket.assigns.form, params: setting_params) do
|
||||
{:ok, updated_settings} ->
|
||||
|
|
@ -82,6 +94,37 @@ defmodule MvWeb.GlobalSettingsLive do
|
|||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_info({:custom_field_saved, _custom_field, action}, socket) do
|
||||
send_update(MvWeb.CustomFieldLive.IndexComponent,
|
||||
id: "custom-fields-component",
|
||||
show_form: false
|
||||
)
|
||||
|
||||
{:noreply,
|
||||
put_flash(socket, :info, gettext("Custom field %{action} successfully", action: action))}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_info({:custom_field_deleted, _custom_field}, socket) do
|
||||
{:noreply, put_flash(socket, :info, gettext("Custom field deleted successfully"))}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_info({:custom_field_delete_error, error}, socket) do
|
||||
{:noreply,
|
||||
put_flash(
|
||||
socket,
|
||||
:error,
|
||||
gettext("Failed to delete custom field: %{error}", error: inspect(error))
|
||||
)}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_info(:custom_field_slug_mismatch, socket) do
|
||||
{:noreply, put_flash(socket, :error, gettext("Slug does not match. Deletion cancelled."))}
|
||||
end
|
||||
|
||||
defp assign_form(%{assigns: %{settings: settings}} = socket) do
|
||||
form =
|
||||
AshPhoenix.Form.for_update(
|
||||
|
|
|
|||
|
|
@ -55,12 +55,6 @@ defmodule MvWeb.Router do
|
|||
live "/members/:id", MemberLive.Show, :show
|
||||
live "/members/:id/show/edit", MemberLive.Show, :edit
|
||||
|
||||
live "/custom_fields", CustomFieldLive.Index, :index
|
||||
live "/custom_fields/new", CustomFieldLive.Form, :new
|
||||
live "/custom_fields/:id/edit", CustomFieldLive.Form, :edit
|
||||
live "/custom_fields/:id", CustomFieldLive.Show, :show
|
||||
live "/custom_fields/:id/show/edit", CustomFieldLive.Show, :edit
|
||||
|
||||
live "/custom_field_values", CustomFieldValueLive.Index, :index
|
||||
live "/custom_field_values/new", CustomFieldValueLive.Form, :new
|
||||
live "/custom_field_values/:id/edit", CustomFieldValueLive.Form, :edit
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ msgid "City"
|
|||
msgstr "Stadt"
|
||||
|
||||
#: lib/mv_web/live/contribution_type_live/index.ex
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#: lib/mv_web/live/member_live/index.html.heex
|
||||
#: lib/mv_web/live/user_live/index.html.heex
|
||||
#, elixir-autogen, elixir-format
|
||||
|
|
@ -41,6 +42,7 @@ msgid "Delete"
|
|||
msgstr "Löschen"
|
||||
|
||||
#: lib/mv_web/live/contribution_type_live/index.ex
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#: lib/mv_web/live/member_live/index.html.heex
|
||||
#: lib/mv_web/live/user_live/form.ex
|
||||
#: lib/mv_web/live/user_live/index.html.heex
|
||||
|
|
@ -154,7 +156,7 @@ msgstr "Postleitzahl"
|
|||
msgid "Save Member"
|
||||
msgstr "Mitglied speichern"
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#: lib/mv_web/live/custom_field_value_live/form.ex
|
||||
#: lib/mv_web/live/global_settings_live.ex
|
||||
#: lib/mv_web/live/member_live/form.ex
|
||||
|
|
@ -169,6 +171,7 @@ msgstr "Speichern..."
|
|||
msgid "Street"
|
||||
msgstr "Straße"
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#: lib/mv_web/live/member_live/index.html.heex
|
||||
#: lib/mv_web/live/member_live/index/formatter.ex
|
||||
#: lib/mv_web/live/member_live/show.ex
|
||||
|
|
@ -181,6 +184,7 @@ msgstr "Nein"
|
|||
msgid "Show Member"
|
||||
msgstr "Mitglied anzeigen"
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#: lib/mv_web/live/member_live/index.html.heex
|
||||
#: lib/mv_web/live/member_live/index/formatter.ex
|
||||
#: lib/mv_web/live/member_live/show.ex
|
||||
|
|
@ -188,14 +192,14 @@ msgstr "Mitglied anzeigen"
|
|||
msgid "Yes"
|
||||
msgstr "Ja"
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#: lib/mv_web/live/custom_field_value_live/form.ex
|
||||
#: lib/mv_web/live/member_live/form.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "create"
|
||||
msgstr "erstellt"
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#: lib/mv_web/live/custom_field_value_live/form.ex
|
||||
#: lib/mv_web/live/member_live/form.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
|
|
@ -237,8 +241,8 @@ msgstr "Ihre E-Mail-Adresse wurde bestätigt"
|
|||
msgid "Your password has successfully been reset"
|
||||
msgstr "Ihr Passwort wurde erfolgreich zurückgesetzt"
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex
|
||||
#: lib/mv_web/live/custom_field_live/index.ex
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#: lib/mv_web/live/custom_field_value_live/form.ex
|
||||
#: lib/mv_web/live/member_live/form.ex
|
||||
#: lib/mv_web/live/user_live/form.ex
|
||||
|
|
@ -251,7 +255,8 @@ msgstr "Abbrechen"
|
|||
msgid "Choose a member"
|
||||
msgstr "Mitglied auswählen"
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Description"
|
||||
msgstr "Beschreibung"
|
||||
|
|
@ -266,7 +271,7 @@ msgstr "Benutzer*in bearbeiten"
|
|||
msgid "Enabled"
|
||||
msgstr "Aktiviert"
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Immutable"
|
||||
msgstr "Unveränderlich"
|
||||
|
|
@ -296,7 +301,8 @@ msgid "Members"
|
|||
msgstr "Mitglieder"
|
||||
|
||||
#: lib/mv_web/live/contribution_type_live/index.ex
|
||||
#: lib/mv_web/live/custom_field_live/form.ex
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Name"
|
||||
msgstr "Name"
|
||||
|
|
@ -327,7 +333,7 @@ msgstr "Passwort-Authentifizierung"
|
|||
msgid "Profil"
|
||||
msgstr "Profil"
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Required"
|
||||
msgstr "Erforderlich"
|
||||
|
|
@ -343,6 +349,7 @@ msgid "Select member"
|
|||
msgstr "Mitglied auswählen"
|
||||
|
||||
#: lib/mv_web/components/layouts/navbar.ex
|
||||
#: lib/mv_web/live/global_settings_live.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Settings"
|
||||
msgstr "Einstellungen"
|
||||
|
|
@ -383,7 +390,7 @@ msgstr "Benutzer*in"
|
|||
msgid "Value"
|
||||
msgstr "Wert"
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Value type"
|
||||
msgstr "Wertetyp"
|
||||
|
|
@ -579,7 +586,7 @@ msgstr "Wähle ein Benutzerdefiniertes Feld"
|
|||
msgid "Custom field"
|
||||
msgstr "Benutzerdefinierte Felder"
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex
|
||||
#: lib/mv_web/live/global_settings_live.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Custom field %{action} successfully"
|
||||
msgstr "Benutzerdefiniertes Feld erfolgreich %{action}"
|
||||
|
|
@ -594,7 +601,7 @@ msgstr "Benutzerdefinierter Feldwert erfolgreich %{action}"
|
|||
msgid "Please select a custom field first"
|
||||
msgstr "Bitte wähle zuerst ein Benutzerdefiniertes Feld"
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Save Custom field"
|
||||
msgstr "Benutzerdefiniertes Feld speichern"
|
||||
|
|
@ -604,12 +611,7 @@ msgstr "Benutzerdefiniertes Feld speichern"
|
|||
msgid "Save Custom field value"
|
||||
msgstr "Benutzerdefinierten Feldwert speichern"
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Use this form to manage custom_field records in your database."
|
||||
msgstr "Verwende dieses Formular, um Benutzerdefinierte Felder in deiner Datenbank zu verwalten."
|
||||
|
||||
#: lib/mv_web/components/layouts/navbar.ex
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#: lib/mv_web/live/member_live/form.ex
|
||||
#: lib/mv_web/live/member_live/show.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
|
|
@ -621,44 +623,39 @@ msgstr "Benutzerdefinierte Felder"
|
|||
msgid "Use this form to manage Custom Field Value records in your database."
|
||||
msgstr "Verwende dieses Formular, um Benutzerdefinierte Feldwerte in deiner Datenbank zu verwalten."
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/show.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Auto-generated identifier (immutable)"
|
||||
msgstr "Automatisch generierter Bezeichner (unveränderlich)"
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index.ex
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{count} member has a value assigned for this custom field."
|
||||
msgid_plural "%{count} members have values assigned for this custom field."
|
||||
msgstr[0] "%{count} Mitglied hat einen Wert für dieses benutzerdefinierte Feld zugewiesen."
|
||||
msgstr[1] "%{count} Mitglieder haben Werte für dieses benutzerdefinierte Feld zugewiesen."
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index.ex
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "All custom field values will be permanently deleted when you delete this custom field."
|
||||
msgstr "Alle benutzerdefinierten Feldwerte werden beim Löschen dieses benutzerdefinierten Feldes dauerhaft gelöscht."
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index.ex
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Delete Custom Field"
|
||||
msgstr "Benutzerdefiniertes Feld löschen"
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index.ex
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Delete Custom Field and All Values"
|
||||
msgstr "Benutzerdefiniertes Feld und alle Werte löschen"
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index.ex
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Enter the text above to confirm"
|
||||
msgstr "Obigen Text zur Bestätigung eingeben"
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index.ex
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "To confirm deletion, please enter this text:"
|
||||
msgstr "Um die Löschung zu bestätigen, gib bitte folgenden Text ein:"
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Show in overview"
|
||||
msgstr "In der Mitglieder-Übersicht anzeigen"
|
||||
|
|
@ -1322,6 +1319,61 @@ msgstr ""
|
|||
msgid "Yearly Interval - Joining Period Included"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Back to custom field overview"
|
||||
msgstr "Zurück zur Felderliste"
|
||||
|
||||
#: lib/mv_web/live/global_settings_live.ex
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Custom field deleted successfully"
|
||||
msgstr "Benutzerdefiniertes Feld erfolgreich %{action}"
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Edit Custom Field"
|
||||
msgstr "Benutzerdefiniertes Feld löschen"
|
||||
|
||||
#: lib/mv_web/live/global_settings_live.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Failed to delete custom field: %{error}"
|
||||
msgstr "Konnte Feld nicht löschen: %{error}"
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "New Custom Field"
|
||||
msgstr "Benutzerdefiniertes Feld speichern"
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "New Custom field"
|
||||
msgstr "Benutzerdefiniertes Feld speichern"
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Show in Overview"
|
||||
msgstr "In der Mitglieder-Übersicht anzeigen"
|
||||
|
||||
#: lib/mv_web/live/global_settings_live.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Slug does not match. Deletion cancelled."
|
||||
msgstr "Eingegebener Text war nicht korrekt. Vorgang abgebrochen."
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "These will appear in addition to other data when adding new members."
|
||||
msgstr "Diese Felder können zusätzlich zu den normalen Daten ausgefüllt werden, wenn ein neues Mitglied angelegt wird."
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Value Type"
|
||||
msgstr "Wertetyp"
|
||||
|
||||
#~ #: lib/mv_web/live/custom_field_live/show.ex
|
||||
#~ #, elixir-autogen, elixir-format
|
||||
#~ msgid "Auto-generated identifier (immutable)"
|
||||
#~ msgstr "Automatisch generierter Bezeichner (unveränderlich)"
|
||||
|
||||
#~ #: lib/mv_web/live/member_live/form.ex
|
||||
#~ #: lib/mv_web/live/member_live/show.ex
|
||||
#~ #, elixir-autogen, elixir-format
|
||||
|
|
@ -1366,3 +1418,8 @@ msgstr ""
|
|||
#~ #, elixir-autogen, elixir-format
|
||||
#~ msgid "This is a member record from your database."
|
||||
#~ msgstr "Dies ist ein Mitglied aus deiner Datenbank."
|
||||
|
||||
#~ #: lib/mv_web/live/custom_field_live/form.ex
|
||||
#~ #, elixir-autogen, elixir-format
|
||||
#~ msgid "Use this form to manage custom_field records in your database."
|
||||
#~ msgstr "Verwende dieses Formular, um Benutzerdefinierte Felder in deiner Datenbank zu verwalten."
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ msgid "City"
|
|||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/contribution_type_live/index.ex
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#: lib/mv_web/live/member_live/index.html.heex
|
||||
#: lib/mv_web/live/user_live/index.html.heex
|
||||
#, elixir-autogen, elixir-format
|
||||
|
|
@ -42,6 +43,7 @@ msgid "Delete"
|
|||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/contribution_type_live/index.ex
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#: lib/mv_web/live/member_live/index.html.heex
|
||||
#: lib/mv_web/live/user_live/form.ex
|
||||
#: lib/mv_web/live/user_live/index.html.heex
|
||||
|
|
@ -155,7 +157,7 @@ msgstr ""
|
|||
msgid "Save Member"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#: lib/mv_web/live/custom_field_value_live/form.ex
|
||||
#: lib/mv_web/live/global_settings_live.ex
|
||||
#: lib/mv_web/live/member_live/form.ex
|
||||
|
|
@ -170,6 +172,7 @@ msgstr ""
|
|||
msgid "Street"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#: lib/mv_web/live/member_live/index.html.heex
|
||||
#: lib/mv_web/live/member_live/index/formatter.ex
|
||||
#: lib/mv_web/live/member_live/show.ex
|
||||
|
|
@ -182,6 +185,7 @@ msgstr ""
|
|||
msgid "Show Member"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#: lib/mv_web/live/member_live/index.html.heex
|
||||
#: lib/mv_web/live/member_live/index/formatter.ex
|
||||
#: lib/mv_web/live/member_live/show.ex
|
||||
|
|
@ -189,14 +193,14 @@ msgstr ""
|
|||
msgid "Yes"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#: lib/mv_web/live/custom_field_value_live/form.ex
|
||||
#: lib/mv_web/live/member_live/form.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "create"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#: lib/mv_web/live/custom_field_value_live/form.ex
|
||||
#: lib/mv_web/live/member_live/form.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
|
|
@ -238,8 +242,8 @@ msgstr ""
|
|||
msgid "Your password has successfully been reset"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex
|
||||
#: lib/mv_web/live/custom_field_live/index.ex
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#: lib/mv_web/live/custom_field_value_live/form.ex
|
||||
#: lib/mv_web/live/member_live/form.ex
|
||||
#: lib/mv_web/live/user_live/form.ex
|
||||
|
|
@ -252,7 +256,8 @@ msgstr ""
|
|||
msgid "Choose a member"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Description"
|
||||
msgstr ""
|
||||
|
|
@ -267,7 +272,7 @@ msgstr ""
|
|||
msgid "Enabled"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Immutable"
|
||||
msgstr ""
|
||||
|
|
@ -297,7 +302,8 @@ msgid "Members"
|
|||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/contribution_type_live/index.ex
|
||||
#: lib/mv_web/live/custom_field_live/form.ex
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
|
|
@ -328,7 +334,7 @@ msgstr ""
|
|||
msgid "Profil"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Required"
|
||||
msgstr ""
|
||||
|
|
@ -344,6 +350,7 @@ msgid "Select member"
|
|||
msgstr ""
|
||||
|
||||
#: lib/mv_web/components/layouts/navbar.ex
|
||||
#: lib/mv_web/live/global_settings_live.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Settings"
|
||||
msgstr ""
|
||||
|
|
@ -384,7 +391,7 @@ msgstr ""
|
|||
msgid "Value"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Value type"
|
||||
msgstr ""
|
||||
|
|
@ -580,7 +587,7 @@ msgstr ""
|
|||
msgid "Custom field"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex
|
||||
#: lib/mv_web/live/global_settings_live.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Custom field %{action} successfully"
|
||||
msgstr ""
|
||||
|
|
@ -595,7 +602,7 @@ msgstr ""
|
|||
msgid "Please select a custom field first"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Save Custom field"
|
||||
msgstr ""
|
||||
|
|
@ -605,12 +612,7 @@ msgstr ""
|
|||
msgid "Save Custom field value"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Use this form to manage custom_field records in your database."
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/components/layouts/navbar.ex
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#: lib/mv_web/live/member_live/form.ex
|
||||
#: lib/mv_web/live/member_live/show.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
|
|
@ -622,44 +624,39 @@ msgstr ""
|
|||
msgid "Use this form to manage Custom Field Value records in your database."
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/show.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Auto-generated identifier (immutable)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index.ex
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{count} member has a value assigned for this custom field."
|
||||
msgid_plural "%{count} members have values assigned for this custom field."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index.ex
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "All custom field values will be permanently deleted when you delete this custom field."
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index.ex
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Delete Custom Field"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index.ex
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Delete Custom Field and All Values"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index.ex
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Enter the text above to confirm"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index.ex
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "To confirm deletion, please enter this text:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Show in overview"
|
||||
msgstr ""
|
||||
|
|
@ -1322,3 +1319,53 @@ msgstr ""
|
|||
#, elixir-autogen, elixir-format
|
||||
msgid "Yearly Interval - Joining Period Included"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Back to custom field overview"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/global_settings_live.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Custom field deleted successfully"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Edit Custom Field"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/global_settings_live.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Failed to delete custom field: %{error}"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "New Custom Field"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "New Custom field"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Show in Overview"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/global_settings_live.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Slug does not match. Deletion cancelled."
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "These will appear in addition to other data when adding new members."
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Value Type"
|
||||
msgstr ""
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ msgid "City"
|
|||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/contribution_type_live/index.ex
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#: lib/mv_web/live/member_live/index.html.heex
|
||||
#: lib/mv_web/live/user_live/index.html.heex
|
||||
#, elixir-autogen, elixir-format
|
||||
|
|
@ -42,6 +43,7 @@ msgid "Delete"
|
|||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/contribution_type_live/index.ex
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#: lib/mv_web/live/member_live/index.html.heex
|
||||
#: lib/mv_web/live/user_live/form.ex
|
||||
#: lib/mv_web/live/user_live/index.html.heex
|
||||
|
|
@ -155,7 +157,7 @@ msgstr ""
|
|||
msgid "Save Member"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#: lib/mv_web/live/custom_field_value_live/form.ex
|
||||
#: lib/mv_web/live/global_settings_live.ex
|
||||
#: lib/mv_web/live/member_live/form.ex
|
||||
|
|
@ -170,6 +172,7 @@ msgstr ""
|
|||
msgid "Street"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#: lib/mv_web/live/member_live/index.html.heex
|
||||
#: lib/mv_web/live/member_live/index/formatter.ex
|
||||
#: lib/mv_web/live/member_live/show.ex
|
||||
|
|
@ -182,6 +185,7 @@ msgstr ""
|
|||
msgid "Show Member"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#: lib/mv_web/live/member_live/index.html.heex
|
||||
#: lib/mv_web/live/member_live/index/formatter.ex
|
||||
#: lib/mv_web/live/member_live/show.ex
|
||||
|
|
@ -189,14 +193,14 @@ msgstr ""
|
|||
msgid "Yes"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#: lib/mv_web/live/custom_field_value_live/form.ex
|
||||
#: lib/mv_web/live/member_live/form.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "create"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#: lib/mv_web/live/custom_field_value_live/form.ex
|
||||
#: lib/mv_web/live/member_live/form.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
|
|
@ -238,8 +242,8 @@ msgstr ""
|
|||
msgid "Your password has successfully been reset"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex
|
||||
#: lib/mv_web/live/custom_field_live/index.ex
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#: lib/mv_web/live/custom_field_value_live/form.ex
|
||||
#: lib/mv_web/live/member_live/form.ex
|
||||
#: lib/mv_web/live/user_live/form.ex
|
||||
|
|
@ -252,7 +256,8 @@ msgstr ""
|
|||
msgid "Choose a member"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Description"
|
||||
msgstr ""
|
||||
|
|
@ -267,7 +272,7 @@ msgstr ""
|
|||
msgid "Enabled"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Immutable"
|
||||
msgstr ""
|
||||
|
|
@ -297,7 +302,8 @@ msgid "Members"
|
|||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/contribution_type_live/index.ex
|
||||
#: lib/mv_web/live/custom_field_live/form.ex
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
|
|
@ -328,7 +334,7 @@ msgstr ""
|
|||
msgid "Profil"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Required"
|
||||
msgstr ""
|
||||
|
|
@ -344,6 +350,7 @@ msgid "Select member"
|
|||
msgstr ""
|
||||
|
||||
#: lib/mv_web/components/layouts/navbar.ex
|
||||
#: lib/mv_web/live/global_settings_live.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Settings"
|
||||
msgstr ""
|
||||
|
|
@ -384,7 +391,7 @@ msgstr ""
|
|||
msgid "Value"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Value type"
|
||||
msgstr ""
|
||||
|
|
@ -580,7 +587,7 @@ msgstr ""
|
|||
msgid "Custom field"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex
|
||||
#: lib/mv_web/live/global_settings_live.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Custom field %{action} successfully"
|
||||
msgstr ""
|
||||
|
|
@ -595,7 +602,7 @@ msgstr ""
|
|||
msgid "Please select a custom field first"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Save Custom field"
|
||||
msgstr ""
|
||||
|
|
@ -605,12 +612,7 @@ msgstr ""
|
|||
msgid "Save Custom field value"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Use this form to manage custom_field records in your database."
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/components/layouts/navbar.ex
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#: lib/mv_web/live/member_live/form.ex
|
||||
#: lib/mv_web/live/member_live/show.ex
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
|
|
@ -622,44 +624,39 @@ msgstr ""
|
|||
msgid "Use this form to manage Custom Field Value records in your database."
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/show.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Auto-generated identifier (immutable)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index.ex
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{count} member has a value assigned for this custom field."
|
||||
msgid_plural "%{count} members have values assigned for this custom field."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index.ex
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "All custom field values will be permanently deleted when you delete this custom field."
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index.ex
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Delete Custom Field"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index.ex
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Delete Custom Field and All Values"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index.ex
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Enter the text above to confirm"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index.ex
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "To confirm deletion, please enter this text:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form.ex
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Show in overview"
|
||||
msgstr ""
|
||||
|
|
@ -1323,6 +1320,61 @@ msgstr ""
|
|||
msgid "Yearly Interval - Joining Period Included"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Back to custom field overview"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/global_settings_live.ex
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Custom field deleted successfully"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Edit Custom Field"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/global_settings_live.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Failed to delete custom field: %{error}"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/form_component.ex
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "New Custom Field"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "New Custom field"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Show in Overview"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/global_settings_live.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Slug does not match. Deletion cancelled."
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "These will appear in addition to other data when adding new members."
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Value Type"
|
||||
msgstr ""
|
||||
|
||||
#~ #: lib/mv_web/live/custom_field_live/show.ex
|
||||
#~ #, elixir-autogen, elixir-format
|
||||
#~ msgid "Auto-generated identifier (immutable)"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ #: lib/mv_web/live/member_live/form.ex
|
||||
#~ #: lib/mv_web/live/member_live/show.ex
|
||||
#~ #, elixir-autogen, elixir-format
|
||||
|
|
@ -1365,3 +1417,8 @@ msgstr ""
|
|||
#~ #, elixir-autogen, elixir-format
|
||||
#~ msgid "This is a member record from your database."
|
||||
#~ msgstr ""
|
||||
|
||||
#~ #: lib/mv_web/live/custom_field_live/form.ex
|
||||
#~ #, elixir-autogen, elixir-format, fuzzy
|
||||
#~ msgid "Use this form to manage custom_field records in your database."
|
||||
#~ msgstr ""
|
||||
|
|
|
|||
|
|
@ -1,14 +0,0 @@
|
|||
defmodule Mv.Membership.MemberFieldVisibilityTest do
|
||||
@moduledoc """
|
||||
Tests for member field visibility configuration.
|
||||
|
||||
Tests cover:
|
||||
- Member fields are visible by default (show_in_overview: true)
|
||||
- Member fields can be hidden (show_in_overview: false)
|
||||
- Checking if a specific field is visible
|
||||
- Configuration is stored in Settings resource
|
||||
"""
|
||||
use Mv.DataCase, async: true
|
||||
|
||||
alias Mv.Membership.Member
|
||||
end
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
defmodule MvWeb.CustomFieldLive.DeletionTest do
|
||||
@moduledoc """
|
||||
Tests for CustomFieldLive.Index deletion modal and slug confirmation.
|
||||
Tests for CustomFieldLive.IndexComponent deletion modal and slug confirmation.
|
||||
Tests the custom field management component embedded in the settings page.
|
||||
|
||||
Tests cover:
|
||||
- Opening deletion confirmation modal
|
||||
|
|
@ -39,11 +40,11 @@ defmodule MvWeb.CustomFieldLive.DeletionTest do
|
|||
# Create custom field value
|
||||
create_custom_field_value(member, custom_field, "test")
|
||||
|
||||
{:ok, view, _html} = live(conn, ~p"/custom_fields")
|
||||
{:ok, view, _html} = live(conn, ~p"/settings")
|
||||
|
||||
# Click delete button
|
||||
# Click delete button - find the delete link within the component
|
||||
view
|
||||
|> element("a", "Delete")
|
||||
|> element("#custom-fields-component a", "Delete")
|
||||
|> render_click()
|
||||
|
||||
# Modal should be visible
|
||||
|
|
@ -65,10 +66,10 @@ defmodule MvWeb.CustomFieldLive.DeletionTest do
|
|||
create_custom_field_value(member1, custom_field, "test1")
|
||||
create_custom_field_value(member2, custom_field, "test2")
|
||||
|
||||
{:ok, view, _html} = live(conn, ~p"/custom_fields")
|
||||
{:ok, view, _html} = live(conn, ~p"/settings")
|
||||
|
||||
view
|
||||
|> element("a", "Delete")
|
||||
|> element("#custom-fields-component a", "Delete")
|
||||
|> render_click()
|
||||
|
||||
# Should show plural form
|
||||
|
|
@ -78,10 +79,10 @@ defmodule MvWeb.CustomFieldLive.DeletionTest do
|
|||
test "shows 0 members for custom field without values", %{conn: conn} do
|
||||
{:ok, _custom_field} = create_custom_field("test_field", :string)
|
||||
|
||||
{:ok, view, _html} = live(conn, ~p"/custom_fields")
|
||||
{:ok, view, _html} = live(conn, ~p"/settings")
|
||||
|
||||
view
|
||||
|> element("a", "Delete")
|
||||
|> element("#custom-fields-component a", "Delete")
|
||||
|> render_click()
|
||||
|
||||
# Should show 0 members
|
||||
|
|
@ -93,15 +94,16 @@ defmodule MvWeb.CustomFieldLive.DeletionTest do
|
|||
test "updates confirmation state when typing", %{conn: conn} do
|
||||
{:ok, custom_field} = create_custom_field("test_field", :string)
|
||||
|
||||
{:ok, view, _html} = live(conn, ~p"/custom_fields")
|
||||
{:ok, view, _html} = live(conn, ~p"/settings")
|
||||
|
||||
view
|
||||
|> element("a", "Delete")
|
||||
|> element("#custom-fields-component a", "Delete")
|
||||
|> render_click()
|
||||
|
||||
# Type in slug input
|
||||
# Type in slug input - use element to find the form with phx-target
|
||||
view
|
||||
|> render_change("update_slug_confirmation", %{"slug" => custom_field.slug})
|
||||
|> element("#delete-custom-field-modal form")
|
||||
|> render_change(%{"slug" => custom_field.slug})
|
||||
|
||||
# Confirm button should be enabled now (no disabled attribute)
|
||||
html = render(view)
|
||||
|
|
@ -111,15 +113,16 @@ defmodule MvWeb.CustomFieldLive.DeletionTest do
|
|||
test "delete button is disabled when slug doesn't match", %{conn: conn} do
|
||||
{:ok, _custom_field} = create_custom_field("test_field", :string)
|
||||
|
||||
{:ok, view, _html} = live(conn, ~p"/custom_fields")
|
||||
{:ok, view, _html} = live(conn, ~p"/settings")
|
||||
|
||||
view
|
||||
|> element("a", "Delete")
|
||||
|> element("#custom-fields-component a", "Delete")
|
||||
|> render_click()
|
||||
|
||||
# Type wrong slug
|
||||
# Type wrong slug - use element to find the form with phx-target
|
||||
view
|
||||
|> render_change("update_slug_confirmation", %{"slug" => "wrong-slug"})
|
||||
|> element("#delete-custom-field-modal form")
|
||||
|> render_change(%{"slug" => "wrong-slug"})
|
||||
|
||||
# Button should be disabled
|
||||
html = render(view)
|
||||
|
|
@ -133,20 +136,21 @@ defmodule MvWeb.CustomFieldLive.DeletionTest do
|
|||
{:ok, custom_field} = create_custom_field("test_field", :string)
|
||||
{:ok, custom_field_value} = create_custom_field_value(member, custom_field, "test")
|
||||
|
||||
{:ok, view, _html} = live(conn, ~p"/custom_fields")
|
||||
{:ok, view, _html} = live(conn, ~p"/settings")
|
||||
|
||||
# Open modal
|
||||
view
|
||||
|> element("a", "Delete")
|
||||
|> element("#custom-fields-component a", "Delete")
|
||||
|> render_click()
|
||||
|
||||
# Enter correct slug
|
||||
# Enter correct slug - use element to find the form with phx-target
|
||||
view
|
||||
|> render_change("update_slug_confirmation", %{"slug" => custom_field.slug})
|
||||
|> element("#delete-custom-field-modal form")
|
||||
|> render_change(%{"slug" => custom_field.slug})
|
||||
|
||||
# Click confirm
|
||||
view
|
||||
|> element("button", "Delete Custom Field and All Values")
|
||||
|> element("#delete-custom-field-modal button", "Delete Custom Field and All Values")
|
||||
|> render_click()
|
||||
|
||||
# Should show success message
|
||||
|
|
@ -162,27 +166,28 @@ defmodule MvWeb.CustomFieldLive.DeletionTest do
|
|||
assert {:ok, _} = Ash.get(Member, member.id)
|
||||
end
|
||||
|
||||
test "shows error when slug doesn't match", %{conn: conn} do
|
||||
test "button remains disabled and custom field not deleted when slug doesn't match", %{
|
||||
conn: conn
|
||||
} do
|
||||
{:ok, custom_field} = create_custom_field("test_field", :string)
|
||||
|
||||
{:ok, view, _html} = live(conn, ~p"/custom_fields")
|
||||
{:ok, view, _html} = live(conn, ~p"/settings")
|
||||
|
||||
view
|
||||
|> element("a", "Delete")
|
||||
|> element("#custom-fields-component a", "Delete")
|
||||
|> render_click()
|
||||
|
||||
# Enter wrong slug
|
||||
# Enter wrong slug - use element to find the form with phx-target
|
||||
view
|
||||
|> render_change("update_slug_confirmation", %{"slug" => "wrong-slug"})
|
||||
|> element("#delete-custom-field-modal form")
|
||||
|> render_change(%{"slug" => "wrong-slug"})
|
||||
|
||||
# Try to confirm (button should be disabled, but test the handler anyway)
|
||||
view
|
||||
|> render_click("confirm_delete", %{})
|
||||
# Button should be disabled and we cannot click it
|
||||
# The test verifies that the button is properly disabled in the UI
|
||||
html = render(view)
|
||||
assert html =~ ~r/disabled(?:=""|(?!\w))/
|
||||
|
||||
# Should show error message
|
||||
assert render(view) =~ "Slug does not match"
|
||||
|
||||
# Custom field should still exist
|
||||
# Custom field should still exist since deletion couldn't proceed
|
||||
assert {:ok, _} = Ash.get(CustomField, custom_field.id)
|
||||
end
|
||||
end
|
||||
|
|
@ -191,10 +196,10 @@ defmodule MvWeb.CustomFieldLive.DeletionTest do
|
|||
test "closes modal without deleting", %{conn: conn} do
|
||||
{:ok, custom_field} = create_custom_field("test_field", :string)
|
||||
|
||||
{:ok, view, _html} = live(conn, ~p"/custom_fields")
|
||||
{:ok, view, _html} = live(conn, ~p"/settings")
|
||||
|
||||
view
|
||||
|> element("a", "Delete")
|
||||
|> element("#custom-fields-component a", "Delete")
|
||||
|> render_click()
|
||||
|
||||
# Modal should be visible
|
||||
|
|
@ -202,7 +207,7 @@ defmodule MvWeb.CustomFieldLive.DeletionTest do
|
|||
|
||||
# Click cancel
|
||||
view
|
||||
|> element("button", "Cancel")
|
||||
|> element("#delete-custom-field-modal button", "Cancel")
|
||||
|> render_click()
|
||||
|
||||
# Modal should be gone
|
||||
|
|
|
|||
|
|
@ -148,8 +148,6 @@ defmodule MvWeb.ProfileNavigationTest do
|
|||
"/members/new",
|
||||
"/custom_field_values",
|
||||
"/custom_field_values/new",
|
||||
"/custom_fields",
|
||||
"/custom_fields/new",
|
||||
"/users",
|
||||
"/users/new"
|
||||
]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue