datajunction-ui 0.0.1-rc.3 → 0.0.1-rc.5
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/package.json +11 -5
- package/src/app/__tests__/__snapshots__/index.test.tsx.snap +95 -25
- package/src/app/components/Tab.jsx +1 -8
- package/src/app/components/djgraph/DJNode.jsx +6 -6
- package/src/app/index.tsx +31 -23
- package/src/app/pages/ListNamespacesPage/index.jsx +10 -4
- package/src/app/pages/NamespacePage/Loadable.jsx +9 -7
- package/src/app/pages/NamespacePage/index.jsx +4 -13
- package/src/app/pages/NodePage/Loadable.jsx +9 -7
- package/src/app/pages/NodePage/NodeGraphTab.jsx +42 -42
- package/src/app/pages/NodePage/index.jsx +5 -5
- package/src/styles/index.css +4 -4
- package/webpack.config.js +11 -0
- package/dist/5fa71a03d45dc2e3d61447f3013a303d.png +0 -0
- package/dist/index.html +0 -1
- package/dist/main.js +0 -23303
- package/dist/static/main.05a86d446163fd5f17d3.js +0 -119255
- package/dist/static/main.05a86d446163fd5f17d3.js.LICENSE.txt +0 -98
- package/dist/static/main.9e53bed734dae98e5b10.js +0 -117977
- package/dist/static/main.9e53bed734dae98e5b10.js.LICENSE.txt +0 -98
- package/dist/static/main.ebaa9bc7ec95d2f8d4fb.js +0 -2
- package/dist/static/main.ebaa9bc7ec95d2f8d4fb.js.LICENSE.txt +0 -98
- package/dist/static/main.js +0 -119255
- package/dist/static/main.js.LICENSE.txt +0 -98
- package/dist/static/vendor.05a86d446163fd5f17d3.js +0 -9835
- package/dist/static/vendor.05a86d446163fd5f17d3.js.LICENSE.txt +0 -29
- package/dist/static/vendor.9e53bed734dae98e5b10.js +0 -9491
- package/dist/static/vendor.9e53bed734dae98e5b10.js.LICENSE.txt +0 -29
- package/dist/static/vendor.ebaa9bc7ec95d2f8d4fb.js +0 -2
- package/dist/static/vendor.ebaa9bc7ec95d2f8d4fb.js.LICENSE.txt +0 -29
- package/dist/static/vendor.js +0 -9835
- package/dist/static/vendor.js.LICENSE.txt +0 -29
- 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/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.5",
|
|
4
4
|
"description": "DataJunction Metrics Platform UI",
|
|
5
5
|
"module": "src/index.tsx",
|
|
6
6
|
"repository": {
|
|
@@ -38,12 +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",
|
|
46
|
+
"datajunction": "0.0.1-rc.0",
|
|
47
|
+
"file-loader": "6.2.0",
|
|
47
48
|
"fontfaceobserver": "2.3.0",
|
|
48
49
|
"husky": "8.0.1",
|
|
49
50
|
"i18next": "21.9.2",
|
|
@@ -74,6 +75,7 @@
|
|
|
74
75
|
"serve": "14.0.1",
|
|
75
76
|
"shelljs": "0.8.5",
|
|
76
77
|
"sql-formatter": "^12.2.0",
|
|
78
|
+
"style-loader": "3.3.2",
|
|
77
79
|
"stylelint": "14.12.0",
|
|
78
80
|
"stylelint-config-recommended": "9.0.0",
|
|
79
81
|
"ts-loader": "9.4.2",
|
|
@@ -81,7 +83,8 @@
|
|
|
81
83
|
"typescript": "4.6.4",
|
|
82
84
|
"web-vitals": "2.1.4",
|
|
83
85
|
"webpack": "5.81.0",
|
|
84
|
-
"webpack-cli": "5.0.2"
|
|
86
|
+
"webpack-cli": "5.0.2",
|
|
87
|
+
"webpack-dev-server": "4.13.3"
|
|
85
88
|
},
|
|
86
89
|
"scripts": {
|
|
87
90
|
"webpack-start": "webpack-dev-server --open",
|
|
@@ -149,6 +152,9 @@
|
|
|
149
152
|
},
|
|
150
153
|
"devDependencies": {
|
|
151
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",
|
|
152
158
|
"html-webpack-plugin": "5.5.1",
|
|
153
159
|
"jest": "^29.5.0",
|
|
154
160
|
"mini-css-extract-plugin": "2.7.5"
|
|
@@ -14,30 +14,100 @@ 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={
|
|
44
|
+
<NodePage
|
|
45
|
+
djClient={
|
|
46
|
+
Object {
|
|
47
|
+
"dag": [Function],
|
|
48
|
+
"downstreams": [Function],
|
|
49
|
+
"lineage": [Function],
|
|
50
|
+
"metric": [Function],
|
|
51
|
+
"namespace": [Function],
|
|
52
|
+
"namespaces": [Function],
|
|
53
|
+
"node": [Function],
|
|
54
|
+
"upstreams": [Function],
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/>
|
|
58
|
+
}
|
|
59
|
+
path=":name"
|
|
60
|
+
/>
|
|
61
|
+
</Route>
|
|
62
|
+
<Route
|
|
63
|
+
element={
|
|
64
|
+
<ListNamespacesPage
|
|
65
|
+
djClient={
|
|
66
|
+
Object {
|
|
67
|
+
"dag": [Function],
|
|
68
|
+
"downstreams": [Function],
|
|
69
|
+
"lineage": [Function],
|
|
70
|
+
"metric": [Function],
|
|
71
|
+
"namespace": [Function],
|
|
72
|
+
"namespaces": [Function],
|
|
73
|
+
"node": [Function],
|
|
74
|
+
"upstreams": [Function],
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/>
|
|
78
|
+
}
|
|
79
|
+
path="/"
|
|
80
|
+
/>
|
|
81
|
+
<Route
|
|
82
|
+
path="namespaces"
|
|
83
|
+
>
|
|
84
|
+
<Route
|
|
85
|
+
element={
|
|
86
|
+
<NamespacePage
|
|
87
|
+
djClient={
|
|
88
|
+
Object {
|
|
89
|
+
"dag": [Function],
|
|
90
|
+
"downstreams": [Function],
|
|
91
|
+
"lineage": [Function],
|
|
92
|
+
"metric": [Function],
|
|
93
|
+
"namespace": [Function],
|
|
94
|
+
"namespaces": [Function],
|
|
95
|
+
"node": [Function],
|
|
96
|
+
"upstreams": [Function],
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/>
|
|
100
|
+
}
|
|
101
|
+
path=":namespace"
|
|
102
|
+
/>
|
|
103
|
+
</Route>
|
|
104
|
+
</React.Fragment>
|
|
105
|
+
</Route>
|
|
106
|
+
<Route
|
|
107
|
+
element={<Unknown />}
|
|
108
|
+
path="*"
|
|
109
|
+
/>
|
|
110
|
+
</Routes>
|
|
111
|
+
</Context.Provider>
|
|
42
112
|
</BrowserRouter>
|
|
43
113
|
`;
|
|
@@ -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,8 +12,13 @@ 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 { DataJunctionAPI } from './services/DJService';
|
|
16
|
+
|
|
17
|
+
const DJClientContext = React.createContext({ DataJunctionAPI });
|
|
15
18
|
|
|
16
19
|
export function App() {
|
|
20
|
+
const DJClient = React.useContext(DJClientContext);
|
|
21
|
+
|
|
17
22
|
return (
|
|
18
23
|
<BrowserRouter>
|
|
19
24
|
<Helmet
|
|
@@ -25,30 +30,33 @@ export function App() {
|
|
|
25
30
|
content="DataJunction serves as a semantic layer to help manage metrics"
|
|
26
31
|
/>
|
|
27
32
|
</Helmet>
|
|
33
|
+
<DJClientContext.Provider value={{ DataJunctionAPI: DataJunctionAPI }}>
|
|
34
|
+
<Routes>
|
|
35
|
+
<Route
|
|
36
|
+
path="/"
|
|
37
|
+
element={<Root />}
|
|
38
|
+
children={
|
|
39
|
+
<>
|
|
40
|
+
<Route path="nodes" key="nodes">
|
|
41
|
+
<Route path=":name" element={<NodePage djClient={ DJClient.DataJunctionAPI } />} />
|
|
42
|
+
</Route>
|
|
28
43
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
element={<NamespacePage />}
|
|
44
|
-
key="namespaces"
|
|
45
|
-
/>
|
|
46
|
-
</Route>
|
|
47
|
-
</>
|
|
48
|
-
}
|
|
49
|
-
/>
|
|
50
|
-
<Route path="*" element={<NotFoundPage />} />
|
|
51
|
-
</Routes>
|
|
44
|
+
<Route path="/" element={<ListNamespacesPage djClient={ DJClient.DataJunctionAPI }/>} key="index" />
|
|
45
|
+
<Route path="namespaces">
|
|
46
|
+
<Route
|
|
47
|
+
path=":namespace"
|
|
48
|
+
element={<NamespacePage djClient={ DJClient.DataJunctionAPI }/>}
|
|
49
|
+
key="namespaces"
|
|
50
|
+
/>
|
|
51
|
+
</Route>
|
|
52
|
+
</>
|
|
53
|
+
}
|
|
54
|
+
/>
|
|
55
|
+
<Route path="*" element={<NotFoundPage />} />
|
|
56
|
+
</Routes>
|
|
57
|
+
</DJClientContext.Provider>
|
|
52
58
|
</BrowserRouter>
|
|
53
59
|
);
|
|
54
60
|
}
|
|
61
|
+
|
|
62
|
+
export { DJClientContext };
|
|
@@ -1,22 +1,24 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { useEffect, useState } from 'react';
|
|
3
|
-
import { DataJunctionAPI } from '../../services/DJService';
|
|
4
3
|
import NamespaceHeader from '../../components/NamespaceHeader';
|
|
4
|
+
import { DataJunctionAPI } from '../../services/DJService';
|
|
5
|
+
// const datajunction = require('datajunction');
|
|
6
|
+
// const dj = new datajunction.DJClient('http://localhost:8000');
|
|
5
7
|
|
|
6
|
-
export function ListNamespacesPage() {
|
|
8
|
+
export function ListNamespacesPage({ djClient }) {
|
|
7
9
|
const [state, setState] = useState({
|
|
8
10
|
namespaces: [],
|
|
9
11
|
});
|
|
10
12
|
|
|
11
13
|
useEffect(() => {
|
|
12
14
|
const fetchData = async () => {
|
|
13
|
-
const namespaces = await
|
|
15
|
+
const namespaces = await djClient.namespaces.get();
|
|
14
16
|
setState({
|
|
15
17
|
namespaces: namespaces,
|
|
16
18
|
});
|
|
17
19
|
};
|
|
18
20
|
fetchData().catch(console.error);
|
|
19
|
-
}, []);
|
|
21
|
+
}, [djClient.namespaces]);
|
|
20
22
|
|
|
21
23
|
const namespacesList = state.namespaces.map(node => (
|
|
22
24
|
<tr>
|
|
@@ -50,3 +52,7 @@ export function ListNamespacesPage() {
|
|
|
50
52
|
</>
|
|
51
53
|
);
|
|
52
54
|
}
|
|
55
|
+
|
|
56
|
+
ListNamespacesPage.defaultProps = {
|
|
57
|
+
djClient: DataJunctionAPI,
|
|
58
|
+
};
|
|
@@ -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
|
+
};
|
|
@@ -5,16 +5,7 @@ import { DataJunctionAPI } from '../../services/DJService';
|
|
|
5
5
|
import NamespaceHeader from '../../components/NamespaceHeader';
|
|
6
6
|
import NodeStatus from '../NodePage/NodeStatus';
|
|
7
7
|
|
|
8
|
-
export
|
|
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
|
-
}
|
|
16
|
-
|
|
17
|
-
export function NamespacePage() {
|
|
8
|
+
export function NamespacePage({ djClient = DataJunctionAPI }) {
|
|
18
9
|
const { namespace } = useParams();
|
|
19
10
|
|
|
20
11
|
const [state, setState] = useState({
|
|
@@ -24,9 +15,9 @@ export function NamespacePage() {
|
|
|
24
15
|
|
|
25
16
|
useEffect(() => {
|
|
26
17
|
const fetchData = async () => {
|
|
27
|
-
const djNodes = await
|
|
18
|
+
const djNodes = await djClient.namespace(namespace);
|
|
28
19
|
const nodes = djNodes.map(node => {
|
|
29
|
-
return
|
|
20
|
+
return djClient.node(node);
|
|
30
21
|
});
|
|
31
22
|
const foundNodes = await Promise.all(nodes);
|
|
32
23
|
setState({
|
|
@@ -35,7 +26,7 @@ export function NamespacePage() {
|
|
|
35
26
|
});
|
|
36
27
|
};
|
|
37
28
|
fetchData().catch(console.error);
|
|
38
|
-
}, [namespace]);
|
|
29
|
+
}, [djClient, namespace]);
|
|
39
30
|
|
|
40
31
|
const nodesList = state.nodes.map(node => (
|
|
41
32
|
<tr>
|
|
@@ -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
|
+
};
|
|
@@ -12,10 +12,9 @@ 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';
|
|
17
16
|
|
|
18
|
-
const NodeLineage = djNode => {
|
|
17
|
+
const NodeLineage = (djNode, djClient) => {
|
|
19
18
|
const nodeTypes = useMemo(() => ({ DJNode: DJNode }), []);
|
|
20
19
|
|
|
21
20
|
const [nodes, setNodes, onNodesChange] = useNodesState([]);
|
|
@@ -25,47 +24,48 @@ const NodeLineage = djNode => {
|
|
|
25
24
|
height: 100,
|
|
26
25
|
width: 150,
|
|
27
26
|
};
|
|
28
|
-
const dagreGraph = new dagre.graphlib.Graph();
|
|
29
|
-
dagreGraph.setDefaultEdgeLabel(() => ({}));
|
|
30
27
|
|
|
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
|
-
};
|
|
28
|
+
const dagreGraph = useMemo(() => new dagre.graphlib.Graph(), []);
|
|
29
|
+
dagreGraph.setDefaultEdgeLabel(() => ({}));
|
|
64
30
|
|
|
65
31
|
useEffect(() => {
|
|
32
|
+
const setElementsLayout = (
|
|
33
|
+
nodes,
|
|
34
|
+
edges,
|
|
35
|
+
direction = 'LR',
|
|
36
|
+
nodeWidth = 800,
|
|
37
|
+
nodeHeight = 150,
|
|
38
|
+
) => {
|
|
39
|
+
const isHorizontal = direction === 'TB';
|
|
40
|
+
dagreGraph.setGraph({ rankdir: direction });
|
|
41
|
+
|
|
42
|
+
nodes.forEach(node => {
|
|
43
|
+
dagreGraph.setNode(node.id, { width: nodeWidth, height: nodeHeight });
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
edges.forEach(edge => {
|
|
47
|
+
dagreGraph.setEdge(edge.source, edge.target);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
dagre.layout(dagreGraph);
|
|
51
|
+
|
|
52
|
+
nodes.forEach(node => {
|
|
53
|
+
const nodeWithPosition = dagreGraph.node(node.id);
|
|
54
|
+
node.targetPosition = isHorizontal ? 'left' : 'top';
|
|
55
|
+
node.sourcePosition = isHorizontal ? 'right' : 'bottom';
|
|
56
|
+
node.position = {
|
|
57
|
+
x: nodeWithPosition.x - nodeWidth / 2,
|
|
58
|
+
y: nodeWithPosition.y - nodeHeight / 2,
|
|
59
|
+
};
|
|
60
|
+
return node;
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
return { nodes, edges };
|
|
64
|
+
};
|
|
65
|
+
|
|
66
66
|
const dagFetch = async () => {
|
|
67
|
-
let upstreams = await
|
|
68
|
-
let downstreams = await
|
|
67
|
+
let upstreams = await djClient.upstreams(djNode.djNode.name);
|
|
68
|
+
let downstreams = await djClient.downstreams(djNode.djNode.name);
|
|
69
69
|
var djNodes = [djNode.djNode];
|
|
70
70
|
for (const iterable of [upstreams, downstreams]) {
|
|
71
71
|
for (const item of iterable) {
|
|
@@ -117,7 +117,7 @@ const NodeLineage = djNode => {
|
|
|
117
117
|
label:
|
|
118
118
|
node.table !== null
|
|
119
119
|
? String(node.schema_ + '.' + node.table)
|
|
120
|
-
:
|
|
120
|
+
: 'default.' + node.name,
|
|
121
121
|
table: node.table,
|
|
122
122
|
name: String(node.name),
|
|
123
123
|
display_name: String(node.display_name),
|
|
@@ -137,11 +137,11 @@ const NodeLineage = djNode => {
|
|
|
137
137
|
};
|
|
138
138
|
|
|
139
139
|
dagFetch();
|
|
140
|
-
}, []);
|
|
140
|
+
}, [dagreGraph, djNode.djNode, setEdges, setNodes]);
|
|
141
141
|
|
|
142
142
|
const onConnect = useCallback(
|
|
143
143
|
params => setEdges(eds => addEdge(params, eds)),
|
|
144
|
-
[],
|
|
144
|
+
[setEdges],
|
|
145
145
|
);
|
|
146
146
|
|
|
147
147
|
return (
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { useParams } from 'react-router-dom';
|
|
3
3
|
import { useEffect, useState } from 'react';
|
|
4
|
-
import { DataJunctionAPI } from '../../services/DJService';
|
|
5
4
|
import Tab from '../../components/Tab';
|
|
6
5
|
import NamespaceHeader from '../../components/NamespaceHeader';
|
|
7
6
|
import NodeInfoTab from './NodeInfoTab';
|
|
8
7
|
import NodeColumnTab from './NodeColumnTab';
|
|
9
8
|
import NodeLineage from './NodeGraphTab';
|
|
9
|
+
import { DataJunctionAPI } from '../../services/DJService';
|
|
10
10
|
|
|
11
|
-
export function NodePage() {
|
|
11
|
+
export function NodePage({ djClient = DataJunctionAPI}) {
|
|
12
12
|
const [state, setState] = useState({
|
|
13
13
|
selectedTab: 0,
|
|
14
14
|
});
|
|
@@ -35,11 +35,11 @@ export function NodePage() {
|
|
|
35
35
|
|
|
36
36
|
useEffect(() => {
|
|
37
37
|
const fetchData = async () => {
|
|
38
|
-
const data = await
|
|
38
|
+
const data = await djClient.node(name);
|
|
39
39
|
setNode(data);
|
|
40
40
|
};
|
|
41
41
|
fetchData().catch(console.error);
|
|
42
|
-
}, [name]);
|
|
42
|
+
}, [djClient, name]);
|
|
43
43
|
|
|
44
44
|
const TabsJson = [
|
|
45
45
|
{
|
|
@@ -66,7 +66,7 @@ export function NodePage() {
|
|
|
66
66
|
tabToDisplay = <NodeColumnTab node={node} />;
|
|
67
67
|
break;
|
|
68
68
|
case 2:
|
|
69
|
-
tabToDisplay = <NodeLineage djNode={node} />;
|
|
69
|
+
tabToDisplay = <NodeLineage djNode={node} djClient={djClient} />;
|
|
70
70
|
break;
|
|
71
71
|
default:
|
|
72
72
|
tabToDisplay = <NodeInfoTab node={node} />;
|
package/src/styles/index.css
CHANGED
|
@@ -379,8 +379,8 @@ tbody th {
|
|
|
379
379
|
}
|
|
380
380
|
|
|
381
381
|
.node_type__cube {
|
|
382
|
-
background-color: #
|
|
383
|
-
color: #
|
|
382
|
+
background-color: #dbafff !important;
|
|
383
|
+
color: #580076;
|
|
384
384
|
}
|
|
385
385
|
|
|
386
386
|
.status__valid {
|
|
@@ -498,8 +498,8 @@ pre {
|
|
|
498
498
|
flex-grow: 0 !important;
|
|
499
499
|
}
|
|
500
500
|
.logo img {
|
|
501
|
-
padding:
|
|
502
|
-
margin-bottom:
|
|
501
|
+
padding: 15px;
|
|
502
|
+
margin-bottom: 0.2rem;
|
|
503
503
|
}
|
|
504
504
|
|
|
505
505
|
.menu-lg-row > .menu-item {
|
package/webpack.config.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const webpack = require('webpack');
|
|
1
2
|
const path = require('path');
|
|
2
3
|
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
|
3
4
|
// const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
|
@@ -37,6 +38,13 @@ module.exports = {
|
|
|
37
38
|
fs: false,
|
|
38
39
|
os: false,
|
|
39
40
|
module: false,
|
|
41
|
+
http: false,
|
|
42
|
+
tls: false,
|
|
43
|
+
https: false,
|
|
44
|
+
url: false,
|
|
45
|
+
browser: false,
|
|
46
|
+
net: false,
|
|
47
|
+
process: false,
|
|
40
48
|
},
|
|
41
49
|
},
|
|
42
50
|
module: {
|
|
@@ -90,6 +98,9 @@ module.exports = {
|
|
|
90
98
|
new HtmlWebpackPlugin({
|
|
91
99
|
template: path.resolve(__dirname, 'public', 'index.html'),
|
|
92
100
|
}),
|
|
101
|
+
new webpack.DefinePlugin({
|
|
102
|
+
REACT_APP_DJ_URL: 'http://localhost:8000',
|
|
103
|
+
}),
|
|
93
104
|
// new MiniCssExtractPlugin({
|
|
94
105
|
// filename: './styles/index.css',
|
|
95
106
|
// }),
|
|
Binary file
|
package/dist/index.html
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<!doctype html><html lang="en"><head><base href="/"/><meta charset="utf-8"/><link rel="icon" href="public/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><link rel="manifest" href="public/manifest.json"/><link rel="manifest" href="src/styles/index.css"/><meta property="og:title" content="DataJunction UI"/><meta property="og:description" content=""/><title>DataJunction App</title><meta name="description" content=""/><script defer="defer" src="/static/main.ebaa9bc7ec95d2f8d4fb.js"></script><script defer="defer" src="/static/vendor.ebaa9bc7ec95d2f8d4fb.js"></script></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;700&display=swap" rel="stylesheet"/></body></html>
|