datajunction-ui 0.0.55 → 0.0.56
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 +1 -1
- package/src/app/components/NamespaceHeader.jsx +431 -11
- package/src/app/components/NodeListActions.jsx +10 -7
- package/src/app/components/__tests__/GitModals.test.jsx +1293 -0
- package/src/app/components/__tests__/NamespaceHeader.test.jsx +764 -0
- package/src/app/components/__tests__/NodeListActions.test.jsx +5 -3
- package/src/app/components/__tests__/__snapshots__/NamespaceHeader.test.jsx.snap +95 -0
- package/src/app/components/git/CreateBranchModal.jsx +229 -0
- package/src/app/components/git/CreatePRModal.jsx +270 -0
- package/src/app/components/git/DeleteBranchModal.jsx +173 -0
- package/src/app/components/git/GitSettingsModal.jsx +292 -0
- package/src/app/components/git/SyncToGitModal.jsx +219 -0
- package/src/app/components/git/index.js +5 -0
- package/src/app/icons/DeleteIcon.jsx +3 -3
- package/src/app/icons/EditIcon.jsx +3 -3
- package/src/app/icons/EyeIcon.jsx +3 -4
- package/src/app/icons/JupyterExportIcon.jsx +3 -7
- package/src/app/icons/PythonIcon.jsx +3 -3
- package/src/app/pages/AddEditNodePage/index.jsx +8 -5
- package/src/app/pages/NamespacePage/index.jsx +34 -21
- package/src/app/pages/NodePage/ClientCodePopover.jsx +3 -7
- package/src/app/pages/NodePage/NodeInfoTab.jsx +10 -3
- package/src/app/pages/NodePage/NotebookDownload.jsx +4 -10
- package/src/app/pages/NodePage/WatchNodeButton.jsx +7 -12
- package/src/app/pages/NodePage/index.jsx +42 -13
- package/src/app/services/DJService.js +198 -1
- package/src/styles/index.css +3 -0
- package/src/styles/node-creation.scss +22 -0
- package/src/styles/settings.css +1 -1
package/package.json
CHANGED
|
@@ -1,21 +1,44 @@
|
|
|
1
1
|
import { useContext, useEffect, useState, useRef } from 'react';
|
|
2
2
|
import DJClientContext from '../providers/djclient';
|
|
3
|
+
import {
|
|
4
|
+
GitSettingsModal,
|
|
5
|
+
CreateBranchModal,
|
|
6
|
+
SyncToGitModal,
|
|
7
|
+
CreatePRModal,
|
|
8
|
+
DeleteBranchModal,
|
|
9
|
+
} from './git';
|
|
3
10
|
|
|
4
|
-
export default function NamespaceHeader({
|
|
11
|
+
export default function NamespaceHeader({
|
|
12
|
+
namespace,
|
|
13
|
+
children,
|
|
14
|
+
onGitConfigLoaded,
|
|
15
|
+
}) {
|
|
5
16
|
const djClient = useContext(DJClientContext).DataJunctionAPI;
|
|
6
17
|
const [sources, setSources] = useState(null);
|
|
7
18
|
const [recentDeployments, setRecentDeployments] = useState([]);
|
|
8
19
|
const [deploymentsDropdownOpen, setDeploymentsDropdownOpen] = useState(false);
|
|
9
20
|
const dropdownRef = useRef(null);
|
|
10
21
|
|
|
22
|
+
// Git config state
|
|
23
|
+
const [gitConfig, setGitConfig] = useState(null);
|
|
24
|
+
const [parentGitConfig, setParentGitConfig] = useState(null);
|
|
25
|
+
const [existingPR, setExistingPR] = useState(null);
|
|
26
|
+
|
|
27
|
+
// Modal states
|
|
28
|
+
const [showGitSettings, setShowGitSettings] = useState(false);
|
|
29
|
+
const [showCreateBranch, setShowCreateBranch] = useState(false);
|
|
30
|
+
const [showSyncToGit, setShowSyncToGit] = useState(false);
|
|
31
|
+
const [showCreatePR, setShowCreatePR] = useState(false);
|
|
32
|
+
const [showDeleteBranch, setShowDeleteBranch] = useState(false);
|
|
33
|
+
|
|
11
34
|
useEffect(() => {
|
|
12
|
-
const
|
|
35
|
+
const fetchData = async () => {
|
|
13
36
|
if (namespace) {
|
|
37
|
+
// Fetch deployment sources
|
|
14
38
|
try {
|
|
15
39
|
const data = await djClient.namespaceSources(namespace);
|
|
16
40
|
setSources(data);
|
|
17
41
|
|
|
18
|
-
// Fetch recent deployments for this namespace
|
|
19
42
|
try {
|
|
20
43
|
const deployments = await djClient.listDeployments(namespace, 5);
|
|
21
44
|
setRecentDeployments(deployments || []);
|
|
@@ -26,9 +49,45 @@ export default function NamespaceHeader({ namespace, children }) {
|
|
|
26
49
|
} catch (e) {
|
|
27
50
|
// Silently fail - badge just won't show
|
|
28
51
|
}
|
|
52
|
+
|
|
53
|
+
// Fetch git config
|
|
54
|
+
try {
|
|
55
|
+
const config = await djClient.getNamespaceGitConfig(namespace);
|
|
56
|
+
setGitConfig(config);
|
|
57
|
+
if (onGitConfigLoaded) {
|
|
58
|
+
onGitConfigLoaded(config);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// If this is a branch namespace, fetch parent's git config and check for existing PR
|
|
62
|
+
if (config?.parent_namespace) {
|
|
63
|
+
try {
|
|
64
|
+
const parentConfig = await djClient.getNamespaceGitConfig(
|
|
65
|
+
config.parent_namespace,
|
|
66
|
+
);
|
|
67
|
+
setParentGitConfig(parentConfig);
|
|
68
|
+
} catch (e) {
|
|
69
|
+
console.error('Failed to fetch parent git config:', e);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Check for existing PR
|
|
73
|
+
try {
|
|
74
|
+
const pr = await djClient.getPullRequest(namespace);
|
|
75
|
+
setExistingPR(pr);
|
|
76
|
+
} catch (e) {
|
|
77
|
+
// No PR or error - that's fine
|
|
78
|
+
setExistingPR(null);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
} catch (e) {
|
|
82
|
+
// Git config not available
|
|
83
|
+
setGitConfig(null);
|
|
84
|
+
if (onGitConfigLoaded) {
|
|
85
|
+
onGitConfigLoaded(null);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
29
88
|
}
|
|
30
89
|
};
|
|
31
|
-
|
|
90
|
+
fetchData();
|
|
32
91
|
}, [djClient, namespace]);
|
|
33
92
|
|
|
34
93
|
// Close dropdown when clicking outside
|
|
@@ -44,6 +103,74 @@ export default function NamespaceHeader({ namespace, children }) {
|
|
|
44
103
|
|
|
45
104
|
const namespaceParts = namespace ? namespace.split('.') : [];
|
|
46
105
|
|
|
106
|
+
const hasGitConfig = gitConfig?.github_repo_path && gitConfig?.git_branch;
|
|
107
|
+
const isBranchNamespace = !!gitConfig?.parent_namespace;
|
|
108
|
+
|
|
109
|
+
// Handlers for git operations
|
|
110
|
+
const handleSaveGitConfig = async config => {
|
|
111
|
+
const result = await djClient.updateNamespaceGitConfig(namespace, config);
|
|
112
|
+
if (!result?._error) {
|
|
113
|
+
setGitConfig(result);
|
|
114
|
+
}
|
|
115
|
+
return result;
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const handleCreateBranch = async branchName => {
|
|
119
|
+
return await djClient.createBranch(namespace, branchName);
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const handleSyncToGit = async commitMessage => {
|
|
123
|
+
return await djClient.syncNamespaceToGit(namespace, commitMessage);
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const handleCreatePR = async (title, body, onProgress) => {
|
|
127
|
+
// First sync changes to git using PR title as commit message
|
|
128
|
+
if (onProgress) onProgress('syncing');
|
|
129
|
+
const syncResult = await djClient.syncNamespaceToGit(namespace, title);
|
|
130
|
+
if (syncResult?._error) {
|
|
131
|
+
return syncResult;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Then create the PR
|
|
135
|
+
if (onProgress) onProgress('creating');
|
|
136
|
+
const result = await djClient.createPullRequest(namespace, title, body);
|
|
137
|
+
if (result && !result._error) {
|
|
138
|
+
setExistingPR(result);
|
|
139
|
+
}
|
|
140
|
+
return result;
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const handleDeleteBranch = async deleteGitBranch => {
|
|
144
|
+
return await djClient.deleteBranch(
|
|
145
|
+
gitConfig.parent_namespace,
|
|
146
|
+
namespace,
|
|
147
|
+
deleteGitBranch,
|
|
148
|
+
);
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
// Button style helpers
|
|
152
|
+
const buttonStyle = {
|
|
153
|
+
height: '28px',
|
|
154
|
+
padding: '0 10px',
|
|
155
|
+
fontSize: '12px',
|
|
156
|
+
border: '1px solid #e2e8f0',
|
|
157
|
+
borderRadius: '4px',
|
|
158
|
+
backgroundColor: '#ffffff',
|
|
159
|
+
color: '#475569',
|
|
160
|
+
cursor: 'pointer',
|
|
161
|
+
display: 'flex',
|
|
162
|
+
alignItems: 'center',
|
|
163
|
+
gap: '4px',
|
|
164
|
+
whiteSpace: 'nowrap',
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
const primaryButtonStyle = {
|
|
168
|
+
...buttonStyle,
|
|
169
|
+
backgroundColor: '#3b82f6',
|
|
170
|
+
borderColor: '#3b82f6',
|
|
171
|
+
color: '#ffffff',
|
|
172
|
+
};
|
|
173
|
+
|
|
47
174
|
return (
|
|
48
175
|
<div
|
|
49
176
|
style={{
|
|
@@ -123,7 +250,82 @@ export default function NamespaceHeader({ namespace, children }) {
|
|
|
123
250
|
</span>
|
|
124
251
|
)}
|
|
125
252
|
|
|
126
|
-
{/*
|
|
253
|
+
{/* Branch indicator */}
|
|
254
|
+
{isBranchNamespace && (
|
|
255
|
+
<span
|
|
256
|
+
style={{
|
|
257
|
+
display: 'flex',
|
|
258
|
+
alignItems: 'center',
|
|
259
|
+
gap: '4px',
|
|
260
|
+
padding: '2px 8px',
|
|
261
|
+
backgroundColor: '#dbeafe',
|
|
262
|
+
borderRadius: '12px',
|
|
263
|
+
fontSize: '11px',
|
|
264
|
+
color: '#1e40af',
|
|
265
|
+
marginLeft: '4px',
|
|
266
|
+
}}
|
|
267
|
+
>
|
|
268
|
+
<svg
|
|
269
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
270
|
+
width="12"
|
|
271
|
+
height="12"
|
|
272
|
+
viewBox="0 0 24 24"
|
|
273
|
+
fill="none"
|
|
274
|
+
stroke="currentColor"
|
|
275
|
+
strokeWidth="2"
|
|
276
|
+
strokeLinecap="round"
|
|
277
|
+
strokeLinejoin="round"
|
|
278
|
+
>
|
|
279
|
+
<line x1="6" y1="3" x2="6" y2="15" />
|
|
280
|
+
<circle cx="18" cy="6" r="3" />
|
|
281
|
+
<circle cx="6" cy="18" r="3" />
|
|
282
|
+
<path d="M18 9a9 9 0 0 1-9 9" />
|
|
283
|
+
</svg>
|
|
284
|
+
Branch of{' '}
|
|
285
|
+
<a
|
|
286
|
+
href={`/namespaces/${gitConfig.parent_namespace}`}
|
|
287
|
+
style={{ color: '#1e40af', textDecoration: 'underline' }}
|
|
288
|
+
>
|
|
289
|
+
{gitConfig.parent_namespace}
|
|
290
|
+
</a>
|
|
291
|
+
</span>
|
|
292
|
+
)}
|
|
293
|
+
|
|
294
|
+
{/* Git-only (read-only) indicator */}
|
|
295
|
+
{gitConfig?.git_only && (
|
|
296
|
+
<span
|
|
297
|
+
style={{
|
|
298
|
+
display: 'flex',
|
|
299
|
+
alignItems: 'center',
|
|
300
|
+
gap: '4px',
|
|
301
|
+
padding: '2px 8px',
|
|
302
|
+
backgroundColor: '#fef3c7',
|
|
303
|
+
borderRadius: '12px',
|
|
304
|
+
fontSize: '11px',
|
|
305
|
+
color: '#92400e',
|
|
306
|
+
marginLeft: '4px',
|
|
307
|
+
}}
|
|
308
|
+
title="This namespace is git-only. Changes must be made via git and deployed."
|
|
309
|
+
>
|
|
310
|
+
<svg
|
|
311
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
312
|
+
width="12"
|
|
313
|
+
height="12"
|
|
314
|
+
viewBox="0 0 24 24"
|
|
315
|
+
fill="none"
|
|
316
|
+
stroke="currentColor"
|
|
317
|
+
strokeWidth="2"
|
|
318
|
+
strokeLinecap="round"
|
|
319
|
+
strokeLinejoin="round"
|
|
320
|
+
>
|
|
321
|
+
<rect x="3" y="11" width="18" height="11" rx="2" ry="2" />
|
|
322
|
+
<path d="M7 11V7a5 5 0 0 1 10 0v4" />
|
|
323
|
+
</svg>
|
|
324
|
+
Read-only
|
|
325
|
+
</span>
|
|
326
|
+
)}
|
|
327
|
+
|
|
328
|
+
{/* Deployment badge + dropdown (existing functionality) */}
|
|
127
329
|
{sources && sources.total_deployments > 0 && (
|
|
128
330
|
<div
|
|
129
331
|
style={{ position: 'relative', marginLeft: '8px' }}
|
|
@@ -437,12 +639,230 @@ export default function NamespaceHeader({ namespace, children }) {
|
|
|
437
639
|
)}
|
|
438
640
|
</div>
|
|
439
641
|
|
|
440
|
-
{/* Right side actions
|
|
441
|
-
{
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
642
|
+
{/* Right side: git actions + children */}
|
|
643
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
|
|
644
|
+
{/* Git controls for non-branch namespaces */}
|
|
645
|
+
{namespace && !isBranchNamespace && (
|
|
646
|
+
<>
|
|
647
|
+
{hasGitConfig ? (
|
|
648
|
+
<>
|
|
649
|
+
<button
|
|
650
|
+
style={buttonStyle}
|
|
651
|
+
onClick={() => setShowGitSettings(true)}
|
|
652
|
+
title="Git Settings"
|
|
653
|
+
>
|
|
654
|
+
<svg
|
|
655
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
656
|
+
width="14"
|
|
657
|
+
height="14"
|
|
658
|
+
viewBox="0 0 24 24"
|
|
659
|
+
fill="none"
|
|
660
|
+
stroke="currentColor"
|
|
661
|
+
strokeWidth="2"
|
|
662
|
+
strokeLinecap="round"
|
|
663
|
+
strokeLinejoin="round"
|
|
664
|
+
>
|
|
665
|
+
<circle cx="12" cy="12" r="3" />
|
|
666
|
+
<path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z" />
|
|
667
|
+
</svg>
|
|
668
|
+
</button>
|
|
669
|
+
<button
|
|
670
|
+
style={primaryButtonStyle}
|
|
671
|
+
onClick={() => setShowCreateBranch(true)}
|
|
672
|
+
>
|
|
673
|
+
<svg
|
|
674
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
675
|
+
width="14"
|
|
676
|
+
height="14"
|
|
677
|
+
viewBox="0 0 24 24"
|
|
678
|
+
fill="none"
|
|
679
|
+
stroke="currentColor"
|
|
680
|
+
strokeWidth="2"
|
|
681
|
+
strokeLinecap="round"
|
|
682
|
+
strokeLinejoin="round"
|
|
683
|
+
>
|
|
684
|
+
<line x1="12" y1="5" x2="12" y2="19" />
|
|
685
|
+
<line x1="5" y1="12" x2="19" y2="12" />
|
|
686
|
+
</svg>
|
|
687
|
+
New Branch
|
|
688
|
+
</button>
|
|
689
|
+
</>
|
|
690
|
+
) : (
|
|
691
|
+
<button
|
|
692
|
+
style={buttonStyle}
|
|
693
|
+
onClick={() => setShowGitSettings(true)}
|
|
694
|
+
>
|
|
695
|
+
<svg
|
|
696
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
697
|
+
width="14"
|
|
698
|
+
height="14"
|
|
699
|
+
viewBox="0 0 24 24"
|
|
700
|
+
fill="none"
|
|
701
|
+
stroke="currentColor"
|
|
702
|
+
strokeWidth="2"
|
|
703
|
+
strokeLinecap="round"
|
|
704
|
+
strokeLinejoin="round"
|
|
705
|
+
>
|
|
706
|
+
<line x1="6" y1="3" x2="6" y2="15" />
|
|
707
|
+
<circle cx="18" cy="6" r="3" />
|
|
708
|
+
<circle cx="6" cy="18" r="3" />
|
|
709
|
+
<path d="M18 9a9 9 0 0 1-9 9" />
|
|
710
|
+
</svg>
|
|
711
|
+
Configure Git
|
|
712
|
+
</button>
|
|
713
|
+
)}
|
|
714
|
+
</>
|
|
715
|
+
)}
|
|
716
|
+
|
|
717
|
+
{/* Git controls for branch namespaces */}
|
|
718
|
+
{isBranchNamespace && hasGitConfig && (
|
|
719
|
+
<>
|
|
720
|
+
<button style={buttonStyle} onClick={() => setShowSyncToGit(true)}>
|
|
721
|
+
<svg
|
|
722
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
723
|
+
width="14"
|
|
724
|
+
height="14"
|
|
725
|
+
viewBox="0 0 24 24"
|
|
726
|
+
fill="none"
|
|
727
|
+
stroke="currentColor"
|
|
728
|
+
strokeWidth="2"
|
|
729
|
+
strokeLinecap="round"
|
|
730
|
+
strokeLinejoin="round"
|
|
731
|
+
>
|
|
732
|
+
<path d="M21 12a9 9 0 0 1-9 9m9-9a9 9 0 0 0-9-9m9 9H3m9 9a9 9 0 0 1-9-9m9 9c1.66 0 3-4.03 3-9s-1.34-9-3-9m0 18c-1.66 0-3-4.03-3-9s1.34-9 3-9m-9 9a9 9 0 0 1 9-9" />
|
|
733
|
+
</svg>
|
|
734
|
+
Sync to Git
|
|
735
|
+
</button>
|
|
736
|
+
{existingPR ? (
|
|
737
|
+
<a
|
|
738
|
+
href={existingPR.pr_url}
|
|
739
|
+
target="_blank"
|
|
740
|
+
rel="noopener noreferrer"
|
|
741
|
+
style={{
|
|
742
|
+
...primaryButtonStyle,
|
|
743
|
+
textDecoration: 'none',
|
|
744
|
+
backgroundColor: '#16a34a',
|
|
745
|
+
borderColor: '#16a34a',
|
|
746
|
+
}}
|
|
747
|
+
>
|
|
748
|
+
<svg
|
|
749
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
750
|
+
width="14"
|
|
751
|
+
height="14"
|
|
752
|
+
viewBox="0 0 24 24"
|
|
753
|
+
fill="none"
|
|
754
|
+
stroke="currentColor"
|
|
755
|
+
strokeWidth="2"
|
|
756
|
+
strokeLinecap="round"
|
|
757
|
+
strokeLinejoin="round"
|
|
758
|
+
>
|
|
759
|
+
<circle cx="18" cy="18" r="3" />
|
|
760
|
+
<circle cx="6" cy="6" r="3" />
|
|
761
|
+
<path d="M13 6h3a2 2 0 0 1 2 2v7" />
|
|
762
|
+
<line x1="6" y1="9" x2="6" y2="21" />
|
|
763
|
+
</svg>
|
|
764
|
+
View PR #{existingPR.pr_number}
|
|
765
|
+
</a>
|
|
766
|
+
) : (
|
|
767
|
+
<button
|
|
768
|
+
style={primaryButtonStyle}
|
|
769
|
+
onClick={() => setShowCreatePR(true)}
|
|
770
|
+
>
|
|
771
|
+
<svg
|
|
772
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
773
|
+
width="14"
|
|
774
|
+
height="14"
|
|
775
|
+
viewBox="0 0 24 24"
|
|
776
|
+
fill="none"
|
|
777
|
+
stroke="currentColor"
|
|
778
|
+
strokeWidth="2"
|
|
779
|
+
strokeLinecap="round"
|
|
780
|
+
strokeLinejoin="round"
|
|
781
|
+
>
|
|
782
|
+
<circle cx="18" cy="18" r="3" />
|
|
783
|
+
<circle cx="6" cy="6" r="3" />
|
|
784
|
+
<path d="M13 6h3a2 2 0 0 1 2 2v7" />
|
|
785
|
+
<line x1="6" y1="9" x2="6" y2="21" />
|
|
786
|
+
</svg>
|
|
787
|
+
Create PR
|
|
788
|
+
</button>
|
|
789
|
+
)}
|
|
790
|
+
<button
|
|
791
|
+
style={{
|
|
792
|
+
...buttonStyle,
|
|
793
|
+
color: '#dc2626',
|
|
794
|
+
borderColor: '#fecaca',
|
|
795
|
+
}}
|
|
796
|
+
onClick={() => setShowDeleteBranch(true)}
|
|
797
|
+
title="Delete Branch"
|
|
798
|
+
>
|
|
799
|
+
<svg
|
|
800
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
801
|
+
width="14"
|
|
802
|
+
height="14"
|
|
803
|
+
viewBox="0 0 24 24"
|
|
804
|
+
fill="none"
|
|
805
|
+
stroke="currentColor"
|
|
806
|
+
strokeWidth="2"
|
|
807
|
+
strokeLinecap="round"
|
|
808
|
+
strokeLinejoin="round"
|
|
809
|
+
>
|
|
810
|
+
<path d="M3 6h18" />
|
|
811
|
+
<path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6" />
|
|
812
|
+
<path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2" />
|
|
813
|
+
</svg>
|
|
814
|
+
</button>
|
|
815
|
+
</>
|
|
816
|
+
)}
|
|
817
|
+
|
|
818
|
+
{/* Additional actions passed as children */}
|
|
819
|
+
{children}
|
|
820
|
+
</div>
|
|
821
|
+
|
|
822
|
+
{/* Modals */}
|
|
823
|
+
<GitSettingsModal
|
|
824
|
+
isOpen={showGitSettings}
|
|
825
|
+
onClose={() => setShowGitSettings(false)}
|
|
826
|
+
onSave={handleSaveGitConfig}
|
|
827
|
+
currentConfig={gitConfig}
|
|
828
|
+
namespace={namespace}
|
|
829
|
+
/>
|
|
830
|
+
|
|
831
|
+
<CreateBranchModal
|
|
832
|
+
isOpen={showCreateBranch}
|
|
833
|
+
onClose={() => setShowCreateBranch(false)}
|
|
834
|
+
onCreate={handleCreateBranch}
|
|
835
|
+
namespace={namespace}
|
|
836
|
+
gitBranch={gitConfig?.git_branch}
|
|
837
|
+
/>
|
|
838
|
+
|
|
839
|
+
<SyncToGitModal
|
|
840
|
+
isOpen={showSyncToGit}
|
|
841
|
+
onClose={() => setShowSyncToGit(false)}
|
|
842
|
+
onSync={handleSyncToGit}
|
|
843
|
+
namespace={namespace}
|
|
844
|
+
gitBranch={gitConfig?.git_branch}
|
|
845
|
+
repoPath={gitConfig?.github_repo_path}
|
|
846
|
+
/>
|
|
847
|
+
|
|
848
|
+
<CreatePRModal
|
|
849
|
+
isOpen={showCreatePR}
|
|
850
|
+
onClose={() => setShowCreatePR(false)}
|
|
851
|
+
onCreate={handleCreatePR}
|
|
852
|
+
namespace={namespace}
|
|
853
|
+
gitBranch={gitConfig?.git_branch}
|
|
854
|
+
parentBranch={parentGitConfig?.git_branch}
|
|
855
|
+
repoPath={gitConfig?.github_repo_path}
|
|
856
|
+
/>
|
|
857
|
+
|
|
858
|
+
<DeleteBranchModal
|
|
859
|
+
isOpen={showDeleteBranch}
|
|
860
|
+
onClose={() => setShowDeleteBranch(false)}
|
|
861
|
+
onDelete={handleDeleteBranch}
|
|
862
|
+
namespace={namespace}
|
|
863
|
+
gitBranch={gitConfig?.git_branch}
|
|
864
|
+
parentNamespace={gitConfig?.parent_namespace}
|
|
865
|
+
/>
|
|
446
866
|
</div>
|
|
447
867
|
);
|
|
448
868
|
}
|
|
@@ -6,9 +6,8 @@ import { Form, Formik } from 'formik';
|
|
|
6
6
|
import { useContext } from 'react';
|
|
7
7
|
import { displayMessageAfterSubmit } from '../../utils/form';
|
|
8
8
|
|
|
9
|
-
export default function NodeListActions({ nodeName }) {
|
|
10
|
-
const [
|
|
11
|
-
const [deleteButton, setDeleteButton] = React.useState(<DeleteIcon />);
|
|
9
|
+
export default function NodeListActions({ nodeName, iconSize = 20 }) {
|
|
10
|
+
const [deleted, setDeleted] = React.useState(false);
|
|
12
11
|
|
|
13
12
|
const djClient = useContext(DJClientContext).DataJunctionAPI;
|
|
14
13
|
const deleteNode = async (values, { setStatus }) => {
|
|
@@ -22,8 +21,8 @@ export default function NodeListActions({ nodeName }) {
|
|
|
22
21
|
setStatus({
|
|
23
22
|
success: <>Successfully deleted node {values.nodeName}</>,
|
|
24
23
|
});
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
// Delay hiding component so success message is visible briefly
|
|
25
|
+
setTimeout(() => setDeleted(true), 1500);
|
|
27
26
|
} else {
|
|
28
27
|
setStatus({
|
|
29
28
|
failure: `${json.message}`,
|
|
@@ -35,10 +34,14 @@ export default function NodeListActions({ nodeName }) {
|
|
|
35
34
|
nodeName: nodeName,
|
|
36
35
|
};
|
|
37
36
|
|
|
37
|
+
if (deleted) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
|
|
38
41
|
return (
|
|
39
42
|
<div>
|
|
40
43
|
<a href={`/nodes/${nodeName}/edit`} style={{ marginLeft: '0.5rem' }}>
|
|
41
|
-
{
|
|
44
|
+
<EditIcon size={iconSize} />
|
|
42
45
|
</a>
|
|
43
46
|
<Formik initialValues={initialValues} onSubmit={deleteNode}>
|
|
44
47
|
{function Render({ status, setFieldValue }) {
|
|
@@ -56,7 +59,7 @@ export default function NodeListActions({ nodeName }) {
|
|
|
56
59
|
cursor: 'pointer',
|
|
57
60
|
}}
|
|
58
61
|
>
|
|
59
|
-
{
|
|
62
|
+
<DeleteIcon size={iconSize} />
|
|
60
63
|
</button>
|
|
61
64
|
</>
|
|
62
65
|
}
|