[CSM Portal] Drive case action bar from backend nextStates; unify reopened spelling - #848
Conversation
…pened spelling The case state machine was duplicated client-side and the FE used a different spelling for one state than the backend/entity service. - CaseActionBar now renders lifecycle buttons solely from the case's backend-supplied nextStates. Removed FALLBACK_TARGETS (the duplicated client-side transition graph): an absent or empty nextStates yields no lifecycle buttons rather than guessing from a second copy of the graph. - Mock case-detail fixtures now carry nextStates (computed from a mock that stands in for the backend) so mock mode keeps showing the right buttons. - Aligned the CaseState vocabulary to the backend spelling 'reopened' (was 'reopen') across types, labels, colours, filters and mocks. uiStateFromBe / beStateFromUi are now identity at the type level; uiStateFromBe keeps a runtime guard defaulting unknown/undefined to 'open'. Build, lint and the webapp test suite (47 tests) pass.
|
Warning Review limit reached
More reviews will be available in 41 minutes and 51 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more credits in the billing tab to continue. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (10)
📝 WalkthroughWalkthroughThis PR unifies the case state vocabulary by replacing ChangesCase State Unification and NextStates Integration
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/csm-portal/webapp/src/features/csm-cases/components/CaseActionBar.tsx`:
- Around line 257-264: The code currently trusts caseDetail.nextStates and maps
it through orderRank and buttonFor, which can create invalid buttons; update
CaseActionBar to first validate/filter caseDetail.nextStates against the
canonical set (e.g., TARGET_CONFIG or the states returned by uiStateFromBe/state
enum) before sorting/mapping so only known states are used. Specifically,
replace direct use of targets = caseDetail.nextStates ?? [] with a filtered list
(filter unknown/typo values by membership in TARGET_CONFIG or
uiStateFromBe(state) keys), then perform the dedupe/sort/map steps; ensure
runPrimary and buttonFor will never receive undefined/badState by only
generating actions for validated states.
🪄 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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: edaada25-4709-4bda-bfbd-15fa537f9835
📒 Files selected for processing (12)
apps/csm-portal/webapp/src/api/backend/mappers.test.tsapps/csm-portal/webapp/src/api/backend/mappers.tsapps/csm-portal/webapp/src/features/csm-cases/api/mocks/casesMocks.tsapps/csm-portal/webapp/src/features/csm-cases/components/CaseActionBar.test.tsxapps/csm-portal/webapp/src/features/csm-cases/components/CaseActionBar.tsxapps/csm-portal/webapp/src/features/csm-cases/components/CasesFilterBar.tsxapps/csm-portal/webapp/src/features/csm-cases/utils/casesFiltersUrl.tsapps/csm-portal/webapp/src/features/csm-dashboard/api/mocks/dashboardMocks.tsapps/csm-portal/webapp/src/features/csm-dashboard/api/useCaseCountsMatrix.tsapps/csm-portal/webapp/src/features/csm-dashboard/components/MyQueueSection.tsxapps/csm-portal/webapp/src/features/csm-dashboard/types/abtDashboard.tsapps/csm-portal/webapp/src/features/csm-dashboard/utils/abtDashboard.ts
A new case state or transition introduced on the backend should not require a frontend change to appear and work. Previously an unrecognized state would build a broken action-bar button (undefined label, dispatching an undefined action) and render an empty status chip. - uiStateFromBe now passes an unknown backend state through unchanged instead of collapsing it to 'open' (only a genuinely absent value defaults to 'open'), so the value reaches the UI. - Added stateLabel()/stateColor()/humanizeState() helpers that fall back to a title-cased key and neutral colour for any state without a curated entry. Status chips (cases list, dashboard queue/SLA sections, related cases) use them. - CaseActionBar renders a usable button for an unknown state via a neutral DEFAULT_TARGET_CONFIG and a generic 'transition' lifecycle action. The PATCH target still comes from the backend nextStates value, so the transition works; the action only drives the post-transition toast. This keeps the action bar driven solely by backend nextStates while making the no-FE-change-for-new-states property hold instead of silently filtering unknown states out (which would have required an FE update for every new state). Build, lint and the webapp test suite (49 tests) pass.
What
The case state machine was duplicated in the webapp and the FE used a different spelling for one state than the backend/entity service. This aligns the FE to the backend as the single source of truth.
nextStates. RemovedFALLBACK_TARGETS(the duplicated client-side transition graph): an absent or emptynextStatesnow yields no lifecycle buttons rather than guessing from a second copy of the graph.EDGE_OVERRIDES-style presentational labels remain driven by the target state's name.nextStates(computed from a small graph that stands in for the backend, mirroringbackend/internal/handler/state.go) so mock mode keeps showing the correct buttons.CaseStatevocabulary now uses the backend spellingreopened(wasreopen) across types, labels, colours, filters and mocks.uiStateFromBe/beStateFromUiare now identity at the type level;uiStateFromBekeeps a runtime guard that defaults unknown/undefined toopen.Why
The transition graph should live in exactly one place per tier. Previously the FE kept its own copy and could drift from the backend (and did, on the
reopen/reopenedspelling). Buttons are now whatever the backend permits, nothing more.Note
The case-filter URL token for that state changes
reopen→reopened; any pre-existing bookmarked filter URL using the old token will drop that one state silently. Acceptable pre-launch.Testing
pnpm build(tsc + vite) — passespnpm lint— cleanpnpm test— 47 tests pass (incl. CaseActionBar and mapper suites; the obsolete fallback test was rewritten to assert no buttons whennextStatesis absent)Summary by CodeRabbit
Bug Fixes
Refactor