diff --git a/web/common/src/components/Lineage/LineageColumnLevel/FactoryColumn.tsx b/web/common/src/components/Lineage/LineageColumnLevel/FactoryColumn.tsx
index 294d3ca462..3b83288615 100644
--- a/web/common/src/components/Lineage/LineageColumnLevel/FactoryColumn.tsx
+++ b/web/common/src/components/Lineage/LineageColumnLevel/FactoryColumn.tsx
@@ -233,7 +233,7 @@ export function FactoryColumn<
{type}
}
className={cn(
- 'FactoryColumn__Metadata relative overflow-visible group',
+ 'FactoryColumn__Metadata relative overflow-visible',
isDisabledColumn && 'cursor-not-allowed',
className,
)}
diff --git a/web/common/src/components/Lineage/LineageColumnLevel/help.ts b/web/common/src/components/Lineage/LineageColumnLevel/help.ts
index fe75ed162a..0966308a72 100644
--- a/web/common/src/components/Lineage/LineageColumnLevel/help.ts
+++ b/web/common/src/components/Lineage/LineageColumnLevel/help.ts
@@ -236,9 +236,9 @@ export function calculateColumnsHeight({
const hasColumns = columnsCount > 0
const columnHeight = 24 // tailwind h-6
const columnsTopSeparator = 1
- const columnSeparator = 1
+ const columnSeparator = 0
const columnsContainerPadding = 4
- const columnsPadding = 4
+ const columnsPadding = 0
const columnsFilterHeight = hasColumnsFilter && hasColumns ? columnHeight : 0
const columnsSeparators = columnsCount > 1 ? columnsCount - 1 : 0
diff --git a/web/common/src/components/Lineage/LineageContext.ts b/web/common/src/components/Lineage/LineageContext.ts
index 7c76c2cfd4..10ed0a1e1a 100644
--- a/web/common/src/components/Lineage/LineageContext.ts
+++ b/web/common/src/components/Lineage/LineageContext.ts
@@ -64,7 +64,6 @@ export interface LineageContextValue<
>
currentNodeId: TNodeID | null
selectedNode: LineageNode | null
- currentNode: LineageNode | null
}
export function getInitial<
@@ -89,7 +88,6 @@ export function getInitial<
selectedNodeId: null,
selectedNode: null,
currentNodeId: null,
- currentNode: null,
}
}
diff --git a/web/common/src/components/Lineage/LineageLayout.tsx b/web/common/src/components/Lineage/LineageLayout.tsx
index e19046780a..32cb989d31 100644
--- a/web/common/src/components/Lineage/LineageLayout.tsx
+++ b/web/common/src/components/Lineage/LineageLayout.tsx
@@ -35,14 +35,11 @@ export function LineageLayout<
edgeTypes,
className,
controls,
- nodesDraggable,
- nodesConnectable,
isBuildingLayout,
useLineage,
onNodeClick,
onNodeDoubleClick,
showControlOnlySelectedNodes,
- showControlZoomToCurrentNode,
showControlZoomToSelectedNode,
}: {
useLineage: LineageContextHook<
@@ -59,10 +56,7 @@ export function LineageLayout<
nodeTypes?: NodeTypes
edgeTypes?: EdgeTypes
className?: string
- nodesDraggable?: boolean
- nodesConnectable?: boolean
showControlOnlySelectedNodes?: boolean
- showControlZoomToCurrentNode?: boolean
showControlZoomToSelectedNode?: boolean
controls?:
| React.ReactNode
@@ -85,14 +79,11 @@ export function LineageLayout<
diff --git a/web/common/src/components/Lineage/LineageLayoutBase.tsx b/web/common/src/components/Lineage/LineageLayoutBase.tsx
index 93a55858bb..45c4db8116 100644
--- a/web/common/src/components/Lineage/LineageLayoutBase.tsx
+++ b/web/common/src/components/Lineage/LineageLayoutBase.tsx
@@ -2,9 +2,7 @@ import {
Background,
BackgroundVariant,
Controls,
- type EdgeChange,
type EdgeTypes,
- type NodeChange,
type NodeTypes,
ReactFlow,
type SetCenter,
@@ -13,14 +11,12 @@ import {
getOutgoers,
useReactFlow,
useViewport,
- applyNodeChanges,
- applyEdgeChanges,
} from '@xyflow/react'
import '@xyflow/react/dist/style.css'
import './Lineage.css'
-import { CircuitBoard, Crosshair, LocateFixed, RotateCcw } from 'lucide-react'
+import { CircuitBoard, LocateFixed, RotateCcw } from 'lucide-react'
import React from 'react'
import { type LineageContextHook } from './LineageContext'
@@ -60,13 +56,10 @@ export function LineageLayoutBase<
edgeTypes,
className,
controls,
- nodesDraggable = false,
- nodesConnectable = false,
useLineage,
onNodeClick,
onNodeDoubleClick,
showControlOnlySelectedNodes = true,
- showControlZoomToCurrentNode = true,
showControlZoomToSelectedNode = true,
}: {
useLineage: LineageContextHook<
@@ -79,13 +72,10 @@ export function LineageLayoutBase<
TSourceHandleID,
TTargetHandleID
>
- nodesDraggable?: boolean
- nodesConnectable?: boolean
nodeTypes?: NodeTypes
edgeTypes?: EdgeTypes
className?: string
showControlOnlySelectedNodes?: boolean
- showControlZoomToCurrentNode?: boolean
showControlZoomToSelectedNode?: boolean
controls?:
| React.ReactNode
@@ -103,74 +93,20 @@ export function LineageLayoutBase<
const { setCenter } = useReactFlow()
const {
- currentNode,
zoom,
- nodes: initialNodes,
+ nodes,
edges,
- setEdges,
selectedNode,
showOnlySelectedNodes,
selectedNodeId,
setZoom,
- setSelectedNodeId,
setShowOnlySelectedNodes,
setSelectedNodes,
setSelectedEdges,
} = useLineage()
- const [nodes, setNodes] =
- React.useState[]>(initialNodes)
-
- const onNodesChange = React.useCallback(
- (changes: NodeChange>[]) => {
- setNodes(applyNodeChanges(changes, nodes))
- },
- [nodes],
- )
-
- const onEdgesChange = React.useCallback(
- (
- changes: EdgeChange<
- LineageEdge<
- TEdgeData,
- TEdgeID,
- TSourceID,
- TTargetID,
- TSourceHandleID,
- TTargetHandleID
- >
- >[],
- ) => {
- setEdges(
- applyEdgeChanges<
- LineageEdge<
- TEdgeData,
- TEdgeID,
- TSourceID,
- TTargetID,
- TSourceHandleID,
- TTargetHandleID
- >
- >(changes, edges),
- )
- },
- [edges],
- )
-
const updateZoom = React.useMemo(() => debounce(setZoom, 200), [setZoom])
- const zoomToCurrentNode = React.useCallback(
- (zoom: number = DEFAULT_ZOOM) => {
- if (currentNode) {
- setCenter(currentNode.position.x, currentNode.position.y, {
- zoom,
- duration: 0,
- })
- }
- },
- [currentNode?.position.x, currentNode?.position.y],
- )
-
const zoomToSelectedNode = React.useCallback(
(zoom: number = DEFAULT_ZOOM) => {
if (selectedNode) {
@@ -195,13 +131,13 @@ export function LineageLayoutBase<
return Array.from(
new Set>([
node,
- ...getIncomers(node, initialNodes, edges)
+ ...getIncomers(node, nodes, edges)
.map(n => getAllIncomers(n, visited))
.flat(),
]),
)
},
- [initialNodes, edges],
+ [nodes, edges],
)
const getAllOutgoers = React.useCallback(
@@ -216,13 +152,13 @@ export function LineageLayoutBase<
return Array.from(
new Set>([
node,
- ...getOutgoers(node, initialNodes, edges)
+ ...getOutgoers(node, nodes, edges)
.map(n => getAllOutgoers(n, visited))
.flat(),
]),
)
},
- [initialNodes, edges],
+ [nodes, edges],
)
const connectedNodes = React.useMemo(() => {
@@ -233,12 +169,8 @@ export function LineageLayoutBase<
...getAllOutgoers(selectedNode),
]
- if (currentNode) {
- all.push(currentNode)
- }
-
return all
- }, [selectedNode, currentNode, getAllIncomers, getAllOutgoers])
+ }, [selectedNode, getAllIncomers, getAllOutgoers])
const connectedEdges = React.useMemo(() => {
return getConnectedEdges<
@@ -254,19 +186,11 @@ export function LineageLayoutBase<
>(connectedNodes, edges)
}, [connectedNodes, edges])
- React.useEffect(() => {
- setNodes(initialNodes)
- }, [initialNodes])
-
React.useEffect(() => {
if (selectedNodeId == null) {
setShowOnlySelectedNodes(false)
setSelectedNodes(new Set())
setSelectedEdges(new Set())
- } else {
- if (selectedNode == null) {
- setSelectedNodeId(null)
- }
}
}, [selectedNodeId, selectedNode])
@@ -317,17 +241,12 @@ export function LineageLayoutBase<
edges={edges}
nodeTypes={nodeTypes}
edgeTypes={edgeTypes}
- onNodesChange={onNodesChange}
- onEdgesChange={onEdgesChange}
- nodesDraggable={nodesDraggable}
- nodesConnectable={nodesConnectable}
zoomOnDoubleClick={false}
panOnScroll={true}
zoomOnScroll={true}
minZoom={nodes.length > NODES_TRESHOLD ? NODES_TRESHOLD_ZOOM : MIN_ZOOM}
maxZoom={MAX_ZOOM}
fitView={false}
- nodeOrigin={[0.5, 0.5]}
onlyRenderVisibleElements
onNodeClick={onNodeClick}
onNodeDoubleClick={onNodeDoubleClick}
@@ -346,14 +265,6 @@ export function LineageLayoutBase<
position="top-right"
className="m-1 border-2 border-lineage-control-border rounded-sm overflow-hidden"
>
- {currentNode && showControlZoomToCurrentNode && (
- zoomToCurrentNode(DEFAULT_ZOOM)}
- >
-
-
- )}
{selectedNodeId && (
<>
{showControlOnlySelectedNodes && (
diff --git a/web/common/src/components/Lineage/help.ts b/web/common/src/components/Lineage/help.ts
index e8041d9f56..63a7c049c5 100644
--- a/web/common/src/components/Lineage/help.ts
+++ b/web/common/src/components/Lineage/help.ts
@@ -41,17 +41,17 @@ export function getTransformedNodes<
adjacencyListKeys: TAdjacencyListKey[],
lineageDetails: LineageDetails,
transformNode: TransformNodeFn,
+ allNodesMap?: LineageNodesMap,
): LineageNodesMap {
const nodesCount = adjacencyListKeys.length
const nodesMap: LineageNodesMap = Object.create(null)
for (let i = 0; i < nodesCount; i++) {
const adjacencyListKey = adjacencyListKeys[i]
- const encodedNodeId = toNodeID(adjacencyListKey)
- nodesMap[encodedNodeId] = transformNode(
- encodedNodeId,
- lineageDetails[adjacencyListKey],
- )
+ const nodeId = toNodeID(adjacencyListKey)
+ nodesMap[nodeId] =
+ allNodesMap?.[nodeId] ||
+ transformNode(nodeId, lineageDetails[adjacencyListKey])
}
return nodesMap
diff --git a/web/common/src/components/Lineage/layout/dagreLayout.ts b/web/common/src/components/Lineage/layout/dagreLayout.ts
index d7a5c01e2e..16f59f495a 100644
--- a/web/common/src/components/Lineage/layout/dagreLayout.ts
+++ b/web/common/src/components/Lineage/layout/dagreLayout.ts
@@ -21,6 +21,7 @@ export function buildLayout<
>({
edges,
nodesMap,
+ shouldReuseExistingPosition = true,
}: {
edges: LineageEdge<
TEdgeData,
@@ -31,6 +32,7 @@ export function buildLayout<
TTargetHandleID
>[]
nodesMap: LineageNodesMap
+ shouldReuseExistingPosition?: boolean
}) {
const nodes = Object.values(nodesMap)
const nodeCount = nodes.length
@@ -46,7 +48,7 @@ export function buildLayout<
g.setGraph({
rankdir: 'LR',
- nodesep: 0,
+ nodesep: 12,
ranksep: 48,
edgesep: 0,
ranker: 'longest-path',
@@ -78,12 +80,19 @@ export function buildLayout<
const nodeWithPosition = g.node(nodeId)
const halfWidth = width / 2
const halfHeight = height / 2
+ const isDefaultPosition = node.position.x === 0 && node.position.y === 0
nodesMap[nodeId] = {
...node,
position: {
- x: nodeWithPosition.x - halfWidth,
- y: nodeWithPosition.y - halfHeight,
+ x:
+ shouldReuseExistingPosition && isDefaultPosition
+ ? nodeWithPosition.x - halfWidth
+ : node.position.x,
+ y:
+ shouldReuseExistingPosition && isDefaultPosition
+ ? nodeWithPosition.y - halfHeight
+ : node.position.y,
},
}
}
diff --git a/web/common/src/components/Lineage/node/useNodeMetadata.tsx b/web/common/src/components/Lineage/node/useNodeMetadata.tsx
index 3601b752fd..72a8be90ba 100644
--- a/web/common/src/components/Lineage/node/useNodeMetadata.tsx
+++ b/web/common/src/components/Lineage/node/useNodeMetadata.tsx
@@ -4,17 +4,14 @@ import {
useNodeConnections,
} from '@xyflow/react'
-import { type LineageNode, type LineageNodeData, type NodeId } from '../utils'
+import { type LineageNodeData, type NodeId } from '../utils'
export type NodeProps =
ReactFlowNodeProps>
-export function useNodeMetadata<
- TNodeData extends LineageNodeData = LineageNodeData,
- TNodeID extends string = NodeId,
->(
+export function useNodeMetadata(
nodeId: TNodeID,
- currentNode: LineageNode | null,
+ currentNodeId: TNodeID | null,
selectedNodeId: TNodeID | null,
selectedNodes: Set,
) {
@@ -29,7 +26,7 @@ export function useNodeMetadata<
const leftId = targets.length > 0 ? nodeId : undefined
const rightId = sources.length > 0 ? nodeId : undefined
- const isCurrent = currentNode?.id === nodeId
+ const isCurrent = currentNodeId === nodeId
const isSelected = selectedNodeId === nodeId
const isActive = selectedNodes.has(nodeId)
diff --git a/web/common/src/components/Lineage/stories/Lineage.stories.tsx b/web/common/src/components/Lineage/stories/Lineage.stories.tsx
index 76c4229250..87a757bbc4 100644
--- a/web/common/src/components/Lineage/stories/Lineage.stories.tsx
+++ b/web/common/src/components/Lineage/stories/Lineage.stories.tsx
@@ -1,5 +1,3 @@
-import type { LineageAdjacencyList, LineageDetails } from '../utils'
-
import { ModelLineage } from './ModelLineage'
import type {
BrandedLineageAdjacencyList,
diff --git a/web/common/src/components/Lineage/stories/ModelLineage.tsx b/web/common/src/components/Lineage/stories/ModelLineage.tsx
index 215ebb1f84..b4a65fd71e 100644
--- a/web/common/src/components/Lineage/stories/ModelLineage.tsx
+++ b/web/common/src/components/Lineage/stories/ModelLineage.tsx
@@ -1,4 +1,4 @@
-import { Focus, LockOpen, Rows2, Rows3, Lock } from 'lucide-react'
+import { Focus, Rows2, Rows3 } from 'lucide-react'
import React from 'react'
import {
@@ -82,7 +82,6 @@ export const ModelLineage = ({
const [zoom, setZoom] = React.useState(ZOOM_THRESHOLD)
const [isBuildingLayout, setIsBuildingLayout] = React.useState(false)
- const [nodesDraggable, setNodesDraggable] = React.useState(false)
const [edges, setEdges] = React.useState<
LineageEdge<
EdgeData,
@@ -311,6 +310,7 @@ export const ModelLineage = ({
})
.catch(error => {
console.error('Layout processing failed:', error)
+
setEdges([])
setNodesMap({})
})
@@ -324,7 +324,6 @@ export const ModelLineage = ({
return Object.values(nodesMap)
}, [nodesMap])
- const currentNode = currentNodeId ? nodesMap[currentNodeId] : null
const selectedNode = selectedNodeId ? nodesMap[selectedNodeId] : null
const handleReset = React.useCallback(() => {
@@ -384,7 +383,6 @@ export const ModelLineage = ({
edges,
nodes,
nodesMap,
- currentNode,
setFetchingColumns,
setColumnLevelLineage,
setShowColumns,
@@ -412,7 +410,6 @@ export const ModelLineage = ({
nodeTypes={nodeTypes}
edgeTypes={edgeTypes}
className={className}
- nodesDraggable={nodesDraggable}
controls={
<>
- setNodesDraggable(prev => !prev)}
- disabled={isBuildingLayout}
- >
-
-
>
}
/>
diff --git a/web/common/src/components/Lineage/stories/ModelNode.tsx b/web/common/src/components/Lineage/stories/ModelNode.tsx
index 8dbcc5fc19..4af804aad2 100644
--- a/web/common/src/components/Lineage/stories/ModelNode.tsx
+++ b/web/common/src/components/Lineage/stories/ModelNode.tsx
@@ -51,7 +51,7 @@ export const ModelNode = React.memo(function ModelNode({
const {
selectedColumns,
zoom,
- currentNode,
+ currentNodeId,
selectedNodeId,
selectedNodes,
showColumns,
@@ -70,7 +70,7 @@ export const ModelNode = React.memo(function ModelNode({
isCurrent,
isSelected, // if selected from inside the lineage and node is selcted
isActive, // if selected from inside the lineage and node is not selected but in path
- } = useNodeMetadata(nodeId, currentNode, selectedNodeId, selectedNodes)
+ } = useNodeMetadata(nodeId, currentNodeId, selectedNodeId, selectedNodes)
const {
columns,
@@ -132,7 +132,7 @@ export const ModelNode = React.memo(function ModelNode({
({
)}