feat: keep empty cells consistent empty
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
9751525a0c
commit
4ac56958b4
18 changed files with 263 additions and 372 deletions
|
|
@ -2779,6 +2779,10 @@ Building accessible applications ensures that all users, including those with di
|
|||
|
||||
- When `row_click` is set, the first column that does not use `col_click` gets `tabindex="0"` and `role="button"` so each row is reachable via Tab. The `TableRowKeydown` hook triggers the row action on Enter and Space (WCAG 2.1.1). Use `row_id` and `row_tooltip` for all clickable tables (e.g. Groups, Users, Roles, Members, Custom Fields, Member Fields) so the table is fully keyboard accessible.
|
||||
|
||||
**Empty table cells (missing values):**
|
||||
|
||||
- Do not use dashes ("-", "—", "–") or "n/a" as placeholders. Use CoreComponents `<.empty_cell sr_text="…">` for a cell with no value, or `<.maybe_value value={…} empty_sr_text="…">` when content is conditional. The cell is visually empty; screen readers get the `sr_text` (e.g. "No cycle", "No group assignment", "Not specified"). See Design Guidelines §8.6.
|
||||
|
||||
**Tab Order:**
|
||||
|
||||
- Ensure logical tab order matches visual order
|
||||
|
|
|
|||
|
|
@ -293,6 +293,12 @@ Notes:
|
|||
- On **mobile**, sticky headers are not used; the layout uses normal flow (header and table scroll with the page) to preserve vertical space.
|
||||
- When the table is inside such a scroll container, use the CoreComponents table’s `sticky_header={true}` so the table’s `<thead>` stays sticky within the scroll area on desktop (`lg:sticky lg:top-0`, opaque background `bg-base-100`, z-index). Sticky areas must not overlap content at 200% zoom; focus order must remain header → filters → table.
|
||||
|
||||
### 8.6 Empty table cells (missing values)
|
||||
- **MUST:** Missing values in tables are shown as **visually empty cells** (no dash, no "n/a").
|
||||
- **MUST NOT:** Use dashes ("-", "—", "–") or "n/a" as placeholders for empty cells.
|
||||
- **MUST:** For accessibility, render a screen-reader-only label so the cell is not announced as "blank". Use the CoreComponents `<.empty_cell sr_text="…">` for a cell that has no value, or `<.maybe_value value={…} empty_sr_text="…">` when the cell content is conditional (value present vs. absent).
|
||||
- **SHOULD:** Use context-specific `sr_text` where it helps (e.g. "No cycle", "No group assignment", "Not specified"). Default for "no value" is "Not specified".
|
||||
|
||||
---
|
||||
|
||||
## 9) Flash / Toast messages (mandatory UX)
|
||||
|
|
|
|||
|
|
@ -300,6 +300,81 @@ defmodule MvWeb.CoreComponents do
|
|||
defp badge_style_class("outline"), do: "badge-outline"
|
||||
defp badge_style_class(_), do: nil
|
||||
|
||||
@doc """
|
||||
Renders a visually empty table cell with screen-reader-only text (WCAG).
|
||||
|
||||
Use when a table cell has no value so that:
|
||||
- The cell appears empty (no dash, no "n/a").
|
||||
- Screen readers still get a meaningful label (e.g. "No cycle", "No group assignment").
|
||||
|
||||
See CODE_GUIDELINES §8 (Empty table cells) and Design Guidelines §8.6.
|
||||
|
||||
## Examples
|
||||
|
||||
<.empty_cell sr_text={gettext("No cycle")} />
|
||||
<.empty_cell sr_text={gettext("No group assignment")} />
|
||||
<.empty_cell sr_text={gettext("Not specified")} />
|
||||
"""
|
||||
attr :sr_text, :string,
|
||||
required: true,
|
||||
doc: "Text read by screen readers when the cell is visually empty"
|
||||
|
||||
def empty_cell(assigns) do
|
||||
~H"""
|
||||
<span class="sr-only">{@sr_text}</span>
|
||||
"""
|
||||
end
|
||||
|
||||
@doc """
|
||||
Renders content when value is present, otherwise an accessible empty cell.
|
||||
|
||||
Use in table cells for optional fields: when `value` is blank, only the
|
||||
screen-reader text is shown (visually empty). Otherwise the inner block is rendered.
|
||||
|
||||
Blank check: `nil`, `false`, `[]`, `""`, whitespace-only string, or `%Ash.NotLoaded{}` count as empty.
|
||||
|
||||
See CODE_GUIDELINES §8 (Empty table cells) and Design Guidelines §8.6.
|
||||
|
||||
## Examples
|
||||
|
||||
<.maybe_value value={member.membership_fee_type} empty_sr_text={gettext("No fee type")}>
|
||||
{member.membership_fee_type.name}
|
||||
</.maybe_value>
|
||||
<.maybe_value value={member.groups} empty_sr_text={gettext("No group assignment")}>
|
||||
<%= for g <- member.groups do %>
|
||||
<.badge variant="primary" style="outline">{g.name}</.badge>
|
||||
<% end %>
|
||||
</.maybe_value>
|
||||
"""
|
||||
attr :value, :any, doc: "Value to check; if blank, empty_cell is rendered"
|
||||
|
||||
attr :empty_sr_text, :string,
|
||||
default: nil,
|
||||
doc: "Screen-reader text when value is blank (default: gettext \"Not specified\")"
|
||||
|
||||
slot :inner_block, required: true
|
||||
|
||||
def maybe_value(assigns) do
|
||||
empty_sr = assigns.empty_sr_text || gettext("Not specified")
|
||||
assigns = assign(assigns, :empty_sr_text, empty_sr)
|
||||
assigns = assign(assigns, :blank?, value_blank?(assigns.value))
|
||||
|
||||
~H"""
|
||||
<%= if @blank? do %>
|
||||
<.empty_cell sr_text={@empty_sr_text} />
|
||||
<% else %>
|
||||
{render_slot(@inner_block)}
|
||||
<% end %>
|
||||
"""
|
||||
end
|
||||
|
||||
defp value_blank?(nil), do: true
|
||||
defp value_blank?(false), do: true
|
||||
defp value_blank?([]), do: true
|
||||
defp value_blank?(%Ash.NotLoaded{}), do: true
|
||||
defp value_blank?(v) when is_binary(v), do: String.trim(v) == ""
|
||||
defp value_blank?(_), do: false
|
||||
|
||||
@doc """
|
||||
Wraps content with a DaisyUI tooltip. Use for icon-only actions, truncated content,
|
||||
or status badges that need explanation (Design Guidelines §8.2).
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ defmodule MvWeb.CustomFieldLive.IndexComponent do
|
|||
</p>
|
||||
<p class="mt-2 text-sm">
|
||||
{gettext(
|
||||
"All datafield values will be permanently deleted when you delete this datfield."
|
||||
"All datafield values will be permanently deleted when you delete this datafield."
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -68,11 +68,9 @@ defmodule MvWeb.GroupLive.Index do
|
|||
{group.name}
|
||||
</:col>
|
||||
<:col :let={group} label={gettext("Description")}>
|
||||
<%= if group.description do %>
|
||||
<.maybe_value value={group.description} empty_sr_text={gettext("Not specified")}>
|
||||
{group.description}
|
||||
<% else %>
|
||||
<span class="text-base-content/50 italic">—</span>
|
||||
<% end %>
|
||||
</.maybe_value>
|
||||
</:col>
|
||||
<:col :let={group} label={gettext("Members")} class="text-right">
|
||||
{group.member_count || 0}
|
||||
|
|
|
|||
|
|
@ -304,16 +304,14 @@ defmodule MvWeb.GroupLive.Show do
|
|||
</.link>
|
||||
</td>
|
||||
<td>
|
||||
<%= if member.email do %>
|
||||
<.maybe_value value={member.email} empty_sr_text={gettext("No email")}>
|
||||
<a
|
||||
href={"mailto:#{member.email}"}
|
||||
class="link link-primary"
|
||||
>
|
||||
{member.email}
|
||||
</a>
|
||||
<% else %>
|
||||
<span class="text-base-content/50 italic">—</span>
|
||||
<% end %>
|
||||
</.maybe_value>
|
||||
</td>
|
||||
<%= if can?(@current_user, :update, @group) do %>
|
||||
<td>
|
||||
|
|
|
|||
|
|
@ -356,11 +356,9 @@
|
|||
"""
|
||||
}
|
||||
>
|
||||
<%= if member.membership_fee_type do %>
|
||||
<.maybe_value value={member.membership_fee_type} empty_sr_text={gettext("Not specified")}>
|
||||
{member.membership_fee_type.name}
|
||||
<% else %>
|
||||
<span class="text-base-content/50">—</span>
|
||||
<% end %>
|
||||
</.maybe_value>
|
||||
</:col>
|
||||
<:col
|
||||
:let={member}
|
||||
|
|
@ -375,7 +373,7 @@
|
|||
{badge.label}
|
||||
</.badge>
|
||||
<% else %>
|
||||
<.badge variant="neutral">{gettext("No cycle")}</.badge>
|
||||
<.empty_cell sr_text={gettext("No cycle")} />
|
||||
<% end %>
|
||||
</:col>
|
||||
<:col
|
||||
|
|
@ -394,18 +392,17 @@
|
|||
"""
|
||||
}
|
||||
>
|
||||
<%= for group <- (member.groups || []) do %>
|
||||
<.badge
|
||||
variant="primary"
|
||||
style="outline"
|
||||
aria-label={gettext("Member of group %{name}", name: group.name)}
|
||||
>
|
||||
{group.name}
|
||||
</.badge>
|
||||
<% end %>
|
||||
<%= if (member.groups || []) == [] do %>
|
||||
<span class="text-base-content/50">—</span>
|
||||
<% end %>
|
||||
<.maybe_value value={member.groups} empty_sr_text={gettext("No group assignment")}>
|
||||
<%= for group <- (member.groups || []) do %>
|
||||
<.badge
|
||||
variant="primary"
|
||||
style="outline"
|
||||
aria-label={gettext("Member of group %{name}", name: group.name)}
|
||||
>
|
||||
{group.name}
|
||||
</.badge>
|
||||
<% end %>
|
||||
</.maybe_value>
|
||||
</:col>
|
||||
<:action :let={member}>
|
||||
<div class="sr-only">
|
||||
|
|
|
|||
|
|
@ -559,7 +559,11 @@ defmodule MvWeb.MemberLive.Show do
|
|||
<%= if @inner_block != [] do %>
|
||||
{render_slot(@inner_block)}
|
||||
<% else %>
|
||||
{display_value(@value)}
|
||||
<%= if value_blank?(@value) do %>
|
||||
<.empty_cell sr_text={gettext("Not set")} />
|
||||
<% else %>
|
||||
{@value}
|
||||
<% end %>
|
||||
<% end %>
|
||||
</dd>
|
||||
</dl>
|
||||
|
|
@ -593,9 +597,9 @@ defmodule MvWeb.MemberLive.Show do
|
|||
# Helper Functions
|
||||
# -----------------------------------------------------------------
|
||||
|
||||
defp display_value(nil), do: render_empty_value()
|
||||
defp display_value(""), do: render_empty_value()
|
||||
defp display_value(value), do: value
|
||||
defp value_blank?(nil), do: true
|
||||
defp value_blank?(v) when is_binary(v), do: String.trim(v) == ""
|
||||
defp value_blank?(_), do: false
|
||||
|
||||
defp format_status_label(:paid), do: gettext("Paid")
|
||||
defp format_status_label(:unpaid), do: gettext("Unpaid")
|
||||
|
|
@ -684,10 +688,10 @@ defmodule MvWeb.MemberLive.Show do
|
|||
if String.trim(value) == "" do
|
||||
render_empty_value()
|
||||
else
|
||||
assigns = %{email: value}
|
||||
assigns = %{email: value, display: value}
|
||||
|
||||
~H"""
|
||||
<.mailto_link email={@email} display={@email} />
|
||||
<.mailto_link email={@email} display={@display} />
|
||||
"""
|
||||
end
|
||||
end
|
||||
|
|
@ -702,17 +706,10 @@ defmodule MvWeb.MemberLive.Show do
|
|||
|
||||
defp format_custom_field_value(value, _type), do: to_string(value)
|
||||
|
||||
# Renders accessible placeholder for empty values
|
||||
# Uses translated text for screen readers while maintaining visual consistency
|
||||
# The visual "—" is hidden from screen readers, while the translated text is only visible to screen readers
|
||||
# Renders accessible empty value: visually empty, screen-reader text only (see Design Guidelines §8.6).
|
||||
# Returns safe HTML so it can be used from helpers without LiveView assigns.
|
||||
defp render_empty_value do
|
||||
assigns = %{text: gettext("Not set")}
|
||||
|
||||
~H"""
|
||||
<span class="text-base-content/50 italic">
|
||||
<span aria-hidden="true">—</span>
|
||||
<span class="sr-only">{@text}</span>
|
||||
</span>
|
||||
"""
|
||||
text = gettext("Not set")
|
||||
{:safe, ["<span class=\"sr-only\">", Phoenix.HTML.Engine.html_escape(text), "</span>"]}
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -101,7 +101,13 @@ defmodule MvWeb.MemberLive.Show.MembershipFeesComponent do
|
|||
<%= for r <- receipts do %>
|
||||
<tr>
|
||||
<%= for {col_key, _header_key} <- cols do %>
|
||||
<td>{format_receipt_cell(col_key, r[col_key])}</td>
|
||||
<td>
|
||||
<%= if (cell_content = format_receipt_cell(col_key, r[col_key])) != nil do %>
|
||||
{cell_content}
|
||||
<% else %>
|
||||
<.empty_cell sr_text={receipt_empty_sr_text(col_key)} />
|
||||
<% end %>
|
||||
</td>
|
||||
<% end %>
|
||||
</tr>
|
||||
<% end %>
|
||||
|
|
@ -1157,7 +1163,11 @@ defmodule MvWeb.MemberLive.Show.MembershipFeesComponent do
|
|||
|> Enum.map(fn {key, msgid} -> {key, Gettext.gettext(MvWeb.Gettext, msgid)} end)
|
||||
end
|
||||
|
||||
defp format_receipt_cell(:amount, nil), do: "—"
|
||||
# Screen-reader text for empty receipt table cells (visually empty, A11y)
|
||||
defp receipt_empty_sr_text(:status), do: gettext("Not set")
|
||||
defp receipt_empty_sr_text(_), do: gettext("Not specified")
|
||||
|
||||
defp format_receipt_cell(:amount, nil), do: nil
|
||||
|
||||
defp format_receipt_cell(:amount, val) when is_number(val) do
|
||||
case Decimal.cast(val) do
|
||||
|
|
@ -1175,7 +1185,7 @@ defmodule MvWeb.MemberLive.Show.MembershipFeesComponent do
|
|||
|
||||
defp format_receipt_cell(:amount, val), do: to_string(val)
|
||||
|
||||
defp format_receipt_cell(:status, nil), do: "—"
|
||||
defp format_receipt_cell(:status, nil), do: nil
|
||||
|
||||
defp format_receipt_cell(:status, val) when is_binary(val) do
|
||||
translate_receipt_status(val)
|
||||
|
|
@ -1183,7 +1193,7 @@ defmodule MvWeb.MemberLive.Show.MembershipFeesComponent do
|
|||
|
||||
defp format_receipt_cell(:status, val), do: translate_receipt_status(to_string(val))
|
||||
|
||||
defp format_receipt_cell(:receiptType, nil), do: "—"
|
||||
defp format_receipt_cell(:receiptType, nil), do: nil
|
||||
|
||||
defp format_receipt_cell(:receiptType, val) when is_binary(val) do
|
||||
translate_receipt_type(val)
|
||||
|
|
@ -1192,7 +1202,7 @@ defmodule MvWeb.MemberLive.Show.MembershipFeesComponent do
|
|||
defp format_receipt_cell(:receiptType, val), do: translate_receipt_type(to_string(val))
|
||||
|
||||
defp format_receipt_cell(col_key, nil) when col_key in [:bookingDate, :createdAt, :updatedAt],
|
||||
do: "—"
|
||||
do: nil
|
||||
|
||||
defp format_receipt_cell(col_key, val) when col_key in [:bookingDate, :createdAt, :updatedAt] do
|
||||
format_receipt_date(val)
|
||||
|
|
@ -1253,7 +1263,7 @@ defmodule MvWeb.MemberLive.Show.MembershipFeesComponent do
|
|||
defp translate_receipt_status("draft"), do: gettext("Draft")
|
||||
defp translate_receipt_status("incompleted"), do: gettext("Incompleted")
|
||||
defp translate_receipt_status("completed"), do: gettext("Completed")
|
||||
defp translate_receipt_status("empty"), do: "—"
|
||||
defp translate_receipt_status("empty"), do: nil
|
||||
defp translate_receipt_status(other), do: other
|
||||
|
||||
# Translate API receipt type values (extend as API returns more values)
|
||||
|
|
|
|||
|
|
@ -329,7 +329,7 @@ defmodule MvWeb.MembershipFeeSettingsLive do
|
|||
</:col>
|
||||
|
||||
<:col :let={mft} label={gettext("Members")}>
|
||||
<.badge variant="neutral">{get_member_count(mft, @member_counts)}</.badge>
|
||||
<span class="text-sm">{get_member_count(mft, @member_counts)}</span>
|
||||
</:col>
|
||||
|
||||
<:action :let={mft}>
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@
|
|||
</:col>
|
||||
|
||||
<:col :let={role} label={gettext("Users")}>
|
||||
<.badge variant="neutral">{get_user_count(role, @user_counts)}</.badge>
|
||||
<span class="text-sm">{get_user_count(role, @user_counts)}</span>
|
||||
</:col>
|
||||
</.table>
|
||||
</Layouts.app>
|
||||
|
|
|
|||
|
|
@ -38,25 +38,25 @@
|
|||
{user.role.name}
|
||||
</:col>
|
||||
<:col :let={user} label={gettext("Linked Member")}>
|
||||
<%= if user.member do %>
|
||||
<.maybe_value value={user.member} empty_sr_text={gettext("No member linked")}>
|
||||
{MvWeb.Helpers.MemberHelpers.display_name(user.member)}
|
||||
<% else %>
|
||||
<span class="text-base-content/70">{gettext("No member linked")}</span>
|
||||
<% end %>
|
||||
</.maybe_value>
|
||||
</:col>
|
||||
<:col :let={user} label={gettext("Password")}>
|
||||
<%= if MvWeb.Helpers.UserHelpers.has_password?(user) do %>
|
||||
<.maybe_value
|
||||
value={MvWeb.Helpers.UserHelpers.has_password?(user)}
|
||||
empty_sr_text={gettext("Not set")}
|
||||
>
|
||||
<span>{gettext("Enabled")}</span>
|
||||
<% else %>
|
||||
<span class="text-base-content/70">—</span>
|
||||
<% end %>
|
||||
</.maybe_value>
|
||||
</:col>
|
||||
<:col :let={user} label={gettext("OIDC")}>
|
||||
<%= if MvWeb.Helpers.UserHelpers.has_oidc?(user) do %>
|
||||
<.maybe_value
|
||||
value={MvWeb.Helpers.UserHelpers.has_oidc?(user)}
|
||||
empty_sr_text={gettext("Not set")}
|
||||
>
|
||||
<span>{gettext("Linked")}</span>
|
||||
<% else %>
|
||||
<span class="text-base-content/70">—</span>
|
||||
<% end %>
|
||||
</.maybe_value>
|
||||
</:col>
|
||||
</.table>
|
||||
</Layouts.app>
|
||||
|
|
|
|||
|
|
@ -591,18 +591,6 @@ msgstr "Diese E-Mail-Adresse ist bereits mit einem anderen OIDC-Konto verknüpft
|
|||
msgid "Custom Fields"
|
||||
msgstr "Benutzerdefinierte Felder"
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{count} member has a value assigned for this custom field."
|
||||
msgid_plural "%{count} members have values assigned for this custom field."
|
||||
msgstr[0] "%{count} Mitglied hat einen Wert für dieses benutzerdefinierte Feld zugewiesen."
|
||||
msgstr[1] "%{count} Mitglieder haben Werte für dieses benutzerdefinierte Feld zugewiesen."
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
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 "Enter the text above to confirm"
|
||||
|
|
@ -788,6 +776,7 @@ msgstr "Beitragsdaten"
|
|||
msgid "Payments"
|
||||
msgstr "Zahlungen"
|
||||
|
||||
#: lib/mv_web/live/datafields_live.ex
|
||||
#: lib/mv_web/live/member_live/form.ex
|
||||
#: lib/mv_web/live/member_live/show.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
|
|
@ -1386,6 +1375,8 @@ msgid "None (no default)"
|
|||
msgstr "Keine (kein Standard)"
|
||||
|
||||
#: lib/mv_web/live/member_live/show.ex
|
||||
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
|
||||
#: lib/mv_web/live/user_live/index.html.heex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Not set"
|
||||
msgstr "Nicht gesetzt"
|
||||
|
|
@ -2918,11 +2909,6 @@ msgstr "Client-ID"
|
|||
msgid "Client Secret"
|
||||
msgstr "Client-Geheimnis"
|
||||
|
||||
#: lib/mv_web/live/datafields_live.ex
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Custom fields"
|
||||
msgstr "Benutzerdefinierte Felder"
|
||||
|
||||
#: lib/mv_web/components/layouts/sidebar.ex
|
||||
#: lib/mv_web/live/datafields_live.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
|
|
@ -2964,11 +2950,6 @@ msgstr "Aus OIDC_REDIRECT_URI"
|
|||
msgid "Groups claim"
|
||||
msgstr "Gruppenclaim"
|
||||
|
||||
#: lib/mv_web/live/datafields_live.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Member fields"
|
||||
msgstr "Mitgliedsfelder"
|
||||
|
||||
#: lib/mv_web/components/layouts/sidebar.ex
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Membership fee settings"
|
||||
|
|
@ -3225,128 +3206,32 @@ msgstr "Verwalte welche Daten du für eure Mitglieder speichern möchtest. Lege
|
|||
msgid "Manage users and their permissions."
|
||||
msgstr "Verwalte Benutzer*innen und ihre Berechtigungen."
|
||||
|
||||
#~ #: 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/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "%{count} member has a value assigned for this datafield."
|
||||
msgid_plural "%{count} members have values assigned for this datafield."
|
||||
msgstr[0] "%{count} Mitglied hat einen Wert für dieses benutzerdefinierte Feld zugewiesen."
|
||||
msgstr[1] "%{count} Mitglieder haben Werte für dieses benutzerdefinierte Feld zugewiesen."
|
||||
|
||||
#~ #: 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/datafields_live.ex
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Individual Datafields"
|
||||
msgstr "Individuelle Datenfelder"
|
||||
|
||||
#~ #: 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_live/index.html.heex
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "No group assignment"
|
||||
msgstr "Keine Gruppenzuordnung"
|
||||
|
||||
#~ #: 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/components/core_components.ex
|
||||
#: lib/mv_web/live/group_live/index.ex
|
||||
#: lib/mv_web/live/member_live/index.html.heex
|
||||
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Not specified"
|
||||
msgstr "Nicht angegeben"
|
||||
|
||||
#~ #: lib/mv_web/live/member_live/form.ex
|
||||
#~ #, elixir-autogen, elixir-format
|
||||
#~ msgid "Coming soon"
|
||||
#~ msgstr "Demnächst verfügbar"
|
||||
|
||||
#~ #: lib/mv_web/live/membership_fee_settings_live.ex
|
||||
#~ #, elixir-autogen, elixir-format, fuzzy
|
||||
#~ msgid "Configure global settings and fee types for membership fees."
|
||||
#~ msgstr "Globale Einstellungen für Mitgliedsbeiträge konfigurieren."
|
||||
|
||||
#~ #: lib/mv_web/live/datafields_live.ex
|
||||
#~ #, elixir-autogen, elixir-format
|
||||
#~ msgid "Configure member fields and custom data fields."
|
||||
#~ msgstr "Mitgliedsfelder und benutzerdefinierte Datenfelder konfigurieren."
|
||||
|
||||
#~ #: 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/import_live.ex
|
||||
#~ #, elixir-autogen, elixir-format
|
||||
#~ msgid "Datei auswählen"
|
||||
#~ msgstr "Datei auswählen"
|
||||
|
||||
#~ #: 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/statistics_live.ex
|
||||
#~ #, elixir-autogen, elixir-format
|
||||
#~ msgid "Overview from first membership to today"
|
||||
#~ msgstr "Übersicht vom ersten Eintritt bis heute"
|
||||
|
||||
#~ #: lib/mv_web/live/components/member_filter_component.ex
|
||||
#~ #, elixir-autogen, elixir-format
|
||||
#~ msgid "Reset"
|
||||
#~ msgstr "Zurücksetzen"
|
||||
|
||||
#~ #: lib/mv_web/live/role_live/show.ex
|
||||
#~ #, elixir-autogen, elixir-format
|
||||
#~ msgid "Rolle bearbeiten"
|
||||
#~ msgstr "Rolle bearbeiten"
|
||||
|
||||
#~ #: lib/mv_web/live/role_live/form.ex
|
||||
#~ #, elixir-autogen, elixir-format
|
||||
#~ 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/user_live/show.ex
|
||||
#~ #, elixir-autogen, elixir-format
|
||||
#~ msgid "This is a user record from your database."
|
||||
#~ msgstr "Dies ist ein Benutzer*innen-Datensatz aus Ihrer Datenbank."
|
||||
|
||||
#~ #: lib/mv_web/live/membership_fee_type_live/form.ex
|
||||
#~ #, elixir-autogen, elixir-format
|
||||
#~ msgid "Use this form to manage membership fee types in your database."
|
||||
#~ msgstr "Verwende dieses Formular, um Mitgliedsbeitragsarten in deiner Datenbank zu verwalten."
|
||||
|
||||
#~ #: lib/mv_web/live/role_live/form.ex
|
||||
#~ #, elixir-autogen, elixir-format
|
||||
#~ msgid "Use this form to manage roles in your database."
|
||||
#~ msgstr "Verwende dieses Formular, um Rollen in deiner Datenbank zu verwalten."
|
||||
|
||||
#~ #: lib/mv_web/live/user_live/form.ex
|
||||
#~ #, elixir-autogen, elixir-format
|
||||
#~ msgid "Use this form to manage user records in your database."
|
||||
#~ msgstr "Verwende dieses Formular, um Benutzer*innen-Datensätze zu verwalten."
|
||||
|
||||
#~ #: 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"
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "All datafield values will be permanently deleted when you delete this datafield."
|
||||
msgstr "Alle benutzerdefinierten Feldwerte werden beim Löschen dieses benutzerdefinierten Feldes dauerhaft gelöscht."
|
||||
|
|
|
|||
|
|
@ -592,18 +592,6 @@ msgstr ""
|
|||
msgid "Custom Fields"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{count} member has a value assigned for this custom field."
|
||||
msgid_plural "%{count} members have values assigned for this custom field."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
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 "Enter the text above to confirm"
|
||||
|
|
@ -789,6 +777,7 @@ msgstr ""
|
|||
msgid "Payments"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/datafields_live.ex
|
||||
#: lib/mv_web/live/member_live/form.ex
|
||||
#: lib/mv_web/live/member_live/show.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
|
|
@ -1387,6 +1376,8 @@ msgid "None (no default)"
|
|||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/member_live/show.ex
|
||||
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
|
||||
#: lib/mv_web/live/user_live/index.html.heex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Not set"
|
||||
msgstr ""
|
||||
|
|
@ -2918,11 +2909,6 @@ msgstr ""
|
|||
msgid "Client Secret"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/datafields_live.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Custom fields"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/components/layouts/sidebar.ex
|
||||
#: lib/mv_web/live/datafields_live.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
|
|
@ -2964,11 +2950,6 @@ msgstr ""
|
|||
msgid "Groups claim"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/datafields_live.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Member fields"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/components/layouts/sidebar.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Membership fee settings"
|
||||
|
|
@ -3224,3 +3205,33 @@ msgstr ""
|
|||
#, elixir-autogen, elixir-format
|
||||
msgid "Manage users and their permissions."
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{count} member has a value assigned for this datafield."
|
||||
msgid_plural "%{count} members have values assigned for this datafield."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: lib/mv_web/live/datafields_live.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Individual Datafields"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/member_live/index.html.heex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "No group assignment"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/components/core_components.ex
|
||||
#: lib/mv_web/live/group_live/index.ex
|
||||
#: lib/mv_web/live/member_live/index.html.heex
|
||||
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Not specified"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "All datafield values will be permanently deleted when you delete this datafield."
|
||||
msgstr ""
|
||||
|
|
|
|||
|
|
@ -592,18 +592,6 @@ msgstr ""
|
|||
msgid "Custom Fields"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{count} member has a value assigned for this custom field."
|
||||
msgid_plural "%{count} members have values assigned for this custom field."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
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 "Enter the text above to confirm"
|
||||
|
|
@ -789,6 +777,7 @@ msgstr ""
|
|||
msgid "Payments"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/datafields_live.ex
|
||||
#: lib/mv_web/live/member_live/form.ex
|
||||
#: lib/mv_web/live/member_live/show.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
|
|
@ -1387,6 +1376,8 @@ msgid "None (no default)"
|
|||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/member_live/show.ex
|
||||
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
|
||||
#: lib/mv_web/live/user_live/index.html.heex
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Not set"
|
||||
msgstr ""
|
||||
|
|
@ -2918,11 +2909,6 @@ msgstr ""
|
|||
msgid "Client Secret"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/datafields_live.ex
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Custom fields"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/components/layouts/sidebar.ex
|
||||
#: lib/mv_web/live/datafields_live.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
|
|
@ -2964,11 +2950,6 @@ msgstr ""
|
|||
msgid "Groups claim"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/live/datafields_live.ex
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Member fields"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mv_web/components/layouts/sidebar.ex
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Membership fee settings"
|
||||
|
|
@ -3225,123 +3206,32 @@ msgstr ""
|
|||
msgid "Manage users and their permissions."
|
||||
msgstr ""
|
||||
|
||||
#~ #: lib/mv_web/live/member_field_live/form_component.ex
|
||||
#~ #, elixir-autogen, elixir-format
|
||||
#~ msgid "Back to Settings"
|
||||
#~ msgstr ""
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "%{count} member has a value assigned for this datafield."
|
||||
msgid_plural "%{count} members have values assigned for this datafield."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#~ #: lib/mv_web/live/role_live/index.html.heex
|
||||
#~ #, elixir-autogen, elixir-format
|
||||
#~ msgid "Cannot delete system role"
|
||||
#~ msgstr ""
|
||||
#: lib/mv_web/live/datafields_live.ex
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Individual Datafields"
|
||||
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_live/index.html.heex
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "No group assignment"
|
||||
msgstr ""
|
||||
|
||||
#~ #: lib/mv_web/live/member_field_live/index_component.ex
|
||||
#~ #, elixir-autogen, elixir-format
|
||||
#~ msgid "Click for datafield details"
|
||||
#~ msgstr ""
|
||||
#: lib/mv_web/components/core_components.ex
|
||||
#: lib/mv_web/live/group_live/index.ex
|
||||
#: lib/mv_web/live/member_live/index.html.heex
|
||||
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Not specified"
|
||||
msgstr ""
|
||||
|
||||
#~ #: lib/mv_web/live/member_live/form.ex
|
||||
#~ #, elixir-autogen, elixir-format
|
||||
#~ msgid "Coming soon"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ #: lib/mv_web/live/membership_fee_settings_live.ex
|
||||
#~ #, elixir-autogen, elixir-format, fuzzy
|
||||
#~ msgid "Configure global settings and fee types for membership fees."
|
||||
#~ msgstr ""
|
||||
|
||||
#~ #: lib/mv_web/live/datafields_live.ex
|
||||
#~ #, elixir-autogen, elixir-format
|
||||
#~ msgid "Configure member fields and custom data fields."
|
||||
#~ 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/statistics_live.ex
|
||||
#~ #, elixir-autogen, elixir-format
|
||||
#~ msgid "Overview from first membership to today"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ #: lib/mv_web/live/components/member_filter_component.ex
|
||||
#~ #, elixir-autogen, elixir-format
|
||||
#~ msgid "Reset"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ #: lib/mv_web/live/role_live/show.ex
|
||||
#~ #, elixir-autogen, elixir-format
|
||||
#~ msgid "Rolle bearbeiten"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ #: lib/mv_web/live/role_live/form.ex
|
||||
#~ #, elixir-autogen, elixir-format, fuzzy
|
||||
#~ 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/user_live/show.ex
|
||||
#~ #, elixir-autogen, elixir-format, fuzzy
|
||||
#~ msgid "This is a user record from your database."
|
||||
#~ msgstr ""
|
||||
|
||||
#~ #: lib/mv_web/live/membership_fee_type_live/form.ex
|
||||
#~ #, elixir-autogen, elixir-format, fuzzy
|
||||
#~ msgid "Use this form to manage membership fee types in your database."
|
||||
#~ msgstr ""
|
||||
|
||||
#~ #: lib/mv_web/live/role_live/form.ex
|
||||
#~ #, elixir-autogen, elixir-format, fuzzy
|
||||
#~ msgid "Use this form to manage roles in your database."
|
||||
#~ msgstr ""
|
||||
|
||||
#~ #: lib/mv_web/live/user_live/form.ex
|
||||
#~ #, elixir-autogen, elixir-format, fuzzy
|
||||
#~ msgid "Use this form to manage user records in your database."
|
||||
#~ 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 ""
|
||||
#: lib/mv_web/live/custom_field_live/index_component.ex
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "All datafield values will be permanently deleted when you delete this datafield."
|
||||
msgstr ""
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ defmodule MvWeb.CustomFieldLive.DeletionTest do
|
|||
refute has_element?(view, "h2", "Custom fields")
|
||||
|
||||
# Should show correct member count (1 member)
|
||||
assert render(view) =~ "1 member has a value assigned for this custom field"
|
||||
assert render(view) =~ "1 member has a value assigned for this datafield"
|
||||
|
||||
# Should show the slug
|
||||
assert render(view) =~ custom_field.slug
|
||||
|
|
@ -95,7 +95,7 @@ defmodule MvWeb.CustomFieldLive.DeletionTest do
|
|||
open_delete_modal(view, custom_field)
|
||||
|
||||
# Should show plural form
|
||||
assert render(view) =~ "2 members have values assigned for this custom field"
|
||||
assert render(view) =~ "2 members have values assigned for this datafield"
|
||||
end
|
||||
|
||||
test "shows 0 members for custom field without values", %{conn: conn} do
|
||||
|
|
@ -105,7 +105,7 @@ defmodule MvWeb.CustomFieldLive.DeletionTest do
|
|||
open_delete_modal(view, custom_field)
|
||||
|
||||
# Should show 0 members
|
||||
assert render(view) =~ "0 members have values assigned for this custom field"
|
||||
assert render(view) =~ "0 members have values assigned for this datafield"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -95,6 +95,20 @@ defmodule MvWeb.MemberLive.IndexGroupsDisplayTest do
|
|||
assert html =~ member3.first_name
|
||||
end
|
||||
|
||||
test "empty group cell is visually empty with sr-only text (no dash)", %{
|
||||
conn: conn,
|
||||
member3: member3
|
||||
} do
|
||||
conn = conn_with_oidc_user(conn)
|
||||
{:ok, _view, html} = live(conn, "/members")
|
||||
assert html =~ member3.first_name
|
||||
# Screen reader gets a meaningful label for the empty cell
|
||||
assert html =~ "sr-only"
|
||||
assert html =~ "No group assignment"
|
||||
# No visible dash as placeholder (Design Guidelines §8.6)
|
||||
refute html =~ ~r/<span[^>]*class="[^"]*text-base-content\/50[^"]*"[^>]*>—<\/span>/
|
||||
end
|
||||
|
||||
test "displays group name correctly in badge", %{conn: conn, group1: group1} do
|
||||
conn = conn_with_oidc_user(conn)
|
||||
{:ok, _view, html} = live(conn, "/members")
|
||||
|
|
|
|||
|
|
@ -210,7 +210,9 @@ defmodule MvWeb.UserLive.IndexTest do
|
|||
end
|
||||
|
||||
describe "Password column display" do
|
||||
test "user without password shows em dash in Password column", %{conn: conn} do
|
||||
test "user without password shows empty cell with sr-only text in Password column", %{
|
||||
conn: conn
|
||||
} do
|
||||
# User created with hashed_password: nil (no password) - must not get default password
|
||||
user_no_pw =
|
||||
create_test_user(%{
|
||||
|
|
@ -223,9 +225,13 @@ defmodule MvWeb.UserLive.IndexTest do
|
|||
|
||||
assert html =~ "no-password@example.com"
|
||||
|
||||
# Password column must show "—" (em dash) for user without password, not "Enabled"
|
||||
# Password column: visually empty, screen-reader gets "Not set" (Design Guidelines §8.6)
|
||||
row = view |> element("tr#row-#{user_no_pw.id}") |> render()
|
||||
assert row =~ "—", "Password column should show em dash for user without password"
|
||||
assert row =~ "sr-only", "Password column should have sr-only text for accessibility"
|
||||
assert row =~ "Not set", "Screen reader should get 'Not set' for empty password"
|
||||
|
||||
refute row =~ "—",
|
||||
"Password column must not show dash (use empty cell + sr-only per CODE_GUIDELINES §8)"
|
||||
|
||||
refute row =~ "Enabled",
|
||||
"Password column must not show Enabled when user has no password"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue