@truedat/dd 8.14.0 → 8.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -3
- package/src/components/LineageGraph.js +177 -30
- package/src/components/LineageGraphToolbar.js +174 -25
- package/src/components/__tests__/LineageGraph.spec.js +98 -0
- package/src/components/__tests__/LineageGraphInteraction.spec.js +278 -13
- package/src/components/__tests__/LineageGraphToolbar.spec.js +86 -0
- package/src/styles/LineageGraph.less +35 -0
- package/src/utils/__tests__/fixtures/lineageInternalDependencies.json +375 -0
- package/src/utils/__tests__/lineageInternalRoutes.spec.js +202 -0
- package/src/utils/__tests__/lineageLayout.spec.js +6 -6
- package/src/utils/__tests__/lineageViewPreferences.spec.js +27 -0
- package/src/utils/lineageGraph.js +56 -11
- package/src/utils/lineageInternalRoutes.js +389 -0
- package/src/utils/lineageLayout.js +32 -12
- package/src/utils/lineageViewPreferences.js +21 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@truedat/dd",
|
|
3
|
-
"version": "8.14.
|
|
3
|
+
"version": "8.14.1",
|
|
4
4
|
"description": "Truedat Web Data Dictionary",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"module": "src/index.js",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"@testing-library/jest-dom": "^6.6.3",
|
|
55
55
|
"@testing-library/react": "^16.3.0",
|
|
56
56
|
"@testing-library/user-event": "^14.6.1",
|
|
57
|
-
"@truedat/test": "8.14.
|
|
57
|
+
"@truedat/test": "8.14.1",
|
|
58
58
|
"identity-obj-proxy": "^3.0.0",
|
|
59
59
|
"jest": "^29.7.0",
|
|
60
60
|
"redux-saga-test-plan": "^4.0.6"
|
|
@@ -90,5 +90,5 @@
|
|
|
90
90
|
"svg-pan-zoom": "^3.6.2",
|
|
91
91
|
"swr": "^2.3.3"
|
|
92
92
|
},
|
|
93
|
-
"gitHead": "
|
|
93
|
+
"gitHead": "391e4e51eebb33b37b9676e541cda5f6f262e5e7"
|
|
94
94
|
}
|
|
@@ -7,6 +7,14 @@ import Graph from "@truedat/core/components/Graph";
|
|
|
7
7
|
import { EdgeHoverContext } from "@truedat/core/components/graph/ColoredEdge";
|
|
8
8
|
import { backgroundGraph } from "../routines";
|
|
9
9
|
import { layoutVisibleLineageGraph } from "../utils/lineageLayout";
|
|
10
|
+
import {
|
|
11
|
+
applyInternalEdgeRoutes,
|
|
12
|
+
applyInternalNodeLayers,
|
|
13
|
+
} from "../utils/lineageInternalRoutes";
|
|
14
|
+
import {
|
|
15
|
+
readDependencyLayout,
|
|
16
|
+
writeDependencyLayout,
|
|
17
|
+
} from "../utils/lineageViewPreferences";
|
|
10
18
|
import {
|
|
11
19
|
createLineageGraphIndex,
|
|
12
20
|
prepareLineageTopology,
|
|
@@ -49,6 +57,7 @@ import {
|
|
|
49
57
|
applyFieldHandlesToEdges,
|
|
50
58
|
redesignedLineageEdges,
|
|
51
59
|
planLineageEdgeRoutes,
|
|
60
|
+
planExternalLineageEdgeRoutes,
|
|
52
61
|
focusLineageNodes,
|
|
53
62
|
focusLineageEdges,
|
|
54
63
|
focusedLineageGraphForNodeSet,
|
|
@@ -138,6 +147,7 @@ export const LineageGraph = ({
|
|
|
138
147
|
structureId,
|
|
139
148
|
initialViewState,
|
|
140
149
|
}) => {
|
|
150
|
+
const { formatMessage } = useIntl();
|
|
141
151
|
const preparedTopology = useMemo(
|
|
142
152
|
() => prepareLineageTopology(topology),
|
|
143
153
|
[topology],
|
|
@@ -163,6 +173,12 @@ export const LineageGraph = ({
|
|
|
163
173
|
Number.MAX_SAFE_INTEGER,
|
|
164
174
|
);
|
|
165
175
|
|
|
176
|
+
const [dependencyLayout, setDependencyLayout] = useState(() =>
|
|
177
|
+
String(initialViewState?.graphId) === String(graphId) &&
|
|
178
|
+
["compact", "expanded"].includes(initialViewState?.dependencyLayout)
|
|
179
|
+
? initialViewState.dependencyLayout
|
|
180
|
+
: readDependencyLayout(),
|
|
181
|
+
);
|
|
166
182
|
const [activePanel, setActivePanel] = useState(null);
|
|
167
183
|
const [selectedContext, setSelectedContext] = useState(null);
|
|
168
184
|
const [doubleClickExpandsNodes, setDoubleClickExpandsNodes] = useState(false);
|
|
@@ -173,6 +189,7 @@ export const LineageGraph = ({
|
|
|
173
189
|
const [searchInput, setSearchInput] = useState("");
|
|
174
190
|
const [searchTerm, setSearchTerm] = useState("");
|
|
175
191
|
const [systemTypeFilter, setSystemTypeFilter] = useState("");
|
|
192
|
+
const [customDepthGraphKey, setCustomDepthGraphKey] = useState(null);
|
|
176
193
|
const [collapsedGroupIds, setCollapsedGroupIds] = useState(() => new Set());
|
|
177
194
|
const [warnedGroupIds, setWarnedGroupIds] = useState(() => new Set());
|
|
178
195
|
const [pendingExpand, setPendingExpand] = useState(null);
|
|
@@ -180,8 +197,10 @@ export const LineageGraph = ({
|
|
|
180
197
|
() => new Set(),
|
|
181
198
|
);
|
|
182
199
|
const [hoveredNodeId, setHoveredNodeId] = useState(null);
|
|
200
|
+
const [keyboardFocusedNodeId, setKeyboardFocusedNodeId] = useState(null);
|
|
183
201
|
const [hoveredEdgeEndpoints, setHoveredEdgeEndpoints] = useState(null);
|
|
184
202
|
const stageRef = useRef(null);
|
|
203
|
+
const resizeFitTimeoutRef = useRef(null);
|
|
185
204
|
const activeSurfaceRef = useRef(null);
|
|
186
205
|
const restoredViewStateRef = useRef(null);
|
|
187
206
|
const graphReadyRef = useRef(false);
|
|
@@ -222,6 +241,20 @@ export const LineageGraph = ({
|
|
|
222
241
|
setHoveredEdgeEndpoints(null);
|
|
223
242
|
if (loading) setFittedGraphKey(null);
|
|
224
243
|
}, [graphIdForFit, loading]);
|
|
244
|
+
useEffect(() => {
|
|
245
|
+
const fitAfterResize = () => {
|
|
246
|
+
clearTimeout(resizeFitTimeoutRef.current);
|
|
247
|
+
resizeFitTimeoutRef.current = setTimeout(() => {
|
|
248
|
+
setFocusNodeId(null);
|
|
249
|
+
setFitViewRequestKey((requestKey) => (requestKey || 0) + 1);
|
|
250
|
+
}, 80);
|
|
251
|
+
};
|
|
252
|
+
window.addEventListener("resize", fitAfterResize);
|
|
253
|
+
return () => {
|
|
254
|
+
window.removeEventListener("resize", fitAfterResize);
|
|
255
|
+
clearTimeout(resizeFitTimeoutRef.current);
|
|
256
|
+
};
|
|
257
|
+
}, []);
|
|
225
258
|
const duplicateNodeIds = useMemo(
|
|
226
259
|
() => positionedDuplicateNodeIds(groups, resources),
|
|
227
260
|
[groups, resources],
|
|
@@ -258,6 +291,7 @@ export const LineageGraph = ({
|
|
|
258
291
|
return;
|
|
259
292
|
}
|
|
260
293
|
setPendingExpand(null);
|
|
294
|
+
setCustomDepthGraphKey(graphIdForFit);
|
|
261
295
|
layoutAnchorNodeIdRef.current = groupId;
|
|
262
296
|
setCollapsedGroupIds((currentIds) => {
|
|
263
297
|
const nextIds = new Set(currentIds);
|
|
@@ -272,7 +306,7 @@ export const LineageGraph = ({
|
|
|
272
306
|
});
|
|
273
307
|
setFocusNodeId(null);
|
|
274
308
|
},
|
|
275
|
-
[collapsedGroupIds, warnedGroupIds],
|
|
309
|
+
[collapsedGroupIds, warnedGroupIds, graphIdForFit],
|
|
276
310
|
);
|
|
277
311
|
const collapseAllGroups = useCallback((groupIds) => {
|
|
278
312
|
layoutAnchorNodeIdRef.current = null;
|
|
@@ -296,9 +330,9 @@ export const LineageGraph = ({
|
|
|
296
330
|
const resolvedNodeWidth = useMemo(
|
|
297
331
|
() =>
|
|
298
332
|
nodeDesign === "redesigned"
|
|
299
|
-
? lineageNodeContentWidth(resources)
|
|
333
|
+
? lineageNodeContentWidth([...groups, ...resources])
|
|
300
334
|
: undefined,
|
|
301
|
-
[nodeDesign, resources],
|
|
335
|
+
[groups, nodeDesign, resources],
|
|
302
336
|
);
|
|
303
337
|
const graphNodes = useMemo(
|
|
304
338
|
() =>
|
|
@@ -337,7 +371,7 @@ export const LineageGraph = ({
|
|
|
337
371
|
const positionedGraphNodes = useMemo(
|
|
338
372
|
() =>
|
|
339
373
|
preparedTopology
|
|
340
|
-
? lineageTopologyNodes(preparedTopology, nodeDesign
|
|
374
|
+
? lineageTopologyNodes(preparedTopology, nodeDesign)
|
|
341
375
|
: positionedLayout
|
|
342
376
|
? lineagePositionedLayoutNodes({
|
|
343
377
|
groups,
|
|
@@ -348,7 +382,6 @@ export const LineageGraph = ({
|
|
|
348
382
|
nodeDesign,
|
|
349
383
|
expandedFieldNodeIds,
|
|
350
384
|
onToggleFields: toggleNodeFields,
|
|
351
|
-
nodeWidth: resolvedNodeWidth,
|
|
352
385
|
})
|
|
353
386
|
: [],
|
|
354
387
|
[
|
|
@@ -360,7 +393,6 @@ export const LineageGraph = ({
|
|
|
360
393
|
preparedHierarchy,
|
|
361
394
|
preparedTopology,
|
|
362
395
|
resources,
|
|
363
|
-
resolvedNodeWidth,
|
|
364
396
|
toggleNodeFields,
|
|
365
397
|
],
|
|
366
398
|
);
|
|
@@ -388,7 +420,10 @@ export const LineageGraph = ({
|
|
|
388
420
|
)
|
|
389
421
|
: effectiveDefaultDepth;
|
|
390
422
|
const setExpansionDepth = useCallback(
|
|
391
|
-
(depth) =>
|
|
423
|
+
(depth) => {
|
|
424
|
+
setExpansionSelection({ depth, graphKey: graphIdForFit });
|
|
425
|
+
setCustomDepthGraphKey(null);
|
|
426
|
+
},
|
|
392
427
|
[graphIdForFit],
|
|
393
428
|
);
|
|
394
429
|
|
|
@@ -435,6 +470,7 @@ export const LineageGraph = ({
|
|
|
435
470
|
return;
|
|
436
471
|
}
|
|
437
472
|
setPendingExpand(null);
|
|
473
|
+
setCustomDepthGraphKey(graphIdForFit);
|
|
438
474
|
layoutAnchorNodeIdRef.current = groupId;
|
|
439
475
|
setCollapsedGroupIds((currentIds) =>
|
|
440
476
|
expandLineageDescendantsUntilOversized(
|
|
@@ -452,6 +488,7 @@ export const LineageGraph = ({
|
|
|
452
488
|
oversizedGroupIds,
|
|
453
489
|
collapsedGroupIds,
|
|
454
490
|
warnedGroupIds,
|
|
491
|
+
graphIdForFit,
|
|
455
492
|
],
|
|
456
493
|
);
|
|
457
494
|
useEffect(() => {
|
|
@@ -461,6 +498,7 @@ export const LineageGraph = ({
|
|
|
461
498
|
(groupId, action) => {
|
|
462
499
|
const nextWarnedIds = new Set([...warnedGroupIds, groupId]);
|
|
463
500
|
setWarnedGroupIds(nextWarnedIds);
|
|
501
|
+
setCustomDepthGraphKey(graphIdForFit);
|
|
464
502
|
setPendingExpand(null);
|
|
465
503
|
if (action === "descendants") {
|
|
466
504
|
layoutAnchorNodeIdRef.current = groupId;
|
|
@@ -483,7 +521,7 @@ export const LineageGraph = ({
|
|
|
483
521
|
}
|
|
484
522
|
setFocusNodeId(null);
|
|
485
523
|
},
|
|
486
|
-
[positionedGraphNodes, oversizedGroupIds, warnedGroupIds],
|
|
524
|
+
[positionedGraphNodes, oversizedGroupIds, warnedGroupIds, graphIdForFit],
|
|
487
525
|
);
|
|
488
526
|
const dismissOversizedWarning = useCallback(() => setPendingExpand(null), []);
|
|
489
527
|
const defaultCollapseSignature = useMemo(
|
|
@@ -697,14 +735,18 @@ export const LineageGraph = ({
|
|
|
697
735
|
);
|
|
698
736
|
const layoutedGraphNodes = useMemo(
|
|
699
737
|
() =>
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
738
|
+
applyInternalNodeLayers(
|
|
739
|
+
layoutVisibleLineageGraph({
|
|
740
|
+
dependencyLayout,
|
|
741
|
+
anchorNodeId: layoutAnchorNodeIdRef.current,
|
|
742
|
+
edges: visibleLineageEdges,
|
|
743
|
+
graphType,
|
|
744
|
+
nodes: positionedLayout ? collapsedGraphNodes : graphNodes,
|
|
745
|
+
previousLayout: previousLayoutRef.current,
|
|
746
|
+
}),
|
|
747
|
+
),
|
|
707
748
|
[
|
|
749
|
+
dependencyLayout,
|
|
708
750
|
collapsedGraphNodes,
|
|
709
751
|
graphType,
|
|
710
752
|
graphNodes,
|
|
@@ -742,21 +784,26 @@ export const LineageGraph = ({
|
|
|
742
784
|
visibleNodeById,
|
|
743
785
|
);
|
|
744
786
|
|
|
787
|
+
const routedEdges =
|
|
788
|
+
nodeDesign === "redesigned"
|
|
789
|
+
? applyInternalEdgeRoutes(handledEdges, layoutedGraphNodes)
|
|
790
|
+
: handledEdges;
|
|
745
791
|
const renderedEdges =
|
|
746
792
|
nodeDesign === "redesigned"
|
|
747
793
|
? redesignedLineageEdges(
|
|
748
794
|
preparedTopology
|
|
749
|
-
?
|
|
750
|
-
:
|
|
795
|
+
? planExternalLineageEdgeRoutes(routedEdges, layoutedGraphNodes)
|
|
796
|
+
: routedEdges,
|
|
751
797
|
)
|
|
752
798
|
: positionedLayout
|
|
753
799
|
? planLineageEdgeRoutes(handledEdges, layoutedGraphNodes)
|
|
754
800
|
: handledEdges;
|
|
755
801
|
return renderedEdges.map((edge) => ({
|
|
756
802
|
...edge,
|
|
757
|
-
data: { ...edge.data, animated: false },
|
|
803
|
+
data: { ...edge.data, dependencyLayout, animated: false },
|
|
758
804
|
}));
|
|
759
805
|
}, [
|
|
806
|
+
dependencyLayout,
|
|
760
807
|
layoutedGraphNodes,
|
|
761
808
|
nodeDesign,
|
|
762
809
|
positionedLayout,
|
|
@@ -973,6 +1020,33 @@ export const LineageGraph = ({
|
|
|
973
1020
|
data: {
|
|
974
1021
|
...node.data,
|
|
975
1022
|
queryOrigin: queryOriginStates.get(node.id),
|
|
1023
|
+
internalColumns: node.data?.internalColumns?.map((column) => ({
|
|
1024
|
+
...column,
|
|
1025
|
+
label: (column.roles || [column.key])
|
|
1026
|
+
.map((role) =>
|
|
1027
|
+
formatMessage({ id: `lineage.graph.layout.${role}` }),
|
|
1028
|
+
)
|
|
1029
|
+
.join(" / "),
|
|
1030
|
+
countLabel: formatMessage(
|
|
1031
|
+
{ id: "lineage.graph.layout.node_count" },
|
|
1032
|
+
{
|
|
1033
|
+
count: column.count,
|
|
1034
|
+
},
|
|
1035
|
+
),
|
|
1036
|
+
title: formatMessage({ id: "lineage.graph.layout.roles_hint" }),
|
|
1037
|
+
})),
|
|
1038
|
+
internalSummary: node.data?.internalEdgeGuides
|
|
1039
|
+
? formatMessage(
|
|
1040
|
+
{ id: "lineage.graph.layout.internal_count" },
|
|
1041
|
+
{
|
|
1042
|
+
count: Object.keys(node.data.internalEdgeGuides).length,
|
|
1043
|
+
},
|
|
1044
|
+
)
|
|
1045
|
+
: undefined,
|
|
1046
|
+
internalHint:
|
|
1047
|
+
node.data?.internalEdgeGuides && dependencyLayout === "compact"
|
|
1048
|
+
? formatMessage({ id: "lineage.graph.layout.compact_hint" })
|
|
1049
|
+
: undefined,
|
|
976
1050
|
onUnpin:
|
|
977
1051
|
node.id === visiblePinnedGraphNodeId ? unpinFocus : undefined,
|
|
978
1052
|
connectedHandleIds: Array.from(
|
|
@@ -981,6 +1055,8 @@ export const LineageGraph = ({
|
|
|
981
1055
|
},
|
|
982
1056
|
})),
|
|
983
1057
|
[
|
|
1058
|
+
dependencyLayout,
|
|
1059
|
+
formatMessage,
|
|
984
1060
|
connectedHandleIdsByNode,
|
|
985
1061
|
focusActive,
|
|
986
1062
|
focusedNodeIds,
|
|
@@ -1036,6 +1112,17 @@ export const LineageGraph = ({
|
|
|
1036
1112
|
}
|
|
1037
1113
|
return ids;
|
|
1038
1114
|
}, [hoveredNodeId, renderedGraphEdges]);
|
|
1115
|
+
useEffect(() => {
|
|
1116
|
+
if (loading || !visibleNodeById.has(keyboardFocusedNodeId))
|
|
1117
|
+
setKeyboardFocusedNodeId(null);
|
|
1118
|
+
}, [loading, visibleNodeById, keyboardFocusedNodeId]);
|
|
1119
|
+
const handleNodeFocus = (event) => {
|
|
1120
|
+
const id = event.target
|
|
1121
|
+
.closest?.(".react-flow__node")
|
|
1122
|
+
?.getAttribute("data-id");
|
|
1123
|
+
setKeyboardFocusedNodeId(!loading && visibleNodeById.has(id) ? id : null);
|
|
1124
|
+
};
|
|
1125
|
+
const handleNodeBlur = () => setKeyboardFocusedNodeId(null);
|
|
1039
1126
|
const hoverContextValue = useMemo(
|
|
1040
1127
|
() => ({
|
|
1041
1128
|
hoveredNodeId,
|
|
@@ -1043,8 +1130,18 @@ export const LineageGraph = ({
|
|
|
1043
1130
|
connectedNodeIds,
|
|
1044
1131
|
hoveredEdgeEndpoints,
|
|
1045
1132
|
setHoveredEdgeEndpoints,
|
|
1133
|
+
keyboardFocusedNodeId,
|
|
1134
|
+
compactReferenceNodeId: focusGraphNodeId,
|
|
1135
|
+
selectedEdgeId: selectedGraphEdgeId,
|
|
1046
1136
|
}),
|
|
1047
|
-
[
|
|
1137
|
+
[
|
|
1138
|
+
hoveredNodeId,
|
|
1139
|
+
keyboardFocusedNodeId,
|
|
1140
|
+
connectedNodeIds,
|
|
1141
|
+
hoveredEdgeEndpoints,
|
|
1142
|
+
focusGraphNodeId,
|
|
1143
|
+
selectedGraphEdgeId,
|
|
1144
|
+
],
|
|
1048
1145
|
);
|
|
1049
1146
|
const hasGraph = !_.isEmpty(graphNodes) || !_.isEmpty(renderedGraphEdges);
|
|
1050
1147
|
const visibleLegendItems = useMemo(() => {
|
|
@@ -1102,6 +1199,8 @@ export const LineageGraph = ({
|
|
|
1102
1199
|
return;
|
|
1103
1200
|
|
|
1104
1201
|
restoredViewStateRef.current = initialViewState;
|
|
1202
|
+
if (["compact", "expanded"].includes(initialViewState.dependencyLayout))
|
|
1203
|
+
setDependencyLayout(initialViewState.dependencyLayout);
|
|
1105
1204
|
setExpansionDepth(
|
|
1106
1205
|
normalizedExpansionDepth(
|
|
1107
1206
|
initialViewState.expansionDepth,
|
|
@@ -1109,6 +1208,8 @@ export const LineageGraph = ({
|
|
|
1109
1208
|
effectiveMaxDepth,
|
|
1110
1209
|
),
|
|
1111
1210
|
);
|
|
1211
|
+
if (initialViewState.expansionDepthCustom)
|
|
1212
|
+
setCustomDepthGraphKey(graphIdForFit);
|
|
1112
1213
|
const groupIds = new Set(collapsibleGroupIds);
|
|
1113
1214
|
setCollapsedGroupIds(
|
|
1114
1215
|
new Set(
|
|
@@ -1155,6 +1256,7 @@ export const LineageGraph = ({
|
|
|
1155
1256
|
hasGraph,
|
|
1156
1257
|
graphId,
|
|
1157
1258
|
setExpansionDepth,
|
|
1259
|
+
graphIdForFit,
|
|
1158
1260
|
effectiveDefaultDepth,
|
|
1159
1261
|
effectiveMaxDepth,
|
|
1160
1262
|
collapsibleGroupIds,
|
|
@@ -1201,6 +1303,8 @@ export const LineageGraph = ({
|
|
|
1201
1303
|
lineageAncestorNodeIds(node, searchableNodeById),
|
|
1202
1304
|
);
|
|
1203
1305
|
|
|
1306
|
+
if ([...ancestorIds].some((id) => effectiveCollapsedGroupIds.has(id)))
|
|
1307
|
+
setCustomDepthGraphKey(graphIdForFit);
|
|
1204
1308
|
setCollapsedGroupIds(
|
|
1205
1309
|
(currentIds) =>
|
|
1206
1310
|
new Set([...currentIds].filter((id) => !ancestorIds.has(id))),
|
|
@@ -1212,7 +1316,12 @@ export const LineageGraph = ({
|
|
|
1212
1316
|
setFocusNodeId(center ? node.id : null);
|
|
1213
1317
|
if (center) setFocusNodeRequestKey((requestKey) => requestKey + 1);
|
|
1214
1318
|
},
|
|
1215
|
-
[
|
|
1319
|
+
[
|
|
1320
|
+
positionedLayout,
|
|
1321
|
+
searchableNodeById,
|
|
1322
|
+
effectiveCollapsedGroupIds,
|
|
1323
|
+
graphIdForFit,
|
|
1324
|
+
],
|
|
1216
1325
|
);
|
|
1217
1326
|
const handleNodeClick = useCallback(
|
|
1218
1327
|
(event, node) => {
|
|
@@ -1327,30 +1436,41 @@ export const LineageGraph = ({
|
|
|
1327
1436
|
};
|
|
1328
1437
|
const handlePaneSelectionClear = useCallback(
|
|
1329
1438
|
(event) => {
|
|
1330
|
-
|
|
1439
|
+
if (activePanel && !pinnedGraphNodeId) setActivePanel(null);
|
|
1440
|
+
else clearSelectedContext();
|
|
1331
1441
|
onPaneClick?.(event);
|
|
1332
1442
|
},
|
|
1333
|
-
[clearSelectedContext, onPaneClick],
|
|
1443
|
+
[activePanel, pinnedGraphNodeId, clearSelectedContext, onPaneClick],
|
|
1334
1444
|
);
|
|
1335
1445
|
|
|
1336
1446
|
useEffect(() => {
|
|
1337
1447
|
if (!activePanel && !selectedContext) return undefined;
|
|
1338
1448
|
|
|
1339
1449
|
const closeOnOutsidePointer = (event) => {
|
|
1340
|
-
if (event.target?.closest?.(".lineage-graph__dock")) return;
|
|
1341
1450
|
if (
|
|
1342
|
-
|
|
1451
|
+
event.target?.closest?.(
|
|
1452
|
+
".lineage-graph__dock, .lineage-graph__settings-popup, .lineage-graph__depth-popover, .react-flow__pane",
|
|
1453
|
+
)
|
|
1454
|
+
)
|
|
1455
|
+
return;
|
|
1456
|
+
if (
|
|
1343
1457
|
event.target?.closest?.(
|
|
1344
1458
|
".react-flow__node, .td-graph-edge-hit-area, .td-graph-edge-metadata-badge",
|
|
1345
1459
|
)
|
|
1346
1460
|
) {
|
|
1347
1461
|
return;
|
|
1348
1462
|
}
|
|
1349
|
-
if (pinnedGraphNodeId)
|
|
1350
|
-
else
|
|
1463
|
+
if (activePanel && !pinnedGraphNodeId) setActivePanel(null);
|
|
1464
|
+
else clearSelectedContext();
|
|
1351
1465
|
};
|
|
1352
1466
|
const closeOnEscape = (event) => {
|
|
1353
1467
|
if (event.key !== "Escape") return;
|
|
1468
|
+
if (
|
|
1469
|
+
event.target?.closest?.(
|
|
1470
|
+
".lineage-graph__settings-popup, .lineage-graph__depth-popover, .lineage-graph__dock-settings-button[aria-expanded=true], .lineage-graph__dock-depth-button[aria-expanded=true]",
|
|
1471
|
+
)
|
|
1472
|
+
)
|
|
1473
|
+
return;
|
|
1354
1474
|
|
|
1355
1475
|
event.preventDefault();
|
|
1356
1476
|
event.stopPropagation();
|
|
@@ -1390,9 +1510,28 @@ export const LineageGraph = ({
|
|
|
1390
1510
|
graphReadyRef.current = ready;
|
|
1391
1511
|
}, [hasGraph, loading, fittedGraphKey, graphIdForFit, onGraphReady]);
|
|
1392
1512
|
|
|
1393
|
-
const handleCollapseAll = useCallback(
|
|
1394
|
-
()
|
|
1395
|
-
|
|
1513
|
+
const handleCollapseAll = useCallback(() => {
|
|
1514
|
+
setExpansionDepth(0);
|
|
1515
|
+
collapseAllGroups(collapsibleGroupIds);
|
|
1516
|
+
}, [collapseAllGroups, collapsibleGroupIds, setExpansionDepth]);
|
|
1517
|
+
const handleExpandAll = useCallback(() => {
|
|
1518
|
+
setExpansionDepth(effectiveMaxDepth);
|
|
1519
|
+
expandAllGroups();
|
|
1520
|
+
}, [effectiveMaxDepth, expandAllGroups, setExpansionDepth]);
|
|
1521
|
+
const handleDependencyLayoutChange = useCallback(
|
|
1522
|
+
(value) => {
|
|
1523
|
+
if (
|
|
1524
|
+
!["compact", "expanded"].includes(value) ||
|
|
1525
|
+
value === dependencyLayout
|
|
1526
|
+
)
|
|
1527
|
+
return;
|
|
1528
|
+
layoutAnchorNodeIdRef.current = visibleNodeById.has(selectedGraphNodeId)
|
|
1529
|
+
? selectedGraphNodeId
|
|
1530
|
+
: null;
|
|
1531
|
+
setDependencyLayout(value);
|
|
1532
|
+
writeDependencyLayout(value);
|
|
1533
|
+
},
|
|
1534
|
+
[dependencyLayout, selectedGraphNodeId, visibleNodeById],
|
|
1396
1535
|
);
|
|
1397
1536
|
const graphTopControls = hasGraph ? (
|
|
1398
1537
|
<LineageGraphToolbar
|
|
@@ -1404,13 +1543,15 @@ export const LineageGraph = ({
|
|
|
1404
1543
|
pinnedContext={pinnedContext}
|
|
1405
1544
|
onPinnedContextSelect={selectPinnedContext}
|
|
1406
1545
|
doubleClickExpandsNodes={doubleClickExpandsNodes}
|
|
1546
|
+
dependencyLayout={dependencyLayout}
|
|
1547
|
+
onDependencyLayoutChange={handleDependencyLayoutChange}
|
|
1407
1548
|
visibleLegend={visibleLegend}
|
|
1408
1549
|
legendItems={visibleLegendItems}
|
|
1409
1550
|
onClosePanel={closeActivePanel}
|
|
1410
1551
|
onClearContext={clearSelectedContext}
|
|
1411
1552
|
onCollapseAll={handleCollapseAll}
|
|
1412
1553
|
onDoubleClickExpandsNodesChange={setDoubleClickExpandsNodes}
|
|
1413
|
-
onExpandAll={
|
|
1554
|
+
onExpandAll={handleExpandAll}
|
|
1414
1555
|
onExpansionDepthChange={handleExpansionDepthChange}
|
|
1415
1556
|
onMinimizeInspector={minimizeInspector}
|
|
1416
1557
|
onPanelChange={handlePanelChange}
|
|
@@ -1426,6 +1567,7 @@ export const LineageGraph = ({
|
|
|
1426
1567
|
selectedContext?.type === "node" &&
|
|
1427
1568
|
visiblePinnedGraphNodeId === selectedContext.node?.graphNodeId
|
|
1428
1569
|
}
|
|
1570
|
+
expansionDepthCustom={customDepthGraphKey === graphIdForFit}
|
|
1429
1571
|
expansionDepth={expansionDepth}
|
|
1430
1572
|
maxExpansionDepth={effectiveMaxDepth}
|
|
1431
1573
|
searchInput={searchInput}
|
|
@@ -1475,6 +1617,8 @@ export const LineageGraph = ({
|
|
|
1475
1617
|
className={`lineage-graph__stage lineage-graph__stage--${graphType === "impact" ? "impact" : "lineage"}`}
|
|
1476
1618
|
ref={stageRef}
|
|
1477
1619
|
onKeyDownCapture={handleNodeKeyDown}
|
|
1620
|
+
onFocusCapture={handleNodeFocus}
|
|
1621
|
+
onBlurCapture={handleNodeBlur}
|
|
1478
1622
|
>
|
|
1479
1623
|
<EdgeHoverContext.Provider value={hoverContextValue}>
|
|
1480
1624
|
<Graph
|
|
@@ -1500,10 +1644,13 @@ export const LineageGraph = ({
|
|
|
1500
1644
|
disabled={loading || !graphId}
|
|
1501
1645
|
viewState={{
|
|
1502
1646
|
graphId,
|
|
1647
|
+
dependencyLayout,
|
|
1503
1648
|
selectedGraphNodeId,
|
|
1504
1649
|
selectedGraphEdgeId,
|
|
1505
1650
|
pinnedGraphNodeId,
|
|
1506
1651
|
expansionDepth,
|
|
1652
|
+
expansionDepthCustom:
|
|
1653
|
+
customDepthGraphKey === graphIdForFit,
|
|
1507
1654
|
collapsedGroupIds: [...effectiveCollapsedGroupIds],
|
|
1508
1655
|
expandedFieldNodeIds: [...expandedFieldNodeIds],
|
|
1509
1656
|
}}
|