Improve UX of join requests and fix minor bugs (#492)
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
## Description of the implemented changes The changes were: - [x] Bugfixing - [x] New Feature - [ ] Breaking Change - [ ] Refactoring This PR improves the join-request flow and presentation quality, fixes several data-display issues in join/join-request screens, and adds a usability improvement in global settings (directly opening the join link). It also includes dependency updates and changelog maintenance. ## What has been changed? - Join form (`JoinLive`) now renders inputs based on actual field types (including checkbox/date/number/email behavior instead of generic text-only handling). - Join form custom-field labels are resolved from configured custom fields (fallback remains safe if lookup fails). - Join-request details page (`JoinRequestLive.Show`) now: - resolves and shows custom field names instead of raw IDs, - formats boolean-like values (`on/true/1`, `off/false/0`) as localized `Yes/No`, - formats ISO date strings for better readability, - keeps legacy field handling while improving output consistency. - Join-request detail layout was improved semantically and visually (`dl/dt/dd` structure for label/value rows). - Global settings page now includes an **Open** button for the join URL (`target="_blank"`, `rel="noopener noreferrer"`, ARIA label). - Added/updated tests around: - join field type rendering, - custom field labels in join-request views, - related auth/global-settings behavior. - Updated translations (`default.pot`, `en`, `de`) for new UI strings. - Updated dependencies/tooling (`mix.lock`, `mix.exs`, CI/renovate-related updates). - Updated `CHANGELOG.md` entries for unreleased changes. ## Definition of Done ### Code Quality - [x] No new technical depths - [x] Linting passed - [x] Documentation is added were needed ### Accessibility - [x] New elements are properly defined with html-tags - [x] Colour contrast follows WCAG criteria - [x] Aria labels are added when needed - [x] Everything is accessible by keyboard - [x] Tab-Order is comprehensible - [x] All interactive elements have a visible focus ### Testing - [x] Tests for new code are written - [ ] All tests pass - [ ] axe-core dev tools show no critical or major issues ## Additional Notes - Reviewer focus areas: - `lib/mv_web/live/join_live.ex`: input type derivation and custom field lookup strategy (`authorize?: false` read path used intentionally for field metadata). - `lib/mv_web/live/join_request_live/show.ex`: value-formatting logic (especially backward compatibility for legacy `form_data` payloads). - `lib/mv_web/live/global_settings_live.ex`: external-link behavior and accessibility attributes. - The branch also contains dependency update commits; please review lockfile and CI-related changes separately from functional join/join-request changes. Reviewed-on: #492 Co-authored-by: Simon <s.thiessen@local-it.org> Co-committed-by: Simon <s.thiessen@local-it.org>
This commit is contained in:
parent
bfa33dcae2
commit
2bb01bd201
14 changed files with 781 additions and 135 deletions
|
|
@ -16,9 +16,13 @@ defmodule Mv.Membership.MemberGroupsRelationshipTest do
|
|||
|
||||
describe "Relationships" do
|
||||
test "member has many_to_many groups relationship (load with preloading)", %{actor: actor} do
|
||||
{:ok, member} = Membership.create_member(%{email: "test@test.com"}, actor: actor)
|
||||
{:ok, group1} = Membership.create_group(%{name: "Group One"}, actor: actor)
|
||||
{:ok, group2} = Membership.create_group(%{name: "Group Two"}, actor: actor)
|
||||
{:ok, member} = Membership.create_member(%{email: unique_email("member")}, actor: actor)
|
||||
|
||||
{:ok, group1} =
|
||||
Membership.create_group(%{name: unique_group_name("Group One")}, actor: actor)
|
||||
|
||||
{:ok, group2} =
|
||||
Membership.create_group(%{name: unique_group_name("Group Two")}, actor: actor)
|
||||
|
||||
{:ok, _mg1} =
|
||||
Membership.create_member_group(%{member_id: member.id, group_id: group1.id},
|
||||
|
|
@ -40,9 +44,11 @@ defmodule Mv.Membership.MemberGroupsRelationshipTest do
|
|||
end
|
||||
|
||||
test "load multiple members with groups preloaded (N+1 prevention)", %{actor: actor} do
|
||||
{:ok, member1} = Membership.create_member(%{email: "member1@test.com"}, actor: actor)
|
||||
{:ok, member2} = Membership.create_member(%{email: "member2@test.com"}, actor: actor)
|
||||
{:ok, group} = Membership.create_group(%{name: "Test Group"}, actor: actor)
|
||||
{:ok, member1} = Membership.create_member(%{email: unique_email("member1")}, actor: actor)
|
||||
{:ok, member2} = Membership.create_member(%{email: unique_email("member2")}, actor: actor)
|
||||
|
||||
{:ok, group} =
|
||||
Membership.create_group(%{name: unique_group_name("Test Group")}, actor: actor)
|
||||
|
||||
{:ok, _mg1} =
|
||||
Membership.create_member_group(%{member_id: member1.id, group_id: group.id},
|
||||
|
|
@ -70,8 +76,10 @@ defmodule Mv.Membership.MemberGroupsRelationshipTest do
|
|||
|
||||
describe "Member-Group Association Operations" do
|
||||
test "add member to group via Ash API", %{actor: actor} do
|
||||
{:ok, member} = Membership.create_member(%{email: "test@test.com"}, actor: actor)
|
||||
{:ok, group} = Membership.create_group(%{name: "Test Group"}, actor: actor)
|
||||
{:ok, member} = Membership.create_member(%{email: unique_email("member")}, actor: actor)
|
||||
|
||||
{:ok, group} =
|
||||
Membership.create_group(%{name: unique_group_name("Test Group")}, actor: actor)
|
||||
|
||||
assert {:ok, member_group} =
|
||||
Membership.create_member_group(%{member_id: member.id, group_id: group.id},
|
||||
|
|
@ -83,8 +91,10 @@ defmodule Mv.Membership.MemberGroupsRelationshipTest do
|
|||
end
|
||||
|
||||
test "remove member from group via Ash API", %{actor: actor} do
|
||||
{:ok, member} = Membership.create_member(%{email: "test@test.com"}, actor: actor)
|
||||
{:ok, group} = Membership.create_group(%{name: "Test Group"}, actor: actor)
|
||||
{:ok, member} = Membership.create_member(%{email: unique_email("member")}, actor: actor)
|
||||
|
||||
{:ok, group} =
|
||||
Membership.create_group(%{name: unique_group_name("Test Group")}, actor: actor)
|
||||
|
||||
{:ok, member_group} =
|
||||
Membership.create_member_group(%{member_id: member.id, group_id: group.id},
|
||||
|
|
@ -107,10 +117,16 @@ defmodule Mv.Membership.MemberGroupsRelationshipTest do
|
|||
end
|
||||
|
||||
test "add member to multiple groups in single operation", %{actor: actor} do
|
||||
{:ok, member} = Membership.create_member(%{email: "test@test.com"}, actor: actor)
|
||||
{:ok, group1} = Membership.create_group(%{name: "Group One"}, actor: actor)
|
||||
{:ok, group2} = Membership.create_group(%{name: "Group Two"}, actor: actor)
|
||||
{:ok, group3} = Membership.create_group(%{name: "Group Three"}, actor: actor)
|
||||
{:ok, member} = Membership.create_member(%{email: unique_email("member")}, actor: actor)
|
||||
|
||||
{:ok, group1} =
|
||||
Membership.create_group(%{name: unique_group_name("Group One")}, actor: actor)
|
||||
|
||||
{:ok, group2} =
|
||||
Membership.create_group(%{name: unique_group_name("Group Two")}, actor: actor)
|
||||
|
||||
{:ok, group3} =
|
||||
Membership.create_group(%{name: unique_group_name("Group Three")}, actor: actor)
|
||||
|
||||
# Add to all groups
|
||||
{:ok, _mg1} =
|
||||
|
|
@ -138,8 +154,10 @@ defmodule Mv.Membership.MemberGroupsRelationshipTest do
|
|||
|
||||
describe "Edge Cases" do
|
||||
test "adding member to same group twice fails (duplicate prevention)", %{actor: actor} do
|
||||
{:ok, member} = Membership.create_member(%{email: "test@test.com"}, actor: actor)
|
||||
{:ok, group} = Membership.create_group(%{name: "Test Group"}, actor: actor)
|
||||
{:ok, member} = Membership.create_member(%{email: unique_email("member")}, actor: actor)
|
||||
|
||||
{:ok, group} =
|
||||
Membership.create_group(%{name: unique_group_name("Test Group")}, actor: actor)
|
||||
|
||||
{:ok, _mg1} =
|
||||
Membership.create_member_group(%{member_id: member.id, group_id: group.id},
|
||||
|
|
@ -154,8 +172,10 @@ defmodule Mv.Membership.MemberGroupsRelationshipTest do
|
|||
end
|
||||
|
||||
test "removing member from group they're not in (idempotent, no error)", %{actor: actor} do
|
||||
{:ok, member} = Membership.create_member(%{email: "test@test.com"}, actor: actor)
|
||||
{:ok, group} = Membership.create_group(%{name: "Test Group"}, actor: actor)
|
||||
{:ok, member} = Membership.create_member(%{email: unique_email("member")}, actor: actor)
|
||||
|
||||
{:ok, group} =
|
||||
Membership.create_group(%{name: unique_group_name("Test Group")}, actor: actor)
|
||||
|
||||
# Verify no association exists
|
||||
{:ok, nil} =
|
||||
|
|
@ -194,4 +214,12 @@ defmodule Mv.Membership.MemberGroupsRelationshipTest do
|
|||
assert result == :ok || match?({:error, _}, result)
|
||||
end
|
||||
end
|
||||
|
||||
defp unique_email(prefix) do
|
||||
"#{prefix}-#{System.unique_integer([:positive])}@test.com"
|
||||
end
|
||||
|
||||
defp unique_group_name(prefix) do
|
||||
"#{prefix} #{System.unique_integer([:positive])}"
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue