Skip to content

Extract persona customize-page categories into PersonaClassBase#29706

Merged
chirag-madlani merged 6 commits into
mainfrom
feat/persona-class-base-override
Jul 3, 2026
Merged

Extract persona customize-page categories into PersonaClassBase#29706
chirag-madlani merged 6 commits into
mainfrom
feat/persona-class-base-override

Conversation

@karanh37

@karanh37 karanh37 commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Moves getCustomizePageCategories/getCustomizePageOptions (and the entity-icon map) out of PersonaUtils.ts into a new PersonaClassBase class, following the same overridable-classbase pattern already used for LeftSidebarClassBase, CustomizeMyDataPageClassBase, etc.
  • PersonaUtils.ts now delegates to a personaClassBase singleton instead of holding the logic inline.
  • No behavior change — getCustomizePageCategories()/getCustomizePageOptions() return identical output to before.

This lets downstream products extend the persona customize-page category list (e.g. adding a product-specific customization entry) via a PersonaClassCollate-style override instead of forking PersonaUtils.ts.

Test plan

  • getCustomizePageCategories/getCustomizePageOptions behavior unchanged (pure refactor, same return values)
  • Existing PersonaUtils.test.ts / CustomizeUI consumers unaffected (same public exports)

Greptile Summary

This PR extracts getCustomizePageCategories, getCustomizePageOptions, and the ENTITY_ICONS map from PersonaUtils.ts into a new PersonaClassBase class, following the overridable ClassBase pattern already established for LeftSidebarClassBase, CustomizeMyDataPageClassBase, etc. PersonaUtils.ts is now a thin delegation layer preserving the existing public API.

  • PersonaClassBase.ts — new class with getEntityIcons(), getCustomizePageCategories(), getCustomizePageOptions(), and a protected generateSettingItems() hook; exported as both a named class and a singleton default.
  • PersonaUtils.ts — slimmed to re-export CustomizeIconKeys and forward the two public functions to the singleton, keeping all callers unaffected.
  • data-marketplace-colored.svg — new dedicated icon added; PageType.DataMarketplace previously reused DataProductIcon and now correctly maps to its own icon (a minor undocumented visual improvement alongside the refactor).

Confidence Score: 5/5

Safe to merge — pure structural refactoring with no change to the existing public API and comprehensive test coverage of all three methods including subclass-override scenarios.

All logic is moved verbatim into PersonaClassBase; PersonaUtils.ts delegates faithfully; the new test file covers getEntityIcons, both public category methods, override propagation, and the singleton contract. The only observable difference from the original code is that PageType.DataMarketplace now uses its own dedicated SVG instead of reusing DataProductIcon — an intentional improvement signalled by the new SVG file being part of this commit.

No files require special attention.

Important Files Changed

Filename Overview
openmetadata-ui/src/main/resources/ui/src/utils/PersonaClassBase.ts New PersonaClassBase class encapsulating entity icons, getCustomizePageCategories, and getCustomizePageOptions; exported as both named class and singleton default. DataMarketplace now uses a dedicated icon instead of the old DataProduct icon reuse.
openmetadata-ui/src/main/resources/ui/src/utils/Persona/PersonaUtils.ts Reduced to a thin delegation layer re-exporting CustomizeIconKeys and forwarding both public functions to the singleton personaClassBase; public API is fully preserved.
openmetadata-ui/src/main/resources/ui/src/utils/PersonaClassBase.test.ts Comprehensive test file covering getEntityIcons, getCustomizePageCategories (including override-propagation), getCustomizePageOptions for all categories, and singleton export; addresses the concern raised in a previous review thread.
openmetadata-ui/src/main/resources/ui/src/assets/svg/data-marketplace-colored.svg New dedicated SVG icon for DataMarketplace; replaces the previously-reused DataProductIcon in the ENTITY_ICONS map.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant Consumer as Consumer(CustomizeUI, etc.)
    participant PU as PersonaUtils.ts
    participant PCB as personaClassBase(PersonaClassBase singleton)
    participant ICONS as ENTITY_ICONS(module constant)

    Consumer->>PU: getCustomizePageCategories()
    PU->>PCB: personaClassBase.getCustomizePageCategories()
    PCB->>ICONS: this.getEntityIcons()
    ICONS-->>PCB: Record CustomizeIconKeys SvgComponent
    PCB-->>PU: SettingMenuItem[]
    PU-->>Consumer: SettingMenuItem[]

    Consumer->>PU: getCustomizePageOptions(category)
    PU->>PCB: personaClassBase.getCustomizePageOptions(category)
    PCB->>PCB: this.generateSettingItems(pageType)
    PCB->>ICONS: this.getEntityIcons()[pageType]
    ICONS-->>PCB: SvgComponent
    PCB-->>PU: SettingMenuItem[]
    PU-->>Consumer: SettingMenuItem[]
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 Consumer as Consumer(CustomizeUI, etc.)
    participant PU as PersonaUtils.ts
    participant PCB as personaClassBase(PersonaClassBase singleton)
    participant ICONS as ENTITY_ICONS(module constant)

    Consumer->>PU: getCustomizePageCategories()
    PU->>PCB: personaClassBase.getCustomizePageCategories()
    PCB->>ICONS: this.getEntityIcons()
    ICONS-->>PCB: Record CustomizeIconKeys SvgComponent
    PCB-->>PU: SettingMenuItem[]
    PU-->>Consumer: SettingMenuItem[]

    Consumer->>PU: getCustomizePageOptions(category)
    PU->>PCB: personaClassBase.getCustomizePageOptions(category)
    PCB->>PCB: this.generateSettingItems(pageType)
    PCB->>ICONS: this.getEntityIcons()[pageType]
    ICONS-->>PCB: SvgComponent
    PCB-->>PU: SettingMenuItem[]
    PU-->>Consumer: SettingMenuItem[]
Loading

Reviews (5): Last reviewed commit: "fix: keep startCase option labels in cus..." | Re-trigger Greptile

Moves getCustomizePageCategories/getCustomizePageOptions out of
PersonaUtils into an overridable PersonaClassBase, following the same
ClassBase pattern used elsewhere in the UI. Lets downstream products
extend the persona customize-page category list without forking
PersonaUtils.
@karanh37 karanh37 requested a review from a team as a code owner July 2, 2026 13:33
Copilot AI review requested due to automatic review settings July 2, 2026 13:33
@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

❌ PR checklist incomplete

This PR cannot be merged until the following are addressed on its linked issue:

  • No GitHub issue is linked. Link an issue in the Development section of the PR (or add Fixes #12345 to the description). For a same-org cross-repo issue, add Fixes open-metadata/<repo>#123 to the description.

The fields live on the linked issue in the Shipping project (open the issue → right sidebar → Projects). After you set them, re-run this check (or push a commit) — issue/project changes do not re-trigger it automatically.

Maintainers can bypass this check by adding the skip-pr-checks label.

@github-actions github-actions Bot added safe to test Add this label to run secure Github workflows on PRs UI UI specific issues labels Jul 2, 2026
Comment on lines +114 to +191
{
key: 'governance',
label: i18n.t('label.governance'),
isBeta: false,
description:
'Customize the Govern pages with widget of your preference',
icon: ENTITY_ICONS['govern'],
},
{
key: 'data-assets',
label: i18n.t('label.data-asset-plural'),
isBeta: false,
description:
'Customize the entity detail page with widget of your preference',
icon: ENTITY_ICONS['dataAssets'],
},
];
}

public getCustomizePageOptions(category: string): SettingMenuItem[] {
const list = map(PageType);

switch (category) {
case 'governance':
return list.reduce((acc, item) => {
if (
[
PageType.Glossary,
PageType.GlossaryTerm,
PageType.Domain,
PageType.DataProduct,
].includes(item)
) {
acc.push(this.generateSettingItems(item));
}

return acc;
}, [] as SettingMenuItem[]);
case 'data-assets':
return list.reduce((acc, item) => {
if (
![
PageType.Glossary,
PageType.GlossaryTerm,
PageType.Domain,
PageType.DataProduct,
PageType.LandingPage,
PageType.Tag,
PageType.Classification,
PageType.DataMarketplace,
].includes(item)
) {
acc.push(this.generateSettingItems(item));
}

return acc;
}, [] as SettingMenuItem[]);
default:
return [];
}
}

protected generateSettingItems(pageType: PageType): SettingMenuItem {
return {
key: pageType,
label: startCase(pageType),
description: i18n.t('message.entity-customize-description', {
entity: startCase(pageType),
}),
icon: ENTITY_ICONS[pageType],
};
}
}

const personaClassBase = new PersonaClassBase();

export default personaClassBase;
export { PersonaClassBase };

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.

P2 Missing companion test file for PersonaClassBase

Every other ClassBase utility in src/utils/ has a dedicated *.test.ts alongside it (e.g. LeftSidebarClassBase.test.ts, GlobalSettingsClassBase.test.ts, DocumentationLinksClassBase.test.ts, etc.). PersonaClassBase.ts is the only ClassBase file in the directory without one. While PersonaUtils.test.ts still exercises the delegated functions through the singleton, it does not cover getEntityIcons(), the protected generateSettingItems() contract, or any subclass-override scenarios — which is precisely the extension point this PR is introducing.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Copilot AI 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.

Pull request overview

This PR refactors persona customize-page configuration by extracting the customize-page category/option generation (and entity icon mapping) from PersonaUtils.ts into a new PersonaClassBase, aligning persona customization with the existing *ClassBase override pattern used elsewhere in the UI.

Changes:

  • Added PersonaClassBase to encapsulate persona customize-page categories/options and the icon map behind an overridable class.
  • Updated PersonaUtils.ts to delegate getCustomizePageCategories() / getCustomizePageOptions() to a personaClassBase singleton.
  • Re-exported CustomizeIconKeys from the new class base to preserve the public type surface.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.

File Description
openmetadata-ui/src/main/resources/ui/src/utils/PersonaClassBase.ts Introduces the new overridable class base containing the category/option generation logic and icon mapping.
openmetadata-ui/src/main/resources/ui/src/utils/Persona/PersonaUtils.ts Converts the previous inline logic into thin delegating wrappers to the personaClassBase singleton.

Comment on lines +93 to +104
key: 'navigation',
label: i18n.t('label.navigation'),
isBeta: false,
description: 'Customize left sidebar ',
icon: ENTITY_ICONS['navigation'],
},
{
key: PageType.LandingPage,
label: i18n.t('label.home-page'),
description:
'Customize the My data page with widget of your preference',
icon: ENTITY_ICONS[PageType.LandingPage],
Comment on lines +115 to +128
key: 'governance',
label: i18n.t('label.governance'),
isBeta: false,
description:
'Customize the Govern pages with widget of your preference',
icon: ENTITY_ICONS['govern'],
},
{
key: 'data-assets',
label: i18n.t('label.data-asset-plural'),
isBeta: false,
description:
'Customize the entity detail page with widget of your preference',
icon: ENTITY_ICONS['dataAssets'],
Comment thread openmetadata-ui/src/main/resources/ui/src/utils/PersonaClassBase.ts Outdated
label: i18n.t('label.navigation'),
isBeta: false,
description: 'Customize left sidebar ',
icon: ENTITY_ICONS['navigation'],
Comment on lines +178 to +182
key: pageType,
label: startCase(pageType),
description: i18n.t('message.entity-customize-description', {
entity: startCase(pageType),
}),
@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Jest test Coverage

UI tests summary

Lines Statements Branches Functions
Coverage: 63%
63.23% (71163/112546) 46.25% (41318/89324) 47.53% (12696/26710)

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

🔴 Playwright Results — 1 failure(s), 25 flaky

✅ 4477 passed · ❌ 1 failed · 🟡 25 flaky · ⏭️ 38 skipped

Shard Passed Failed Flaky Skipped
🟡 Shard 1 441 0 2 16
🟡 Shard 2 802 0 8 8
🟡 Shard 3 807 0 2 7
🟡 Shard 4 808 0 3 5
🔴 Shard 5 853 1 3 0
🟡 Shard 6 766 0 7 2

Genuine Failures (failed on all attempts)

Pages/ExploreBrowse.spec.ts › service type drill-down disables unrelated roots and query-panel Clear resets it (shard 5)
�[31mTest timeout of 180000ms exceeded.�[39m
🟡 25 flaky test(s) (passed on retry)
  • Pages/Lineage/LineageRightPanel.spec.ts › Verify custom properties tab IS visible for supported type: metric (shard 1, 1 retry)
  • Flow/SearchRBAC.spec.ts › the browse tree only shows the asset-type categories a user can access (shard 1, 1 retry)
  • Features/BulkEditEntity.spec.ts › Database (shard 2, 1 retry)
  • Features/BulkEditEntity.spec.ts › Database Schema (shard 2, 1 retry)
  • Features/BulkEditOperationBadges.spec.ts › Glossary bulk edit search filters rows and clear restores them (shard 2, 1 retry)
  • Features/BulkImport.spec.ts › Database service (shard 2, 1 retry)
  • Features/BulkImport.spec.ts › Database Schema (shard 2, 1 retry)
  • Features/ContextCenter.spec.ts › clicking a memory row opens the view-only modal (shard 2, 1 retry)
  • Features/ContextCenterPermission.spec.ts › user with view-only permission cannot see restore or delete actions on an archived document (shard 2, 1 retry)
  • Features/DataQuality/TestCaseImportExportE2eFlow.spec.ts › Admin: Complete export-import-validate flow (shard 2, 1 retry)
  • Features/SearchExport.spec.ts › Export queues a background job and downloads from the jobs tray (shard 3, 1 retry)
  • Features/TestSuiteMultiPipeline.spec.ts › TestSuite multi pipeline support (shard 3, 1 retry)
  • Features/UserProfileOnlineStatus.spec.ts › Should show online status badge on user profile for active users (shard 4, 1 retry)
  • Pages/CustomProperties.spec.ts › Time (shard 4, 1 retry)
  • Pages/CustomProperties.spec.ts › Table (shard 4, 1 retry)
  • Pages/Entity.spec.ts › User as Owner Add, Update and Remove (shard 5, 1 retry)
  • Pages/Entity.spec.ts › User as Owner with unsorted list (shard 5, 1 retry)
  • Pages/EntityDataSteward.spec.ts › Tier Add, Update and Remove (shard 5, 1 retry)
  • Pages/GlossaryImportExport.spec.ts › Glossary Bulk Import Export (shard 6, 1 retry)
  • Pages/GlossaryImportExport.spec.ts › Import partial success - some terms pass, some fail (shard 6, 1 retry)
  • Pages/Lineage/DataAssetLineage.spec.ts › Column lineage for dashboard -> topic (shard 6, 1 retry)
  • Pages/Lineage/LineageFilters.spec.ts › Verify Impact Analysis service filter selection (shard 6, 1 retry)
  • Pages/Lineage/LineageRightPanel.spec.ts › Verify custom properties tab is NOT visible for pipelineService in platform lineage (shard 6, 1 retry)
  • Pages/Lineage/LineageRightPanel.spec.ts › Verify custom properties tab is NOT visible for apiService in platform lineage (shard 6, 1 retry)
  • Pages/TestSuite.spec.ts › Logical TestSuite (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

- Route category/option icons through this.getEntityIcons() instead of
  the module-level ENTITY_ICONS constant, so subclass overrides of
  getEntityIcons() actually take effect (was previously bypassed).
- Localize the four category descriptions that were hardcoded English
  strings (one with a trailing space), reusing existing
  message.entity-customize-description and
  message.customize-your-navigation-subheader keys.
- generateSettingItems now derives PageType labels/descriptions via
  i18n.t(label.<kebab-case>) instead of lodash startCase, matching
  every label key that already exists for these PageTypes.
- Add PersonaClassBase.test.ts, following the *ClassBase.test.ts
  convention used elsewhere in src/utils/.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
DataMarketplace previously reused DataProductIcon; add its own colored SVG.
Copilot AI review requested due to automatic review settings July 3, 2026 08:24

Copilot AI 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.

Pull request overview

Copilot reviewed 4 out of 5 changed files in this pull request and generated 3 comments.

Comment thread openmetadata-ui/src/main/resources/ui/src/utils/PersonaClassBase.ts
Comment thread openmetadata-ui/src/main/resources/ui/src/utils/PersonaClassBase.ts
karanh37 and others added 2 commits July 3, 2026 16:32
Revert the customize-page category descriptions to their original hardcoded
copy (navigation, home page, governance, data assets). The i18n-driven
descriptions changed the rendered text and broke the Governance customize
Playwright assertion; restoring the previous strings keeps behavior
unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 3, 2026 11:03
Comment thread openmetadata-ui/src/main/resources/ui/src/utils/PersonaClassBase.ts

Copilot AI 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.

Pull request overview

Copilot reviewed 4 out of 5 changed files in this pull request and generated 6 comments.

Comment thread openmetadata-ui/src/main/resources/ui/src/utils/PersonaClassBase.ts
Comment thread openmetadata-ui/src/main/resources/ui/src/utils/PersonaClassBase.ts
Comment thread openmetadata-ui/src/main/resources/ui/src/utils/PersonaClassBase.ts
Comment thread openmetadata-ui/src/main/resources/ui/src/utils/PersonaClassBase.ts
Comment thread openmetadata-ui/src/main/resources/ui/src/utils/PersonaClassBase.ts
Comment thread openmetadata-ui/src/main/resources/ui/src/utils/PersonaClassBase.ts
Revert generateSettingItems option labels from i18n.t('label.<kebab>') back
to startCase(pageType) to preserve the original output (e.g. "Ml Model", not
"ML Model"). The i18n labels broke customize-page Playwright clicks
(CustomizeDetailPage, CustomizeCollate) and contradicted the PR's
no-behavior-change claim. Update the affected unit expectations accordingly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@sonarqubecloud

sonarqubecloud Bot commented Jul 3, 2026

Copy link
Copy Markdown

@chirag-madlani chirag-madlani merged commit cfd2651 into main Jul 3, 2026
49 of 54 checks passed
@chirag-madlani chirag-madlani deleted the feat/persona-class-base-override branch July 3, 2026 15:51
@gitar-bot

gitar-bot Bot commented Jul 3, 2026

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

Refactors persona customization logic into an overridable PersonaClassBase to support future extensions. Note that category descriptions remain hardcoded in English, which should be updated to use localized i18n keys for consistency.

✅ 1 resolved
Quality: Category descriptions hardcoded in English, not localized

📄 openmetadata-ui/src/main/resources/ui/src/utils/PersonaClassBase.ts:99 📄 openmetadata-ui/src/main/resources/ui/src/utils/PersonaClassBase.ts:105-106 📄 openmetadata-ui/src/main/resources/ui/src/utils/PersonaClassBase.ts:121-122 📄 openmetadata-ui/src/main/resources/ui/src/utils/PersonaClassBase.ts:129-130
In getCustomizePageCategories(), the navigation, LandingPage, governance, and data-assets entries use hardcoded English description strings (e.g. 'Customize left sidebar '), while the newly added DataMarketplace entry (lines 112-114) and generateSettingItems() (line 185) use i18n.t('message.entity-customize-description', ...). This creates an inconsistent, non-localized experience: these four descriptions won't be translated for non-English locales. Note this delta restores the pre-PR behavior (the original PersonaUtils.ts also hardcoded these strings), so it is not a regression — but since the surrounding code now uses i18n, consider routing all descriptions through i18n.t(...) for consistency and localization. Also 'Customize left sidebar ' has a trailing space.

Options

Display: compact → Showing less information.

Comment with these commands to change the behavior for this request:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

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 UI UI specific issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants