Skip to content

[CSM Portal] case-type + assignee filters; align FE with BE field rename - #930

Merged
dilshanfardil merged 4 commits into
wso2-open-operations:v2from
rksk:csm-case-filters
Jun 24, 2026
Merged

[CSM Portal] case-type + assignee filters; align FE with BE field rename#930
dilshanfardil merged 4 commits into
wso2-open-operations:v2from
rksk:csm-case-filters

Conversation

@rksk

@rksk rksk commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Stacked on the merged mock-removal work; rebased onto current v2.

1. Case-type + assignee filters

  • Case type — multi-select wired to /cases/search types, URL param types.
  • Assignee — email-based engineer picker + @me. Disabled ("coming soon") and not sent (no /cases/search assignee filter yet), so it can't break the search. Built to enable in one flip once the BE adds it.

2. Align FE with the BE Key/Keys rename (entity PR #929 / BFF #933)

  • search filters severityKeys→severities, stateKeys→states, typeKeys→types; response title→subject; POST /cases typeKey→type, severityKey→severity, issueTypeKey→issueType; PATCH /cases/{id} stateKey→state/severityKey→severity/workStateKey→workState; deployment search deploymentTypeKeys→deploymentTypes.

3. Review fixes

  • useFindMyOngoingCases pages through all work_in_progress results (bounded by BE_MAX_PAGE_LIMIT).
  • useDirectoryUsers drops directory entries without an email.

4. Align FE with BE PR #938 (entity #934)

  • Case type value supportcase across BeCaseType, POST /cases, the case-type filter (label "Support" → "Case"), and CsmCaseCreatePage.
  • CaseView: add nullable type/engagementType + catalog/catalogItem/assignedTeam/conversation refs; mark deployment/deployedProduct nullable.
  • CaseSearchView: add type (mapped onto the row); mark deployment/deployedProduct nullable.

⚠️ Merge order: part 4 sends the new case value, so merge this after BE PR #938 — otherwise the cases list/create send case to a BE that still expects support.

Testing

pnpm lint, pnpm test, pnpm build, tsc -b all green.

@coderabbitai

coderabbitai Bot commented Jun 24, 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 53 minutes and 52 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.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

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: 43e0dcdc-885c-4c76-9b5d-c66f8293bbc8

📥 Commits

Reviewing files that changed from the base of the PR and between 9f1adc3 and 7eecd4b.

📒 Files selected for processing (1)
  • apps/csm-portal/webapp/src/features/csm-cases/api/useFindMyOngoingCases.ts
📝 Walkthrough

Walkthrough

Frontend types, hooks, and components in the CSM portal are updated to match backend API field renames (dropping *Key/*Keys suffixes from case create/update/search payloads). A new case-type filter is added to CasesFilters, assignees switch from name-based to email-based values, and the ongoing-case search gains multi-page pagination.

Changes

Backend Alignment, Case-Type Filtering, and Assignee Email Migration

Layer / File(s) Summary
Backend API type renames and frontend row types
src/api/backend/types.ts, src/features/csm-cases/types/csmCases.ts
BeCaseCreatePayload, BeCaseUpdatePayload, BeCaseSearchFilters, BeCaseSearchView, and BeDeploymentSearchPayload drop *Key/*Keys suffixes; BeCaseSearchView.title becomes subject; CsmCaseRow gains caseType; CsmCasesListResponse drops scope.
Case-type order and label constants
src/features/csm-cases/utils/caseType.ts
New module exports ALL_CASE_TYPES and CASE_TYPE_LABEL as a shared single source of truth for case-type ordering and display strings.
CasesFilters shape, URL serialization, and filter bar UI
src/features/csm-cases/components/CasesFilterBar.tsx, src/features/csm-cases/utils/casesFiltersUrl.ts, src/features/csm-cases/utils/casesFiltersUrl.test.ts
CasesFilters adds caseTypes and switches assignees to email-based values; URL read/write/count functions updated; filter bar adds a Case type multi-select and rewires the assignee picker to email-backed options with @me support; tests updated for new shape.
Directory user email requirement
src/api/useDirectoryUsers.ts
Query post-processing rejects entries missing an email in addition to those missing a name, ensuring only users with both fields appear in the assignee picker.
Cases list search payload and row mapping
src/features/csm-cases/api/useGetCsmCases.ts, src/features/csm-cases/api/useQuickCaseSearch.ts
React Query key adds caseTypes and removes assignees; /cases/search payload uses renamed fields (severities, states, types, projectIds); case subject mapped from c.subject in both hooks.
Paginated ongoing-case lookup
src/features/csm-cases/api/useFindMyOngoingCases.ts
Single-page fetch replaced with a MAX_PAGES loop using states: ["work_in_progress"], accumulating matches by excludeCaseId, workState, and engineer email, stopping on hasMore or short page.
Case create and detail page PATCH payloads
src/features/csm-cases/pages/CsmCaseCreatePage.tsx, src/features/csm-cases/pages/CsmCaseDetailPage.tsx
Create page sends type/severity/issueType; detail page sends state and workState across all lifecycle PATCH calls; not-found message now includes the caseId.
Dashboard aggregation hooks
src/features/csm-dashboard/api/useCaseComposition.ts, src/features/csm-dashboard/api/useCaseCountsMatrix.ts
severityKeys/stateKeys replaced with severities/states in all /cases/search fan-out requests.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • wso2-open-operations/cs-tools#893: Modifies the same BeCaseUpdatePayload and case search view field shapes in api/backend/types.ts, directly overlapping with the workState and PATCH contract renames in this PR.
  • wso2-open-operations/cs-tools#933: Backend PR that drops the same *Key/*Keys suffixes from request/response JSON fields (stateKey→state, severityKey→severity, typeKeys→types, deploymentTypeKeys→deploymentTypes) that this PR consumes on the frontend.
  • wso2-open-operations/cs-tools#914: Directly touches the same case create/update request-field naming surface (stateKey, typeKey) that this PR renames to state/type.

Suggested labels

Type/Improvement, App/Customer Portal, Platform/Web

Suggested reviewers

  • dilshanfardil
  • shayanmalinda

Poem

🐇 Hop, hop, no more *Key in sight,
The fields are renamed, the payloads just right!
caseTypes now filters, subject holds true,
Emails for assignees — a fresh point of view.
The backend and frontend now dance hand in paw,
A cleaner contract without any flaw! 🌟

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description does not follow the required template and omits most mandatory sections like Purpose, Goals, Approach, and checks. Rewrite the PR description using the repository template and fill in all required sections, especially Purpose, Goals, Approach, Testing, and Security checks.
Docstring Coverage ⚠️ Warning Docstring coverage is 53.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main changes: case-type/assignee filters and FE/BE field renames.
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.

✏️ 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.

@rksk rksk changed the title [CSM Portal] add case-type filter to cases list [CSM Portal] add case-type and assignee filters to cases list Jun 24, 2026
@rksk
rksk force-pushed the csm-case-filters branch from 21044c5 to 1f346d9 Compare June 24, 2026 08:03

@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: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
apps/csm-portal/webapp/src/features/csm-cases/api/useFindMyOngoingCases.ts (1)

56-65: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Page through the search results before concluding there are no ongoing cases.

Now that this hook always uses /cases/search, it only inspects the first 50 work_in_progress rows and then filters assignee/workState client-side. If there are more than 50 matching cases overall, this can miss the current user's ongoing case and suppress the warning flow.

Suggested fix
-      const res = await api.post<BeCaseSearchPayload, BeCaseSearchResponse>(
-        "/cases/search",
-        {
-          filters: { stateKeys: ["work_in_progress"] },
-          pagination: { offset: 0, limit: SEARCH_LIMIT },
-        },
-      );
-
-      return (res.cases ?? [])
-        .filter(
-          (c) =>
-            c.id !== excludeCaseId &&
-            // A null/absent workState is never "ongoing".
-            c.workState === "ongoing" &&
-            c.assignedEngineer?.email?.toLowerCase() === myEmail,
-        )
-        .map((c) => ({
-          id: c.id,
-          label: c.internalId || c.number || c.title || c.id,
-        }));
+      const matches: MyOngoingCase[] = [];
+
+      for (let offset = 0; ; offset += SEARCH_LIMIT) {
+        const res = await api.post<BeCaseSearchPayload, BeCaseSearchResponse>(
+          "/cases/search",
+          {
+            filters: { stateKeys: ["work_in_progress"] },
+            pagination: { offset, limit: SEARCH_LIMIT },
+          },
+        );
+
+        const page = res.cases ?? [];
+        matches.push(
+          ...page
+            .filter(
+              (c) =>
+                c.id !== excludeCaseId &&
+                c.workState === "ongoing" &&
+                c.assignedEngineer?.email?.toLowerCase() === myEmail,
+            )
+            .map((c) => ({
+              id: c.id,
+              label: c.internalId || c.number || c.title || c.id,
+            })),
+        );
+
+        if (page.length < SEARCH_LIMIT) break;
+      }
+
+      return matches;
🤖 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/webapp/src/features/csm-cases/api/useFindMyOngoingCases.ts`
around lines 56 - 65, The `useFindMyOngoingCases` search currently only checks
the first page of `/cases/search` results, so it can miss the user’s case when
there are more than 50 `work_in_progress` items. Update the logic in the
`useFindMyOngoingCases` request flow to page through `api.post("/cases/search",
...)` results until all matching cases are exhausted, then apply the existing
assignee/workState filtering before deciding there are no ongoing cases.
apps/csm-portal/webapp/src/api/useDirectoryUsers.ts (1)

61-64: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Filter out directory users without emails.

/users/search can return users with no email, but assignee options are email-backed and later sent as assignedTo. Returning name-only users can create empty/invalid assignee filter values.

Proposed fix
-      return rows.map(toDirectoryUser).filter((u) => u.name);
+      return rows.map(toDirectoryUser).filter((u) => u.name && u.email);
🤖 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/webapp/src/api/useDirectoryUsers.ts` around lines 61 - 64,
The user list normalization in useDirectoryUsers should exclude entries that do
not have an email address, since assignee options are email-backed and invalid
name-only users can leak through. Update the mapping/filtering around
toDirectoryUser so the returned rows only include users with a valid email,
while preserving the existing name check and the /users/search response
handling.
🧹 Nitpick comments (2)
apps/csm-portal/webapp/src/features/csm-dashboard/api/useCaseComposition.ts (1)

79-133: 🚀 Performance & Scalability | 🔵 Trivial | 🏗️ Heavy lift

Avoid recomputing counts the matrix already fetched.

CsmDashboardPage renders CaseCountsMatrix and CaseCompositionCharts together, so this hook issues a second wave of /cases/search requests for the same active severity/state totals that the matrix query already loaded. Deriving bySeverity/byState from the matrix data (or moving both widgets onto one aggregate backend response) would cut dashboard load/refetch traffic substantially while keeping only the separate closed-case lookup here.

🤖 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/webapp/src/features/csm-dashboard/api/useCaseComposition.ts`
around lines 79 - 133, The hook in useCaseComposition is recomputing active
severity/state totals that CaseCountsMatrix already fetches, causing duplicate
/cases/search traffic. Reuse the matrix-provided counts to populate bySeverity
and byState instead of issuing the Promise.all wave in this hook, and keep only
the separate closed-case lookup here. If needed, adjust the data flow between
CsmDashboardPage, CaseCountsMatrix, and CaseCompositionCharts so both widgets
consume a shared aggregate response.
apps/csm-portal/webapp/src/features/csm-cases/components/CasesFilterBar.tsx (1)

80-99: 📐 Maintainability & Code Quality | 🔵 Trivial

Move ASSIGNEE_ME_TOKEN and CasesFilters into a shared module. They’re used by the URL helpers and cases API, so keeping them in CasesFilterBar.tsx mixes shared contract data with the component.

🤖 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/webapp/src/features/csm-cases/components/CasesFilterBar.tsx`
around lines 80 - 99, Move the shared filter contract out of CasesFilterBar.tsx:
the ASSIGNEE_ME_TOKEN constant and CasesFilters interface are used by the URL
helpers and cases API, so extract them into a dedicated shared module and update
all imports to reference that module. Keep CasesFilterBar focused on UI state,
and make sure the shared symbol names remain ASSIGNEE_ME_TOKEN and CasesFilters
so existing callers can be migrated cleanly.
🤖 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/utils/casesFiltersUrl.ts`:
- Line 74: The assignee query parsing in casesFiltersUrl currently forwards
arbitrary values from parseFreeFormCsv(params.get("assignees")) into the backend
search filter. Update the assignees handling so only valid values are kept:
allow the special token `@me` and email-shaped entries, and discard anything else
before building the backend payload. Keep the fix localized to the assignees
mapping in the URL-to-filter conversion logic so the rest of the filter parsing
remains unchanged.

---

Outside diff comments:
In `@apps/csm-portal/webapp/src/api/useDirectoryUsers.ts`:
- Around line 61-64: The user list normalization in useDirectoryUsers should
exclude entries that do not have an email address, since assignee options are
email-backed and invalid name-only users can leak through. Update the
mapping/filtering around toDirectoryUser so the returned rows only include users
with a valid email, while preserving the existing name check and the
/users/search response handling.

In `@apps/csm-portal/webapp/src/features/csm-cases/api/useFindMyOngoingCases.ts`:
- Around line 56-65: The `useFindMyOngoingCases` search currently only checks
the first page of `/cases/search` results, so it can miss the user’s case when
there are more than 50 `work_in_progress` items. Update the logic in the
`useFindMyOngoingCases` request flow to page through `api.post("/cases/search",
...)` results until all matching cases are exhausted, then apply the existing
assignee/workState filtering before deciding there are no ongoing cases.

---

Nitpick comments:
In `@apps/csm-portal/webapp/src/features/csm-cases/components/CasesFilterBar.tsx`:
- Around line 80-99: Move the shared filter contract out of CasesFilterBar.tsx:
the ASSIGNEE_ME_TOKEN constant and CasesFilters interface are used by the URL
helpers and cases API, so extract them into a dedicated shared module and update
all imports to reference that module. Keep CasesFilterBar focused on UI state,
and make sure the shared symbol names remain ASSIGNEE_ME_TOKEN and CasesFilters
so existing callers can be migrated cleanly.

In `@apps/csm-portal/webapp/src/features/csm-dashboard/api/useCaseComposition.ts`:
- Around line 79-133: The hook in useCaseComposition is recomputing active
severity/state totals that CaseCountsMatrix already fetches, causing duplicate
/cases/search traffic. Reuse the matrix-provided counts to populate bySeverity
and byState instead of issuing the Promise.all wave in this hook, and keep only
the separate closed-case lookup here. If needed, adjust the data flow between
CsmDashboardPage, CaseCountsMatrix, and CaseCompositionCharts so both widgets
consume a shared aggregate response.
🪄 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: 99b236bd-9d8b-4508-9937-54e02b18d14a

📥 Commits

Reviewing files that changed from the base of the PR and between d6c9c40 and 1f346d9.

📒 Files selected for processing (35)
  • apps/csm-portal/webapp/src/AppWithConfig.tsx
  • apps/csm-portal/webapp/src/api/backend/client.ts
  • apps/csm-portal/webapp/src/api/backend/types.ts
  • apps/csm-portal/webapp/src/api/useDirectoryUsers.ts
  • apps/csm-portal/webapp/src/components/header/Actions.tsx
  • apps/csm-portal/webapp/src/components/header/MockModeToggle.tsx
  • apps/csm-portal/webapp/src/config/authConfig.ts
  • apps/csm-portal/webapp/src/context/mock-mode/MockModeContext.tsx
  • apps/csm-portal/webapp/src/features/csm-cases/api/mocks/casesMocks.ts
  • apps/csm-portal/webapp/src/features/csm-cases/api/mocks/commentsMocks.ts
  • apps/csm-portal/webapp/src/features/csm-cases/api/useCsmCaseAttachments.ts
  • apps/csm-portal/webapp/src/features/csm-cases/api/useCsmCaseComments.ts
  • apps/csm-portal/webapp/src/features/csm-cases/api/useFindMyOngoingCases.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/api/usePatchCsmCase.ts
  • apps/csm-portal/webapp/src/features/csm-cases/api/usePostCsmCase.ts
  • apps/csm-portal/webapp/src/features/csm-cases/api/useQuickCaseSearch.ts
  • apps/csm-portal/webapp/src/features/csm-cases/components/CaseActionBar.test.tsx
  • apps/csm-portal/webapp/src/features/csm-cases/components/CasesFilterBar.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/caseType.ts
  • apps/csm-portal/webapp/src/features/csm-cases/utils/casesClientFilter.ts
  • apps/csm-portal/webapp/src/features/csm-cases/utils/casesFiltersUrl.test.ts
  • apps/csm-portal/webapp/src/features/csm-cases/utils/casesFiltersUrl.ts
  • apps/csm-portal/webapp/src/features/csm-dashboard/api/mocks/dashboardMocks.ts
  • apps/csm-portal/webapp/src/features/csm-dashboard/api/useCaseComposition.ts
  • apps/csm-portal/webapp/src/features/csm-dashboard/api/useCaseCountsMatrix.ts
  • apps/csm-portal/webapp/src/features/csm-dashboard/api/useGetCsmDashboard.ts
  • apps/csm-portal/webapp/src/features/csm-dashboard/components/MyQueueSection.tsx
  • apps/csm-portal/webapp/src/features/csm-dashboard/components/SlaAtRiskSection.tsx
  • apps/csm-portal/webapp/src/main.tsx
  • apps/csm-portal/webapp/vite.config.ts
💤 Files with no reviewable changes (12)
  • apps/csm-portal/webapp/src/features/csm-dashboard/components/MyQueueSection.tsx
  • apps/csm-portal/webapp/src/main.tsx
  • apps/csm-portal/webapp/src/features/csm-cases/utils/casesClientFilter.ts
  • apps/csm-portal/webapp/src/context/mock-mode/MockModeContext.tsx
  • apps/csm-portal/webapp/src/features/csm-cases/api/mocks/commentsMocks.ts
  • apps/csm-portal/webapp/src/features/csm-cases/api/mocks/casesMocks.ts
  • apps/csm-portal/webapp/src/api/backend/client.ts
  • apps/csm-portal/webapp/src/components/header/MockModeToggle.tsx
  • apps/csm-portal/webapp/src/features/csm-dashboard/api/mocks/dashboardMocks.ts
  • apps/csm-portal/webapp/src/features/csm-dashboard/components/SlaAtRiskSection.tsx
  • apps/csm-portal/webapp/src/components/header/Actions.tsx
  • apps/csm-portal/webapp/src/config/authConfig.ts

@rksk

rksk commented Jun 24, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

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.

Add two filters to the cases list filter bar:

- Case type: a multi-select dropdown (Support, Service request, Security
  report, Announcement, Engagement) wired to the /cases/search 'typeKeys'
  filter and serialized to the 'types' URL param.

- Assignee: an email-based engineer picker (options labelled by name,
  valued by email) plus a '@me' sentinel. Wired to /cases/search as
  'assignedTo' (engineer emails) + 'assignedToMe' (caller), mirroring the
  existing createdBy / createdByMe pair. NOTE: these search-filter fields
  are pending backend support; the FE sends them so the filter works the
  moment the entity/BFF add them. Serialized to the 'assignees' URL param.

Both counted as active filters and round-tripped through the URL.
@rksk rksk changed the title [CSM Portal] add case-type and assignee filters to cases list [CSM Portal] case-type + assignee filters; align FE with BE field rename Jun 24, 2026
…itle->subject)

Backend dropped the Key/Keys suffix from case enum request fields and
standardised the search response on 'subject'. Align every FE call site:

- /cases/search filters: severityKeys->severities, stateKeys->states,
  typeKeys->types (useGetCsmCases, useFindMyOngoingCases,
  useCaseCountsMatrix, useCaseComposition; BeCaseSearchFilters type).
- search response: title->subject (the list subject was rendering as
  '(no subject)'), and caseType dropped from the search view
  (useGetCsmCases / useQuickCaseSearch / useFindMyOngoingCases mappers,
  BeCaseSearchView type).
- POST /cases: typeKey->type, severityKey->severity, issueTypeKey->issueType
  (CsmCaseCreatePage, BeCaseCreatePayload).
- PATCH /cases/{id}: stateKey->state, severityKey->severity,
  workStateKey->workState (CsmCaseDetailPage, BeCaseUpdatePayload).

Pure field renames; no behaviour change. assignedTo/assignedToMe (the
pending assignee filter) left intact.
@rksk
rksk force-pushed the csm-case-filters branch from 1f346d9 to c97993b Compare June 24, 2026 08:36
@rksk rksk added the Type/New Feature Represents a request or task for a new feature label Jun 24, 2026
@rksk

rksk commented Jun 24, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

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.

…g-case lookup, require directory email

- Assignee filter: disabled in the UI ('coming soon') and NOT sent in the
  /cases/search payload. /cases/search has no assigned-engineer filter and
  the entity rejects unknown fields, so sending one would 400 the whole
  search. The email-based picker stays, ready to enable when the BE adds
  the field. Removes the speculative assignedTo/assignedToMe.
- useFindMyOngoingCases: page through all work_in_progress results (bounded)
  instead of inspecting only the first page, so the single-active-case guard
  can't miss a case beyond page 1 (CodeRabbit, Major).
- useDirectoryUsers: drop directory users without an email, since assignee
  options are email-backed (CodeRabbit, Major).
@rksk

rksk commented Jun 24, 2026

Copy link
Copy Markdown
Contributor Author

Thanks @coderabbitai — dispositions:

Fixed

  • useFindMyOngoingCases (page through results): done — it now loops through all work_in_progress pages (bounded by a safety cap) before deciding, so the single-active-case guard won't miss a case beyond page 1.
  • useDirectoryUsers (require email): done — filter(u => u.name && u.email).

No longer applicable

  • casesFiltersUrl assignees validation, and moving ASSIGNEE_ME_TOKEN/CasesFilters to a shared module: the assignee filter is now disabled and never sent to the backend (no /cases/search support yet), so untrusted assignees URL values can't reach the API and the shared-module coupling those changes required is unnecessary for now. Will revisit both when the BE adds the assignee filter and the control is re-enabled.

Deferred (pre-existing, out of this PR's scope)

  • Dashboard duplicate /cases/search traffic (useCaseComposition recomputing what CaseCountsMatrix already fetches): valid, but it predates this PR and needs a cross-component data-flow change. Tracking separately rather than widening this PR.

@rksk

rksk commented Jun 24, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

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.

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

@rksk Thanks for the detailed rundown!

Fixes ✓ — Pagination guard in useFindMyOngoingCases (bounded page-loop) and the name && email filter in useDirectoryUsers both look solid. Appreciate the quick turnaround.

No longer applicable ✓ — Makes complete sense. Validating/sanitising assignees URL values and decoupling the shared types are only worthwhile once the control is live and the backend consumes them. Withdrawing those suggestions; I've noted the context below so the same suggestions don't resurface prematurely.

Deferred — Good call keeping the dashboard duplicate-traffic concern out of scope here. Would you like me to open a GitHub issue to track the useCaseComposition / useCaseCountsMatrix deduplication work so it doesn't fall through the cracks?

🐇 (__/)
(•ᴗ•)っ ✔


✏️ Learnings added
Learnt from: rksk
URL: https://github.com/wso2-open-operations/cs-tools/pull/930

Timestamp: 2026-06-24T08:45:58.407Z
Learning: In apps/csm-portal/webapp/src/features/csm-cases/components/CasesFilterBar.tsx and casesFiltersUrl.ts, the assignee filter (`assignees` URL param, `ASSIGNEE_ME_TOKEN`, `CasesFilters.assignees`) is intentionally disabled and never forwarded to the backend `/cases/search` API because the backend does not yet support `assignedTo` / `assignedToMe` filtering. Do not flag missing assignees URL-value validation or suggest moving `ASSIGNEE_ME_TOKEN`/`CasesFilters` to a shared module until the backend adds support and the control is re-enabled.

Learnt from: rksk
URL: https://github.com/wso2-open-operations/cs-tools/pull/930

Timestamp: 2026-06-24T08:45:58.407Z
Learning: In apps/csm-portal/webapp, the duplicate `/cases/search` traffic caused by `useCaseComposition` recomputing counts that `useCaseCountsMatrix` already fetches is a pre-existing issue predating PR `#930`. It requires a cross-component data-flow refactor and is being tracked separately; do not flag it as part of mock-removal or filter-addition PRs.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


If you found this review helpful, would you consider giving us a shout-out on X?

Thank you for using CodeRabbit!

@rksk

rksk commented Jun 24, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai resume

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Reviews resumed.

useFindMyOngoingCases paged at 100, which exceeds BE_MAX_PAGE_LIMIT (50)
and would be rejected by the backend. Use BE_MAX_PAGE_LIMIT as the page
size. All other search requests already sit at or below the cap.

@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: 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/pages/CsmCaseDetailPage.tsx`:
- Around line 584-586: The work-state transition in CsmCaseDetailPage’s case
update flow is not atomic, so a successful pause on older cases can be left
behind if a later patchCaseById or patchCase.mutateAsync call fails. Update this
flow so the grouped case-state change is handled atomically on the server, or
add compensating logic that restores any already-paused cases before
rethrowing/surfacing the error from the patchCaseById and patchCase steps.
🪄 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: 31498ab6-3ddf-41da-a104-cff7210c1ace

📥 Commits

Reviewing files that changed from the base of the PR and between 1f346d9 and 9f1adc3.

📒 Files selected for processing (14)
  • apps/csm-portal/webapp/src/api/backend/types.ts
  • apps/csm-portal/webapp/src/api/useDirectoryUsers.ts
  • apps/csm-portal/webapp/src/features/csm-cases/api/useFindMyOngoingCases.ts
  • apps/csm-portal/webapp/src/features/csm-cases/api/useGetCsmCases.ts
  • apps/csm-portal/webapp/src/features/csm-cases/api/useQuickCaseSearch.ts
  • apps/csm-portal/webapp/src/features/csm-cases/components/CasesFilterBar.tsx
  • apps/csm-portal/webapp/src/features/csm-cases/pages/CsmCaseCreatePage.tsx
  • apps/csm-portal/webapp/src/features/csm-cases/pages/CsmCaseDetailPage.tsx
  • apps/csm-portal/webapp/src/features/csm-cases/types/csmCases.ts
  • apps/csm-portal/webapp/src/features/csm-cases/utils/caseType.ts
  • apps/csm-portal/webapp/src/features/csm-cases/utils/casesFiltersUrl.test.ts
  • apps/csm-portal/webapp/src/features/csm-cases/utils/casesFiltersUrl.ts
  • apps/csm-portal/webapp/src/features/csm-dashboard/api/useCaseComposition.ts
  • apps/csm-portal/webapp/src/features/csm-dashboard/api/useCaseCountsMatrix.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • apps/csm-portal/webapp/src/features/csm-cases/utils/caseType.ts
  • apps/csm-portal/webapp/src/features/csm-cases/utils/casesFiltersUrl.ts
  • apps/csm-portal/webapp/src/features/csm-cases/types/csmCases.ts
  • apps/csm-portal/webapp/src/features/csm-cases/components/CasesFilterBar.tsx

@dilshanfardil
dilshanfardil merged commit 9fcc885 into wso2-open-operations:v2 Jun 24, 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 Area/Frontend Type/New Feature Represents a request or task for a new feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants