Skip to content

feat: delete user front end#8877

Merged
csiyang merged 29 commits intomainfrom
siyangcao/nes-1455-deleteuser-frontend
Apr 15, 2026
Merged

feat: delete user front end#8877
csiyang merged 29 commits intomainfrom
siyangcao/nes-1455-deleteuser-frontend

Conversation

@csiyang
Copy link
Copy Markdown
Contributor

@csiyang csiyang commented Mar 19, 2026

Summary by CodeRabbit

  • New Features

    • Dedicated confirmation dialog for permanent user deletion and staged deletion checks with real-time confirmation updates.
  • Bug Fixes

    • Navigation selection now reflects the current page path for the Delete User item.
  • Refactor

    • Reorganized user-deletion components and centralized mutation error handling for clearer, more consistent error messaging.

@csiyang csiyang self-assigned this Mar 19, 2026
@linear
Copy link
Copy Markdown

linear Bot commented Mar 19, 2026

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 19, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 21366fdc-04e7-4d2e-b976-145b315a2ad9

📥 Commits

Reviewing files that changed from the base of the PR and between ea89d14 and ebde122.

📒 Files selected for processing (2)
  • apps/journeys-admin/src/components/UserDelete/UserDelete.tsx
  • apps/journeys-admin/src/components/UserDelete/UserDeleteErrorBoundary.tsx
✅ Files skipped from review due to trivial changes (1)
  • apps/journeys-admin/src/components/UserDelete/UserDeleteErrorBoundary.tsx

Walkthrough

Refactors user deletion by extracting GraphQL documents and UI pieces into separate files, adds an error boundary and confirmation dialog, centralizes mutation error handling, updates Apollo SSE link/header handling and adds createErrorLink, and tweaks navigation selection and tests.

Changes

Cohort / File(s) Summary
User Deletion UI & Documents
apps/journeys-admin/src/components/UserDelete/UserDelete.tsx, apps/journeys-admin/src/components/UserDelete/UserDelete.documents.ts, apps/journeys-admin/src/components/UserDelete/UserDeleteConfirmDialog.tsx, apps/journeys-admin/src/components/UserDelete/UserDeleteErrorBoundary.tsx, apps/journeys-admin/src/components/UserDelete/UserDelete.spec.tsx
Extracted GraphQL documents to UserDelete.documents.ts; replaced inline documents with imports/re-exports; moved ErrorBoundary to its own file and use it; added UserDeleteConfirmDialog component and wired it into UserDelete; centralized mutation error handling via handleMutationError; switched TextField accessibility to slotProps.htmlInput; updated test textbox label selector to "User Email".
Apollo Client & Tests
apps/journeys-admin/src/libs/apolloClient/apolloClient.ts, apps/journeys-admin/src/libs/apolloClient/apolloClient.test.ts
Exported SSELink with simplified constructor and per-request header factory, changed subscription query generation to print(operation.query), renamed unused param to _forward, added exported createErrorLink() to encapsulate UNAUTHENTICATED handling, and expanded tests to cover SSE subscription construction and error-link behavior (including logout on UNAUTHENTICATED).
Navigation
apps/journeys-admin/src/components/PageWrapper/NavigationDrawer/UserNavigation/UserNavigation.tsx
Changed "Delete User" menu item selected check from selectedPage === 'users-delete' to router.pathname === '/users/delete'.
Pages & Localization
apps/journeys-admin/pages/users/verify.tsx, libs/locales/en/apps-journeys-admin.json
Switched catch {} syntax in getServerSideProps and reordered a locale JSON entry (no text changes).

Sequence Diagram(s)

sequenceDiagram
  participant AdminUI as Admin UI
  participant UserDelete as UserDelete Component
  participant Apollo as Apollo Client (SSELink)
  participant GraphQL as GraphQL Server / API
  Note over AdminUI,GraphQL: User deletion flow (check -> confirm -> subscription updates)

  AdminUI->>UserDelete: enter user identifier & click "Check"
  UserDelete->>Apollo: mutation UserDeleteCheck(idType,id,...) 
  Apollo->>GraphQL: HTTP mutation request
  GraphQL-->>Apollo: check response (counts, items to delete/transfer)
  Apollo-->>UserDelete: return check result
  UserDelete->>AdminUI: show results and open Confirm Dialog
  AdminUI->>UserDelete: click "Delete Permanently"
  UserDelete->>Apollo: mutation UserDeleteJourneysConfirm(userId)
  Apollo->>GraphQL: execute confirm mutation
  GraphQL-->>Apollo: confirm ack
  UserDelete->>Apollo: subscribe UserDeleteConfirmSubscription(...) via SSELink
  Apollo->>GraphQL: open SSE subscription (headers via factory, query via print)
  GraphQL-->>Apollo: stream logs/updates (logs, done, success)
  Apollo-->>UserDelete: forward streamed updates
  UserDelete->>AdminUI: render logs/status until done
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: delete user front end' directly summarizes the main change: adding frontend UI for user deletion in the journeys-admin app, which matches the core purpose of all modified and new files in the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 siyangcao/nes-1455-deleteuser-frontend

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@csiyang csiyang changed the title feat: delete user backend feat: delete user front end Mar 19, 2026
@csiyang csiyang changed the base branch from main to siyangcao/nes-1454-deleteuser-backend March 19, 2026 01:53
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 19, 2026

Warnings
⚠️ ❗ Big PR (809 changes)

(change count - 809): Pull Request size seems relatively large. If Pull Request contains multiple changes, split each into separate PR will helps faster, easier review.

Generated by 🚫 dangerJS against 26a418a

@csiyang csiyang marked this pull request as ready for review March 25, 2026 22:13
@csiyang
Copy link
Copy Markdown
Contributor Author

csiyang commented Mar 25, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 25, 2026

✅ Actions performed

Review triggered.

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.

@csiyang
Copy link
Copy Markdown
Contributor Author

csiyang commented Mar 26, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 26, 2026

✅ Actions performed

Review triggered.

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.

@stage-branch-merger
Copy link
Copy Markdown
Contributor

I see you added the "on stage" label, I'll get this merged to the stage branch!

@stage-branch-merger
Copy link
Copy Markdown
Contributor

Merge conflict attempting to merge this into stage. Please fix manually.

@stage-branch-merger
Copy link
Copy Markdown
Contributor

Merge conflict attempting to merge this into stage. Please fix manually.

@jesus-film-bot
Copy link
Copy Markdown

Ran Plan for dir: infrastructure workspace: default

Plan Failed: This project is currently locked by an unapplied plan from pull #8969. To continue, delete the lock from #8969 or apply that plan and merge the pull request.

Once the lock is released, comment atlantis plan here to re-plan.

@jesus-film-bot
Copy link
Copy Markdown

Ran Plan for dir: infrastructure workspace: default

Plan Failed: This project is currently locked by an unapplied plan from pull #8969. To continue, delete the lock from #8969 or apply that plan and merge the pull request.

Once the lock is released, comment atlantis plan here to re-plan.

@jesus-film-bot
Copy link
Copy Markdown

Ran Plan for dir: infrastructure workspace: default

Plan Failed: This project is currently locked by an unapplied plan from pull #8969. To continue, delete the lock from #8969 or apply that plan and merge the pull request.

Once the lock is released, comment atlantis plan here to re-plan.

Copy link
Copy Markdown
Contributor Author

@csiyang csiyang left a comment

Choose a reason for hiding this comment

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

Review summary

Conventions loaded: .claude/rules/frontend/apps.md, .claude/rules/backend/apis.md, apps/journeys-admin/AGENTS.md

Critical: None

Concern (1 item):

  • apps/journeys-admin/src/components/UserDelete/UserDelete.tsx:198<Suspense> has no fallback prop. During the initial GET_ME query, useSuspenseQuery will suspend the component and render nothing (blank area). Should show a loading indicator.

Nit:

  • Lines 551 and 609: onClick={handleCheck} and onClick={handleConfirmDelete} pass async functions directly as event handlers, while the onKeyDown handler on line 543 correctly uses void handleCheck(). Both onClick handlers should use the same pattern: onClick={() => void handleCheck()} / onClick={() => void handleConfirmDelete()}.

Positive:

  • Clean 4-step delete flow with clear separation between the check phase and the delete phase
  • Step 1 logs are preserved even when Step 2 fails — good UX
  • Trust boundary is explicitly documented with a comment in userDeleteConfirm.ts
  • Server-side superAdmin guard in getServerSideProps (defense in depth alongside the client-side check)
  • Lazy isSuperAdmin in authScopes.ts avoids an extra DB roundtrip on every authenticated request
  • Good error recovery — both ApolloError and unknown errors are handled in the catch blocks
  • confirmLoading correctly covers the gap between clicking Delete and the subscription starting
  • Accessibility attributes (aria-label, aria-describedby) on form inputs

Comment thread apps/journeys-admin/src/components/UserDelete/UserDelete.tsx Outdated
Comment thread apps/journeys-admin/src/components/UserDelete/UserDelete.tsx Outdated
Comment thread apps/journeys-admin/src/components/UserDelete/UserDelete.tsx Outdated
@jesus-film-bot
Copy link
Copy Markdown

Ran Plan for dir: infrastructure workspace: default

Plan Failed: This project is currently locked by an unapplied plan from pull #8969. To continue, delete the lock from #8969 or apply that plan and merge the pull request.

Once the lock is released, comment atlantis plan here to re-plan.

@jesus-film-bot
Copy link
Copy Markdown

Ran Plan for dir: infrastructure workspace: default

Plan Failed: This project is currently locked by an unapplied plan from pull #8969. To continue, delete the lock from #8969 or apply that plan and merge the pull request.

Once the lock is released, comment atlantis plan here to re-plan.

Copy link
Copy Markdown
Contributor Author

@csiyang csiyang left a comment

Choose a reason for hiding this comment

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

Round 2 review — all findings resolved

All items from the previous review pass:

  • Suspense fallback ✅ — <Suspense fallback={<CircularProgress />}> added at line 199; CircularProgress imported from @mui/material/CircularProgress
  • Async onClick handlers ✅ — both handleCheck and handleConfirmDelete now use the () => void fn() pattern, consistent with the onKeyDown handler

No new issues introduced by the fix commit.

Critical: None
Concern: None
Overall: Ready to merge.

@github-actions github-actions Bot temporarily deployed to Preview - resources April 15, 2026 08:17 Inactive
@github-actions github-actions Bot temporarily deployed to Preview - watch-modern April 15, 2026 08:17 Inactive
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 15, 2026

The latest updates on your projects.

Name Status Preview Updated (UTC)
watch-modern ✅ Ready watch-modern preview Wed Apr 15 21:18:59 NZST 2026

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 15, 2026

The latest updates on your projects.

Name Status Preview Updated (UTC)
player ✅ Ready player preview Wed Apr 15 21:19:23 NZST 2026

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 15, 2026

The latest updates on your projects.

Name Status Preview Updated (UTC)
videos-admin ✅ Ready videos-admin preview Wed Apr 15 21:19:21 NZST 2026

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
apps/journeys-admin/src/components/UserDelete/UserDeleteErrorBoundary.tsx (1)

42-46: Extract a named props type for the fallback component.

The inline { error: Error | null } shape makes this the only component in the file that skips the repo’s {ComponentName}Props convention. Pulling it into UserDeleteErrorFallbackProps keeps the new component aligned with the rest of journeys-admin.

As per coding guidelines, "**/*.{ts,tsx}: Define a type if possible" and "Props interfaces must follow naming convention {ComponentName}Props".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/journeys-admin/src/components/UserDelete/UserDeleteErrorBoundary.tsx`
around lines 42 - 46, Create a named props type for the fallback component by
extracting the inline `{ error: Error | null }` into a new type called
UserDeleteErrorFallbackProps and update the UserDeleteErrorFallback signature to
accept `props: UserDeleteErrorFallbackProps`; ensure the new type is exported or
defined adjacent to UserDeleteErrorFallback so the file follows the
{ComponentName}Props convention used across the repo and keeps the component
consistent with other types in journeys-admin.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/journeys-admin/src/components/UserDelete/UserDelete.tsx`:
- Around line 397-404: The ARIA attributes currently passed into the MUI
slotProps.input in the UserDelete component are not applied to the native
<input>; update the slotProps to use slotProps.htmlInput instead so aria-label
and aria-describedby reach the actual DOM node: locate the slotProps block in
the UserDelete component (where idType === UserDeleteIdType.email ? t('User
email to delete') : t('Database ID to delete') is used) and move the
'aria-label' and 'aria-describedby' properties under slotProps.htmlInput
(preserving the conditional value and key names), ensuring accessibility
attributes are applied to the underlying input element.

---

Nitpick comments:
In `@apps/journeys-admin/src/components/UserDelete/UserDeleteErrorBoundary.tsx`:
- Around line 42-46: Create a named props type for the fallback component by
extracting the inline `{ error: Error | null }` into a new type called
UserDeleteErrorFallbackProps and update the UserDeleteErrorFallback signature to
accept `props: UserDeleteErrorFallbackProps`; ensure the new type is exported or
defined adjacent to UserDeleteErrorFallback so the file follows the
{ComponentName}Props convention used across the repo and keeps the component
consistent with other types in journeys-admin.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: da15a207-e630-4c6d-9898-212bb5c38db7

📥 Commits

Reviewing files that changed from the base of the PR and between 3be2e2f and ea89d14.

📒 Files selected for processing (8)
  • apps/journeys-admin/pages/users/verify.tsx
  • apps/journeys-admin/src/components/UserDelete/UserDelete.spec.tsx
  • apps/journeys-admin/src/components/UserDelete/UserDelete.tsx
  • apps/journeys-admin/src/components/UserDelete/UserDeleteConfirmDialog.tsx
  • apps/journeys-admin/src/components/UserDelete/UserDeleteErrorBoundary.tsx
  • apps/journeys-admin/src/libs/apolloClient/apolloClient.test.ts
  • apps/journeys-admin/src/libs/apolloClient/apolloClient.ts
  • libs/locales/en/apps-journeys-admin.json
✅ Files skipped from review due to trivial changes (1)
  • libs/locales/en/apps-journeys-admin.json
🚧 Files skipped from review as they are similar to previous changes (4)
  • apps/journeys-admin/src/components/UserDelete/UserDelete.spec.tsx
  • apps/journeys-admin/src/libs/apolloClient/apolloClient.test.ts
  • apps/journeys-admin/src/components/UserDelete/UserDeleteConfirmDialog.tsx
  • apps/journeys-admin/src/libs/apolloClient/apolloClient.ts

Comment thread apps/journeys-admin/src/components/UserDelete/UserDelete.tsx
… type

- UserDelete.tsx: change slotProps.input → slotProps.htmlInput so that
  aria-label and aria-describedby reach the underlying <input> DOM node
  in MUI v7; slotProps.input targets the MUI wrapper component, not the
  native element, so screen readers were not receiving these attributes
  (CodeRabbit major accessibility finding)
- UserDeleteErrorBoundary.tsx: extract inline { error: Error | null }
  type into named UserDeleteErrorFallbackProps interface, consistent
  with the repo's {ComponentName}Props convention (CodeRabbit nitpick)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions github-actions Bot temporarily deployed to Preview - watch April 15, 2026 09:07 Inactive
@github-actions github-actions Bot temporarily deployed to Preview - journeys April 15, 2026 09:07 Inactive
@github-actions github-actions Bot temporarily deployed to Preview - videos-admin April 15, 2026 09:07 Inactive
@github-actions github-actions Bot temporarily deployed to Preview - journeys-admin April 15, 2026 09:07 Inactive
@github-actions github-actions Bot temporarily deployed to Preview - watch-modern April 15, 2026 09:07 Inactive
@github-actions github-actions Bot temporarily deployed to Preview - resources April 15, 2026 09:07 Inactive
@github-actions github-actions Bot temporarily deployed to Preview - player April 15, 2026 09:07 Inactive
slotProps.htmlInput applies aria-label directly to the DOM <input>,
which takes precedence over the associated <label> text for accessible
name computation. Tests that queried getByRole('textbox', { name: 'User
Email' }) now get no match because the accessible name is the aria-label
value 'User email to delete'. Update all three occurrences.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions github-actions Bot temporarily deployed to Preview - journeys April 15, 2026 09:17 Inactive
@github-actions github-actions Bot temporarily deployed to Preview - resources April 15, 2026 09:17 Inactive
@github-actions github-actions Bot temporarily deployed to Preview - videos-admin April 15, 2026 09:17 Inactive
@github-actions github-actions Bot temporarily deployed to Preview - journeys-admin April 15, 2026 09:17 Inactive
@github-actions github-actions Bot temporarily deployed to Preview - watch April 15, 2026 09:17 Inactive
@github-actions github-actions Bot temporarily deployed to Preview - player April 15, 2026 09:17 Inactive
@github-actions github-actions Bot temporarily deployed to Preview - watch-modern April 15, 2026 09:17 Inactive
@csiyang csiyang enabled auto-merge April 15, 2026 23:13
@csiyang csiyang added this pull request to the merge queue Apr 15, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Apr 15, 2026
@csiyang csiyang added this pull request to the merge queue Apr 15, 2026
Merged via the queue into main with commit 944e3a4 Apr 15, 2026
33 of 34 checks passed
@csiyang csiyang deleted the siyangcao/nes-1455-deleteuser-frontend branch April 15, 2026 23:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants