style: combines member and custom fields in settings
This commit is contained in:
parent
5fa0b48acc
commit
c88f805b6e
2 changed files with 171 additions and 155 deletions
|
|
@ -17,165 +17,161 @@ defmodule MvWeb.CustomFieldLive.IndexComponent do
|
||||||
assigns = assign(assigns, :field_type_label, &MvWeb.Translations.FieldTypes.label/1)
|
assigns = assign(assigns, :field_type_label, &MvWeb.Translations.FieldTypes.label/1)
|
||||||
|
|
||||||
~H"""
|
~H"""
|
||||||
<div id={@id}>
|
<div id={@id} class="mt-8">
|
||||||
<.form_section title={gettext("Custom Fields")}>
|
<div class="flex">
|
||||||
<div class="flex">
|
<p class="text-sm text-base-content/70">
|
||||||
<p class="text-sm text-base-content/70">
|
{gettext("These will appear in addition to other data when adding new members.")}
|
||||||
{gettext("These will appear in addition to other data when adding new members.")}
|
</p>
|
||||||
</p>
|
<div class="ml-auto">
|
||||||
<div class="ml-auto">
|
<.button
|
||||||
<.button
|
class="ml-auto"
|
||||||
class="ml-auto"
|
variant="primary"
|
||||||
variant="primary"
|
phx-click="new_custom_field"
|
||||||
phx-click="new_custom_field"
|
phx-target={@myself}
|
||||||
phx-target={@myself}
|
>
|
||||||
>
|
<.icon name="hero-plus" /> {gettext("New Custom field")}
|
||||||
<.icon name="hero-plus" /> {gettext("New Custom field")}
|
</.button>
|
||||||
</.button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<%!-- Show form when creating or editing --%>
|
</div>
|
||||||
<div :if={@show_form} class="mb-8">
|
<%!-- Show form when creating or editing --%>
|
||||||
<.live_component
|
<div :if={@show_form} class="mb-8">
|
||||||
module={MvWeb.CustomFieldLive.FormComponent}
|
<.live_component
|
||||||
id={@form_id}
|
module={MvWeb.CustomFieldLive.FormComponent}
|
||||||
custom_field={@editing_custom_field}
|
id={@form_id}
|
||||||
on_save={
|
custom_field={@editing_custom_field}
|
||||||
fn custom_field, action -> send(self(), {:custom_field_saved, custom_field, action}) end
|
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
|
|
||||||
}
|
}
|
||||||
|
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")}>
|
||||||
|
{@field_type_label.(custom_field.value_type)}
|
||||||
|
</:col>
|
||||||
|
|
||||||
|
<:col :let={{_id, custom_field}} label={gettext("Description")}>
|
||||||
|
{custom_field.description}
|
||||||
|
</:col>
|
||||||
|
|
||||||
|
<:col
|
||||||
|
:let={{_id, custom_field}}
|
||||||
|
label={gettext("Required")}
|
||||||
|
class="max-w-[9.375rem] text-center"
|
||||||
>
|
>
|
||||||
<:col :let={{_id, custom_field}} label={gettext("Name")}>{custom_field.name}</:col>
|
<span :if={custom_field.required} class="text-base-content font-semibold">
|
||||||
|
{gettext("Required")}
|
||||||
|
</span>
|
||||||
|
<span :if={!custom_field.required} class="text-base-content/70">
|
||||||
|
{gettext("Optional")}
|
||||||
|
</span>
|
||||||
|
</:col>
|
||||||
|
|
||||||
<:col :let={{_id, custom_field}} label={gettext("Value Type")}>
|
<:col
|
||||||
{@field_type_label.(custom_field.value_type)}
|
:let={{_id, custom_field}}
|
||||||
</:col>
|
label={gettext("Show in overview")}
|
||||||
|
class="max-w-[9.375rem] text-center"
|
||||||
|
>
|
||||||
|
<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>
|
||||||
|
|
||||||
<:col :let={{_id, custom_field}} label={gettext("Description")}>
|
<:action :let={{_id, custom_field}}>
|
||||||
{custom_field.description}
|
<.link phx-click={
|
||||||
</:col>
|
JS.push("edit_custom_field", value: %{id: custom_field.id}, target: @myself)
|
||||||
|
}>
|
||||||
|
{gettext("Edit")}
|
||||||
|
</.link>
|
||||||
|
</:action>
|
||||||
|
|
||||||
<:col
|
<:action :let={{_id, custom_field}}>
|
||||||
:let={{_id, custom_field}}
|
<.link phx-click={JS.push("prepare_delete", value: %{id: custom_field.id}, target: @myself)}>
|
||||||
label={gettext("Required")}
|
{gettext("Delete")}
|
||||||
class="max-w-[9.375rem] text-center"
|
</.link>
|
||||||
>
|
</:action>
|
||||||
<span :if={custom_field.required} class="text-base-content font-semibold">
|
</.table>
|
||||||
{gettext("Required")}
|
|
||||||
</span>
|
|
||||||
<span :if={!custom_field.required} class="text-base-content/70">
|
|
||||||
{gettext("Optional")}
|
|
||||||
</span>
|
|
||||||
</:col>
|
|
||||||
|
|
||||||
<:col
|
<%!-- Delete Confirmation Modal --%>
|
||||||
:let={{_id, custom_field}}
|
<dialog :if={@show_delete_modal} id="delete-custom-field-modal" class="modal modal-open">
|
||||||
label={gettext("Show in overview")}
|
<div class="modal-box">
|
||||||
class="max-w-[9.375rem] text-center"
|
<h3 class="text-lg font-bold">{gettext("Delete Custom Field")}</h3>
|
||||||
>
|
|
||||||
<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 class="py-4 space-y-4">
|
||||||
|
<div class="alert alert-warning">
|
||||||
|
<.icon name="hero-exclamation-triangle" class="w-5 h-5" />
|
||||||
<div>
|
<div>
|
||||||
<label for="slug-confirmation" class="label">
|
<p class="font-semibold">
|
||||||
<span class="label-text">
|
{ngettext(
|
||||||
{gettext("To confirm deletion, please enter this text:")}
|
"%{count} member has a value assigned for this custom field.",
|
||||||
</span>
|
"%{count} members have values assigned for this custom field.",
|
||||||
</label>
|
@custom_field_to_delete.assigned_members_count,
|
||||||
<div class="p-2 mb-2 font-mono text-lg font-bold break-all rounded bg-base-200">
|
count: @custom_field_to_delete.assigned_members_count
|
||||||
{@custom_field_to_delete.slug}
|
)}
|
||||||
</div>
|
</p>
|
||||||
<form phx-change="update_slug_confirmation" phx-target={@myself}>
|
<p class="mt-2 text-sm">
|
||||||
<input
|
{gettext(
|
||||||
id="slug-confirmation"
|
"All custom field values will be permanently deleted when you delete this custom field."
|
||||||
name="slug"
|
)}
|
||||||
type="text"
|
</p>
|
||||||
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>
|
</div>
|
||||||
|
|
||||||
<div class="modal-action">
|
<div>
|
||||||
<button phx-click="cancel_delete" phx-target={@myself} class="btn">
|
<label for="slug-confirmation" class="label">
|
||||||
{gettext("Cancel")}
|
<span class="label-text">
|
||||||
</button>
|
{gettext("To confirm deletion, please enter this text:")}
|
||||||
<button
|
</span>
|
||||||
phx-click="confirm_delete"
|
</label>
|
||||||
phx-target={@myself}
|
<div class="p-2 mb-2 font-mono text-lg font-bold break-all rounded bg-base-200">
|
||||||
class="btn btn-error"
|
{@custom_field_to_delete.slug}
|
||||||
disabled={@slug_confirmation != @custom_field_to_delete.slug}
|
</div>
|
||||||
>
|
<form phx-change="update_slug_confirmation" phx-target={@myself}>
|
||||||
{gettext("Delete Custom Field and All Values")}
|
<input
|
||||||
</button>
|
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>
|
</div>
|
||||||
</dialog>
|
|
||||||
</.form_section>
|
<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>
|
</div>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -63,16 +63,18 @@ defmodule MvWeb.GlobalSettingsLive do
|
||||||
</.form>
|
</.form>
|
||||||
</.form_section>
|
</.form_section>
|
||||||
<%!-- Memberdata Section --%>
|
<%!-- Memberdata Section --%>
|
||||||
<.live_component
|
<.form_section title={gettext("Memberdata")}>
|
||||||
module={MvWeb.MemberFieldLive.IndexComponent}
|
<.live_component
|
||||||
id="member-fields-component"
|
module={MvWeb.MemberFieldLive.IndexComponent}
|
||||||
settings={@settings}
|
id="member-fields-component"
|
||||||
/>
|
settings={@settings}
|
||||||
<%!-- Custom Fields Section --%>
|
/>
|
||||||
<.live_component
|
<%!-- Custom Fields Section --%>
|
||||||
module={MvWeb.CustomFieldLive.IndexComponent}
|
<.live_component
|
||||||
id="custom-fields-component"
|
module={MvWeb.CustomFieldLive.IndexComponent}
|
||||||
/>
|
id="custom-fields-component"
|
||||||
|
/>
|
||||||
|
</.form_section>
|
||||||
</Layouts.app>
|
</Layouts.app>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
@ -158,6 +160,24 @@ defmodule MvWeb.GlobalSettingsLive do
|
||||||
{:noreply, put_flash(socket, :error, error_message)}
|
{:noreply, put_flash(socket, :error, error_message)}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def handle_info({:member_field_saved, _member_field, action}, socket) do
|
||||||
|
# Reload settings to get updated member_field_visibility
|
||||||
|
{:ok, updated_settings} = Membership.get_settings()
|
||||||
|
|
||||||
|
# Send update to member fields component to close form
|
||||||
|
send_update(MvWeb.MemberFieldLive.IndexComponent,
|
||||||
|
id: "member-fields-component",
|
||||||
|
show_form: false,
|
||||||
|
settings: updated_settings
|
||||||
|
)
|
||||||
|
|
||||||
|
{:noreply,
|
||||||
|
socket
|
||||||
|
|> assign(:settings, updated_settings)
|
||||||
|
|> put_flash(:info, gettext("Member field %{action} successfully", action: action))}
|
||||||
|
end
|
||||||
|
|
||||||
defp assign_form(%{assigns: %{settings: settings}} = socket) do
|
defp assign_form(%{assigns: %{settings: settings}} = socket) do
|
||||||
form =
|
form =
|
||||||
AshPhoenix.Form.for_update(
|
AshPhoenix.Form.for_update(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue