Skip to content

Addressed Context Center feedbacks#29230

Open
Rohit0301 wants to merge 15 commits into
mainfrom
addressed-context-center-feedbacks
Open

Addressed Context Center feedbacks#29230
Rohit0301 wants to merge 15 commits into
mainfrom
addressed-context-center-feedbacks

Conversation

@Rohit0301

@Rohit0301 Rohit0301 commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Describe your changes:

Screen.Recording.2026-06-22.at.1.05.56.PM.mov

Fixes 29275

I worked on ... because ...

Type of change:

  • Bug fix
  • Improvement
  • New feature
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation

High-level design:

N/A — small change.

Tests:

Use cases covered

Unit tests

Backend integration tests

Ingestion integration tests

Playwright (UI) tests

Manual testing performed

UI screen recording / screenshots:

Not applicable.

Checklist:

  • I have read the CONTRIBUTING document.
  • My PR title is Fixes <issue-number>: <short explanation>
  • My PR is linked to a GitHub issue via Fixes #<issue-number> above.
  • I have commented on my code, particularly in hard-to-understand areas.
  • For JSON Schema changes: I updated the migration scripts or explained why it is not needed.
  • For UI changes: I attached a screen recording and/or screenshots above.
  • I have added tests (unit / integration / Playwright as applicable) and listed them above.

Summary by Gitar

  • UI/UX improvements:
    • Refactored ArchiveView and MemoriesView to use updated button components and improved icon layouts.
    • Updated KnowledgeCard and ArticleDetailHeader to standardize typography weights and iconography.
    • Added maxItemWidth to Breadcrumbs to prevent layout overflow in headers.
  • Knowledge Center state management:
    • Implemented pendingSaveCountRef in KnowledgePageDetailComponent to prevent premature status transitions to SAVED during concurrent debounced patches.
    • Synchronized TitleComponent with external prop changes to ensure the input reflects the persisted display name.
  • Messaging and Localization:
    • Updated soft-delete-message-for-entity in en-us.json to reflect that soft-deleted items can be restored from Archives.
    • Standardized delete confirmation modal messages across ContextCenter modules to use consistent entity type labeling.

This will update automatically on new commits.

Greptile Summary

This PR addresses a round of Context Center UI feedback: it stabilizes the save-state indicator during concurrent debounced saves, fixes article-count display in the hierarchy sidebar, and standardizes button/icon/typography tokens across ArchiveView, MemoriesView, and related components.

  • Save-state race condition fixedpendingSaveCountRef in KnowledgePageDetailComponent prevents the status badge from flipping to SAVED while another debounced save is still in flight; setKnowledgePage calls are switched to functional updaters to avoid stale-closure overwrites.
  • Accurate article countKnowledgePagesHierarchy now fetches the total separately (limit=0, pageType=ARTICLE) instead of reading paginationState.paging.total, so the sidebar count is always article-specific; Quick Links are hard-deleted while Articles are soft-deleted to Archives.
  • i18n cleanup — a new dedicated soft-delete-archive-message key is added for Context Center soft-deletes, leaving the global soft-delete-message-for-entity key untouched.

Confidence Score: 5/5

Safe to merge; changes are UI/UX improvements and targeted logic fixes with no backend impact.

The core logic changes (pending-save counter, functional state updaters, separate article count fetch) are well-scoped and backed by tests. The one open question — whether removing the PageType.ARTICLE filter from KnowledgePageListComponent is intentional — is a behavioral change worth confirming, but does not break anything on its own.

KnowledgePageListComponent.tsx — the PageType.ARTICLE filter was removed from both the search and list API calls; worth confirming this is deliberate before merging.

Important Files Changed

Filename Overview
openmetadata-ui/src/main/resources/ui/src/components/KnowledgeCenter/KnowledgePageDetailComponent/KnowledgePageDetailComponent.tsx Adds pendingSaveCountRef to guard against premature SAVED state transitions when concurrent debounced saves are in flight; also switches setKnowledgePage calls to functional updates for correctness.
openmetadata-ui/src/main/resources/ui/src/components/KnowledgeCenter/TitleComponent/TitleComponent.tsx Adds useEffect to re-sync titleValue from the prop after a save resolves; the race condition between prop sync and active user input was flagged in a previous review thread.
openmetadata-ui/src/main/resources/ui/src/components/KnowledgeCenter/KnowledgePagesHierarchy/KnowledgePagesHierarchy.tsx Introduces a dedicated fetchKnowledgePagesTotalCount (limit=0, pageType=ARTICLE) so the sidebar article count is accurate regardless of what the paginated hierarchy query returns; differentiates Quick Link hard-delete from Article soft-delete.
openmetadata-ui/src/main/resources/ui/src/utils/StringUtils.ts Adds decodeHtmlEntities using DOMParser (browser-safe, no script execution) and pipes it through stripMarkdown so HTML entities left over after markdown removal are decoded.
openmetadata-ui/src/main/resources/ui/src/locale/languages/en-us.json Adds soft-delete-archive-message (Context Center-specific) and article-lowercase/document-lowercase labels; the global soft-delete-message-for-entity key is left untouched, addressing the concern from a prior review thread.
openmetadata-ui/src/main/resources/ui/src/components/KnowledgeCenter/KnowledgePageListComponent/KnowledgePageListComponent.tsx Removes the PageType.ARTICLE filter from both the ES search and REST API paths, causing the list to return all page types; the intent behind this behavioral change is unclear.
openmetadata-ui/src/main/resources/ui/src/pages/ContextCenterPage/ContextCenterArchivePage/ContextCenterArchivePage.tsx Refactors the filter tabs out of the Card container, uses classNames for active/inactive styles, and switches the delete message to the new entity-type-specific label keys.
openmetadata-ui/src/main/resources/ui/src/components/ContextCenter/ArticleDetailHeader/ArticleDetailHeader.component.tsx Replaces inline clipboard state + handleShare with the shared CopyLinkButton component; updates icon color tokens from gray-400/fg-disabled to tw:text-quaternary for consistency.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant User
    participant TitleComponent
    participant KnowledgePageDetailComponent
    participant API

    User->>TitleComponent: types display name
    TitleComponent->>KnowledgePageDetailComponent: handleDisplayNameOnChange(value)
    KnowledgePageDetailComponent->>KnowledgePageDetailComponent: pendingSaveCountRef++ (beginTrackedSave)
    KnowledgePageDetailComponent->>KnowledgePageDetailComponent: setContentChangeState(SAVING)
    User->>TitleComponent: types content (concurrent)
    TitleComponent->>KnowledgePageDetailComponent: handleContentOnChange(content)
    KnowledgePageDetailComponent->>KnowledgePageDetailComponent: pendingSaveCountRef++ (beginTrackedSave)
    KnowledgePageDetailComponent->>API: patchKnowledgePage (displayName)
    KnowledgePageDetailComponent->>API: patchKnowledgePage (content)
    API-->>KnowledgePageDetailComponent: response1
    KnowledgePageDetailComponent->>KnowledgePageDetailComponent: "pendingSaveCountRef-- (endTrackedSave: count=1, no SAVED)"
    API-->>KnowledgePageDetailComponent: response2
    KnowledgePageDetailComponent->>KnowledgePageDetailComponent: "pendingSaveCountRef-- (endTrackedSave: count=0, SAVED)"
    KnowledgePageDetailComponent->>TitleComponent: value prop updated
    TitleComponent->>TitleComponent: useEffect syncs titleValue from prop
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant User
    participant TitleComponent
    participant KnowledgePageDetailComponent
    participant API

    User->>TitleComponent: types display name
    TitleComponent->>KnowledgePageDetailComponent: handleDisplayNameOnChange(value)
    KnowledgePageDetailComponent->>KnowledgePageDetailComponent: pendingSaveCountRef++ (beginTrackedSave)
    KnowledgePageDetailComponent->>KnowledgePageDetailComponent: setContentChangeState(SAVING)
    User->>TitleComponent: types content (concurrent)
    TitleComponent->>KnowledgePageDetailComponent: handleContentOnChange(content)
    KnowledgePageDetailComponent->>KnowledgePageDetailComponent: pendingSaveCountRef++ (beginTrackedSave)
    KnowledgePageDetailComponent->>API: patchKnowledgePage (displayName)
    KnowledgePageDetailComponent->>API: patchKnowledgePage (content)
    API-->>KnowledgePageDetailComponent: response1
    KnowledgePageDetailComponent->>KnowledgePageDetailComponent: "pendingSaveCountRef-- (endTrackedSave: count=1, no SAVED)"
    API-->>KnowledgePageDetailComponent: response2
    KnowledgePageDetailComponent->>KnowledgePageDetailComponent: "pendingSaveCountRef-- (endTrackedSave: count=0, SAVED)"
    KnowledgePageDetailComponent->>TitleComponent: value prop updated
    TitleComponent->>TitleComponent: useEffect syncs titleValue from prop
Loading

Reviews (11): Last reviewed commit: "addressed gitar comment" | Re-trigger Greptile

@Rohit0301 Rohit0301 self-assigned this Jun 19, 2026
@Rohit0301 Rohit0301 added the safe to test Add this label to run secure Github workflows on PRs label Jun 19, 2026
@Rohit0301 Rohit0301 requested a review from a team as a code owner June 19, 2026 17:24
@Rohit0301 Rohit0301 added the skip-pr-checks Bypass PR metadata validation check label Jun 19, 2026
Comment on lines +246 to +274
@@ -264,6 +265,13 @@ const MemoryRow: FC<MemoryRowProps> = ({
</Typography>
</Badge>
))}
{memory?.tags?.length > VISIBLE_LINKED_ENTITIES_COUNT && (
<Badge size="md" type="color">
<Typography className="tw:text-secondary" size="text-xs">
+{memory.tags.length - VISIBLE_LINKED_ENTITIES_COUNT}
</Typography>
</Badge>
)}

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.

P1 Missing .slice() — all tags rendered alongside the overflow badge

VISIBLE_LINKED_ENTITIES_COUNT (4) is only used to compute the badge count; the .map() still iterates over every tag. When a memory has, say, 6 tags, the UI shows all 6 badges plus a "+2 more" badge simultaneously, which defeats the purpose of the constant. The fix is to add .slice(0, VISIBLE_LINKED_ENTITIES_COUNT) on the memory.tags array before calling .map(), matching the pattern already used in KnowledgeCard.tsx ((knowledgePage.tags ?? []).slice(0, 2).map(...)).

Comment on lines +55 to +57
useEffect(() => {
setTitleValue(value);
}, [value]);

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.

P1 useEffect can overwrite active user input when a debounced save resolves

The comment states this is safe because the parent only updates value after typing has settled, but the parent actually updates value when the API response resolves — not when typing stops. Concrete race condition: user types "Hello!", the debounce fires, a fast network returns displayName: "Hello!", then knowledgePage.displayName updates, and value prop changes. If the user resumed typing before the response arrived (e.g., "Hello! More text"), the useEffect fires setTitleValue("Hello!"), visibly resetting their cursor and truncating their input. The component should guard against overwriting unsaved local edits, for example by only syncing when titleValue already matches the previous prop value (i.e., when the user has not diverged from it).

@github-actions

github-actions Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

🟡 Playwright Results — all passed (11 flaky)

✅ 4007 passed · ❌ 0 failed · 🟡 11 flaky · ⏭️ 84 skipped

Shard Passed Failed Flaky Skipped
🟡 Shard 2 813 0 2 9
🟡 Shard 3 815 0 1 8
🟡 Shard 4 857 0 2 12
🟡 Shard 5 731 0 2 47
🟡 Shard 6 791 0 4 8
🟡 11 flaky test(s) (passed on retry)
  • Features/DataQuality/TestCaseImportExportE2eFlow.spec.ts › Admin: Complete export-import-validate flow (shard 2, 1 retry)
  • Features/Glossary/GlossaryHierarchy.spec.ts › should cancel move operation (shard 2, 1 retry)
  • Features/OntologyExplorerIntegration.spec.ts › filtering by relatedTo should show only terms connected by that relation and hide others (shard 3, 1 retry)
  • Pages/CustomProperties.spec.ts › Enum (shard 4, 1 retry)
  • Pages/DomainAdvanced.spec.ts › Data product version history shows changes (shard 4, 1 retry)
  • Pages/EntityDataConsumer.spec.ts › Tier Add, Update and Remove (shard 5, 1 retry)
  • Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts › Should remove user owner for knowledgeCenter (shard 5, 1 retry)
  • Pages/Lineage/DataAssetLineage.spec.ts › Column lineage for apiEndpoint -> table (shard 6, 1 retry)
  • Pages/Lineage/LineageFilters.spec.ts › Verify Impact Analysis service filter selection (shard 6, 1 retry)
  • Pages/Lineage/LineageInteraction.spec.ts › Verify edge delete button in drawer (shard 6, 1 retry)
  • Pages/Users.spec.ts › Admin soft & hard delete and restore user (shard 6, 1 retry)

📦 Download artifacts

How to debug locally
# Download playwright-test-results-<shard> artifact and unzip
npx playwright show-trace path/to/trace.zip    # view trace

@github-actions

github-actions Bot commented Jun 20, 2026

Copy link
Copy Markdown
Contributor

Jest test Coverage

UI tests summary

Lines Statements Branches Functions
Coverage: 62%
62.27% (66689/107090) 44.06% (37355/84764) 45.39% (11210/24693)

<div className="custom-group tw:flex tw:flex-1 tw:items-center tw:gap-2 tw:min-w-0">
<button
className="tw:flex tw:flex-1 tw:items-center tw:gap-2 tw:min-w-0 tw:text-left tw:bg-transparent tw:border-none tw:cursor-pointer tw:p-0"
className="tw:flex tw:flex-1 tw:items-center tw:gap-2 tw:min-w-0 tw:text-left tw:bg-transparent tw:border-none tw:cursor-pointer tw:p-0 tw:font-normal"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reason for using a HTML button here?

Comment on lines -140 to -142
queryFilter: {
query: { term: { pageType: PageType.ARTICLE } },
},

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We we are removing this? because we are already on KNOWLEDGE_PAGE_INDEX?

{(tab) => (
<Tabs.Item
{...tab}
className={({ isSelected }) =>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we added isSelected prop on tab item no?

Comment on lines +407 to +411
export function decodeHtmlEntities(text: string): string {
const doc = new DOMParser().parseFromString(text, 'text/html');

return doc.documentElement.textContent ?? text;
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did we try stress tests? like for very huge HTML how much time it will take?

@gitar-bot

gitar-bot Bot commented Jun 22, 2026

Copy link
Copy Markdown
Code Review ✅ Approved 4 resolved / 4 findings

Refines Context Center state management with concurrent save tracking and standardizes UI components like Breadcrumbs and ArchiveView. This update resolves previous issues regarding incorrect total counts and tag rendering.

✅ 4 resolved
Quality: Tag key changed from tagFQN to non-unique tag.name

📄 openmetadata-ui/src/main/resources/ui/src/components/ContextCenter/MemoriesView/MemoriesView.component.tsx:249
The badge key was changed from String(tag.tagFQN ?? '') to tag.name. tag.name is less unique than the fully-qualified tagFQN (two tags in different classifications can share the same name), risking duplicate React keys and reconciliation glitches. tag.name can also be undefined for some tag shapes. Prefer keeping tagFQN as the key.

Bug: Total count counts all pages, mislabeled as articles

📄 openmetadata-ui/src/main/resources/ui/src/components/KnowledgeCenter/KnowledgePagesHierarchy/KnowledgePagesHierarchy.tsx:239-246 📄 openmetadata-ui/src/main/resources/ui/src/components/KnowledgeCenter/KnowledgePagesHierarchy/KnowledgePagesHierarchy.tsx:722
fetchKnowledgePagesTotalCount calls getListKnowledgePages({ limit: 0 }) without a pageType filter. Per knowledgeCenterAPI.ts, getListKnowledgePages hits /contextCenter/pages and returns ALL knowledge pages (articles + quick links), whereas the hierarchy itself is fetched via getPageHierarchyFromES, which defaults to pageType: PageType.ARTICLE. The rendered label uses this count next to t('label.article-plural') ({knowledgePagesTotalCount} {t('label.article-plural')}).

Previously the displayed value came from paginationState.paging.total, which was derived from the ARTICLE-filtered hierarchy fetch. After this change the displayed article count will be inflated by quick-link pages (and any other page types), so the number shown to users no longer matches the article list. KnowledgePageListParams already supports a pageType field, so the fix is to pass pageType: PageType.ARTICLE to scope the count to articles.

Bug: Memory tags render all items plus a redundant overflow badge

📄 openmetadata-ui/src/main/resources/ui/src/components/ContextCenter/MemoriesView/MemoriesView.component.tsx:246-260
In MemoryRow, memory.tags.map(...) renders every tag (no slice), but a +N overflow badge is also rendered when memory.tags.length > VISIBLE_LINKED_ENTITIES_COUNT. The result is that all tags are shown AND a misleading +N more badge is appended (e.g. 6 tags → 6 badges + a +2 badge). The overflow badge clearly intends only the first VISIBLE_LINKED_ENTITIES_COUNT (4) tags to be visible, mirroring the .slice(0, 2) pattern used in KnowledgeCard.tsx. The map should be sliced to VISIBLE_LINKED_ENTITIES_COUNT.

Quality: Truncated version title loses hover tooltip

📄 openmetadata-ui/src/main/resources/ui/src/components/KnowledgeCenter/KnowledgePageVersion/KnowledgePageVersion.tsx:147-152 📄 openmetadata-ui/src/main/resources/ui/src/pages/KnowledgeCenterPage/knowledge-center-page.less:91-97
The display-name Typography.Text previously used ellipsis={{ tooltip: true }}, which both truncated the text and showed the full value in a tooltip on hover. This commit removes the ellipsis prop and replaces it with CSS-only truncation (text-overflow: ellipsis; white-space: nowrap;). The CSS approach truncates correctly but provides no way for users to read the full title when it is clipped — a minor UX regression for long knowledge-page names.

Consider restoring an accessible tooltip, e.g. keep ellipsis={{ tooltip: true }} on the Typography.Text (Ant Design measures overflow and renders the tooltip), or add a title={displayName || knowledgePage.name} attribute so the native browser tooltip appears on hover.

Options

Display: compact → Showing less information.

Comment with these commands to change:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

safe to test Add this label to run secure Github workflows on PRs skip-pr-checks Bypass PR metadata validation check

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Context Center Design Feedbacks

2 participants