datajunction-ui 0.0.1-rc.2 → 0.0.1-rc.20

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.
Files changed (135) hide show
  1. package/.env +1 -0
  2. package/.prettierignore +3 -1
  3. package/dj-logo.svg +10 -0
  4. package/package.json +43 -13
  5. package/public/favicon.ico +0 -0
  6. package/src/__tests__/reportWebVitals.test.jsx +44 -0
  7. package/src/app/__tests__/__snapshots__/index.test.tsx.snap +5 -39
  8. package/src/app/components/DeleteNode.jsx +79 -0
  9. package/src/app/components/ListGroupItem.jsx +8 -1
  10. package/src/app/components/NamespaceHeader.jsx +4 -13
  11. package/src/app/components/QueryInfo.jsx +77 -0
  12. package/src/app/components/Tab.jsx +3 -2
  13. package/src/app/components/ToggleSwitch.jsx +20 -0
  14. package/src/app/components/__tests__/QueryInfo.test.jsx +55 -0
  15. package/src/app/components/__tests__/Tab.test.jsx +27 -0
  16. package/src/app/components/__tests__/ToggleSwitch.test.jsx +43 -0
  17. package/src/app/components/__tests__/__snapshots__/ListGroupItem.test.tsx.snap +3 -0
  18. package/src/app/components/__tests__/__snapshots__/NamespaceHeader.test.jsx.snap +2 -18
  19. package/src/app/components/djgraph/Collapse.jsx +46 -0
  20. package/src/app/components/djgraph/DJNode.jsx +60 -82
  21. package/src/app/components/djgraph/DJNodeColumns.jsx +71 -0
  22. package/src/app/components/djgraph/DJNodeDimensions.jsx +75 -0
  23. package/src/app/components/djgraph/LayoutFlow.jsx +104 -0
  24. package/src/app/components/djgraph/__tests__/Collapse.test.jsx +51 -0
  25. package/src/app/components/djgraph/__tests__/DJNodeColumns.test.jsx +83 -0
  26. package/src/app/components/djgraph/__tests__/DJNodeDimensions.test.jsx +118 -0
  27. package/src/app/components/djgraph/__tests__/__snapshots__/DJNode.test.tsx.snap +84 -40
  28. package/src/app/constants.js +2 -0
  29. package/src/app/icons/AlertIcon.jsx +32 -0
  30. package/src/app/icons/CollapsedIcon.jsx +15 -0
  31. package/src/app/icons/DJLogo.jsx +36 -0
  32. package/src/app/icons/DeleteIcon.jsx +21 -0
  33. package/src/app/icons/EditIcon.jsx +18 -0
  34. package/src/app/icons/ExpandedIcon.jsx +15 -0
  35. package/src/app/icons/HorizontalHierarchyIcon.jsx +15 -0
  36. package/src/app/icons/InvalidIcon.jsx +14 -0
  37. package/src/app/icons/PythonIcon.jsx +52 -0
  38. package/src/app/icons/TableIcon.jsx +14 -0
  39. package/src/app/icons/ValidIcon.jsx +14 -0
  40. package/src/app/index.tsx +79 -26
  41. package/src/app/pages/AddEditNodePage/FormikSelect.jsx +46 -0
  42. package/src/app/pages/AddEditNodePage/FullNameField.jsx +37 -0
  43. package/src/app/pages/AddEditNodePage/Loadable.jsx +16 -0
  44. package/src/app/pages/AddEditNodePage/NodeQueryField.jsx +89 -0
  45. package/src/app/pages/AddEditNodePage/__tests__/AddEditNodePageFormFailed.test.jsx +77 -0
  46. package/src/app/pages/AddEditNodePage/__tests__/AddEditNodePageFormSuccess.test.jsx +93 -0
  47. package/src/app/pages/AddEditNodePage/__tests__/FormikSelect.test.jsx +75 -0
  48. package/src/app/pages/AddEditNodePage/__tests__/FullNameField.test.jsx +31 -0
  49. package/src/app/pages/AddEditNodePage/__tests__/NodeQueryField.test.jsx +30 -0
  50. package/src/app/pages/AddEditNodePage/__tests__/__snapshots__/AddEditNodePageFormFailed.test.jsx.snap +53 -0
  51. package/src/app/pages/AddEditNodePage/__tests__/__snapshots__/AddEditNodePageFormSuccess.test.jsx.snap +53 -0
  52. package/src/app/pages/AddEditNodePage/__tests__/__snapshots__/index.test.jsx.snap +3 -0
  53. package/src/app/pages/AddEditNodePage/__tests__/index.test.jsx +178 -0
  54. package/src/app/pages/AddEditNodePage/index.jsx +357 -0
  55. package/src/app/pages/LoginPage/__tests__/index.test.jsx +70 -0
  56. package/src/app/pages/LoginPage/assets/sign-in-with-github.png +0 -0
  57. package/src/app/pages/LoginPage/assets/sign-in-with-google.png +0 -0
  58. package/src/app/pages/LoginPage/index.jsx +90 -0
  59. package/src/app/pages/NamespacePage/Explorer.jsx +57 -0
  60. package/src/app/pages/NamespacePage/Loadable.jsx +9 -7
  61. package/src/app/pages/NamespacePage/__tests__/index.test.jsx +95 -0
  62. package/src/app/pages/NamespacePage/index.jsx +131 -31
  63. package/src/app/pages/NodePage/ClientCodePopover.jsx +32 -0
  64. package/src/app/pages/NodePage/EditColumnPopover.jsx +102 -0
  65. package/src/app/pages/NodePage/LinkDimensionPopover.jsx +135 -0
  66. package/src/app/pages/NodePage/Loadable.jsx +9 -7
  67. package/src/app/pages/NodePage/NodeColumnTab.jsx +106 -27
  68. package/src/app/pages/NodePage/NodeGraphTab.jsx +94 -148
  69. package/src/app/pages/NodePage/NodeHistory.jsx +212 -0
  70. package/src/app/pages/NodePage/NodeInfoTab.jsx +166 -51
  71. package/src/app/pages/NodePage/NodeLineageTab.jsx +84 -0
  72. package/src/app/pages/NodePage/NodeMaterializationTab.jsx +174 -0
  73. package/src/app/pages/NodePage/NodeSQLTab.jsx +82 -0
  74. package/src/app/pages/NodePage/NodeStatus.jsx +14 -20
  75. package/src/app/pages/NodePage/NodesWithDimension.jsx +42 -0
  76. package/src/app/pages/NodePage/__tests__/ClientCodePopover.test.jsx +49 -0
  77. package/src/app/pages/NodePage/__tests__/EditColumnPopover.test.jsx +148 -0
  78. package/src/app/pages/NodePage/__tests__/LinkDimensionPopover.test.jsx +165 -0
  79. package/src/app/pages/NodePage/__tests__/NodeGraphTab.test.jsx +591 -0
  80. package/src/app/pages/NodePage/__tests__/NodeLineageTab.test.jsx +57 -0
  81. package/src/app/pages/NodePage/__tests__/NodePage.test.jsx +725 -0
  82. package/src/app/pages/NodePage/__tests__/NodeWithDimension.test.jsx +175 -0
  83. package/src/app/pages/NodePage/__tests__/__snapshots__/NodePage.test.jsx.snap +402 -0
  84. package/src/app/pages/NodePage/index.jsx +151 -41
  85. package/src/app/pages/NotFoundPage/__tests__/index.test.jsx +16 -0
  86. package/src/app/pages/RegisterTablePage/Loadable.jsx +16 -0
  87. package/src/app/pages/RegisterTablePage/index.jsx +163 -0
  88. package/src/app/pages/Root/__tests__/index.test.jsx +77 -0
  89. package/src/app/pages/Root/index.tsx +32 -4
  90. package/src/app/pages/SQLBuilderPage/Loadable.jsx +16 -0
  91. package/src/app/pages/SQLBuilderPage/__tests__/index.test.jsx +173 -0
  92. package/src/app/pages/SQLBuilderPage/index.jsx +390 -0
  93. package/src/app/providers/djclient.jsx +5 -0
  94. package/src/app/services/DJService.js +388 -22
  95. package/src/app/services/__tests__/DJService.test.jsx +609 -0
  96. package/src/mocks/mockNodes.jsx +1397 -0
  97. package/src/setupTests.ts +31 -1
  98. package/src/styles/dag.css +111 -5
  99. package/src/styles/index.css +467 -31
  100. package/src/styles/login.css +67 -0
  101. package/src/styles/node-creation.scss +197 -0
  102. package/src/styles/styles.scss +44 -0
  103. package/src/styles/styles.scss.d.ts +9 -0
  104. package/src/utils/form.jsx +23 -0
  105. package/tsconfig.json +1 -5
  106. package/webpack.config.js +29 -6
  107. package/.babelrc +0 -4
  108. package/.env.local +0 -4
  109. package/.env.production +0 -1
  110. package/.github/pull_request_template.md +0 -11
  111. package/.github/workflows/ci.yml +0 -33
  112. package/.vscode/extensions.json +0 -7
  113. package/.vscode/launch.json +0 -15
  114. package/.vscode/settings.json +0 -25
  115. package/Dockerfile +0 -7
  116. package/dist/5fa71a03d45dc2e3d61447f3013a303d.png +0 -0
  117. package/dist/index.html +0 -1
  118. package/dist/main.js +0 -23303
  119. package/dist/static/main.05a86d446163fd5f17d3.js +0 -2
  120. package/dist/static/main.05a86d446163fd5f17d3.js.LICENSE.txt +0 -98
  121. package/dist/static/main.9e53bed734dae98e5b10.js +0 -2
  122. package/dist/static/main.9e53bed734dae98e5b10.js.LICENSE.txt +0 -98
  123. package/dist/static/main.js +0 -2
  124. package/dist/static/main.js.LICENSE.txt +0 -98
  125. package/dist/static/vendor.05a86d446163fd5f17d3.js +0 -2
  126. package/dist/static/vendor.05a86d446163fd5f17d3.js.LICENSE.txt +0 -29
  127. package/dist/static/vendor.9e53bed734dae98e5b10.js +0 -2
  128. package/dist/static/vendor.9e53bed734dae98e5b10.js.LICENSE.txt +0 -29
  129. package/dist/static/vendor.js +0 -2
  130. package/dist/static/vendor.js.LICENSE.txt +0 -29
  131. package/dist/vendor.js +0 -281
  132. package/src/app/pages/ListNamespacesPage/Loadable.jsx +0 -14
  133. package/src/app/pages/ListNamespacesPage/index.jsx +0 -52
  134. package/src/app/pages/NamespacePage/__tests__/__snapshots__/index.test.tsx.snap +0 -45
  135. package/src/app/pages/NamespacePage/__tests__/index.test.tsx +0 -14
@@ -0,0 +1,118 @@
1
+ import React from 'react';
2
+ import { render, screen, waitFor } from '@testing-library/react';
3
+ import { DJNodeDimensions } from '../DJNodeDimensions';
4
+ import DJClientContext from '../../../providers/djclient';
5
+
6
+ const mockMetric = jest.fn();
7
+ describe('<DJNodeDimensions />', () => {
8
+ const defaultProps = {
9
+ type: 'metric',
10
+ name: 'TestMetric',
11
+ };
12
+ const mockDJClient = () => {
13
+ return {
14
+ DataJunctionAPI: {
15
+ metric: mockMetric,
16
+ },
17
+ };
18
+ };
19
+
20
+ const DJNodeDimensionsWithContext = (djClient, props) => {
21
+ return (
22
+ <DJClientContext.Provider value={djClient}>
23
+ <DJNodeDimensions {...props} />
24
+ </DJClientContext.Provider>
25
+ );
26
+ };
27
+
28
+ beforeEach(() => {
29
+ // Reset the mock before each test
30
+ mockMetric.mockReset();
31
+ });
32
+
33
+ it('fetches dimensions for metric type', async () => {
34
+ mockMetric.mockResolvedValueOnce({
35
+ dimensions: [{ name: 'test.dimension' }],
36
+ });
37
+ const djClient = mockDJClient();
38
+
39
+ render(
40
+ <DJClientContext.Provider value={djClient}>
41
+ <DJNodeDimensions {...defaultProps} />
42
+ </DJClientContext.Provider>,
43
+ );
44
+ waitFor(() => {
45
+ expect(mockMetric).toHaveBeenCalledWith(defaultProps.name);
46
+ });
47
+ });
48
+
49
+ it('renders dimensions correctly after processing', async () => {
50
+ const testDimensions = [
51
+ {
52
+ name: 'default.us_state.state_name',
53
+ type: 'string',
54
+ path: [
55
+ 'default.repair_order_details.repair_order_id',
56
+ 'default.repair_order.hard_hat_id',
57
+ 'default.hard_hat.state',
58
+ ],
59
+ },
60
+ {
61
+ name: 'default.us_state.state_region',
62
+ type: 'int',
63
+ path: [
64
+ 'default.repair_order_details.repair_order_id',
65
+ 'default.repair_order.hard_hat_id',
66
+ 'default.hard_hat.state',
67
+ ],
68
+ },
69
+ {
70
+ name: 'default.us_state.state_region_description',
71
+ type: 'string',
72
+ path: [
73
+ 'default.repair_order_details.repair_order_id',
74
+ 'default.repair_order.hard_hat_id',
75
+ 'default.hard_hat.state',
76
+ ],
77
+ },
78
+ ];
79
+ mockMetric.mockResolvedValueOnce({ dimensions: testDimensions });
80
+ const djClient = mockDJClient();
81
+
82
+ const { findByText } = render(
83
+ <DJClientContext.Provider value={djClient}>
84
+ <DJNodeDimensions {...defaultProps} />
85
+ </DJClientContext.Provider>,
86
+ );
87
+
88
+ for (const dim of testDimensions) {
89
+ const [attribute, ...nodeName] = dim.name.split('.').reverse();
90
+ const dimension = nodeName.reverse().join('.');
91
+ expect(await findByText(attribute)).toBeInTheDocument();
92
+ expect(await findByText(dimension)).toBeInTheDocument();
93
+ }
94
+ });
95
+
96
+ it('does not fetch dimensions if type is not metric', () => {
97
+ const djClient = mockDJClient();
98
+ render(
99
+ <DJClientContext.Provider value={djClient}>
100
+ <DJNodeDimensions {...defaultProps} type="transform" />
101
+ </DJClientContext.Provider>,
102
+ );
103
+ expect(mockMetric).not.toHaveBeenCalled();
104
+ });
105
+
106
+ it('handles errors gracefully', async () => {
107
+ mockMetric.mockRejectedValueOnce(new Error('API error'));
108
+
109
+ const djClient = mockDJClient();
110
+ render(
111
+ <DJClientContext.Provider value={djClient}>
112
+ <DJNodeDimensions {...defaultProps} />
113
+ </DJClientContext.Provider>,
114
+ );
115
+
116
+ expect(await mockMetric).toHaveBeenCalledWith(defaultProps.name);
117
+ });
118
+ });
@@ -2,24 +2,46 @@
2
2
 
3
3
  exports[`<DJNode /> should render and match the snapshot 1`] = `
4
4
  <React.Fragment>
5
- <Memo(Handle)
6
- position="left"
7
- style={
8
- Object {
9
- "backgroundColor": "#ccc",
10
- }
11
- }
12
- type="target"
13
- />
14
5
  <div
15
- className="dj-node__full"
6
+ className="dj-node__full node_type__source"
16
7
  style={
17
8
  Object {
18
- "backgroundColor": "#7EB46150",
19
- "color": "#7EB461",
9
+ "width": "450px",
20
10
  }
21
11
  }
22
12
  >
13
+ <div
14
+ style={
15
+ Object {
16
+ "display": "flex",
17
+ "flexDirection": "column",
18
+ "height": "100%",
19
+ "justifyContent": "space-between",
20
+ "position": "absolute",
21
+ "top": "50%",
22
+ }
23
+ }
24
+ >
25
+ <Memo(Handle)
26
+ id="shared.dimensions.accounts"
27
+ position="left"
28
+ style={
29
+ Object {
30
+ "background": "transparent",
31
+ "border": "4px solid transparent",
32
+ "borderRadius": "12px",
33
+ "cursor": "pointer",
34
+ "height": "12px",
35
+ "left": 0,
36
+ "position": "absolute",
37
+ "top": "0px",
38
+ "transform": "translate(-100%, -50%)",
39
+ "width": "12px",
40
+ }
41
+ }
42
+ type="target"
43
+ />
44
+ </div>
23
45
  <div
24
46
  className="dj-node__header"
25
47
  >
@@ -35,39 +57,61 @@ exports[`<DJNode /> should render and match the snapshot 1`] = `
35
57
  <b>
36
58
  Source
37
59
  </b>
38
- :
60
+ <br />
39
61
 
62
+ <a
63
+ href="/nodes/shared.dimensions.accounts"
64
+ />
40
65
  <Collapse
41
66
  collapsed={true}
67
+ data={
68
+ Object {
69
+ "column_names": Array [
70
+ "a",
71
+ ],
72
+ "name": "shared.dimensions.accounts",
73
+ "primary_key": Array [
74
+ "id",
75
+ ],
76
+ "type": "source",
77
+ }
78
+ }
42
79
  text="columns"
43
- >
44
- <div
45
- className="dj-node__metadata"
46
- >
47
- <tr>
48
- <td>
49
- <React.Fragment />
50
- </td>
51
- <td
52
- style={
53
- Object {
54
- "textAlign": "right",
55
- }
56
- }
57
- />
58
- </tr>
59
- </div>
60
- </Collapse>
80
+ />
61
81
  </div>
62
- </div>
63
- <Memo(Handle)
64
- position="right"
65
- style={
66
- Object {
67
- "backgroundColor": "#ccc",
82
+ <div
83
+ style={
84
+ Object {
85
+ "display": "flex",
86
+ "flexDirection": "column",
87
+ "height": "100%",
88
+ "justifyContent": "space-between",
89
+ "position": "absolute",
90
+ "right": 0,
91
+ "top": "50%",
92
+ }
68
93
  }
69
- }
70
- type="source"
71
- />
94
+ >
95
+ <Memo(Handle)
96
+ id="shared.dimensions.accounts"
97
+ position="right"
98
+ style={
99
+ Object {
100
+ "background": "transparent",
101
+ "border": "4px solid transparent",
102
+ "borderRadius": "12px",
103
+ "cursor": "pointer",
104
+ "height": "12px",
105
+ "left": 0,
106
+ "position": "absolute",
107
+ "top": "0px",
108
+ "transform": "translate(-90%, -50%)",
109
+ "width": "12px",
110
+ }
111
+ }
112
+ type="source"
113
+ />
114
+ </div>
115
+ </div>
72
116
  </React.Fragment>
73
117
  `;
@@ -0,0 +1,2 @@
1
+ export const DJ_AUTH_COOKIE = '__dj';
2
+ export const DJ_LOGGED_IN_FLAG_COOKIE = '__djlif';
@@ -0,0 +1,32 @@
1
+ const AlertIcon = props => (
2
+ <svg
3
+ width="2em"
4
+ height="2em"
5
+ viewBox="0 0 24 24"
6
+ version="1.1"
7
+ xmlns="http://www.w3.org/2000/svg"
8
+ >
9
+ <title>alert_fill</title>
10
+ <g id="page-1" stroke="none" strokeWidth="1" fill="none" fillRule="evenodd">
11
+ <g
12
+ id="System"
13
+ transform="translate(-48.000000, -48.000000)"
14
+ fillRule="nonzero"
15
+ >
16
+ <g id="alert_fill" transform="translate(48.000000, 48.000000)">
17
+ <path
18
+ d="M24,0 L24,24 L0,24 L0,0 L24,0 Z M12.5934901,23.257841 L12.5819402,23.2595131 L12.5108777,23.2950439 L12.4918791,23.2987469 L12.4918791,23.2987469 L12.4767152,23.2950439 L12.4056548,23.2595131 C12.3958229,23.2563662 12.3870493,23.2590235 12.3821421,23.2649074 L12.3780323,23.275831 L12.360941,23.7031097 L12.3658947,23.7234994 L12.3769048,23.7357139 L12.4804777,23.8096931 L12.4953491,23.8136134 L12.4953491,23.8136134 L12.5071152,23.8096931 L12.6106902,23.7357139 L12.6232938,23.7196733 L12.6232938,23.7196733 L12.6266527,23.7031097 L12.609561,23.275831 C12.6075724,23.2657013 12.6010112,23.2592993 12.5934901,23.257841 L12.5934901,23.257841 Z M12.8583906,23.1452862 L12.8445485,23.1473072 L12.6598443,23.2396597 L12.6498822,23.2499052 L12.6498822,23.2499052 L12.6471943,23.2611114 L12.6650943,23.6906389 L12.6699349,23.7034178 L12.6699349,23.7034178 L12.678386,23.7104931 L12.8793402,23.8032389 C12.8914285,23.8068999 12.9022333,23.8029875 12.9078286,23.7952264 L12.9118235,23.7811639 L12.8776777,23.1665331 C12.8752882,23.1545897 12.8674102,23.1470016 12.8583906,23.1452862 L12.8583906,23.1452862 Z M12.1430473,23.1473072 C12.1332178,23.1423925 12.1221763,23.1452606 12.1156365,23.1525954 L12.1099173,23.1665331 L12.0757714,23.7811639 C12.0751323,23.7926639 12.0828099,23.8018602 12.0926481,23.8045676 L12.108256,23.8032389 L12.3092106,23.7104931 L12.3186497,23.7024347 L12.3186497,23.7024347 L12.3225043,23.6906389 L12.340401,23.2611114 L12.337245,23.2485176 L12.337245,23.2485176 L12.3277531,23.2396597 L12.1430473,23.1473072 Z"
19
+ id="MingCute"
20
+ fillRule="nonzero"
21
+ ></path>
22
+ <path
23
+ d="M13.299,3.1477 L21.933,18.1022 C22.5103,19.1022 21.7887,20.3522 20.634,20.3522 L3.36601,20.3522 C2.21131,20.3522 1.48962,19.1022 2.06697,18.1022 L10.7009,3.14771 C11.2783,2.14771 12.7217,2.1477 13.299,3.1477 Z M12,15 C11.4477,15 11,15.4477 11,16 C11,16.5523 11.4477,17 12,17 C12.5523,17 13,16.5523 13,16 C13,15.4477 12.5523,15 12,15 Z M12,8 C11.48715,8 11.0644908,8.38604429 11.0067275,8.88337975 L11,9 L11,13 C11,13.5523 11.4477,14 12,14 C12.51285,14 12.9355092,13.613973 12.9932725,13.1166239 L13,13 L13,9 C13,8.44772 12.5523,8 12,8 Z"
24
+ id="shape"
25
+ fill="#09244B"
26
+ ></path>
27
+ </g>
28
+ </g>
29
+ </g>
30
+ </svg>
31
+ );
32
+ export default AlertIcon;
@@ -0,0 +1,15 @@
1
+ const CollapsedIcon = props => (
2
+ <svg
3
+ stroke="currentColor"
4
+ fill="currentColor"
5
+ strokeWidth="0"
6
+ viewBox="0 0 512 512"
7
+ height="1em"
8
+ width="1em"
9
+ xmlns="http://www.w3.org/2000/svg"
10
+ >
11
+ <path d="M48 256c0 114.9 93.1 208 208 208s208-93.1 208-208S370.9 48 256 48 48 141.1 48 256zm244.5 0l-81.9-81.1c-7.5-7.5-7.5-19.8 0-27.3s19.8-7.5 27.3 0l95.4 95.7c7.3 7.3 7.5 19.1.6 26.6l-94 94.3c-3.8 3.8-8.7 5.7-13.7 5.7-4.9 0-9.9-1.9-13.6-5.6-7.5-7.5-7.6-19.7 0-27.3l79.9-81z"></path>
12
+ </svg>
13
+ );
14
+
15
+ export default CollapsedIcon;
@@ -0,0 +1,36 @@
1
+ const DJLogo = props => (
2
+ <svg
3
+ width="30"
4
+ height="30"
5
+ style={{
6
+ marginRight: '10px',
7
+ marginBottom: '2px',
8
+ stroke: 'transparent',
9
+ strokeWidth: '0px',
10
+ }}
11
+ viewBox="0 0 83 83"
12
+ fill="none"
13
+ xmlns="http://www.w3.org/2000/svg"
14
+ xmlnsXlink="http://www.w3.org/1999/xlink"
15
+ >
16
+ <rect width="83" height="83" fill="url(#pattern0)" />
17
+ <rect width="83" height="83" stroke="black" />
18
+ <defs>
19
+ <pattern
20
+ id="pattern0"
21
+ patternContentUnits="objectBoundingBox"
22
+ width="1"
23
+ height="1"
24
+ >
25
+ <use xlinkHref="#image0_1_2" transform="scale(0.00364964)" />
26
+ </pattern>
27
+ <image
28
+ id="image0_1_2"
29
+ width="274"
30
+ height="274"
31
+ xlinkHref="data:image/png;base64,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"
32
+ />
33
+ </defs>
34
+ </svg>
35
+ );
36
+ export default DJLogo;
@@ -0,0 +1,21 @@
1
+ const DeleteIcon = props => (
2
+ <svg
3
+ className="feather feather-trash-2"
4
+ fill="none"
5
+ height="24"
6
+ stroke="currentColor"
7
+ strokeLinecap="round"
8
+ strokeLinejoin="round"
9
+ strokeWidth="2"
10
+ viewBox="0 0 24 24"
11
+ width="24"
12
+ xmlns="http://www.w3.org/2000/svg"
13
+ >
14
+ <polyline points="3 6 5 6 21 6" />
15
+ <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" />
16
+ <line x1="10" x2="10" y1="11" y2="17" />
17
+ <line x1="14" x2="14" y1="11" y2="17" />
18
+ </svg>
19
+ );
20
+
21
+ export default DeleteIcon;
@@ -0,0 +1,18 @@
1
+ const EditIcon = props => (
2
+ <svg
3
+ className="feather feather-edit"
4
+ fill="none"
5
+ height="24"
6
+ stroke="currentColor"
7
+ strokeLinecap="round"
8
+ strokeLinejoin="round"
9
+ strokeWidth="2"
10
+ viewBox="0 0 24 24"
11
+ width="24"
12
+ xmlns="http://www.w3.org/2000/svg"
13
+ >
14
+ <path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" />
15
+ <path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" />
16
+ </svg>
17
+ );
18
+ export default EditIcon;
@@ -0,0 +1,15 @@
1
+ const ExpandedIcon = props => (
2
+ <svg
3
+ stroke="currentColor"
4
+ fill="currentColor"
5
+ strokeWidth="0"
6
+ viewBox="0 0 512 512"
7
+ height="1em"
8
+ width="1em"
9
+ xmlns="http://www.w3.org/2000/svg"
10
+ >
11
+ <path d="M48 256c0 114.9 93.1 208 208 208s208-93.1 208-208S370.9 48 256 48 48 141.1 48 256zm289.1-43.4c7.5-7.5 19.8-7.5 27.3 0 3.8 3.8 5.6 8.7 5.6 13.6s-1.9 9.9-5.7 13.7l-94.3 94c-7.6 6.9-19.3 6.7-26.6-.6l-95.7-95.4c-7.5-7.5-7.6-19.7 0-27.3 7.5-7.5 19.7-7.6 27.3 0l81.1 81.9 81-79.9z"></path>
12
+ </svg>
13
+ );
14
+
15
+ export default ExpandedIcon;
@@ -0,0 +1,15 @@
1
+ const HorizontalHierarchyIcon = props => (
2
+ <svg
3
+ xmlns="http://www.w3.org/2000/svg"
4
+ width="16"
5
+ height="16"
6
+ fill="currentColor"
7
+ className="bi bi-house-door-fill"
8
+ viewBox="0 0 16 16"
9
+ style={{ paddingBottom: '0.2rem' }}
10
+ >
11
+ <path d="M6.5 14.5v-3.505c0-.245.25-.495.5-.495h2c.25 0 .5.25.5.5v3.5a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5v-7a.5.5 0 0 0-.146-.354L13 5.793V2.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1.293L8.354 1.146a.5.5 0 0 0-.708 0l-6 6A.5.5 0 0 0 1.5 7.5v7a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5Z" />
12
+ </svg>
13
+ );
14
+
15
+ export default HorizontalHierarchyIcon;
@@ -0,0 +1,14 @@
1
+ const InvalidIcon = props => (
2
+ <svg
3
+ xmlns="http://www.w3.org/2000/svg"
4
+ width="25"
5
+ height="25"
6
+ fill="currentColor"
7
+ className="bi bi-x-circle-fill"
8
+ viewBox="0 0 16 16"
9
+ >
10
+ <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" />
11
+ </svg>
12
+ );
13
+
14
+ export default InvalidIcon;
@@ -0,0 +1,52 @@
1
+ const PythonIcon = props => (
2
+ <svg
3
+ width="45px"
4
+ height="45px"
5
+ viewBox="0 0 64 64"
6
+ fill="none"
7
+ xmlns="http://www.w3.org/2000/svg"
8
+ >
9
+ <g id="SVGRepo_bgCarrier" strokeWidth="0"></g>
10
+ <g
11
+ id="SVGRepo_tracerCarrier"
12
+ strokeLinecap="round"
13
+ strokeLinejoin="round"
14
+ ></g>
15
+ <g id="SVGRepo_iconCarrier">
16
+ <path
17
+ d="M31.885 16c-8.124 0-7.617 3.523-7.617 3.523l.01 3.65h7.752v1.095H21.197S16 23.678 16 31.876c0 8.196 4.537 7.906 4.537 7.906h2.708v-3.804s-.146-4.537 4.465-4.537h7.688s4.32.07 4.32-4.175v-7.019S40.374 16 31.885 16zm-4.275 2.454c.771 0 1.395.624 1.395 1.395s-.624 1.395-1.395 1.395a1.393 1.393 0 0 1-1.395-1.395c0-.771.624-1.395 1.395-1.395z"
18
+ fill="url(#a)"
19
+ ></path>
20
+ <path
21
+ d="M32.115 47.833c8.124 0 7.617-3.523 7.617-3.523l-.01-3.65H31.97v-1.095h10.832S48 40.155 48 31.958c0-8.197-4.537-7.906-4.537-7.906h-2.708v3.803s.146 4.537-4.465 4.537h-7.688s-4.32-.07-4.32 4.175v7.019s-.656 4.247 7.833 4.247zm4.275-2.454a1.393 1.393 0 0 1-1.395-1.395c0-.77.624-1.394 1.395-1.394s1.395.623 1.395 1.394c0 .772-.624 1.395-1.395 1.395z"
22
+ fill="url(#b)"
23
+ ></path>
24
+ <defs>
25
+ <linearGradient
26
+ id="a"
27
+ x1="19.075"
28
+ y1="18.782"
29
+ x2="34.898"
30
+ y2="34.658"
31
+ gradientUnits="userSpaceOnUse"
32
+ >
33
+ <stop stopColor="#387EB8"></stop>
34
+ <stop offset="1" stopColor="#366994"></stop>
35
+ </linearGradient>
36
+ <linearGradient
37
+ id="b"
38
+ x1="28.809"
39
+ y1="28.882"
40
+ x2="45.803"
41
+ y2="45.163"
42
+ gradientUnits="userSpaceOnUse"
43
+ >
44
+ <stop stopColor="#FFE052"></stop>
45
+ <stop offset="1" stopColor="#FFC331"></stop>
46
+ </linearGradient>
47
+ </defs>
48
+ </g>
49
+ </svg>
50
+ );
51
+
52
+ export default PythonIcon;
@@ -0,0 +1,14 @@
1
+ const TableIcon = props => (
2
+ <svg
3
+ xmlns="http://www.w3.org/2000/svg"
4
+ width="16"
5
+ height="16"
6
+ fill="currentColor"
7
+ className="bi bi-table"
8
+ viewBox="0 0 16 16"
9
+ >
10
+ <path d="M0 2a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V2zm15 2h-4v3h4V4zm0 4h-4v3h4V8zm0 4h-4v3h3a1 1 0 0 0 1-1v-2zm-5 3v-3H6v3h4zm-5 0v-3H1v2a1 1 0 0 0 1 1h3zm-4-4h4V8H1v3zm0-4h4V4H1v3zm5-3v3h4V4H6zm4 4H6v3h4V8z" />
11
+ </svg>
12
+ );
13
+
14
+ export default TableIcon;
@@ -0,0 +1,14 @@
1
+ const ValidIcon = props => (
2
+ <svg
3
+ xmlns="http://www.w3.org/2000/svg"
4
+ width="25"
5
+ height="25"
6
+ fill="currentColor"
7
+ className="bi bi-check-circle-fill"
8
+ viewBox="0 0 16 16"
9
+ >
10
+ <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" />
11
+ </svg>
12
+ );
13
+
14
+ export default ValidIcon;