feat(web): add tooltips to icon-only action buttons
This commit is contained in:
parent
bec49f0771
commit
035edae522
10 changed files with 144 additions and 44 deletions
|
|
@ -586,15 +586,25 @@ defmodule MvWeb.GlobalSettingsLive do
|
||||||
>
|
>
|
||||||
{gettext("Test Integration")}
|
{gettext("Test Integration")}
|
||||||
</.button>
|
</.button>
|
||||||
<.button
|
<.tooltip
|
||||||
:if={Mv.Config.vereinfacht_configured?()}
|
:if={Mv.Config.vereinfacht_configured?()}
|
||||||
|
content={
|
||||||
|
gettext(
|
||||||
|
"Creates a Vereinfacht finance contact for every member that does not have one yet."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
position="top"
|
||||||
|
>
|
||||||
|
<.button
|
||||||
type="button"
|
type="button"
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
phx-click="sync_vereinfacht_contacts"
|
phx-click="sync_vereinfacht_contacts"
|
||||||
phx-disable-with={gettext("Syncing...")}
|
phx-disable-with={gettext("Syncing...")}
|
||||||
|
aria-label={gettext("Sync all members without Vereinfacht contact")}
|
||||||
>
|
>
|
||||||
{gettext("Sync all members without Vereinfacht contact")}
|
{gettext("Sync all members without Vereinfacht contact")}
|
||||||
</.button>
|
</.button>
|
||||||
|
</.tooltip>
|
||||||
</div>
|
</div>
|
||||||
<%= if @vereinfacht_test_result do %>
|
<%= if @vereinfacht_test_result do %>
|
||||||
<.vereinfacht_test_result result={@vereinfacht_test_result} />
|
<.vereinfacht_test_result result={@vereinfacht_test_result} />
|
||||||
|
|
|
||||||
|
|
@ -250,6 +250,7 @@ defmodule MvWeb.GroupLive.Show do
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
<.tooltip content={gettext("Add members")} position="top">
|
||||||
<.button
|
<.button
|
||||||
type="button"
|
type="button"
|
||||||
variant="primary"
|
variant="primary"
|
||||||
|
|
@ -261,6 +262,7 @@ defmodule MvWeb.GroupLive.Show do
|
||||||
>
|
>
|
||||||
<.icon name="hero-plus" class="size-5" />
|
<.icon name="hero-plus" class="size-5" />
|
||||||
</.button>
|
</.button>
|
||||||
|
</.tooltip>
|
||||||
<.button
|
<.button
|
||||||
type="button"
|
type="button"
|
||||||
variant="neutral"
|
variant="neutral"
|
||||||
|
|
|
||||||
|
|
@ -143,16 +143,21 @@ defmodule MvWeb.MemberLive.Show.MembershipFeesComponent do
|
||||||
|
|
||||||
<%!-- Action Buttons (only when user has permission) --%>
|
<%!-- Action Buttons (only when user has permission) --%>
|
||||||
<div class="flex gap-2 mb-4">
|
<div class="flex gap-2 mb-4">
|
||||||
<.button
|
<.tooltip
|
||||||
:if={@member.membership_fee_type != nil and @can_create_cycle}
|
:if={@member.membership_fee_type != nil and @can_create_cycle}
|
||||||
|
content={gettext("Generate cycles from the last existing cycle to today")}
|
||||||
|
position="top"
|
||||||
|
>
|
||||||
|
<.button
|
||||||
phx-click="regenerate_cycles"
|
phx-click="regenerate_cycles"
|
||||||
phx-target={@myself}
|
phx-target={@myself}
|
||||||
class={["btn btn-sm btn-outline", if(@regenerating, do: "btn-disabled", else: "")]}
|
class={["btn btn-sm btn-outline", if(@regenerating, do: "btn-disabled", else: "")]}
|
||||||
title={gettext("Generate cycles from the last existing cycle to today")}
|
aria-label={gettext("Regenerate membership fee cycles")}
|
||||||
>
|
>
|
||||||
<.icon name="hero-arrow-path" class="size-4" />
|
<.icon name="hero-arrow-path" class="size-4" />
|
||||||
{if(@regenerating, do: gettext("Regenerating..."), else: gettext("Regenerate Cycles"))}
|
{if(@regenerating, do: gettext("Regenerating..."), else: gettext("Regenerate Cycles"))}
|
||||||
</.button>
|
</.button>
|
||||||
|
</.tooltip>
|
||||||
<.button
|
<.button
|
||||||
:if={Enum.any?(@cycles) and @can_destroy_cycle}
|
:if={Enum.any?(@cycles) and @can_destroy_cycle}
|
||||||
variant="outline"
|
variant="outline"
|
||||||
|
|
|
||||||
|
|
@ -298,8 +298,12 @@ defmodule MvWeb.MembershipFeeSettingsLive do
|
||||||
<.icon name="hero-trash" class="size-4" />
|
<.icon name="hero-trash" class="size-4" />
|
||||||
</button>
|
</button>
|
||||||
</.tooltip>
|
</.tooltip>
|
||||||
<.button
|
<.tooltip
|
||||||
:if={get_member_count(mft, @member_counts) == 0}
|
:if={get_member_count(mft, @member_counts) == 0}
|
||||||
|
content={gettext("Delete Membership Fee Type")}
|
||||||
|
position="left"
|
||||||
|
>
|
||||||
|
<.button
|
||||||
variant="danger"
|
variant="danger"
|
||||||
size="sm"
|
size="sm"
|
||||||
phx-click="delete"
|
phx-click="delete"
|
||||||
|
|
@ -309,6 +313,7 @@ defmodule MvWeb.MembershipFeeSettingsLive do
|
||||||
>
|
>
|
||||||
<.icon name="hero-trash" class="size-4" />
|
<.icon name="hero-trash" class="size-4" />
|
||||||
</.button>
|
</.button>
|
||||||
|
</.tooltip>
|
||||||
</:action>
|
</:action>
|
||||||
</.table>
|
</.table>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -115,8 +115,12 @@ defmodule MvWeb.MembershipFeeTypeLive.Index do
|
||||||
<.icon name="hero-trash" class="size-4" />
|
<.icon name="hero-trash" class="size-4" />
|
||||||
</button>
|
</button>
|
||||||
</.tooltip>
|
</.tooltip>
|
||||||
<.button
|
<.tooltip
|
||||||
:if={get_member_count(mft, @member_counts) == 0}
|
:if={get_member_count(mft, @member_counts) == 0}
|
||||||
|
content={gettext("Delete Membership Fee Type")}
|
||||||
|
position="left"
|
||||||
|
>
|
||||||
|
<.button
|
||||||
variant="danger"
|
variant="danger"
|
||||||
size="sm"
|
size="sm"
|
||||||
phx-click="delete"
|
phx-click="delete"
|
||||||
|
|
@ -126,6 +130,7 @@ defmodule MvWeb.MembershipFeeTypeLive.Index do
|
||||||
>
|
>
|
||||||
<.icon name="hero-trash" class="size-4" />
|
<.icon name="hero-trash" class="size-4" />
|
||||||
</.button>
|
</.button>
|
||||||
|
</.tooltip>
|
||||||
</:action>
|
</:action>
|
||||||
</.table>
|
</.table>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -791,6 +791,11 @@ msgstr "Beitragsart erstellen"
|
||||||
msgid "Created at:"
|
msgid "Created at:"
|
||||||
msgstr "Erstellt am:"
|
msgstr "Erstellt am:"
|
||||||
|
|
||||||
|
#: lib/mv_web/live/global_settings_live.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Creates a Vereinfacht finance contact for every member that does not have one yet."
|
||||||
|
msgstr "Legt für jedes Mitglied ohne Vereinfacht-Kontakt einen Finanzkontakt an."
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
|
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Credit"
|
msgid "Credit"
|
||||||
|
|
@ -2872,6 +2877,11 @@ msgstr "Weiterleitungs-URI"
|
||||||
msgid "Regenerate Cycles"
|
msgid "Regenerate Cycles"
|
||||||
msgstr "Zyklen regenerieren"
|
msgstr "Zyklen regenerieren"
|
||||||
|
|
||||||
|
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Regenerate membership fee cycles"
|
||||||
|
msgstr "Beitragszyklen neu generieren"
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
|
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Regenerating..."
|
msgid "Regenerating..."
|
||||||
|
|
|
||||||
|
|
@ -792,6 +792,11 @@ msgstr ""
|
||||||
msgid "Created at:"
|
msgid "Created at:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/live/global_settings_live.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Creates a Vereinfacht finance contact for every member that does not have one yet."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
|
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Credit"
|
msgid "Credit"
|
||||||
|
|
@ -2873,6 +2878,11 @@ msgstr ""
|
||||||
msgid "Regenerate Cycles"
|
msgid "Regenerate Cycles"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Regenerate membership fee cycles"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
|
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Regenerating..."
|
msgid "Regenerating..."
|
||||||
|
|
|
||||||
|
|
@ -792,6 +792,11 @@ msgstr ""
|
||||||
msgid "Created at:"
|
msgid "Created at:"
|
||||||
msgstr "Created at:"
|
msgstr "Created at:"
|
||||||
|
|
||||||
|
#: lib/mv_web/live/global_settings_live.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Creates a Vereinfacht finance contact for every member that does not have one yet."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
|
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Credit"
|
msgid "Credit"
|
||||||
|
|
@ -2873,6 +2878,11 @@ msgstr ""
|
||||||
msgid "Regenerate Cycles"
|
msgid "Regenerate Cycles"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Regenerate membership fee cycles"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
|
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Regenerating..."
|
msgid "Regenerating..."
|
||||||
|
|
|
||||||
|
|
@ -300,4 +300,31 @@ defmodule MvWeb.GlobalSettingsLiveTest do
|
||||||
"Single Sign-On"
|
"Single Sign-On"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "Vereinfacht sync control tooltip (§1.9)" do
|
||||||
|
setup %{conn: conn} do
|
||||||
|
user = create_test_user(%{email: "admin@example.com"})
|
||||||
|
conn = conn_with_oidc_user(conn, user)
|
||||||
|
|
||||||
|
System.put_env("VEREINFACHT_API_URL", "https://example.test/api/v1")
|
||||||
|
System.put_env("VEREINFACHT_API_KEY", "test-key")
|
||||||
|
System.put_env("VEREINFACHT_CLUB_ID", "club-1")
|
||||||
|
|
||||||
|
on_exit(fn ->
|
||||||
|
System.delete_env("VEREINFACHT_API_URL")
|
||||||
|
System.delete_env("VEREINFACHT_API_KEY")
|
||||||
|
System.delete_env("VEREINFACHT_CLUB_ID")
|
||||||
|
end)
|
||||||
|
|
||||||
|
{:ok, conn: conn}
|
||||||
|
end
|
||||||
|
|
||||||
|
test "global Vereinfacht sync control carries a tooltip and accessible label", %{conn: conn} do
|
||||||
|
{:ok, view, _html} = live(conn, ~p"/settings")
|
||||||
|
|
||||||
|
# The sync button is wrapped in a <.tooltip> (data-tip) and carries an aria-label
|
||||||
|
assert has_element?(view, ".tooltip[data-tip] button[phx-click=sync_vereinfacht_contacts]")
|
||||||
|
assert has_element?(view, "button[phx-click=sync_vereinfacht_contacts][aria-label]")
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,22 @@ defmodule MvWeb.MemberLive.ShowMembershipFeesTest do
|
||||||
|> Ash.create!(actor: system_actor)
|
|> Ash.create!(actor: system_actor)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "cycle-regeneration control tooltip (§3.5 icon/tooltip audit)" do
|
||||||
|
test "the regenerate_cycles control carries a tooltip and accessible label", %{conn: conn} do
|
||||||
|
fee_type = create_fee_type(%{interval: :yearly})
|
||||||
|
member = Mv.Fixtures.member_fixture(%{membership_fee_type_id: fee_type.id})
|
||||||
|
|
||||||
|
{:ok, view, _html} = live(conn, "/members/#{member.id}")
|
||||||
|
|
||||||
|
view
|
||||||
|
|> element("button[phx-click='switch_tab'][phx-value-tab='membership_fees']")
|
||||||
|
|> render_click()
|
||||||
|
|
||||||
|
assert has_element?(view, ".tooltip[data-tip] button[phx-click=regenerate_cycles]")
|
||||||
|
assert has_element?(view, "button[phx-click=regenerate_cycles][aria-label]")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "cycles table display" do
|
describe "cycles table display" do
|
||||||
test "displays all cycles for member", %{conn: conn} do
|
test "displays all cycles for member", %{conn: conn} do
|
||||||
fee_type = create_fee_type(%{interval: :yearly})
|
fee_type = create_fee_type(%{interval: :yearly})
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue