Skip to content

[Customer Portal][FE][Web] Improve Update Details Rendering with Safe HTML Handling and Dark Mode Support - #698

Merged
cloby99 merged 10 commits into
wso2-open-operations:mainfrom
dileepapeiris:feat-kb-articles
May 15, 2026
Merged

cloby99 merged 10 commits into
wso2-open-operations:mainfrom
dileepapeiris:feat-kb-articles

Conversation

@dileepapeiris

@dileepapeiris dileepapeiris commented May 15, 2026 •

Copy link
Copy Markdown
Contributor

Description

This pull request significantly improves how update descriptions, instructions, and security advisories are rendered in the customer portal, especially with regard to HTML content and dark mode support. The main changes ensure that any real HTML markup in these fields is sanitized and rendered safely, while plain text (including text with HTML entities) is displayed correctly with preserved formatting. Additionally, the UI for descriptions and advisories is streamlined, and dark mode compatibility is enhanced.

Rendering and Content Handling Improvements:

  • Introduced HtmlOrText and updated UpdateSection to detect and safely render real HTML tags using DOMPurify, while decoding and formatting plain text and HTML entities for correct display. This prevents issues with XML/config-like tags and ensures consistent formatting. (UpdateLevelsReportModal.tsx, UpdateLevelDetailsPage.tsx) [1] [2]
  • Added logic to strip light-mode-only inline styles from HTML when in dark mode, using the stripLightModeInlineStyles utility and useDarkMode hook. (UpdateLevelsReportModal.tsx, UpdateLevelDetailsPage.tsx) [1] [2] [3]

UI and Layout Enhancements:

  • Updated the display of update descriptions, instructions, and security advisories to use the new rendering logic, improving readability and visual consistency, including better handling of lists and section headers. (UpdateLevelsReportModal.tsx, UpdateLevelDetailsPage.tsx) [1] [2] [3]
  • Adjusted padding and margin for buttons and headers for improved alignment and appearance. (ListPageHeader.tsx, CaseDetailsBackButton.tsx) [1] [2]

Code Simplification and Safety:

  • Removed the use of parseDescriptionSections in favor of direct rendering, and improved the logic for displaying non-empty instructions and descriptions. (UpdateLevelsReportModal.tsx, updateLevelsReportPdf.ts) [1] [2]
  • Updated all relevant component calls to pass dark mode state and use the new rendering utilities for consistent behavior. (UpdateLevelsReportModal.tsx, UpdateLevelDetailsPage.tsx) [1] [2] [3]

These changes together make the update details UI more robust, secure, and visually consistent, especially when handling mixed content and different display modes.

Summary by CodeRabbit

  • Bug Fixes

    • Improved rendering of update descriptions, instructions, and security advisory information to properly display formatted content
    • Enhanced dark mode compatibility for update content display across all views
    • Enhanced PDF generation for update reports with improved formatting, text styling, and hyperlink support
  • Style

    • Refined back button spacing for improved visual alignment

Review Change Stack

Add HTML-aware parsing and rendering for description fields in updateLevelsReportPdf. Introduces stripHtmlTags (decodes common entities) and htmlToBlocks (uses DOMParser to produce paragraph-level blocks with bold/italic runs and list handling). Replace the old simple renderField with renderHtmlField that lays out styled runs, preserves bullets and line breaks, and performs manual word-wrap for PDF output. Also call stripHtmlTags in parseDescriptionSections and update all field render calls to use the new HTML-aware renderer.
Increase horizontal padding (px: 1) and add a negative left margin (ml: -1) on the ListPageHeader control to preserve visual alignment while providing consistent touch/click padding. This tweaks spacing to better align the header element with surrounding content.
Sanitize and correctly render HTML/plain text in update descriptions and related fields. Adds DOMPurify, HtmlOrText helper, entity decoding, HTML detection regex, and shared styling (HTML_CONTENT_SX). Integrates useDarkMode and stripLightModeInlineStyles to handle dark-mode inline styles. Refactors UpdateDescriptionItem to use HtmlOrText and bug-fix parsing, removes parseDescriptionSections usage, and renders entry.description, instructions, and advisory overviews via HtmlOrText. Also adjusts layout/styles for instructions and security advisories and passes isDark flag where needed.
Add safe HTML handling for update/advisory sections: introduce DOMPurify-based sanitization, HTML detection, entity decoding and newline-to-<br> conversion for plain text. Add HTML_CONTENT_SX styling and decodeEntities helper; stripLightModeInlineStyles is applied when dark mode is active (useDarkMode hook). Update UpdateSection to choose sanitized HTML vs escaped text and pass isDark from UpdateDetailCard to all section usages. Adjust advisory layout spacing for Overview/Description and ensure rendered content is safe and styled consistently.
Detect and render URLs inside text segments when generating the Update Levels report PDF. Added a URL regex and logic to split segment text into URL and non-URL parts, render URLs in blue with an underline and clickable link area, and keep non-URL text in the original gray color. Also reset regex state between uses and restore draw color after underlining. Increased vertical spacing (y offset) slightly to improve layout.
Update default sx prop for CaseDetailsBackButton: change left margin from ml: -0.5 to ml: -1 and add px: 1. This tweaks the button's horizontal spacing and adds horizontal padding to improve alignment and the touch/click target.
@coderabbitai

coderabbitai Bot commented May 15, 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 49 minutes and 5 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ 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: 2cbaef48-3c26-4fc7-bfd4-c06b6e38a26e

📥 Commits

Reviewing files that changed from the base of the PR and between 6de373a and 87df2f3.

📒 Files selected for processing (4)
  • apps/customer-portal/webapp/src/features/updates/components/HtmlOrText.tsx
  • apps/customer-portal/webapp/src/features/updates/components/all-updates/UpdateLevelsReportModal.tsx
  • apps/customer-portal/webapp/src/features/updates/pages/UpdateLevelDetailsPage.tsx
  • apps/customer-portal/webapp/src/features/updates/utils/updateLevelsReportPdf.ts
📝 Walkthrough

Walkthrough

Back button styling is aligned across the customer portal. Update descriptions, instructions, and security advisory content are refactored to detect and render HTML markup with DOMPurify sanitization, entity decoding, and dark-mode-aware inline style stripping in modal, page details, and PDF export views.

Changes

Button styling alignment

Layer / File(s) Summary
Back button spacing updates
apps/customer-portal/webapp/src/components/list-view/ListPageHeader.tsx, apps/customer-portal/webapp/src/features/support/components/case-details/header/CaseDetailsBackButton.tsx
ListPageHeader and CaseDetailsBackButton back buttons updated with consistent horizontal padding (px: 1) and adjusted left margin for visual alignment.

HTML content rendering for updates

Layer / File(s) Summary
PDF HTML-to-blocks rendering utilities
apps/customer-portal/webapp/src/features/updates/utils/updateLevelsReportPdf.ts
Introduces stripHtmlTags and htmlToBlocks helpers to convert HTML into styled PDF blocks with bold/italic runs and list support. renderHtmlField replaces plain text rendering to wrap styled blocks, preserve line breaks, and detect URLs for blue underlined clickable hyperlinks. parseDescriptionSections now strips HTML tags before section parsing.
Modal HTML description and advisory rendering
apps/customer-portal/webapp/src/features/updates/components/all-updates/UpdateLevelsReportModal.tsx
UpdateLevelsReportModal introduces HtmlOrText component that detects real HTML, sanitizes with DOMPurify, and strips light-mode inline styles in dark mode. UpdateDescriptionItem updated to accept isDark prop and render descriptions through HtmlOrText. Modal computes isDark via useDarkMode() and wires it through description items. Update entry descriptions, instructions, and advisory overviews now use HtmlOrText rendering instead of parsed sections and plain text blocks.
Page details HTML content rendering
apps/customer-portal/webapp/src/features/updates/pages/UpdateLevelDetailsPage.tsx
UpdateLevelDetailsPage refactors UpdateSection to detect real HTML tags, sanitize with DOMPurify, decode entities for non-HTML text, and safely escape/convert newlines to <br>. UpdateDetailCard derives isDark from useDarkMode() and wires it into UpdateSection for main description/instructions and all security advisory sub-sections (Overview, Description, Impact, Solution, Notes, Credits).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • wso2-open-operations/cs-tools#651: Both PRs modify updateLevelsReportPdf.ts's generateUpdateLevelsReportPdf to change PDF output (main PR switches description/advisory rendering to HTML-sanitized blocks, while retrieved PR adds parseFileList and aggregated "Files Added/Removed/Updated" sections), so they conflict/overlap in the same PDF generation flow.
  • wso2-open-operations/cs-tools#621: Both PRs change the Update Levels Report rendering pipeline—especially UpdateLevelsReportModal.tsx and updateLevelsReportPdf.ts (notably parseDescriptionSections)—so the main PR's HTML-aware/DOMPurify refactor directly overlaps with the retrieved PR's description-section parsing updates.
  • wso2-open-operations/cs-tools#617: Both PRs modify the Update Levels Report PDF pipeline in apps/customer-portal/webapp/src/features/updates/utils/updateLevelsReportPdf.ts by changing how update descriptions/security advisories are parsed and rendered into PDF output (main PR adds HTML-aware sanitization/block rendering; retrieved PR overhauls PDF generation structure).

Suggested labels

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

Suggested reviewers

  • cloby99
  • chanukaranaba
  • Rashmika998

Poem

🐰 HTML content flows so clean,
DOMPurify keeps markup keen,
Dark mode styles stripped away,
PDF renders, styled in every way,
Buttons aligned, the portal's bright! ✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description covers key changes and improvements but does not follow the required template structure with sections like Purpose, Goals, Approach, User stories, Release notes, Documentation, etc. Fill in the missing required template sections (Purpose with issue links, Goals, Approach with UI changes, User stories, Release note, Documentation, Training, Certification, Marketing, Test environment, and others) to comply with the repository's PR template.
Docstring Coverage ⚠️ Warning Docstring coverage is 55.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changes: improving update details rendering with HTML handling and dark mode support, which matches the core objectives.
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.

@dileepapeiris dileepapeiris self-assigned this May 15, 2026
@dileepapeiris dileepapeiris added 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 May 15, 2026
@dileepapeiris dileepapeiris changed the title Feat kb articles [Customer Portal][FE][Web] Improve Update Details Rendering with Safe HTML Handling and Dark Mode Support May 15, 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: 2

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

Inline comments:
In
`@apps/customer-portal/webapp/src/features/updates/components/all-updates/UpdateLevelsReportModal.tsx`:
- Around line 31-88: Extract the duplicated HTML-vs-text rendering into a shared
component module: create a new features/updates/components/HtmlOrText.tsx that
exports HtmlOrText plus HTML_FORMAT_RE, decodeEntities, and HTML_CONTENT_SX;
move the implementation from UpdateLevelsReportModal.tsx (the HtmlOrText
function and helpers) into that module and replace the local definitions with
imports; update UpdateLevelsReportModal (where HtmlOrText is used) and
UpdateLevelDetailsPage.tsx (replace its UpdateSection/UpdateDescriptionItem
usage) to import and reuse HtmlOrText and the constants, ensuring the dark-mode
stripping (stripLightModeInlineStyles) and DOMPurify usage remain unchanged and
props/signature match the original HtmlOrText.

In
`@apps/customer-portal/webapp/src/features/updates/utils/updateLevelsReportPdf.ts`:
- Around line 132-147: stripHtmlTags currently removes all tags and collapses
all consecutive whitespace which removes paragraph/newline boundaries and breaks
parseDescriptionSections; update stripHtmlTags to replace common block-level
tags (e.g., </p>, <p>, <div>, </div>, <br>, <li>, </h[1-6]>, </h[1-6]>) with a
newline before stripping remaining tags, then decode entities as before but
change the whitespace normalization to only collapse runs of spaces/tabs (e.g.,
/[ \t]{2,}/g) and limit excessive newlines (e.g., replace /\n{3,}/g with '\n\n')
so section-label regexes in parseDescriptionSections can still match on line
starts.
🪄 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: 539d863d-4e7a-46c7-9f18-d0e1e34a7096

📥 Commits

Reviewing files that changed from the base of the PR and between ec1d36b and 6de373a.

📒 Files selected for processing (5)
  • apps/customer-portal/webapp/src/components/list-view/ListPageHeader.tsx
  • apps/customer-portal/webapp/src/features/support/components/case-details/header/CaseDetailsBackButton.tsx
  • apps/customer-portal/webapp/src/features/updates/components/all-updates/UpdateLevelsReportModal.tsx
  • apps/customer-portal/webapp/src/features/updates/pages/UpdateLevelDetailsPage.tsx
  • apps/customer-portal/webapp/src/features/updates/utils/updateLevelsReportPdf.ts

Refactor UpdateLevelsReportModal by moving the HtmlOrText rendering logic and related helpers into a dedicated module. Removed the local DOMPurify import, HTML_FORMAT_RE, decodeEntities, HTML_CONTENT_SX, and stripLightModeInlineStyles usage and now import HtmlOrText from @features/updates/components/HtmlOrText. This simplifies the modal file and centralizes HTML/text rendering for reuse and easier maintenance; behavior should remain unchanged.
Introduce HtmlOrText.tsx: a new component to render strings that may contain HTML or plain text. It detects real HTML tags (HTML_FORMAT_RE), sanitizes markup with DOMPurify (optionally stripping light-mode inline styles for dark mode), and decodes/plain-escapes entities and newlines for plain text. Also adds helper decodeEntities and shared styling (HTML_CONTENT_SX) and uses Box from @wso2/oxygen-ui.
When converting HTML to plain text for PDFs, replace closing block-level tags and <br> with newlines so section boundaries are preserved for downstream parsers (e.g. newline-anchored regexes). Also tighten whitespace normalization: collapse only consecutive spaces/tabs (not newlines) and reduce runs of 3+ newlines to two, keeping paragraph separation intact while still trimming extraneous whitespace and decoding HTML entities.
Replace the inline HTML/text parsing and sanitization logic in UpdateLevelDetailsPage's UpdateSection with the shared HtmlOrText component. Removed DOMPurify usage, the HTML detection regex, decodeEntities helper, HTML_CONTENT_SX styles, and the stripLightModeInlineStyles handling; updated imports accordingly to centralize HTML/text rendering and sanitization.
@cloby99
cloby99 merged commit 64805b7 into wso2-open-operations:main May 15, 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/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