@truedat/dd 8.11.4 → 8.11.7
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 +4 -3
- package/src/components/Graphs.js +30 -4
- package/src/components/LineageContextMenu.js +185 -58
- package/src/components/LineageDownloadButton.js +16 -6
- package/src/components/LineageEventsPanel.js +80 -27
- package/src/components/LineageEventsTable.js +7 -3
- package/src/components/LineageGraph.js +5144 -306
- package/src/components/LineageGraphToolbar.js +896 -0
- package/src/components/LineageInspectorPanel.js +748 -0
- package/src/components/LineageResourceNode.js +501 -0
- package/src/components/LineageRoutes.js +1 -2
- package/src/components/LineageSelectionPanel.js +28 -12
- package/src/components/StructureGraph.js +8 -1
- package/src/components/StructureGraphView.js +14 -0
- package/src/components/StructureImpact.js +2 -22
- package/src/components/StructureLineage.js +2 -19
- package/src/components/StructuresUploadEventsTable.js +0 -3
- package/src/components/__tests__/LineageContextMenu.spec.js +42 -0
- package/src/components/__tests__/LineageGraph.spec.js +896 -0
- package/src/components/__tests__/LineageGraphInteractions.spec.js +660 -0
- package/src/components/__tests__/LineageGraphLayout.spec.js +620 -0
- package/src/components/__tests__/LineageGraphToolbar.spec.js +366 -0
- package/src/components/__tests__/LineageHierarchy.spec.js +116 -0
- package/src/components/__tests__/LineageInspectorPanel.spec.js +357 -0
- package/src/components/__tests__/LineageResourceNode.spec.js +338 -0
- package/src/components/__tests__/LineageRoutes.spec.js +27 -9
- package/src/components/__tests__/__snapshots__/LineageDownloadButton.spec.js.snap +23 -3
- package/src/components/__tests__/__snapshots__/LineageForm.spec.js.snap +23 -3
- package/src/components/__tests__/lineageEventHelpers.spec.js +60 -0
- package/src/components/lineageEventHelpers.js +53 -17
- package/src/reducers/__tests__/lineageEvents.spec.js +164 -0
- package/src/reducers/__tests__/lineageQuery.spec.js +11 -0
- package/src/reducers/lineageEvents.js +68 -2
- package/src/reducers/lineageQuery.js +2 -6
- package/src/styles/LineageGraphColors.less +105 -0
- package/src/styles/LineageGraphCore.less +20 -0
- package/src/styles/LineageResourceNode.less +711 -0
- package/src/styles/lineageGraph.less +2973 -84
- package/src/utils/__tests__/lineageGraphIndex.spec.js +52 -0
- package/src/utils/__tests__/lineageLayout.spec.js +234 -0
- package/src/utils/__tests__/lineageTopology.spec.js +256 -0
- package/src/utils/lineageGraphIndex.js +296 -0
- package/src/utils/lineageLayout.js +1047 -0
|
@@ -0,0 +1,501 @@
|
|
|
1
|
+
import LineageQueryOrigin from "@truedat/core/components/graph/LineageQueryOrigin";
|
|
2
|
+
import { memo, useContext } from "react";
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
import { Icon } from "semantic-ui-react";
|
|
5
|
+
import { useIntl } from "react-intl";
|
|
6
|
+
import { Handle, Position } from "@truedat/core/components/graph/FlowPorts";
|
|
7
|
+
import { EdgeHoverContext } from "@truedat/core/components/graph/ColoredEdge";
|
|
8
|
+
|
|
9
|
+
const nodeText = (value) => {
|
|
10
|
+
if (value === undefined || value === null) return "";
|
|
11
|
+
if (typeof value === "object") {
|
|
12
|
+
return nodeText(value.name || value.label || value.value || value.id);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return `${value}`;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const fieldName = (field) => {
|
|
19
|
+
if (typeof field === "string") return field;
|
|
20
|
+
|
|
21
|
+
return nodeText(
|
|
22
|
+
field?.name ||
|
|
23
|
+
field?.label ||
|
|
24
|
+
field?.field ||
|
|
25
|
+
field?.external_id ||
|
|
26
|
+
field?.id,
|
|
27
|
+
);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const fieldType = (field) =>
|
|
31
|
+
typeof field === "object" && field
|
|
32
|
+
? nodeText(
|
|
33
|
+
field.type || field.data_type || field.dataType || field.metadata?.type,
|
|
34
|
+
)
|
|
35
|
+
: "";
|
|
36
|
+
|
|
37
|
+
const fieldKey = (field, index) => `${fieldName(field) || "field"}-${index}`;
|
|
38
|
+
const fieldSourceHandleId = (index) => `field-source-${index}`;
|
|
39
|
+
const fieldTargetHandleId = (index) => `field-target-${index}`;
|
|
40
|
+
const fieldSourceLeftHandleId = (index) => `field-source-left-${index}`;
|
|
41
|
+
const fieldTargetRightHandleId = (index) => `field-target-right-${index}`;
|
|
42
|
+
|
|
43
|
+
const toQualityScore = (value) => {
|
|
44
|
+
if (value === undefined || value === null || value === "") return undefined;
|
|
45
|
+
|
|
46
|
+
const number =
|
|
47
|
+
typeof value === "number"
|
|
48
|
+
? value
|
|
49
|
+
: Number(`${value}`.trim().replace(/%$/, ""));
|
|
50
|
+
|
|
51
|
+
if (!Number.isFinite(number)) return undefined;
|
|
52
|
+
|
|
53
|
+
return number <= 1 ? number * 100 : number;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export const lineageQualityLevel = (quality) => {
|
|
57
|
+
const score = toQualityScore(quality);
|
|
58
|
+
|
|
59
|
+
if (score === undefined) return undefined;
|
|
60
|
+
if (score >= 90) return "good";
|
|
61
|
+
if (score >= 75) return "warning";
|
|
62
|
+
|
|
63
|
+
return "poor";
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const statusClass = (status) => {
|
|
67
|
+
const text = nodeText(status);
|
|
68
|
+
if (!text) return "";
|
|
69
|
+
return text.toLowerCase().replace(/[^a-z0-9]+/g, "-");
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const focusModifier = (focusSelected, focusDirect, focusDimmed) => {
|
|
73
|
+
if (focusSelected) return "td-lineage-resource-node--focus-selected";
|
|
74
|
+
if (focusDirect) return "td-lineage-resource-node--focus-direct";
|
|
75
|
+
if (focusDimmed) return "td-lineage-resource-node--focus-dimmed";
|
|
76
|
+
return "";
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const LineageField = ({
|
|
80
|
+
edgeState,
|
|
81
|
+
field,
|
|
82
|
+
index,
|
|
83
|
+
showHandles,
|
|
84
|
+
sourceConnected,
|
|
85
|
+
sourceLeftConnected,
|
|
86
|
+
targetConnected,
|
|
87
|
+
targetRightConnected,
|
|
88
|
+
}) => {
|
|
89
|
+
const name = fieldName(field);
|
|
90
|
+
const type = fieldType(field);
|
|
91
|
+
const isPK =
|
|
92
|
+
typeof field === "object" &&
|
|
93
|
+
(field?.isPK || field?.is_pk || field?.primary_key);
|
|
94
|
+
const isFK =
|
|
95
|
+
typeof field === "object" &&
|
|
96
|
+
(field?.isFK || field?.is_fk || field?.foreign_key);
|
|
97
|
+
const isCDE =
|
|
98
|
+
typeof field === "object" &&
|
|
99
|
+
(field?.isCDE ||
|
|
100
|
+
field?.is_cde ||
|
|
101
|
+
field?.critical_data_element ||
|
|
102
|
+
field?.metadata?.isCDE ||
|
|
103
|
+
field?.metadata?.is_cde);
|
|
104
|
+
const className = [
|
|
105
|
+
"td-lineage-resource-node__field",
|
|
106
|
+
edgeState ? `td-lineage-resource-node__field--${edgeState}` : "",
|
|
107
|
+
]
|
|
108
|
+
.filter(Boolean)
|
|
109
|
+
.join(" ");
|
|
110
|
+
|
|
111
|
+
return (
|
|
112
|
+
<div className={className}>
|
|
113
|
+
{showHandles ? (
|
|
114
|
+
<Handle
|
|
115
|
+
id={fieldTargetHandleId(index)}
|
|
116
|
+
type="target"
|
|
117
|
+
position={Position.Left}
|
|
118
|
+
className={`td-lineage-resource-node__field-handle td-lineage-resource-node__field-handle--target td-lineage-resource-node__field-handle--edge-target${
|
|
119
|
+
targetConnected ? " td-lineage-node-handle--connected" : ""
|
|
120
|
+
}`}
|
|
121
|
+
/>
|
|
122
|
+
) : null}
|
|
123
|
+
<span className="td-lineage-resource-node__field-name" title={name}>
|
|
124
|
+
{isPK ? (
|
|
125
|
+
<span className="td-lineage-resource-node__field-key">PK</span>
|
|
126
|
+
) : null}
|
|
127
|
+
{isFK ? (
|
|
128
|
+
<span className="td-lineage-resource-node__field-key">FK</span>
|
|
129
|
+
) : null}
|
|
130
|
+
{isCDE ? (
|
|
131
|
+
<Icon
|
|
132
|
+
aria-label="Critical data element"
|
|
133
|
+
className="td-lineage-resource-node__field-cde"
|
|
134
|
+
name="certificate"
|
|
135
|
+
/>
|
|
136
|
+
) : null}
|
|
137
|
+
{name}
|
|
138
|
+
</span>
|
|
139
|
+
{type ? (
|
|
140
|
+
<span
|
|
141
|
+
className="td-lineage-resource-node__field-key td-lineage-resource-node__field-type-badge"
|
|
142
|
+
title={type}
|
|
143
|
+
>
|
|
144
|
+
{type}
|
|
145
|
+
</span>
|
|
146
|
+
) : null}
|
|
147
|
+
{showHandles ? (
|
|
148
|
+
<Handle
|
|
149
|
+
id={fieldSourceLeftHandleId(index)}
|
|
150
|
+
type="source"
|
|
151
|
+
position={Position.Left}
|
|
152
|
+
className={`td-lineage-resource-node__field-handle td-lineage-resource-node__field-handle--source-left td-lineage-resource-node__field-handle--edge-source${
|
|
153
|
+
sourceLeftConnected ? " td-lineage-node-handle--connected" : ""
|
|
154
|
+
}`}
|
|
155
|
+
/>
|
|
156
|
+
) : null}
|
|
157
|
+
{showHandles ? (
|
|
158
|
+
<Handle
|
|
159
|
+
id={fieldSourceHandleId(index)}
|
|
160
|
+
type="source"
|
|
161
|
+
position={Position.Right}
|
|
162
|
+
className={`td-lineage-resource-node__field-handle td-lineage-resource-node__field-handle--source td-lineage-resource-node__field-handle--edge-source${
|
|
163
|
+
sourceConnected ? " td-lineage-node-handle--connected" : ""
|
|
164
|
+
}`}
|
|
165
|
+
/>
|
|
166
|
+
) : null}
|
|
167
|
+
{showHandles ? (
|
|
168
|
+
<Handle
|
|
169
|
+
id={fieldTargetRightHandleId(index)}
|
|
170
|
+
type="target"
|
|
171
|
+
position={Position.Right}
|
|
172
|
+
className={`td-lineage-resource-node__field-handle td-lineage-resource-node__field-handle--target-right td-lineage-resource-node__field-handle--edge-target${
|
|
173
|
+
targetRightConnected ? " td-lineage-node-handle--connected" : ""
|
|
174
|
+
}`}
|
|
175
|
+
/>
|
|
176
|
+
) : null}
|
|
177
|
+
</div>
|
|
178
|
+
);
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
LineageField.propTypes = {
|
|
182
|
+
edgeState: PropTypes.oneOf(["source", "target", "dimmed"]),
|
|
183
|
+
field: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),
|
|
184
|
+
index: PropTypes.number,
|
|
185
|
+
showHandles: PropTypes.bool,
|
|
186
|
+
sourceConnected: PropTypes.bool,
|
|
187
|
+
sourceLeftConnected: PropTypes.bool,
|
|
188
|
+
targetConnected: PropTypes.bool,
|
|
189
|
+
targetRightConnected: PropTypes.bool,
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
const LineageResourceNode = ({ id, data }) => {
|
|
193
|
+
const { formatMessage } = useIntl();
|
|
194
|
+
const hoverCtx = useContext(EdgeHoverContext);
|
|
195
|
+
const isHovered = hoverCtx?.hoveredNodeId === id;
|
|
196
|
+
const isConnected =
|
|
197
|
+
(hoverCtx?.connectedNodeIds && hoverCtx.connectedNodeIds.has(id)) ||
|
|
198
|
+
(hoverCtx?.hoveredEdgeEndpoints &&
|
|
199
|
+
(hoverCtx.hoveredEdgeEndpoints.source === id ||
|
|
200
|
+
hoverCtx.hoveredEdgeEndpoints.target === id));
|
|
201
|
+
const handleMouseEnter = () => hoverCtx?.setHoveredNodeId(id);
|
|
202
|
+
const handleMouseLeave = () => hoverCtx?.setHoveredNodeId(null);
|
|
203
|
+
const {
|
|
204
|
+
connectedHandleIds = [],
|
|
205
|
+
entityType,
|
|
206
|
+
fields = [],
|
|
207
|
+
fieldHandleLimit = fields.length,
|
|
208
|
+
fieldsExpanded,
|
|
209
|
+
focusDimmed,
|
|
210
|
+
focusDirect,
|
|
211
|
+
focusSelected,
|
|
212
|
+
hiddenFieldsCount = 0,
|
|
213
|
+
isActive,
|
|
214
|
+
queryOrigin,
|
|
215
|
+
kind,
|
|
216
|
+
label,
|
|
217
|
+
lineageNode,
|
|
218
|
+
onToggleFields,
|
|
219
|
+
quality,
|
|
220
|
+
status,
|
|
221
|
+
systemTypeClassName,
|
|
222
|
+
systemTypeLabel,
|
|
223
|
+
systemTypeMissing,
|
|
224
|
+
totalFields = fields.length,
|
|
225
|
+
variant,
|
|
226
|
+
} = data;
|
|
227
|
+
const connectedHandles = new Set(connectedHandleIds);
|
|
228
|
+
const compact = variant === "lineage-compact";
|
|
229
|
+
const fieldLike = variant === "lineage-field";
|
|
230
|
+
const redesigned = variant === "lineage-redesigned" || fieldLike;
|
|
231
|
+
const resolvedKind = data.kind || data.lineageKind;
|
|
232
|
+
const isLeaf = totalFields === 0;
|
|
233
|
+
const entityTypeBadge = entityType ? (
|
|
234
|
+
<span className="td-lineage-resource-node__entity-badge" title={entityType}>
|
|
235
|
+
{formatMessage({
|
|
236
|
+
id: `lineage.graph.entity_type.${entityType}`,
|
|
237
|
+
defaultMessage: entityType,
|
|
238
|
+
})}
|
|
239
|
+
</span>
|
|
240
|
+
) : null;
|
|
241
|
+
const statusText = status || "";
|
|
242
|
+
const qualityLevel = lineageQualityLevel(quality);
|
|
243
|
+
const hoveredEdgeTouchesNode =
|
|
244
|
+
hoverCtx?.hoveredEdgeEndpoints?.source === id ||
|
|
245
|
+
hoverCtx?.hoveredEdgeEndpoints?.target === id;
|
|
246
|
+
const fieldLikeSource =
|
|
247
|
+
fieldLike && hoverCtx?.hoveredEdgeEndpoints?.source === id;
|
|
248
|
+
const fieldLikeTarget =
|
|
249
|
+
fieldLike && hoverCtx?.hoveredEdgeEndpoints?.target === id;
|
|
250
|
+
const fieldLikePrimaryKey =
|
|
251
|
+
fieldLike &&
|
|
252
|
+
(lineageNode?.isPK ||
|
|
253
|
+
lineageNode?.is_pk ||
|
|
254
|
+
lineageNode?.primary_key ||
|
|
255
|
+
lineageNode?.metadata?.isPK ||
|
|
256
|
+
lineageNode?.metadata?.is_pk);
|
|
257
|
+
const fieldLikeCDE =
|
|
258
|
+
fieldLike &&
|
|
259
|
+
(lineageNode?.isCDE ||
|
|
260
|
+
lineageNode?.is_cde ||
|
|
261
|
+
lineageNode?.critical_data_element ||
|
|
262
|
+
lineageNode?.metadata?.isCDE ||
|
|
263
|
+
lineageNode?.metadata?.is_cde);
|
|
264
|
+
const edgeStateForField = (index) => {
|
|
265
|
+
if (!hoveredEdgeTouchesNode) return undefined;
|
|
266
|
+
|
|
267
|
+
if (
|
|
268
|
+
hoverCtx.hoveredEdgeEndpoints.source === id &&
|
|
269
|
+
hoverCtx.hoveredEdgeEndpoints.sourceFieldIndex === index
|
|
270
|
+
) {
|
|
271
|
+
return "source";
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if (
|
|
275
|
+
hoverCtx.hoveredEdgeEndpoints.target === id &&
|
|
276
|
+
hoverCtx.hoveredEdgeEndpoints.targetFieldIndex === index
|
|
277
|
+
) {
|
|
278
|
+
return "target";
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
return "dimmed";
|
|
282
|
+
};
|
|
283
|
+
const hasFieldDisclosure = totalFields > 6 && onToggleFields;
|
|
284
|
+
const fieldsId = `lineage-node-fields-${id || "unknown"}`;
|
|
285
|
+
const fieldDisclosureLabel = fieldsExpanded
|
|
286
|
+
? formatMessage({
|
|
287
|
+
id: "lineage.graph.node.fields.less",
|
|
288
|
+
defaultMessage: "Show less",
|
|
289
|
+
})
|
|
290
|
+
: formatMessage(
|
|
291
|
+
{
|
|
292
|
+
id: "lineage.graph.node.fields.more",
|
|
293
|
+
defaultMessage: "+ {count} elements",
|
|
294
|
+
},
|
|
295
|
+
{ count: hiddenFieldsCount },
|
|
296
|
+
);
|
|
297
|
+
const resolvedStatusClass = statusClass(status);
|
|
298
|
+
const className = [
|
|
299
|
+
"td-lineage-resource-node",
|
|
300
|
+
compact ? "td-lineage-resource-node--compact" : "",
|
|
301
|
+
redesigned ? "td-lineage-resource-node--redesigned" : "",
|
|
302
|
+
isLeaf ? "td-lineage-resource-node--leaf" : "",
|
|
303
|
+
fieldLike ? "td-lineage-resource-node--field-like" : "",
|
|
304
|
+
fieldLikeSource ? "td-lineage-resource-node--field-source" : "",
|
|
305
|
+
fieldLikeTarget ? "td-lineage-resource-node--field-target" : "",
|
|
306
|
+
kind ? `td-lineage-resource-node--${kind}` : "",
|
|
307
|
+
systemTypeClassName
|
|
308
|
+
? `td-lineage-resource-node--system-type-${systemTypeClassName}`
|
|
309
|
+
: "",
|
|
310
|
+
resolvedStatusClass
|
|
311
|
+
? `td-lineage-resource-node--status-${resolvedStatusClass}`
|
|
312
|
+
: "",
|
|
313
|
+
qualityLevel ? `td-lineage-resource-node--quality-${qualityLevel}` : "",
|
|
314
|
+
focusModifier(focusSelected, focusDirect, focusDimmed),
|
|
315
|
+
isActive ? "td-lineage-resource-node--active" : "",
|
|
316
|
+
queryOrigin ? "td-lineage-resource-node--query-origin" : "",
|
|
317
|
+
isHovered ? "td-lineage-resource-node--hovered" : "",
|
|
318
|
+
isConnected ? "td-lineage-resource-node--connected" : "",
|
|
319
|
+
]
|
|
320
|
+
.filter(Boolean)
|
|
321
|
+
.join(" ");
|
|
322
|
+
|
|
323
|
+
return (
|
|
324
|
+
<div
|
|
325
|
+
className={className}
|
|
326
|
+
onMouseEnter={handleMouseEnter}
|
|
327
|
+
onMouseLeave={handleMouseLeave}
|
|
328
|
+
>
|
|
329
|
+
<Handle
|
|
330
|
+
className={
|
|
331
|
+
connectedHandles.has("start-node")
|
|
332
|
+
? "td-lineage-node-handle--connected"
|
|
333
|
+
: ""
|
|
334
|
+
}
|
|
335
|
+
id="start-node"
|
|
336
|
+
type="target"
|
|
337
|
+
position={Position.Left}
|
|
338
|
+
/>
|
|
339
|
+
<Handle
|
|
340
|
+
className={
|
|
341
|
+
connectedHandles.has("source-left-node")
|
|
342
|
+
? "td-lineage-node-handle--connected"
|
|
343
|
+
: ""
|
|
344
|
+
}
|
|
345
|
+
id="source-left-node"
|
|
346
|
+
type="source"
|
|
347
|
+
position={Position.Left}
|
|
348
|
+
/>
|
|
349
|
+
<div className="td-lineage-resource-node__header">
|
|
350
|
+
<span className="td-lineage-resource-node__title">
|
|
351
|
+
{fieldLikePrimaryKey ? (
|
|
352
|
+
<span className="td-lineage-resource-node__field-key">PK</span>
|
|
353
|
+
) : null}
|
|
354
|
+
{fieldLikeCDE ? (
|
|
355
|
+
<Icon
|
|
356
|
+
aria-label="Critical data element"
|
|
357
|
+
className="td-lineage-resource-node__field-cde"
|
|
358
|
+
name="certificate"
|
|
359
|
+
/>
|
|
360
|
+
) : null}
|
|
361
|
+
<span className="td-lineage-resource-node__label" title={label}>
|
|
362
|
+
{label}
|
|
363
|
+
</span>
|
|
364
|
+
<LineageQueryOrigin origin={queryOrigin} />
|
|
365
|
+
{!queryOrigin &&
|
|
366
|
+
!fieldLike &&
|
|
367
|
+
!systemTypeMissing &&
|
|
368
|
+
systemTypeLabel ? (
|
|
369
|
+
<span className="td-lineage-resource-node__kind">
|
|
370
|
+
<span className="td-lineage-resource-node__system-group">
|
|
371
|
+
{systemTypeLabel}
|
|
372
|
+
</span>
|
|
373
|
+
</span>
|
|
374
|
+
) : null}
|
|
375
|
+
</span>
|
|
376
|
+
<span className="td-lineage-resource-node__header-meta">
|
|
377
|
+
{entityTypeBadge}
|
|
378
|
+
{quality ? (
|
|
379
|
+
<span
|
|
380
|
+
className={`td-lineage-resource-node__quality${
|
|
381
|
+
qualityLevel
|
|
382
|
+
? ` td-lineage-resource-node__quality--${qualityLevel}`
|
|
383
|
+
: ""
|
|
384
|
+
}`}
|
|
385
|
+
>
|
|
386
|
+
<Icon name="bolt" />
|
|
387
|
+
{quality} QC
|
|
388
|
+
</span>
|
|
389
|
+
) : null}
|
|
390
|
+
{status ? (
|
|
391
|
+
<span
|
|
392
|
+
className="td-lineage-resource-node__header-status"
|
|
393
|
+
title={statusText}
|
|
394
|
+
>
|
|
395
|
+
<span className="td-lineage-resource-node__status-dot" />
|
|
396
|
+
</span>
|
|
397
|
+
) : null}
|
|
398
|
+
</span>
|
|
399
|
+
</div>
|
|
400
|
+
{fields.length ? (
|
|
401
|
+
<div
|
|
402
|
+
className={`td-lineage-resource-node__fields nowheel${
|
|
403
|
+
fieldsExpanded && totalFields > 10
|
|
404
|
+
? " td-lineage-resource-node__fields--scrollable"
|
|
405
|
+
: ""
|
|
406
|
+
}`}
|
|
407
|
+
id={fieldsId}
|
|
408
|
+
onWheel={(event) => event.stopPropagation()}
|
|
409
|
+
>
|
|
410
|
+
{fields.map((field, index) => (
|
|
411
|
+
<LineageField
|
|
412
|
+
edgeState={edgeStateForField(index)}
|
|
413
|
+
field={field}
|
|
414
|
+
index={index}
|
|
415
|
+
key={fieldKey(field, index)}
|
|
416
|
+
showHandles={index < fieldHandleLimit}
|
|
417
|
+
sourceConnected={connectedHandles.has(fieldSourceHandleId(index))}
|
|
418
|
+
sourceLeftConnected={connectedHandles.has(
|
|
419
|
+
fieldSourceLeftHandleId(index),
|
|
420
|
+
)}
|
|
421
|
+
targetConnected={connectedHandles.has(fieldTargetHandleId(index))}
|
|
422
|
+
targetRightConnected={connectedHandles.has(
|
|
423
|
+
fieldTargetRightHandleId(index),
|
|
424
|
+
)}
|
|
425
|
+
/>
|
|
426
|
+
))}
|
|
427
|
+
</div>
|
|
428
|
+
) : null}
|
|
429
|
+
{hasFieldDisclosure ? (
|
|
430
|
+
<button
|
|
431
|
+
aria-controls={fieldsId}
|
|
432
|
+
aria-expanded={Boolean(fieldsExpanded)}
|
|
433
|
+
className="td-lineage-resource-node__field-more nodrag nopan nowheel"
|
|
434
|
+
onClick={(event) => {
|
|
435
|
+
event.preventDefault();
|
|
436
|
+
event.stopPropagation();
|
|
437
|
+
onToggleFields();
|
|
438
|
+
}}
|
|
439
|
+
onMouseDown={(event) => event.stopPropagation()}
|
|
440
|
+
onPointerDown={(event) => event.stopPropagation()}
|
|
441
|
+
type="button"
|
|
442
|
+
>
|
|
443
|
+
{fieldDisclosureLabel}
|
|
444
|
+
</button>
|
|
445
|
+
) : null}
|
|
446
|
+
<Handle
|
|
447
|
+
className={
|
|
448
|
+
connectedHandles.has("end-node")
|
|
449
|
+
? "td-lineage-node-handle--connected"
|
|
450
|
+
: ""
|
|
451
|
+
}
|
|
452
|
+
id="end-node"
|
|
453
|
+
type="source"
|
|
454
|
+
position={Position.Right}
|
|
455
|
+
/>
|
|
456
|
+
<Handle
|
|
457
|
+
className={
|
|
458
|
+
connectedHandles.has("target-right-node")
|
|
459
|
+
? "td-lineage-node-handle--connected"
|
|
460
|
+
: ""
|
|
461
|
+
}
|
|
462
|
+
id="target-right-node"
|
|
463
|
+
type="target"
|
|
464
|
+
position={Position.Right}
|
|
465
|
+
/>
|
|
466
|
+
</div>
|
|
467
|
+
);
|
|
468
|
+
};
|
|
469
|
+
|
|
470
|
+
LineageResourceNode.propTypes = {
|
|
471
|
+
id: PropTypes.string,
|
|
472
|
+
data: PropTypes.shape({
|
|
473
|
+
allFields: PropTypes.array,
|
|
474
|
+
connectedHandleIds: PropTypes.arrayOf(PropTypes.string),
|
|
475
|
+
entityType: PropTypes.string,
|
|
476
|
+
fields: PropTypes.array,
|
|
477
|
+
fieldHandleLimit: PropTypes.number,
|
|
478
|
+
fieldsExpanded: PropTypes.bool,
|
|
479
|
+
focusDimmed: PropTypes.bool,
|
|
480
|
+
focusDirect: PropTypes.bool,
|
|
481
|
+
focusSelected: PropTypes.bool,
|
|
482
|
+
hiddenFieldsCount: PropTypes.number,
|
|
483
|
+
iconName: PropTypes.string,
|
|
484
|
+
isActive: PropTypes.bool,
|
|
485
|
+
queryOrigin: PropTypes.oneOf(["direct", "contained"]),
|
|
486
|
+
kind: PropTypes.string,
|
|
487
|
+
label: PropTypes.string,
|
|
488
|
+
lineageNode: PropTypes.object,
|
|
489
|
+
meta: PropTypes.string,
|
|
490
|
+
onToggleFields: PropTypes.func,
|
|
491
|
+
quality: PropTypes.string,
|
|
492
|
+
status: PropTypes.string,
|
|
493
|
+
systemTypeClassName: PropTypes.string,
|
|
494
|
+
systemTypeLabel: PropTypes.string,
|
|
495
|
+
systemTypeMissing: PropTypes.bool,
|
|
496
|
+
totalFields: PropTypes.number,
|
|
497
|
+
variant: PropTypes.string,
|
|
498
|
+
}),
|
|
499
|
+
};
|
|
500
|
+
|
|
501
|
+
export default memo(LineageResourceNode);
|
|
@@ -3,6 +3,7 @@ import PropTypes from "prop-types";
|
|
|
3
3
|
import { connect } from "react-redux";
|
|
4
4
|
import { FormattedMessage, useIntl } from "react-intl";
|
|
5
5
|
import { Button, Icon } from "semantic-ui-react";
|
|
6
|
+
import { TrendingUpDown } from "lucide-react";
|
|
6
7
|
import { fetchLineageEvents } from "../routines";
|
|
7
8
|
import LineageForm from "./LineageForm";
|
|
8
9
|
import LineageEventsPanel from "./LineageEventsPanel";
|
|
@@ -24,10 +25,7 @@ export const LineageSelectionPanel = ({
|
|
|
24
25
|
const toggleLabel = formatMessage({
|
|
25
26
|
id: collapsed ? "lineage.sidebar.expand" : "lineage.sidebar.collapse",
|
|
26
27
|
});
|
|
27
|
-
const activeRailLabel =
|
|
28
|
-
activeSidebarTab === "events"
|
|
29
|
-
? "lineage.sidebar.tabs.graphs"
|
|
30
|
-
: "lineage.sidebar.tabs.lineage";
|
|
28
|
+
const activeRailLabel = "lineage.sidebar.rail";
|
|
31
29
|
const openTab = (tab) => {
|
|
32
30
|
setActiveSidebarTab(tab);
|
|
33
31
|
if (tab === "events") fetchLineageEvents();
|
|
@@ -40,14 +38,28 @@ export const LineageSelectionPanel = ({
|
|
|
40
38
|
useEffect(() => {
|
|
41
39
|
if (collapsed) return;
|
|
42
40
|
|
|
43
|
-
const
|
|
41
|
+
const handleGraphInteraction = (e) => {
|
|
42
|
+
if (e.target.closest?.(".lineage-events-panel__status-popup")) return;
|
|
44
43
|
if (sidebarRef.current && !sidebarRef.current.contains(e.target)) {
|
|
45
44
|
onToggle();
|
|
46
45
|
}
|
|
47
46
|
};
|
|
48
47
|
|
|
49
|
-
document.addEventListener("mousedown",
|
|
50
|
-
|
|
48
|
+
document.addEventListener("mousedown", handleGraphInteraction, {
|
|
49
|
+
capture: true,
|
|
50
|
+
});
|
|
51
|
+
document.addEventListener("wheel", handleGraphInteraction, {
|
|
52
|
+
capture: true,
|
|
53
|
+
passive: true,
|
|
54
|
+
});
|
|
55
|
+
return () => {
|
|
56
|
+
document.removeEventListener("mousedown", handleGraphInteraction, {
|
|
57
|
+
capture: true,
|
|
58
|
+
});
|
|
59
|
+
document.removeEventListener("wheel", handleGraphInteraction, {
|
|
60
|
+
capture: true,
|
|
61
|
+
});
|
|
62
|
+
};
|
|
51
63
|
}, [collapsed, onToggle]);
|
|
52
64
|
|
|
53
65
|
return (
|
|
@@ -67,7 +79,7 @@ export const LineageSelectionPanel = ({
|
|
|
67
79
|
type="button"
|
|
68
80
|
>
|
|
69
81
|
<span className="lineage-view__sidebar-tab-icon">
|
|
70
|
-
<
|
|
82
|
+
<TrendingUpDown size={16} aria-hidden="true" />
|
|
71
83
|
</span>
|
|
72
84
|
<span className="lineage-view__sidebar-tab-label">
|
|
73
85
|
<FormattedMessage
|
|
@@ -113,16 +125,17 @@ export const LineageSelectionPanel = ({
|
|
|
113
125
|
<div
|
|
114
126
|
className={`lineage-view__sidebar-content lineage-view__sidebar-content--${activeSidebarTab}`}
|
|
115
127
|
>
|
|
116
|
-
{activeSidebarTab
|
|
128
|
+
<div hidden={activeSidebarTab !== "lineage"}>
|
|
117
129
|
<LineageForm
|
|
118
130
|
autoCollapse={false}
|
|
119
131
|
collapsible={false}
|
|
120
132
|
onGraphSubmit={onGraphLoad}
|
|
121
133
|
showDownloadButton={false}
|
|
122
134
|
/>
|
|
123
|
-
|
|
135
|
+
</div>
|
|
136
|
+
{activeSidebarTab === "events" ? (
|
|
124
137
|
<LineageEventsPanel onGraphLoad={onGraphLoad} />
|
|
125
|
-
)}
|
|
138
|
+
) : null}
|
|
126
139
|
</div>
|
|
127
140
|
</div>
|
|
128
141
|
<Button
|
|
@@ -140,7 +153,10 @@ export const LineageSelectionPanel = ({
|
|
|
140
153
|
>
|
|
141
154
|
<Icon name="angle right" />
|
|
142
155
|
<span>
|
|
143
|
-
<FormattedMessage
|
|
156
|
+
<FormattedMessage
|
|
157
|
+
id={activeRailLabel}
|
|
158
|
+
defaultMessage="Trazar linaje"
|
|
159
|
+
/>
|
|
144
160
|
</span>
|
|
145
161
|
</Button>
|
|
146
162
|
</aside>
|
|
@@ -14,6 +14,7 @@ export const StructureGraph = ({
|
|
|
14
14
|
id,
|
|
15
15
|
graphId,
|
|
16
16
|
height,
|
|
17
|
+
simplified,
|
|
17
18
|
type,
|
|
18
19
|
}) => {
|
|
19
20
|
useEffect(() => {
|
|
@@ -25,7 +26,12 @@ export const StructureGraph = ({
|
|
|
25
26
|
return degree ? (
|
|
26
27
|
<>
|
|
27
28
|
<GraphRedirector />
|
|
28
|
-
<LineageGraph
|
|
29
|
+
<LineageGraph
|
|
30
|
+
height={height || "640px"}
|
|
31
|
+
graph={graph}
|
|
32
|
+
simplified={simplified}
|
|
33
|
+
structureId={id}
|
|
34
|
+
/>
|
|
29
35
|
</>
|
|
30
36
|
) : null;
|
|
31
37
|
};
|
|
@@ -38,6 +44,7 @@ StructureGraph.propTypes = {
|
|
|
38
44
|
id: PropTypes.string,
|
|
39
45
|
graphId: PropTypes.number,
|
|
40
46
|
height: PropTypes.string,
|
|
47
|
+
simplified: PropTypes.bool,
|
|
41
48
|
type: PropTypes.string,
|
|
42
49
|
};
|
|
43
50
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import PropTypes from "prop-types";
|
|
2
|
+
import StructureGraph from "./StructureGraph";
|
|
3
|
+
|
|
4
|
+
export const StructureGraphView = (props) => (
|
|
5
|
+
<div className="structure-lineage">
|
|
6
|
+
<StructureGraph {...props} height="100%" simplified />
|
|
7
|
+
</div>
|
|
8
|
+
);
|
|
9
|
+
|
|
10
|
+
StructureGraphView.propTypes = {
|
|
11
|
+
graph: PropTypes.object,
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default StructureGraphView;
|
|
@@ -1,25 +1,5 @@
|
|
|
1
1
|
import { connect } from "react-redux";
|
|
2
|
-
import
|
|
3
|
-
import { Grid } from "semantic-ui-react";
|
|
4
|
-
import StructureGraph from "./StructureGraph";
|
|
5
|
-
import LineageDownloadButton from "./LineageDownloadButton";
|
|
6
|
-
|
|
7
|
-
export const StructureImpact = (props) => (
|
|
8
|
-
<>
|
|
9
|
-
<Grid>
|
|
10
|
-
<Grid.Row>
|
|
11
|
-
<Grid.Column width={1} floated="right">
|
|
12
|
-
<LineageDownloadButton graph={props.graph} />
|
|
13
|
-
</Grid.Column>
|
|
14
|
-
</Grid.Row>
|
|
15
|
-
</Grid>
|
|
16
|
-
<StructureGraph {...props} />
|
|
17
|
-
</>
|
|
18
|
-
);
|
|
19
|
-
|
|
20
|
-
StructureImpact.propTypes = {
|
|
21
|
-
graph: PropTypes.object,
|
|
22
|
-
};
|
|
2
|
+
import StructureGraphView from "./StructureGraphView";
|
|
23
3
|
|
|
24
4
|
const mapStateToProps = ({
|
|
25
5
|
structureImpactId: graphId,
|
|
@@ -30,4 +10,4 @@ const mapStateToProps = ({
|
|
|
30
10
|
type: "impact",
|
|
31
11
|
});
|
|
32
12
|
|
|
33
|
-
export default connect(mapStateToProps)(
|
|
13
|
+
export default connect(mapStateToProps)(StructureGraphView);
|