From 0f12befd11f3f7b2e2c4d3828e9c6e062ff60546 Mon Sep 17 00:00:00 2001 From: carla Date: Wed, 25 Feb 2026 16:25:13 +0100 Subject: [PATCH] style: consistent back button and some translations --- CODE_GUIDELINES.md | 2 +- DESIGN_DUIDELINES.md | 30 +- lib/mv_web/components/core_components.ex | 17 +- .../field_visibility_dropdown_component.ex | 2 +- .../components/member_filter_component.ex | 2 +- .../live/custom_field_live/form_component.ex | 2 +- .../live/custom_field_live/index_component.ex | 2 +- lib/mv_web/live/global_settings_live.ex | 2 +- lib/mv_web/live/group_live/form.ex | 6 +- lib/mv_web/live/group_live/show.ex | 10 +- lib/mv_web/live/member_live/form.ex | 57 ++-- lib/mv_web/live/member_live/show.ex | 8 +- .../live/membership_fee_type_live/form.ex | 16 ++ lib/mv_web/live/role_live/form.ex | 8 +- lib/mv_web/live/role_live/show.ex | 12 +- lib/mv_web/live/user_live/form.ex | 72 +++-- lib/mv_web/live/user_live/index.ex | 42 +-- lib/mv_web/live/user_live/index.html.heex | 27 -- lib/mv_web/live/user_live/show.ex | 64 +++-- priv/gettext/de/LC_MESSAGES/default.po | 265 ++++++++++++------ priv/gettext/default.pot | 214 ++++++++------ priv/gettext/en/LC_MESSAGES/default.po | 265 ++++++++++++------ .../live/custom_field_live/deletion_test.exs | 59 ++-- test/mv_web/live/role_live_test.exs | 52 ++-- .../live/user_live_authorization_test.exs | 12 +- test/mv_web/user_live/index_test.exs | 209 ++------------ 26 files changed, 747 insertions(+), 710 deletions(-) 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