[Customer Portal] Add Created By filter to All Cases view - #774
Conversation
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.
📝 WalkthroughWalkthroughThis 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. ChangesCreated By Filter Feature
Sequence DiagramsequenceDiagram
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
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ 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.
🧹 Nitpick comments (2)
apps/customer-portal/webapp/src/features/support/pages/AllCasesPage.tsx (1)
145-147: ⚡ Quick winRemove the unused
contactsListdependency fromcaseSearchRequestmemo.Line 186 adds
contactsListto 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 valueDual
createdByMeandcreatedByfilter support may cause confusion.The function now accepts both
createdByMe?: boolean(line 89) andcreatedBy?: 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:
- Document that
createdBysupersedescreatedByMewhen both are present- Add validation to ensure mutual exclusion
- 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
📒 Files selected for processing (9)
apps/customer-portal/webapp/src/components/list-view/ListFilters.tsxapps/customer-portal/webapp/src/components/list-view/ListSearchPanel.tsxapps/customer-portal/webapp/src/features/dashboard/utils/dashboardNavigation.tsapps/customer-portal/webapp/src/features/settings/api/useGetProjectContacts.tsapps/customer-portal/webapp/src/features/support/constants/supportConstants.tsapps/customer-portal/webapp/src/features/support/pages/AllCasesPage.tsxapps/customer-portal/webapp/src/features/support/types/cases.tsapps/customer-portal/webapp/src/features/support/types/supportUiConfig.tsapps/customer-portal/webapp/src/features/support/utils/support.ts
Description:
Summary
createdBy: string[]in the case search request bodyChanges
Types
AllCasesFilterValues— addedcreatedBy?: string[]CaseSearchFilters— addedcreatedBy?: string[]AllCasesFilterDefinition— mademetadataKeyoptional to support filters with custom data sourcesFilter UI
createdByentry toALL_CASES_FILTER_DEFINITIONSas multi-selectderiveFilterLabels— added label mapping: "Created By" / "All Users"ListFilters— acceptscontactsandisContactsLoadingprops; renders Created By dropdown with a "Loading..." state while contacts are in flightListSearchPanel— passes throughcontacts,isContactsLoading, andhideCreatedByFilterData & API
buildDashboardCaseSearchFilters— threadscreatedBythrough all three return pathsAllCasesPage— callsuseGetProjectContacts, passes contacts to the filter panel, and includescreatedByin the search requestuseGetProjectContacts— alignedstaleTimeto5 * 60 * 1000(matchinguseGetProjectFilters) so contacts are cached and load instantly on repeat visitsisInitialPageLoading) now waits for both cases and contacts before dismissingSummary by CodeRabbit