Skip to content

fix(user-mgmt): single toast + stable editor on group update (closes #998) - #1002

Merged
cristim merged 1 commit into
feat/multicloud-web-frontendfrom
fix/998-group-update-ux
Jun 6, 2026
Merged

fix(user-mgmt): single toast + stable editor on group update (closes #998)#1002
cristim merged 1 commit into
feat/multicloud-web-frontendfrom
fix/998-group-update-ux

Conversation

@cristim

@cristim cristim commented Jun 5, 2026

Copy link
Copy Markdown
Member

Summary

  • Fixes duplicate success toasts when toggling a group checkbox in the User Management expand panel (listener stacking: each renderUsers() call added another document.addEventListener for group-assign-checkbox change events, so N renders produced N toasts per toggle).
  • Fixes panel collapsing on first checkbox click: toggleUserGroup previously called loadUsers() which called renderUsers() which replaced the whole table innerHTML, resetting all expand rows to hidden.
  • Fixes the first-click-unresponsive-after-collapse symptom, which was a downstream effect of the same re-render teardown.

Root cause

setupUserTableListeners() (called by renderUsers()) registered the group-assign handler with a bare document.addEventListener. No cleanup. Every re-render stacked another listener, so after N group saves the N-th toast fired N times.

toggleUserGroup called loadUsers() on success which called renderUsers() which nuked the DOM and collapsed the panel before the user could make a second group change.

Fix

  • Added a module-level AbortController (groupAssignListenerCtrl). Each setupUserTableListeners() call aborts the previous controller and creates a fresh one, so only one listener is ever active. Same pattern as settings.ts:1564-1565.
  • toggleUserGroup no longer calls loadUsers(). Instead: patch the user in allUsers in-memory, then re-render only the affected expand panel (panel.innerHTML = renderUserExpandPanel(updatedUser)) and the groups-cell badge in the main row. The expand row stays open; the user can make multiple group changes without the panel collapsing.

Test plan

8 new tests added to users.test.ts under group assignment UX (issue #998):

  • Single toggle emits exactly one success toast
  • Three renderUsers() calls before a toggle still emit exactly one toast (direct regression test for listener stacking)
  • Expand row is NOT hidden after a group toggle
  • Expand panel element stays in the DOM after a toggle
  • Expand button opens panel on first click after renderUsers
  • Expand button toggles correctly after multiple renderUsers calls
  • allUsers state reflects added group after toggle
  • allUsers state reflects removed group after toggle

All 204 users tests pass; full 71-suite frontend test run green; tsc --noEmit clean; npm run build succeeds.

closes #998

Summary by CodeRabbit

  • Bug Fixes

    • Fixed group assignment to patch user state in-memory and update only affected UI elements instead of reloading the entire user list.
    • Prevented duplicate toast notifications from stacking listeners during group assignment operations.
  • Tests

    • Added comprehensive tests for group assignment functionality, verifying panel persistence and listener behavior.

…998)

Two bugs on the User Management expand panel:

1. Duplicate toasts: document.addEventListener for group-assign-checkbox
   was called on every renderUsers() invocation, stacking N listeners for N
   renders. A single checkbox change fired all N handlers -> N toasts.
   Fix: module-level AbortController (groupAssignListenerCtrl); abort +
   recreate on each renderUsers() call so only one listener is ever live.

2. Panel collapse + first-click unresponsive: toggleUserGroup called
   loadUsers() on success, which called renderUsers(), which replaced the
   entire table innerHTML and reset every expand row to hidden. The next
   expand-button click reacted correctly (new element, one listener), but
   the UX felt broken because the row collapsed mid-edit.
   Fix: patch the user in allUsers in-memory, then re-render only the
   affected expand panel and groups-cell badge in place. No full re-render,
   no collapse.

Tests: 8 new tests covering single toast (incl. listener-stacking
regression case), panel stays visible after toggle, expand-on-first-click,
and in-memory state patching. All 204 users tests pass; full suite green.
@cristim cristim added triaged Item has been triaged priority/p3 Polish / idea / may never ship severity/low Minor harm urgency/eventually No deadline impact/few Limited audience effort/s Hours type/bug Defect labels Jun 5, 2026
@cristim

cristim commented Jun 5, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Wondering what really moved? Review this PR in Change Stack to inspect semantic changes, definitions, and references.

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 879f7b2c-dad8-4576-a380-8ab5a62fbb30

📥 Commits

Reviewing files that changed from the base of the PR and between 5f037eb and 0c8d1d2.

📒 Files selected for processing (2)
  • frontend/src/__tests__/users.test.ts
  • frontend/src/users/userList.ts

📝 Walkthrough

Walkthrough

This PR fixes issue #998 by preventing duplicate event listeners and avoiding panel collapse during group edits. An AbortController replaces stacked change listeners on each render, eliminating duplicate toasts. In toggleUserGroup, full-user reload is replaced with targeted in-memory state patching and localized UI updates, keeping the expanded panel open during editing.

Changes

Group Assignment UX Fix

Layer / File(s) Summary
Event listener deduplication with AbortController
frontend/src/users/userList.ts
Module-level groupAssignListenerCtrl AbortController is initialized and used to abort prior document-level change listeners before attaching new ones, preventing listener accumulation and duplicate toast emissions on each renderUsers() call.
In-place state and UI patching for group toggles
frontend/src/users/userList.ts
toggleUserGroup documentation and implementation revised to patch userState.allUsers in-memory, re-render the expand panel contents and groups cell inline, and show a single success toast instead of reloading all users, eliminating panel collapse during group edits.
Comprehensive UI behavior tests for group assignment
frontend/src/__tests__/users.test.ts
New test suite validates single-toast emission across repeated renders, expand-panel persistence after toggles, expand-button listener reliability, and in-memory group state synchronization.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A rabbit's cheer for deeds so fine—
One toast, not many, in line!
The panel stays put, no collapse in sight,
The checkbox dance flows smooth and right!

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/998-group-update-ux

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai

coderabbitai Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@cristim

cristim commented Jun 6, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 6, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@cristim
cristim merged commit 7485a75 into feat/multicloud-web-frontend Jun 6, 2026
4 of 5 checks passed
@cristim
cristim deleted the fix/998-group-update-ux branch July 27, 2026 11:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/s Hours impact/few Limited audience priority/p3 Polish / idea / may never ship severity/low Minor harm triaged Item has been triaged type/bug Defect urgency/eventually No deadline

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant