Adds more consistency in various UX topics closes #447 #448

Merged
carla merged 9 commits from feat/447_concistency into main 2026-02-25 17:34:12 +01:00
26 changed files with 747 additions and 710 deletions
Showing only changes of commit 0f12befd11 - Show all commits

View file

@ -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.
---

View file

@ -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.</:subtitle>
<:leading>
<.button navigate={return_path(@return_to, @resource)} variant="neutral">
<.icon name="hero-arrow-left" class="size-4" />
{gettext("Back")}
</.button>
</:leading>
Page title (e.g. “Edit Member” or “New User”)
<:subtitle>Short explanation.</:subtitle>
<:actions>
<.button variant="primary" navigate={...}>Primary action</.button>
<.button phx-disable-with={gettext("Saving...")} variant="primary" type="submit">
{gettext("Save")}
</.button>
</:actions>
</.header>
```
<div class="mt-6 space-y-6">
<!-- Sections / Cards / Tables -->
</div>
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)

View file

@ -111,7 +111,7 @@ defmodule MvWeb.CoreComponents do
<.button variant="ghost" size="sm">Edit</.button>
<.button disabled={true}>Disabled</.button>
"""
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"""
<header class={[@actions != [] && "flex items-center justify-between gap-6", "pb-4", @class]}>
<div>
<header class={["flex items-center gap-6 pb-4", @class]}>
<div :if={@leading != []} class="shrink-0">
{render_slot(@leading)}
</div>
<div class="min-w-0 flex-1">
<h1 class="text-xl font-semibold leading-8">
{render_slot(@inner_block)}
</h1>
@ -651,7 +658,9 @@ defmodule MvWeb.CoreComponents do
{render_slot(@subtitle)}
</p>
</div>
<div class="flex gap-4 justify-end">{render_slot(@actions)}</div>
<div :if={@actions != []} class="shrink-0 flex gap-4 justify-end">
{render_slot(@actions)}
</div>
</header>
"""
end

View file

@ -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

View file

@ -252,7 +252,7 @@ defmodule MvWeb.Components.MemberFilterComponent do
<!-- Custom Fields Group -->
<div :if={length(@boolean_custom_fields) > 0} class="mb-2">
<div class="text-xs font-semibold opacity-70 mb-2 uppercase tracking-wider">
{gettext("Custom Fields")}
{gettext("Individual datafields")}
</div>
<div class="max-h-60 overflow-y-auto pr-2">
<fieldset

View file

@ -107,7 +107,7 @@ defmodule MvWeb.CustomFieldLive.FormComponent do
<div class="border border-base-300 rounded-lg p-4 bg-base-100">
<p class="text-base-content/70 mb-4">
{gettext(
"Deleting this data field cannot be undone. All custom field values for this field will be permanently removed."
"Deleting this data field cannot be undone. All datafield values for this field will be permanently removed."
)}
</p>
<.button

View file

@ -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")}
</.button>
</div>
</div>

View file

@ -95,7 +95,7 @@ defmodule MvWeb.GlobalSettingsLive do
</div>
<.button phx-disable-with={gettext("Saving...")} variant="primary">
{gettext("Save Settings")}
{gettext("Save Name")}
</.button>
</.form>
</.form_section>

View file

@ -79,12 +79,14 @@ defmodule MvWeb.GroupLive.Form do
<Layouts.app flash={@flash} current_user={@current_user}>
<.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")}
</.button>
</:leading>
{@page_title}
<:actions>
<.button phx-disable-with={gettext("Saving...")} variant="primary" type="submit">
{gettext("Save")}
</.button>

View file

@ -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"""
<Layouts.app flash={@flash} current_user={@current_user}>
<.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")}
</.button>
</:leading>
{@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")}
</.button>
<% end %>
</:actions>

View file

@ -39,16 +39,18 @@ defmodule MvWeb.MemberLive.Form do
<Layouts.app flash={@flash} current_user={@current_user}>
<.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")}
</.button>
</:leading>
<%= 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>
<.button phx-disable-with={gettext("Saving...")} variant="primary" type="submit">
{gettext("Save")}
</.button>
@ -408,12 +410,19 @@ defmodule MvWeb.MemberLive.Form do
member = socket.assigns.member
actor = current_actor(socket)
if is_nil(member) do
cond do
is_nil(member) ->
{:noreply, put_flash(socket, :error, gettext("Member not found"))}
else
if to_string(id) != to_string(member.id) do
to_string(id) != to_string(member.id) ->
{:noreply, put_flash(socket, :error, gettext("Member not found"))}
else
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,
@ -423,19 +432,13 @@ defmodule MvWeb.MemberLive.Form do
{:error, %Ash.Error.Forbidden{}} ->
{:noreply,
put_flash(
socket,
:error,
gettext("You do not have permission to delete this member")
)}
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
end
end
defp handle_save_success(socket, member) do
notify_parent({:saved, member})

View file

@ -31,8 +31,7 @@ defmodule MvWeb.MemberLive.Show do
~H"""
<Layouts.app flash={@flash} current_user={@current_user}>
<.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")}
</.button>
</:leading>
{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")}
</.button>
<% end %>
</:actions>

View file

@ -27,10 +27,26 @@ defmodule MvWeb.MembershipFeeTypeLive.Form do
~H"""
<Layouts.app flash={@flash} current_user={@current_user}>
<.header>
<:leading>
<.button navigate={return_path(@return_to, @membership_fee_type)} variant="neutral">
<.icon name="hero-arrow-left" class="size-4" />
{gettext("Back")}
</.button>
</:leading>
{@page_title}
<:subtitle>
{gettext("Use this form to manage membership fee types in your database.")}
</:subtitle>
<:actions>
<.button
form="membership-fee-type-form"
phx-disable-with={gettext("Saving...")}
variant="primary"
type="submit"
>
{gettext("Save")}
</.button>
</:actions>
</.header>
<.form

View file

@ -23,13 +23,15 @@ defmodule MvWeb.RoleLive.Form do
<Layouts.app flash={@flash} current_user={@current_user}>
<.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.")}</:subtitle>
<:actions>
<:leading>
<.button navigate={return_path(@return_to, @role)} variant="neutral">
<.icon name="hero-arrow-left" class="size-4" />
{gettext("Back")}
</.button>
</:leading>
{@page_title}
<:subtitle>{gettext("Use this form to manage roles in your database.")}</:subtitle>
<:actions>
<.button phx-disable-with={gettext("Saving...")} variant="primary" type="submit">
{gettext("Save")}
</.button>

View file

@ -161,10 +161,7 @@ defmodule MvWeb.RoleLive.Show do
~H"""
<Layouts.app flash={@flash} current_user={@current_user}>
<.header>
{gettext("Role")} {@role.name}
<:subtitle>{gettext("Role details and permissions.")}</:subtitle>
<: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")}
</.button>
</:leading>
{gettext("Role")} {@role.name}
<:subtitle>{gettext("Role details and permissions.")}</:subtitle>
<: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")}
</.button>
<% end %>
</:actions>

View file

@ -46,8 +46,24 @@ defmodule MvWeb.UserLive.Form do
~H"""
<Layouts.app flash={@flash} current_user={@current_user}>
<.header>
<:leading>
<.button navigate={return_path(@return_to, @user)} variant="neutral">
<.icon name="hero-arrow-left" class="size-4" />
{gettext("Back")}
</.button>
</:leading>
{@page_title}
<:subtitle>{gettext("Use this form to manage user records in your database.")}</:subtitle>
<:actions>
<.button
form="user-form"
phx-disable-with={gettext("Saving...")}
variant="primary"
type="submit"
>
{gettext("Save User")}
</.button>
</:actions>
</.header>
<.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
cond do
is_nil(user) ->
{:noreply, put_flash(socket, :error, gettext("User not found"))}
else
if to_string(id) != to_string(user.id) do
to_string(id) != to_string(user.id) ->
{: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")
)}
Mv.Helpers.SystemActor.system_user?(user) ->
{:noreply, put_flash(socket, :error, gettext("System user cannot be deleted."))}
{:error, error} ->
{:noreply, put_flash(socket, :error, format_ash_error(error))}
end
end
end
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)

View file

@ -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

View file

@ -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>
<:col
:let={user}
sort_field={:email}

View file

@ -34,14 +34,20 @@ defmodule MvWeb.UserLive.Show do
~H"""
<Layouts.app flash={@flash} current_user={@current_user}>
<.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")}
</.button>
</:leading>
{gettext("User")} {@user.email}
<:subtitle>{gettext("This is a user record from your database.")}</:subtitle>
<:actions>
<.button navigate={~p"/users"} variant="neutral" aria-label={gettext("Back to users list")}>
<.icon name="hero-arrow-left" />
<span class="sr-only">{gettext("Back to users list")}</span>
</.button>
<%= 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,13 +148,19 @@ defmodule MvWeb.UserLive.Show do
user = socket.assigns.user
actor = current_actor(socket)
if to_string(id) != to_string(user.id) do
cond do
to_string(id) != to_string(user.id) ->
{: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
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,
@ -157,17 +170,10 @@ defmodule MvWeb.UserLive.Show do
{:error, %Ash.Error.Forbidden{}} ->
{:noreply,
put_flash(
socket,
:error,
gettext("You do not have permission to delete this user")
)}
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
{:noreply, put_flash(socket, :error, format_ash_error(error))}
end
end
end

View file

@ -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"

View file

@ -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 ""

View file

@ -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 ""

View file

@ -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")

View file

@ -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

View file

@ -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

View file

@ -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