Repository navigation
Fixes #33865: Inline lineage editing via node and column menus - #34551
chirag-madlani wants to merge 75 commits into
Conversation
Add canEditLineage to the lineage store, computed from hasEditAccess, deleted, platformView, entity type, and scene band instead of the isEditMode toggle. Remove the Edit Lineage button from CustomControls; gate the edge overlay buttons, node connectability, delete-key handler, and drag-drop sidebar on canEditLineage/canEditScene. isEditMode stays in the store but nothing sets it anymore.
Add a node-delete confirmation dialog, route node removal (menu and the temporary-node remove button) through it, and make Delete/Backspace open the node or edge confirmation instead of deleting immediately.
Standalone, props-driven AddLineagePopover: step 1 entity type (filtered to TABLE and DASHBOARD_DATA_MODEL when opened from a column, since those are the only search hit shapes getEntityChildrenAndLabel can flatten via its getTableEntityChildren resolver), step 2 entity search excluding the current node, step 3 column picker only when opened from a column. Picking the final value submits immediately (no Add button); placement is left for upstream, right for downstream, no arrow. Task 6 will mount this in LineageMap.
Adds LineageNodeMenu (a per-node dots menu) and mounts it in CustomNodeV1 in place of the already-dead always-there remove button. Wires LineageMap to open the shared AddLineagePopover from the menu's Edit Upstream/Edit Downstream actions and route Delete through the existing node-delete confirmation. Closes the popover on canvas pan/zoom.
SceneDrillButton is absolutely positioned over the same top-right corner as the new node ⋮ menu, so it always painted on top and swallowed the click. Shift the drill button left via a has-lineage-node-menu modifier class whenever the menu renders, and give the menu trigger an explicit 24x24 size so the offset matches its real footprint.
Dropdown.DotsButton is a plain function component with no forwardRef, so
ref={triggerRef} placed on it never attached in React 18 and the popover
fell back to the viewport origin. Anchor the ref to the wrapper div both
LineageNodeMenu and LineageColumnMenu already own instead.
Without edit mode an edge click opens the modal edge drawer, which hid the floating edit/delete toolbar. Editors now get Edit Pipeline / Delete from a menu in the drawer header; the canvas toolbar is removed. Also fixes issues edit mode used to mask: - edge clicks also reached the pane click handler and cleared the selection, so aggregated edges never opened the drawer - a direct load of the Field band lost its column layer to the default layer setting, collapsing column lists and hiding metric column edges - adding a column edge at the Field band always exhausted the scene refetch retries because the confirmation only matched entity edges
- Delete key on a selected node matched a drawer copy by reference and never fired; match by entity id and only offer it for removable, non-root nodes - Delete key on a selected edge ignored editability, letting rollup edges reach the delete confirmation; require an editable edge - Dropdown.DotsButton now honours a caller's aria-label, so lineage node, column and edge-drawer menus announce their purpose instead of "Open menu" - The add-lineage popover title names its dialog - Replace suppressed hook deps in NodeChildren with the real dependencies - Read-only lineage checks wait for rendered nodes before asserting no menu
Lineage is added from the node and column menus, so the connectable handles on each node side are no longer needed. The expand/collapse buttons keep their handle placement classes. Removes the unused drag-connect path and the dead buildConnectPayload helper.
…oads The asset band fetches no field payloads, so tables, topics, dashboards and other field-bearing kinds were reported as non-expandable and semantic zoom could not drill into them.
- Container nodes (service/database/schema/domain/data product) render logo + name, a 'Type · kind' subtitle and a child count pill, at a fixed width by node type - Control bar: mini-map toggle state, zoom level, fit to screen replaces fullscreen, aria-labels - Semantic zoom drills only into the node under the pointer and shows a toast when that node has no deeper level - Hover via ReactFlow node events, full-graph loading overlay, ReactFlow as the canvas root with pan-on-focus
✅ PR checks passedThe linked issue has a description and all required Shipping project fields set. Thanks! |
🔄 Playwright impact map auto-refreshedThis PR touched specs or UI source that changed the source→spec routing map. I regenerated What is this file? It is the auto-generated half of Playwright's PR planner. It routes "if source X changes, run specs Y" by walking spec imports and cross-referencing What if I want to regenerate locally instead? Run this before pushing your next change to skip the bot commit: python3 .github/scripts/generate_playwright_impact_map.py
git add .github/playwright/impact-map.generated.json
git commit --amend --no-edit # or a separate commit |
# Conflicts: # openmetadata-ui/src/main/resources/ui/eslint-rules/openmetadata-antd.test.mjs # openmetadata-ui/src/main/resources/ui/src/components/Lineage/LineageMap/LineageMap.component.tsx # openmetadata-ui/src/main/resources/ui/src/components/Lineage/LineageMap/LineageMap.utils.test.ts # openmetadata-ui/src/main/resources/ui/src/components/Lineage/LineageMap/LineageMap.utils.ts
🚦 Removed from the merge queue —
|
# Conflicts: # openmetadata-ui/src/main/resources/ui/eslint-rules/openmetadata-antd.test.mjs # openmetadata-ui/src/main/resources/ui/src/components/Lineage/LineageMap/LineageMap.component.tsx
🚦 Removed from the merge queue —
|
Resolves the overlap with the antd-to-core migration (#35280): keeps this branch's versions of LineageConfigModal, LineageSearchSelect, NodeChildren, AddPipeLineModal and PlatformLineage (with main's aria-labels added), restores the two node-paging constants LineageSearchSelect still uses, drops EntitySuggestionOption, and prunes the antd suppression baseline to 244.
🔄 Playwright impact map auto-refreshedThis PR touched specs or UI source that changed the source→spec routing map. I regenerated What is this file? It is the auto-generated half of Playwright's PR planner. It routes "if source X changes, run specs Y" by walking spec imports and cross-referencing What if I want to regenerate locally instead? Run this before pushing your next change to skip the bot commit: python3 .github/scripts/generate_playwright_impact_map.py
git add .github/playwright/impact-map.generated.json
git commit --amend --no-edit # or a separate commit |
|
| Count | Rule |
|---|---|
| 12 | react-hooks/exhaustive-deps |
| 4 | openmetadata-imports/no-impure-pure-utils |
All findings
| Location | Rule | Message | |
|---|---|---|---|
| 🟡 | src/components/Entity/EntityInfoDrawer/EdgeInfoDrawer.component.tsx:316:5 |
react-hooks/exhaustive-deps |
React Hook useCallback has a missing dependency: 'onEdgeDetailsUpdate'. Either include it or remove the dependency array. If 'onEdgeDetailsUpdate' changes too o |
| 🟡 | src/components/Entity/EntityInfoDrawer/EdgeInfoDrawer.component.tsx:362:5 |
react-hooks/exhaustive-deps |
React Hook useCallback has a missing dependency: 'onEdgeDetailsUpdate'. Either include it or remove the dependency array. If 'onEdgeDetailsUpdate' changes too o |
| 🟡 | src/components/Entity/EntityInfoDrawer/EdgeInfoDrawer.component.tsx:427:6 |
react-hooks/exhaustive-deps |
React Hook useMemo has a missing dependency: 't'. Either include it or remove the dependency array. |
| 🟡 | src/components/Entity/EntityInfoDrawer/EdgeInfoDrawer.component.tsx:480:5 |
react-hooks/exhaustive-deps |
React Hook useCallback has a missing dependency: 'onEdgeDetailsUpdate'. Either include it or remove the dependency array. If 'onEdgeDetailsUpdate' changes too o |
| 🟡 | src/components/Entity/EntityInfoDrawer/EdgeInfoDrawer.component.tsx:487:6 |
react-hooks/exhaustive-deps |
React Hook useEffect has a missing dependency: 'getEdgeInfo'. Either include it or remove the dependency array. |
| 🟡 | src/components/Entity/EntityLineage/AppPipelineModel/AddPipeLineModal.tsx:120:28 |
react-hooks/exhaustive-deps |
React Hook useCallback received a function whose dependencies are unknown. Pass an inline function instead. |
| 🟡 | src/components/Entity/EntityLineage/AppPipelineModel/AddPipeLineModal.tsx:129:6 |
react-hooks/exhaustive-deps |
React Hook useEffect has missing dependencies: 'edgeSearchValue' and 'getSearchResults'. Either include them or remove the dependency array. |
| 🟡 | src/components/Entity/EntityLineage/CanvasButtonPopover.component.tsx:51:6 |
react-hooks/exhaustive-deps |
React Hook useCallback has missing dependencies: 'hoverTimeoutRef' and 'isOverPopoverRef'. Either include them or remove the dependency array. |
| 🟡 | src/components/Entity/EntityLineage/CustomNodeV1.component.tsx:383:6 |
react-hooks/exhaustive-deps |
React Hook useMemo has an unnecessary dependency: 'onSceneNodeSelect'. Either exclude it or remove the dependency array. |
| 🟡 | src/components/Entity/EntityLineage/NodeChildren/VirtualColumnList.component.tsx:157:5 |
react-hooks/exhaustive-deps |
React Hook useCallback has an unnecessary dependency: 'selectedColumn'. Either exclude it or remove the dependency array. |
| 🟡 | src/components/Lineage/EntityLineageCanvas/EntityLineageCanvas.tsx:131:6 |
react-hooks/exhaustive-deps |
React Hook useEffect has a missing dependency: 'updateEntityData'. Either include it or remove the dependency array. |
| 🟡 | src/hooks/useLineageEdgeColors.ts:42:6 |
react-hooks/exhaustive-deps |
React Hook useMemo has an unnecessary dependency: 'theme'. Either exclude it or remove the dependency array. |
| 🟡 | src/utils/EntityLineagePureUtils.ts:17:1 |
openmetadata-imports/no-impure-pure-utils |
Pure utilities must not depend on React, UI, state, hooks, pages, or REST clients. Move orchestration/rendering out or move shared types to a lower layer. |
| 🟡 | src/utils/EntityLineagePureUtils.ts:19:1 |
openmetadata-imports/no-impure-pure-utils |
Pure utilities must not depend on React, UI, state, hooks, pages, or REST clients. Move orchestration/rendering out or move shared types to a lower layer. |
| 🟡 | src/utils/EntityLineagePureUtils.ts:24:1 |
openmetadata-imports/no-impure-pure-utils |
Pure utilities must not depend on React, UI, state, hooks, pages, or REST clients. Move orchestration/rendering out or move shared types to a lower layer. |
| 🟡 | src/utils/EntityLineagePureUtils.ts:45:1 |
openmetadata-imports/no-impure-pure-utils |
Pure utilities must not depend on React, UI, state, hooks, pages, or REST clients. Move orchestration/rendering out or move shared types to a lower layer. |
Fix locally (fast - only checks files changed in this branch):
make ui-checkstyle-changedLint baselines only: takes main's antd suppressions (#35253), prunes the two entries for lineage files this branch deleted, and sets the count to 146.
🚦 Removed from the merge queue —
|
🚦 Removed from the merge queue —
|
- ImpactAnalysis: match "Asset Level" exactly; the Layers trigger now reads "Data Asset Level" - ContextCenterMemories: the asset search escapes Elasticsearch-reserved characters, so compare the unescaped query - MetricBulkImportExportEdit: Dropdown.DotsButton keeps the caller's aria-label, so the metrics menu is named "Actions", not "Open menu" - LineageInteraction: fire the column click in place; the minimap can cover the column after fit - PlatformLineage: pick a depth different from the current one; the global lineage settings are shared with other specs
|
🚦 Removed from the merge queue —
|
| "lineage-map-field-count": "{{count}} fields", | ||
| "lineage-map-onboarding-altitude-description": "Overview -> group -> tables -> columns. Zooming changes detail, like Maps country -> city -> street.", | ||
| "lineage-map-onboarding-description": "Today, zoom only scales pixels. Here, two separate controls keep you oriented in graphs of any size.", | ||
| "lineage-map-onboarding-description": "Navigate lineage like a map. Pan freely, zoom in or out to adjust your level of detail, or switch between different views", |
There was a problem hiding this comment.
💡 Quality: sv-se onboarding description still has the old copy
This commit rewrote message.lineage-map-onboarding-description in every locale. The old copy said "Today, zoom only scales pixels..." and the new copy is "Navigate lineage like a map...". sv-se.json was skipped (that's why its diff is +13/-1 instead of +14/-2), so line 4852 still describes the old behaviour. Swedish users will see onboarding text that no longer matches the feature. Update the sv-se value to a translation of the new en-us string.
Translate the updated en-us onboarding description for sv-se:
"lineage-map-onboarding-description": "Navigera i datahärkomsten som på en karta. Panorera fritt, zooma in eller ut för att justera detaljnivån eller växla mellan olika vyer",
- Apply fix
Check the box to apply the fix or reply for a change | Was this helpful? React with 👍 / 👎
Code Review 👍 Approved with suggestions 3 closed / 4 findings🟡 Medium risk · Inline node and column menus add or delete persisted lineage links, so mistaken selections could remove valid relationships from asset graphs. Replaces lineage edit mode with inline ⋮ menu editing on nodes and columns, adds delete confirmation, and makes the platform Lineage page view and export only. Popover search errors, failed node deletes, and duplicate error toasts on failed adds are resolved.
💡 Quality: sv-se onboarding description still has the old copy📄 openmetadata-ui/src/main/resources/ui/src/locale/languages/sv-se.json:4852 📄 openmetadata-ui/src/main/resources/ui/src/locale/languages/en-us.json:4852 This commit rewrote Translate the updated en-us onboarding description for sv-se✅ 3 closed✅ Edge Case: Popover search ignores errors and can show results for the old type
✅ Bug: Failed node delete causes an unhandled rejection and leaves the canvas half-updated
✅ Bug: A failed add-lineage request shows two error toasts
🤖 Prompt for agentsVerificationRules No rules evaluated Functional validation Not enabledAuto-approval Not enabledFor more verification details, comment OptionsDisplay: compact → Showing compact verification results. Comment with these commands to change the behavior for this request:
Was this helpful? React with 👍 / 👎 | Powered by Gitar — free for open source |



Describe your changes:
Fixes #33865, #25265
Replaces lineage edit mode with inline editing, so users add or remove lineage directly from the graph, without switching modes or dragging nodes. Asset Lineage tabs use the classic lineage graph with inline editing. The platform Lineage page (
/lineage) keeps the hierarchical scene map and is view and export only.Type of change:
High-level design:
AddLineagePopover, a slide-out panel built fromFilterSelect+DataAssetAsyncSelectList, with a column picker for column targets. Deleting a node asks for confirmation; Delete / Backspace removes the selected node or edge. Edge actions (Edit Pipeline, Delete) live in the edge drawer.NodeSuggestionsandLineageNodeRemoveButtonstay unchanged because Collate's ER diagram still imports them; their removal is tracked in Remove NodeSuggestions and LineageNodeRemoveButton once Collate ER diagram stops using them #35330.LineageSceneHierarchy.isExpandabletreats field-bearing kinds (table, topic, dashboard, container…) as expandable even though the asset band carries no field payloads.Tests:
Use cases covered
/lineagepage view, search and exportUnit tests
src/components/Lineage/**,src/components/Entity/EntityLineage/**,src/utils/Lineage/**), including the newLineage.integration.test.tsxcase for the duplicate fetch (fails without the fix: 2 calls),edgeMutations.test.ts(single error toast on a failed add) andLineageColumnMenu.test.tsxdropdown.dots-button.test.tsxLineageSceneResolverTest#assetSceneMarksFieldBearingAssetsExpandableWithoutFieldPayloadsBackend integration tests
Ingestion integration tests
Playwright (UI) tests
LineageInteraction,LineageControls,LineageFilters,DataAssetLineage,PlatformLineage,LineageExportPNGSnapshot; helpers inplaywright/utils/lineage.tschromium:DataAssetLineage(101),LineagePipelineAnnotator(5),LineageExportPNGSnapshot(1),LineageFilters(15),PlatformLineage(2)Basic:LineageInteraction(25),LineageControls,LineageNodePagination,LineageRightPanel,PlatformLineage(4),LineageSettingsManual testing performed
dim_customer, added an upstream from the node menu, switched to the Column layer, added a column edge from the column menu, then deleted both nodes from the node menuUI screen recording / screenshots:
lineage-inline-editing.mp4
lineage-inline-editingatdd06eb7ddf2(after the main merge and the review fixes).collate_server, MySQL and Elasticsearch containers healthy;/api/v1/system/versionreturned 200) with the repository sample data. That server image predates this branch, so theLineageSceneHierarchychange is covered by the Java unit test above rather than the recording.customers; Layers → Column; column ⋮ → Edit Downstream →customer_profile.customer_id; node ⋮ → Delete for both added nodes; platform Lineage page → Export. Each save and delete was asserted against the API response, and the added edges were removed afterwards. Light and dark (AI mode) screenshots of the reviewed screens were checked on the same build.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: not applicable, no schema changes.
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.
The issue properly describes why the new feature is needed, what's the goal, and how we are building it.
I have updated the documentation.
I have added tests around the new logic.