Skip to content

refactor(FR-3848): give the assign modal's user select its own Suspense boundary - #9419

Open
nowgnuesLee wants to merge 3 commits into
mainfrom
FR-3848
Open

refactor(FR-3848): give the assign modal's user select its own Suspense boundary#9419
nowgnuesLee wants to merge 3 commits into
mainfrom
FR-3848

Conversation

@nowgnuesLee

@nowgnuesLee nowgnuesLee commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Resolves #9418 (FR-3848)

Follow-up to #9413 (FR-3725).

Why

#9413 stopped the Add user click from suspending the whole Role assignment tab by deferring the modal's open inside AssignRoleModal (useDeferredValue(open, false) plus a store-only first pass). That keeps the tab rendered, but it is an indirect way of saying "this query needs its own Suspense boundary".

Change

react/src/components/AssignRoleModal.tsx only.

  • The user options query (AssignRoleModalQuery), the search state and the BAISelect move into AssignRoleUserSelect. The deferred-open handling is removed.
  • The Form.Item that renders it is wrapped in a Suspense inline in the form, the same shape as UpdateUsersModal. The fallback is a Form.Item with the same label holding the select in loading + disabled state, so the modal opens at once with no layout shift.
  • maxTagCount / maxTagPlaceholder are dropped while moving the select: BAISelect accepts and ignores both. Their Tooltip / BAIFlex imports go with them.
  • The modal is only mounted while open (BAIUnmountAfterClose), so the fetch policy is a fixed store-and-network.

The GraphQL document is unchanged, so no __generated__ output changes.

Verification

🤖 Generated with Claude Code

…se boundary

`AssignRoleModal` ran `useLazyLoadQuery` in the modal body, so a fresh
mount suspended up to the tab-level boundary; #9413 worked around that by
deferring `open` and reading the store only on the first pass.

Express the boundary directly instead: the user options query, the search
state and the `BAISelect` move into `AssignRoleUserSelect`, rendered
inside its own `Suspense`. The boundary sits inside the `Form.Item` child
so the `userIds` field stays registered while the options load; the
fallback is the same select in `loading` + `disabled` state.

`maxTagCount` / `maxTagPlaceholder` are dropped while moving the select —
`BAISelect` accepts and ignores both — which also retires the `Tooltip`
and `BAIFlex` imports. The modal only mounts while open, so the fetch
policy is a fixed `store-and-network`.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
The wrapper component existed only to hold a Suspense around the select.
Put the boundary inline where the select is rendered instead, wrapping the
Form.Item the way UpdateUsersModal does, with a same-label loading select
as the fallback.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Coverage Report for react-coverage (./react)

Status Category Percentage Covered / Total
🔵 Lines 15.62% 5691 / 36415
🔵 Statements 13.1% 6933 / 52912
🔵 Functions 13.69% 887 / 6479
🔵 Branches 9.47% 4795 / 50598
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
react/src/components/AssignRoleModal.tsx 0% 0% 0% 0% 48-114
Generated in workflow #536 for commit c6a2e8d by the Vitest Coverage Report Action

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The fallback unregisters required validation, allowing an empty assignment during loading.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Refactors the role assignment modal so user loading suspends only the select.

Changes:

  • Extracts the queried user select.
  • Adds an inline loading fallback.
  • Removes deferred modal opening and ignored select props.
File summaries
File Description
react/src/components/AssignRoleModal.tsx Adds the Suspense-bounded user select.
Review details
  • Files reviewed: 1/1 changed files
  • Comments generated: 1
  • Review effort level: Balanced

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

Comment thread react/src/components/AssignRoleModal.tsx Outdated
The Suspense fallback rendered an unnamed Form.Item, so while the query
suspended `validateFields()` skipped `userIds` and Assign could submit an
empty list. Register the same field and required rule on the fallback.

Co-Authored-By: Claude Fable 5.1 <[email protected]>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The focused refactor matches the issue requirements without introducing unresolved issues.

Review details
  • Files reviewed: 1/1 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

@nowgnuesLee
nowgnuesLee marked this pull request as ready for review September 3, 2026 10:11
>;

/** Owns the user options query; render it under a Suspense boundary. */
const AssignRoleUserSelect: React.FC<AssignRoleUserSelectProps> = ({

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about separate this select?

{option.data?.description && (
<div
style={{
fontSize: 12,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please use token value.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

rbac size:L 100~500 LoC

Projects

None yet

Development

Successfully merging this pull request may close these issues.

RBAC role detail > Role assignment: move the user query of the assign modal into its own Suspense-bounded select

3 participants