[CSM Portal] fix page clipping, dark-mode comment readability, and severity defaulting to S3 - #1422
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
🚧 Files skipped from review as they are similar to previous changes (4)
📝 WalkthroughWalkthroughThe PR adds explicit unset severity handling across case APIs and UI components, replaces the application shell layout, and changes inline background sanitization to use relative luminance with expanded color parsing. ChangesUnset severity handling
Application shell layout
Light-background sanitization
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Backend
participant useGetCsmCaseDetail
participant severityFromBe
participant SeverityChip
Backend->>useGetCsmCaseDetail: case severity value
useGetCsmCaseDetail->>severityFromBe: map backend severity
severityFromBe-->>useGetCsmCaseDetail: SeverityOrUnset
useGetCsmCaseDetail->>SeverityChip: render severity
SeverityChip-->>SeverityChip: display severity or "Unset"
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: 2
🤖 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-dashboard/types/abtDashboard.ts`:
- Around line 19-25: Update the documentation for SeverityOrUnset in
apps/csm-portal/webapp/src/features/csm-dashboard/types/abtDashboard.ts:19-25
and CsmCaseRow.severity in
apps/csm-portal/webapp/src/features/csm-cases/types/csmCases.ts:60-64 to state
that "unset" also represents unrecognized backend severity values, in addition
to empty or missing values. No code behavior changes are needed.
In `@apps/csm-portal/webapp/src/utils/sanitizeHtml.ts`:
- Around line 118-122: Replace the hard-coded
LIGHT_BACKGROUND_LUMINANCE_THRESHOLD value with a threshold derived from the
dark-mode text color and the required 4.5:1 contrast ratio, using the existing
luminance/contrast utilities or conventions in sanitizeHtml.ts. Update the
sanitization logic so background-color: `#808080` is removed, and add a focused
test covering that behavior.
🪄 Autofix
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 Plus
Run ID: 6ae816bf-efa5-4573-8d44-afc2535d8e47
📒 Files selected for processing (21)
apps/csm-portal/webapp/src/api/backend/mappers.test.tsapps/csm-portal/webapp/src/api/backend/mappers.tsapps/csm-portal/webapp/src/components/SeverityChip.test.tsxapps/csm-portal/webapp/src/components/SeverityChip.tsxapps/csm-portal/webapp/src/features/csm-cases/api/useGetCsmCaseDetail.tsapps/csm-portal/webapp/src/features/csm-cases/api/useQuickCaseSearch.tsapps/csm-portal/webapp/src/features/csm-cases/api/useSearchChildCases.tsapps/csm-portal/webapp/src/features/csm-cases/components/CallRequestsWidget.tsxapps/csm-portal/webapp/src/features/csm-cases/components/CaseActionBar.tsxapps/csm-portal/webapp/src/features/csm-cases/components/ChangeSeverityDialog.tsxapps/csm-portal/webapp/src/features/csm-cases/components/CreateCallRequestDialog.tsxapps/csm-portal/webapp/src/features/csm-cases/pages/CsmCaseDetailPage.tsxapps/csm-portal/webapp/src/features/csm-cases/types/csmCases.tsapps/csm-portal/webapp/src/features/csm-cases/utils/caseSearchPayload.tsapps/csm-portal/webapp/src/features/csm-dashboard/api/useGetMyAssignedOpenCases.tsapps/csm-portal/webapp/src/features/csm-dashboard/types/abtDashboard.tsapps/csm-portal/webapp/src/features/csm-timecards/components/LogTimeCardDialog.tsxapps/csm-portal/webapp/src/layouts/AppLayout.tsxapps/csm-portal/webapp/src/layouts/AppShellLayout.tsxapps/csm-portal/webapp/src/utils/sanitizeHtml.test.tsapps/csm-portal/webapp/src/utils/sanitizeHtml.ts
Case-detail (and other) pages silently clipped content on the right edge below roughly 1780px window width: oxygen-ui's AppShell never sets minWidth: 0 on its <main> flex item, so it locks to its content's intrinsic width instead of shrinking, and the surrounding row's overflow:hidden then clips the excess instead of scrolling. Replace the oxygen-ui AppShell wiring in AppLayout with a hand-built AppShellLayout that cascades minWidth: 0 through every flex ancestor, mirroring the fix already shipped in the customer portal. Separately, dark-mode comment rendering only stripped near-white inline backgrounds from ServiceNow-authored HTML, so a light/pastel background (e.g. a call-note callout box) survived into dark mode with the app's light default text on top, reading as low-contrast. Switch the check to a WCAG relative-luminance threshold so any sufficiently light background gets neutralized, not just near-white ones.
…ontrast The fixed 0.55 luminance cutoff still preserved backgrounds like #808080 (luminance ~0.22, ~3.95:1 contrast against white text) that fall below the 4.5:1 WCAG AA minimum for normal text. Derive the threshold from the actual contrast formula instead of an eyeballed constant.
03f71f7 to
e2a6f1a
Compare
A case with no severity value (empty/missing from the source) was rendered and filtered as if it were S3 (Medium) -- a false signal, since "we don't know the severity" and "the severity really is Medium" are different facts. severityFromBe (renamed from severityFromPriority, which no longer matched what it consumes) now maps falsy/unrecognized input to a new "unset" state instead of collapsing it into S3. SeverityChip renders "unset" as a distinct outlined "Unset" badge, visually unlike any real S0-S4 chip. Filtering by a specific severity is unaffected since the filter dropdown never offers "unset" as an option and the backend query already excludes non-matching cases, so unset-severity cases only ever show up in the unfiltered list. Also fixes a related discrepancy in CreateCallRequestDialog's lead-time table, which previously enforced 90 min (S3's lead time) for a null-severity case instead of the backend's own 300 min fallback for null/unknown.
…real contract Both doc comments described "unset" as only empty/missing severity, but severityFromBe also falls back to "unset" for any unrecognized value.
|
@coderabbitai resume |
✅ Action performedReviews resumed. |
Purpose
Three UX/correctness issues reported on the CSM portal's case-detail page and case views:
@wso2/oxygen-ui'sAppShellcomponent never setsminWidth: 0on the<main>flex item it renders, so<main>locks to its content's intrinsic width instead of shrinking to the viewport, and the surrounding flex row'soverflow: hiddenthen clips the excess instead of scrolling or wrapping. This affects the whole page, not just comments.Goals
AppShellfor the page shell; use a hand-builtAppShellLayoutthat explicitly cascadesminWidth: 0through every flex ancestor down to<main>, so content sizes to the actual viewport instead of clipping."S3". Represent "unset" as its own distinct value, rendered as a visually distinct "Unset" badge, and keep it excluded from all S1-S4 severity filters so it can never be mistaken for a real severity again.Approach
apps/csm-portal/webapp/src/layouts/AppShellLayout.tsx(new) ports the same pattern the customer portal already ships in production for the identical bug (apps/customer-portal/webapp/src/layouts/AppShellLayout.tsx), trimmed to what CSM'sAppLayoutactually needs (no footer slot, no overlay/mobile-drawer sidebar — CSM's sidebar only ever renders inline).AppLayout.tsxswaps its<AppShell>/<AppShell.Navbar>/<AppShell.Sidebar>/<AppShell.Main>usage for the new component; all surrounding behavior (banners, loading state, scroll-reset-on-route-change,useAppShell()state) is unchanged.utils/sanitizeHtml.ts'sstripLightModeInlineStyles(dark-mode only, called fromCsmCaseCommentBubble.tsx) replaces its near-white-only RGB threshold with a WCAG relative-luminance calculation, catching light/pastel backgrounds generally while leaving dark/saturated backgrounds (code blocks, etc.) untouched.For the severity issue:
src/api/backend/mappers.ts's severity mapper (renamedseverityFromPriority→severityFromBe, since it consumes the backend'sseverityfield, not a "priority" field) now returns a new"unset"value instead of"S3"for falsy/unrecognized input. A newSeverityOrUnset = Severity | "unset"type is applied only to display-facing fields (case-list rows, case detail, quick-search hits, child-case rows); severity filter option arrays and the severity-change dialog's radio options staySeverity-only, which keeps "unset" out of the filter UI by construction rather than needing separate exclusion logic.SeverityChiprenders"unset"as an outlined, non-bold "Unset" badge, visually distinct from every real severity's filled/bold chip. Investigation confirmed the backend (Go entity-service) already returns an empty value for unmapped severity and never defaults it to Medium — the defaulting was purely a frontend display bug.User stories
As a CS engineer, I can see the full case-detail page (Overview fields, comment content) without content being cut off on my laptop screen, I can read ServiceNow-authored comments with light-colored callout boxes in dark mode, and I can tell at a glance whether a case genuinely has no severity set versus being a real S3 case.
Release note
Fixed CSM portal page content being clipped on narrower browser windows, fixed low-contrast comment backgrounds in dark mode, and fixed cases with no severity set incorrectly displaying as S3.
Documentation
N/A — internal layout/rendering/display fix, no user-facing documentation to update.
Training
N/A — not training content.
Certification
N/A — no certification exam impact.
Marketing
N/A — internal bug fix, not a marketed feature.
Automation tests
Added/updated
sanitizeHtml.test.ts(16 tests passing, including 3 new cases: pastel background stripped, near-white regression check, dark background left untouched). Added/updatedmappers.test.tsand newSeverityChip.test.tsxfor the severity fix (61/61 passing across the 7 directly-affected test files: mapper, chip, severity-change dialog, log-time-card dialog, case-detail page, case search payload, filters URL).None added; layout and severity changes verified via typecheck + full existing suite (
tsc -b --forceexit 0,eslint .unchanged from baseline,vitest run133/141 with the same 8 pre-existing unrelated failures confirmed present onmain).Security checks
eslint, clean on touched filesSamples
N/A
Related PRs
A companion fix for the same dark-mode background-contrast issue in the customer portal is being opened separately (different app, kept as its own PR).
Migrations (if applicable)
N/A
Test environment
Verified with
pnpm run buildandpnpm run test(Vitest) locally against Node/pnpm versions pinned in this repo. Full local-stack browser verification (real viewport resize + dark-mode screenshot, and a live unset-severity case vs. a real S3 case) is recommended as a follow-up before merge.Learning
Root-caused the clipping bug by reading
@wso2/oxygen-ui's compiled source directly (a shallow-merge bug in itsLayout.Content'ssxprop handling dropsminWidth/overflowdefaults) and comparing against the customer portal's existing fix for the same issue. For the severity bug, confirmed the defaulting lived entirely in the frontend mapper by reading the Go entity-service's case-severity path first — it already exposesseverity(notpriority) and never defaults unmapped input to Medium.Summary by CodeRabbit
New Features
Bug Fixes