Skip to content

[Customer Portal] Add Created By filter to All Cases view - #774

Merged
Rashmika998 merged 1 commit into
wso2-open-operations:mainfrom
SasmithaDilshan:customer-portal
May 29, 2026
Merged

Rashmika998 merged 1 commit into
wso2-open-operations:mainfrom
SasmithaDilshan:customer-portal

Conversation

@SasmithaDilshan

@SasmithaDilshan SasmithaDilshan commented May 29, 2026 •

Copy link
Copy Markdown
Contributor

Description:

Summary

  • Added a Created By multi-select filter to the All Cases view, consistent with existing filters (Status, Severity, Category, Deployment)
  • Populated from project contacts — same user list as Settings > User Management
  • Sends selected user emails as createdBy: string[] in the case search request body

Changes

Types

  • AllCasesFilterValues — added createdBy?: string[]
  • CaseSearchFilters — added createdBy?: string[]
  • AllCasesFilterDefinition — made metadataKey optional to support filters with custom data sources

Filter UI

  • Added createdBy entry to ALL_CASES_FILTER_DEFINITIONS as multi-select
  • deriveFilterLabels — added label mapping: "Created By" / "All Users"
  • ListFilters — accepts contacts and isContactsLoading props; renders Created By dropdown with a "Loading..." state while contacts are in flight
  • ListSearchPanel — passes through contacts, isContactsLoading, and hideCreatedByFilter

Data & API

  • buildDashboardCaseSearchFilters — threads createdBy through all three return paths
  • AllCasesPage — calls useGetProjectContacts, passes contacts to the filter panel, and includes createdBy in the search request
  • useGetProjectContacts — aligned staleTime to 5 * 60 * 1000 (matching useGetProjectFilters) so contacts are cached and load instantly on repeat visits
  • Page-level loader (isInitialPageLoading) now waits for both cases and contacts before dismissing

Summary by CodeRabbit

  • New Features
    • Added a multi-select "Created By" filter to the cases list, enabling users to filter by one or more contacts who created cases.

Review Change Stack

  Adds a multi-select Created By dropdown filter to the All Cases page,
  populated from project contacts (same users as Settings > User Management).
  Includes staleTime alignment for contacts query and loading state sync.
@coderabbitai

coderabbitai Bot commented May 29, 2026 •

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

This PR adds a contact-driven "created by" filter to the case search feature in the customer portal. The implementation extends filter type definitions, registers the new filter in the filter configuration, updates dashboard filter building to use contact email arrays instead of a boolean flag, and wires the UI components to fetch and render contact options during case filtering.

Changes

Created By Filter Feature

Layer / File(s) Summary
Filter type contracts and configuration shapes
src/features/support/types/cases.ts, src/features/support/types/supportUiConfig.ts
AllCasesFilterValues and CaseSearchFilters add optional createdBy?: string[] field; AllCasesFilterDefinition.metadataKey becomes optional to support filters not backed by metadata.
Filter constant definition and label derivation
src/features/support/constants/supportConstants.ts, src/features/support/utils/support.ts
New "createdBy" filter registered in ALL_CASES_FILTER_DEFINITIONS with multi-select enabled; deriveFilterLabels returns "Created By" and "All Users" for this filter instead of derived labels.
Dashboard case filter building
src/features/dashboard/utils/dashboardNavigation.ts
buildDashboardCaseSearchFilters signature changes from createdByMe?: boolean to createdBy?: string[], normalizes the array input, and propagates it through all return branches.
Contact data caching strategy
src/features/settings/api/useGetProjectContacts.ts
React Query staleTime increased from 0 to 5 minutes (5 * 60 * 1000) to reduce refetch frequency for project contacts.
ListFilters contact options rendering
src/components/list-view/ListFilters.tsx
Component accepts contacts and isContactsLoading props; detects "createdBy" filter and generates selectable options from contact email/name; renders disabled "Loading..." when fetching; supports conditional hide via hideCreatedByFilter.
ListSearchPanel filter wrapper and wiring
src/components/list-view/ListSearchPanel.tsx
Extended props interface adds createdBy, contacts, isContactsLoading, and hideCreatedByFilter; forwards these to ListFilters and nulls out createdBy from filter counts when the filter is hidden.
AllCasesPage contacts and filter integration
src/features/support/pages/AllCasesPage.tsx
Fetches project contacts via useGetProjectContacts; maps response to contactsList; adds createdBy to case search request from filter state; includes contacts loading in page-level loading state; passes contacts and loading state to ListSearchPanel.

Sequence Diagram

sequenceDiagram
  participant User
  participant AllCasesPage
  participant useGetProjectContacts
  participant ListSearchPanel
  participant ListFilters
  
  User->>AllCasesPage: Load page
  AllCasesPage->>useGetProjectContacts: Fetch project contacts
  useGetProjectContacts-->>AllCasesPage: Contacts data + loading state
  AllCasesPage->>ListSearchPanel: Pass contacts, isContactsLoading
  User->>ListSearchPanel: Open createdBy filter
  ListSearchPanel->>ListFilters: Render with contact options
  ListFilters-->>User: Display contact list (or loading state)
  User->>ListFilters: Select contacts
  ListFilters->>AllCasesPage: Update filters.createdBy
  AllCasesPage->>AllCasesPage: Build caseSearchRequest with createdBy
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • wso2-open-operations/cs-tools#271: Earlier PR that introduced createdByMe?: boolean to backend CaseSearchFilters, now being replaced by frontend createdBy: string[] in this change.
  • wso2-open-operations/cs-tools#372: Prior refactor that made filter UI dynamically driven by ALL_CASES_FILTER_DEFINITIONS and deriveFilterLabels, which this PR extends with the new "createdBy" filter definition and label handling.

Suggested labels

Type/New Feature, Type/UX, App/Customer Portal, Area/Frontend, Platform/Web

Suggested reviewers

  • Rashmika998
  • cloby99
  • shayanmalinda

🐰 A filter for creators, built with care,
Contact names now float through the air,
Who made the case? Just ask the search,
No more wondering—find your perch! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive The PR description is well-structured with Summary, Changes sections covering types, filter UI, and data/API layers. However, it does not follow the repository's template and omits several required sections like Purpose/Goals, Approach, Release notes, Documentation, and Testing details. Align the description with the repository template by adding Purpose, Goals, Approach, Release note, Documentation, Testing sections, and other required information for a complete PR review.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: adding a Created By filter to the All Cases view in the Customer Portal.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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 and usage tips.

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

🧹 Nitpick comments (2)
apps/customer-portal/webapp/src/features/support/pages/AllCasesPage.tsx (1)

145-147: ⚡ Quick win

Remove the unused contactsList dependency from caseSearchRequest memo.

Line 186 adds contactsList to the dependency array, but it isn’t used inside the memo callback. Combined with Line 146 (contactsData ?? []), this can invalidate the memo repeatedly while contacts are loading.

Proposed fix
-  const contactsList = contactsData ?? [];
+  const contactsList = useMemo(() => contactsData ?? [], [contactsData]);

   const caseSearchRequest = useMemo(
     () => ({
       filters: {
         caseTypes: [CaseType.DEFAULT_CASE],
         ...buildDashboardCaseSearchFilters({
@@
     [
       statusFilter,
       filters,
       searchTerm,
       sortField,
       sortOrder,
       createdByMe,
       permissions.hasDeployments,
       filterMetadata?.caseStates,
       isDashboardSeverityNavigation,
       initialSeverityId,
-      contactsList,
     ],
   );

Also applies to: 186-186

🤖 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/customer-portal/webapp/src/features/support/pages/AllCasesPage.tsx`
around lines 145 - 147, The memo for caseSearchRequest is being invalidated by
the unused contactsList variable; remove contactsList from the dependency array
of the caseSearchRequest useMemo callback (located near the caseSearchRequest
declaration) so the memo no longer re-runs when contacts load; if the memo
genuinely depends on contact data, depend on contactsData (or isContactsLoading)
instead of contactsList, otherwise omit any contact-related dependency entirely
and keep the existing contactsData ?? [] assignment as is.
apps/customer-portal/webapp/src/features/dashboard/utils/dashboardNavigation.ts (1)

83-104: 💤 Low value

Dual createdByMe and createdBy filter support may cause confusion.

The function now accepts both createdByMe?: boolean (line 89) and createdBy?: string[] (line 90), passing both through to all return branches (lines 122-123, 132-133, 141-142). If both are set simultaneously, the backend behavior may be ambiguous.

Consider one of:

  1. Document that createdBy supersedes createdByMe when both are present
  2. Add validation to ensure mutual exclusion
  3. Confirm this dual support is intentional for backward compatibility during gradual migration
📋 Example validation for mutual exclusion
 export function buildDashboardCaseSearchFilters(params: {
   statusIds?: string[];
   severityIds?: string[];
   issueTypes?: string | string[];
   deploymentIds?: string[];
   searchQuery?: string;
   createdByMe?: boolean;
   createdBy?: string[];
   caseStates?: MetadataItem[];
   isDashboardSeverityNavigation?: boolean;
 }): CaseSearchFilters {
   const {
     statusIds,
     severityIds,
     issueTypes,
     deploymentIds,
     searchQuery,
     createdByMe,
     createdBy,
     caseStates,
     isDashboardSeverityNavigation = false,
   } = params;
+
+  // Ensure only one "created by" filter is active
+  if (createdByMe && createdBy?.length) {
+    throw new Error('Cannot specify both createdByMe and createdBy filters');
+  }
🤖 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/customer-portal/webapp/src/features/dashboard/utils/dashboardNavigation.ts`
around lines 83 - 104, In buildDashboardCaseSearchFilters, enforce mutual
exclusion between createdByMe and createdBy to avoid ambiguous backend requests:
at the start of the function (inside buildDashboardCaseSearchFilters) check if
both createdByMe and createdBy are provided and either throw a clear error or
normalize by choosing one behavior (e.g., treat createdBy as authoritative and
ignore createdByMe) and document that choice; update all return branches that
currently propagate createdByMe/createdBy so they use the normalized value
(refer to createdByMe and createdBy variables and the
buildDashboardCaseSearchFilters function name).
🤖 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.

Nitpick comments:
In
`@apps/customer-portal/webapp/src/features/dashboard/utils/dashboardNavigation.ts`:
- Around line 83-104: In buildDashboardCaseSearchFilters, enforce mutual
exclusion between createdByMe and createdBy to avoid ambiguous backend requests:
at the start of the function (inside buildDashboardCaseSearchFilters) check if
both createdByMe and createdBy are provided and either throw a clear error or
normalize by choosing one behavior (e.g., treat createdBy as authoritative and
ignore createdByMe) and document that choice; update all return branches that
currently propagate createdByMe/createdBy so they use the normalized value
(refer to createdByMe and createdBy variables and the
buildDashboardCaseSearchFilters function name).

In `@apps/customer-portal/webapp/src/features/support/pages/AllCasesPage.tsx`:
- Around line 145-147: The memo for caseSearchRequest is being invalidated by
the unused contactsList variable; remove contactsList from the dependency array
of the caseSearchRequest useMemo callback (located near the caseSearchRequest
declaration) so the memo no longer re-runs when contacts load; if the memo
genuinely depends on contact data, depend on contactsData (or isContactsLoading)
instead of contactsList, otherwise omit any contact-related dependency entirely
and keep the existing contactsData ?? [] assignment as is.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: da963a72-8168-4e3e-a307-26189c3c7300

📥 Commits

Reviewing files that changed from the base of the PR and between bc9d5ae and 3af21b5.

📒 Files selected for processing (9)
  • apps/customer-portal/webapp/src/components/list-view/ListFilters.tsx
  • apps/customer-portal/webapp/src/components/list-view/ListSearchPanel.tsx
  • apps/customer-portal/webapp/src/features/dashboard/utils/dashboardNavigation.ts
  • apps/customer-portal/webapp/src/features/settings/api/useGetProjectContacts.ts
  • apps/customer-portal/webapp/src/features/support/constants/supportConstants.ts
  • apps/customer-portal/webapp/src/features/support/pages/AllCasesPage.tsx
  • apps/customer-portal/webapp/src/features/support/types/cases.ts
  • apps/customer-portal/webapp/src/features/support/types/supportUiConfig.ts
  • apps/customer-portal/webapp/src/features/support/utils/support.ts

@Rashmika998
Rashmika998 merged commit cc7a1c9 into wso2-open-operations:main May 29, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants