datajunction-ui 0.0.1-rc.12 → 0.0.1-rc.14
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/.env +1 -0
- package/package.json +1 -1
- package/public/favicon.ico +0 -0
- package/src/app/__tests__/__snapshots__/index.test.tsx.snap +3 -0
- package/src/app/components/QueryInfo.jsx +2 -34
- package/src/app/components/djgraph/DJNode.jsx +5 -3
- package/src/app/components/djgraph/DJNodeDimensions.jsx +1 -2
- package/src/app/components/djgraph/LayoutFlow.jsx +104 -0
- package/src/app/components/djgraph/__tests__/__snapshots__/DJNode.test.tsx.snap +6 -1
- package/src/app/pages/NamespacePage/__tests__/__snapshots__/index.test.tsx.snap +3 -0
- package/src/app/pages/NamespacePage/index.jsx +8 -2
- package/src/app/pages/NodePage/NodeColumnTab.jsx +1 -1
- package/src/app/pages/NodePage/NodeGraphTab.jsx +92 -174
- package/src/app/pages/NodePage/NodeHistory.jsx +110 -1
- package/src/app/pages/NodePage/NodeInfoTab.jsx +2 -19
- package/src/app/pages/NodePage/NodeLineageTab.jsx +84 -0
- package/src/app/pages/NodePage/NodeSQLTab.jsx +1 -9
- package/src/app/pages/NodePage/NodesWithDimension.jsx +40 -0
- package/src/app/pages/NodePage/index.jsx +71 -30
- package/src/app/pages/Root/index.tsx +7 -1
- package/src/app/pages/SQLBuilderPage/index.jsx +64 -55
- package/src/app/services/DJService.js +36 -13
- package/src/styles/index.css +16 -8
- package/webpack.config.js +1 -0
package/.env
CHANGED
package/package.json
CHANGED
package/public/favicon.ico
CHANGED
|
Binary file
|
|
@@ -35,9 +35,12 @@ exports[`<App /> should render and match the snapshot 1`] = `
|
|
|
35
35
|
"namespaces": [Function],
|
|
36
36
|
"node": [Function],
|
|
37
37
|
"node_dag": [Function],
|
|
38
|
+
"node_lineage": [Function],
|
|
39
|
+
"nodesWithDimension": [Function],
|
|
38
40
|
"revisions": [Function],
|
|
39
41
|
"sql": [Function],
|
|
40
42
|
"sqls": [Function],
|
|
43
|
+
"stream": [Function],
|
|
41
44
|
"upstreams": [Function],
|
|
42
45
|
},
|
|
43
46
|
}
|
|
@@ -10,38 +10,6 @@ export default function QueryInfo({
|
|
|
10
10
|
started,
|
|
11
11
|
numRows,
|
|
12
12
|
}) {
|
|
13
|
-
const stateIcon =
|
|
14
|
-
state === 'FINISHED' ? (
|
|
15
|
-
<span className="status__valid status" style={{ alignContent: 'center' }}>
|
|
16
|
-
<svg
|
|
17
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
18
|
-
width="25"
|
|
19
|
-
height="25"
|
|
20
|
-
fill="currentColor"
|
|
21
|
-
className="bi bi-check-circle-fill"
|
|
22
|
-
viewBox="0 0 16 16"
|
|
23
|
-
>
|
|
24
|
-
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z" />
|
|
25
|
-
</svg>
|
|
26
|
-
</span>
|
|
27
|
-
) : (
|
|
28
|
-
<span
|
|
29
|
-
className="status__invalid status"
|
|
30
|
-
style={{ alignContent: 'center' }}
|
|
31
|
-
>
|
|
32
|
-
<svg
|
|
33
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
34
|
-
width="16"
|
|
35
|
-
height="16"
|
|
36
|
-
fill="currentColor"
|
|
37
|
-
className="bi bi-x-circle-fill"
|
|
38
|
-
viewBox="0 0 16 16"
|
|
39
|
-
>
|
|
40
|
-
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM5.354 4.646a.5.5 0 1 0-.708.708L7.293 8l-2.647 2.646a.5.5 0 0 0 .708.708L8 8.707l2.646 2.647a.5.5 0 0 0 .708-.708L8.707 8l2.647-2.646a.5.5 0 0 0-.708-.708L8 7.293 5.354 4.646z" />
|
|
41
|
-
</svg>
|
|
42
|
-
</span>
|
|
43
|
-
);
|
|
44
|
-
|
|
45
13
|
return (
|
|
46
14
|
<div className="table-responsive">
|
|
47
15
|
<table className="card-inner-table table">
|
|
@@ -70,11 +38,11 @@ export default function QueryInfo({
|
|
|
70
38
|
{engine_version}
|
|
71
39
|
</span>
|
|
72
40
|
</td>
|
|
73
|
-
<td>{
|
|
41
|
+
<td>{state}</td>
|
|
74
42
|
<td>{scheduled}</td>
|
|
75
43
|
<td>{started}</td>
|
|
76
44
|
<td>
|
|
77
|
-
{errors
|
|
45
|
+
{errors?.length ? (
|
|
78
46
|
errors.map(e => (
|
|
79
47
|
<p>
|
|
80
48
|
<span className="rounded-pill badge bg-secondary-error">
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { memo, useLayoutEffect, useRef, useState } from 'react';
|
|
2
2
|
import { Handle, Position } from 'reactflow';
|
|
3
|
-
import { DJNodeDimensions } from './DJNodeDimensions';
|
|
4
3
|
import Collapse from './Collapse';
|
|
5
4
|
|
|
6
5
|
function capitalize(string) {
|
|
@@ -43,6 +42,8 @@ export function DJNode({ id, data }) {
|
|
|
43
42
|
<>
|
|
44
43
|
<div
|
|
45
44
|
className={'dj-node__full node_type__' + data.type + highlightNodeClass}
|
|
45
|
+
key={data.name}
|
|
46
|
+
style={{ width: '450px' }}
|
|
46
47
|
>
|
|
47
48
|
<div style={handleWrapperStyle}>
|
|
48
49
|
<Handle
|
|
@@ -61,7 +62,8 @@ export function DJNode({ id, data }) {
|
|
|
61
62
|
</div>
|
|
62
63
|
</div>
|
|
63
64
|
<div className="dj-node__body">
|
|
64
|
-
<b>{capitalize(data.type)}</b
|
|
65
|
+
<b>{capitalize(data.type)}</b>
|
|
66
|
+
<br />{' '}
|
|
65
67
|
<a href={`/nodes/${data.name}`}>
|
|
66
68
|
{data.type === 'source' ? data.table : data.display_name}
|
|
67
69
|
</a>
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useContext, useEffect, useState } from 'react';
|
|
2
2
|
import DJClientContext from '../../providers/djclient';
|
|
3
|
-
import Collapse from './Collapse';
|
|
4
3
|
|
|
5
4
|
export function DJNodeDimensions(data) {
|
|
6
5
|
const [dimensions, setDimensions] = useState([]);
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|
2
|
+
import ReactFlow, {
|
|
3
|
+
addEdge,
|
|
4
|
+
MiniMap,
|
|
5
|
+
Controls,
|
|
6
|
+
Background,
|
|
7
|
+
useNodesState,
|
|
8
|
+
useEdgesState,
|
|
9
|
+
} from 'reactflow';
|
|
10
|
+
|
|
11
|
+
import '../../../styles/dag.css';
|
|
12
|
+
import 'reactflow/dist/style.css';
|
|
13
|
+
import DJNode from '../../components/djgraph/DJNode';
|
|
14
|
+
import dagre from 'dagre';
|
|
15
|
+
|
|
16
|
+
const getLayoutedElements = (
|
|
17
|
+
nodes,
|
|
18
|
+
edges,
|
|
19
|
+
direction = 'LR',
|
|
20
|
+
nodeWidth = 600,
|
|
21
|
+
) => {
|
|
22
|
+
const dagreGraph = new dagre.graphlib.Graph();
|
|
23
|
+
dagreGraph.setDefaultEdgeLabel(() => ({}));
|
|
24
|
+
|
|
25
|
+
const isHorizontal = direction === 'TB';
|
|
26
|
+
dagreGraph.setGraph({
|
|
27
|
+
rankdir: direction,
|
|
28
|
+
nodesep: 40,
|
|
29
|
+
ranksep: 10,
|
|
30
|
+
ranker: 'longest-path',
|
|
31
|
+
});
|
|
32
|
+
const nodeHeightTracker = {};
|
|
33
|
+
|
|
34
|
+
nodes.forEach(node => {
|
|
35
|
+
nodeHeightTracker[node.id] =
|
|
36
|
+
Math.min(node.data.column_names.length, 10) * 40 + 250;
|
|
37
|
+
dagreGraph.setNode(node.id, {
|
|
38
|
+
width: nodeWidth,
|
|
39
|
+
height: nodeHeightTracker[node.id],
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
edges.forEach(edge => {
|
|
44
|
+
dagreGraph.setEdge(edge.source, edge.target);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
dagre.layout(dagreGraph);
|
|
48
|
+
|
|
49
|
+
nodes.forEach(node => {
|
|
50
|
+
const nodeWithPosition = dagreGraph.node(node.id);
|
|
51
|
+
node.targetPosition = isHorizontal ? 'left' : 'top';
|
|
52
|
+
node.sourcePosition = isHorizontal ? 'right' : 'bottom';
|
|
53
|
+
node.position = {
|
|
54
|
+
x: nodeWithPosition.x - nodeWidth / 2,
|
|
55
|
+
y: nodeWithPosition.y - nodeHeightTracker[node.id] / 2,
|
|
56
|
+
};
|
|
57
|
+
node.width = nodeWidth;
|
|
58
|
+
node.height = nodeHeightTracker[node.id];
|
|
59
|
+
return node;
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
return { nodes: nodes, edges: edges };
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const LayoutFlow = (djNode, saveGraph) => {
|
|
66
|
+
const nodeTypes = useMemo(() => ({ DJNode: DJNode }), []);
|
|
67
|
+
|
|
68
|
+
// These are used internally by ReactFlow (to update the nodes on the ReactFlow pane)
|
|
69
|
+
const [nodes, setNodes, onNodesChange] = useNodesState([]);
|
|
70
|
+
const [edges, setEdges, onEdgesChange] = useEdgesState([]);
|
|
71
|
+
|
|
72
|
+
const minimapStyle = {
|
|
73
|
+
height: 100,
|
|
74
|
+
width: 150,
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
useEffect(() => {
|
|
78
|
+
saveGraph(getLayoutedElements, setNodes, setEdges).catch(console.error);
|
|
79
|
+
}, [djNode]);
|
|
80
|
+
|
|
81
|
+
const onConnect = useCallback(
|
|
82
|
+
params => setEdges(eds => addEdge(params, eds)),
|
|
83
|
+
[setEdges],
|
|
84
|
+
);
|
|
85
|
+
return (
|
|
86
|
+
<div style={{ height: '800px' }}>
|
|
87
|
+
<ReactFlow
|
|
88
|
+
nodes={nodes}
|
|
89
|
+
edges={edges}
|
|
90
|
+
nodeTypes={nodeTypes}
|
|
91
|
+
onNodesChange={onNodesChange}
|
|
92
|
+
onEdgesChange={onEdgesChange}
|
|
93
|
+
onConnect={onConnect}
|
|
94
|
+
snapToGrid={true}
|
|
95
|
+
fitView
|
|
96
|
+
>
|
|
97
|
+
<MiniMap style={minimapStyle} zoomable pannable />
|
|
98
|
+
<Controls />
|
|
99
|
+
<Background color="#aaa" gap={16} />
|
|
100
|
+
</ReactFlow>
|
|
101
|
+
</div>
|
|
102
|
+
);
|
|
103
|
+
};
|
|
104
|
+
export default LayoutFlow;
|
|
@@ -4,6 +4,11 @@ exports[`<DJNode /> should render and match the snapshot 1`] = `
|
|
|
4
4
|
<React.Fragment>
|
|
5
5
|
<div
|
|
6
6
|
className="dj-node__full node_type__source"
|
|
7
|
+
style={
|
|
8
|
+
Object {
|
|
9
|
+
"width": "450px",
|
|
10
|
+
}
|
|
11
|
+
}
|
|
7
12
|
>
|
|
8
13
|
<div
|
|
9
14
|
style={
|
|
@@ -52,7 +57,7 @@ exports[`<DJNode /> should render and match the snapshot 1`] = `
|
|
|
52
57
|
<b>
|
|
53
58
|
Source
|
|
54
59
|
</b>
|
|
55
|
-
|
|
60
|
+
<br />
|
|
56
61
|
|
|
57
62
|
<a
|
|
58
63
|
href="/nodes/shared.dimensions.accounts"
|
|
@@ -20,7 +20,7 @@ export function NamespacePage() {
|
|
|
20
20
|
const hierarchy = [];
|
|
21
21
|
|
|
22
22
|
for (const item of namespaceList) {
|
|
23
|
-
const namespaces = item.
|
|
23
|
+
const namespaces = item.split('.');
|
|
24
24
|
let currentLevel = hierarchy;
|
|
25
25
|
|
|
26
26
|
let path = '';
|
|
@@ -75,7 +75,7 @@ export function NamespacePage() {
|
|
|
75
75
|
<tr>
|
|
76
76
|
<td>
|
|
77
77
|
<a href={'/nodes/' + node.name} className="link-table">
|
|
78
|
-
{node.
|
|
78
|
+
{node.name}
|
|
79
79
|
</a>
|
|
80
80
|
<span
|
|
81
81
|
className="rounded-pill badge bg-secondary-soft"
|
|
@@ -84,6 +84,11 @@ export function NamespacePage() {
|
|
|
84
84
|
{node.version}
|
|
85
85
|
</span>
|
|
86
86
|
</td>
|
|
87
|
+
<td>
|
|
88
|
+
<a href={'/nodes/' + node.name} className="link-table">
|
|
89
|
+
{node.display_name}
|
|
90
|
+
</a>
|
|
91
|
+
</td>
|
|
87
92
|
<td>
|
|
88
93
|
<span className={'node_type__' + node.type + ' badge node_type'}>
|
|
89
94
|
{node.type}
|
|
@@ -138,6 +143,7 @@ export function NamespacePage() {
|
|
|
138
143
|
<thead>
|
|
139
144
|
<tr>
|
|
140
145
|
<th>Name</th>
|
|
146
|
+
<th>Display Name</th>
|
|
141
147
|
<th>Type</th>
|
|
142
148
|
<th>Status</th>
|
|
143
149
|
<th>Mode</th>
|
|
@@ -1,195 +1,113 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
import
|
|
3
|
-
addEdge,
|
|
4
|
-
MiniMap,
|
|
5
|
-
Controls,
|
|
6
|
-
Background,
|
|
7
|
-
useNodesState,
|
|
8
|
-
useEdgesState,
|
|
9
|
-
MarkerType,
|
|
10
|
-
} from 'reactflow';
|
|
1
|
+
import React, { useContext } from 'react';
|
|
2
|
+
import { MarkerType } from 'reactflow';
|
|
11
3
|
|
|
12
4
|
import '../../../styles/dag.css';
|
|
13
5
|
import 'reactflow/dist/style.css';
|
|
14
6
|
import DJNode from '../../components/djgraph/DJNode';
|
|
15
|
-
import dagre from 'dagre';
|
|
16
7
|
import DJClientContext from '../../providers/djclient';
|
|
8
|
+
import LayoutFlow from '../../components/djgraph/LayoutFlow';
|
|
17
9
|
|
|
18
10
|
const NodeLineage = djNode => {
|
|
19
11
|
const djClient = useContext(DJClientContext).DataJunctionAPI;
|
|
20
|
-
const nodeTypes = useMemo(() => ({ DJNode: DJNode }), []);
|
|
21
12
|
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
13
|
+
const createNode = node => {
|
|
14
|
+
const primary_key = node.columns
|
|
15
|
+
.filter(col =>
|
|
16
|
+
col.attributes.some(attr => attr.attribute_type.name === 'primary_key'),
|
|
17
|
+
)
|
|
18
|
+
.map(col => col.name);
|
|
19
|
+
const column_names = node.columns.map(col => {
|
|
20
|
+
return { name: col.name, type: col.type };
|
|
21
|
+
});
|
|
22
|
+
return {
|
|
23
|
+
id: String(node.name),
|
|
24
|
+
type: 'DJNode',
|
|
25
|
+
data: {
|
|
26
|
+
label:
|
|
27
|
+
node.table !== null
|
|
28
|
+
? String(node.schema_ + '.' + node.table)
|
|
29
|
+
: 'default.' + node.name,
|
|
30
|
+
table: node.table,
|
|
31
|
+
name: String(node.name),
|
|
32
|
+
display_name: String(node.display_name),
|
|
33
|
+
type: node.type,
|
|
34
|
+
primary_key: primary_key,
|
|
35
|
+
column_names: column_names,
|
|
36
|
+
is_current: node.name === djNode.djNode.name,
|
|
37
|
+
},
|
|
38
|
+
};
|
|
28
39
|
};
|
|
29
40
|
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
edges.forEach(edge => {
|
|
54
|
-
dagreGraph.setEdge(edge.source, edge.target);
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
dagre.layout(dagreGraph);
|
|
58
|
-
|
|
59
|
-
nodes.forEach(node => {
|
|
60
|
-
const nodeWithPosition = dagreGraph.node(node.id);
|
|
61
|
-
node.targetPosition = isHorizontal ? 'left' : 'top';
|
|
62
|
-
node.sourcePosition = isHorizontal ? 'right' : 'bottom';
|
|
63
|
-
node.position = {
|
|
64
|
-
x: nodeWithPosition.x - nodeWidth / 2,
|
|
65
|
-
y: nodeWithPosition.y - nodeHeightTracker[node.id] / 2,
|
|
41
|
+
const dimensionEdges = node => {
|
|
42
|
+
return node.columns
|
|
43
|
+
.filter(col => col.dimension)
|
|
44
|
+
.map(col => {
|
|
45
|
+
return {
|
|
46
|
+
id: col.dimension.name + '->' + node.name + '.' + col.name,
|
|
47
|
+
source: col.dimension.name,
|
|
48
|
+
sourceHandle: col.dimension.name,
|
|
49
|
+
target: node.name,
|
|
50
|
+
targetHandle: node.name + '.' + col.name,
|
|
51
|
+
draggable: true,
|
|
52
|
+
markerStart: {
|
|
53
|
+
type: MarkerType.Arrow,
|
|
54
|
+
width: 20,
|
|
55
|
+
height: 20,
|
|
56
|
+
color: '#b0b9c2',
|
|
57
|
+
},
|
|
58
|
+
style: {
|
|
59
|
+
strokeWidth: 3,
|
|
60
|
+
stroke: '#b0b9c2',
|
|
61
|
+
},
|
|
66
62
|
};
|
|
67
|
-
node.width = nodeWidth;
|
|
68
|
-
node.height = nodeHeightTracker[node.id];
|
|
69
|
-
return node;
|
|
70
63
|
});
|
|
71
|
-
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
const dagFetch = async () => {
|
|
75
|
-
let related_nodes = await djClient.node_dag(djNode.djNode.name);
|
|
76
|
-
// djNode.djNode.is_current = true;
|
|
77
|
-
var djNodes = [djNode.djNode];
|
|
78
|
-
for (const iterable of [related_nodes]) {
|
|
79
|
-
for (const item of iterable) {
|
|
80
|
-
if (item.type !== 'cube') {
|
|
81
|
-
djNodes.push(item);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
let edges = [];
|
|
86
|
-
djNodes.forEach(obj => {
|
|
87
|
-
obj.parents.forEach(parent => {
|
|
88
|
-
if (parent.name) {
|
|
89
|
-
edges.push({
|
|
90
|
-
id: obj.name + '-' + parent.name,
|
|
91
|
-
source: parent.name,
|
|
92
|
-
sourceHandle: parent.name,
|
|
93
|
-
target: obj.name,
|
|
94
|
-
targetHandle: obj.name,
|
|
95
|
-
animated: true,
|
|
96
|
-
markerEnd: {
|
|
97
|
-
type: MarkerType.Arrow,
|
|
98
|
-
},
|
|
99
|
-
style: {
|
|
100
|
-
strokeWidth: 3,
|
|
101
|
-
stroke: '#b0b9c2',
|
|
102
|
-
},
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
});
|
|
64
|
+
};
|
|
106
65
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
source: col.dimension.name,
|
|
112
|
-
sourceHandle: col.dimension.name,
|
|
113
|
-
target: obj.name,
|
|
114
|
-
targetHandle: obj.name + '.' + col.name,
|
|
115
|
-
draggable: true,
|
|
116
|
-
markerStart: {
|
|
117
|
-
type: MarkerType.Arrow,
|
|
118
|
-
width: 20,
|
|
119
|
-
height: 20,
|
|
120
|
-
color: '#b0b9c2',
|
|
121
|
-
},
|
|
122
|
-
style: {
|
|
123
|
-
strokeWidth: 3,
|
|
124
|
-
stroke: '#b0b9c2',
|
|
125
|
-
},
|
|
126
|
-
};
|
|
127
|
-
edges.push(edge);
|
|
128
|
-
}
|
|
129
|
-
});
|
|
130
|
-
});
|
|
131
|
-
const nodes = djNodes.map(node => {
|
|
132
|
-
const primary_key = node.columns
|
|
133
|
-
.filter(col =>
|
|
134
|
-
col.attributes.some(
|
|
135
|
-
attr => attr.attribute_type.name === 'primary_key',
|
|
136
|
-
),
|
|
137
|
-
)
|
|
138
|
-
.map(col => col.name);
|
|
139
|
-
const column_names = node.columns.map(col => {
|
|
140
|
-
return { name: col.name, type: col.type };
|
|
141
|
-
});
|
|
66
|
+
const parentEdges = node => {
|
|
67
|
+
return node.parents
|
|
68
|
+
.filter(parent => parent.name)
|
|
69
|
+
.map(parent => {
|
|
142
70
|
return {
|
|
143
|
-
id:
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
column_names: column_names,
|
|
156
|
-
is_current: node.name === djNode.djNode.name,
|
|
71
|
+
id: node.name + '-' + parent.name,
|
|
72
|
+
source: parent.name,
|
|
73
|
+
sourceHandle: parent.name,
|
|
74
|
+
target: node.name,
|
|
75
|
+
targetHandle: node.name,
|
|
76
|
+
animated: true,
|
|
77
|
+
markerEnd: {
|
|
78
|
+
type: MarkerType.Arrow,
|
|
79
|
+
},
|
|
80
|
+
style: {
|
|
81
|
+
strokeWidth: 3,
|
|
82
|
+
stroke: '#b0b9c2',
|
|
157
83
|
},
|
|
158
84
|
};
|
|
159
85
|
});
|
|
160
|
-
|
|
161
|
-
setEdges(edges);
|
|
162
|
-
|
|
163
|
-
// use dagre to determine the position of the parents (the DJ nodes)
|
|
164
|
-
// the positions of the columns are relative to each DJ node
|
|
165
|
-
setElementsLayout(nodes, edges);
|
|
166
|
-
};
|
|
167
|
-
|
|
168
|
-
dagFetch();
|
|
169
|
-
}, [dagreGraph, djClient, djNode.djNode, setEdges, setNodes]);
|
|
170
|
-
|
|
171
|
-
const onConnect = useCallback(
|
|
172
|
-
params => setEdges(eds => addEdge(params, eds)),
|
|
173
|
-
[setEdges],
|
|
174
|
-
);
|
|
86
|
+
};
|
|
175
87
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
88
|
+
const dagFetch = async (getLayoutedElements, setNodes, setEdges) => {
|
|
89
|
+
let related_nodes = await djClient.node_dag(djNode.djNode.name);
|
|
90
|
+
var djNodes = [djNode.djNode];
|
|
91
|
+
for (const iterable of [related_nodes]) {
|
|
92
|
+
for (const item of iterable) {
|
|
93
|
+
if (item.type !== 'cube') {
|
|
94
|
+
djNodes.push(item);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
let edges = [];
|
|
99
|
+
djNodes.forEach(node => {
|
|
100
|
+
edges = edges.concat(parentEdges(node));
|
|
101
|
+
edges = edges.concat(dimensionEdges(node));
|
|
102
|
+
});
|
|
103
|
+
const nodes = djNodes.map(node => createNode(node));
|
|
104
|
+
|
|
105
|
+
// use dagre to determine the position of the parents (the DJ nodes)
|
|
106
|
+
// the positions of the columns are relative to each DJ node
|
|
107
|
+
getLayoutedElements(nodes, edges);
|
|
108
|
+
setNodes(nodes);
|
|
109
|
+
setEdges(edges);
|
|
110
|
+
};
|
|
111
|
+
return LayoutFlow(djNode, dagFetch);
|
|
194
112
|
};
|
|
195
113
|
export default NodeLineage;
|