Skip to content

Revamped metric ontology and workflow header#29704

Open
anuj-kumary wants to merge 1 commit into
mainfrom
header-revamp-ai
Open

Revamped metric ontology and workflow header#29704
anuj-kumary wants to merge 1 commit into
mainfrom
header-revamp-ai

Conversation

@anuj-kumary

@anuj-kumary anuj-kumary commented Jul 2, 2026

Copy link
Copy Markdown
Member

Describe your changes:

Fixes #

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.

Greptile Summary

This PR refactors the Metric list page, Ontology Explorer page, and Workflows page headers by extracting inline JSX into dedicated *Header.tsx components and routing them through the class-base singleton pattern (MetricListPageClassBase, OntologyExplorerClassBase, updated WorkflowClassBase). This enables Collate builds to swap in gradient-styled headers via the Vite class-replacement plugin without forking the shared page components.

  • Three new header components (MetricListHeader, OntologyExplorerHeader, WorkflowsHeader) extract previously inline JSX with no logic changes; all props and state management remain in the parent pages.
  • Three new/updated class-base files expose a getHeader(): FC<Props> extension point so Collate overrides can inject a different header implementation without touching OSS code.
  • MetricListHeader carries over two non-functional stub buttons (Rename, Delete) with no onClick handlers that were also stubs in the original MetricListPage; now that they're part of a typed component API, they should either be wired up or removed.

Confidence Score: 4/5

Safe to merge — the changes are a mechanical refactor that moves JSX into dedicated components with no logic alterations; the class-base wiring is straightforward and follows an established pattern in the codebase.

The Rename and Delete buttons in MetricListHeader are non-functional stubs (no onClick, not in the props interface), and getHeader() is called inside component render bodies rather than at module level, making all three pages mildly fragile against Collate overrides that return non-stable component references. Neither issue affects current behavior, but both deserve a follow-up before adding Collate overrides.

MetricListHeader.tsx — the stub Rename/Delete buttons and their absence from MetricListHeaderProps need resolution before adding Collate-side implementations.

Important Files Changed

Filename Overview
openmetadata-ui/src/main/resources/ui/src/pages/MetricsPage/MetricListPage/MetricListHeader.tsx New component extracting the Metric page header. Contains two non-functional action buttons (Rename, Delete) with no onClick handlers and no corresponding props in the interface.
openmetadata-ui/src/main/resources/ui/src/pages/MetricsPage/MetricListPage/MetricListPageClassBase.ts New class-base for the metrics page header to support OSS/Collate override via the Vite class-replacement plugin. Clean singleton pattern.
openmetadata-ui/src/main/resources/ui/src/pages/MetricsPage/MetricListPage/MetricListPage.tsx Delegates header rendering to MetricListPageClassBase; getHeader() is called inside the component render body — works today with stable references but is fragile against inline-function overrides.
openmetadata-ui/src/main/resources/ui/src/pages/OntologyExplorerPage/OntologyExplorerHeader.tsx Extracts the Ontology Explorer breadcrumb and stats card into a standalone component; code moved verbatim from OntologyExplorerPage with no logic changes.
openmetadata-ui/src/main/resources/ui/src/pages/OntologyExplorerPage/OntologyExplorerPage.tsx Now delegates header to OntologyExplorerClassBase; same getHeader()-inside-render pattern as MetricListPage.
openmetadata-ui/src/main/resources/ui/src/pages/WorkflowDefinitions/WorkflowsPage/WorkflowsHeader.tsx New component for the Workflows page header; clean extraction with all required props (allowCreateWorkflow, onNewWorkflow).
openmetadata-ui/src/main/resources/ui/src/pages/WorkflowDefinitions/WorkflowsPage/WorkflowsPage.tsx Delegates header to WorkflowClassBase; same getHeader()-inside-render pattern as the other pages.
openmetadata-ui/src/main/resources/ui/src/utils/OntologyExplorerClassBase.ts New class-base for the OntologyExplorer header; has an extra blank line between imports and the class declaration (style).
openmetadata-ui/src/main/resources/ui/src/utils/WorkflowClassBase.ts Adds getHeader() method to the existing WorkflowClassBase; clean addition following existing patterns.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    subgraph OSS ["OSS Build"]
        MLP["MetricListPage"] -->|"getHeader()"| MLCB["MetricListPageClassBase"]
        MLCB -->|returns| MLH["MetricListHeader"]

        OEP["OntologyExplorerPage"] -->|"getHeader()"| OECB["OntologyExplorerClassBase"]
        OECB -->|returns| OEH["OntologyExplorerHeader"]

        WP["WorkflowsPage"] -->|"getHeader()"| WCB["WorkflowClassBase"]
        WCB -->|returns| WH["WorkflowsHeader"]
    end

    subgraph Collate ["Collate Build - Vite plugin swaps ClassBase"]
        MLCB_C["MetricListPageClassCollate"] -->|"getHeader()"| MLH_C["GradientMetricHeader"]
        OECB_C["OntologyExplorerClassCollate"] -->|"getHeader()"| OEH_C["GradientOntologyHeader"]
        WCB_C["WorkflowClassCollate"] -->|"getHeader()"| WH_C["GradientWorkflowsHeader"]
    end

    MLP -.->|Collate override| MLCB_C
    OEP -.->|Collate override| OECB_C
    WP -.->|Collate override| WCB_C
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"}}}%%
flowchart TD
    subgraph OSS ["OSS Build"]
        MLP["MetricListPage"] -->|"getHeader()"| MLCB["MetricListPageClassBase"]
        MLCB -->|returns| MLH["MetricListHeader"]

        OEP["OntologyExplorerPage"] -->|"getHeader()"| OECB["OntologyExplorerClassBase"]
        OECB -->|returns| OEH["OntologyExplorerHeader"]

        WP["WorkflowsPage"] -->|"getHeader()"| WCB["WorkflowClassBase"]
        WCB -->|returns| WH["WorkflowsHeader"]
    end

    subgraph Collate ["Collate Build - Vite plugin swaps ClassBase"]
        MLCB_C["MetricListPageClassCollate"] -->|"getHeader()"| MLH_C["GradientMetricHeader"]
        OECB_C["OntologyExplorerClassCollate"] -->|"getHeader()"| OEH_C["GradientOntologyHeader"]
        WCB_C["WorkflowClassCollate"] -->|"getHeader()"| WH_C["GradientWorkflowsHeader"]
    end

    MLP -.->|Collate override| MLCB_C
    OEP -.->|Collate override| OECB_C
    WP -.->|Collate override| WCB_C
Loading

Comments Outside Diff (1)

  1. openmetadata-ui/src/main/resources/ui/src/pages/MetricsPage/MetricListPage/MetricListPage.tsx, line 217 (link)

    P2 getHeader() called inside the render body — same pattern in all three pages

    metricListPageClassBase.getHeader() (and the equivalent calls in OntologyExplorerPage and WorkflowsPage) runs on every render of the parent component. React uses reference equality to decide whether to reconcile or unmount+remount a child component: if getHeader() ever returns a different function reference between renders — e.g., an override that does return (props) => <GradientHeader {...props}/> inline — React sees a new component type and unmounts the entire header subtree, discarding its local state. The current base-class implementations always return a stable module-level reference so it works today, but the pattern is fragile for Collate overrides. Moving these calls outside the component function (at module level) eliminates the risk entirely.

Reviews (1): Last reviewed commit: "Revamped metric ontology and workflow he..." | Re-trigger Greptile

Greptile also left 2 inline comments on this PR.

@anuj-kumary anuj-kumary self-assigned this Jul 2, 2026
@anuj-kumary anuj-kumary requested a review from a team as a code owner July 2, 2026 12:51
@anuj-kumary anuj-kumary added UI UI specific issues safe to test Add this label to run secure Github workflows on PRs skip-pr-checks Bypass PR metadata validation check labels Jul 2, 2026
Comment on lines +117 to +131
<button className="metric-actions-menu-item" type="button">
<span className="metric-actions-icon">
<File06 size={18} />
</span>
<span>
<span className="metric-actions-title">
{t('label.rename')}
</span>
<span className="metric-actions-description">
{t('message.metrics-rename-collection-description')}
</span>
</span>
</button>
<button
className="metric-actions-menu-item metric-actions-menu-item-danger"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Bug: Rename/Delete actions in metric menu are non-functional

In MetricListHeader.tsx the actions dropdown renders four items, but the "Rename" (lines 117-129) and "Delete" (lines 130-144) <button> elements have no onClick handler and no disabled state. They are always shown to users with permission.EditAll, so clicking them does nothing — a broken/dead UI action from the user's perspective. Either wire up the handlers (pass onRename/onDelete props from MetricListPage) or omit these items until they are implemented.

Was this helpful? React with 👍 / 👎

Comment on lines +82 to +96
<button
aria-busy={isExporting}
className="metric-actions-menu-item"
disabled={isExporting}
type="button"
onClick={onExport}>
<span className="metric-actions-icon">
<Download01 size={18} />
</span>
<span>
<span className="metric-actions-title">
{t('label.export')}
</span>
<span className="metric-actions-description">
{t('message.metrics-export-description')}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Quality: Export/import menu items use raw instead of core components

The frontend guidelines call for prioritizing openmetadata-ui-core-components over ad-hoc elements. MetricListHeader.tsx builds the dropdown menu items as raw <button> elements with custom class names (metric-actions-menu-item) rather than using the core Dropdown/menu-item primitives already imported. This diverges from the design-system convention and relies on separate CSS. Consider using the core component menu items for consistency and accessibility (focus/keyboard handling).

Was this helpful? React with 👍 / 👎

@gitar-bot

gitar-bot Bot commented Jul 2, 2026

Copy link
Copy Markdown
Code Review ⚠️ Changes requested 0 resolved / 2 findings

Updates the metric ontology and workflow header, but requires fixing non-functional rename/delete actions and replacing raw buttons with core UI components.

⚠️ Bug: Rename/Delete actions in metric menu are non-functional

📄 openmetadata-ui/src/main/resources/ui/src/pages/MetricsPage/MetricListPage/MetricListHeader.tsx:117-131

In MetricListHeader.tsx the actions dropdown renders four items, but the "Rename" (lines 117-129) and "Delete" (lines 130-144) <button> elements have no onClick handler and no disabled state. They are always shown to users with permission.EditAll, so clicking them does nothing — a broken/dead UI action from the user's perspective. Either wire up the handlers (pass onRename/onDelete props from MetricListPage) or omit these items until they are implemented.

💡 Quality: Export/import menu items use raw instead of core components

📄 openmetadata-ui/src/main/resources/ui/src/pages/MetricsPage/MetricListPage/MetricListHeader.tsx:82-96

The frontend guidelines call for prioritizing openmetadata-ui-core-components over ad-hoc elements. MetricListHeader.tsx builds the dropdown menu items as raw <button> elements with custom class names (metric-actions-menu-item) rather than using the core Dropdown/menu-item primitives already imported. This diverges from the design-system convention and relies on separate CSS. Consider using the core component menu items for consistency and accessibility (focus/keyboard handling).

🤖 Prompt for agents
Code Review: Updates the metric ontology and workflow header, but requires fixing non-functional rename/delete actions and replacing raw buttons with core UI components.

1. ⚠️ Bug: Rename/Delete actions in metric menu are non-functional
   Files: openmetadata-ui/src/main/resources/ui/src/pages/MetricsPage/MetricListPage/MetricListHeader.tsx:117-131

   In `MetricListHeader.tsx` the actions dropdown renders four items, but the "Rename" (lines 117-129) and "Delete" (lines 130-144) `<button>` elements have no `onClick` handler and no `disabled` state. They are always shown to users with `permission.EditAll`, so clicking them does nothing — a broken/dead UI action from the user's perspective. Either wire up the handlers (pass `onRename`/`onDelete` props from `MetricListPage`) or omit these items until they are implemented.

2. 💡 Quality: Export/import menu items use raw <button> instead of core components
   Files: openmetadata-ui/src/main/resources/ui/src/pages/MetricsPage/MetricListPage/MetricListHeader.tsx:82-96

   The frontend guidelines call for prioritizing `openmetadata-ui-core-components` over ad-hoc elements. `MetricListHeader.tsx` builds the dropdown menu items as raw `<button>` elements with custom class names (`metric-actions-menu-item`) rather than using the core `Dropdown`/menu-item primitives already imported. This diverges from the design-system convention and relies on separate CSS. Consider using the core component menu items for consistency and accessibility (focus/keyboard handling).

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

Comment on lines +123 to +151
{t('label.rename')}
</span>
<span className="metric-actions-description">
{t('message.metrics-rename-collection-description')}
</span>
</span>
</button>
<button
className="metric-actions-menu-item metric-actions-menu-item-danger"
type="button">
<span className="metric-actions-icon">
<Trash01 size={18} />
</span>
<span>
<span className="metric-actions-title">
{t('label.delete')}
</span>
<span className="metric-actions-description">
{t('message.metrics-delete-collection-description')}
</span>
</span>
</button>
</div>
</Dropdown.Popover>
</Dropdown.Root>
)}
</div>
</div>
);

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 Non-functional Rename and Delete buttons

The Rename (line 123) and Delete (line 136) buttons render with no onClick handler and no corresponding props in MetricListHeaderProps. Clicking them is a no-op. While these stubs existed in the original MetricListPage.tsx, extracting them into a formally typed component API makes the gap more visible — any Collate override that calls onRename/onDelete would need to add them to the interface. If these are intentional placeholders for future work, a // TODO comment with the tracking issue would clarify intent; if they're truly dead UI, they should be removed so the component matches its own contract.

Comment on lines +17 to +20
} from '../pages/OntologyExplorerPage/OntologyExplorerHeader';


class OntologyExplorerClassBase {

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 Extra blank line between the import block and the class declaration — Prettier/ESLint will flag this in CI.

Suggested change
} from '../pages/OntologyExplorerPage/OntologyExplorerHeader';
class OntologyExplorerClassBase {
} from '../pages/OntologyExplorerPage/OntologyExplorerHeader';
class OntologyExplorerClassBase {

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!

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant