datajunction-ui 0.0.1-rc.1 → 0.0.1-rc.10
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/.github/workflows/ci.yml +3 -3
- package/.prettierignore +3 -1
- package/package.json +13 -8
- package/src/app/__tests__/__snapshots__/index.test.tsx.snap +65 -25
- package/src/app/components/DashboardItem.jsx +29 -0
- package/src/app/components/Tab.jsx +1 -8
- package/src/app/components/djgraph/DJNode.jsx +6 -6
- package/src/app/index.tsx +26 -14
- package/src/app/pages/ListNamespacesPage/index.jsx +13 -5
- package/src/app/pages/NamespacePage/Loadable.jsx +9 -7
- package/src/app/pages/NamespacePage/__tests__/__snapshots__/index.test.tsx.snap +18 -15
- package/src/app/pages/NamespacePage/index.jsx +14 -20
- package/src/app/pages/NodePage/Loadable.jsx +9 -7
- package/src/app/pages/NodePage/NodeGraphTab.jsx +44 -43
- package/src/app/pages/NodePage/index.jsx +6 -5
- package/src/app/providers/djclient.jsx +5 -0
- package/src/styles/index.css +6 -4
- package/tsconfig.json +1 -1
- package/webpack.config.js +20 -3
- package/dist/5fa71a03d45dc2e3d61447f3013a303d.png +0 -0
- package/dist/index.html +0 -26
- package/dist/main.js +0 -23303
- package/dist/vendor.js +0 -281
package/.github/workflows/ci.yml
CHANGED
|
@@ -2,9 +2,9 @@ name: CI/CD
|
|
|
2
2
|
|
|
3
3
|
on:
|
|
4
4
|
push:
|
|
5
|
-
branches: [
|
|
5
|
+
branches: [main]
|
|
6
6
|
pull_request:
|
|
7
|
-
branches: [
|
|
7
|
+
branches: [main]
|
|
8
8
|
|
|
9
9
|
jobs:
|
|
10
10
|
build:
|
|
@@ -19,7 +19,7 @@ jobs:
|
|
|
19
19
|
uses: actions/checkout@v2
|
|
20
20
|
|
|
21
21
|
- name: Set up Node.js ${{ matrix.node-version }}
|
|
22
|
-
uses: actions/setup-node@v3
|
|
22
|
+
uses: actions/setup-node@v3
|
|
23
23
|
with:
|
|
24
24
|
node-version: ${{ matrix.node-version }}
|
|
25
25
|
|
package/.prettierignore
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "datajunction-ui",
|
|
3
|
-
"version": "0.0.1-rc.
|
|
3
|
+
"version": "0.0.1-rc.10",
|
|
4
4
|
"description": "DataJunction Metrics Platform UI",
|
|
5
5
|
"module": "src/index.tsx",
|
|
6
6
|
"repository": {
|
|
@@ -38,14 +38,13 @@
|
|
|
38
38
|
"@types/testing-library__jest-dom": "^5.14.5",
|
|
39
39
|
"@types/webpack": "^5.28.0",
|
|
40
40
|
"@types/webpack-env": "^1.18.0",
|
|
41
|
+
"babel-loader": "9.1.2",
|
|
41
42
|
"chalk": "4.1.2",
|
|
42
43
|
"cross-env": "7.0.3",
|
|
44
|
+
"css-loader": "6.7.3",
|
|
43
45
|
"dagre": "^0.8.5",
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"eslint-plugin-react-hooks": "4.6.0",
|
|
47
|
-
"fbemitter": "3.0.0",
|
|
48
|
-
"flux": "4.0.4",
|
|
46
|
+
"datajunction": "0.0.1-rc.0",
|
|
47
|
+
"file-loader": "6.2.0",
|
|
49
48
|
"fontfaceobserver": "2.3.0",
|
|
50
49
|
"husky": "8.0.1",
|
|
51
50
|
"i18next": "21.9.2",
|
|
@@ -76,6 +75,7 @@
|
|
|
76
75
|
"serve": "14.0.1",
|
|
77
76
|
"shelljs": "0.8.5",
|
|
78
77
|
"sql-formatter": "^12.2.0",
|
|
78
|
+
"style-loader": "3.3.2",
|
|
79
79
|
"stylelint": "14.12.0",
|
|
80
80
|
"stylelint-config-recommended": "9.0.0",
|
|
81
81
|
"ts-loader": "9.4.2",
|
|
@@ -83,7 +83,8 @@
|
|
|
83
83
|
"typescript": "4.6.4",
|
|
84
84
|
"web-vitals": "2.1.4",
|
|
85
85
|
"webpack": "5.81.0",
|
|
86
|
-
"webpack-cli": "5.0.2"
|
|
86
|
+
"webpack-cli": "5.0.2",
|
|
87
|
+
"webpack-dev-server": "4.13.3"
|
|
87
88
|
},
|
|
88
89
|
"scripts": {
|
|
89
90
|
"webpack-start": "webpack-dev-server --open",
|
|
@@ -102,7 +103,8 @@
|
|
|
102
103
|
"generate": "plop --plopfile internals/generators/plopfile.ts",
|
|
103
104
|
"cleanAndSetup": "ts-node ./internals/scripts/clean.ts",
|
|
104
105
|
"prettify": "prettier --write",
|
|
105
|
-
"extract-messages": "i18next-scanner --config=internals/extractMessages/i18next-scanner.config.js"
|
|
106
|
+
"extract-messages": "i18next-scanner --config=internals/extractMessages/i18next-scanner.config.js",
|
|
107
|
+
"prepublishOnly": "webpack --mode=production"
|
|
106
108
|
},
|
|
107
109
|
"eslintConfig": {
|
|
108
110
|
"extends": "react-app"
|
|
@@ -150,6 +152,9 @@
|
|
|
150
152
|
},
|
|
151
153
|
"devDependencies": {
|
|
152
154
|
"@babel/plugin-proposal-class-properties": "7.18.6",
|
|
155
|
+
"eslint-config-prettier": "8.8.0",
|
|
156
|
+
"eslint-plugin-prettier": "4.2.1",
|
|
157
|
+
"eslint-plugin-react-hooks": "4.6.0",
|
|
153
158
|
"html-webpack-plugin": "5.5.1",
|
|
154
159
|
"jest": "^29.5.0",
|
|
155
160
|
"mini-css-extract-plugin": "2.7.5"
|
|
@@ -14,30 +14,70 @@ exports[`<App /> should render and match the snapshot 1`] = `
|
|
|
14
14
|
name="description"
|
|
15
15
|
/>
|
|
16
16
|
</Helmet>
|
|
17
|
-
<
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
17
|
+
<Context.Provider
|
|
18
|
+
value={
|
|
19
|
+
Object {
|
|
20
|
+
"DataJunctionAPI": Object {
|
|
21
|
+
"dag": [Function],
|
|
22
|
+
"downstreams": [Function],
|
|
23
|
+
"lineage": [Function],
|
|
24
|
+
"metric": [Function],
|
|
25
|
+
"namespace": [Function],
|
|
26
|
+
"namespaces": [Function],
|
|
27
|
+
"node": [Function],
|
|
28
|
+
"upstreams": [Function],
|
|
29
|
+
},
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
>
|
|
33
|
+
<Routes>
|
|
34
|
+
<Route
|
|
35
|
+
element={<Unknown />}
|
|
36
|
+
path="/"
|
|
37
|
+
>
|
|
38
|
+
<React.Fragment>
|
|
39
|
+
<Route
|
|
40
|
+
path="nodes"
|
|
41
|
+
>
|
|
42
|
+
<Route
|
|
43
|
+
element={<NodePage />}
|
|
44
|
+
path=":name"
|
|
45
|
+
/>
|
|
46
|
+
</Route>
|
|
47
|
+
<Route
|
|
48
|
+
element={
|
|
49
|
+
<ListNamespacesPage
|
|
50
|
+
djClient={
|
|
51
|
+
Object {
|
|
52
|
+
"dag": [Function],
|
|
53
|
+
"downstreams": [Function],
|
|
54
|
+
"lineage": [Function],
|
|
55
|
+
"metric": [Function],
|
|
56
|
+
"namespace": [Function],
|
|
57
|
+
"namespaces": [Function],
|
|
58
|
+
"node": [Function],
|
|
59
|
+
"upstreams": [Function],
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/>
|
|
63
|
+
}
|
|
64
|
+
path="/"
|
|
65
|
+
/>
|
|
66
|
+
<Route
|
|
67
|
+
path="namespaces"
|
|
68
|
+
>
|
|
69
|
+
<Route
|
|
70
|
+
element={<NamespacePage />}
|
|
71
|
+
path=":namespace"
|
|
72
|
+
/>
|
|
73
|
+
</Route>
|
|
74
|
+
</React.Fragment>
|
|
75
|
+
</Route>
|
|
76
|
+
<Route
|
|
77
|
+
element={<Unknown />}
|
|
78
|
+
path="*"
|
|
79
|
+
/>
|
|
80
|
+
</Routes>
|
|
81
|
+
</Context.Provider>
|
|
42
82
|
</BrowserRouter>
|
|
43
83
|
`;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Component } from 'react';
|
|
2
|
+
|
|
3
|
+
export default class DashboardItem extends Component {
|
|
4
|
+
render() {
|
|
5
|
+
const { label, value } = this.props;
|
|
6
|
+
return (
|
|
7
|
+
// <div className="col-xl col-md-6 col-12">
|
|
8
|
+
// <div className="card">
|
|
9
|
+
// <div className="card-body">
|
|
10
|
+
// <div className="align-items-center row">
|
|
11
|
+
// <div className="col"><h6 className="text-uppercase text-muted mb-2">{ label }</h6><span
|
|
12
|
+
// className="h2 mb-0">{ value }</span><span className="mt-n1 ms-2 badge bg-success-soft">+3.5%</span></div>
|
|
13
|
+
// <div className="col-auto">
|
|
14
|
+
// <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
|
15
|
+
// stroke-linecap="round" stroke-linejoin="round" className="feather feather-dollar-sign text-muted">
|
|
16
|
+
// <g>
|
|
17
|
+
// <line x1="12" y1="1" x2="12" y2="23"></line>
|
|
18
|
+
// <path d="M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"></path>
|
|
19
|
+
// </g>
|
|
20
|
+
// </svg>
|
|
21
|
+
// </div>
|
|
22
|
+
// </div>
|
|
23
|
+
// </div>
|
|
24
|
+
// </div>
|
|
25
|
+
// </div>
|
|
26
|
+
<div></div>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -7,15 +7,8 @@ export default class Tab extends Component {
|
|
|
7
7
|
<div className={selectedTab === id ? 'col active' : 'col'}>
|
|
8
8
|
<div className="header-tabs nav-overflow nav nav-tabs">
|
|
9
9
|
<div className="nav-item">
|
|
10
|
-
<button
|
|
11
|
-
id={id}
|
|
12
|
-
role="button"
|
|
13
|
-
className="nav-link"
|
|
14
|
-
tabIndex="0"
|
|
15
|
-
onClick={onClick}
|
|
16
|
-
>
|
|
10
|
+
<button id={id} className="nav-link" tabIndex="0" onClick={onClick}>
|
|
17
11
|
{this.props.name}
|
|
18
|
-
{/*<span className="rounded-pill badge bg-secondary-soft">823</span>*/}
|
|
19
12
|
</button>
|
|
20
13
|
</div>
|
|
21
14
|
</div>
|
|
@@ -61,12 +61,12 @@ export function DJNode({ id, data }) {
|
|
|
61
61
|
<td style={{ textAlign: 'right' }}>{col.type}</td>
|
|
62
62
|
</tr>
|
|
63
63
|
));
|
|
64
|
-
const dimensionsRenderer = data =>
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
64
|
+
// const dimensionsRenderer = data =>
|
|
65
|
+
// data.dimensions.map(dim => (
|
|
66
|
+
// <tr>
|
|
67
|
+
// <td>{dim}</td>
|
|
68
|
+
// </tr>
|
|
69
|
+
// ));
|
|
70
70
|
|
|
71
71
|
return (
|
|
72
72
|
<>
|
package/src/app/index.tsx
CHANGED
|
@@ -12,6 +12,8 @@ import { NodePage } from './pages/NodePage/Loadable';
|
|
|
12
12
|
import { NotFoundPage } from './pages/NotFoundPage/Loadable';
|
|
13
13
|
import { Root } from './pages/Root/Loadable';
|
|
14
14
|
import { ListNamespacesPage } from './pages/ListNamespacesPage';
|
|
15
|
+
import DJClientContext from './providers/djclient';
|
|
16
|
+
import { DataJunctionAPI } from './services/DJService';
|
|
15
17
|
|
|
16
18
|
export function App() {
|
|
17
19
|
return (
|
|
@@ -25,21 +27,31 @@ export function App() {
|
|
|
25
27
|
content="DataJunction serves as a semantic layer to help manage metrics"
|
|
26
28
|
/>
|
|
27
29
|
</Helmet>
|
|
30
|
+
<DJClientContext.Provider value={{ DataJunctionAPI }}>
|
|
31
|
+
<Routes>
|
|
32
|
+
<Route
|
|
33
|
+
path="/"
|
|
34
|
+
element={<Root />}
|
|
35
|
+
children={
|
|
36
|
+
<>
|
|
37
|
+
<Route path="nodes" key="nodes">
|
|
38
|
+
<Route path=":name" element={<NodePage />} />
|
|
39
|
+
</Route>
|
|
28
40
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
</
|
|
41
|
+
<Route path="/" element={<ListNamespacesPage />} key="index" />
|
|
42
|
+
<Route path="namespaces">
|
|
43
|
+
<Route
|
|
44
|
+
path=":namespace"
|
|
45
|
+
element={<NamespacePage />}
|
|
46
|
+
key="namespaces"
|
|
47
|
+
/>
|
|
48
|
+
</Route>
|
|
49
|
+
</>
|
|
50
|
+
}
|
|
51
|
+
/>
|
|
52
|
+
<Route path="*" element={<NotFoundPage />} />
|
|
53
|
+
</Routes>
|
|
54
|
+
</DJClientContext.Provider>
|
|
43
55
|
</BrowserRouter>
|
|
44
56
|
);
|
|
45
57
|
}
|
|
@@ -1,29 +1,33 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { useEffect, useState } from 'react';
|
|
3
|
-
import { DataJunctionAPI } from '../../services/DJService';
|
|
2
|
+
import { useContext, useEffect, useState } from 'react';
|
|
4
3
|
import NamespaceHeader from '../../components/NamespaceHeader';
|
|
4
|
+
import { DataJunctionAPI } from '../../services/DJService';
|
|
5
|
+
import DJClientContext from '../../providers/djclient';
|
|
6
|
+
// const datajunction = require('datajunction');
|
|
7
|
+
// const dj = new datajunction.DJClient('http://localhost:8000');
|
|
5
8
|
|
|
6
9
|
export function ListNamespacesPage() {
|
|
10
|
+
const djClient = useContext(DJClientContext).DataJunctionAPI;
|
|
7
11
|
const [state, setState] = useState({
|
|
8
12
|
namespaces: [],
|
|
9
13
|
});
|
|
10
14
|
|
|
11
15
|
useEffect(() => {
|
|
12
16
|
const fetchData = async () => {
|
|
13
|
-
const namespaces = await
|
|
17
|
+
const namespaces = await djClient.namespaces();
|
|
14
18
|
setState({
|
|
15
19
|
namespaces: namespaces,
|
|
16
20
|
});
|
|
17
21
|
};
|
|
18
22
|
fetchData().catch(console.error);
|
|
19
|
-
}, []);
|
|
23
|
+
}, [djClient, djClient.namespaces]);
|
|
20
24
|
|
|
21
25
|
const namespacesList = state.namespaces.map(node => (
|
|
22
26
|
<tr>
|
|
23
27
|
<td>
|
|
24
28
|
<a href={'/namespaces/' + node.namespace}>{node.namespace}</a>
|
|
25
29
|
</td>
|
|
26
|
-
<td
|
|
30
|
+
<td></td>
|
|
27
31
|
</tr>
|
|
28
32
|
));
|
|
29
33
|
|
|
@@ -50,3 +54,7 @@ export function ListNamespacesPage() {
|
|
|
50
54
|
</>
|
|
51
55
|
);
|
|
52
56
|
}
|
|
57
|
+
|
|
58
|
+
ListNamespacesPage.defaultProps = {
|
|
59
|
+
djClient: DataJunctionAPI,
|
|
60
|
+
};
|
|
@@ -5,10 +5,12 @@
|
|
|
5
5
|
import * as React from 'react';
|
|
6
6
|
import { lazyLoad } from '../../../utils/loadable';
|
|
7
7
|
|
|
8
|
-
export const NamespacePage =
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
export const NamespacePage = props => {
|
|
9
|
+
return lazyLoad(
|
|
10
|
+
() => import('./index'),
|
|
11
|
+
module => module.NamespacePage,
|
|
12
|
+
{
|
|
13
|
+
fallback: <div></div>,
|
|
14
|
+
},
|
|
15
|
+
)(props);
|
|
16
|
+
};
|
|
@@ -21,22 +21,25 @@ exports[`<NamespacePage /> should render and match the snapshot 1`] = `
|
|
|
21
21
|
className="card-table table"
|
|
22
22
|
>
|
|
23
23
|
<thead>
|
|
24
|
-
<
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
24
|
+
<tr>
|
|
25
|
+
<th>
|
|
26
|
+
Namespace
|
|
27
|
+
</th>
|
|
28
|
+
<th>
|
|
29
|
+
Name
|
|
30
|
+
</th>
|
|
31
|
+
<th>
|
|
32
|
+
Type
|
|
33
|
+
</th>
|
|
34
|
+
<th>
|
|
35
|
+
Status
|
|
36
|
+
</th>
|
|
37
|
+
<th>
|
|
38
|
+
Mode
|
|
39
|
+
</th>
|
|
40
|
+
</tr>
|
|
39
41
|
</thead>
|
|
42
|
+
<tbody />
|
|
40
43
|
</table>
|
|
41
44
|
</div>
|
|
42
45
|
</div>
|
|
@@ -1,20 +1,12 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { useParams } from 'react-router-dom';
|
|
3
|
-
import { useEffect, useState } from 'react';
|
|
4
|
-
import { DataJunctionAPI } from '../../services/DJService';
|
|
3
|
+
import { useContext, useEffect, useState } from 'react';
|
|
5
4
|
import NamespaceHeader from '../../components/NamespaceHeader';
|
|
6
5
|
import NodeStatus from '../NodePage/NodeStatus';
|
|
7
|
-
|
|
8
|
-
export async function loader({ params }) {
|
|
9
|
-
const djNode = await DataJunctionAPI.node(params.name);
|
|
10
|
-
if (djNode.type === 'metric') {
|
|
11
|
-
const metricNode = await DataJunctionAPI.metric(params.name);
|
|
12
|
-
djNode.dimensions = metricNode.dimensions;
|
|
13
|
-
}
|
|
14
|
-
return djNode;
|
|
15
|
-
}
|
|
6
|
+
import DJClientContext from '../../providers/djclient';
|
|
16
7
|
|
|
17
8
|
export function NamespacePage() {
|
|
9
|
+
const djClient = useContext(DJClientContext).DataJunctionAPI;
|
|
18
10
|
const { namespace } = useParams();
|
|
19
11
|
|
|
20
12
|
const [state, setState] = useState({
|
|
@@ -24,9 +16,9 @@ export function NamespacePage() {
|
|
|
24
16
|
|
|
25
17
|
useEffect(() => {
|
|
26
18
|
const fetchData = async () => {
|
|
27
|
-
const djNodes = await
|
|
19
|
+
const djNodes = await djClient.namespace(namespace);
|
|
28
20
|
const nodes = djNodes.map(node => {
|
|
29
|
-
return
|
|
21
|
+
return djClient.node(node);
|
|
30
22
|
});
|
|
31
23
|
const foundNodes = await Promise.all(nodes);
|
|
32
24
|
setState({
|
|
@@ -35,7 +27,7 @@ export function NamespacePage() {
|
|
|
35
27
|
});
|
|
36
28
|
};
|
|
37
29
|
fetchData().catch(console.error);
|
|
38
|
-
}, [namespace]);
|
|
30
|
+
}, [djClient, namespace]);
|
|
39
31
|
|
|
40
32
|
const nodesList = state.nodes.map(node => (
|
|
41
33
|
<tr>
|
|
@@ -77,13 +69,15 @@ export function NamespacePage() {
|
|
|
77
69
|
<div className="table-responsive">
|
|
78
70
|
<table className="card-table table">
|
|
79
71
|
<thead>
|
|
80
|
-
<
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
72
|
+
<tr>
|
|
73
|
+
<th>Namespace</th>
|
|
74
|
+
<th>Name</th>
|
|
75
|
+
<th>Type</th>
|
|
76
|
+
<th>Status</th>
|
|
77
|
+
<th>Mode</th>
|
|
78
|
+
</tr>
|
|
85
79
|
</thead>
|
|
86
|
-
{nodesList}
|
|
80
|
+
<tbody>{nodesList}</tbody>
|
|
87
81
|
</table>
|
|
88
82
|
</div>
|
|
89
83
|
</div>
|
|
@@ -5,10 +5,12 @@
|
|
|
5
5
|
import * as React from 'react';
|
|
6
6
|
import { lazyLoad } from '../../../utils/loadable';
|
|
7
7
|
|
|
8
|
-
export const NodePage =
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
export const NodePage = props => {
|
|
9
|
+
return lazyLoad(
|
|
10
|
+
() => import('./index'),
|
|
11
|
+
module => module.NodePage,
|
|
12
|
+
{
|
|
13
|
+
fallback: <div></div>,
|
|
14
|
+
},
|
|
15
|
+
)(props);
|
|
16
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useCallback, useEffect, useMemo } from 'react';
|
|
1
|
+
import React, { useCallback, useContext, useEffect, useMemo } from 'react';
|
|
2
2
|
import ReactFlow, {
|
|
3
3
|
addEdge,
|
|
4
4
|
MiniMap,
|
|
@@ -12,10 +12,11 @@ import ReactFlow, {
|
|
|
12
12
|
import '../../../styles/dag.css';
|
|
13
13
|
import 'reactflow/dist/style.css';
|
|
14
14
|
import DJNode from '../../components/djgraph/DJNode';
|
|
15
|
-
import { DataJunctionAPI } from '../../services/DJService';
|
|
16
15
|
import dagre from 'dagre';
|
|
16
|
+
import DJClientContext from '../../providers/djclient';
|
|
17
17
|
|
|
18
18
|
const NodeLineage = djNode => {
|
|
19
|
+
const djClient = useContext(DJClientContext).DataJunctionAPI;
|
|
19
20
|
const nodeTypes = useMemo(() => ({ DJNode: DJNode }), []);
|
|
20
21
|
|
|
21
22
|
const [nodes, setNodes, onNodesChange] = useNodesState([]);
|
|
@@ -25,47 +26,48 @@ const NodeLineage = djNode => {
|
|
|
25
26
|
height: 100,
|
|
26
27
|
width: 150,
|
|
27
28
|
};
|
|
28
|
-
const dagreGraph = new dagre.graphlib.Graph();
|
|
29
|
-
dagreGraph.setDefaultEdgeLabel(() => ({}));
|
|
30
29
|
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
edges,
|
|
34
|
-
direction = 'LR',
|
|
35
|
-
nodeWidth = 800,
|
|
36
|
-
nodeHeight = 150,
|
|
37
|
-
) => {
|
|
38
|
-
const isHorizontal = direction === 'TB';
|
|
39
|
-
dagreGraph.setGraph({ rankdir: direction });
|
|
40
|
-
|
|
41
|
-
nodes.forEach(node => {
|
|
42
|
-
dagreGraph.setNode(node.id, { width: nodeWidth, height: nodeHeight });
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
edges.forEach(edge => {
|
|
46
|
-
dagreGraph.setEdge(edge.source, edge.target);
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
dagre.layout(dagreGraph);
|
|
50
|
-
|
|
51
|
-
nodes.forEach(node => {
|
|
52
|
-
const nodeWithPosition = dagreGraph.node(node.id);
|
|
53
|
-
node.targetPosition = isHorizontal ? 'left' : 'top';
|
|
54
|
-
node.sourcePosition = isHorizontal ? 'right' : 'bottom';
|
|
55
|
-
node.position = {
|
|
56
|
-
x: nodeWithPosition.x - nodeWidth / 2,
|
|
57
|
-
y: nodeWithPosition.y - nodeHeight / 2,
|
|
58
|
-
};
|
|
59
|
-
return node;
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
return { nodes, edges };
|
|
63
|
-
};
|
|
30
|
+
const dagreGraph = useMemo(() => new dagre.graphlib.Graph(), []);
|
|
31
|
+
dagreGraph.setDefaultEdgeLabel(() => ({}));
|
|
64
32
|
|
|
65
33
|
useEffect(() => {
|
|
34
|
+
const setElementsLayout = (
|
|
35
|
+
nodes,
|
|
36
|
+
edges,
|
|
37
|
+
direction = 'LR',
|
|
38
|
+
nodeWidth = 800,
|
|
39
|
+
nodeHeight = 150,
|
|
40
|
+
) => {
|
|
41
|
+
const isHorizontal = direction === 'TB';
|
|
42
|
+
dagreGraph.setGraph({ rankdir: direction });
|
|
43
|
+
|
|
44
|
+
nodes.forEach(node => {
|
|
45
|
+
dagreGraph.setNode(node.id, { width: nodeWidth, height: nodeHeight });
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
edges.forEach(edge => {
|
|
49
|
+
dagreGraph.setEdge(edge.source, edge.target);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
dagre.layout(dagreGraph);
|
|
53
|
+
|
|
54
|
+
nodes.forEach(node => {
|
|
55
|
+
const nodeWithPosition = dagreGraph.node(node.id);
|
|
56
|
+
node.targetPosition = isHorizontal ? 'left' : 'top';
|
|
57
|
+
node.sourcePosition = isHorizontal ? 'right' : 'bottom';
|
|
58
|
+
node.position = {
|
|
59
|
+
x: nodeWithPosition.x - nodeWidth / 2,
|
|
60
|
+
y: nodeWithPosition.y - nodeHeight / 2,
|
|
61
|
+
};
|
|
62
|
+
return node;
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
return { nodes, edges };
|
|
66
|
+
};
|
|
67
|
+
|
|
66
68
|
const dagFetch = async () => {
|
|
67
|
-
let upstreams = await
|
|
68
|
-
let downstreams = await
|
|
69
|
+
let upstreams = await djClient.upstreams(djNode.djNode.name);
|
|
70
|
+
let downstreams = await djClient.downstreams(djNode.djNode.name);
|
|
69
71
|
var djNodes = [djNode.djNode];
|
|
70
72
|
for (const iterable of [upstreams, downstreams]) {
|
|
71
73
|
for (const item of iterable) {
|
|
@@ -117,7 +119,7 @@ const NodeLineage = djNode => {
|
|
|
117
119
|
label:
|
|
118
120
|
node.table !== null
|
|
119
121
|
? String(node.schema_ + '.' + node.table)
|
|
120
|
-
:
|
|
122
|
+
: 'default.' + node.name,
|
|
121
123
|
table: node.table,
|
|
122
124
|
name: String(node.name),
|
|
123
125
|
display_name: String(node.display_name),
|
|
@@ -130,18 +132,17 @@ const NodeLineage = djNode => {
|
|
|
130
132
|
// extent: 'parent',
|
|
131
133
|
};
|
|
132
134
|
});
|
|
133
|
-
console.log(djNodes);
|
|
134
135
|
setNodes(nodes);
|
|
135
136
|
setEdges(edges);
|
|
136
137
|
setElementsLayout(nodes, edges);
|
|
137
138
|
};
|
|
138
139
|
|
|
139
140
|
dagFetch();
|
|
140
|
-
}, []);
|
|
141
|
+
}, [dagreGraph, djClient, djNode.djNode, setEdges, setNodes]);
|
|
141
142
|
|
|
142
143
|
const onConnect = useCallback(
|
|
143
144
|
params => setEdges(eds => addEdge(params, eds)),
|
|
144
|
-
[],
|
|
145
|
+
[setEdges],
|
|
145
146
|
);
|
|
146
147
|
|
|
147
148
|
return (
|