fix: datafield edit view was shown alongside othe relements
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
This commit is contained in:
parent
faf80bfb4b
commit
9751525a0c
8 changed files with 85 additions and 41 deletions
|
|
@ -19,8 +19,8 @@ defmodule MvWeb.CustomFieldLive.IndexComponent do
|
|||
assigns = assign(assigns, :field_type_label, &MvWeb.Translations.FieldTypes.label/1)
|
||||
|
||||
~H"""
|
||||
<div id={@id} class="mt-8">
|
||||
<div class="flex">
|
||||
<div id={@id}>
|
||||
<div :if={!@show_form} class="flex">
|
||||
<p class="text-sm text-base-content/70">
|
||||
{gettext("These will appear in addition to other data when adding new members.")}
|
||||
</p>
|
||||
|
|
@ -118,15 +118,15 @@ defmodule MvWeb.CustomFieldLive.IndexComponent do
|
|||
<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.",
|
||||
"%{count} member has a value assigned for this datafield.",
|
||||
"%{count} members have values assigned for this datafield.",
|
||||
@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."
|
||||
"All datafield values will be permanently deleted when you delete this datfield."
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -192,8 +192,8 @@ defmodule MvWeb.CustomFieldLive.IndexComponent do
|
|||
|
||||
@impl true
|
||||
def update(assigns, socket) do
|
||||
# Track previous show_form state to detect when form is closed
|
||||
previous_show_form = Map.get(socket.assigns, :show_form, false)
|
||||
# Use socket state so send_update(open_delete_for_id: ...) does not trigger false "form closed"
|
||||
previous_show_form = socket.assigns[:show_form] || false
|
||||
|
||||
# If show_form is explicitly provided in assigns, reset editing state
|
||||
socket =
|
||||
|
|
@ -205,13 +205,6 @@ defmodule MvWeb.CustomFieldLive.IndexComponent do
|
|||
socket
|
||||
end
|
||||
|
||||
# Detect when form is closed (show_form changes from true to false)
|
||||
new_show_form = Map.get(assigns, :show_form, false)
|
||||
|
||||
if previous_show_form and not new_show_form do
|
||||
send(self(), {:editing_section_changed, nil})
|
||||
end
|
||||
|
||||
# Get actor from assigns or fall back to socket assigns
|
||||
actor = Map.get(assigns, :actor, socket.assigns[:actor])
|
||||
|
||||
|
|
@ -246,6 +239,13 @@ defmodule MvWeb.CustomFieldLive.IndexComponent do
|
|||
|> assign(:open_delete_for_id, nil)
|
||||
end
|
||||
|
||||
# Detect form closed only from final socket state (not from assigns alone)
|
||||
current_show_form = socket.assigns[:show_form] || false
|
||||
|
||||
if previous_show_form and not current_show_form do
|
||||
send(self(), {:editing_section_changed, nil})
|
||||
end
|
||||
|
||||
{:ok, socket}
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -29,27 +29,47 @@ defmodule MvWeb.DatafieldsLive do
|
|||
<.header>
|
||||
{gettext("Datafields")}
|
||||
<:subtitle>
|
||||
{gettext("Configure which data you want to save for your members. Define individual datafields.")}
|
||||
{gettext(
|
||||
"Configure which data you want to save for your members. Define individual datafields."
|
||||
)}
|
||||
</:subtitle>
|
||||
</.header>
|
||||
|
||||
<.form_section title={gettext("Member fields")}>
|
||||
<%!-- Overview: both sections with form_section wrappers --%>
|
||||
<div :if={@active_editing_section == nil} class="mt-6 space-y-6">
|
||||
<.form_section title={gettext("Personal Data")}>
|
||||
<.live_component
|
||||
module={MvWeb.MemberFieldLive.IndexComponent}
|
||||
id="member-fields-component"
|
||||
settings={@settings}
|
||||
/>
|
||||
</.form_section>
|
||||
|
||||
<.form_section title={gettext("Individual Datafields")}>
|
||||
<.live_component
|
||||
module={MvWeb.CustomFieldLive.IndexComponent}
|
||||
id="custom-fields-component"
|
||||
actor={@current_user}
|
||||
/>
|
||||
</.form_section>
|
||||
</div>
|
||||
|
||||
<%!-- Edit mode: only the active section, no section title/card wrapper --%>
|
||||
<div :if={@active_editing_section == :member_fields} class="mt-6">
|
||||
<.live_component
|
||||
:if={@active_editing_section != :custom_fields}
|
||||
module={MvWeb.MemberFieldLive.IndexComponent}
|
||||
id="member-fields-component"
|
||||
settings={@settings}
|
||||
/>
|
||||
</.form_section>
|
||||
</div>
|
||||
|
||||
<.form_section title={gettext("Custom fields")}>
|
||||
<div :if={@active_editing_section == :custom_fields} class="mt-6">
|
||||
<.live_component
|
||||
:if={@active_editing_section != :member_fields}
|
||||
module={MvWeb.CustomFieldLive.IndexComponent}
|
||||
id="custom-fields-component"
|
||||
actor={@current_user}
|
||||
/>
|
||||
</.form_section>
|
||||
</div>
|
||||
</Layouts.app>
|
||||
"""
|
||||
end
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ defmodule MvWeb.MemberFieldLive.IndexComponent do
|
|||
|
||||
~H"""
|
||||
<div id={@id}>
|
||||
<p class="text-sm text-base-content/70 mb-4">
|
||||
<p :if={!@show_form} class="text-sm text-base-content/70 mb-4">
|
||||
{gettext(
|
||||
"These fields are neccessary for MILA to handle member identification and payment calculations in the future. Thus you cannot delete these fields but hide them in the member overview."
|
||||
)}
|
||||
|
|
@ -100,8 +100,8 @@ defmodule MvWeb.MemberFieldLive.IndexComponent do
|
|||
|
||||
@impl true
|
||||
def update(assigns, socket) do
|
||||
# Track previous show_form state to detect when form is closed
|
||||
previous_show_form = Map.get(socket.assigns, :show_form, false)
|
||||
# Use socket state so send_update(show_form: false) is the only trigger for "form closed"
|
||||
previous_show_form = socket.assigns[:show_form] || false
|
||||
|
||||
# If show_form is explicitly provided in assigns, reset editing state
|
||||
socket =
|
||||
|
|
@ -113,20 +113,22 @@ defmodule MvWeb.MemberFieldLive.IndexComponent do
|
|||
socket
|
||||
end
|
||||
|
||||
# Detect when form is closed (show_form changes from true to false)
|
||||
new_show_form = Map.get(assigns, :show_form, false)
|
||||
socket =
|
||||
socket
|
||||
|> assign(assigns)
|
||||
|> assign_new(:settings, fn -> get_settings() end)
|
||||
|> assign_new(:show_form, fn -> false end)
|
||||
|> assign_new(:form_id, fn -> "member-field-form-new" end)
|
||||
|> assign_new(:editing_member_field, fn -> nil end)
|
||||
|
||||
if previous_show_form and not new_show_form do
|
||||
# Detect form closed only from final socket state (not from assigns alone)
|
||||
current_show_form = socket.assigns[:show_form] || false
|
||||
|
||||
if previous_show_form and not current_show_form do
|
||||
send(self(), {:editing_section_changed, nil})
|
||||
end
|
||||
|
||||
{:ok,
|
||||
socket
|
||||
|> assign(assigns)
|
||||
|> assign_new(:settings, fn -> get_settings() end)
|
||||
|> assign_new(:show_form, fn -> false end)
|
||||
|> assign_new(:form_id, fn -> "member-field-form-new" end)
|
||||
|> assign_new(:editing_member_field, fn -> nil end)}
|
||||
{:ok, socket}
|
||||
end
|
||||
|
||||
@impl true
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ defmodule MvWeb.UserLive.Form do
|
|||
/>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
|
||||
<!-- Password Section -->
|
||||
<div class="mt-6">
|
||||
<label class="flex items-center space-x-2">
|
||||
|
|
@ -116,7 +116,7 @@ defmodule MvWeb.UserLive.Form do
|
|||
required
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
|
||||
|
||||
<!-- Only show password confirmation for new users (register_with_password) -->
|
||||
<%= if !@user do %>
|
||||
<.input
|
||||
|
|
@ -167,7 +167,7 @@ defmodule MvWeb.UserLive.Form do
|
|||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Member Linking Section (admin only: only admins can link/unlink users to members) -->
|
||||
<%= if @can_manage_member_linking do %>
|
||||
<div class="mt-6">
|
||||
|
|
|
|||
|
|
@ -71,6 +71,10 @@ defmodule MvWeb.CustomFieldLive.DeletionTest do
|
|||
# Modal should be visible
|
||||
assert has_element?(view, "#delete-custom-field-modal")
|
||||
|
||||
# Edit mode: section titles must not reappear when modal opens (regression)
|
||||
refute has_element?(view, "h2", "Member fields")
|
||||
refute has_element?(view, "h2", "Custom fields")
|
||||
|
||||
# Should show correct member count (1 member)
|
||||
assert render(view) =~ "1 member has a value assigned for this custom field"
|
||||
|
||||
|
|
|
|||
|
|
@ -83,6 +83,21 @@ defmodule MvWeb.MemberFieldLive.IndexComponentTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "edit mode visibility" do
|
||||
test "clicking member field row shows only form, no section titles", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/datafields")
|
||||
|
||||
# Row click is on the first td (no col_click); click that cell to open edit form
|
||||
view
|
||||
|> element("tr#member_field-first_name td:first-child")
|
||||
|> render_click()
|
||||
|
||||
assert has_element?(view, "#member-field-form-first_name")
|
||||
refute has_element?(view, "h2", "Custom fields")
|
||||
refute has_element?(view, "h2", "Member fields")
|
||||
end
|
||||
end
|
||||
|
||||
describe "required fields" do
|
||||
setup do
|
||||
{:ok, settings} = Membership.get_settings()
|
||||
|
|
|
|||
|
|
@ -29,9 +29,8 @@ defmodule MvWeb.StatisticsLiveTest do
|
|||
test "page shows overview of all relevant years without year selector", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/statistics")
|
||||
|
||||
# No year dropdown: single select for year should not be present as main control
|
||||
assert html =~ "Overview" or html =~ "overview"
|
||||
# table header or legend
|
||||
# Page shows multi-year data (member numbers by year) and year column; no single-year selector as main control
|
||||
assert html =~ "Member numbers by year"
|
||||
assert html =~ "Year"
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -123,13 +123,17 @@ defmodule MvWeb.UserLive.IndexTest do
|
|||
{:ok, index_view, _html} = live(conn, "/users")
|
||||
assert render(index_view) =~ "delete-me@example.com"
|
||||
|
||||
# Navigate to user show and trigger delete from Danger zone
|
||||
# Navigate to user show, open delete modal, then confirm in modal (WCAG modal pattern)
|
||||
{:ok, show_view, _html} = live(conn, "/users/#{user.id}")
|
||||
|
||||
show_view
|
||||
|> element("[data-testid=user-delete]")
|
||||
|> render_click()
|
||||
|
||||
show_view
|
||||
|> element("#delete-user-modal button", "Delete")
|
||||
|> render_click()
|
||||
|
||||
# Should redirect to index
|
||||
assert_redirect(show_view, "/users")
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue