diff --git a/CODE_GUIDELINES.md b/CODE_GUIDELINES.md
index 68e7887..d4769f3 100644
--- a/CODE_GUIDELINES.md
+++ b/CODE_GUIDELINES.md
@@ -61,7 +61,7 @@ We are building a membership management system (Mila) using the following techno
8. [Accessibility Guidelines](#8-accessibility-guidelines)
**Related documents:**
-- **UI / UX:** [`DESIGN_DUIDELINES.md`](../DESIGN_DUIDELINES.md) defines visual and interaction consistency: use of CoreComponents (no raw DaisyUI in views), page skeleton (`<.header>`, `mt-6 space-y-6`), typography, buttons, forms, tables, flash/toast, and microcopy (e.g. German "du" and glossary). Follow "components first" and semantic variants instead of hard-coded colors.
+- **UI / UX:** [`DESIGN_DUIDELINES.md`](../DESIGN_DUIDELINES.md) defines visual and interaction consistency: use of CoreComponents (no raw DaisyUI in views), page skeleton (`<.header>`, `mt-6 space-y-6`), **Back button left in header for edit/new forms** (§2.2), typography, buttons, forms, tables, flash/toast, and microcopy (e.g. German "du" and glossary). Follow "components first" and semantic variants instead of hard-coded colors.
---
diff --git a/DESIGN_DUIDELINES.md b/DESIGN_DUIDELINES.md
index e3faf50..fc3acac 100644
--- a/DESIGN_DUIDELINES.md
+++ b/DESIGN_DUIDELINES.md
@@ -46,19 +46,35 @@ Every authenticated page should follow the same structure:
**MUST:** Use `<.header>` on every page (except login/public pages).
**SHOULD:** Put short explanations into `<:subtitle>` rather than sprinkling random text blocks.
-**Template:**
+### 2.2 Edit/New form header: Back button left (mandatory)
+
+For LiveViews that render an edit or new form (e.g. member, group, role, user, custom field, membership fee type):
+
+- **MUST:** Provide a **Back** button on the **left** side of the header using the `<:leading>` slot (same as data fields: Back left, title next, primary action on the right).
+- **MUST:** Use the same pattern everywhere: Back button with `variant="neutral"`, arrow-left icon, and label “Back”. It navigates to the previous context (e.g. detail page or index) via a `return_path`-style helper.
+- **SHOULD:** Place the primary action (e.g. “Save”) in `<:actions>` on the right.
+- **Rationale:** Users expect a consistent way to leave the form without submitting; Back left matches the data fields edit view and keeps primary actions on the right.
+
+**Template for form pages:**
```heex
<.header>
- Title
- <:subtitle>Short explanation of what the page is for.
+ <:leading>
+ <.button navigate={return_path(@return_to, @resource)} variant="neutral">
+ <.icon name="hero-arrow-left" class="size-4" />
+ {gettext("Back")}
+
+
+ Page title (e.g. “Edit Member” or “New User”)
+ <:subtitle>Short explanation.
<:actions>
- <.button variant="primary" navigate={...}>Primary action
+ <.button phx-disable-with={gettext("Saving...")} variant="primary" type="submit">
+ {gettext("Save")}
+
+```
-
-
-
+If the `<.header>` is outside the `<.form>`, the submit button must reference the form via the `form` attribute (e.g. `form="user-form"`).
## 3) Typography (system)
diff --git a/lib/mv_web/components/core_components.ex b/lib/mv_web/components/core_components.ex
index 83d506a..85c26c7 100644
--- a/lib/mv_web/components/core_components.ex
+++ b/lib/mv_web/components/core_components.ex
@@ -111,7 +111,7 @@ defmodule MvWeb.CoreComponents do
<.button variant="ghost" size="sm">Edit
<.button disabled={true}>Disabled
"""
- attr :rest, :global, include: ~w(href navigate patch method data-testid)
+ attr :rest, :global, include: ~w(href navigate patch method data-testid form)
attr :variant, :string,
values: ~w(primary secondary neutral ghost outline danger link icon),
@@ -633,17 +633,24 @@ defmodule MvWeb.CoreComponents do
@doc """
Renders a header with title.
+
+ Use the `:leading` slot for the Back button (left side, consistent with data fields).
+ Use the `:actions` slot for primary actions (e.g. Save) on the right.
"""
attr :class, :string, default: nil
+ slot :leading, doc: "Content on the left (e.g. Back button)"
slot :inner_block, required: true
slot :subtitle
slot :actions
def header(assigns) do
~H"""
-
-
+
+
+ {render_slot(@leading)}
+
+
{render_slot(@inner_block)}
@@ -651,7 +658,9 @@ defmodule MvWeb.CoreComponents do
{render_slot(@subtitle)}
- {render_slot(@actions)}
+
+ {render_slot(@actions)}
+
"""
end
diff --git a/lib/mv_web/live/components/field_visibility_dropdown_component.ex b/lib/mv_web/live/components/field_visibility_dropdown_component.ex
index a8e8d45..58777da 100644
--- a/lib/mv_web/live/components/field_visibility_dropdown_component.ex
+++ b/lib/mv_web/live/components/field_visibility_dropdown_component.ex
@@ -188,7 +188,7 @@ defmodule MvWeb.Components.FieldVisibilityDropdownComponent do
defp find_custom_field_name(id, _field_string, custom_fields) do
case Enum.find(custom_fields, fn cf -> to_string(cf.id) == id end) do
- nil -> gettext("Custom Field %{id}", id: id)
+ nil -> gettext("Datafield %{id}", id: id)
custom_field -> custom_field.name
end
end
diff --git a/lib/mv_web/live/components/member_filter_component.ex b/lib/mv_web/live/components/member_filter_component.ex
index b837bc0..4ee72d3 100644
--- a/lib/mv_web/live/components/member_filter_component.ex
+++ b/lib/mv_web/live/components/member_filter_component.ex
@@ -252,7 +252,7 @@ defmodule MvWeb.Components.MemberFilterComponent do
0} class="mb-2">
- {gettext("Custom Fields")}
+ {gettext("Individual datafields")}
{gettext(
- "Deleting this data field cannot be undone. All custom field values for this field will be permanently removed."
+ "Deleting this data field cannot be undone. All datafield values for this field will be permanently removed."
)}
<.button
diff --git a/lib/mv_web/live/custom_field_live/index_component.ex b/lib/mv_web/live/custom_field_live/index_component.ex
index b0e9862..3b70c3d 100644
--- a/lib/mv_web/live/custom_field_live/index_component.ex
+++ b/lib/mv_web/live/custom_field_live/index_component.ex
@@ -158,7 +158,7 @@ defmodule MvWeb.CustomFieldLive.IndexComponent do
phx-target={@myself}
disabled={@slug_confirmation != @custom_field_to_delete.slug}
>
- {gettext("Delete Custom Field and All Values")}
+ {gettext("Delete Datafields and All Values")}
diff --git a/lib/mv_web/live/global_settings_live.ex b/lib/mv_web/live/global_settings_live.ex
index 485601a..bb8eb32 100644
--- a/lib/mv_web/live/global_settings_live.ex
+++ b/lib/mv_web/live/global_settings_live.ex
@@ -95,7 +95,7 @@ defmodule MvWeb.GlobalSettingsLive do
<.button phx-disable-with={gettext("Saving...")} variant="primary">
- {gettext("Save Settings")}
+ {gettext("Save Name")}
diff --git a/lib/mv_web/live/group_live/form.ex b/lib/mv_web/live/group_live/form.ex
index 490214f..2e79a7f 100644
--- a/lib/mv_web/live/group_live/form.ex
+++ b/lib/mv_web/live/group_live/form.ex
@@ -79,12 +79,14 @@ defmodule MvWeb.GroupLive.Form do
<.form for={@form} id="group-form" phx-change="validate" phx-submit="save">
<.header>
- {@page_title}
- <:actions>
+ <:leading>
<.button navigate={return_path(@return_to, @group)} variant="neutral">
<.icon name="hero-arrow-left" class="size-4" />
{gettext("Back")}
+
+ {@page_title}
+ <:actions>
<.button phx-disable-with={gettext("Saving...")} variant="primary" type="submit">
{gettext("Save")}
diff --git a/lib/mv_web/live/group_live/show.ex b/lib/mv_web/live/group_live/show.ex
index d970f2a..dbc0523 100644
--- a/lib/mv_web/live/group_live/show.ex
+++ b/lib/mv_web/live/group_live/show.ex
@@ -50,7 +50,7 @@ defmodule MvWeb.GroupLive.Show do
end
end
- defp load_group_by_slug(socket, slug, actor, params \\ %{}) do
+ defp load_group_by_slug(socket, slug, actor, params) do
# Load group with members and member_count
# Using explicit load ensures efficient preloading of members relationship
require Ash.Query
@@ -92,8 +92,7 @@ defmodule MvWeb.GroupLive.Show do
~H"""
<.header>
- {@group.name}
- <:actions>
+ <:leading>
<.button
navigate={~p"/groups"}
variant="neutral"
@@ -102,13 +101,16 @@ defmodule MvWeb.GroupLive.Show do
<.icon name="hero-arrow-left" class="size-4" />
{gettext("Back")}
+
+ {@group.name}
+ <:actions>
<%= if can?(@current_user, :update, @group) do %>
<.button
variant="primary"
navigate={~p"/groups/#{@group.slug}/edit"}
data-testid="group-show-edit-btn"
>
- {gettext("Edit group")}
+ <.icon name="hero-pencil-square" /> {gettext("Edit group")}
<% end %>
diff --git a/lib/mv_web/live/member_live/form.ex b/lib/mv_web/live/member_live/form.ex
index 1875205..d0eaabf 100644
--- a/lib/mv_web/live/member_live/form.ex
+++ b/lib/mv_web/live/member_live/form.ex
@@ -39,16 +39,18 @@ defmodule MvWeb.MemberLive.Form do
<.form for={@form} id="member-form" phx-change="validate" phx-submit="save">
<.header>
+ <:leading>
+ <.button navigate={return_path(@return_to, @member)} variant="neutral">
+ <.icon name="hero-arrow-left" class="size-4" />
+ {gettext("Back")}
+
+
<%= if @member do %>
{MvWeb.Helpers.MemberHelpers.display_name(@member)}
<% else %>
{gettext("New Member")}
<% end %>
<:actions>
- <.button navigate={return_path(@return_to, @member)} variant="neutral">
- <.icon name="hero-arrow-left" class="size-4" />
- {gettext("Back")}
-
<.button phx-disable-with={gettext("Saving...")} variant="primary" type="submit">
{gettext("Save")}
@@ -408,32 +410,33 @@ defmodule MvWeb.MemberLive.Form do
member = socket.assigns.member
actor = current_actor(socket)
- if is_nil(member) do
- {:noreply, put_flash(socket, :error, gettext("Member not found"))}
- else
- if to_string(id) != to_string(member.id) do
+ cond do
+ is_nil(member) ->
{:noreply, put_flash(socket, :error, gettext("Member not found"))}
- else
- case Ash.destroy(member, actor: actor) do
- :ok ->
- {:noreply,
- socket
- |> put_flash(:success, gettext("Member deleted successfully"))
- |> push_navigate(to: ~p"/members")}
- {:error, %Ash.Error.Forbidden{}} ->
- {:noreply,
- put_flash(
- socket,
- :error,
- gettext("You do not have permission to delete this member")
- )}
+ to_string(id) != to_string(member.id) ->
+ {:noreply, put_flash(socket, :error, gettext("Member not found"))}
- {:error, error} ->
- Logger.warning("Member delete failed: member_id=#{member.id} error=#{inspect(error)}")
- {:noreply, put_flash(socket, :error, format_destroy_error(error))}
- end
- end
+ true ->
+ handle_member_delete_destroy(socket, member, actor)
+ end
+ end
+
+ defp handle_member_delete_destroy(socket, member, actor) do
+ case Ash.destroy(member, actor: actor) do
+ :ok ->
+ {:noreply,
+ socket
+ |> put_flash(:success, gettext("Member deleted successfully"))
+ |> push_navigate(to: ~p"/members")}
+
+ {:error, %Ash.Error.Forbidden{}} ->
+ {:noreply,
+ put_flash(socket, :error, gettext("You do not have permission to delete this member"))}
+
+ {:error, error} ->
+ Logger.warning("Member delete failed: member_id=#{member.id} error=#{inspect(error)}")
+ {:noreply, put_flash(socket, :error, format_destroy_error(error))}
end
end
diff --git a/lib/mv_web/live/member_live/show.ex b/lib/mv_web/live/member_live/show.ex
index 63349be..ecd2d51 100644
--- a/lib/mv_web/live/member_live/show.ex
+++ b/lib/mv_web/live/member_live/show.ex
@@ -31,8 +31,7 @@ defmodule MvWeb.MemberLive.Show do
~H"""
<.header>
- {MvWeb.Helpers.MemberHelpers.display_name(@member)}
- <:actions>
+ <:leading>
<.button
navigate={~p"/members?highlight=#{@member.id}"}
variant="neutral"
@@ -41,13 +40,16 @@ defmodule MvWeb.MemberLive.Show do
<.icon name="hero-arrow-left" class="size-4" />
{gettext("Back")}
+
+ {MvWeb.Helpers.MemberHelpers.display_name(@member)}
+ <:actions>
<%= if can?(@current_user, :update, @member) do %>
<.button
variant="primary"
navigate={~p"/members/#{@member}/edit?return_to=show"}
data-testid="member-edit"
>
- {gettext("Edit member")}
+ <.icon name="hero-pencil-square" /> {gettext("Edit member")}
<% end %>
diff --git a/lib/mv_web/live/membership_fee_type_live/form.ex b/lib/mv_web/live/membership_fee_type_live/form.ex
index ca61e19..237b4b4 100644
--- a/lib/mv_web/live/membership_fee_type_live/form.ex
+++ b/lib/mv_web/live/membership_fee_type_live/form.ex
@@ -27,10 +27,26 @@ defmodule MvWeb.MembershipFeeTypeLive.Form do
~H"""
<.header>
+ <:leading>
+ <.button navigate={return_path(@return_to, @membership_fee_type)} variant="neutral">
+ <.icon name="hero-arrow-left" class="size-4" />
+ {gettext("Back")}
+
+
{@page_title}
<:subtitle>
{gettext("Use this form to manage membership fee types in your database.")}
+ <:actions>
+ <.button
+ form="membership-fee-type-form"
+ phx-disable-with={gettext("Saving...")}
+ variant="primary"
+ type="submit"
+ >
+ {gettext("Save")}
+
+
<.form
diff --git a/lib/mv_web/live/role_live/form.ex b/lib/mv_web/live/role_live/form.ex
index 684e695..e066555 100644
--- a/lib/mv_web/live/role_live/form.ex
+++ b/lib/mv_web/live/role_live/form.ex
@@ -23,13 +23,15 @@ defmodule MvWeb.RoleLive.Form do
<.form class="max-w-xl" for={@form} id="role-form" phx-change="validate" phx-submit="save">
<.header>
- {@page_title}
- <:subtitle>{gettext("Use this form to manage roles in your database.")}
- <:actions>
+ <:leading>
<.button navigate={return_path(@return_to, @role)} variant="neutral">
<.icon name="hero-arrow-left" class="size-4" />
{gettext("Back")}
+
+ {@page_title}
+ <:subtitle>{gettext("Use this form to manage roles in your database.")}
+ <:actions>
<.button phx-disable-with={gettext("Saving...")} variant="primary" type="submit">
{gettext("Save")}
diff --git a/lib/mv_web/live/role_live/show.ex b/lib/mv_web/live/role_live/show.ex
index 8b615b6..4f36eca 100644
--- a/lib/mv_web/live/role_live/show.ex
+++ b/lib/mv_web/live/role_live/show.ex
@@ -161,10 +161,7 @@ defmodule MvWeb.RoleLive.Show do
~H"""
<.header>
- {gettext("Role")} {@role.name}
- <:subtitle>{gettext("Role details and permissions.")}
-
- <:actions>
+ <:leading>
<.button
navigate={~p"/admin/roles"}
variant="neutral"
@@ -173,13 +170,18 @@ defmodule MvWeb.RoleLive.Show do
<.icon name="hero-arrow-left" class="size-4" />
{gettext("Back")}
+
+ {gettext("Role")} {@role.name}
+ <:subtitle>{gettext("Role details and permissions.")}
+
+ <:actions>
<%= if can?(@current_user, :update, Mv.Authorization.Role) do %>
<.button
variant="primary"
navigate={~p"/admin/roles/#{@role}/edit"}
data-testid="role-show-edit-btn"
>
- {gettext("Edit role")}
+ <.icon name="hero-pencil-square" /> {gettext("Edit role")}
<% end %>
diff --git a/lib/mv_web/live/user_live/form.ex b/lib/mv_web/live/user_live/form.ex
index 34defe1..f7c440d 100644
--- a/lib/mv_web/live/user_live/form.ex
+++ b/lib/mv_web/live/user_live/form.ex
@@ -46,8 +46,24 @@ defmodule MvWeb.UserLive.Form do
~H"""
<.header>
+ <:leading>
+ <.button navigate={return_path(@return_to, @user)} variant="neutral">
+ <.icon name="hero-arrow-left" class="size-4" />
+ {gettext("Back")}
+
+
{@page_title}
<:subtitle>{gettext("Use this form to manage user records in your database.")}
+ <:actions>
+ <.button
+ form="user-form"
+ phx-disable-with={gettext("Saving...")}
+ variant="primary"
+ type="submit"
+ >
+ {gettext("Save User")}
+
+
<.form class="max-w-xl" for={@form} id="user-form" phx-change="validate" phx-submit="save">
@@ -300,7 +316,8 @@ defmodule MvWeb.UserLive.Form do
phx-click="delete"
phx-value-id={@user.id}
data-confirm={
- gettext("Are you sure you want to delete the user %{email}? This action cannot be undone.",
+ gettext(
+ "Are you sure you want to delete the user %{email}? This action cannot be undone.",
email: @user.email
)
}
@@ -442,36 +459,18 @@ defmodule MvWeb.UserLive.Form do
user = socket.assigns.user
actor = current_actor(socket)
- if is_nil(user) do
- {:noreply, put_flash(socket, :error, gettext("User not found"))}
- else
- if to_string(id) != to_string(user.id) do
+ cond do
+ is_nil(user) ->
{:noreply, put_flash(socket, :error, gettext("User not found"))}
- else
- if Mv.Helpers.SystemActor.system_user?(user) do
- {:noreply,
- put_flash(socket, :error, gettext("System user cannot be deleted."))}
- else
- case Ash.destroy(user, domain: Mv.Accounts, actor: actor) do
- :ok ->
- {:noreply,
- socket
- |> put_flash(:success, gettext("User deleted successfully"))
- |> push_navigate(to: ~p"/users")}
- {:error, %Ash.Error.Forbidden{}} ->
- {:noreply,
- put_flash(
- socket,
- :error,
- gettext("You do not have permission to delete this user")
- )}
+ to_string(id) != to_string(user.id) ->
+ {:noreply, put_flash(socket, :error, gettext("User not found"))}
- {:error, error} ->
- {:noreply, put_flash(socket, :error, format_ash_error(error))}
- end
- end
- end
+ Mv.Helpers.SystemActor.system_user?(user) ->
+ {:noreply, put_flash(socket, :error, gettext("System user cannot be deleted."))}
+
+ true ->
+ handle_user_delete_destroy(socket, user, actor)
end
end
@@ -585,6 +584,23 @@ defmodule MvWeb.UserLive.Form do
{:noreply, socket}
end
+ defp handle_user_delete_destroy(socket, user, actor) do
+ case Ash.destroy(user, domain: Mv.Accounts, actor: actor) do
+ :ok ->
+ {:noreply,
+ socket
+ |> put_flash(:success, gettext("User deleted successfully"))
+ |> push_navigate(to: ~p"/users")}
+
+ {:error, %Ash.Error.Forbidden{}} ->
+ {:noreply,
+ put_flash(socket, :error, gettext("You do not have permission to delete this user"))}
+
+ {:error, error} ->
+ {:noreply, put_flash(socket, :error, format_ash_error(error))}
+ end
+ end
+
defp handle_member_linking(socket, user, actor) do
result = perform_member_link_action(socket, user, actor)
diff --git a/lib/mv_web/live/user_live/index.ex b/lib/mv_web/live/user_live/index.ex
index d72c1fd..4858202 100644
--- a/lib/mv_web/live/user_live/index.ex
+++ b/lib/mv_web/live/user_live/index.ex
@@ -7,15 +7,10 @@ defmodule MvWeb.UserLive.Index do
- Sort users by email (default)
- Navigate to user details (row click) and edit from details header
- Delete only via Danger zone on user show/edit
- - Bulk selection for future batch operations
## Relationships
Displays linked member information when a user is connected to a member account.
- ## Events
- - `select_user` - Toggle individual user selection
- - `select_all` - Toggle selection of all visible users
-
## Security
User deletion requires admin permissions (enforced by Ash policies).
"""
@@ -42,24 +37,7 @@ defmodule MvWeb.UserLive.Index do
|> assign(:page_title, gettext("Listing Users"))
|> assign(:sort_field, :email)
|> assign(:sort_order, :asc)
- |> assign(:users, sorted)
- |> assign(:selected_users, [])}
- end
-
- # Selects one user in the list of users
- @impl true
- def handle_event("select_user", %{"id" => id}, socket) do
- # Normalize ID to string for consistent comparison
- id_str = to_string(id)
-
- selected =
- if id_str in socket.assigns.selected_users do
- List.delete(socket.assigns.selected_users, id_str)
- else
- [id_str | socket.assigns.selected_users]
- end
-
- {:noreply, assign(socket, :selected_users, selected)}
+ |> assign(:users, sorted)}
end
# Sorts the list of users according to a field, when you click on the column header
@@ -86,24 +64,6 @@ defmodule MvWeb.UserLive.Index do
|> assign(:users, sorted_users)}
end
- # Selects all users in the list of users
- @impl true
- def handle_event("select_all", _params, socket) do
- users = socket.assigns.users
-
- # Normalize IDs to strings for consistent comparison
- all_ids = Enum.map(users, &to_string(&1.id))
-
- selected =
- if Enum.sort(socket.assigns.selected_users) == Enum.sort(all_ids) do
- []
- else
- all_ids
- end
-
- {:noreply, assign(socket, :selected_users, selected)}
- end
-
defp toggle_order(:asc), do: :desc
defp toggle_order(:desc), do: :asc
defp sort_fun(:asc), do: &<=/2
diff --git a/lib/mv_web/live/user_live/index.html.heex b/lib/mv_web/live/user_live/index.html.heex
index 7ffa0e3..86f0ab7 100644
--- a/lib/mv_web/live/user_live/index.html.heex
+++ b/lib/mv_web/live/user_live/index.html.heex
@@ -19,33 +19,6 @@
sort_field={@sort_field}
sort_order={@sort_order}
>
- <:col
- :let={user}
- label={
- ~H"""
- <.input
- type="checkbox"
- name="select_all"
- phx-click="select_all"
- checked={Enum.sort(@selected_users) == Enum.map(@users, &to_string(&1.id)) |> Enum.sort()}
- aria-label={gettext("Select all users")}
- role="checkbox"
- />
- """
- }
- >
- <.input
- type="checkbox"
- name={to_string(user.id)}
- phx-click="select_user"
- phx-value-id={to_string(user.id)}
- checked={to_string(user.id) in @selected_users}
- phx-capture-click
- phx-stop-propagation
- aria-label={gettext("Select user")}
- role="checkbox"
- />
-
<:col
:let={user}
sort_field={:email}
diff --git a/lib/mv_web/live/user_live/show.ex b/lib/mv_web/live/user_live/show.ex
index a77a1c4..d7a12b2 100644
--- a/lib/mv_web/live/user_live/show.ex
+++ b/lib/mv_web/live/user_live/show.ex
@@ -34,14 +34,20 @@ defmodule MvWeb.UserLive.Show do
~H"""
<.header>
+ <:leading>
+ <.button
+ navigate={~p"/users"}
+ variant="neutral"
+ aria-label={gettext("Back to users list")}
+ >
+ <.icon name="hero-arrow-left" class="size-4" />
+ {gettext("Back")}
+
+
{gettext("User")} {@user.email}
<:subtitle>{gettext("This is a user record from your database.")}
<:actions>
- <.button navigate={~p"/users"} variant="neutral" aria-label={gettext("Back to users list")}>
- <.icon name="hero-arrow-left" />
- {gettext("Back to users list")}
-
<%= if can?(@current_user, :update, @user) do %>
<.button
variant="primary"
@@ -99,7 +105,8 @@ defmodule MvWeb.UserLive.Show do
phx-click="delete"
phx-value-id={@user.id}
data-confirm={
- gettext("Are you sure you want to delete the user %{email}? This action cannot be undone.",
+ gettext(
+ "Are you sure you want to delete the user %{email}? This action cannot be undone.",
email: @user.email
)
}
@@ -141,33 +148,32 @@ defmodule MvWeb.UserLive.Show do
user = socket.assigns.user
actor = current_actor(socket)
- if to_string(id) != to_string(user.id) do
- {:noreply, put_flash(socket, :error, gettext("User not found"))}
- else
- if Mv.Helpers.SystemActor.system_user?(user) do
+ cond do
+ to_string(id) != to_string(user.id) ->
+ {:noreply, put_flash(socket, :error, gettext("User not found"))}
+
+ Mv.Helpers.SystemActor.system_user?(user) ->
+ {:noreply, put_flash(socket, :error, gettext("System user cannot be deleted."))}
+
+ true ->
+ handle_user_delete_destroy(socket, user, actor)
+ end
+ end
+
+ defp handle_user_delete_destroy(socket, user, actor) do
+ case Ash.destroy(user, domain: Mv.Accounts, actor: actor) do
+ :ok ->
{:noreply,
- put_flash(socket, :error, gettext("System user cannot be deleted."))}
- else
- case Ash.destroy(user, domain: Mv.Accounts, actor: actor) do
- :ok ->
- {:noreply,
- socket
- |> put_flash(:success, gettext("User deleted successfully"))
- |> push_navigate(to: ~p"/users")}
+ socket
+ |> put_flash(:success, gettext("User deleted successfully"))
+ |> push_navigate(to: ~p"/users")}
- {:error, %Ash.Error.Forbidden{}} ->
- {:noreply,
- put_flash(
- socket,
- :error,
- gettext("You do not have permission to delete this user")
- )}
+ {:error, %Ash.Error.Forbidden{}} ->
+ {:noreply,
+ put_flash(socket, :error, gettext("You do not have permission to delete this user"))}
- {:error, error} ->
- {:noreply,
- put_flash(socket, :error, format_ash_error(error))}
- end
- end
+ {:error, error} ->
+ {:noreply, put_flash(socket, :error, format_ash_error(error))}
end
end
end
diff --git a/priv/gettext/de/LC_MESSAGES/default.po b/priv/gettext/de/LC_MESSAGES/default.po
index 4e6c888..1bd57e1 100644
--- a/priv/gettext/de/LC_MESSAGES/default.po
+++ b/priv/gettext/de/LC_MESSAGES/default.po
@@ -18,9 +18,6 @@ msgstr "Aktionen"
#: lib/mv_web/live/membership_fee_settings_live.ex
#: lib/mv_web/live/membership_fee_type_live/index.ex
-#: lib/mv_web/live/role_live/index.html.heex
-#: lib/mv_web/live/role_live/show.ex
-#: lib/mv_web/live/user_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "Are you sure?"
msgstr "Bist du sicher?"
@@ -38,11 +35,8 @@ msgstr "Verbindung wird wiederhergestellt"
msgid "City"
msgstr "Stadt"
-#: lib/mv_web/live/custom_field_live/index_component.ex
#: lib/mv_web/live/group_live/show.ex
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
-#: lib/mv_web/live/role_live/index.html.heex
-#: lib/mv_web/live/user_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "Delete"
msgstr "Löschen"
@@ -100,8 +94,6 @@ msgid "New Member"
msgstr "Neues Mitglied"
#: lib/mv_web/live/member_live/index.html.heex
-#: lib/mv_web/live/role_live/index.html.heex
-#: lib/mv_web/live/user_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "Show"
msgstr "Anzeigen"
@@ -480,16 +472,6 @@ msgstr "Passwort"
msgid "Password requirements"
msgstr "Passwort-Anforderungen"
-#: lib/mv_web/live/user_live/index.html.heex
-#, elixir-autogen, elixir-format
-msgid "Select all users"
-msgstr "Alle Benutzer*innen auswählen"
-
-#: lib/mv_web/live/user_live/index.html.heex
-#, elixir-autogen, elixir-format
-msgid "Select user"
-msgstr "Benutzer*in auswählen"
-
#: lib/mv_web/live/user_live/form.ex
#, elixir-autogen, elixir-format
msgid "Set Password"
@@ -605,7 +587,6 @@ msgstr "E-Mail kann nicht aktualisiert werden: Diese E-Mail-Adresse ist bereits
msgid "This email is already linked to a different OIDC account. Cannot link multiple OIDC providers to the same account."
msgstr "Diese E-Mail-Adresse ist bereits mit einem anderen OIDC-Konto verknüpft. Es können nicht mehrere OIDC-Provider mit demselben Konto verknüpft werden."
-#: lib/mv_web/live/components/member_filter_component.ex
#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show.ex
#, elixir-autogen, elixir-format
@@ -624,11 +605,6 @@ msgstr[1] "%{count} Mitglieder haben Werte für dieses benutzerdefinierte Feld z
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_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_component.ex
#, elixir-autogen, elixir-format
msgid "Enter the text above to confirm"
@@ -662,7 +638,6 @@ msgstr "Vereinsdaten"
msgid "Manage global settings for the association."
msgstr "Passe übergreifende Einstellungen für den Verein an."
-#: lib/mv_web/live/global_settings_live.ex
#: lib/mv_web/live/membership_fee_settings_live.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Save Settings"
@@ -785,8 +760,11 @@ msgstr "Adresse"
#: lib/mv_web/live/member_field_live/form_component.ex
#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show.ex
+#: lib/mv_web/live/membership_fee_type_live/form.ex
#: lib/mv_web/live/role_live/form.ex
#: lib/mv_web/live/role_live/show.ex
+#: lib/mv_web/live/user_live/form.ex
+#: lib/mv_web/live/user_live/show.ex
#, elixir-autogen, elixir-format
msgid "Back"
msgstr "Zurück"
@@ -821,6 +799,7 @@ msgstr "Persönliche Daten"
#: lib/mv_web/live/group_live/form.ex
#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
+#: lib/mv_web/live/membership_fee_type_live/form.ex
#: lib/mv_web/live/role_live/form.ex
#, elixir-autogen, elixir-format
msgid "Save"
@@ -964,11 +943,6 @@ msgstr "Unbezahlt"
msgid "Yearly"
msgstr "jährlich"
-#: lib/mv_web/live/components/field_visibility_dropdown_component.ex
-#, elixir-autogen, elixir-format
-msgid "Custom Field %{id}"
-msgstr "Benutzerdefiniertes Feld %{id}"
-
#: lib/mv_web/live/member_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "Last name"
@@ -1604,17 +1578,11 @@ msgstr "Datenfeld speichern"
msgid "Back to roles list"
msgstr "Zurück zur Rollen-Liste"
-#: lib/mv_web/live/role_live/index.html.heex
-#, elixir-autogen, elixir-format
-msgid "Cannot delete system role"
-msgstr "System-Rolle kann nicht gelöscht werden"
-
#: lib/mv_web/live/role_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "Custom"
msgstr "Benutzerdefiniert"
-#: lib/mv_web/live/role_live/index.ex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format
msgid "Failed to delete role: %{error}"
@@ -1631,7 +1599,6 @@ msgstr "Rollen auflisten"
msgid "Manage user roles and their permission sets."
msgstr "Verwalte Benutzer*innen-Rollen und ihre Berechtigungssätze."
-#: lib/mv_web/live/role_live/index.ex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format
msgid "Cannot delete role. %{count} user(s) are still assigned to this role. Please assign them to another role first."
@@ -1642,11 +1609,6 @@ msgstr "Rolle kann nicht gelöscht werden. %{count} Benutzer*in(nen) sind dieser
msgid "Close sidebar"
msgstr "Sidebar schließen"
-#: lib/mv_web/live/role_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Delete Role"
-msgstr "Rolle löschen"
-
#: lib/mv_web/components/layouts/sidebar.ex
#, elixir-autogen, elixir-format
msgid "Main navigation"
@@ -1690,7 +1652,6 @@ msgstr "Profil"
msgid "Role"
msgstr "Rolle"
-#: lib/mv_web/live/role_live/index.ex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format
msgid "Role deleted successfully."
@@ -1702,7 +1663,6 @@ msgid "Role details and permissions."
msgstr "Rollen-Details und Berechtigungen."
#: lib/mv_web/live/role_live/form.ex
-#: lib/mv_web/live/role_live/index.ex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format
msgid "Role not found."
@@ -1734,12 +1694,6 @@ msgstr "System"
msgid "System Role"
msgstr "System-Rolle"
-#: lib/mv_web/live/role_live/index.html.heex
-#, elixir-autogen, elixir-format
-msgid "System roles cannot be deleted"
-msgstr "System-Rollen können nicht gelöscht werden"
-
-#: lib/mv_web/live/role_live/index.ex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format
msgid "System roles cannot be deleted."
@@ -1816,12 +1770,14 @@ msgstr "Mitgliedsbeitragsart nicht gefunden"
msgid "User %{action} successfully"
msgstr "Benutzer*in wurde erfolgreich %{action}"
-#: lib/mv_web/live/user_live/index.ex
+#: lib/mv_web/live/user_live/form.ex
+#: lib/mv_web/live/user_live/show.ex
#, elixir-autogen, elixir-format
msgid "User deleted successfully"
msgstr "Benutzer*in erfolgreich gelöscht"
-#: lib/mv_web/live/user_live/index.ex
+#: lib/mv_web/live/user_live/form.ex
+#: lib/mv_web/live/user_live/show.ex
#, elixir-autogen, elixir-format
msgid "User not found"
msgstr "Benutzer*in nicht gefunden"
@@ -1832,18 +1788,14 @@ msgstr "Benutzer*in nicht gefunden"
msgid "You do not have permission to access this membership fee type"
msgstr "Du hast keine Berechtigung, auf diese Mitgliedsbeitragsart zuzugreifen"
-#: lib/mv_web/live/user_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "You do not have permission to access this user"
-msgstr "Du hast keine Berechtigung, auf diese*n Benutzer*in zuzugreifen"
-
#: lib/mv_web/live/membership_fee_settings_live.ex
#: lib/mv_web/live/membership_fee_type_live/index.ex
#, elixir-autogen, elixir-format
msgid "You do not have permission to delete this membership fee type"
msgstr "Du hast keine Berechtigung, diese Mitgliedsbeitragsart zu löschen"
-#: lib/mv_web/live/user_live/index.ex
+#: lib/mv_web/live/user_live/form.ex
+#: lib/mv_web/live/user_live/show.ex
#, elixir-autogen, elixir-format
msgid "You do not have permission to delete this user"
msgstr "Du hast keine Berechtigung, diese*n Benutzer*in zu löschen"
@@ -1864,16 +1816,19 @@ msgstr "aktualisiert"
msgid "Unknown error"
msgstr "Unbekannter Fehler"
+#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show.ex
#, elixir-autogen, elixir-format
msgid "Member deleted successfully"
msgstr "Mitglied wurde erfolgreich gelöscht"
+#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show.ex
#, elixir-autogen, elixir-format
msgid "Member not found"
msgstr "Mitglied nicht gefunden"
+#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show.ex
#, elixir-autogen, elixir-format
msgid "You do not have permission to delete this member"
@@ -2130,6 +2085,7 @@ msgstr "Gruppe erstellen"
msgid "Delete Group"
msgstr "Gruppe löschen"
+#: lib/mv_web/live/group_live/form.ex
#: lib/mv_web/live/group_live/show.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Delete group"
@@ -2210,11 +2166,6 @@ msgstr[1] "Diese Gruppe hat %{count} Mitglieder. Alle Mitglied-Gruppen-Zuordnung
msgid "To confirm deletion, please enter the group name:"
msgstr "Um die Löschung zu bestätigen, gib bitte den Gruppennamen ein:"
-#: lib/mv_web/live/group_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "View"
-msgstr "Anzeigen"
-
#: lib/mv_web/live/group_live/show.ex
#, elixir-autogen, elixir-format
msgid "Total: %{count} member"
@@ -3073,38 +3024,42 @@ msgstr "Filter zurücksetzen“"
msgid "Apply filters"
msgstr "Filter auswählen"
+#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Are you sure you want to delete %{name}? This action cannot be undone."
msgstr "Möchtest du diese Gruppe wirklich löschen? Die Aktion kann nicht rückgängig gemacht werden."
+#: lib/mv_web/live/custom_field_live/form_component.ex
+#: lib/mv_web/live/group_live/form.ex
+#: lib/mv_web/live/group_live/show.ex
+#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show.ex
+#: lib/mv_web/live/role_live/show.ex
+#: lib/mv_web/live/user_live/form.ex
+#: lib/mv_web/live/user_live/show.ex
#, elixir-autogen, elixir-format
msgid "Danger zone"
msgstr "Gefahrenzone"
+#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Delete member"
msgstr "Mitglied löschen"
+#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show.ex
#, elixir-autogen, elixir-format
msgid "Delete member %{name}"
msgstr "Mitglied %{name} löschen"
+#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show.ex
#, elixir-autogen, elixir-format
msgid "Deleting this member cannot be undone. All related data (e.g. membership fee cycles) will be removed."
msgstr "Das Löschen des Mitglieds kann nicht rückgängig gemacht werden. Alle dazugehörigen Daten (z.B. Mitgliedsbeitragszylen) werden gelöscht."
-#: lib/mv_web/live/custom_field_live/index_component.ex
-#: lib/mv_web/live/member_field_live/index_component.ex
-#, elixir-autogen, elixir-format, fuzzy
-msgid "Edit datafield"
-msgstr "Datenfeld bearbeiten"
-
-#: lib/mv_web/live/group_live/index.ex
#: lib/mv_web/live/group_live/show.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Edit group"
@@ -3115,22 +3070,11 @@ msgstr "Gruppe bearbeiten"
msgid "Edit member"
msgstr "Mitglied bearbeiten"
-#: lib/mv_web/live/role_live/index.html.heex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Edit role"
msgstr "Rolle bearbeiten"
-#: lib/mv_web/live/user_live/index.html.heex
-#, elixir-autogen, elixir-format, fuzzy
-msgid "Edit user"
-msgstr "Benutzer*in bearbeiten"
-
-#: lib/mv_web/live/member_field_live/index_component.ex
-#, elixir-autogen, elixir-format
-msgid "Click for datafield details"
-msgstr "Klicke für Datenfeld-Details"
-
#: lib/mv_web/live/group_live/index.ex
#, elixir-autogen, elixir-format
msgid "Click for group details"
@@ -3151,31 +3095,155 @@ msgstr "Klicke für Rollen-Details"
msgid "Click for user details"
msgstr "Klicke für Benutzer*innen-Details"
-#: lib/mv_web/live/custom_field_live/index_component.ex
-#, elixir-autogen, elixir-format, fuzzy
-msgid "Click for dataield details"
-msgstr "Klicke für Datenfeld-Details"
-
#: lib/mv_web/live/member_live/index.html.heex
#, elixir-autogen, elixir-format, fuzzy
msgid "Members table"
msgstr "Mitglieder"
+#: lib/mv_web/live/role_live/show.ex
+#, elixir-autogen, elixir-format, fuzzy
+msgid "Are you sure you want to delete the role %{name}? This action cannot be undone."
+msgstr "Möchtest du diese Gruppe wirklich löschen? Die Aktion kann nicht rückgängig gemacht werden."
+
+#: lib/mv_web/live/user_live/form.ex
+#: lib/mv_web/live/user_live/show.ex
+#, elixir-autogen, elixir-format, fuzzy
+msgid "Are you sure you want to delete the user %{email}? This action cannot be undone."
+msgstr "Möchtest du diese Gruppe wirklich löschen? Die Aktion kann nicht rückgängig gemacht werden."
+
+#: lib/mv_web/live/custom_field_live/index_component.ex
+#: lib/mv_web/live/member_field_live/index_component.ex
+#, elixir-autogen, elixir-format, fuzzy
+msgid "Click to edit datafield"
+msgstr "Klicke für Datenfeld-Details"
+
+#: lib/mv_web/live/custom_field_live/form_component.ex
+#, elixir-autogen, elixir-format, fuzzy
+msgid "Delete data field"
+msgstr "Datenfeld löschen"
+
+#: lib/mv_web/live/custom_field_live/form_component.ex
+#, elixir-autogen, elixir-format
+msgid "Delete data field %{name}"
+msgstr "Datenfeld %{name} löschen"
+
+#: lib/mv_web/live/group_live/form.ex
+#: lib/mv_web/live/group_live/show.ex
+#, elixir-autogen, elixir-format, fuzzy
+msgid "Delete group %{name}"
+msgstr "Gruppe %{name} löschen"
+
+#: lib/mv_web/live/role_live/show.ex
+#, elixir-autogen, elixir-format, fuzzy
+msgid "Delete role"
+msgstr "Rolle löschen"
+
+#: lib/mv_web/live/role_live/show.ex
+#, elixir-autogen, elixir-format, fuzzy
+msgid "Delete role %{name}"
+msgstr "Mitglied %{name} löschen"
+
+#: lib/mv_web/live/user_live/form.ex
+#: lib/mv_web/live/user_live/show.ex
+#, elixir-autogen, elixir-format, fuzzy
+msgid "Delete user"
+msgstr "Löschen"
+
+#: lib/mv_web/live/user_live/form.ex
+#: lib/mv_web/live/user_live/show.ex
+#, elixir-autogen, elixir-format
+msgid "Delete user %{email}"
+msgstr "Benutzer*in %{email} löschen"
+
+#: lib/mv_web/live/group_live/form.ex
+#: lib/mv_web/live/group_live/show.ex
+#, elixir-autogen, elixir-format
+msgid "Deleting this group cannot be undone. All member-group associations will be permanently removed."
+msgstr "Das Löschen der Gruppe kann nicht rückgängig gemacht werden. Alle Mitglieds-Gruppen Zugehörigkeiten werden gelöscht."
+
+#: lib/mv_web/live/role_live/show.ex
+#, elixir-autogen, elixir-format
+msgid "Deleting this role cannot be undone. Users assigned to this role must be reassigned first."
+msgstr "Das Löschen dieser Rolle kann nicht rückgängig gemacht werden. Benutzer*inen die dieser Rolle zugewiesen wurden, müssen zuerst einer anderen Rolle zugewiesen werden."
+
+#: lib/mv_web/live/user_live/form.ex
+#: lib/mv_web/live/user_live/show.ex
+#, elixir-autogen, elixir-format
+msgid "Deleting this user cannot be undone. The user account and any linked member association will be affected."
+msgstr "Das Löschen kann nicht rückgängig gemacht werden. Der Account und Verlinkungen zu Mitgliedern werden entfernt."
+
+#: lib/mv_web/live/user_live/form.ex
+#: lib/mv_web/live/user_live/show.ex
+#, elixir-autogen, elixir-format, fuzzy
+msgid "System user cannot be deleted."
+msgstr "System-Rollen können nicht gelöscht werden."
+
+#: lib/mv_web/live/global_settings_live.ex
+#, elixir-autogen, elixir-format, fuzzy
+msgid "Save Name"
+msgstr "Speichern"
+
+#: lib/mv_web/live/components/field_visibility_dropdown_component.ex
+#, elixir-autogen, elixir-format, fuzzy
+msgid "Datafield %{id}"
+msgstr "Datenfelder"
+
+#: lib/mv_web/live/custom_field_live/index_component.ex
+#, elixir-autogen, elixir-format, fuzzy
+msgid "Delete Datafields and All Values"
+msgstr "Benutzerdefiniertes Feld und alle Werte löschen"
+
+#: lib/mv_web/live/custom_field_live/form_component.ex
+#, elixir-autogen, elixir-format, fuzzy
+msgid "Deleting this data field cannot be undone. All datafield values for this field will be permanently removed."
+msgstr "Das Löschen dieses Datenfeldes kann nicht rückgängig gemacht werden. Alle "
+
+#: lib/mv_web/live/components/member_filter_component.ex
+#, elixir-autogen, elixir-format
+msgid "Individual datafields"
+msgstr "Individuelle Datenfelder"
+
#~ #: lib/mv_web/live/member_field_live/form_component.ex
#~ #, elixir-autogen, elixir-format
#~ msgid "Back to Settings"
#~ msgstr "Zurück zu den Einstellungen"
+#~ #: lib/mv_web/live/role_live/index.html.heex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Cannot delete system role"
+#~ msgstr "System-Rolle kann nicht gelöscht werden"
+
#~ #: lib/mv_web/live/custom_field_live/index_component.ex
#~ #, elixir-autogen, elixir-format
#~ msgid "Click for custom field details"
#~ msgstr "Klicke für Datenfeld-Details"
+#~ #: lib/mv_web/live/member_field_live/index_component.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Click for datafield details"
+#~ msgstr "Klicke für Datenfeld-Details"
+
#~ #: lib/mv_web/live/member_live/form.ex
#~ #, elixir-autogen, elixir-format
#~ msgid "Coming soon"
#~ msgstr "Demnächst verfügbar"
+#~ #: lib/mv_web/live/components/field_visibility_dropdown_component.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Custom Field %{id}"
+#~ msgstr "Benutzerdefiniertes Feld %{id}"
+
+#~ #: lib/mv_web/live/custom_field_live/index_component.ex
+#~ #: lib/mv_web/live/member_field_live/index_component.ex
+#~ #, elixir-autogen, elixir-format, fuzzy
+#~ msgid "Edit datafield"
+#~ msgstr "Datenfeld bearbeiten"
+
+#~ #: lib/mv_web/live/user_live/index.html.heex
+#~ #, elixir-autogen, elixir-format, fuzzy
+#~ msgid "Edit user"
+#~ msgstr "Benutzer*in bearbeiten"
+
#~ #: lib/mv_web/live/components/member_filter_component.ex
#~ #, elixir-autogen, elixir-format
#~ msgid "Reset"
@@ -3191,7 +3259,32 @@ msgstr "Mitglieder"
#~ msgid "Save Role"
#~ msgstr "Rolle speichern"
+#~ #: lib/mv_web/live/user_live/index.html.heex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Select all users"
+#~ msgstr "Alle Benutzer*innen auswählen"
+
+#~ #: lib/mv_web/live/user_live/index.html.heex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Select user"
+#~ msgstr "Benutzer*in auswählen"
+
+#~ #: lib/mv_web/live/role_live/index.html.heex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "System roles cannot be deleted"
+#~ msgstr "System-Rollen können nicht gelöscht werden"
+
+#~ #: lib/mv_web/live/group_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "View"
+#~ msgstr "Anzeigen"
+
#~ #: lib/mv_web/live/member_live/index.ex
#~ #, elixir-autogen, elixir-format
#~ msgid "You do not have permission to access this member"
#~ msgstr "Du hast keine Berechtigung, auf dieses Mitglied zuzugreifen"
+
+#~ #: lib/mv_web/live/user_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "You do not have permission to access this user"
+#~ msgstr "Du hast keine Berechtigung, auf diese*n Benutzer*in zuzugreifen"
diff --git a/priv/gettext/default.pot b/priv/gettext/default.pot
index ed020a0..309b425 100644
--- a/priv/gettext/default.pot
+++ b/priv/gettext/default.pot
@@ -19,9 +19,6 @@ msgstr ""
#: lib/mv_web/live/membership_fee_settings_live.ex
#: lib/mv_web/live/membership_fee_type_live/index.ex
-#: lib/mv_web/live/role_live/index.html.heex
-#: lib/mv_web/live/role_live/show.ex
-#: lib/mv_web/live/user_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "Are you sure?"
msgstr ""
@@ -39,11 +36,8 @@ msgstr ""
msgid "City"
msgstr ""
-#: lib/mv_web/live/custom_field_live/index_component.ex
#: lib/mv_web/live/group_live/show.ex
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
-#: lib/mv_web/live/role_live/index.html.heex
-#: lib/mv_web/live/user_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "Delete"
msgstr ""
@@ -101,8 +95,6 @@ msgid "New Member"
msgstr ""
#: lib/mv_web/live/member_live/index.html.heex
-#: lib/mv_web/live/role_live/index.html.heex
-#: lib/mv_web/live/user_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "Show"
msgstr ""
@@ -481,16 +473,6 @@ msgstr ""
msgid "Password requirements"
msgstr ""
-#: lib/mv_web/live/user_live/index.html.heex
-#, elixir-autogen, elixir-format
-msgid "Select all users"
-msgstr ""
-
-#: lib/mv_web/live/user_live/index.html.heex
-#, elixir-autogen, elixir-format
-msgid "Select user"
-msgstr ""
-
#: lib/mv_web/live/user_live/form.ex
#, elixir-autogen, elixir-format
msgid "Set Password"
@@ -606,7 +588,6 @@ msgstr ""
msgid "This email is already linked to a different OIDC account. Cannot link multiple OIDC providers to the same account."
msgstr ""
-#: lib/mv_web/live/components/member_filter_component.ex
#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show.ex
#, elixir-autogen, elixir-format
@@ -625,11 +606,6 @@ msgstr[1] ""
msgid "All custom field values will be permanently deleted when you delete this custom field."
msgstr ""
-#: 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_component.ex
#, elixir-autogen, elixir-format
msgid "Enter the text above to confirm"
@@ -663,7 +639,6 @@ msgstr ""
msgid "Manage global settings for the association."
msgstr ""
-#: lib/mv_web/live/global_settings_live.ex
#: lib/mv_web/live/membership_fee_settings_live.ex
#, elixir-autogen, elixir-format
msgid "Save Settings"
@@ -786,8 +761,11 @@ msgstr ""
#: lib/mv_web/live/member_field_live/form_component.ex
#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show.ex
+#: lib/mv_web/live/membership_fee_type_live/form.ex
#: lib/mv_web/live/role_live/form.ex
#: lib/mv_web/live/role_live/show.ex
+#: lib/mv_web/live/user_live/form.ex
+#: lib/mv_web/live/user_live/show.ex
#, elixir-autogen, elixir-format
msgid "Back"
msgstr ""
@@ -822,6 +800,7 @@ msgstr ""
#: lib/mv_web/live/group_live/form.ex
#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
+#: lib/mv_web/live/membership_fee_type_live/form.ex
#: lib/mv_web/live/role_live/form.ex
#, elixir-autogen, elixir-format
msgid "Save"
@@ -965,11 +944,6 @@ msgstr ""
msgid "Yearly"
msgstr ""
-#: lib/mv_web/live/components/field_visibility_dropdown_component.ex
-#, elixir-autogen, elixir-format
-msgid "Custom Field %{id}"
-msgstr ""
-
#: lib/mv_web/live/member_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "Last name"
@@ -1605,17 +1579,11 @@ msgstr ""
msgid "Back to roles list"
msgstr ""
-#: lib/mv_web/live/role_live/index.html.heex
-#, elixir-autogen, elixir-format
-msgid "Cannot delete system role"
-msgstr ""
-
#: lib/mv_web/live/role_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "Custom"
msgstr ""
-#: lib/mv_web/live/role_live/index.ex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format
msgid "Failed to delete role: %{error}"
@@ -1632,7 +1600,6 @@ msgstr ""
msgid "Manage user roles and their permission sets."
msgstr ""
-#: lib/mv_web/live/role_live/index.ex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format
msgid "Cannot delete role. %{count} user(s) are still assigned to this role. Please assign them to another role first."
@@ -1643,11 +1610,6 @@ msgstr ""
msgid "Close sidebar"
msgstr ""
-#: lib/mv_web/live/role_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Delete Role"
-msgstr ""
-
#: lib/mv_web/components/layouts/sidebar.ex
#, elixir-autogen, elixir-format
msgid "Main navigation"
@@ -1691,7 +1653,6 @@ msgstr ""
msgid "Role"
msgstr ""
-#: lib/mv_web/live/role_live/index.ex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format
msgid "Role deleted successfully."
@@ -1703,7 +1664,6 @@ msgid "Role details and permissions."
msgstr ""
#: lib/mv_web/live/role_live/form.ex
-#: lib/mv_web/live/role_live/index.ex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format
msgid "Role not found."
@@ -1735,12 +1695,6 @@ msgstr ""
msgid "System Role"
msgstr ""
-#: lib/mv_web/live/role_live/index.html.heex
-#, elixir-autogen, elixir-format
-msgid "System roles cannot be deleted"
-msgstr ""
-
-#: lib/mv_web/live/role_live/index.ex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format
msgid "System roles cannot be deleted."
@@ -1817,12 +1771,14 @@ msgstr ""
msgid "User %{action} successfully"
msgstr ""
-#: lib/mv_web/live/user_live/index.ex
+#: lib/mv_web/live/user_live/form.ex
+#: lib/mv_web/live/user_live/show.ex
#, elixir-autogen, elixir-format
msgid "User deleted successfully"
msgstr ""
-#: lib/mv_web/live/user_live/index.ex
+#: lib/mv_web/live/user_live/form.ex
+#: lib/mv_web/live/user_live/show.ex
#, elixir-autogen, elixir-format
msgid "User not found"
msgstr ""
@@ -1833,18 +1789,14 @@ msgstr ""
msgid "You do not have permission to access this membership fee type"
msgstr ""
-#: lib/mv_web/live/user_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "You do not have permission to access this user"
-msgstr ""
-
#: lib/mv_web/live/membership_fee_settings_live.ex
#: lib/mv_web/live/membership_fee_type_live/index.ex
#, elixir-autogen, elixir-format
msgid "You do not have permission to delete this membership fee type"
msgstr ""
-#: lib/mv_web/live/user_live/index.ex
+#: lib/mv_web/live/user_live/form.ex
+#: lib/mv_web/live/user_live/show.ex
#, elixir-autogen, elixir-format
msgid "You do not have permission to delete this user"
msgstr ""
@@ -1865,16 +1817,19 @@ msgstr ""
msgid "Unknown error"
msgstr ""
+#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show.ex
#, elixir-autogen, elixir-format
msgid "Member deleted successfully"
msgstr ""
+#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show.ex
#, elixir-autogen, elixir-format
msgid "Member not found"
msgstr ""
+#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show.ex
#, elixir-autogen, elixir-format
msgid "You do not have permission to delete this member"
@@ -2131,6 +2086,7 @@ msgstr ""
msgid "Delete Group"
msgstr ""
+#: lib/mv_web/live/group_live/form.ex
#: lib/mv_web/live/group_live/show.ex
#, elixir-autogen, elixir-format
msgid "Delete group"
@@ -2211,11 +2167,6 @@ msgstr[1] ""
msgid "To confirm deletion, please enter the group name:"
msgstr ""
-#: lib/mv_web/live/group_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "View"
-msgstr ""
-
#: lib/mv_web/live/group_live/show.ex
#, elixir-autogen, elixir-format
msgid "Total: %{count} member"
@@ -3073,38 +3024,42 @@ msgstr ""
msgid "Apply filters"
msgstr ""
+#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show.ex
#, elixir-autogen, elixir-format
msgid "Are you sure you want to delete %{name}? This action cannot be undone."
msgstr ""
+#: lib/mv_web/live/custom_field_live/form_component.ex
+#: lib/mv_web/live/group_live/form.ex
+#: lib/mv_web/live/group_live/show.ex
+#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show.ex
+#: lib/mv_web/live/role_live/show.ex
+#: lib/mv_web/live/user_live/form.ex
+#: lib/mv_web/live/user_live/show.ex
#, elixir-autogen, elixir-format
msgid "Danger zone"
msgstr ""
+#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show.ex
#, elixir-autogen, elixir-format
msgid "Delete member"
msgstr ""
+#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show.ex
#, elixir-autogen, elixir-format
msgid "Delete member %{name}"
msgstr ""
+#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show.ex
#, elixir-autogen, elixir-format
msgid "Deleting this member cannot be undone. All related data (e.g. membership fee cycles) will be removed."
msgstr ""
-#: lib/mv_web/live/custom_field_live/index_component.ex
-#: lib/mv_web/live/member_field_live/index_component.ex
-#, elixir-autogen, elixir-format
-msgid "Edit datafield"
-msgstr ""
-
-#: lib/mv_web/live/group_live/index.ex
#: lib/mv_web/live/group_live/show.ex
#, elixir-autogen, elixir-format
msgid "Edit group"
@@ -3115,22 +3070,11 @@ msgstr ""
msgid "Edit member"
msgstr ""
-#: lib/mv_web/live/role_live/index.html.heex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format
msgid "Edit role"
msgstr ""
-#: lib/mv_web/live/user_live/index.html.heex
-#, elixir-autogen, elixir-format
-msgid "Edit user"
-msgstr ""
-
-#: lib/mv_web/live/member_field_live/index_component.ex
-#, elixir-autogen, elixir-format
-msgid "Click for datafield details"
-msgstr ""
-
#: lib/mv_web/live/group_live/index.ex
#, elixir-autogen, elixir-format
msgid "Click for group details"
@@ -3151,12 +3095,110 @@ msgstr ""
msgid "Click for user details"
msgstr ""
-#: lib/mv_web/live/custom_field_live/index_component.ex
-#, elixir-autogen, elixir-format
-msgid "Click for dataield details"
-msgstr ""
-
#: lib/mv_web/live/member_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "Members table"
msgstr ""
+
+#: lib/mv_web/live/role_live/show.ex
+#, elixir-autogen, elixir-format
+msgid "Are you sure you want to delete the role %{name}? This action cannot be undone."
+msgstr ""
+
+#: lib/mv_web/live/user_live/form.ex
+#: lib/mv_web/live/user_live/show.ex
+#, elixir-autogen, elixir-format
+msgid "Are you sure you want to delete the user %{email}? This action cannot be undone."
+msgstr ""
+
+#: lib/mv_web/live/custom_field_live/index_component.ex
+#: lib/mv_web/live/member_field_live/index_component.ex
+#, elixir-autogen, elixir-format
+msgid "Click to edit datafield"
+msgstr ""
+
+#: lib/mv_web/live/custom_field_live/form_component.ex
+#, elixir-autogen, elixir-format
+msgid "Delete data field"
+msgstr ""
+
+#: lib/mv_web/live/custom_field_live/form_component.ex
+#, elixir-autogen, elixir-format
+msgid "Delete data field %{name}"
+msgstr ""
+
+#: lib/mv_web/live/group_live/form.ex
+#: lib/mv_web/live/group_live/show.ex
+#, elixir-autogen, elixir-format
+msgid "Delete group %{name}"
+msgstr ""
+
+#: lib/mv_web/live/role_live/show.ex
+#, elixir-autogen, elixir-format
+msgid "Delete role"
+msgstr ""
+
+#: lib/mv_web/live/role_live/show.ex
+#, elixir-autogen, elixir-format
+msgid "Delete role %{name}"
+msgstr ""
+
+#: lib/mv_web/live/user_live/form.ex
+#: lib/mv_web/live/user_live/show.ex
+#, elixir-autogen, elixir-format
+msgid "Delete user"
+msgstr ""
+
+#: lib/mv_web/live/user_live/form.ex
+#: lib/mv_web/live/user_live/show.ex
+#, elixir-autogen, elixir-format
+msgid "Delete user %{email}"
+msgstr ""
+
+#: lib/mv_web/live/group_live/form.ex
+#: lib/mv_web/live/group_live/show.ex
+#, elixir-autogen, elixir-format
+msgid "Deleting this group cannot be undone. All member-group associations will be permanently removed."
+msgstr ""
+
+#: lib/mv_web/live/role_live/show.ex
+#, elixir-autogen, elixir-format
+msgid "Deleting this role cannot be undone. Users assigned to this role must be reassigned first."
+msgstr ""
+
+#: lib/mv_web/live/user_live/form.ex
+#: lib/mv_web/live/user_live/show.ex
+#, elixir-autogen, elixir-format
+msgid "Deleting this user cannot be undone. The user account and any linked member association will be affected."
+msgstr ""
+
+#: lib/mv_web/live/user_live/form.ex
+#: lib/mv_web/live/user_live/show.ex
+#, elixir-autogen, elixir-format
+msgid "System user cannot be deleted."
+msgstr ""
+
+#: lib/mv_web/live/global_settings_live.ex
+#, elixir-autogen, elixir-format
+msgid "Save Name"
+msgstr ""
+
+#: lib/mv_web/live/components/field_visibility_dropdown_component.ex
+#, elixir-autogen, elixir-format
+msgid "Datafield %{id}"
+msgstr ""
+
+#: lib/mv_web/live/custom_field_live/index_component.ex
+#, elixir-autogen, elixir-format
+msgid "Delete Datafields and All Values"
+msgstr ""
+
+#: lib/mv_web/live/custom_field_live/form_component.ex
+#, elixir-autogen, elixir-format
+msgid "Deleting this data field cannot be undone. All datafield values for this field will be permanently removed."
+msgstr ""
+
+#: lib/mv_web/live/components/member_filter_component.ex
+#, elixir-autogen, elixir-format
+msgid "Individual datafields"
+msgstr ""
diff --git a/priv/gettext/en/LC_MESSAGES/default.po b/priv/gettext/en/LC_MESSAGES/default.po
index a44e87c..a42bdbd 100644
--- a/priv/gettext/en/LC_MESSAGES/default.po
+++ b/priv/gettext/en/LC_MESSAGES/default.po
@@ -19,9 +19,6 @@ msgstr ""
#: lib/mv_web/live/membership_fee_settings_live.ex
#: lib/mv_web/live/membership_fee_type_live/index.ex
-#: lib/mv_web/live/role_live/index.html.heex
-#: lib/mv_web/live/role_live/show.ex
-#: lib/mv_web/live/user_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "Are you sure?"
msgstr ""
@@ -39,11 +36,8 @@ msgstr ""
msgid "City"
msgstr ""
-#: lib/mv_web/live/custom_field_live/index_component.ex
#: lib/mv_web/live/group_live/show.ex
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
-#: lib/mv_web/live/role_live/index.html.heex
-#: lib/mv_web/live/user_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "Delete"
msgstr ""
@@ -101,8 +95,6 @@ msgid "New Member"
msgstr ""
#: lib/mv_web/live/member_live/index.html.heex
-#: lib/mv_web/live/role_live/index.html.heex
-#: lib/mv_web/live/user_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "Show"
msgstr ""
@@ -481,16 +473,6 @@ msgstr ""
msgid "Password requirements"
msgstr ""
-#: lib/mv_web/live/user_live/index.html.heex
-#, elixir-autogen, elixir-format, fuzzy
-msgid "Select all users"
-msgstr ""
-
-#: lib/mv_web/live/user_live/index.html.heex
-#, elixir-autogen, elixir-format, fuzzy
-msgid "Select user"
-msgstr ""
-
#: lib/mv_web/live/user_live/form.ex
#, elixir-autogen, elixir-format
msgid "Set Password"
@@ -606,7 +588,6 @@ msgstr ""
msgid "This email is already linked to a different OIDC account. Cannot link multiple OIDC providers to the same account."
msgstr ""
-#: lib/mv_web/live/components/member_filter_component.ex
#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show.ex
#, elixir-autogen, elixir-format, fuzzy
@@ -625,11 +606,6 @@ msgstr[1] ""
msgid "All custom field values will be permanently deleted when you delete this custom field."
msgstr ""
-#: 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_component.ex
#, elixir-autogen, elixir-format
msgid "Enter the text above to confirm"
@@ -663,7 +639,6 @@ msgstr ""
msgid "Manage global settings for the association."
msgstr ""
-#: lib/mv_web/live/global_settings_live.ex
#: lib/mv_web/live/membership_fee_settings_live.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Save Settings"
@@ -786,8 +761,11 @@ msgstr ""
#: lib/mv_web/live/member_field_live/form_component.ex
#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show.ex
+#: lib/mv_web/live/membership_fee_type_live/form.ex
#: lib/mv_web/live/role_live/form.ex
#: lib/mv_web/live/role_live/show.ex
+#: lib/mv_web/live/user_live/form.ex
+#: lib/mv_web/live/user_live/show.ex
#, elixir-autogen, elixir-format
msgid "Back"
msgstr ""
@@ -822,6 +800,7 @@ msgstr ""
#: lib/mv_web/live/group_live/form.ex
#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
+#: lib/mv_web/live/membership_fee_type_live/form.ex
#: lib/mv_web/live/role_live/form.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Save"
@@ -965,11 +944,6 @@ msgstr ""
msgid "Yearly"
msgstr ""
-#: lib/mv_web/live/components/field_visibility_dropdown_component.ex
-#, elixir-autogen, elixir-format, fuzzy
-msgid "Custom Field %{id}"
-msgstr ""
-
#: lib/mv_web/live/member_live/index.html.heex
#, elixir-autogen, elixir-format, fuzzy
msgid "Last name"
@@ -1605,17 +1579,11 @@ msgstr ""
msgid "Back to roles list"
msgstr ""
-#: lib/mv_web/live/role_live/index.html.heex
-#, elixir-autogen, elixir-format
-msgid "Cannot delete system role"
-msgstr ""
-
#: lib/mv_web/live/role_live/index.html.heex
#, elixir-autogen, elixir-format, fuzzy
msgid "Custom"
msgstr ""
-#: lib/mv_web/live/role_live/index.ex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Failed to delete role: %{error}"
@@ -1632,7 +1600,6 @@ msgstr ""
msgid "Manage user roles and their permission sets."
msgstr ""
-#: lib/mv_web/live/role_live/index.ex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format
msgid "Cannot delete role. %{count} user(s) are still assigned to this role. Please assign them to another role first."
@@ -1643,11 +1610,6 @@ msgstr ""
msgid "Close sidebar"
msgstr ""
-#: lib/mv_web/live/role_live/show.ex
-#, elixir-autogen, elixir-format, fuzzy
-msgid "Delete Role"
-msgstr ""
-
#: lib/mv_web/components/layouts/sidebar.ex
#, elixir-autogen, elixir-format
msgid "Main navigation"
@@ -1691,7 +1653,6 @@ msgstr ""
msgid "Role"
msgstr ""
-#: lib/mv_web/live/role_live/index.ex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Role deleted successfully."
@@ -1703,7 +1664,6 @@ msgid "Role details and permissions."
msgstr ""
#: lib/mv_web/live/role_live/form.ex
-#: lib/mv_web/live/role_live/index.ex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format
msgid "Role not found."
@@ -1735,12 +1695,6 @@ msgstr ""
msgid "System Role"
msgstr ""
-#: lib/mv_web/live/role_live/index.html.heex
-#, elixir-autogen, elixir-format
-msgid "System roles cannot be deleted"
-msgstr ""
-
-#: lib/mv_web/live/role_live/index.ex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "System roles cannot be deleted."
@@ -1817,12 +1771,14 @@ msgstr ""
msgid "User %{action} successfully"
msgstr ""
-#: lib/mv_web/live/user_live/index.ex
+#: lib/mv_web/live/user_live/form.ex
+#: lib/mv_web/live/user_live/show.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "User deleted successfully"
msgstr ""
-#: lib/mv_web/live/user_live/index.ex
+#: lib/mv_web/live/user_live/form.ex
+#: lib/mv_web/live/user_live/show.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "User not found"
msgstr ""
@@ -1833,18 +1789,14 @@ msgstr ""
msgid "You do not have permission to access this membership fee type"
msgstr ""
-#: lib/mv_web/live/user_live/index.ex
-#, elixir-autogen, elixir-format, fuzzy
-msgid "You do not have permission to access this user"
-msgstr ""
-
#: lib/mv_web/live/membership_fee_settings_live.ex
#: lib/mv_web/live/membership_fee_type_live/index.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "You do not have permission to delete this membership fee type"
msgstr ""
-#: lib/mv_web/live/user_live/index.ex
+#: lib/mv_web/live/user_live/form.ex
+#: lib/mv_web/live/user_live/show.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "You do not have permission to delete this user"
msgstr ""
@@ -1865,16 +1817,19 @@ msgstr ""
msgid "Unknown error"
msgstr ""
+#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show.ex
#, elixir-autogen, elixir-format
msgid "Member deleted successfully"
msgstr ""
+#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show.ex
#, elixir-autogen, elixir-format
msgid "Member not found"
msgstr ""
+#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show.ex
#, elixir-autogen, elixir-format
msgid "You do not have permission to delete this member"
@@ -2131,6 +2086,7 @@ msgstr ""
msgid "Delete Group"
msgstr ""
+#: lib/mv_web/live/group_live/form.ex
#: lib/mv_web/live/group_live/show.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Delete group"
@@ -2211,11 +2167,6 @@ msgstr[1] ""
msgid "To confirm deletion, please enter the group name:"
msgstr ""
-#: lib/mv_web/live/group_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "View"
-msgstr ""
-
#: lib/mv_web/live/group_live/show.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Total: %{count} member"
@@ -3073,38 +3024,42 @@ msgstr ""
msgid "Apply filters"
msgstr ""
+#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Are you sure you want to delete %{name}? This action cannot be undone."
msgstr ""
+#: lib/mv_web/live/custom_field_live/form_component.ex
+#: lib/mv_web/live/group_live/form.ex
+#: lib/mv_web/live/group_live/show.ex
+#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show.ex
+#: lib/mv_web/live/role_live/show.ex
+#: lib/mv_web/live/user_live/form.ex
+#: lib/mv_web/live/user_live/show.ex
#, elixir-autogen, elixir-format
msgid "Danger zone"
msgstr ""
+#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Delete member"
msgstr ""
+#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show.ex
#, elixir-autogen, elixir-format
msgid "Delete member %{name}"
msgstr ""
+#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show.ex
#, elixir-autogen, elixir-format
msgid "Deleting this member cannot be undone. All related data (e.g. membership fee cycles) will be removed."
msgstr ""
-#: lib/mv_web/live/custom_field_live/index_component.ex
-#: lib/mv_web/live/member_field_live/index_component.ex
-#, elixir-autogen, elixir-format, fuzzy
-msgid "Edit datafield"
-msgstr ""
-
-#: lib/mv_web/live/group_live/index.ex
#: lib/mv_web/live/group_live/show.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Edit group"
@@ -3115,22 +3070,11 @@ msgstr ""
msgid "Edit member"
msgstr ""
-#: lib/mv_web/live/role_live/index.html.heex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Edit role"
msgstr ""
-#: lib/mv_web/live/user_live/index.html.heex
-#, elixir-autogen, elixir-format, fuzzy
-msgid "Edit user"
-msgstr ""
-
-#: lib/mv_web/live/member_field_live/index_component.ex
-#, elixir-autogen, elixir-format
-msgid "Click for datafield details"
-msgstr ""
-
#: lib/mv_web/live/group_live/index.ex
#, elixir-autogen, elixir-format
msgid "Click for group details"
@@ -3151,31 +3095,155 @@ msgstr ""
msgid "Click for user details"
msgstr ""
-#: lib/mv_web/live/custom_field_live/index_component.ex
-#, elixir-autogen, elixir-format, fuzzy
-msgid "Click for dataield details"
-msgstr ""
-
#: lib/mv_web/live/member_live/index.html.heex
#, elixir-autogen, elixir-format, fuzzy
msgid "Members table"
msgstr ""
+#: lib/mv_web/live/role_live/show.ex
+#, elixir-autogen, elixir-format, fuzzy
+msgid "Are you sure you want to delete the role %{name}? This action cannot be undone."
+msgstr ""
+
+#: lib/mv_web/live/user_live/form.ex
+#: lib/mv_web/live/user_live/show.ex
+#, elixir-autogen, elixir-format, fuzzy
+msgid "Are you sure you want to delete the user %{email}? This action cannot be undone."
+msgstr ""
+
+#: lib/mv_web/live/custom_field_live/index_component.ex
+#: lib/mv_web/live/member_field_live/index_component.ex
+#, elixir-autogen, elixir-format, fuzzy
+msgid "Click to edit datafield"
+msgstr ""
+
+#: lib/mv_web/live/custom_field_live/form_component.ex
+#, elixir-autogen, elixir-format, fuzzy
+msgid "Delete data field"
+msgstr ""
+
+#: lib/mv_web/live/custom_field_live/form_component.ex
+#, elixir-autogen, elixir-format
+msgid "Delete data field %{name}"
+msgstr ""
+
+#: lib/mv_web/live/group_live/form.ex
+#: lib/mv_web/live/group_live/show.ex
+#, elixir-autogen, elixir-format, fuzzy
+msgid "Delete group %{name}"
+msgstr ""
+
+#: lib/mv_web/live/role_live/show.ex
+#, elixir-autogen, elixir-format, fuzzy
+msgid "Delete role"
+msgstr ""
+
+#: lib/mv_web/live/role_live/show.ex
+#, elixir-autogen, elixir-format, fuzzy
+msgid "Delete role %{name}"
+msgstr ""
+
+#: lib/mv_web/live/user_live/form.ex
+#: lib/mv_web/live/user_live/show.ex
+#, elixir-autogen, elixir-format, fuzzy
+msgid "Delete user"
+msgstr ""
+
+#: lib/mv_web/live/user_live/form.ex
+#: lib/mv_web/live/user_live/show.ex
+#, elixir-autogen, elixir-format
+msgid "Delete user %{email}"
+msgstr ""
+
+#: lib/mv_web/live/group_live/form.ex
+#: lib/mv_web/live/group_live/show.ex
+#, elixir-autogen, elixir-format
+msgid "Deleting this group cannot be undone. All member-group associations will be permanently removed."
+msgstr ""
+
+#: lib/mv_web/live/role_live/show.ex
+#, elixir-autogen, elixir-format
+msgid "Deleting this role cannot be undone. Users assigned to this role must be reassigned first."
+msgstr ""
+
+#: lib/mv_web/live/user_live/form.ex
+#: lib/mv_web/live/user_live/show.ex
+#, elixir-autogen, elixir-format
+msgid "Deleting this user cannot be undone. The user account and any linked member association will be affected."
+msgstr ""
+
+#: lib/mv_web/live/user_live/form.ex
+#: lib/mv_web/live/user_live/show.ex
+#, elixir-autogen, elixir-format, fuzzy
+msgid "System user cannot be deleted."
+msgstr ""
+
+#: lib/mv_web/live/global_settings_live.ex
+#, elixir-autogen, elixir-format, fuzzy
+msgid "Save Name"
+msgstr ""
+
+#: lib/mv_web/live/components/field_visibility_dropdown_component.ex
+#, elixir-autogen, elixir-format, fuzzy
+msgid "Datafield %{id}"
+msgstr ""
+
+#: lib/mv_web/live/custom_field_live/index_component.ex
+#, elixir-autogen, elixir-format, fuzzy
+msgid "Delete Datafields and All Values"
+msgstr ""
+
+#: lib/mv_web/live/custom_field_live/form_component.ex
+#, elixir-autogen, elixir-format, fuzzy
+msgid "Deleting this data field cannot be undone. All datafield values for this field will be permanently removed."
+msgstr ""
+
+#: lib/mv_web/live/components/member_filter_component.ex
+#, elixir-autogen, elixir-format
+msgid "Individual datafields"
+msgstr ""
+
#~ #: lib/mv_web/live/member_field_live/form_component.ex
#~ #, elixir-autogen, elixir-format
#~ msgid "Back to Settings"
#~ msgstr ""
+#~ #: lib/mv_web/live/role_live/index.html.heex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Cannot delete system role"
+#~ msgstr ""
+
#~ #: lib/mv_web/live/custom_field_live/index_component.ex
#~ #, elixir-autogen, elixir-format
#~ msgid "Click for custom field details"
#~ msgstr ""
+#~ #: lib/mv_web/live/member_field_live/index_component.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Click for datafield details"
+#~ msgstr ""
+
#~ #: lib/mv_web/live/member_live/form.ex
#~ #, elixir-autogen, elixir-format
#~ msgid "Coming soon"
#~ msgstr ""
+#~ #: lib/mv_web/live/components/field_visibility_dropdown_component.ex
+#~ #, elixir-autogen, elixir-format, fuzzy
+#~ msgid "Custom Field %{id}"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/custom_field_live/index_component.ex
+#~ #: lib/mv_web/live/member_field_live/index_component.ex
+#~ #, elixir-autogen, elixir-format, fuzzy
+#~ msgid "Edit datafield"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/user_live/index.html.heex
+#~ #, elixir-autogen, elixir-format, fuzzy
+#~ msgid "Edit user"
+#~ msgstr ""
+
#~ #: lib/mv_web/live/components/member_filter_component.ex
#~ #, elixir-autogen, elixir-format
#~ msgid "Reset"
@@ -3191,7 +3259,32 @@ msgstr ""
#~ msgid "Save Role"
#~ msgstr ""
+#~ #: lib/mv_web/live/user_live/index.html.heex
+#~ #, elixir-autogen, elixir-format, fuzzy
+#~ msgid "Select all users"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/user_live/index.html.heex
+#~ #, elixir-autogen, elixir-format, fuzzy
+#~ msgid "Select user"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/role_live/index.html.heex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "System roles cannot be deleted"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/group_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "View"
+#~ msgstr ""
+
#~ #: lib/mv_web/live/member_live/index.ex
#~ #, elixir-autogen, elixir-format
#~ msgid "You do not have permission to access this member"
#~ msgstr ""
+
+#~ #: lib/mv_web/live/user_live/index.ex
+#~ #, elixir-autogen, elixir-format, fuzzy
+#~ msgid "You do not have permission to access this user"
+#~ msgstr ""
diff --git a/test/mv_web/live/custom_field_live/deletion_test.exs b/test/mv_web/live/custom_field_live/deletion_test.exs
index 28f98a2..5ec955e 100644
--- a/test/mv_web/live/custom_field_live/deletion_test.exs
+++ b/test/mv_web/live/custom_field_live/deletion_test.exs
@@ -46,6 +46,17 @@ defmodule MvWeb.CustomFieldLive.DeletionTest do
%{conn: conn, user: user_with_role}
end
+ # Delete is in the edit form (FormComponent); open form by clicking the name cell (unique td with phx-click)
+ defp open_delete_modal(view, custom_field) do
+ view
+ |> element("tr#custom_fields-#{custom_field.id} td", custom_field.name)
+ |> render_click()
+
+ view
+ |> element("[data-testid=custom-field-delete]")
+ |> render_click()
+ end
+
describe "delete button and modal" do
test "opens modal with correct member count when delete is clicked", %{conn: conn} do
{:ok, member} = create_member()
@@ -55,11 +66,7 @@ defmodule MvWeb.CustomFieldLive.DeletionTest do
create_custom_field_value(member, custom_field, "test")
{:ok, view, _html} = live(conn, ~p"/admin/datafields")
-
- # Click delete button - find the delete link within the component
- view
- |> element("#custom-fields-component a", "Delete")
- |> render_click()
+ open_delete_modal(view, custom_field)
# Modal should be visible
assert has_element?(view, "#delete-custom-field-modal")
@@ -81,23 +88,17 @@ defmodule MvWeb.CustomFieldLive.DeletionTest do
create_custom_field_value(member2, custom_field, "test2")
{:ok, view, _html} = live(conn, ~p"/admin/datafields")
-
- view
- |> element("#custom-fields-component a", "Delete")
- |> render_click()
+ open_delete_modal(view, custom_field)
# Should show plural form
assert render(view) =~ "2 members have values assigned for this custom field"
end
test "shows 0 members for custom field without values", %{conn: conn} do
- {:ok, _custom_field} = create_custom_field("test_field", :string)
+ {:ok, custom_field} = create_custom_field("test_field", :string)
{:ok, view, _html} = live(conn, ~p"/admin/datafields")
-
- view
- |> element("#custom-fields-component a", "Delete")
- |> render_click()
+ open_delete_modal(view, custom_field)
# Should show 0 members
assert render(view) =~ "0 members have values assigned for this custom field"
@@ -109,10 +110,7 @@ defmodule MvWeb.CustomFieldLive.DeletionTest do
{:ok, custom_field} = create_custom_field("test_field", :string)
{:ok, view, _html} = live(conn, ~p"/admin/datafields")
-
- view
- |> element("#custom-fields-component a", "Delete")
- |> render_click()
+ open_delete_modal(view, custom_field)
# Type in slug input - use element to find the form with phx-target
view
@@ -124,13 +122,10 @@ defmodule MvWeb.CustomFieldLive.DeletionTest do
end
test "delete button is disabled when slug doesn't match", %{conn: conn} do
- {:ok, _custom_field} = create_custom_field("test_field", :string)
+ {:ok, custom_field} = create_custom_field("test_field", :string)
{:ok, view, _html} = live(conn, ~p"/admin/datafields")
-
- view
- |> element("#custom-fields-component a", "Delete")
- |> render_click()
+ open_delete_modal(view, custom_field)
# Type wrong slug - use element to find the form with phx-target
view
@@ -149,11 +144,7 @@ defmodule MvWeb.CustomFieldLive.DeletionTest do
{:ok, custom_field_value} = create_custom_field_value(member, custom_field, "test")
{:ok, view, _html} = live(conn, ~p"/admin/datafields")
-
- # Open modal
- view
- |> element("#custom-fields-component a", "Delete")
- |> render_click()
+ open_delete_modal(view, custom_field)
# Enter correct slug - use element to find the form with phx-target
view
@@ -162,7 +153,7 @@ defmodule MvWeb.CustomFieldLive.DeletionTest do
# Click confirm
view
- |> element("#delete-custom-field-modal button", "Delete Custom Field and All Values")
+ |> element("#delete-custom-field-modal button", "Delete Datafields and All Values")
|> render_click()
# Should show success message
@@ -186,10 +177,7 @@ defmodule MvWeb.CustomFieldLive.DeletionTest do
{:ok, custom_field} = create_custom_field("test_field", :string)
{:ok, view, _html} = live(conn, ~p"/admin/datafields")
-
- view
- |> element("#custom-fields-component a", "Delete")
- |> render_click()
+ open_delete_modal(view, custom_field)
# Enter wrong slug - use element to find the form with phx-target
view
@@ -210,10 +198,7 @@ defmodule MvWeb.CustomFieldLive.DeletionTest do
{:ok, custom_field} = create_custom_field("test_field", :string)
{:ok, view, _html} = live(conn, ~p"/admin/datafields")
-
- view
- |> element("#custom-fields-component a", "Delete")
- |> render_click()
+ open_delete_modal(view, custom_field)
# Modal should be visible
assert has_element?(view, "#delete-custom-field-modal")
diff --git a/test/mv_web/live/role_live_test.exs b/test/mv_web/live/role_live_test.exs
index cb112f2..57ce814 100644
--- a/test/mv_web/live/role_live_test.exs
+++ b/test/mv_web/live/role_live_test.exs
@@ -138,7 +138,7 @@ defmodule MvWeb.RoleLiveTest do
assert html =~ "System Role" || html =~ "system"
end
- test "delete button disabled for system roles", %{conn: conn, actor: actor} do
+ test "delete button not shown for system roles", %{conn: conn, actor: actor} do
system_role =
Role
|> Ash.Changeset.for_create(:create_role, %{
@@ -148,28 +148,19 @@ defmodule MvWeb.RoleLiveTest do
|> Ash.Changeset.force_change_attribute(:is_system_role, true)
|> Ash.create!(actor: actor)
- {:ok, view, _html} = live(conn, "/admin/roles")
+ {:ok, view, _html} = live(conn, "/admin/roles/#{system_role.id}")
- assert has_element?(
- view,
- "button[phx-click='delete'][phx-value-id='#{system_role.id}'][disabled]"
- ) ||
- not has_element?(
- view,
- "button[phx-click='delete'][phx-value-id='#{system_role.id}']"
- )
+ # Danger zone (and delete button) is not rendered for system roles
+ refute has_element?(view, "[data-testid=role-delete]")
end
test "delete button enabled for non-system roles", %{conn: conn} do
role = create_role()
- {:ok, view, html} = live(conn, "/admin/roles")
+ {:ok, view, _html} = live(conn, "/admin/roles/#{role.id}")
- # Delete is a link with phx-click containing delete event
- # Check if delete link exists in HTML (phx-click contains delete and role id)
- assert (html =~ "phx-click" && html =~ "delete" && html =~ role.id) ||
- has_element?(view, "a[phx-click*='delete'][phx-value-id='#{role.id}']") ||
- has_element?(view, "a[aria-label='Delete role']")
+ # Delete is on show page (Danger zone)
+ assert has_element?(view, "[data-testid=role-delete]")
end
test "new role button navigates to form", %{conn: conn} do
@@ -393,21 +384,21 @@ defmodule MvWeb.RoleLiveTest do
test "deletes non-system role", %{conn: conn, actor: actor} do
role = create_role()
- {:ok, view, html} = live(conn, "/admin/roles")
+ {:ok, view, _html} = live(conn, "/admin/roles/#{role.id}")
- # Delete is a link - JS.push creates phx-click with value containing id
- # Verify the role id is in the HTML (in phx-click value)
- assert html =~ role.id
+ # Delete from Danger zone on show page
+ view
+ |> element("[data-testid=role-delete]")
+ |> render_click()
- # Send delete event directly to avoid selector issues with multiple delete buttons
- render_click(view, "delete", %{"id" => role.id})
+ assert_redirect(view, "/admin/roles")
# Verify deletion by checking database
assert {:error, %Ash.Error.Invalid{errors: [%Ash.Error.Query.NotFound{}]}} =
Authorization.get_role(role.id, actor: actor)
end
- test "fails to delete system role with error message", %{conn: conn, actor: actor} do
+ test "system role has no delete button and cannot be deleted", %{conn: conn, actor: actor} do
system_role =
Role
|> Ash.Changeset.for_create(:create_role, %{
@@ -417,19 +408,12 @@ defmodule MvWeb.RoleLiveTest do
|> Ash.Changeset.force_change_attribute(:is_system_role, true)
|> Ash.create!(actor: actor)
- {:ok, view, html} = live(conn, "/admin/roles")
+ {:ok, view, _html} = live(conn, "/admin/roles/#{system_role.id}")
- # System role delete button should be disabled
- assert html =~ "disabled" || html =~ "cursor-not-allowed" ||
- html =~ "System roles cannot be deleted"
+ # Danger zone is not rendered for system roles (no delete button)
+ refute has_element?(view, "[data-testid=role-delete]")
- # Try to delete via event (backend check)
- render_click(view, "delete", %{"id" => system_role.id})
-
- # Should show error message
- assert render(view) =~ "System roles cannot be deleted"
-
- # Role should still exist
+ # Role still exists
{:ok, _role} = Authorization.get_role(system_role.id, actor: actor)
end
end
diff --git a/test/mv_web/live/user_live_authorization_test.exs b/test/mv_web/live/user_live_authorization_test.exs
index f4b4746..ee9f2b6 100644
--- a/test/mv_web/live/user_live_authorization_test.exs
+++ b/test/mv_web/live/user_live_authorization_test.exs
@@ -10,14 +10,16 @@ defmodule MvWeb.UserLiveAuthorizationTest do
describe "User Index - Admin" do
@tag role: :admin
- test "sees New User, Edit and Delete buttons", %{conn: conn} do
+ test "sees New User button; Edit and Delete are on show page", %{conn: conn} do
user = Fixtures.user_with_role_fixture("admin")
- {:ok, view, _html} = live(conn, "/users")
+ {:ok, index_view, _html} = live(conn, "/users")
+ assert has_element?(index_view, "[data-testid=user-new]")
- assert has_element?(view, "[data-testid=user-new]")
- assert has_element?(view, "#row-#{user.id} [data-testid=user-edit]")
- assert has_element?(view, "#row-#{user.id} [data-testid=user-delete]")
+ # Edit and Delete are on user show page (Danger zone), not on index
+ {:ok, show_view, _html} = live(conn, "/users/#{user.id}")
+ assert has_element?(show_view, "[data-testid=user-edit]")
+ assert has_element?(show_view, "[data-testid=user-delete]")
end
end
diff --git a/test/mv_web/user_live/index_test.exs b/test/mv_web/user_live/index_test.exs
index 11cd70b..f748000 100644
--- a/test/mv_web/user_live/index_test.exs
+++ b/test/mv_web/user_live/index_test.exs
@@ -16,11 +16,10 @@ defmodule MvWeb.UserLive.IndexTest do
assert html =~ "alice@example.com"
assert html =~ "bob@example.com"
- # UI elements: New User button, action links
+ # UI elements: New User button; row click navigates to show (no Edit/Delete on index)
assert html =~ "New User"
- assert html =~ "Edit"
- assert html =~ "Delete"
- assert html =~ ~r/href="[^"]*\/users\/#{user1.id}\/edit"/
+ # Row or navigation contains user id (e.g. row id or phx-click navigate)
+ assert html =~ "row-#{user1.id}" or html =~ to_string(user1.id)
end
@tag :ui
@@ -116,177 +115,29 @@ defmodule MvWeb.UserLive.IndexTest do
end
end
- describe "checkbox selection functionality" do
- setup do
- user1 = create_test_user(%{email: "user1@example.com", oidc_id: "user1"})
- user2 = create_test_user(%{email: "user2@example.com", oidc_id: "user2"})
- %{users: [user1, user2]}
- end
-
- @tag :ui
- test "shows checkbox UI elements", %{conn: conn, users: [user1, user2]} do
- conn = conn_with_oidc_user(conn)
- {:ok, _view, html} = live(conn, "/users")
-
- # Check select all checkbox exists
- assert html =~ ~s(name="select_all")
- assert html =~ ~s(phx-click="select_all")
-
- # Check individual user checkboxes exist
- assert html =~ ~s(name="#{user1.id}")
- assert html =~ ~s(name="#{user2.id}")
- assert html =~ ~s(phx-click="select_user")
- end
-
- @tag :ui
- test "can select and deselect individual users", %{conn: conn, users: [user1, user2]} do
- conn = conn_with_oidc_user(conn)
- {:ok, view, _html} = live(conn, "/users")
-
- # Initially, individual checkboxes should exist but not be checked
- assert view |> element("input[type='checkbox'][name='#{user1.id}']") |> has_element?()
- assert view |> element("input[type='checkbox'][name='#{user2.id}']") |> has_element?()
-
- refute view
- |> element("input[type='checkbox'][name='select_all'][checked]")
- |> has_element?()
-
- # Select first user checkbox
- html = view |> element("input[type='checkbox'][name='#{user1.id}']") |> render_click()
- assert html =~ "Email"
- assert html =~ to_string(user1.email)
-
- # The select_all checkbox should still not be checked (not all users selected)
- refute view
- |> element("input[type='checkbox'][name='select_all'][checked]")
- |> has_element?()
-
- # Deselect user
- html = view |> element("input[type='checkbox'][name='#{user1.id}']") |> render_click()
- assert html =~ "Email"
-
- refute view
- |> element("input[type='checkbox'][name='select_all'][checked]")
- |> has_element?()
- end
-
- @tag :ui
- test "select all and deselect all functionality", %{conn: conn, users: [user1, user2]} do
- conn = conn_with_oidc_user(conn)
- {:ok, view, _html} = live(conn, "/users")
-
- # Initially no checkboxes should be checked
- refute view
- |> element("input[type='checkbox'][name='select_all'][checked]")
- |> has_element?()
-
- refute view
- |> element("input[type='checkbox'][name='#{user1.id}'][checked]")
- |> has_element?()
-
- refute view
- |> element("input[type='checkbox'][name='#{user2.id}'][checked]")
- |> has_element?()
-
- # Click select all
- html = view |> element("input[type='checkbox'][name='select_all']") |> render_click()
-
- # After selecting all, the select_all checkbox should be checked
- assert view
- |> element("input[type='checkbox'][name='select_all'][checked]")
- |> has_element?()
-
- assert html =~ "Email"
- assert html =~ to_string(user1.email)
- assert html =~ to_string(user2.email)
-
- # Then deselect all
- html = view |> element("input[type='checkbox'][name='select_all']") |> render_click()
-
- # After deselecting all, no checkboxes should be checked
- refute view
- |> element("input[type='checkbox'][name='select_all'][checked]")
- |> has_element?()
-
- refute view
- |> element("input[type='checkbox'][name='#{user1.id}'][checked]")
- |> has_element?()
-
- refute view
- |> element("input[type='checkbox'][name='#{user2.id}'][checked]")
- |> has_element?()
-
- assert html =~ "Email"
- end
-
- @tag :slow
- test "select all automatically checks when all individual users are selected", %{
- conn: conn,
- users: [_user1, _user2]
- } do
- conn = conn_with_oidc_user(conn)
- {:ok, view, html} = live(conn, "/users")
-
- # Get all user IDs from the rendered HTML by finding all checkboxes with phx-click="select_user"
- # Extract user IDs from the HTML (they appear as name attributes on checkboxes)
- user_ids =
- html
- |> String.split("phx-click=\"select_user\"")
- |> Enum.flat_map(fn part ->
- case Regex.run(~r/name="([^"]+)"[^>]*phx-value-id/, part) do
- [_, user_id] -> [user_id]
- _ -> []
- end
- end)
- |> Enum.uniq()
-
- # Skip if no users found (shouldn't happen, but be safe)
- if user_ids != [] do
- # Initially nothing should be checked
- refute view
- |> element("input[type='checkbox'][name='select_all'][checked]")
- |> has_element?()
-
- # Select all users one by one
- Enum.each(user_ids, fn user_id ->
- view |> element("input[type='checkbox'][name='#{user_id}']") |> render_click()
- end)
-
- # Now select all should be automatically checked (all individual users are selected)
- assert view
- |> element("input[type='checkbox'][name='select_all'][checked]")
- |> has_element?()
- end
- end
- end
-
describe "delete functionality" do
- test "can delete a user", %{conn: conn} do
- _user = create_test_user(%{email: "delete-me@example.com"})
+ # Delete is only on user show page (Danger zone), not on index (per CODE_GUIDELINES: at most one UI smoke test for delete)
+ test "can delete a user from show page", %{conn: conn} do
+ user = create_test_user(%{email: "delete-me@example.com"})
conn = conn_with_oidc_user(conn)
- {:ok, view, _html} = live(conn, "/users")
+ {:ok, index_view, _html} = live(conn, "/users")
+ assert render(index_view) =~ "delete-me@example.com"
- # Confirm user is displayed
- assert render(view) =~ "delete-me@example.com"
+ # Navigate to user show and trigger delete from Danger zone
+ {:ok, show_view, _html} = live(conn, "/users/#{user.id}")
- # Click the delete button (phx-click="delete" event)
- view |> element("tbody tr:first-child a[data-confirm]") |> render_click()
+ show_view
+ |> element("[data-testid=user-delete]")
+ |> render_click()
- # Verify user was actually deleted (should not appear in HTML anymore)
- html = render(view)
+ # Should redirect to index
+ assert_redirect(show_view, "/users")
+
+ # Reload index with same session; user should be gone
+ {:ok, _view_after, html} = live(conn, "/users")
refute html =~ "delete-me@example.com"
- # Table header should still be there
assert html =~ "Email"
end
-
- test "shows delete confirmation", %{conn: conn} do
- _user = create_test_user(%{email: "confirm-delete@example.com"})
- conn = conn_with_oidc_user(conn)
- {:ok, _view, html} = live(conn, "/users")
-
- # Check that delete link has confirmation attribute
- assert html =~ ~s(data-confirm="Are you sure?")
- end
end
describe "navigation" do
@@ -296,36 +147,14 @@ defmodule MvWeb.UserLive.IndexTest do
conn = conn_with_oidc_user(conn)
{:ok, _view, html} = live(conn, "/users")
- # Check that user row contains link to show page
+ # Row click navigates to show page (edit is on show page)
assert html =~ ~s(/users/#{user.id})
- # Check edit link points to correct edit page
- assert html =~ ~s(/users/#{user.id}/edit)
-
# Check new user button points to correct new page
assert html =~ ~s(/users/new)
end
end
- describe "translations" do
- @tag :ui
- test "shows translations for selection in different locales", %{conn: conn} do
- conn = conn_with_oidc_user(conn)
-
- # Test German translations
- conn = Plug.Test.init_test_session(conn, locale: "de")
- {:ok, _view, html_de} = live(conn, "/users")
- assert html_de =~ "Alle Benutzer*innen auswählen"
- assert html_de =~ "Benutzer*in auswählen"
-
- # Test English translations
- Gettext.put_locale(MvWeb.Gettext, "en")
- {:ok, _view, html_en} = live(conn, "/users")
- # Check that aria-label attributes exist (structure is there)
- assert html_en =~ ~s(aria-label=)
- end
- end
-
describe "edge cases" do
test "handles empty user list gracefully", %{conn: conn} do
# Don't create any users besides the authenticated one