style: highlight selected table and add tooltip
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
carla 2026-02-25 13:16:27 +01:00
parent 02af136fd9
commit 49fd2181a7
19 changed files with 687 additions and 151 deletions

View file

@ -460,7 +460,7 @@ defmodule MvWeb.Components.MemberFilterComponent do
boolean_filter_label(boolean_custom_fields, boolean_filters)
true ->
gettext("All")
gettext("Apply filters")
end
end
@ -487,7 +487,7 @@ defmodule MvWeb.Components.MemberFilterComponent do
# Get boolean filter label (comma-separated list of active filter names)
defp boolean_filter_label(_boolean_custom_fields, boolean_filters)
when map_size(boolean_filters) == 0 do
gettext("Apply filters")
gettext("All")
end
defp boolean_filter_label(boolean_custom_fields, boolean_filters) do

View file

@ -59,6 +59,7 @@ defmodule MvWeb.CustomFieldLive.IndexComponent do
JS.push("edit_custom_field", value: %{id: custom_field.id}, target: @myself)
end
}
row_tooltip={gettext("Click for dataield details")}
>
<:col :let={{_id, custom_field}} label={gettext("Name")}>{custom_field.name}</:col>

View file

@ -62,6 +62,7 @@ defmodule MvWeb.GroupLive.Index do
rows={@groups}
row_id={fn group -> "group-#{group.id}" end}
row_click={fn group -> JS.navigate(~p"/groups/#{group.slug}") end}
row_tooltip={gettext("Click for group details")}
>
<:col :let={group} label={gettext("Name")}>
{group.name}

View file

@ -57,6 +57,7 @@ defmodule MvWeb.MemberFieldLive.IndexComponent do
JS.push("edit_member_field", value: %{"field" => field_name}, target: @myself)
end
}
row_tooltip={gettext("Click for datafield details")}
>
<:col :let={{_field_name, field_data}} label={gettext("Name")}>
{MemberFields.label(field_data.field)}

View file

@ -122,6 +122,7 @@ defmodule MvWeb.MemberLive.Index do
|> assign(:groups, groups)
|> assign(:boolean_custom_field_filters, %{})
|> assign(:selected_members, MapSet.new())
|> assign(:selected_member_id, nil)
|> assign(:settings, settings)
|> assign(:custom_fields_visible, custom_fields_visible)
|> assign(:all_custom_fields, all_custom_fields)
@ -160,6 +161,12 @@ defmodule MvWeb.MemberLive.Index do
- `"select_all"` - Toggles selection of all visible members
- `"sort"` - Sort event from SortHeaderComponent. Updates sort field/order and syncs URL
"""
@impl true
def handle_event("select_row_and_navigate", %{"id" => id}, socket) do
# Navigate to member show. Back button on show page uses ?highlight=id so returning to index shows row as selected.
{:noreply, push_navigate(socket, to: ~p"/members/#{id}")}
end
@impl true
def handle_event("select_member", %{"id" => id}, socket) do
selected =
@ -599,6 +606,7 @@ defmodule MvWeb.MemberLive.Index do
|> assign(:member_fields_visible_db, visible_member_fields_db)
|> assign(:member_fields_visible_computed, visible_member_fields_computed)
|> assign(:visible_custom_field_ids, extract_custom_field_ids(visible_custom_fields))
|> assign(:selected_member_id, parse_highlight_param(params["highlight"]))
next_sig = build_signature(socket)
@ -798,6 +806,18 @@ defmodule MvWeb.MemberLive.Index do
end
end
# Parses optional "highlight" URL param (member id for selected row styling). Returns nil if missing or invalid.
defp parse_highlight_param(nil), do: nil
defp parse_highlight_param(""), do: nil
defp parse_highlight_param(id) when is_binary(id) do
if String.length(id) <= @max_uuid_length and match?({:ok, _}, Ecto.UUID.cast(id)),
do: id,
else: nil
end
defp parse_highlight_param(_), do: nil
defp merge_fields_param_from_uri(params, nil), do: params
defp merge_fields_param_from_uri(params, %URI{query: query}) when is_binary(query) do

View file

@ -59,6 +59,7 @@
variant="secondary"
class={["gap-2", @show_current_cycle && "btn-active"]}
phx-click="toggle_cycle_view"
data-testid="toggle-cycle-view"
aria-label={
if(@show_current_cycle,
do: gettext("Current Cycle Payment Status"),
@ -93,7 +94,9 @@
id="members"
rows={@members}
row_id={fn member -> "row-#{member.id}" end}
row_click={fn member -> JS.navigate(~p"/members/#{member}") end}
row_click={fn member -> JS.push("select_row_and_navigate", value: %{id: member.id}) end}
row_tooltip={gettext("Click for member details")}
row_selected?={fn member -> MapSet.member?(@selected_members, member.id) end}
dynamic_cols={@dynamic_cols}
sort_field={@sort_field}
sort_order={@sort_order}

View file

@ -34,7 +34,7 @@ defmodule MvWeb.MemberLive.Show do
{MvWeb.Helpers.MemberHelpers.display_name(@member)}
<:actions>
<.button
navigate={~p"/members"}
navigate={~p"/members?highlight=#{@member.id}"}
variant="neutral"
aria-label={gettext("Back to members list")}
>

View file

@ -17,6 +17,7 @@
id="roles"
rows={@roles}
row_click={fn role -> JS.navigate(~p"/admin/roles/#{role}") end}
row_tooltip={gettext("Click for role details")}
>
<:col :let={role} label={gettext("Name")}>
<div class="flex items-center gap-2">

View file

@ -174,8 +174,8 @@ defmodule MvWeb.RoleLive.Show do
{gettext("Back")}
</.button>
<%= if can?(@current_user, :update, Mv.Authorization.Role) do %>
<.button variant="primary" navigate={~p"/admin/roles/#{@role}/edit"}>
<.icon name="hero-pencil-square" /> {gettext("Rolle bearbeiten")}
<.button variant="primary" navigate={~p"/admin/roles/#{@role}/edit"} data-testid=role-edit">
{gettext("Edit role")}
</.button>
<% end %>
<%= if can?(@current_user, :destroy, Mv.Authorization.Role) and not @role.is_system_role do %>

View file

@ -15,6 +15,7 @@
rows={@users}
row_id={fn user -> "row-#{user.id}" end}
row_click={fn user -> JS.navigate(~p"/users/#{user}") end}
row_tooltip={gettext("Click for user details")}
sort_field={@sort_field}
sort_order={@sort_order}
>