Skip to content

[CSM Portal] Cases list & dashboard: human IDs, pagination, BE-aligned columns/fields - #867

Merged
cloby99 merged 4 commits into
wso2-open-operations:v2from
rksk:csm/human-case-ids-dashboard-counts
Jun 15, 2026
Merged

[CSM Portal] Cases list & dashboard: human IDs, pagination, BE-aligned columns/fields#867
cloby99 merged 4 commits into
wso2-open-operations:v2from
rksk:csm/human-case-ids-dashboard-counts

Conversation

@rksk

@rksk rksk commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

What

A cases-list + dashboard overhaul, plus a backend field-name correction.

Backend field alignment (bug fix)

The FE types used wso2Id / createdAt / updatedAt, but the actual /cases/search and case-view payloads use internalId / createdOn / updatedOn (and createdBy is an object). The old names silently resolved to undefined, so the WSO2 case id and timestamps were blank. Corrected the types and mappers. FE-only change — no backend touched.

Case identifiers shown to humans

  • A case has a UUID id (API/links only), a CS-prefixed number, and the project-scoped internalId. The mappers no longer fall back to the UUID, so it's never shown to humans.
  • The case list shows both human ids; case search matches them; detail header/details tab guard missing ids.

Server-side pagination + page size

  • The list previously fetched only the first 50 rows and never surfaced the rest. It now pages via the backend's total / limit / offset / hasMore, with a TablePagination footer (10 / 20 / 50 per page; 50 is the backend max) — consistent with the projects/accounts pages.

Filters pushed server-side where supported

  • searchsearchQuery (debounced), alongside severity / state / project; results sorted by updated_at desc.
  • Assignee / SLA / product have no clean backend support and are disabled in live (product would need the backend to map product name → deployed-product instance id). Mock mode still filters/sorts/slices the seeded data client-side.

Column layout tuned for long subjects

  • Case ids move to their own narrow column (WSO2 internal id over CS number); Subject gets its own wide column with the project as context beneath; Customer column dropped to free the space. Assignee and SLA were already dropped (no backend data) and Product added.
  • Columns: Case ID · Subject · Product · Severity · State · Updated.

Dashboard "Cases by severity and state"

  • Exact counts via count-only searches (limit: 1, read total) instead of a 500-row client-side sample; dropped the Closed column.

Verification

  • pnpm lint, pnpm build (typecheck), pnpm test (84 tests) all pass.

…otals

Case identifiers
- Stop substituting the UUID primary key for a missing human id. The case
  mappers fell back to `id` when `number`/`wso2Id` were absent, leaking the
  raw UUID into the detail headline and the "WSO2 case ID" field.
- Make caseNumber and wso2CaseId optional on the case row type; render the
  UUID nowhere. Add caseIdLabel() ("WSO2 id / CS number", dropping whichever
  is absent) and use it for the recent-views label.
- Case list now shows BOTH ids as the row headline, and case search matches
  the WSO2 id too. Detail header/details-tab guard missing ids (show "—").

Dashboard "Cases by severity and state"
- Replace the up-to-500-case client-side sample with exact counts: one
  count-only search per cell (limit 1, read the `total` attribute). Removes
  the truncation warning.
- Drop the Closed column; the matrix tracks active work only.
@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@rksk, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 45 minutes and 57 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 5c786241-bb77-4f77-858a-90a866eb5936

📥 Commits

Reviewing files that changed from the base of the PR and between 6d9c9d3 and 88567a9.

📒 Files selected for processing (13)
  • apps/csm-portal/webapp/src/api/backend/types.ts
  • apps/csm-portal/webapp/src/features/csm-cases/api/mocks/casesMocks.ts
  • apps/csm-portal/webapp/src/features/csm-cases/api/useGetCsmCaseDetail.ts
  • apps/csm-portal/webapp/src/features/csm-cases/api/useGetCsmCases.ts
  • apps/csm-portal/webapp/src/features/csm-cases/components/CasesFilterBar.tsx
  • apps/csm-portal/webapp/src/features/csm-cases/components/CasesList.tsx
  • apps/csm-portal/webapp/src/features/csm-cases/pages/CsmCaseDetailPage.tsx
  • apps/csm-portal/webapp/src/features/csm-cases/pages/CsmCasesPage.tsx
  • apps/csm-portal/webapp/src/features/csm-cases/types/csmCases.ts
  • apps/csm-portal/webapp/src/features/csm-cases/utils/caseIdentity.ts
  • apps/csm-portal/webapp/src/features/csm-cases/utils/casesClientFilter.ts
  • apps/csm-portal/webapp/src/features/csm-dashboard/api/useCaseCountsMatrix.ts
  • apps/csm-portal/webapp/src/features/csm-dashboard/components/CaseCountsMatrix.tsx
📝 Walkthrough

Walkthrough

The PR realigns CSM portal backend type field names (wso2IdinternalId, createdAt/updatedAtcreatedOn/updatedOn), makes caseNumber and wso2CaseId optional, adds server-driven pagination to the cases list hook and page, introduces client-side filter/sort utilities for MOCK mode, switches the dashboard matrix from sampled to exact per-cell counting, and updates all UI components accordingly.

Changes

CSM Portal — Server-side pagination, exact matrix counts, and backend type realignment

Layer / File(s) Summary
Backend types, domain types, and new utilities
src/api/backend/types.ts, src/features/csm-cases/types/csmCases.ts, src/features/csm-cases/utils/caseIdentity.ts, src/features/csm-cases/utils/casesClientFilter.ts
BeCaseView/BeCaseSearchView field renames (internalId, createdOn/updatedOn, nullable closedAt). CsmCaseRow fields made optional; CsmCasesListResponse extended with total/limit/offset/hasMore. New caseIdLabel display helper and applyCasesFilters/sortBySlaUrgency MOCK-mode utilities added.
Mock data adapter updates
src/features/csm-cases/api/mocks/casesMocks.ts
getMockCsmCases returns CsmCaseRow[] instead of CsmCasesListResponse; ALL_CASES_BY_NUMBER skips entries without caseNumber; linked case references fall back through caseNumber→wso2CaseId→id.
useGetCsmCases pagination and useGetCsmCaseDetail mapping
src/features/csm-cases/api/useGetCsmCases.ts, src/features/csm-cases/api/useGetCsmCaseDetail.ts
useGetCsmCases takes page/pageSize, applies MOCK filtering/sorting/slicing, sends offset/pageSize+sortBy to LIVE backend, and returns full pagination metadata. useGetCsmCaseDetail maps from c.number/c.internalId and c.createdOn/c.updatedOn.
CsmCasesPage server-driven pagination UI
src/features/csm-cases/pages/CsmCasesPage.tsx
Adds page/rowsPerPage state, debounced search, pagination reset on filter change, derives cases from hook response, computes display range from backend total, renders TablePagination wired to server paging.
CasesList and CasesFilterBar UI updates
src/features/csm-cases/components/CasesList.tsx, src/features/csm-cases/components/CasesFilterBar.tsx
CasesList removes assignee/SLA columns, adds Product column, renders case identity via caseIdLabel. CasesFilterBar wraps Product filter in live-backend-unsupported tooltip, matching SLA/Assignee pattern.
CsmCaseDetailPage identity display
src/features/csm-cases/pages/CsmCaseDetailPage.tsx
Uses caseIdLabel for recordView title, conditionally renders wso2CaseId/caseNumber header with fallback, renames "Case ID" to "Case number" with placeholders.
Dashboard matrix exact per-cell counting
src/features/csm-dashboard/api/useCaseCountsMatrix.ts, src/features/csm-dashboard/components/CaseCountsMatrix.tsx
Replaces sampled pagination with parallel POST /cases/search {limit:1} per (severity, state) cell; MATRIX_STATES excludes "closed"; CaseCountsMatrix drops truncated field; truncation caption removed from component.

Sequence Diagram(s)

sequenceDiagram
  actor User
  participant CsmCasesPage
  participant useGetCsmCases
  participant BackendAPI

  User->>CsmCasesPage: change filter / search / page
  CsmCasesPage->>CsmCasesPage: debounce search, reset page to 0
  CsmCasesPage->>useGetCsmCases: filters, page, rowsPerPage
  useGetCsmCases->>BackendAPI: POST /cases/search {pagination:{offset, limit}, sortBy:updated_at desc, searchQuery?}
  BackendAPI-->>useGetCsmCases: {cases[], total, limit, offset, hasMore}
  useGetCsmCases-->>CsmCasesPage: CsmCasesListResponse
  CsmCasesPage->>CsmCasesPage: compute rangeStart/rangeEnd from total + page
  CsmCasesPage->>User: render CasesList + TablePagination
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • wso2-open-operations/cs-tools#860: Introduces BE_MAX_PAGE_LIMIT and adjusts useGetCsmCases paging constants — directly in the same hook this PR rewires for server-driven page/pageSize pagination.
  • wso2-open-operations/cs-tools#844: Modifies useCaseCountsMatrix React Query invalidation/query key — same hook this PR changes to exact per-cell counting.
  • wso2-open-operations/cs-tools#839: Changes LIVE query behavior and CsmCaseRow mapping in useGetCsmCases.ts, overlapping with this PR's identifier/timestamp mapping updates.

Suggested labels

Type/Improvement, Type/UX, App/CSM Portal, Area/Frontend, Platform/Web

Suggested reviewers

  • cloby99
  • Rashmika998

Poem

🐇 Hop hop, the pages now flow from the server's hand,
No more counting cases that the client had planned.
internalId replaces the old WSO2 name,
The matrix counts exactly — no sampling game!
A caseIdLabel shines where once stood bare,
This bunny approves of the pagination care! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely summarizes the main changes: human-readable case identifiers, server-side pagination, and backend-aligned column/field names.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The PR description comprehensively addresses the PR objectives, detailing backend field corrections, case identifier handling, server-side pagination, filter implementation, column layout changes, and dashboard improvements with verification steps.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

…real field names

Align FE types with the actual /cases/search payload
- Rename wso2Id -> internalId, createdAt -> createdOn, updatedAt -> updatedOn on
  the case view/search types and their mappers. The previous names never matched
  the backend, so the WSO2 case id and timestamps were silently empty.

Server-side pagination + page size (mirrors the projects/accounts pages)
- The list fetched only the first 50 rows and never surfaced the rest. It now
  pages via the backend's pagination/total/limit/offset/hasMore, with a
  TablePagination footer (10 / 20 / 50 per page; 50 is the backend max).

Push supported filters server-side
- search -> searchQuery (debounced), alongside severity/state/project; results
  sorted by updated_at desc. Assignee / SLA / product have no backend support
  and are disabled in live (product can't map name -> deployed-product id).
  Mock mode still filters + sorts + slices the seeded set client-side.

Columns reflect what the backend returns
- Drop Assignee and SLA (no backend data); add Product. Now:
  Case (ids + subject) | Customer | Product | Severity | State | Updated.
@rksk rksk changed the title [CSM Portal] Show human case IDs; count dashboard matrix via search totals [CSM Portal] Cases list & dashboard: human IDs, pagination, BE-aligned columns/fields Jun 15, 2026
Long subjects were cramped sharing one cell with the case ids (and the
customer column ate horizontal space). Restructure the row:
- Case ids move to their own narrow column (WSO2 internal id over CS number).
- Subject gets its own wide column with the project as context beneath.
- Drop the Customer column to free the space.
Columns: Case ID | Subject | Product | Severity | State | Updated.

@coderabbitai coderabbitai Bot 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.

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-cases/pages/CsmCasesPage.tsx`:
- Around line 155-166: The pagination can display an empty out-of-range page
when the total count decreases (from filter changes or backend updates) while
the current page index remains beyond the last valid page. Add a useEffect hook
that monitors the total value and recalculates the maximum valid page index
based on the current rowsPerPage. When total changes, clamp the page state to
ensure it does not exceed the calculated maximum valid page index, preventing
empty table displays with misleading range information. The effect should
trigger whenever total or rowsPerPage changes and update the page state if
necessary.

In `@apps/csm-portal/webapp/src/features/csm-cases/utils/casesClientFilter.ts`:
- Around line 37-45: The SLA status filters are matching closed cases because
they only check minutesToBreach values without verifying the case is active. In
the casesClientFilter.ts file, add a check to exclude closed cases before
evaluating the "breached" and "at_risk" SLA filter conditions. Determine how
closed cases are identified in the case object c (likely through a status
property or boolean flag) and add this condition early in the SLA filter logic
so closed cases return false and do not match any SLA status filters.
🪄 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: 965024a2-9ec2-4a68-945a-de363af3858a

📥 Commits

Reviewing files that changed from the base of the PR and between 6d9c9d3 and 4b4932f.

📒 Files selected for processing (13)
  • apps/csm-portal/webapp/src/api/backend/types.ts
  • apps/csm-portal/webapp/src/features/csm-cases/api/mocks/casesMocks.ts
  • apps/csm-portal/webapp/src/features/csm-cases/api/useGetCsmCaseDetail.ts
  • apps/csm-portal/webapp/src/features/csm-cases/api/useGetCsmCases.ts
  • apps/csm-portal/webapp/src/features/csm-cases/components/CasesFilterBar.tsx
  • apps/csm-portal/webapp/src/features/csm-cases/components/CasesList.tsx
  • apps/csm-portal/webapp/src/features/csm-cases/pages/CsmCaseDetailPage.tsx
  • apps/csm-portal/webapp/src/features/csm-cases/pages/CsmCasesPage.tsx
  • apps/csm-portal/webapp/src/features/csm-cases/types/csmCases.ts
  • apps/csm-portal/webapp/src/features/csm-cases/utils/caseIdentity.ts
  • apps/csm-portal/webapp/src/features/csm-cases/utils/casesClientFilter.ts
  • apps/csm-portal/webapp/src/features/csm-dashboard/api/useCaseCountsMatrix.ts
  • apps/csm-portal/webapp/src/features/csm-dashboard/components/CaseCountsMatrix.tsx
💤 Files with no reviewable changes (1)
  • apps/csm-portal/webapp/src/features/csm-dashboard/components/CaseCountsMatrix.tsx

Comment thread apps/csm-portal/webapp/src/features/csm-cases/utils/casesClientFilter.ts Outdated
… SLA filters

Address review feedback on the cases list:
- When the total shrinks (background refetch / rows closing) while on a later
  page, clamp back to the last valid page during render so the table never
  shows an empty out-of-range page with a misleading "showing X-Y" range.
- SLA status filters (mock mode) no longer match closed cases: a closed row
  with minutesToBreach = 0 previously satisfied "at_risk".
@rksk

rksk commented Jun 15, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

@rksk Sure, I'll review the changes in this PR now.

✅ Action performed

Full review finished.

@rksk rksk added Type/Improvement Marks enhancements or improvements to existing features Platform/Web App/CSM Portal labels Jun 15, 2026
@cloby99
cloby99 merged commit 550f59f into wso2-open-operations:v2 Jun 15, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

App/CSM Portal Platform/Web Type/Improvement Marks enhancements or improvements to existing features

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants