[CSM Portal Microapp] Build out the Case detail page - #1149
Conversation
…ns, comments, attachments, SLAs, call requests Adds the full webapp-parity Case detail experience: nextStates-driven state transitions with the resolution dialog for close/propose-solution, severity change, work-state (ongoing/paused) toggle with the single-active-case pause-conflict dialog, gated comment composer (public vs work-note rules) with inline attachments, and new SLAs / Attachments / Call requests / Time tracking tabs backed by new services (slas, callRequests, extended attachments/cases).
…for real The ongoing-conflict check and confirm dialog from the previous commit had three real bugs, found by reading the Go backend directly and tracing live 409s instead of guessing: - The single-ongoing-case rule is enforced entirely by the upstream ServiceNow instance (confirmed: that error text appears nowhere in the portal's own backend), so the proactive search was only ever a prediction — it needed a reactive fallback using the case number ServiceNow's own 409 already names, not just a proactive check. - The reactive fallback's case-number search always returned zero results because it omitted an explicit `types` filter — the only other place in this app that searches cases by text (SupportPage/toCaseSearchFilters) always sends one; omitting it scopes the search to nothing rather than "all types". - "Assign to me"/"Start progress" ran the assignee change and state transition *before* checking for a conflict, so declining the pause dialog left the case reassigned and moved anyway. The whole sequence is now gated behind the conflict check so nothing is applied — not even the assignee change — until the check clears or the user explicitly confirms pausing the other case. Also unwraps double-JSON-wrapped backend error messages (ApiError.ts) so the real ServiceNow message surfaces cleanly instead of raw JSON.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (3)
📝 WalkthroughWalkthroughAdds a tabbed CSM case-detail experience with case transitions, dialogs, comment composition, activity timelines, attachment uploads, SLA and call-request views, time-card navigation, conflict handling, and supporting query services and domain types. ChangesCase detail functionality
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant CaseDetailPage
participant CommentComposer
participant cases
participant attachments
CaseDetailPage->>CommentComposer: render gated composer
CommentComposer-->>CaseDetailPage: submit comment and attachments
CaseDetailPage->>cases: post comment
CaseDetailPage->>attachments: create attachments
CaseDetailPage-->>CaseDetailPage: invalidate comments query
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ 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: 10
🤖 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/microapp/src/components/case-detail/AttachmentsTab.tsx`:
- Around line 67-78: Update the upload completion logic in AttachmentsTab to
retain only rejected attachment entries from the Promise.allSettled results,
rather than clearing all pending files. Preserve successful uploads as removed,
keep failed files selected for retry, and ensure the existing error messaging
and upload-state cleanup remain unchanged.
In `@apps/csm-portal/microapp/src/components/case-detail/CaseActionBar.tsx`:
- Around line 126-127: Replace the inline paper component in the CaseActionBar
dialog’s slots configuration with the shared DialogPaper component. Import
DialogPaper from its existing shared module and preserve the current paper
styling through slotProps.
In `@apps/csm-portal/microapp/src/components/case-detail/CommentBody.tsx`:
- Around line 42-55: Update CommentBody’s rendering decision to test
HTML_FORMAT_RE against the full content rather than the truncated shown value,
preserving the same rendering mode when expanded. For truncated HTML, sanitize
the sliced content first and append the ellipsis outside the sanitized HTML so
it remains visible even when truncation cuts through a tag; keep plain-text
truncation behavior unchanged.
In `@apps/csm-portal/microapp/src/components/case-detail/CommentComposer.tsx`:
- Around line 65-67: Update the canSubmit calculation in CommentComposer to
check whether the currently selected type is blocked, rather than relying only
on allBlocked. Preserve attachment-only submission and existing content and
isSubmitting requirements, while preventing posts when the selected comment type
becomes blocked after a caseState refresh.
In `@apps/csm-portal/microapp/src/components/case-detail/PauseConflictDialog.tsx`:
- Around line 42-46: Update the Dialog’s onClose handler in PauseConflictDialog
to ignore dismissal attempts while isSubmitting is true, while preserving the
existing onDecline behavior when submission is not in progress.
In `@apps/csm-portal/microapp/src/components/support/AttachmentsField.tsx`:
- Around line 57-61: Update the oversized-file validation branch in the
AttachmentsField change handler to reset the file input via
inputRef.current.value before returning. Preserve the existing error message and
early-return behavior so the same file can be selected again after correction.
In `@apps/csm-portal/microapp/src/pages/CaseDetailPage.tsx`:
- Around line 145-154: Update runOngoingAction and the assign/start/ongoing flow
to make the transition atomic: use a backend operation that applies assignment,
work-in-progress, and ongoing state together, or restore the original assignee
and state before setting pendingOngoingAction and showing the conflict dialog.
Ensure declining the dialog leaves the case unchanged as promised by the
cancellation path around the conflict handling.
- Around line 323-334: Update the submission promise handler around the results
processing so it returns failure when the submission contains only attachments
and every upload is rejected, preventing the composer from clearing files after
displaying the retry error. Preserve the existing success return for partial
failures or submissions with text, and use the existing fields.attachments and
text/content state symbols to distinguish the all-failed attachment-only case.
In `@apps/csm-portal/microapp/src/services/cases.ts`:
- Around line 129-133: Normalize both email values before the comparison in the
loop filtering within the cases-matching function: lowercase myEmail as well as
c.assignedEngineer.email, while preserving the existing fallback behavior and
other filters.
In `@apps/csm-portal/microapp/src/utils/ApiError.ts`:
- Around line 42-52: Update unwrapMessage to preserve the supplied fallback when
trimming or recursively unwrapping produces an empty message. Ensure the same
non-empty check is applied to the related fallback handling around the second
referenced section, while retaining existing JSON unwrapping and prefix removal
behavior for valid messages.
🪄 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: ab06391d-271d-4ef0-81fd-81d664ecb90c
📒 Files selected for processing (31)
apps/csm-portal/microapp/src/components/case-detail/AttachmentsTab.tsxapps/csm-portal/microapp/src/components/case-detail/CallRequestsTab.tsxapps/csm-portal/microapp/src/components/case-detail/CaseActionBar.tsxapps/csm-portal/microapp/src/components/case-detail/ChangeSeverityDialog.tsxapps/csm-portal/microapp/src/components/case-detail/CommentBody.tsxapps/csm-portal/microapp/src/components/case-detail/CommentComposer.tsxapps/csm-portal/microapp/src/components/case-detail/PauseConflictDialog.tsxapps/csm-portal/microapp/src/components/case-detail/ResolutionDialog.tsxapps/csm-portal/microapp/src/components/case-detail/SlaTab.tsxapps/csm-portal/microapp/src/components/case-detail/TimeTrackingTab.tsxapps/csm-portal/microapp/src/components/case-detail/caseResolution.tsapps/csm-portal/microapp/src/components/common/DialogPaper.tsxapps/csm-portal/microapp/src/components/support/AttachmentsField.tsxapps/csm-portal/microapp/src/config/endpoints.tsapps/csm-portal/microapp/src/pages/CaseDetailPage.tsxapps/csm-portal/microapp/src/services/attachments.tsapps/csm-portal/microapp/src/services/callRequests.tsapps/csm-portal/microapp/src/services/cases.tsapps/csm-portal/microapp/src/services/slas.tsapps/csm-portal/microapp/src/types/attachment.dto.tsapps/csm-portal/microapp/src/types/attachment.model.tsapps/csm-portal/microapp/src/types/callRequest.dto.tsapps/csm-portal/microapp/src/types/callRequest.model.tsapps/csm-portal/microapp/src/types/case.dto.tsapps/csm-portal/microapp/src/types/case.model.tsapps/csm-portal/microapp/src/types/index.tsapps/csm-portal/microapp/src/types/sla.dto.tsapps/csm-portal/microapp/src/types/sla.model.tsapps/csm-portal/microapp/src/utils/ApiError.tsapps/csm-portal/microapp/src/utils/attachments.tsapps/csm-portal/microapp/src/utils/caseWorkState.ts
…ards, and HTML-safe description
…ist for compact layouts
…l; drop the Description card
…g produces an empty string
…don't clear a fully-failed attachment-only post
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
apps/csm-portal/microapp/src/components/case-detail/CaseActionBar.tsx (1)
78-95: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueRemove unnecessary React fragments.
The
<Fragment>and<>wrappers around the singleButtonandFormControlroot elements are redundant and can be safely removed, which will also allow you to drop theFragmentimport.♻️ Proposed refactor
For the single target button:
- return ( - <Fragment> - <Button - variant="contained" - size="small" - disabled={isPending} - onClick={() => runTarget(targets[0])} - sx={{ borderRadius: 999 }} - > - {labelFor(targets[0])} - </Button> - </Fragment> - ); + return ( + <Button + variant="contained" + size="small" + disabled={isPending} + onClick={() => runTarget(targets[0])} + sx={{ borderRadius: 999 }} + > + {labelFor(targets[0])} + </Button> + );For the multiple target select (and remove
</>at the end of the return statement):- return ( - <> - <FormControl size="small" sx={{ minWidth: 150, flexShrink: 0 }}> + return ( + <FormControl size="small" sx={{ minWidth: 150, flexShrink: 0 }}>🤖 Prompt for 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. In `@apps/csm-portal/microapp/src/components/case-detail/CaseActionBar.tsx` around lines 78 - 95, In CaseActionBar, remove the redundant Fragment wrappers around the single Button and FormControl return roots, including the matching closing fragment tag for the multi-target path, and remove the now-unused Fragment import.
🤖 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/microapp/src/components/case-detail/CaseActivityFeed.tsx`:
- Around line 167-183: The “Download” IconButton in the attachment actions
currently invokes the same full-screen openUrl behavior as “Open.” Update its
onClick handler to use the bridge’s download mechanism with the attachment
downloadUrl, or remove the download control if no download API is available;
leave the “Open” button unchanged.
In `@apps/csm-portal/microapp/src/services/activities.ts`:
- Around line 31-40: Update searchCaseActivities to handle paginated responses
when hasMore is true, fetching subsequent pages with the appropriate offset
until all activity records are collected before filtering and mapping
field_change entries. Preserve the existing page limit and return the complete
CaseAuditEntry history.
---
Nitpick comments:
In `@apps/csm-portal/microapp/src/components/case-detail/CaseActionBar.tsx`:
- Around line 78-95: In CaseActionBar, remove the redundant Fragment wrappers
around the single Button and FormControl return roots, including the matching
closing fragment tag for the multi-target path, and remove the now-unused
Fragment import.
🪄 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: 91c1ec17-81ab-4df8-94fd-67c39292571a
📒 Files selected for processing (15)
apps/csm-portal/microapp/src/components/case-detail/AttachmentsTab.tsxapps/csm-portal/microapp/src/components/case-detail/CaseActionBar.tsxapps/csm-portal/microapp/src/components/case-detail/CaseActivityFeed.tsxapps/csm-portal/microapp/src/components/case-detail/CommentBody.tsxapps/csm-portal/microapp/src/components/case-detail/CommentComposer.tsxapps/csm-portal/microapp/src/components/case-detail/PauseConflictDialog.tsxapps/csm-portal/microapp/src/components/support/AttachmentsField.tsxapps/csm-portal/microapp/src/config/endpoints.tsapps/csm-portal/microapp/src/pages/CaseDetailPage.tsxapps/csm-portal/microapp/src/services/activities.tsapps/csm-portal/microapp/src/services/cases.tsapps/csm-portal/microapp/src/types/activity.dto.tsapps/csm-portal/microapp/src/types/activity.model.tsapps/csm-portal/microapp/src/types/index.tsapps/csm-portal/microapp/src/utils/ApiError.ts
🚧 Files skipped from review as they are similar to previous changes (7)
- apps/csm-portal/microapp/src/utils/ApiError.ts
- apps/csm-portal/microapp/src/config/endpoints.ts
- apps/csm-portal/microapp/src/components/case-detail/PauseConflictDialog.tsx
- apps/csm-portal/microapp/src/components/case-detail/AttachmentsTab.tsx
- apps/csm-portal/microapp/src/components/case-detail/CommentComposer.tsx
- apps/csm-portal/microapp/src/pages/CaseDetailPage.tsx
- apps/csm-portal/microapp/src/services/cases.ts
|
@coderabbitai review |
✅ Action performedReview finished.
|
646f934
into
wso2-open-operations:dev-app-csm-portal
Purpose
Build out the CSM Portal microapp case detail experience so engineers can view and act on case information without falling back to the web app. This change also addresses interaction gaps around pause conflicts and dialog/input behavior inside the case detail flow.
Goals
Approach
User stories
Release note
Expanded the CSM Portal microapp case detail page with lifecycle actions, comments, attachments, SLAs, call requests, and supporting interaction fixes.
Documentation
N/A - This is a microapp UI and client-side integration enhancement; no external product documentation update is required.
Training
N/A - No training-material change is required for this microapp case detail enhancement.
Certification
N/A - No certification exam impact for this change.
Marketing
N/A - No marketing content is needed for this internal product enhancement.
Automation tests
Not run locally for this PR.
Not run locally for this PR.
Security checks
Samples
N/A - No sample assets or sample applications were added.
Related PRs
N/A
Migrations (if applicable)
N/A - No migration steps are required.
Test environment
Not run locally for this PR.
Learning
Reused existing microapp service and case UI patterns, then extended them to cover case-detail-specific state handling, backend-aligned comment gating, and more stable dialog composition.
Summary by CodeRabbit