datajunction-ui 0.0.21 → 0.0.23-rc.0
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 +5 -4
- package/src/app/components/NotificationBell.tsx +11 -5
- package/src/app/components/UserMenu.tsx +3 -11
- package/src/app/components/__tests__/NotificationBell.test.tsx +17 -6
- package/src/app/components/__tests__/UserMenu.test.tsx +10 -3
- package/src/app/index.tsx +92 -85
- package/src/app/pages/AddEditNodePage/OwnersField.jsx +2 -3
- package/src/app/pages/NamespacePage/index.jsx +2 -4
- package/src/app/pages/NodePage/ClientCodePopover.jsx +27 -5
- package/src/app/pages/NodePage/NodeDependenciesTab.jsx +47 -45
- package/src/app/pages/NodePage/NodeInfoTab.jsx +73 -15
- package/src/app/pages/NodePage/__tests__/NodeDependenciesTab.test.jsx +13 -7
- package/src/app/pages/NodePage/__tests__/NodePage.test.jsx +23 -13
- package/src/app/pages/NodePage/index.jsx +14 -19
- package/src/app/pages/SettingsPage/__tests__/index.test.jsx +4 -1
- package/src/app/pages/SettingsPage/index.jsx +6 -6
- package/src/app/providers/UserProvider.tsx +78 -0
- package/src/app/services/DJService.js +43 -0
- package/src/app/services/__tests__/DJService.test.jsx +76 -0
- package/src/styles/nav-bar.css +1 -1
- package/webpack.config.js +3 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "datajunction-ui",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.23-rc.0",
|
|
4
4
|
"description": "DataJunction Metrics Platform UI",
|
|
5
5
|
"module": "src/index.tsx",
|
|
6
6
|
"repository": {
|
|
@@ -180,14 +180,15 @@
|
|
|
180
180
|
}
|
|
181
181
|
},
|
|
182
182
|
"resolutions": {
|
|
183
|
-
"@
|
|
184
|
-
"
|
|
185
|
-
"@lezer/common": "^1.0.0"
|
|
183
|
+
"@lezer/common": "^1.2.0",
|
|
184
|
+
"glob": "^10.4.5"
|
|
186
185
|
},
|
|
187
186
|
"devDependencies": {
|
|
188
187
|
"@babel/plugin-proposal-class-properties": "7.18.6",
|
|
189
188
|
"@babel/plugin-proposal-private-property-in-object": "7.21.11",
|
|
190
189
|
"@testing-library/user-event": "14.4.3",
|
|
190
|
+
"@types/glob": "^8.1.0",
|
|
191
|
+
"@types/minimatch": "^5.1.2",
|
|
191
192
|
"eslint-config-prettier": "8.8.0",
|
|
192
193
|
"eslint-plugin-prettier": "4.2.1",
|
|
193
194
|
"eslint-plugin-react-hooks": "4.6.0",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useContext, useEffect, useState } from 'react';
|
|
2
2
|
import DJClientContext from '../providers/djclient';
|
|
3
|
+
import { useCurrentUser } from '../providers/UserProvider';
|
|
3
4
|
import NotificationIcon from '../icons/NotificationIcon';
|
|
4
5
|
import SettingsIcon from '../icons/SettingsIcon';
|
|
5
6
|
import LoadingIcon from '../icons/LoadingIcon';
|
|
@@ -68,6 +69,7 @@ export default function NotificationBell({
|
|
|
68
69
|
forceClose,
|
|
69
70
|
}: NotificationBellProps) {
|
|
70
71
|
const djClient = useContext(DJClientContext).DataJunctionAPI;
|
|
72
|
+
const { currentUser, loading: userLoading } = useCurrentUser();
|
|
71
73
|
const [showDropdown, setShowDropdown] = useState(false);
|
|
72
74
|
|
|
73
75
|
// Close when forceClose becomes true
|
|
@@ -82,14 +84,15 @@ export default function NotificationBell({
|
|
|
82
84
|
const [loading, setLoading] = useState(false);
|
|
83
85
|
const [unreadCount, setUnreadCount] = useState(0);
|
|
84
86
|
|
|
85
|
-
// Fetch notifications
|
|
87
|
+
// Fetch notifications when user data is available
|
|
86
88
|
useEffect(() => {
|
|
89
|
+
if (userLoading) return;
|
|
90
|
+
|
|
87
91
|
async function fetchNotifications() {
|
|
88
92
|
setLoading(true);
|
|
89
93
|
try {
|
|
90
|
-
const current = await djClient.whoami();
|
|
91
94
|
const history: HistoryEntry[] =
|
|
92
|
-
(await djClient.getSubscribedHistory(
|
|
95
|
+
(await djClient.getSubscribedHistory(5)) || [];
|
|
93
96
|
|
|
94
97
|
// Get unique entity names and fetch their info via GraphQL
|
|
95
98
|
// (some may not be nodes, but GraphQL will just not return them)
|
|
@@ -101,7 +104,10 @@ export default function NotificationBell({
|
|
|
101
104
|
const enriched = enrichWithNodeInfo(history, nodes);
|
|
102
105
|
setNotifications(enriched);
|
|
103
106
|
setUnreadCount(
|
|
104
|
-
calculateUnreadCount(
|
|
107
|
+
calculateUnreadCount(
|
|
108
|
+
history,
|
|
109
|
+
currentUser?.last_viewed_notifications_at,
|
|
110
|
+
),
|
|
105
111
|
);
|
|
106
112
|
} catch (error) {
|
|
107
113
|
console.error('Error fetching notifications:', error);
|
|
@@ -110,7 +116,7 @@ export default function NotificationBell({
|
|
|
110
116
|
}
|
|
111
117
|
}
|
|
112
118
|
fetchNotifications();
|
|
113
|
-
}, [djClient]);
|
|
119
|
+
}, [djClient, currentUser, userLoading]);
|
|
114
120
|
|
|
115
121
|
// Close dropdown when clicking outside
|
|
116
122
|
useEffect(() => {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useContext, useEffect, useState } from 'react';
|
|
2
2
|
import DJClientContext from '../providers/djclient';
|
|
3
|
+
import { useCurrentUser } from '../providers/UserProvider';
|
|
3
4
|
|
|
4
5
|
interface User {
|
|
5
6
|
id: number;
|
|
@@ -32,7 +33,7 @@ export default function UserMenu({
|
|
|
32
33
|
forceClose,
|
|
33
34
|
}: UserMenuProps) {
|
|
34
35
|
const djClient = useContext(DJClientContext).DataJunctionAPI;
|
|
35
|
-
const
|
|
36
|
+
const { currentUser } = useCurrentUser();
|
|
36
37
|
const [showDropdown, setShowDropdown] = useState(false);
|
|
37
38
|
|
|
38
39
|
// Close when forceClose becomes true
|
|
@@ -42,15 +43,6 @@ export default function UserMenu({
|
|
|
42
43
|
}
|
|
43
44
|
}, [forceClose, showDropdown]);
|
|
44
45
|
|
|
45
|
-
// Fetch current user on mount
|
|
46
|
-
useEffect(() => {
|
|
47
|
-
async function fetchUser() {
|
|
48
|
-
const user = await djClient.whoami();
|
|
49
|
-
setCurrentUser(user);
|
|
50
|
-
}
|
|
51
|
-
fetchUser();
|
|
52
|
-
}, [djClient]);
|
|
53
|
-
|
|
54
46
|
// Close dropdown when clicking outside
|
|
55
47
|
useEffect(() => {
|
|
56
48
|
const handleClickOutside = (event: MouseEvent) => {
|
|
@@ -79,7 +71,7 @@ export default function UserMenu({
|
|
|
79
71
|
return (
|
|
80
72
|
<div className="nav-dropdown user-menu-dropdown">
|
|
81
73
|
<button className="avatar-button" onClick={handleToggle}>
|
|
82
|
-
{getInitials(currentUser)}
|
|
74
|
+
{getInitials(currentUser as User | null)}
|
|
83
75
|
</button>
|
|
84
76
|
{showDropdown && (
|
|
85
77
|
<div className="nav-dropdown-menu">
|
|
@@ -2,6 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
|
3
3
|
import NotificationBell from '../NotificationBell';
|
|
4
4
|
import DJClientContext from '../../providers/djclient';
|
|
5
|
+
import { UserProvider } from '../../providers/UserProvider';
|
|
5
6
|
|
|
6
7
|
describe('<NotificationBell />', () => {
|
|
7
8
|
const mockNotifications = [
|
|
@@ -52,10 +53,12 @@ describe('<NotificationBell />', () => {
|
|
|
52
53
|
...overrides,
|
|
53
54
|
});
|
|
54
55
|
|
|
55
|
-
const renderWithContext = (mockDjClient: any) => {
|
|
56
|
+
const renderWithContext = (mockDjClient: any, props = {}) => {
|
|
56
57
|
return render(
|
|
57
58
|
<DJClientContext.Provider value={{ DataJunctionAPI: mockDjClient }}>
|
|
58
|
-
<
|
|
59
|
+
<UserProvider>
|
|
60
|
+
<NotificationBell {...props} />
|
|
61
|
+
</UserProvider>
|
|
59
62
|
</DJClientContext.Provider>,
|
|
60
63
|
);
|
|
61
64
|
};
|
|
@@ -218,7 +221,9 @@ describe('<NotificationBell />', () => {
|
|
|
218
221
|
<DJClientContext.Provider
|
|
219
222
|
value={{ DataJunctionAPI: mockDjClient as any }}
|
|
220
223
|
>
|
|
221
|
-
<
|
|
224
|
+
<UserProvider>
|
|
225
|
+
<NotificationBell onDropdownToggle={onDropdownToggle} />
|
|
226
|
+
</UserProvider>
|
|
222
227
|
</DJClientContext.Provider>,
|
|
223
228
|
);
|
|
224
229
|
|
|
@@ -239,7 +244,9 @@ describe('<NotificationBell />', () => {
|
|
|
239
244
|
<DJClientContext.Provider
|
|
240
245
|
value={{ DataJunctionAPI: mockDjClient as any }}
|
|
241
246
|
>
|
|
242
|
-
<
|
|
247
|
+
<UserProvider>
|
|
248
|
+
<NotificationBell forceClose={false} />
|
|
249
|
+
</UserProvider>
|
|
243
250
|
</DJClientContext.Provider>,
|
|
244
251
|
);
|
|
245
252
|
|
|
@@ -259,7 +266,9 @@ describe('<NotificationBell />', () => {
|
|
|
259
266
|
<DJClientContext.Provider
|
|
260
267
|
value={{ DataJunctionAPI: mockDjClient as any }}
|
|
261
268
|
>
|
|
262
|
-
<
|
|
269
|
+
<UserProvider>
|
|
270
|
+
<NotificationBell forceClose={true} />
|
|
271
|
+
</UserProvider>
|
|
263
272
|
</DJClientContext.Provider>,
|
|
264
273
|
);
|
|
265
274
|
|
|
@@ -275,7 +284,9 @@ describe('<NotificationBell />', () => {
|
|
|
275
284
|
<DJClientContext.Provider
|
|
276
285
|
value={{ DataJunctionAPI: mockDjClient as any }}
|
|
277
286
|
>
|
|
278
|
-
<
|
|
287
|
+
<UserProvider>
|
|
288
|
+
<NotificationBell onDropdownToggle={onDropdownToggle} />
|
|
289
|
+
</UserProvider>
|
|
279
290
|
</DJClientContext.Provider>,
|
|
280
291
|
);
|
|
281
292
|
|
|
@@ -2,6 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
|
3
3
|
import UserMenu from '../UserMenu';
|
|
4
4
|
import DJClientContext from '../../providers/djclient';
|
|
5
|
+
import { UserProvider } from '../../providers/UserProvider';
|
|
5
6
|
|
|
6
7
|
describe('<UserMenu />', () => {
|
|
7
8
|
const createMockDjClient = (overrides = {}) => ({
|
|
@@ -17,7 +18,9 @@ describe('<UserMenu />', () => {
|
|
|
17
18
|
const renderWithContext = (mockDjClient: any, props = {}) => {
|
|
18
19
|
return render(
|
|
19
20
|
<DJClientContext.Provider value={{ DataJunctionAPI: mockDjClient }}>
|
|
20
|
-
<
|
|
21
|
+
<UserProvider>
|
|
22
|
+
<UserMenu {...props} />
|
|
23
|
+
</UserProvider>
|
|
21
24
|
</DJClientContext.Provider>,
|
|
22
25
|
);
|
|
23
26
|
};
|
|
@@ -164,7 +167,9 @@ describe('<UserMenu />', () => {
|
|
|
164
167
|
<DJClientContext.Provider
|
|
165
168
|
value={{ DataJunctionAPI: mockDjClient as any }}
|
|
166
169
|
>
|
|
167
|
-
<
|
|
170
|
+
<UserProvider>
|
|
171
|
+
<UserMenu forceClose={false} />
|
|
172
|
+
</UserProvider>
|
|
168
173
|
</DJClientContext.Provider>,
|
|
169
174
|
);
|
|
170
175
|
|
|
@@ -184,7 +189,9 @@ describe('<UserMenu />', () => {
|
|
|
184
189
|
<DJClientContext.Provider
|
|
185
190
|
value={{ DataJunctionAPI: mockDjClient as any }}
|
|
186
191
|
>
|
|
187
|
-
<
|
|
192
|
+
<UserProvider>
|
|
193
|
+
<UserMenu forceClose={true} />
|
|
194
|
+
</UserProvider>
|
|
188
195
|
</DJClientContext.Provider>,
|
|
189
196
|
);
|
|
190
197
|
|
package/src/app/index.tsx
CHANGED
|
@@ -11,7 +11,7 @@ import { NamespacePage } from './pages/NamespacePage/Loadable';
|
|
|
11
11
|
import { OverviewPage } from './pages/OverviewPage/Loadable';
|
|
12
12
|
import { SettingsPage } from './pages/SettingsPage/Loadable';
|
|
13
13
|
import { NotificationsPage } from './pages/NotificationsPage/Loadable';
|
|
14
|
-
import { NodePage } from './pages/NodePage
|
|
14
|
+
import { NodePage } from './pages/NodePage';
|
|
15
15
|
import RevisionDiff from './pages/NodePage/RevisionDiff';
|
|
16
16
|
import { SQLBuilderPage } from './pages/SQLBuilderPage/Loadable';
|
|
17
17
|
import { CubeBuilderPage } from './pages/CubeBuilderPage/Loadable';
|
|
@@ -21,8 +21,9 @@ import { AddEditTagPage } from './pages/AddEditTagPage/Loadable';
|
|
|
21
21
|
import { NotFoundPage } from './pages/NotFoundPage/Loadable';
|
|
22
22
|
import { LoginPage } from './pages/LoginPage';
|
|
23
23
|
import { RegisterTablePage } from './pages/RegisterTablePage';
|
|
24
|
-
import { Root } from './pages/Root
|
|
24
|
+
import { Root } from './pages/Root';
|
|
25
25
|
import DJClientContext from './providers/djclient';
|
|
26
|
+
import { UserProvider } from './providers/UserProvider';
|
|
26
27
|
import { DataJunctionAPI } from './services/DJService';
|
|
27
28
|
import { CookiesProvider, useCookies } from 'react-cookie';
|
|
28
29
|
import * as Constants from './constants';
|
|
@@ -44,101 +45,107 @@ export function App() {
|
|
|
44
45
|
/>
|
|
45
46
|
</Helmet>
|
|
46
47
|
<DJClientContext.Provider value={{ DataJunctionAPI }}>
|
|
47
|
-
<
|
|
48
|
-
<
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
<Route path="
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
48
|
+
<UserProvider>
|
|
49
|
+
<Routes>
|
|
50
|
+
<Route
|
|
51
|
+
path="/"
|
|
52
|
+
element={<Root />}
|
|
53
|
+
children={
|
|
54
|
+
<>
|
|
55
|
+
<Route path="nodes" key="nodes">
|
|
56
|
+
<Route path=":name" element={<NodePage />} />
|
|
57
|
+
<Route
|
|
58
|
+
path=":name/edit"
|
|
59
|
+
key="edit"
|
|
60
|
+
element={<AddEditNodePage />}
|
|
61
|
+
/>
|
|
62
|
+
<Route
|
|
63
|
+
path=":name/edit-cube"
|
|
64
|
+
key="edit-cube"
|
|
65
|
+
element={<CubeBuilderPage />}
|
|
66
|
+
/>
|
|
67
|
+
<Route
|
|
68
|
+
path=":name/revisions/:revision"
|
|
69
|
+
element={<RevisionDiff />}
|
|
70
|
+
/>
|
|
71
|
+
<Route path=":name/:tab" element={<NodePage />} />
|
|
72
|
+
</Route>
|
|
71
73
|
|
|
72
|
-
<Route path="/" element={<NamespacePage />} key="index" />
|
|
73
|
-
<Route path="namespaces">
|
|
74
74
|
<Route
|
|
75
|
-
path="
|
|
75
|
+
path="/"
|
|
76
76
|
element={<NamespacePage />}
|
|
77
|
-
key="
|
|
77
|
+
key="index"
|
|
78
78
|
/>
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
79
|
+
<Route path="namespaces">
|
|
80
|
+
<Route
|
|
81
|
+
path=":namespace"
|
|
82
|
+
element={<NamespacePage />}
|
|
83
|
+
key="namespaces"
|
|
84
|
+
/>
|
|
85
|
+
</Route>
|
|
86
|
+
<Route
|
|
87
|
+
path="create/tag"
|
|
88
|
+
key="createtag"
|
|
89
|
+
element={<AddEditTagPage />}
|
|
90
|
+
></Route>
|
|
91
|
+
<Route
|
|
92
|
+
path="create/source"
|
|
93
|
+
key="register"
|
|
94
|
+
element={<RegisterTablePage />}
|
|
95
|
+
></Route>
|
|
96
|
+
<Route path="/create/cube">
|
|
97
|
+
<Route
|
|
98
|
+
path=":initialNamespace"
|
|
99
|
+
key="create"
|
|
100
|
+
element={<CubeBuilderPage />}
|
|
101
|
+
/>
|
|
102
|
+
<Route
|
|
103
|
+
path=""
|
|
104
|
+
key="create"
|
|
105
|
+
element={<CubeBuilderPage />}
|
|
106
|
+
/>
|
|
107
|
+
</Route>
|
|
108
|
+
<Route path="create/:nodeType">
|
|
109
|
+
<Route
|
|
110
|
+
path=":initialNamespace"
|
|
111
|
+
key="create"
|
|
112
|
+
element={<AddEditNodePage />}
|
|
113
|
+
/>
|
|
114
|
+
<Route
|
|
115
|
+
path=""
|
|
116
|
+
key="create"
|
|
117
|
+
element={<AddEditNodePage />}
|
|
118
|
+
/>
|
|
119
|
+
</Route>
|
|
91
120
|
<Route
|
|
92
|
-
path="
|
|
93
|
-
key="
|
|
94
|
-
element={<
|
|
121
|
+
path="sql"
|
|
122
|
+
key="sql"
|
|
123
|
+
element={<SQLBuilderPage />}
|
|
95
124
|
/>
|
|
125
|
+
<Route path="tags" key="tags">
|
|
126
|
+
<Route path=":name" element={<TagPage />} />
|
|
127
|
+
</Route>
|
|
96
128
|
<Route
|
|
97
|
-
path=""
|
|
98
|
-
key="
|
|
99
|
-
element={<
|
|
129
|
+
path="overview"
|
|
130
|
+
key="overview"
|
|
131
|
+
element={<OverviewPage />}
|
|
100
132
|
/>
|
|
101
|
-
</Route>
|
|
102
|
-
<Route path="create/:nodeType">
|
|
103
133
|
<Route
|
|
104
|
-
path="
|
|
105
|
-
key="
|
|
106
|
-
element={<
|
|
134
|
+
path="settings"
|
|
135
|
+
key="settings"
|
|
136
|
+
element={<SettingsPage />}
|
|
107
137
|
/>
|
|
108
138
|
<Route
|
|
109
|
-
path=""
|
|
110
|
-
key="
|
|
111
|
-
element={<
|
|
139
|
+
path="notifications"
|
|
140
|
+
key="notifications"
|
|
141
|
+
element={<NotificationsPage />}
|
|
112
142
|
/>
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
<Route path="tags" key="tags">
|
|
120
|
-
<Route path=":name" element={<TagPage />} />
|
|
121
|
-
</Route>
|
|
122
|
-
<Route
|
|
123
|
-
path="overview"
|
|
124
|
-
key="overview"
|
|
125
|
-
element={<OverviewPage />}
|
|
126
|
-
/>
|
|
127
|
-
<Route
|
|
128
|
-
path="settings"
|
|
129
|
-
key="settings"
|
|
130
|
-
element={<SettingsPage />}
|
|
131
|
-
/>
|
|
132
|
-
<Route
|
|
133
|
-
path="notifications"
|
|
134
|
-
key="notifications"
|
|
135
|
-
element={<NotificationsPage />}
|
|
136
|
-
/>
|
|
137
|
-
</>
|
|
138
|
-
}
|
|
139
|
-
/>
|
|
140
|
-
<Route path="*" element={<NotFoundPage />} />
|
|
141
|
-
</Routes>
|
|
143
|
+
</>
|
|
144
|
+
}
|
|
145
|
+
/>
|
|
146
|
+
<Route path="*" element={<NotFoundPage />} />
|
|
147
|
+
</Routes>
|
|
148
|
+
</UserProvider>
|
|
142
149
|
</DJClientContext.Provider>
|
|
143
150
|
</>
|
|
144
151
|
) : (
|
|
@@ -4,13 +4,14 @@
|
|
|
4
4
|
import { ErrorMessage } from 'formik';
|
|
5
5
|
import { useContext, useEffect, useState } from 'react';
|
|
6
6
|
import DJClientContext from '../../providers/djclient';
|
|
7
|
+
import { useCurrentUser } from '../../providers/UserProvider';
|
|
7
8
|
import { FormikSelect } from './FormikSelect';
|
|
8
9
|
|
|
9
10
|
export const OwnersField = ({ defaultValue }) => {
|
|
10
11
|
const djClient = useContext(DJClientContext).DataJunctionAPI;
|
|
12
|
+
const { currentUser } = useCurrentUser();
|
|
11
13
|
|
|
12
14
|
const [availableUsers, setAvailableUsers] = useState([]);
|
|
13
|
-
const [currentUser, setCurrentUser] = useState(null);
|
|
14
15
|
|
|
15
16
|
useEffect(() => {
|
|
16
17
|
async function fetchData() {
|
|
@@ -23,8 +24,6 @@ export const OwnersField = ({ defaultValue }) => {
|
|
|
23
24
|
};
|
|
24
25
|
}),
|
|
25
26
|
);
|
|
26
|
-
const current = await djClient.whoami();
|
|
27
|
-
setCurrentUser(current);
|
|
28
27
|
}
|
|
29
28
|
fetchData();
|
|
30
29
|
}, [djClient]);
|
|
@@ -3,6 +3,7 @@ import { useParams } from 'react-router-dom';
|
|
|
3
3
|
import { useContext, useEffect, useState } from 'react';
|
|
4
4
|
import NodeStatus from '../NodePage/NodeStatus';
|
|
5
5
|
import DJClientContext from '../../providers/djclient';
|
|
6
|
+
import { useCurrentUser } from '../../providers/UserProvider';
|
|
6
7
|
import Explorer from '../NamespacePage/Explorer';
|
|
7
8
|
import AddNodeDropdown from '../../components/AddNodeDropdown';
|
|
8
9
|
import NodeListActions from '../../components/NodeListActions';
|
|
@@ -24,6 +25,7 @@ export function NamespacePage() {
|
|
|
24
25
|
const fields = ['name', 'displayName', 'type', 'status', 'mode', 'updatedAt'];
|
|
25
26
|
|
|
26
27
|
const djClient = useContext(DJClientContext).DataJunctionAPI;
|
|
28
|
+
const { currentUser } = useCurrentUser();
|
|
27
29
|
var { namespace } = useParams();
|
|
28
30
|
|
|
29
31
|
const [state, setState] = useState({
|
|
@@ -31,7 +33,6 @@ export function NamespacePage() {
|
|
|
31
33
|
nodes: [],
|
|
32
34
|
});
|
|
33
35
|
const [retrieved, setRetrieved] = useState(false);
|
|
34
|
-
const [currentUser, setCurrentUser] = useState(null);
|
|
35
36
|
|
|
36
37
|
const [filters, setFilters] = useState({
|
|
37
38
|
tags: [],
|
|
@@ -105,9 +106,6 @@ export function NamespacePage() {
|
|
|
105
106
|
const namespaces = await djClient.namespaces();
|
|
106
107
|
const hierarchy = createNamespaceHierarchy(namespaces);
|
|
107
108
|
setNamespaceHierarchy(hierarchy);
|
|
108
|
-
const currentUser = await djClient.whoami();
|
|
109
|
-
// setFilters({...filters, edited_by: currentUser?.username});
|
|
110
|
-
setCurrentUser(currentUser);
|
|
111
109
|
};
|
|
112
110
|
fetchData().catch(console.error);
|
|
113
111
|
}, [djClient, djClient.namespaces]);
|
|
@@ -1,11 +1,27 @@
|
|
|
1
|
+
import DJClientContext from '../../providers/djclient';
|
|
1
2
|
import { Light as SyntaxHighlighter } from 'react-syntax-highlighter';
|
|
2
|
-
import { useEffect, useRef, useState } from 'react';
|
|
3
|
+
import { useEffect, useRef, useState, useContext } from 'react';
|
|
3
4
|
import { nightOwl } from 'react-syntax-highlighter/dist/esm/styles/hljs';
|
|
4
5
|
import PythonIcon from '../../icons/PythonIcon';
|
|
6
|
+
import LoadingIcon from 'app/icons/LoadingIcon';
|
|
5
7
|
|
|
6
|
-
export default function ClientCodePopover({
|
|
8
|
+
export default function ClientCodePopover({ nodeName }) {
|
|
9
|
+
const djClient = useContext(DJClientContext).DataJunctionAPI;
|
|
7
10
|
const [showModal, setShowModal] = useState(false);
|
|
8
11
|
const modalRef = useRef(null);
|
|
12
|
+
const [code, setCode] = useState(null);
|
|
13
|
+
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
async function fetchCode() {
|
|
16
|
+
try {
|
|
17
|
+
const code = await djClient.clientCode(nodeName);
|
|
18
|
+
setCode(code);
|
|
19
|
+
} catch (err) {
|
|
20
|
+
console.log(err);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
fetchCode();
|
|
24
|
+
}, [nodeName, djClient]);
|
|
9
25
|
|
|
10
26
|
useEffect(() => {
|
|
11
27
|
const handleClickOutside = event => {
|
|
@@ -83,9 +99,15 @@ export default function ClientCodePopover({ code }) {
|
|
|
83
99
|
×
|
|
84
100
|
</button>
|
|
85
101
|
<h2>Python Client Code</h2>
|
|
86
|
-
|
|
87
|
-
{
|
|
88
|
-
|
|
102
|
+
{code ? (
|
|
103
|
+
<SyntaxHighlighter language="python" style={nightOwl}>
|
|
104
|
+
{code}
|
|
105
|
+
</SyntaxHighlighter>
|
|
106
|
+
) : (
|
|
107
|
+
<>
|
|
108
|
+
<LoadingIcon />
|
|
109
|
+
</>
|
|
110
|
+
)}
|
|
89
111
|
</div>
|
|
90
112
|
</div>
|
|
91
113
|
)}
|