feat: conistent danger zone delete flow
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
carla 2026-02-25 15:09:37 +01:00
parent e5a6003ace
commit 91cf7cca6a
19 changed files with 499 additions and 287 deletions

View file

@ -98,6 +98,33 @@ defmodule MvWeb.CustomFieldLive.FormComponent do
label={gettext("Show in overview")}
/>
<%= if @custom_field do %>
<%!-- Danger zone: canonical pattern (same as member form) --%>
<section class="mt-8 mb-6" aria-labelledby="danger-zone-heading">
<h2 id="danger-zone-heading" class="text-lg font-semibold mb-3 text-error">
{gettext("Danger zone")}
</h2>
<div class="border border-base-300 rounded-lg p-4 bg-base-100">
<p class="text-base-content/70 mb-4">
{gettext(
"Deleting this data field cannot be undone. All custom field values for this field will be permanently removed."
)}
</p>
<.button
type="button"
variant="danger"
phx-click="request_delete"
phx-target={@myself}
data-testid="custom-field-delete"
aria-label={gettext("Delete data field %{name}", name: @custom_field.name)}
>
<.icon name="hero-trash" class="size-4" />
{gettext("Delete data field")}
</.button>
</div>
</section>
<% end %>
<div class="justify-end mt-4 card-actions">
<.button type="button" variant="neutral" phx-click="cancel" phx-target={@myself}>
{gettext("Cancel")}
@ -170,6 +197,15 @@ defmodule MvWeb.CustomFieldLive.FormComponent do
{:noreply, socket}
end
@impl true
def handle_event("request_delete", _params, socket) do
if custom_field = socket.assigns[:custom_field] do
send(self(), {:open_delete_modal_for, custom_field})
end
{:noreply, socket}
end
defp assign_form(%{assigns: %{custom_field: custom_field}} = socket) do
form =
if custom_field do

View file

@ -59,7 +59,7 @@ defmodule MvWeb.CustomFieldLive.IndexComponent do
JS.push("edit_custom_field", value: %{id: custom_field.id}, target: @myself)
end
}
row_tooltip={gettext("Click for dataield details")}
row_tooltip={gettext("Click to edit datafield")}
>
<:col :let={{_id, custom_field}} label={gettext("Name")}>{custom_field.name}</:col>
@ -96,22 +96,6 @@ defmodule MvWeb.CustomFieldLive.IndexComponent do
{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 datafield")}
</.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>
</div>
@ -223,16 +207,38 @@ defmodule MvWeb.CustomFieldLive.IndexComponent do
# Get actor from assigns or fall back to socket assigns
actor = Map.get(assigns, :actor, socket.assigns[:actor])
{: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, stream_custom_fields(actor, self()), reset: true)}
socket =
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, stream_custom_fields(actor, self()), reset: true)
# Open delete modal when requested from form (e.g. Danger zone in FormComponent)
socket =
case Map.get(assigns, :open_delete_for_id) do
nil ->
socket
id ->
custom_field =
Ash.get!(Mv.Membership.CustomField, id,
load: [:assigned_members_count],
actor: actor
)
socket
|> assign(:show_delete_modal, true)
|> assign(:custom_field_to_delete, custom_field)
|> assign(:slug_confirmation, "")
|> assign(:open_delete_for_id, nil)
end
{:ok, socket}
end
@impl true