Skip to content

[Customer Portal][FE][Web] Add Knowledge Base Recommendations API Integration and Refactor List Layout Components - #512

Merged
cloby99 merged 25 commits into
wso2-open-operations:dev-app-customer-portalfrom
dileepapeiris:knowledge-based-articles
Apr 19, 2026
Merged

cloby99 merged 25 commits into
wso2-open-operations:dev-app-customer-portalfrom
dileepapeiris:knowledge-based-articles

Conversation

@dileepapeiris

@dileepapeiris dileepapeiris commented Apr 19, 2026 •

Copy link
Copy Markdown
Contributor

Description

This pull request introduces a new API integration for Knowledge Base article recommendations in the case details view and refactors related UI components to support this feature. It also improves the layout of the ListPageHeader and ListStatGrid components for better flexibility and maintainability.

image image image

Knowledge Base Recommendations Integration

  • Added a new React Query hook useConversationRecommendationsSearch to POST chat/case context and fetch Knowledge Base article recommendations from the backend.
  • Updated the case details flow to eagerly fetch recommendations and display the count in the "Knowledge Base" tab, passing the count through to the tab label and panel. [1] [2] [3] [4] [5] [6] [7] [8]
  • Added the CONVERSATION_RECOMMENDATIONS_SEARCH query key to apiConstants.

UI Component Improvements

  • Refactored ListPageHeader to use Stack for layout instead of nested Box components, improving responsiveness and code clarity. [1] [2] [3]
  • Refactored ListStatGrid to use CSS grid instead of MUI's Grid for more flexible and maintainable layouts, with a utility for responsive column counts. [1] [2] [3] [4]

Testing

  • Updated tests to mock the new recommendations API and verify the Knowledge Base recommendations panel renders as expected. [1] [2]

Summary by CodeRabbit

Release Notes

  • New Features

    • Knowledge Base article recommendations now appear in support cases and conversations, automatically suggesting relevant articles based on case and chat history
    • Knowledge Base tab displays a count of relevant recommended articles
    • Recommendation cards show article title, relevance score, and direct view button
  • UI Improvements

    • Enhanced list page header and grid layouts for improved responsiveness and visual alignment

Add a new recommendations.ts utility module for the customer-portal support feature. Provides helpers to convert recommendation scores to percentages, build envProducts from case data, determine API roles from case comments, and construct RecommendationSearchRequest payloads from CaseDetails+comments or ConversationMessage arrays. Messages/comments are sorted chronologically, bot/"novera" authors are mapped to assistant, chat history is concatenated into conversationData, and functions return null when no usable content exists. Includes Apache-2.0 license header.
Add vitest unit tests for recommendation utilities at apps/customer-portal/webapp/src/features/support/utils/__tests__/recommendations.test.ts. Tests cover recommendationScoreToPercent (mapping 0–1 to percentages and treating values >1 as percent-like) and buildRecommendationRequestFromCase (handling undefined case data and building chat history + envProducts mapping). Ensures expected behavior for recommendation request generation.
Add an optional knowledgeBaseCount to CaseDetailsTabsProps and an onKnowledgeBaseCountChange callback to CaseDetailsTabPanelsProps. These props allow the case details UI to receive and propagate updates to the number of knowledge base items associated with a case.
Introduce TypeScript types for the customer-portal support recommendations API. Adds types for message roles, API messages, conversation data, request/response payloads, and individual recommendation items (used by POST /conversations/recommendations/search and mapped to OpenAPI models). File includes Apache-2.0 license header.
Replace the static "Knowledge Base Articles Suggested" placeholder with the ConversationKnowledgeRecommendations component. Adds an import and renders <ConversationKnowledgeRecommendations messages={messages} /> in place of the previous Paper block that displayed an Error500Page placeholder, wiring the real KB recommendations UI into the conversation details page.
Replace the locally defined KB_BASE_URL with the exported KB_ARTICLE_VIEW_BASE_URL from supportConstants and use it when opening KB articles. This centralizes the KB base URL for easier maintenance and avoids hardcoded URLs; also adjust window.open call formatting.
Introduce a new React component that displays knowledge base article recommendations for a conversation. It builds a recommendation request from conversation messages, calls the shared recommendations API via useConversationRecommendationsSearch, and renders loading, error, empty, and results states. Articles are clickable (open in a new tab) and show a relevance percent chip; utility functions and a KB base URL constant are used. Includes WSO2 license header.
Introduce CaseKnowledgeBaseRecommendations, a React component for the Support Knowledge Base tab. It fetches case comments, builds a recommendation payload, and queries conversation-driven article recommendations. The component handles loading skeletons, empty and error states, and renders recommended articles with a relevance percentage and a View Article action that opens the KB in a new tab. Props: caseId, projectId, data, onCountChange. Uses useGetCaseComments, useConversationRecommendationsSearch, buildRecommendationRequestFromCase, and recommendationScoreToPercent.
Add a new unit test for the ConversationKnowledgeRecommendations component. The test file (Vitest) mocks useConversationRecommendationsSearch to return sample recommendation data, renders the component inside QueryClientProvider and ThemeProvider, and asserts that the recommendation header, article title, and query text are present.
Add a knowledgeBaseCount prop to CaseDetailsTabs and update tab rendering to detect the "Knowledge Base" tab and append its count when provided, mirroring the existing behavior for Attachments and Calls.
Replace the static Knowledge Base placeholder with the CaseKnowledgeBaseRecommendations component. Adds import and a new onKnowledgeBaseCountChange prop, computes a resolvedProjectId fallback (data?.project?.id ?? projectId ?? ""), and passes caseId, projectId, data, and onCountChange to the recommendations component. Also updates the doc comment to reflect API-driven recommendations.
Add a vi.mock for useConversationRecommendationsSearch in CaseDetailsTabPanels tests to return an empty recommendations payload (data, isLoading: false, isError: false). Also update the test name and assertion for the Knowledge Base tab to check the new UI copy (/Knowledge base articles that may help/i) instead of the previous placeholder text.
Import case comments and recommendation hooks and build a KB recommendation payload from the case to fetch recommendations eagerly on page load. Adds useGetCaseComments, useConversationRecommendationsSearch, and buildRecommendationRequestFromCase; computes knowledgeBaseCount (guarded by hideKnowledgeBaseTab and comment-loading state) so the Knowledge Base tab can display its item count immediately. Passes knowledgeBaseCount into the child component. React Query dedupes the network call when the KB tab mounts later.
Introduce useConversationRecommendationsSearch hook to POST chat context to /conversations/recommendations/search and return KB recommendation results via react-query. The hook serializes the payload for the queryKey, validates payload and backend base URL, uses the authenticated fetch client and Asgardeo auth state, and enables the query only when signed in, not auth-loading, and the payload.chatHistory has entries. Includes debug logging, error handling for missing config or non-OK responses, and a 5-minute staleTime.
Introduce CONVERSATION_RECOMMENDATIONS_SEARCH to ApiQueryKeys in apps/customer-portal/webapp/src/constants/apiConstants.ts to standardize the query key used for conversation recommendations search (e.g. caching and query identification).
Swap the previous MUI Grid layout for a CSS Grid implemented via Box. Adds columnsFromSegment helper to convert 12-column segments into repeat(...) grid tracks and derives responsive xs/sm/md/lg/xl segment values with fallbacks. Replaces Grid container/items with a Box using gridTemplateColumns and gap (spacing), removes the Grid import and the size prop on items, and adds minWidth: 0 to item boxes. StatCard rendering and icon handling remain unchanged.
Replace nested Box layout with Oxygen UI Stack for improved responsive layout and spacing. Import Stack from @wso2/oxygen-ui, adjust the back Button styles (remove margin, use alignSelf, px/minWidth tweaks), and convert the header container to a responsive Stack with direction, spacing, justifyContent and alignItems tuned for actions presence. Also add minWidth: 0 to the title wrapper to help truncation and keep actions with flexShrink removed. Small header comment spacing added.
@dileepapeiris dileepapeiris self-assigned this Apr 19, 2026
@coderabbitai

coderabbitai Bot commented Apr 19, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Rate limit exceeded

@dileepapeiris has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 55 minutes and 27 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 55 minutes and 27 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, 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 have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d41d0edd-29ce-48ae-b78e-4a337d871dfa

📥 Commits

Reviewing files that changed from the base of the PR and between 4fbcab9 and 39d61c3.

📒 Files selected for processing (15)
  • apps/customer-portal/webapp/src/components/list-view/ListPageHeader.tsx
  • apps/customer-portal/webapp/src/components/list-view/ListStatGrid.tsx
  • apps/customer-portal/webapp/src/features/dashboard/components/cases-table/CasesList.tsx
  • apps/customer-portal/webapp/src/features/support/api/useConversationRecommendationsSearch.ts
  • apps/customer-portal/webapp/src/features/support/components/case-details/details-tab/CaseDetailsContent.tsx
  • apps/customer-portal/webapp/src/features/support/components/case-details/header/CaseDetailsTabPanels.tsx
  • apps/customer-portal/webapp/src/features/support/components/case-details/header/CaseDetailsTabs.tsx
  • apps/customer-portal/webapp/src/features/support/components/case-details/header/__tests__/CaseDetailsTabPanels.test.tsx
  • apps/customer-portal/webapp/src/features/support/components/knowledge-base/CaseKnowledgeBaseRecommendations.tsx
  • apps/customer-portal/webapp/src/features/support/components/knowledge-base/ConversationKnowledgeRecommendations.tsx
  • apps/customer-portal/webapp/src/features/support/components/knowledge-base/__tests__/ConversationKnowledgeRecommendations.test.tsx
  • apps/customer-portal/webapp/src/features/support/types/recommendations.ts
  • apps/customer-portal/webapp/src/features/support/types/supportComponents.ts
  • apps/customer-portal/webapp/src/features/support/utils/__tests__/recommendations.test.ts
  • apps/customer-portal/webapp/src/features/support/utils/recommendations.ts
📝 Walkthrough

Walkthrough

Introduces knowledge base recommendation functionality to the customer portal by adding an API hook to fetch recommendations based on chat history, creating UI components to display recommendations in case details and conversations, developing utility functions to build recommendation payloads, and refactoring layout components for improved responsive design.

Changes

Cohort / File(s) Summary
Type Definitions & Constants
constants/apiConstants.ts, types/recommendations.ts, constants/supportConstants.ts
Added new recommendation query key constant, exported KB article view base URL, and defined six new TypeScript types for recommendation request/response structures.
API Hook
features/support/api/useConversationRecommendationsSearch.ts
Created new React Query hook that fetches KB article recommendations from /conversations/recommendations/search endpoint, with conditional execution based on payload availability and authentication state.
Recommendation Utilities
features/support/utils/recommendations.ts, features/support/utils/__tests__/recommendations.test.ts
Implemented four utility functions to build recommendation API payloads from case details and conversation messages, convert scores to percentages, derive product/environment metadata, and infer message roles from comment metadata; added corresponding test coverage.
Knowledge Base Components
features/support/components/knowledge-base/CaseKnowledgeBaseRecommendations.tsx, features/support/components/knowledge-base/ConversationKnowledgeRecommendations.tsx, features/support/components/knowledge-base/__tests__/ConversationKnowledgeRecommendations.test.tsx
Added two new React components to render KB recommendation lists for case and conversation contexts, displaying article titles, relevance scores, and clickable cards with loading, error, and empty states; included test for conversation component.
Case Details Integration
features/support/components/case-details/details-tab/CaseDetailsContent.tsx, features/support/components/case-details/header/CaseDetailsTabPanels.tsx, features/support/components/case-details/header/CaseDetailsTabs.tsx, types/supportComponents.ts, features/support/components/case-details/header/__tests__/CaseDetailsTabPanels.test.tsx
Wired KB recommendation fetching and display into case details flow: prefetch recommendations in content tab, render panel in tab structure, append count to tab label, updated prop signatures, and updated test expectations for KB tab rendering.
Page & Chat Updates
features/support/pages/ConversationDetailsPage.tsx, features/support/components/novera-ai-assistant/novera-chat-page/RecommendationsCard.tsx
Replaced hardcoded KB placeholder in conversation page with ConversationKnowledgeRecommendations component; unified KB article URL construction in RecommendationsCard to use shared constant.
Layout Refactoring
components/list-view/ListPageHeader.tsx, components/list-view/ListStatGrid.tsx
Refactored outer layout container from Box to Stack with improved spacing and alignment; replaced Grid with CSS grid Box layout with responsive column configuration and proper sizing constraints.

Sequence Diagram(s)

sequenceDiagram
    participant CaseDetailsContent
    participant useGetCaseComments
    participant buildRecommendationRequestFromCase
    participant useConversationRecommendationsSearch
    participant RecommendationAPI as /conversations/recommendations/search
    participant CaseDetailsTabs

    CaseDetailsContent->>useGetCaseComments: fetch(projectId, caseId)
    useGetCaseComments-->>CaseDetailsContent: comments loaded
    CaseDetailsContent->>buildRecommendationRequestFromCase: build payload from case + comments
    buildRecommendationRequestFromCase-->>CaseDetailsContent: RecommendationSearchRequest
    CaseDetailsContent->>useConversationRecommendationsSearch: call with payload + enabled flag
    useConversationRecommendationsSearch->>RecommendationAPI: POST /conversations/recommendations/search
    RecommendationAPI-->>useConversationRecommendationsSearch: RecommendationSearchResponse
    useConversationRecommendationsSearch-->>CaseDetailsContent: recommendations + metadata
    CaseDetailsContent->>CaseDetailsTabs: pass knowledgeBaseCount prop
    CaseDetailsTabs-->>CaseDetailsContent: render with count in tab label
Loading
sequenceDiagram
    participant ConversationDetailsPage
    participant buildRecommendationRequestFromConversationMessages
    participant useConversationRecommendationsSearch
    participant RecommendationAPI as /conversations/recommendations/search
    participant ConversationKnowledgeRecommendations

    ConversationDetailsPage->>buildRecommendationRequestFromConversationMessages: build from messages
    buildRecommendationRequestFromConversationMessages-->>ConversationDetailsPage: RecommendationSearchRequest
    ConversationDetailsPage->>useConversationRecommendationsSearch: fetch recommendations
    useConversationRecommendationsSearch->>RecommendationAPI: POST with message history
    RecommendationAPI-->>useConversationRecommendationsSearch: articles + query summary
    useConversationRecommendationsSearch-->>ConversationDetailsPage: recommendations data
    ConversationDetailsPage->>ConversationKnowledgeRecommendations: render with results
    ConversationKnowledgeRecommendations-->>ConversationDetailsPage: clickable KB articles
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

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

Suggested reviewers

  • Rashmika998
  • cloby99
  • sacheeramesh

Poem

🐰 A knowledge base gleams, bright and true,
Recommendations flow like morning dew,
From case to chat, the articles shine,
With relevance scores and links so fine—
Now seekers find answers in no time! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The description provides a comprehensive overview with clear sections on KB recommendations integration, UI improvements, and testing, but lacks critical template sections like Purpose, Goals, Release Notes, Documentation, and other standard metadata.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Title check ✅ Passed The title clearly and comprehensively summarizes the two main changes: adding KB recommendations API integration and refactoring list layout components.

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

@dileepapeiris dileepapeiris added Type/New Feature Represents a request or task for a new feature Type/Improvement Marks enhancements or improvements to existing features Type/Task General task that does not fit into other categories Type/UX Refers to user experience-related tasks or issues App/Customer Portal Area/Frontend Platform/Web labels Apr 19, 2026

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

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

313-313: Consider gating on load/error state of messages.

ConversationKnowledgeRecommendations is rendered unconditionally — even when isLoading or isError is true for the conversation fetch, it will build a payload from whatever messages is (possibly empty) and display its own skeleton/empty state. This means on error the page shows a red error box AND the KB section attempts to fetch against an empty payload. Consider only rendering it in the success branch (after messages.length > 0 or at least !isError).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/customer-portal/webapp/src/features/support/pages/ConversationDetailsPage.tsx`
at line 313, ConversationKnowledgeRecommendations is being rendered
unconditionally and can trigger requests with an empty payload when the
conversation fetch is loading or errored; update the render logic in
ConversationDetailsPage to only render <ConversationKnowledgeRecommendations
messages={messages} /> when the conversation fetch is successful (e.g.,
!isLoading && !isError) and preferably when messages.length > 0 so the KB
component receives a valid payload and won’t fetch on empty/error states.
apps/customer-portal/webapp/src/features/support/components/case-details/header/CaseDetailsTabPanels.tsx (1)

109-119: Count propagation is disconnected.

onKnowledgeBaseCountChange is plumbed through to CaseKnowledgeBaseRecommendations.onCountChange, but CaseDetailsContent.tsx never passes onKnowledgeBaseCountChange to CaseDetailsTabPanels — the count shown in the tab label comes entirely from the parent's own useConversationRecommendationsSearch call. Either remove this prop (dead plumbing) or wire it through and drop the parent-side fetch to avoid duplicated responsibility.

Also, resolvedProjectId can still be "" here when data?.project?.id is unavailable; CaseKnowledgeBaseRecommendations will then call useGetCaseComments("", caseId) — please confirm that's gracefully disabled inside the hook.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/customer-portal/webapp/src/features/support/components/case-details/header/CaseDetailsTabPanels.tsx`
around lines 109 - 119, The prop onKnowledgeBaseCountChange passed into
CaseKnowledgeBaseRecommendations from CaseDetailsTabPanels is dead — either
remove the prop plumbing and the onKnowledgeBaseCountChange usage in
CaseDetailsTabPanels and rely on the parent's
useConversationRecommendationsSearch, or wire the callback end-to-end: have
CaseDetailsContent.tsx accept and forward onKnowledgeBaseCountChange into
CaseDetailsTabPanels, then drop the parent-side
useConversationRecommendationsSearch fetch to avoid duplicated responsibilities;
also prevent passing an empty projectId into CaseKnowledgeBaseRecommendations by
ensuring resolvedProjectId is undefined/null (not "") or guard inside
CaseKnowledgeBaseRecommendations/useGetCaseComments so
useGetCaseComments(projectId, caseId) is a no-op when projectId is falsy (check
useGetCaseComments for an early return when projectId is empty).
apps/customer-portal/webapp/src/features/support/components/knowledge-base/CaseKnowledgeBaseRecommendations.tsx (2)

68-73: useMemo has a fresh dependency every render.

commentsData?.comments ?? [] returns a new [] array on every render when the data is absent, so comments is a fresh reference and the useMemo for payload recomputes each render. If useConversationRecommendationsSearch derives its React Query key from payload by reference, this may cause unstable keys.

Proposed fix
-  const comments = commentsData?.comments ?? [];
-
   const payload = useMemo(
-    () => buildRecommendationRequestFromCase(data, comments),
-    [data, comments],
+    () => buildRecommendationRequestFromCase(data, commentsData?.comments ?? []),
+    [data, commentsData],
   );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/customer-portal/webapp/src/features/support/components/knowledge-base/CaseKnowledgeBaseRecommendations.tsx`
around lines 68 - 73, The current comments variable gets a fresh [] each render
when commentsData is absent, causing payload (built by
buildRecommendationRequestFromCase) to recompute; change comments to a stable
memoized value e.g. replace const comments = commentsData?.comments ?? [] with
const comments = useMemo(() => commentsData?.comments ?? [],
[commentsData?.comments]) so payload’s useMemo([data, comments]) sees a stable
reference and avoids unstable keys for useConversationRecommendationsSearch.

92-96: onCountChange is not reference-stable in the effect deps.

If callers pass an inline arrow for onCountChange (which CaseDetailsTabPanels / CaseDetailsContent would do if wired), this effect runs on every render even when items.length is unchanged — causing redundant state updates in the parent. Either memoize the callback at call sites or compare against a previously-reported count ref before invoking.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/customer-portal/webapp/src/features/support/components/knowledge-base/CaseKnowledgeBaseRecommendations.tsx`
around lines 92 - 96, The effect in CaseKnowledgeBaseRecommendations calls
onCountChange directly and includes it in deps, causing runs when callers pass
unstable callbacks; modify the effect to remove onCountChange from the
dependency requirement by keeping a local ref (e.g., lastReportedCountRef) that
stores the last items.length reported and only call onCountChange(items.length)
when recData is present and items.length !== lastReportedCountRef.current, then
update the ref; keep other deps (isLoading, isError, recData, items.length) so
the effect fires correctly but avoid invoking the parent callback on every
render when it is not actually changed.
🤖 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/components/list-view/ListStatGrid.tsx`:
- Around line 46-48: columnsFromSegment currently divides 12 by segment and
returns a repeat(n, ...) string which breaks for non-divisors; instead make the
container use a fixed 12-column template (e.g. "repeat(12, minmax(0, 1fr))") and
compute integer column spans per segment for items. Modify columnsFromSegment to
return the fixed 12-column template and add a helper (e.g.
columnSpanFromSegment(segment)) that computes span = clamp(1, round(12/segment),
12). Then update callers (the grid container usage and item sx in
EngagementsStatCards and SecurityStats) to set gridTemplateColumns to the fixed
12-column string and set each item’s gridColumn to responsive spans using
cascading breakpoints (xs: `span ${spanXs}`, sm: `span ${spanSm ?? spanXs}`, md:
`span ${spanMd ?? spanSm ?? spanXs}`) so breakpoint values cascade like MUI
Grid.

In
`@apps/customer-portal/webapp/src/features/support/api/useConversationRecommendationsSearch.ts`:
- Around line 43-50: The query key currently embeds full payload via the
variable `serialized` in `useConversationRecommendationsSearch` (used in the
`queryKey` with `ApiQueryKeys.CONVERSATION_RECOMMENDATIONS_SEARCH`), which leaks
chat content to React Query metadata; change the key to a sanitized identifier
set (e.g., `conversationId`, message count, latest message timestamp or other
minimal filters) derived from `payload` instead of JSON.stringify(payload).
Update the `queryKey` construction to use those minimal fields and mirror the
same change pattern found in `useSearchConversations.ts` (remove embedding of
full request object, use only necessary filter IDs) so cache keys no longer
contain raw conversation text.

In
`@apps/customer-portal/webapp/src/features/support/components/case-details/header/__tests__/CaseDetailsTabPanels.test.tsx`:
- Around line 239-244: The test expecting "Knowledge base articles that may
help" is incorrect because with the mock returning recommendations: [] the
CaseKnowledgeBaseRecommendations component renders the empty-state message;
update the test in CaseDetailsTabPanels.test.tsx (the it block using
renderTabPanels(4)) to assert that the empty-state text "No matching knowledge
base articles were found for this case." is in the document, or alternatively
change the test fixture/mock that provides recommendations to include at least
one item and then assert the existing heading; reference renderTabPanels and
CaseKnowledgeBaseRecommendations when making the change.

In
`@apps/customer-portal/webapp/src/features/support/components/knowledge-base/ConversationKnowledgeRecommendations.tsx`:
- Around line 118-170: The Paper wrapper's click and keyboard accessibility need
fixes: update the Button's onClick handler in
ConversationKnowledgeRecommendations (where Button currently calls
openArticle(item.articleId)) to accept the event and call e.stopPropagation()
before invoking openArticle(item.articleId) to prevent the Paper's onClick from
firing twice; additionally add keyboard affordances to the Paper component (set
role="button", tabIndex={0}, and an onKeyDown handler that calls
openArticle(item.articleId) when Enter or Space is pressed) so the Paper is
keyboard-accessible. Ensure you modify the Paper and Button instances in
ConversationKnowledgeRecommendations.tsx and reuse the same openArticle
function.

In `@apps/customer-portal/webapp/src/features/support/utils/recommendations.ts`:
- Around line 105-178: The code uses new Date().toISOString() as a fallback
timestamp which changes each render; make a deterministic fallback instead:
compute a stableFallback timestamp (for example the earliest existing createdOn
found in the input or a fixed constant like "1970-01-01T00:00:00Z") and replace
occurrences of new Date().toISOString() used as fallbacks (e.g., the createdOn
assignment at the top of the case builder and the timestamp fallback in
buildRecommendationRequestFromConversationMessages where you use m.createdOn ??
new Date().toISOString()) to use stableFallback so identical inputs produce
identical request bodies and cache keys.

---

Nitpick comments:
In
`@apps/customer-portal/webapp/src/features/support/components/case-details/header/CaseDetailsTabPanels.tsx`:
- Around line 109-119: The prop onKnowledgeBaseCountChange passed into
CaseKnowledgeBaseRecommendations from CaseDetailsTabPanels is dead — either
remove the prop plumbing and the onKnowledgeBaseCountChange usage in
CaseDetailsTabPanels and rely on the parent's
useConversationRecommendationsSearch, or wire the callback end-to-end: have
CaseDetailsContent.tsx accept and forward onKnowledgeBaseCountChange into
CaseDetailsTabPanels, then drop the parent-side
useConversationRecommendationsSearch fetch to avoid duplicated responsibilities;
also prevent passing an empty projectId into CaseKnowledgeBaseRecommendations by
ensuring resolvedProjectId is undefined/null (not "") or guard inside
CaseKnowledgeBaseRecommendations/useGetCaseComments so
useGetCaseComments(projectId, caseId) is a no-op when projectId is falsy (check
useGetCaseComments for an early return when projectId is empty).

In
`@apps/customer-portal/webapp/src/features/support/components/knowledge-base/CaseKnowledgeBaseRecommendations.tsx`:
- Around line 68-73: The current comments variable gets a fresh [] each render
when commentsData is absent, causing payload (built by
buildRecommendationRequestFromCase) to recompute; change comments to a stable
memoized value e.g. replace const comments = commentsData?.comments ?? [] with
const comments = useMemo(() => commentsData?.comments ?? [],
[commentsData?.comments]) so payload’s useMemo([data, comments]) sees a stable
reference and avoids unstable keys for useConversationRecommendationsSearch.
- Around line 92-96: The effect in CaseKnowledgeBaseRecommendations calls
onCountChange directly and includes it in deps, causing runs when callers pass
unstable callbacks; modify the effect to remove onCountChange from the
dependency requirement by keeping a local ref (e.g., lastReportedCountRef) that
stores the last items.length reported and only call onCountChange(items.length)
when recData is present and items.length !== lastReportedCountRef.current, then
update the ref; keep other deps (isLoading, isError, recData, items.length) so
the effect fires correctly but avoid invoking the parent callback on every
render when it is not actually changed.

In
`@apps/customer-portal/webapp/src/features/support/pages/ConversationDetailsPage.tsx`:
- Line 313: ConversationKnowledgeRecommendations is being rendered
unconditionally and can trigger requests with an empty payload when the
conversation fetch is loading or errored; update the render logic in
ConversationDetailsPage to only render <ConversationKnowledgeRecommendations
messages={messages} /> when the conversation fetch is successful (e.g.,
!isLoading && !isError) and preferably when messages.length > 0 so the KB
component receives a valid payload and won’t fetch on empty/error states.
🪄 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: 960148d5-59ba-4c23-bc85-c6aec6d4086d

📥 Commits

Reviewing files that changed from the base of the PR and between 32289d9 and 4fbcab9.

📒 Files selected for processing (18)
  • apps/customer-portal/webapp/src/components/list-view/ListPageHeader.tsx
  • apps/customer-portal/webapp/src/components/list-view/ListStatGrid.tsx
  • apps/customer-portal/webapp/src/constants/apiConstants.ts
  • apps/customer-portal/webapp/src/features/support/api/useConversationRecommendationsSearch.ts
  • apps/customer-portal/webapp/src/features/support/components/case-details/details-tab/CaseDetailsContent.tsx
  • apps/customer-portal/webapp/src/features/support/components/case-details/header/CaseDetailsTabPanels.tsx
  • apps/customer-portal/webapp/src/features/support/components/case-details/header/CaseDetailsTabs.tsx
  • apps/customer-portal/webapp/src/features/support/components/case-details/header/__tests__/CaseDetailsTabPanels.test.tsx
  • apps/customer-portal/webapp/src/features/support/components/knowledge-base/CaseKnowledgeBaseRecommendations.tsx
  • apps/customer-portal/webapp/src/features/support/components/knowledge-base/ConversationKnowledgeRecommendations.tsx
  • apps/customer-portal/webapp/src/features/support/components/knowledge-base/__tests__/ConversationKnowledgeRecommendations.test.tsx
  • apps/customer-portal/webapp/src/features/support/components/novera-ai-assistant/novera-chat-page/RecommendationsCard.tsx
  • apps/customer-portal/webapp/src/features/support/constants/supportConstants.ts
  • apps/customer-portal/webapp/src/features/support/pages/ConversationDetailsPage.tsx
  • apps/customer-portal/webapp/src/features/support/types/recommendations.ts
  • apps/customer-portal/webapp/src/features/support/types/supportComponents.ts
  • apps/customer-portal/webapp/src/features/support/utils/__tests__/recommendations.test.ts
  • apps/customer-portal/webapp/src/features/support/utils/recommendations.ts

Comment thread apps/customer-portal/webapp/src/features/support/utils/recommendations.ts Outdated
@dileepapeiris dileepapeiris changed the title Knowledge based articles [Customer Portal][FE][Web] Add Knowledge Base Recommendations API Integration and Refactor List Layout Components Apr 19, 2026
Replace runtime-generated timestamps with a fixed epoch string for missing createdOn fields in recommendations utilities. This makes outputs deterministic and avoids using the current time. Updated buildRecommendationRequestFromCase and buildRecommendationRequestFromConversationMessages to use "1970-01-01T00:00:00Z" instead of new Date().toISOString().
Make knowledge-base recommendation items keyboard-accessible by adding role="button", tabIndex, and an onKeyDown handler to open articles on Enter/Space. Prevent double-handling when clicking the external link by stopping propagation on the button's onClick. Also remove the now-unused onKnowledgeBaseCountChange prop from CaseDetailsTabPanelsProps to clean up types.
UI: Constrain the Details column in CasesList (maxWidth 320) and enable text truncation (overflow/ellipsis, white-space nowrap) with minWidth:0 on the container so long titles don't overflow. API: Replace JSON serialization in useConversationRecommendationsSearch query key with lightweight values (message count, first and last timestamps) to produce a more stable and efficient cache key for react-query.
Drop the knowledge-base result count callback from the case details tab and the CaseKnowledgeBaseRecommendations component. Memoize fetched comments to avoid recalculating arrays on each render and remove the effect that reported recommendation counts. Update the tab panel to stop passing the removed prop and adjust the test expectation to the new empty-state message.

Files changed:
- CaseDetailsTabPanels.tsx: remove onKnowledgeBaseCountChange prop and its propagation.
- CaseKnowledgeBaseRecommendations.tsx: remove onCountChange prop and related useEffect, memoize comments, clean up imports.
- CaseDetailsTabPanels.test.tsx: update assertion to match the new empty-state text.
Add a loading state for the Knowledge Base tab count to show a Skeleton while recommendations/comments are being fetched. Compute knowledgeBaseCountLoading in CaseDetailsContent and pass it to CaseDetailsTabs; render a Skeleton in the tab label when loading. Also update the props type (knowledgeBaseCountLoading?) and import ReactNode and Skeleton in CaseDetailsTabs.
Comment thread apps/customer-portal/webapp/src/components/list-view/ListPageHeader.tsx Outdated
Remove an extra '//' blank comment line from the top of apps/customer-portal/webapp/src/components/list-view/ListPageHeader.tsx to tidy the Apache license header.
Apply code formatting and reflow across the knowledge-base recommendation feature. Changes include removing stray license comment lines, reflowing JSX and props to multiple lines for readability, expanding destructured assignments, and making small test formatting tweaks in ConversationKnowledgeRecommendations.test.tsx. No functional behavior changes were made.
Comment thread apps/customer-portal/webapp/src/components/list-view/ListStatGrid.tsx Outdated
Remove an extra stray '//' blank comment line from the license header in ListStatGrid.tsx to tidy the file and ensure consistent header formatting.
@cloby99
cloby99 merged commit ee4451b into wso2-open-operations:dev-app-customer-portal Apr 19, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

App/Customer Portal Area/Frontend Platform/Web Type/Improvement Marks enhancements or improvements to existing features Type/New Feature Represents a request or task for a new feature Type/Task General task that does not fit into other categories Type/UX Refers to user experience-related tasks or issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants