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
|
|
@ -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>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue