Skip to content

Commit f02e0dd

Browse files
committed
add option to toggle node dragging
1 parent 8342c37 commit f02e0dd

File tree

3 files changed

+113
-21
lines changed

3 files changed

+113
-21
lines changed

web/common/src/components/Lineage/LineageLayout.tsx

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ import {
22
Background,
33
BackgroundVariant,
44
Controls,
5+
type EdgeChange,
56
type EdgeTypes,
7+
type NodeChange,
68
type NodeTypes,
79
ReactFlow,
810
ReactFlowProvider,
@@ -12,6 +14,10 @@ import {
1214
getOutgoers,
1315
useReactFlow,
1416
useViewport,
17+
useEdgesState,
18+
useNodesState,
19+
applyNodeChanges,
20+
applyEdgeChanges,
1521
} from '@xyflow/react'
1622

1723
import '@xyflow/react/dist/style.css'
@@ -55,6 +61,8 @@ export function LineageLayout<
5561
edgeTypes,
5662
className,
5763
controls,
64+
nodesDraggable,
65+
nodesConnectable,
5866
useLineage,
5967
onNodeClick,
6068
onNodeDoubleClick,
@@ -69,6 +77,8 @@ export function LineageLayout<
6977
nodeTypes?: NodeTypes
7078
edgeTypes?: EdgeTypes
7179
className?: string
80+
nodesDraggable?: boolean
81+
nodesConnectable?: boolean
7282
controls?:
7383
| React.ReactNode
7484
| (({ setCenter }: { setCenter: SetCenter }) => React.ReactNode)
@@ -86,6 +96,8 @@ export function LineageLayout<
8696
<LineageLayoutBase
8797
nodeTypes={nodeTypes}
8898
edgeTypes={edgeTypes}
99+
nodesDraggable={nodesDraggable}
100+
nodesConnectable={nodesConnectable}
89101
className={className}
90102
controls={controls}
91103
useLineage={useLineage}
@@ -107,6 +119,8 @@ function LineageLayoutBase<
107119
edgeTypes,
108120
className,
109121
controls,
122+
nodesDraggable = false,
123+
nodesConnectable = false,
110124
useLineage,
111125
onNodeClick,
112126
onNodeDoubleClick,
@@ -118,6 +132,8 @@ function LineageLayoutBase<
118132
TEdgeID,
119133
TPortID
120134
>
135+
nodesDraggable?: boolean
136+
nodesConnectable?: boolean
121137
nodeTypes?: NodeTypes
122138
edgeTypes?: EdgeTypes
123139
className?: string
@@ -140,8 +156,8 @@ function LineageLayoutBase<
140156
isBuildingLayout,
141157
currentNode,
142158
zoom,
143-
nodes,
144-
edges,
159+
nodes: initialNodes,
160+
edges: initialEdges,
145161
nodesMap,
146162
showOnlySelectedNodes,
147163
selectedNodeId,
@@ -152,6 +168,32 @@ function LineageLayoutBase<
152168
setSelectedEdges,
153169
} = useLineage()
154170

171+
const [nodes, setNodes] = React.useState(initialNodes)
172+
const [edges, setEdges] = React.useState(initialEdges)
173+
174+
const onNodesChange = React.useCallback(
175+
(changes: NodeChange<LineageNode<TNodeData, TNodeID>>[]) => {
176+
setNodes(
177+
applyNodeChanges<LineageNode<TNodeData, TNodeID>>(changes, nodes),
178+
)
179+
},
180+
[nodes, setNodes],
181+
)
182+
183+
const onEdgesChange = React.useCallback(
184+
(
185+
changes: EdgeChange<LineageEdge<TEdgeData, TNodeID, TEdgeID, TPortID>>[],
186+
) => {
187+
setEdges(
188+
applyEdgeChanges<LineageEdge<TEdgeData, TNodeID, TEdgeID, TPortID>>(
189+
changes,
190+
edges,
191+
),
192+
)
193+
},
194+
[edges, setEdges],
195+
)
196+
155197
const updateZoom = React.useMemo(() => debounce(setZoom, 200), [setZoom])
156198

157199
const zoomToCurrentNode = React.useCallback(
@@ -221,6 +263,14 @@ function LineageLayoutBase<
221263
[nodes, edges],
222264
)
223265

266+
React.useEffect(() => {
267+
setNodes(initialNodes)
268+
}, [initialNodes])
269+
270+
React.useEffect(() => {
271+
setEdges(initialEdges)
272+
}, [initialEdges])
273+
224274
React.useEffect(() => {
225275
if (selectedNodeId == null) {
226276
setShowOnlySelectedNodes(false)
@@ -332,8 +382,10 @@ function LineageLayoutBase<
332382
edges={edges}
333383
nodeTypes={nodeTypes}
334384
edgeTypes={edgeTypes}
335-
nodesDraggable={false}
336-
nodesConnectable={false}
385+
onNodesChange={onNodesChange}
386+
onEdgesChange={onEdgesChange}
387+
nodesDraggable={nodesDraggable}
388+
nodesConnectable={nodesConnectable}
337389
zoomOnDoubleClick={false}
338390
panOnScroll={true}
339391
zoomOnScroll={true}

web/common/src/components/Lineage/stories/Lineage.stories.tsx

Lines changed: 47 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,33 +17,56 @@ export const LineageModel = () => {
1717
>
1818
<style>{`
1919
:root {
20+
--color-metadata-label: rgba(100, 100, 100, 1);
21+
--color-metadata-value: rgba(10, 10, 10, 1);
2022
21-
--color-lineage-control-button-tooltip-background: rgba(150, 150, 150, 1);
22-
--color-lineage-control-button-tooltip-foreground: rgba(255, 255, 255, 1);
23+
--color-tooltip-background: rgba(150, 150, 150, 1);
24+
--color-tooltip-foreground: rgba(255, 255, 255, 1);
2325
24-
--color-lineage-divider: rgba(0, 0, 0, 0.1);
25-
--color-lineage-background: rgba(255, 255, 255, 1);
26-
--color-lineage-border: rgba(0, 0, 0, 0.1);
26+
--color-filterable-list-counter-background: rgba(200, 0, 0, 1);
27+
--color-filterable-list-counter-foreground: rgba(255, 255, 255, 1);
28+
--color-filterable-list-input-background: rgba(250, 250, 250, 1);
29+
--color-filterable-list-input-foreground: rgba(0, 0, 0, 1);
30+
--color-filterable-list-input-placeholder: rgba(100, 100, 100, 1);
31+
--color-filterable-list-input-border: rgba(100, 100, 100, 1);
2732
2833
--color-lineage-control-background: rgba(250, 250, 250, 1);
2934
--color-lineage-control-background-hover: rgba(245, 245, 245, 1);
3035
--color-lineage-control-icon-background: rgba(0, 0, 0, 1);
3136
--color-lineage-control-icon-foreground: rgba(255, 255, 255, 1);
37+
--color-lineage-control-button-tooltip-background: rgba(150, 150, 150, 1);
38+
--color-lineage-control-button-tooltip-foreground: rgba(255, 255, 255, 1);
3239
33-
--color-lineage-grid-dot: rgba(0, 0, 0, 1);
40+
--color-model-name-grayscale-link-underline: rgba(125, 125, 125, 1);
41+
--color-model-name-grayscale-link-underline-hover: rgba(125, 125, 125, 1);
42+
--color-model-name-link-underline: rgba(0, 0, 0, 1);
43+
--color-model-name-link-underline-hover: rgba(0, 0, 0, 1);
44+
--color-model-name-catalog: rgba(0, 0, 0, 1);
45+
--color-model-name-schema: rgba(0, 0, 0, 1);
46+
--color-model-name-model: rgba(0, 0, 0, 1);
47+
--color-model-name-grayscale-catalog: rgba(100, 100, 100, 1);
48+
--color-model-name-grayscale-schema: rgba(50, 50, 50, 1);
49+
--color-model-name-grayscale-model: rgba(10, 10, 10, 1);
50+
--color-model-name-copy-icon: rgba(100, 100, 100, 1);
51+
--color-model-name-copy-icon-hover: rgba(125, 125, 125, 1);
52+
53+
--color-lineage-background: rgba(255, 255, 255, 1);
54+
--color-lineage-divider: rgba(0, 0, 0, 0.1);
55+
--color-lineage-border: rgba(0, 0, 0, 0.1);
56+
57+
--color-lineage-grid-dot: rgba(0, 0, 0, 0.1);
3458
35-
--color-lineage-node-appendix-background: transparent;
36-
3759
--color-lineage-node-background: rgba(255, 255, 255, 1);
3860
--color-lineage-node-foreground: rgba(0, 0, 0, 0.75);
61+
--color-lineage-node-selected-border: rgba(0, 120, 120, 0.5);
3962
--color-lineage-node-border: rgba(0, 0, 0, 0.1);
4063
--color-lineage-node-border-hover: rgba(0, 0, 0, 0.2);
4164
42-
--color-lineage-node-selected-border: rgba(0, 120, 120, 0.5);
43-
44-
--color-lineage-node-badge-background: rgba(240, 240, 240, 1);
65+
--color-lineage-node-badge-background: rgba(200, 200, 200, 1);
4566
--color-lineage-node-badge-foreground: rgba(0, 0, 0, 1);
4667
68+
--color-lineage-node-appendix-background: transparent;
69+
4770
--color-lineage-node-type-background-sql: rgba(0, 0, 120, 1);
4871
--color-lineage-node-type-foreground-sql: rgba(0, 0, 120, 1);
4972
--color-lineage-node-type-border-sql: rgba(0, 0, 120, 1);
@@ -52,7 +75,18 @@ export const LineageModel = () => {
5275
--color-lineage-node-type-foreground-python: rgba(120, 0, 120, 1);
5376
--color-lineage-node-type-border-python: rgba(120, 0, 120, 1);
5477
78+
--color-lineage-node-type-background-source: rgba(120, 120, 0, 1);
79+
--color-lineage-node-type-foreground-source: rgba(120, 120, 0, 1);
80+
--color-lineage-node-type-border-source: rgba(120, 120, 0, 1);
81+
82+
--color-lineage-node-type-background-cte-subquery: rgba(120, 120, 120, 1);
83+
--color-lineage-node-type-foreground-cte-subquery: rgba(120, 120, 120, 1);
84+
--color-lineage-node-type-border-cte-subquery: rgba(120, 120, 120, 1);
85+
5586
--color-lineage-node-type-handle-icon-background: rgba(255, 255, 255, 1);
87+
--color-lineage-node-type-handle-icon-foreground: rgba(0, 0, 0, 1);
88+
89+
--color-lineage-edge: rgba(0, 0, 0, 0.1);
5690
5791
--color-lineage-node-port-background: rgba(70, 0, 0, 0.05);
5892
--color-lineage-node-port-handle-source: rgba(70, 0, 0, 1);
@@ -61,15 +95,12 @@ export const LineageModel = () => {
6195
--color-lineage-node-port-edge-target: rgba(130, 0, 0, 1);
6296
6397
--color-lineage-model-column-error-background: rgba(255, 0, 0, 1);
64-
--color-lineage-model-column-source-background: rgba(200, 0, 0, 1);
65-
--color-lineage-model-column-expression-background: rgba(100, 0, 0, 1);
98+
--color-lineage-model-column-source-background: rgba(0, 200, 200, 1);
99+
--color-lineage-model-column-expression-background: rgba(0, 10, 100, 1);
66100
--color-lineage-model-column-error-icon: rgba(255, 0, 0, 1);
67101
--color-lineage-model-column-active: rgba(70, 0, 0, 0.1);
68102
--color-lineage-model-column-icon: rgba(0, 0, 0, 1);
69103
--color-lineage-model-column-icon-active: rgba(0, 0, 0, 1);
70-
71-
--color-filterable-list-counter-background: rgba(200, 0, 0, 1);
72-
--color-filterable-list-counter-foreground: rgba(200, 200, 200, 1);
73104
}
74105
`}</style>
75106
<ModelLineage

web/common/src/components/Lineage/stories/ModelLineage.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { debounce } from 'lodash'
2-
import { Focus, Rows2, Rows3 } from 'lucide-react'
2+
import { Focus, LockOpen, Rows2, Rows3, Lock } from 'lucide-react'
33
import React from 'react'
44

55
import { type ColumnLevelLineageAdjacencyList } from '../LineageColumnLevel/ColumnLevelLineageContext'
@@ -74,6 +74,7 @@ export const ModelLineage = ({
7474
}) => {
7575
const [zoom, setZoom] = React.useState(ZOOM_THRESHOLD)
7676
const [isBuildingLayout, setIsBuildingLayout] = React.useState(false)
77+
const [nodesDraggable, setNodesDraggable] = React.useState(false)
7778
const [edges, setEdges] = React.useState<
7879
LineageEdge<EdgeData, ModelNodeId, ModelEdgeId, ModelColumnID>[]
7980
>([])
@@ -388,6 +389,7 @@ export const ModelLineage = ({
388389
nodeTypes={nodeTypes}
389390
edgeTypes={edgeTypes}
390391
className={className}
392+
nodesDraggable={nodesDraggable}
391393
controls={
392394
<>
393395
<LineageControlButton
@@ -408,6 +410,13 @@ export const ModelLineage = ({
408410
>
409411
<LineageControlIcon Icon={Focus} />
410412
</LineageControlButton>
413+
<LineageControlButton
414+
text={nodesDraggable ? 'Lock nodes' : 'Unlock nodes'}
415+
onClick={() => setNodesDraggable(prev => !prev)}
416+
disabled={isBuildingLayout}
417+
>
418+
<LineageControlIcon Icon={nodesDraggable ? Lock : LockOpen} />
419+
</LineageControlButton>
411420
</>
412421
}
413422
/>

0 commit comments

Comments
 (0)