Skip to content

[Customer Portal][Web] Improve Novera Chat UX with Conversation History & Article Recommendations - #292

Merged
Rashmika998 merged 5 commits into
wso2-open-operations:customer-portal-milestone-1from
dileepapeiris:feat/add-kb-articles-view
Mar 3, 2026
Merged

Rashmika998 merged 5 commits into
wso2-open-operations:customer-portal-milestone-1from
dileepapeiris:feat/add-kb-articles-view

Conversation

@dileepapeiris

@dileepapeiris dileepapeiris commented Mar 2, 2026 •

Copy link
Copy Markdown
Contributor

Description

This pull request introduces several enhancements to the Novera AI chat experience in the customer portal, focusing on improved conversation history handling, article recommendations, and user interface improvements. The main changes include support for resuming chat conversations via URL, displaying knowledge base article recommendations in chat, and adding a loading skeleton for chat messages.

image image

Conversation history and navigation improvements:

  • Added support for resuming chat conversations via a URL parameter (:conversationId), enabling users to revisit or share specific chat sessions. The chat page now loads and displays previous messages for the given conversation. (apps/customer-portal/webapp/src/App.tsx [1] apps/customer-portal/webapp/src/pages/NoveraChatPage.tsx [2] [3] [4] [5] [6] [7]
  • Updated navigation logic so that resuming a chat from the chat history list directs users to the chat page with the correct conversation ID in the URL. (apps/customer-portal/webapp/src/pages/SupportPage.tsx [1] [2] apps/customer-portal/webapp/src/components/support/support-overview-cards/ChatHistoryList.tsx [3]

Chat UI and user experience enhancements:

  • Introduced a ChatSkeleton component to display loading skeletons while chat history is being fetched, providing a smoother user experience during data loads. (apps/customer-portal/webapp/src/components/support/novera-ai-assistant/novera-chat-page/ChatSkeleton.tsx [1] apps/customer-portal/webapp/src/pages/NoveraChatPage.tsx [2] [3]
  • Minor UI tweak to adjust the alignment of status chips in the chat history list. (apps/customer-portal/webapp/src/components/support/support-overview-cards/ChatHistoryList.tsx apps/customer-portal/webapp/src/components/support/support-overview-cards/ChatHistoryList.tsxR171)

Knowledge base recommendations:

  • Added a RecommendationsCard component that displays knowledge base article recommendations under bot messages when available, enhancing the value of AI responses. (apps/customer-portal/webapp/src/components/support/novera-ai-assistant/novera-chat-page/RecommendationsCard.tsx [1] apps/customer-portal/webapp/src/components/support/novera-ai-assistant/novera-chat-page/ChatMessageBubble.tsx [2] [3] apps/customer-portal/webapp/src/pages/NoveraChatPage.tsx [4] [5] [6]

API and type updates:

  • Integrated the useGetConversationMessages hook to fetch conversation history and updated the Message and Recommendation types to support new features. (apps/customer-portal/webapp/src/pages/NoveraChatPage.tsx [1] [2] [3]

Other:

Summary by CodeRabbit

  • New Features

    • AI assistant now shows up to four knowledge-base article recommendations in chat; items open in a new tab.
    • Chat supports direct conversation links (conversationId) so users can resume specific conversations via URL.
    • Loading skeleton introduced for resumed chats to indicate history is being restored.
  • UX Improvements

    • Chat history items consistently trigger a view action when selected.
    • Conversation statuses gain clearer color and icon visuals throughout the UI.

Introduce a Recommendation interface (title, articleId, score) and add an optional recommendations field to the Message type. Wire conversationResponse.recommendations?.recommendations into newly created Message objects so recommendation data from the backend is preserved in the chat message model for rendering in the UI.
Introduce a new RecommendationsCard React component to display knowledge base article recommendations from the Novera AI agent. The component (apps/customer-portal/webapp/src/components/support/novera-ai-assistant/novera-chat-page/RecommendationsCard.tsx) accepts a recommendations array, renders up to four clickable cards, and opens the corresponding KB article in a new tab via KB_BASE_URL. Uses WSO2 Oxygen UI components and icons, applies themed styling and hover effects, and returns an empty fragment when no recommendations are provided.
Import RecommendationsCard and conditionally render it for non-user messages that include recommendations. Adds a block that displays message.recommendations via RecommendationsCard (when length > 0), so suggested recommendations appear below the message content.
@coderabbitai

coderabbitai Bot commented Mar 2, 2026 •

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Adds UI and data flow for knowledge-base article recommendations in the Novera AI chat: new RecommendationsCard component, rendering of recommendations in ChatMessageBubble, propagation of a Recommendation type and recommendations[] on Message in NoveraChatPage, plus related routing, skeleton, and chat-status helper changes.

Changes

Cohort / File(s) Summary
Recommendations UI
apps/customer-portal/webapp/src/components/support/novera-ai-assistant/novera-chat-page/RecommendationsCard.tsx
New component rendering up to four clickable KB article cards (opens in new tab), themed orange, uses Oxygen UI layout and icons.
Chat message rendering & message model
apps/customer-portal/webapp/src/components/support/novera-ai-assistant/novera-chat-page/ChatMessageBubble.tsx, apps/customer-portal/webapp/src/pages/NoveraChatPage.tsx
ChatMessageBubble imports and conditionally renders RecommendationsCard for bot messages with recommendations. NoveraChatPage adds Recommendation type and optional recommendations?: Recommendation[] on Message, and maps API responses into this field.
Routing & loading UX
apps/customer-portal/webapp/src/App.tsx, apps/customer-portal/webapp/src/components/support/novera-ai-assistant/novera-chat-page/ChatSkeleton.tsx
Adds dynamic route /:conversationId for NoveraChatPage and introduces ChatSkeleton component used while resuming/loading conversation history.
Chat history & support behavior
apps/customer-portal/webapp/src/components/support/support-overview-cards/ChatHistoryList.tsx, apps/customer-portal/webapp/src/pages/SupportPage.tsx
Changed chat item click behavior to always call onItemAction(..., ChatAction.VIEW) and updated SupportPage to handle a two-argument onItemAction(chatId, action) for resume vs view navigation. Minor UI tweak to status Chip margin.
Helpers / status visuals
apps/customer-portal/webapp/src/utils/support.ts
Added getConversationStatusColor and getConversationStatusIcon, updated getChatStatusAction logic to treat resolved-like statuses as VIEW, and set resume action color to warning.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant Frontend as NoveraChatPage
  participant Backend as ConversationAPI
  participant KB as KnowledgeBase

  User->>Frontend: Send message / resume conversation
  Frontend->>Backend: fetch conversation messages / send user message
  Backend-->>Frontend: bot message with recommendations[]
  Frontend->>Frontend: map API response -> Message(recommendations)
  Frontend->>Frontend: render ChatMessageBubble for bot
  Frontend->>Frontend: render RecommendationsCard (cards with links)
  User->>KB: click recommendation (opens new tab to KB article)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • Rashmika998
  • sacheeramesh
  • shayanmalinda

Poem

🐰 In chat the knowledge cards hop into view,
Four bright links in orange, fresh as dew,
Bot whispers suggestions, the rabbit grins wide,
Click and a new tab takes you for a ride,
Hooray — recommendations bundled with pride! 🥕📚

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description includes implementation details, screenshots, and file references, but lacks critical sections required by the repository template such as Purpose, Goals, Approach, User stories, Release note, Documentation, Training, Certification, Marketing, Automation tests, Security checks, Samples, Related PRs, Migrations, Test environment, and Learning. Add missing sections from the description template: Purpose (with issue links), Goals, Approach (with UI documentation), User stories, Release note, Documentation links, Training, Certification, Marketing, test coverage details, Security checks (secure coding, FindSecurityBugs, secrets verification), Samples, Related PRs, Migrations, Test environment specifications, and Learning/research phase.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Feat/add kb articles view' is specific and directly related to the main feature—adding knowledge base article recommendations to the chat interface as shown in the PR description images.
Docstring Coverage ✅ Passed Docstring coverage is 90.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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 self-assigned this Mar 2, 2026
@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 Mar 2, 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: 1

🧹 Nitpick comments (1)
apps/customer-portal/webapp/src/components/support/novera-ai-assistant/novera-chat-page/RecommendationsCard.tsx (1)

49-51: Encode the articleId to prevent URL issues with special characters.

If articleId contains characters like spaces, &, ?, or #, the URL could break or behave unexpectedly. Use encodeURIComponent for safety.

🛡️ Proposed fix
 const handleArticleClick = (articleId: string) => {
-  window.open(`${KB_BASE_URL}${articleId}`, "_blank", "noopener,noreferrer");
+  window.open(`${KB_BASE_URL}${encodeURIComponent(articleId)}`, "_blank", "noopener,noreferrer");
 };
🤖 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/novera-ai-assistant/novera-chat-page/RecommendationsCard.tsx`
around lines 49 - 51, The handleArticleClick function should URL-encode the
articleId before concatenating with KB_BASE_URL to avoid broken URLs from
special characters; update handleArticleClick to call
encodeURIComponent(articleId) (keeping window.open with target "_blank" and
"noopener,noreferrer") so the final URL is
`${KB_BASE_URL}${encodeURIComponent(articleId)}`.
🤖 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/support/novera-ai-assistant/novera-chat-page/RecommendationsCard.tsx`:
- Around line 80-95: The Card elements rendered in RecommendationsCard are
clickable via onClick but missing keyboard accessibility; update the Card (the
Card element that uses key={rec.articleId || index} and onClick={() =>
handleArticleClick(rec.articleId)}) to either use an accessible Link or add
role="button", tabIndex={0}, and an onKeyDown handler that calls
handleArticleClick(rec.articleId) when Enter or Space is pressed; ensure the
same visual focus styles are preserved and do not remove the existing onClick
handler so both mouse and keyboard activate the same action.

---

Nitpick comments:
In
`@apps/customer-portal/webapp/src/components/support/novera-ai-assistant/novera-chat-page/RecommendationsCard.tsx`:
- Around line 49-51: The handleArticleClick function should URL-encode the
articleId before concatenating with KB_BASE_URL to avoid broken URLs from
special characters; update handleArticleClick to call
encodeURIComponent(articleId) (keeping window.open with target "_blank" and
"noopener,noreferrer") so the final URL is
`${KB_BASE_URL}${encodeURIComponent(articleId)}`.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0d7d8ec and d5b29d4.

📒 Files selected for processing (3)
  • apps/customer-portal/webapp/src/components/support/novera-ai-assistant/novera-chat-page/ChatMessageBubble.tsx
  • apps/customer-portal/webapp/src/components/support/novera-ai-assistant/novera-chat-page/RecommendationsCard.tsx
  • apps/customer-portal/webapp/src/pages/NoveraChatPage.tsx

Load and resume conversations from URL in NoveraChatPage, show skeleton while history loads, and persist conversationId to the URL. Changes include importing useGetConversationMessages and ChatSkeleton, initializing messages empty when resuming, converting loaded history into Message items, and guarding send/input while history is loading. SupportPage onItemAction now accepts an action and routes to the chat resume path for resume actions (otherwise routes to conversation details). utils/support.ts: adjust chat action logic/colors and add getConversationStatusColor and getConversationStatusIcon helpers (with new icon imports) to map ConversationStatus to palette colors and icons.
Introduce a new ChatSkeleton component to show loading placeholders for the chat UI. Add a dynamic route (":conversationId") that renders NoveraChatPage so individual conversation URLs open correctly. Update ChatHistoryList to always trigger ChatAction.VIEW on item click (ensuring consistent behavior) and apply a small chip label spacing tweak (marginTop: -1px) for visual alignment.
@dileepapeiris dileepapeiris changed the title Feat/add kb articles view [Customer Portal][Web] Improve Novera Chat UX with Conversation History & Article Recommendations Mar 3, 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.

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

198-207: Use ChatAction.RESUME constant instead of string literal.

The comparison uses the string literal "resume" while the codebase defines ChatAction.RESUME constant in supportConstants.ts. Using the constant improves type safety and consistency.

♻️ Suggested refactor
+import { ChatAction } from "@constants/supportConstants";

Then update the comparison:

-                      if (action === "resume") {
+                      if (action === ChatAction.RESUME) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/customer-portal/webapp/src/pages/SupportPage.tsx` around lines 198 -
207, Replace the string literal "resume" used in the action comparison with the
ChatAction.RESUME constant from supportConstants.ts: update the conditional that
checks action (the one that chooses between
navigate(`/${projectId}/support/chat/${chatId}`) and
navigate(`/${projectId}/support/conversations/${chatId}`, { state: {
conversationSummary: summary } })) to compare against ChatAction.RESUME instead
of "resume" to ensure type safety and consistency.
apps/customer-portal/webapp/src/pages/NoveraChatPage.tsx (1)

49-53: Consider co-locating or sharing the Recommendation type.

The Recommendation interface is exported here but appears to originate from API responses. Consider moving it to a shared types/models location (e.g., @models/responses) for better discoverability and reuse across components.

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

In `@apps/customer-portal/webapp/src/pages/NoveraChatPage.tsx` around lines 49 -
53, The Recommendation interface should be moved out of NoveraChatPage and into
a shared model so it can be reused: create or add to a shared types module
(e.g., `@models/responses`) an exported Recommendation type (matching the current
fields title, articleId, score), replace the local export in NoveraChatPage.tsx
with an import from that shared module, and update any other files that
currently import or declare Recommendation to import it from the new shared
location; ensure named export/imports remain consistent and run the
build/type-check to catch any import path fixes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@apps/customer-portal/webapp/src/pages/NoveraChatPage.tsx`:
- Around line 49-53: The Recommendation interface should be moved out of
NoveraChatPage and into a shared model so it can be reused: create or add to a
shared types module (e.g., `@models/responses`) an exported Recommendation type
(matching the current fields title, articleId, score), replace the local export
in NoveraChatPage.tsx with an import from that shared module, and update any
other files that currently import or declare Recommendation to import it from
the new shared location; ensure named export/imports remain consistent and run
the build/type-check to catch any import path fixes.

In `@apps/customer-portal/webapp/src/pages/SupportPage.tsx`:
- Around line 198-207: Replace the string literal "resume" used in the action
comparison with the ChatAction.RESUME constant from supportConstants.ts: update
the conditional that checks action (the one that chooses between
navigate(`/${projectId}/support/chat/${chatId}`) and
navigate(`/${projectId}/support/conversations/${chatId}`, { state: {
conversationSummary: summary } })) to compare against ChatAction.RESUME instead
of "resume" to ensure type safety and consistency.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d5b29d4 and 0e2ce47.

📒 Files selected for processing (6)
  • apps/customer-portal/webapp/src/App.tsx
  • apps/customer-portal/webapp/src/components/support/novera-ai-assistant/novera-chat-page/ChatSkeleton.tsx
  • apps/customer-portal/webapp/src/components/support/support-overview-cards/ChatHistoryList.tsx
  • apps/customer-portal/webapp/src/pages/NoveraChatPage.tsx
  • apps/customer-portal/webapp/src/pages/SupportPage.tsx
  • apps/customer-portal/webapp/src/utils/support.ts

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