[Customer Portal][FE][Web] Improve Deployment Search Pagination and Remove Project Card Descriptions - #457
Conversation
Make the empty MenuItem entries for product, version, start level, and end level disabled and show context-aware placeholder text. Placeholders now reflect loading state and empty lists (e.g. "No products available", "No versions available", "No starting update levels available", "No ending update levels available") while preserving the default "Select ..." prompts when appropriate. This prevents selecting an empty value and provides clearer UX feedback based on isProductLevelsLoading, filter state, and the relevant arrays (productNames, versionEntries, startLevelOptions, endLevelOptions).
Allow productOptionList to be recognized as a list even when empty, by splitting Array.isArray(productOptionList) into useProductOptionList and a separate hasProductRows check. Add showNoProductsHint to display a "No products available for this deployment" placeholder when there are no rows and the dropdown is not disabled or loading. Replace MenuProps.PaperProps with MenuListProps to ensure onScroll handlers for deployments and products menus are attached correctly. Adjust renderValue and empty MenuItem logic to surface the new hint and make dropdown behavior clearer for empty lists.
Remove the combined 'noveraAndKb' success kind and message, and simplify the patch logic for toggling the Novera AI assistant. Disabling the assistant no longer forces hasKbReferences to false; the mutation now only updates hasAgent and always shows the 'novera' success message. Also adjusted the notifyPatchSuccess callback dependencies to use projectDetails instead of projectDetails?.hasAgent and cleaned up related handlers.
Remove the unused `subtitle` prop from ProjectCardProps and the ProjectCard component signature, and stop passing `subtitle` to ProjectCardInfo. Also reduce the card container `minHeight` from 320 to 260 to tighten the layout.
Adjust tests to match updated @wso2/oxygen-ui component shape: remove mocked Card, add Form.CardButton mock, and simplify CardHeader to render only title. Update assertions to expect card-button instead of card and reduce expected skeleton-text count from 9 to 6 to reflect the component change.
Drop the subtitle prop and related rendering from ProjectCardInfo: removes the stripHtmlTags import and useMemo/substring logic, deletes the subheader/descripton block (clamped text + tooltip), and updates the JSDoc and constants to reflect that hub cards only render a title. This simplifies the card since project hub cards no longer show descriptions.
Update the ProjectCard unit tests: the mocked ProjectCardInfo now only accepts and renders a typed title prop ({ title: string }) instead of title and subtitle, and the test fixture no longer includes the subtitle field. This keeps the test mock in sync with the component's API and avoids asserting on subtitle output.
Remove the ProjectDescription import, the getDescription helper, and the <ProjectDescription /> rendering from ProjectInformationCard. Cleans up unused code after removing the project description display from the project overview.
Replace addApiHeaders with mergeApiHeaders in the useAllDeploymentProducts hook and pass init?.headers to merge existing headers with the auth token. This prevents overwriting custom fetch headers when calling fetchDeploymentProductsAll.
Refactor ProjectCardInfo unit tests and update the @wso2/oxygen-ui mock. The mock now includes explicit any typings (with eslint-disable comments), removes the CardHeader subheader mock, and adjusts Tooltip/Typography mocks. Tests were simplified to focus on rendering the project title, verifying h6 typography for the title, and checking the '--' fallback for an empty title; removed HTML subtitle stripping and body2/subtitle assertions.
Adjust tests for ProjectInformationCard by updating and simplifying mocks to match current implementation. Removed the mocked ProjectDescription component and corresponding assertions, switched the utils mock from "@/utils/projectStats" to "@utils/projectDetails" with a simple formatProjectDate implementation, and added startDate/endDate to the test project fixture. These changes align the tests with the component's updated dependencies and expected output.
Reduce ProjectCardSkeleton minHeight from 320 to 260 and remove the subheader Skeleton block (the three text skeleton lines). This decreases the card's vertical footprint and simplifies the skeleton layout.
In apps/customer-portal/webapp/src/components/support/all-cases/AllCasesFilters.tsx, move the onScroll handler from PaperProps to MenuListProps inside MenuProps when isDeploymentFilter is true. This corrects the target of the scroll listener so load-more behavior for deployments triggers on the menu list element rather than the paper wrapper.
Use getDeploymentProductDisplayLabel and isUnknownPlaceholderProductLabel when filtering deploymentProductsData to remove empty or placeholder "unknown" labels from allDeploymentProducts. Replaces the previous simple trim check on product.label and adds the two new imports so placeholder entries won't appear in product options.
Refactor tests for BasicInformationSection: remove interaction-based edit-button/toggle tests and add a new test that asserts the no-products hint when the product list is empty and a deployment is selected. Also remove the unused fireEvent import and update the renderSection call to pass productOptionList, isProductDropdownDisabled, and isProductLoading props. This aligns the tests with the component's current UI behavior for empty product lists.
Remove subtitle={project.description} from ProjectHub.tsx so the project description is no longer passed as a subtitle to the project card. Prevents the subtitle from rendering in the project list and centralizes description handling.
Import isUnknownPlaceholderProductLabel and add unit tests to verify detection of empty/unknown-only product labels and that real product labels are not flagged. Also add a test to ensure getBaseProductOptions omits placeholder "Unknown Unknown" product/version rows. Helps prevent placeholder entries from appearing in product option lists.
Move the onScroll handler from PaperProps to MenuListProps inside MenuProps in FilterPopover. This ensures the scroll event is attached to the menu list (so field.onLoadMore is triggered correctly for select menus) rather than the Paper element.
Lower the minHeight prop on the issue description editor in DescribeIssuePage from 270 to 250 to slightly reduce the initial editor height and improve page layout/spacing. No other behavior or props were changed.
Add buildDeployedProductSearchPayload to construct a safe request body (only pagination and optional consumption filters) instead of spreading unknown keys. Refactor postDeploymentProductsSearchPage usage and make fetchDeploymentProductsAll pagination robust: iterate until no more items, compute nextOffset from page.offset/limit, respect page.totalRecords when present, and handle cases where totalRecords is missing. Update getNextPageParam in the infinite hook to use totalRecords when available and fallback to item count vs limit to decide next offset.
Handle cases where totalRecords is missing or NaN and prevent infinite paging. Updated usePostProjectDeploymentsSearchInfinite to prefer numeric totalRecords but fall back to comparing page item count against limit to determine next offset. Refactored usePostProjectDeploymentsSearchAll to use a while(true) loop, compute nextOffset, respect numeric totalRecords when present, and stop when fewer items than the page limit or when nextOffset reaches total. These changes make pagination more robust when the backend omits totalRecords or returns invalid values.
Replace MenuProps.PaperProps with MenuProps.MenuListProps so the onScroll handler is attached to the menu list element. This ensures the load-more behavior (field.onLoadMore) is triggered correctly when scrolling the menu in the CasesFilters component.
Filter out deployment products whose display label is empty or corresponds to an unknown/placeholder label when building allDeploymentProducts. Adds an import for isUnknownPlaceholderProductLabel and uses getDeploymentProductDisplayLabel to determine and exclude placeholder labels from the options.
Add isUnknownPlaceholderProductLabel(label) to detect combined product/version labels that are empty or composed only of 'unknown' tokens. Use this helper in getBaseProductOptions and buildEnvProducts to exclude placeholder labels (e.g. "Unknown Unknown") so meaningless options are not returned for product lists.
Import addApiHeaders and add helper functions to merge Asgardeo auth headers into existing fetch init headers. Introduces mergeAuthHeadersIntoFetchInit and exported createFetchWithMergedAuthHeaders(idToken) which returns a fetch-compatible function that preserves caller headers (e.g. Content-Type) while applying Bearer + x-user-id-token. Intended for use cases where useAuthApiClient can't be used (e.g. obtaining token via getIdToken() in useQueries).
Replace the inline fetch wrapper (and mergeApiHeaders usage) with createFetchWithMergedAuthHeaders to centralize auth header merging. Add an explicit check for a missing ID token and throw an error early. Remove the now-unused FetchFn type and mergeApiHeaders import, and tidy up related imports.
📝 WalkthroughWalkthroughThis PR refactors pagination logic in deployment/product search hooks to better handle missing Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (2 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.
Actionable comments posted: 2
🧹 Nitpick comments (2)
apps/customer-portal/webapp/src/components/project-hub/project-card/__tests__/ProjectCardInfo.test.tsx (1)
49-64: Consider adding one truncation-path test for tooltip behavior.Current coverage verifies title/fallback rendering, but not the
isTruncatedbranch inClampedTextWithTooltip. A small mocked overflow case would help prevent tooltip regressions.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/customer-portal/webapp/src/components/project-hub/project-card/__tests__/ProjectCardInfo.test.tsx` around lines 49 - 64, Add a unit test to cover the truncation branch by forcing ClampedTextWithTooltip to behave as truncated and asserting the tooltip appears; in ProjectCardInfo tests (ProjectCardInfo.test.tsx) mock or stub the ClampedTextWithTooltip component (or its isTruncated behavior) so it returns/show a tooltip when title overflows, render <ProjectCardInfo title="Long Title" /> and assert the tooltip content is present (e.g., findByRole/getByText for the tooltip text). Ensure the test targets the ClampedTextWithTooltip truncation path rather than the default render to prevent regressions in tooltip behavior.apps/customer-portal/webapp/src/components/support/case-creation-layout/form-sections/basic-information-section/__tests__/BasicInformationSection.test.tsx (1)
63-72: Test name slightly misleading: deployment selection not explicitly tested.The test name mentions "deployment selected" but doesn't pass a
deploymentvalue. The test still works becauseshowNoProductsHintdoesn't depend on deployment being set—it only checksisProductDropdownDisabled. Consider either:
- Renaming to "should show no-products hint when product list is empty"
- Or passing
deployment: "SomeDeployment"to match the test name💡 Suggested test rename
- it("should show no-products hint when product list is empty and deployment selected", () => { + it("should show no-products hint when product list is empty", () => {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/customer-portal/webapp/src/components/support/case-creation-layout/form-sections/basic-information-section/__tests__/BasicInformationSection.test.tsx` around lines 63 - 72, The test name mentions "deployment selected" but the test call to renderSection does not pass a deployment, so either rename the test to "should show no-products hint when product list is empty" or update the test to pass a deployment value (e.g., add deployment: "SomeDeployment" to the renderSection call); locate the test in BasicInformationSection.test.tsx and modify the it(...) title or the renderSection call accordingly (referencing renderSection and the showNoProductsHint behavior in the BasicInformationSection component).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/customer-portal/webapp/src/api/usePostProjectDeploymentsSearch.ts`:
- Around line 117-129: The pagination spread from the caller is currently
applied after the hook-controlled offset/limit so stale pagination can override
and freeze progress; update the calls to postDeploymentsSearchPage (used by
usePostProjectDeploymentsSearchAll and the other occurrence in the same file) to
spread request?.pagination before setting the explicit offset and limit so the
explicit offset and limit fields always override caller values, ensuring the
hook-controlled pagination advances and preventing duplicate/stuck pages.
In `@apps/customer-portal/webapp/src/pages/CreateCasePage.tsx`:
- Around line 188-193: The dropdown still gets an invalid "Unknown" option
because extraProductOptions is populated with classificationProductLabel without
the same placeholder guard used when filtering allDeploymentProducts; update the
logic that builds extraProductOptions to first compute the label via
getDeploymentProductDisplayLabel(classificationProductLabel) (or use the
existing label variable) and only push/add classificationProductLabel when
Boolean(label.trim()) && !isUnknownPlaceholderProductLabel(label) is true,
mirroring the filter in items.filter so resolveProductId() won't receive
unresolved placeholder values.
---
Nitpick comments:
In
`@apps/customer-portal/webapp/src/components/project-hub/project-card/__tests__/ProjectCardInfo.test.tsx`:
- Around line 49-64: Add a unit test to cover the truncation branch by forcing
ClampedTextWithTooltip to behave as truncated and asserting the tooltip appears;
in ProjectCardInfo tests (ProjectCardInfo.test.tsx) mock or stub the
ClampedTextWithTooltip component (or its isTruncated behavior) so it
returns/show a tooltip when title overflows, render <ProjectCardInfo title="Long
Title" /> and assert the tooltip content is present (e.g., findByRole/getByText
for the tooltip text). Ensure the test targets the ClampedTextWithTooltip
truncation path rather than the default render to prevent regressions in tooltip
behavior.
In
`@apps/customer-portal/webapp/src/components/support/case-creation-layout/form-sections/basic-information-section/__tests__/BasicInformationSection.test.tsx`:
- Around line 63-72: The test name mentions "deployment selected" but the test
call to renderSection does not pass a deployment, so either rename the test to
"should show no-products hint when product list is empty" or update the test to
pass a deployment value (e.g., add deployment: "SomeDeployment" to the
renderSection call); locate the test in BasicInformationSection.test.tsx and
modify the it(...) title or the renderSection call accordingly (referencing
renderSection and the showNoProductsHint behavior in the BasicInformationSection
component).
🪄 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: 5ecf7ae4-3ebe-44db-bd5e-6f21663cda00
📒 Files selected for processing (24)
apps/customer-portal/webapp/src/api/usePostDeploymentProductsSearch.tsapps/customer-portal/webapp/src/api/usePostProjectDeploymentsSearch.tsapps/customer-portal/webapp/src/components/common/filter-panel/FilterPopover.tsxapps/customer-portal/webapp/src/components/dashboard/cases-table/CasesFilters.tsxapps/customer-portal/webapp/src/components/project-details/project-overview/project-information/ProjectInformationCard.tsxapps/customer-portal/webapp/src/components/project-details/project-overview/project-information/__tests__/ProjectInformationCard.test.tsxapps/customer-portal/webapp/src/components/project-hub/project-card/ProjectCard.tsxapps/customer-portal/webapp/src/components/project-hub/project-card/ProjectCardInfo.tsxapps/customer-portal/webapp/src/components/project-hub/project-card/ProjectCardSkeleton.tsxapps/customer-portal/webapp/src/components/project-hub/project-card/__tests__/ProjectCard.test.tsxapps/customer-portal/webapp/src/components/project-hub/project-card/__tests__/ProjectCardInfo.test.tsxapps/customer-portal/webapp/src/components/project-hub/project-card/__tests__/ProjectCardSkeleton.test.tsxapps/customer-portal/webapp/src/components/settings/SettingsAiAssistant.tsxapps/customer-portal/webapp/src/components/support/all-cases/AllCasesFilters.tsxapps/customer-portal/webapp/src/components/support/case-creation-layout/form-sections/basic-information-section/BasicInformationSection.tsxapps/customer-portal/webapp/src/components/support/case-creation-layout/form-sections/basic-information-section/__tests__/BasicInformationSection.test.tsxapps/customer-portal/webapp/src/components/updates/all-updates/AllUpdatesTab.tsxapps/customer-portal/webapp/src/hooks/useAllDeploymentProducts.tsapps/customer-portal/webapp/src/pages/CreateCasePage.tsxapps/customer-portal/webapp/src/pages/CreateServiceRequestPage.tsxapps/customer-portal/webapp/src/pages/DescribeIssuePage.tsxapps/customer-portal/webapp/src/pages/ProjectHub.tsxapps/customer-portal/webapp/src/utils/__tests__/caseCreation.test.tsapps/customer-portal/webapp/src/utils/caseCreation.ts
💤 Files with no reviewable changes (2)
- apps/customer-portal/webapp/src/components/project-details/project-overview/project-information/ProjectInformationCard.tsx
- apps/customer-portal/webapp/src/pages/ProjectHub.tsx
Description
This pull request refactors and improves several aspects of the customer portal's project and deployment search APIs, as well as UI components for project cards and filters. The main themes are: making the pagination logic more robust and consistent, simplifying project card components by removing the description/subtitle, and fixing filter popover scroll handling. Some test and utility updates are included to support these changes.
API and Pagination Improvements:
usePostDeploymentProductsSearchandusePostProjectDeploymentsSearchto better handle edge cases where the total number of items is unknown or missing, breaking the loop on empty results or when all records are fetched. The logic now checks for both total record counts and batch sizes to decide when to stop fetching. [1] [2] [3] [4] [5] [6]buildDeployedProductSearchPayloadandcreateFetchWithMergedAuthHeadersto ensure correct request payloads and header handling for authenticated fetches. [1] [2]Project Card Component Simplification:
ProjectCard,ProjectCardInfo), its props, and associated logic, resulting in a cleaner and more focused card display. Adjusted the minimum card height accordingly. [1] [2] [3] [4] [5] [6] [7]ProjectInformationCardcomponent and its tests to remove all usage and references to the project description. [1] [2] [3] [4] [5] [6] [7]UI Consistency and Bug Fixes:
PaperPropstoMenuListPropsin filter popovers to fix infinite scroll loading. [1] [2]Test and Utility Updates:
These changes collectively improve the reliability of data fetching, simplify the UI, and address specific UI bugs.