datajunction-ui 0.0.55 → 0.0.57
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 +423 -12
- 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 +905 -16
- package/src/app/components/__tests__/NodeListActions.test.jsx +5 -3
- package/src/app/components/__tests__/__snapshots__/NamespaceHeader.test.jsx.snap +41 -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 +375 -0
- package/src/app/components/git/SyncToGitModal.jsx +219 -0
- package/src/app/components/git/__tests__/GitSettingsModal.test.jsx +301 -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 +218 -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,48 @@
|
|
|
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 [gitConfigLoading, setGitConfigLoading] = useState(true);
|
|
25
|
+
const [parentGitConfig, setParentGitConfig] = useState(null);
|
|
26
|
+
const [existingPR, setExistingPR] = useState(null);
|
|
27
|
+
|
|
28
|
+
// Modal states
|
|
29
|
+
const [showGitSettings, setShowGitSettings] = useState(false);
|
|
30
|
+
const [showCreateBranch, setShowCreateBranch] = useState(false);
|
|
31
|
+
const [showSyncToGit, setShowSyncToGit] = useState(false);
|
|
32
|
+
const [showCreatePR, setShowCreatePR] = useState(false);
|
|
33
|
+
const [showDeleteBranch, setShowDeleteBranch] = useState(false);
|
|
34
|
+
|
|
11
35
|
useEffect(() => {
|
|
12
|
-
|
|
36
|
+
// Reset loading state when namespace changes
|
|
37
|
+
setGitConfigLoading(true);
|
|
38
|
+
|
|
39
|
+
const fetchData = async () => {
|
|
13
40
|
if (namespace) {
|
|
41
|
+
// Fetch deployment sources
|
|
14
42
|
try {
|
|
15
43
|
const data = await djClient.namespaceSources(namespace);
|
|
16
44
|
setSources(data);
|
|
17
45
|
|
|
18
|
-
// Fetch recent deployments for this namespace
|
|
19
46
|
try {
|
|
20
47
|
const deployments = await djClient.listDeployments(namespace, 5);
|
|
21
48
|
setRecentDeployments(deployments || []);
|
|
@@ -26,9 +53,47 @@ export default function NamespaceHeader({ namespace, children }) {
|
|
|
26
53
|
} catch (e) {
|
|
27
54
|
// Silently fail - badge just won't show
|
|
28
55
|
}
|
|
56
|
+
|
|
57
|
+
// Fetch git config
|
|
58
|
+
try {
|
|
59
|
+
const config = await djClient.getNamespaceGitConfig(namespace);
|
|
60
|
+
setGitConfig(config);
|
|
61
|
+
if (onGitConfigLoaded) {
|
|
62
|
+
onGitConfigLoaded(config);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// If this is a branch namespace, fetch parent's git config and check for existing PR
|
|
66
|
+
if (config?.parent_namespace) {
|
|
67
|
+
try {
|
|
68
|
+
const parentConfig = await djClient.getNamespaceGitConfig(
|
|
69
|
+
config.parent_namespace,
|
|
70
|
+
);
|
|
71
|
+
setParentGitConfig(parentConfig);
|
|
72
|
+
} catch (e) {
|
|
73
|
+
console.error('Failed to fetch parent git config:', e);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Check for existing PR
|
|
77
|
+
try {
|
|
78
|
+
const pr = await djClient.getPullRequest(namespace);
|
|
79
|
+
setExistingPR(pr);
|
|
80
|
+
} catch (e) {
|
|
81
|
+
// No PR or error - that's fine
|
|
82
|
+
setExistingPR(null);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
} catch (e) {
|
|
86
|
+
// Git config not available
|
|
87
|
+
setGitConfig(null);
|
|
88
|
+
if (onGitConfigLoaded) {
|
|
89
|
+
onGitConfigLoaded(null);
|
|
90
|
+
}
|
|
91
|
+
} finally {
|
|
92
|
+
setGitConfigLoading(false);
|
|
93
|
+
}
|
|
29
94
|
}
|
|
30
95
|
};
|
|
31
|
-
|
|
96
|
+
fetchData();
|
|
32
97
|
}, [djClient, namespace]);
|
|
33
98
|
|
|
34
99
|
// Close dropdown when clicking outside
|
|
@@ -44,6 +109,80 @@ export default function NamespaceHeader({ namespace, children }) {
|
|
|
44
109
|
|
|
45
110
|
const namespaceParts = namespace ? namespace.split('.') : [];
|
|
46
111
|
|
|
112
|
+
const hasGitConfig = gitConfig?.github_repo_path && gitConfig?.git_branch;
|
|
113
|
+
const isBranchNamespace = !!gitConfig?.parent_namespace;
|
|
114
|
+
|
|
115
|
+
// Handlers for git operations
|
|
116
|
+
const handleSaveGitConfig = async config => {
|
|
117
|
+
const result = await djClient.updateNamespaceGitConfig(namespace, config);
|
|
118
|
+
if (!result?._error) {
|
|
119
|
+
setGitConfig(result);
|
|
120
|
+
}
|
|
121
|
+
return result;
|
|
122
|
+
};
|
|
123
|
+
const handleRemoveGitConfig = async () => {
|
|
124
|
+
const result = await djClient.deleteNamespaceGitConfig(namespace);
|
|
125
|
+
if (!result?._error) {
|
|
126
|
+
setGitConfig(null);
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
const handleCreateBranch = async branchName => {
|
|
131
|
+
return await djClient.createBranch(namespace, branchName);
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const handleSyncToGit = async commitMessage => {
|
|
135
|
+
return await djClient.syncNamespaceToGit(namespace, commitMessage);
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const handleCreatePR = async (title, body, onProgress) => {
|
|
139
|
+
// First sync changes to git using PR title as commit message
|
|
140
|
+
if (onProgress) onProgress('syncing');
|
|
141
|
+
const syncResult = await djClient.syncNamespaceToGit(namespace, title);
|
|
142
|
+
if (syncResult?._error) {
|
|
143
|
+
return syncResult;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Then create the PR
|
|
147
|
+
if (onProgress) onProgress('creating');
|
|
148
|
+
const result = await djClient.createPullRequest(namespace, title, body);
|
|
149
|
+
if (result && !result._error) {
|
|
150
|
+
setExistingPR(result);
|
|
151
|
+
}
|
|
152
|
+
return result;
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
const handleDeleteBranch = async deleteGitBranch => {
|
|
156
|
+
return await djClient.deleteBranch(
|
|
157
|
+
gitConfig.parent_namespace,
|
|
158
|
+
namespace,
|
|
159
|
+
deleteGitBranch,
|
|
160
|
+
);
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
// Button style helpers
|
|
164
|
+
const buttonStyle = {
|
|
165
|
+
height: '28px',
|
|
166
|
+
padding: '0 10px',
|
|
167
|
+
fontSize: '12px',
|
|
168
|
+
border: '1px solid #e2e8f0',
|
|
169
|
+
borderRadius: '4px',
|
|
170
|
+
backgroundColor: '#ffffff',
|
|
171
|
+
color: '#475569',
|
|
172
|
+
cursor: 'pointer',
|
|
173
|
+
display: 'flex',
|
|
174
|
+
alignItems: 'center',
|
|
175
|
+
gap: '4px',
|
|
176
|
+
whiteSpace: 'nowrap',
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
const primaryButtonStyle = {
|
|
180
|
+
...buttonStyle,
|
|
181
|
+
backgroundColor: '#3b82f6',
|
|
182
|
+
borderColor: '#3b82f6',
|
|
183
|
+
color: '#ffffff',
|
|
184
|
+
};
|
|
185
|
+
|
|
47
186
|
return (
|
|
48
187
|
<div
|
|
49
188
|
style={{
|
|
@@ -123,7 +262,82 @@ export default function NamespaceHeader({ namespace, children }) {
|
|
|
123
262
|
</span>
|
|
124
263
|
)}
|
|
125
264
|
|
|
126
|
-
{/*
|
|
265
|
+
{/* Branch indicator */}
|
|
266
|
+
{isBranchNamespace && (
|
|
267
|
+
<span
|
|
268
|
+
style={{
|
|
269
|
+
display: 'flex',
|
|
270
|
+
alignItems: 'center',
|
|
271
|
+
gap: '4px',
|
|
272
|
+
padding: '2px 8px',
|
|
273
|
+
backgroundColor: '#dbeafe',
|
|
274
|
+
borderRadius: '12px',
|
|
275
|
+
fontSize: '11px',
|
|
276
|
+
color: '#1e40af',
|
|
277
|
+
marginLeft: '4px',
|
|
278
|
+
}}
|
|
279
|
+
>
|
|
280
|
+
<svg
|
|
281
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
282
|
+
width="12"
|
|
283
|
+
height="12"
|
|
284
|
+
viewBox="0 0 24 24"
|
|
285
|
+
fill="none"
|
|
286
|
+
stroke="currentColor"
|
|
287
|
+
strokeWidth="2"
|
|
288
|
+
strokeLinecap="round"
|
|
289
|
+
strokeLinejoin="round"
|
|
290
|
+
>
|
|
291
|
+
<line x1="6" y1="3" x2="6" y2="15" />
|
|
292
|
+
<circle cx="18" cy="6" r="3" />
|
|
293
|
+
<circle cx="6" cy="18" r="3" />
|
|
294
|
+
<path d="M18 9a9 9 0 0 1-9 9" />
|
|
295
|
+
</svg>
|
|
296
|
+
Branch of{' '}
|
|
297
|
+
<a
|
|
298
|
+
href={`/namespaces/${gitConfig.parent_namespace}`}
|
|
299
|
+
style={{ color: '#1e40af', textDecoration: 'underline' }}
|
|
300
|
+
>
|
|
301
|
+
{gitConfig.parent_namespace}
|
|
302
|
+
</a>
|
|
303
|
+
</span>
|
|
304
|
+
)}
|
|
305
|
+
|
|
306
|
+
{/* Git-only (read-only) indicator */}
|
|
307
|
+
{gitConfig?.git_only && (
|
|
308
|
+
<span
|
|
309
|
+
style={{
|
|
310
|
+
display: 'flex',
|
|
311
|
+
alignItems: 'center',
|
|
312
|
+
gap: '4px',
|
|
313
|
+
padding: '2px 8px',
|
|
314
|
+
backgroundColor: '#fef3c7',
|
|
315
|
+
borderRadius: '12px',
|
|
316
|
+
fontSize: '11px',
|
|
317
|
+
color: '#92400e',
|
|
318
|
+
marginLeft: '4px',
|
|
319
|
+
}}
|
|
320
|
+
title="This namespace is git-only. Changes must be made via git and deployed."
|
|
321
|
+
>
|
|
322
|
+
<svg
|
|
323
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
324
|
+
width="12"
|
|
325
|
+
height="12"
|
|
326
|
+
viewBox="0 0 24 24"
|
|
327
|
+
fill="none"
|
|
328
|
+
stroke="currentColor"
|
|
329
|
+
strokeWidth="2"
|
|
330
|
+
strokeLinecap="round"
|
|
331
|
+
strokeLinejoin="round"
|
|
332
|
+
>
|
|
333
|
+
<rect x="3" y="11" width="18" height="11" rx="2" ry="2" />
|
|
334
|
+
<path d="M7 11V7a5 5 0 0 1 10 0v4" />
|
|
335
|
+
</svg>
|
|
336
|
+
Read-only
|
|
337
|
+
</span>
|
|
338
|
+
)}
|
|
339
|
+
|
|
340
|
+
{/* Deployment badge + dropdown (existing functionality) */}
|
|
127
341
|
{sources && sources.total_deployments > 0 && (
|
|
128
342
|
<div
|
|
129
343
|
style={{ position: 'relative', marginLeft: '8px' }}
|
|
@@ -166,7 +380,7 @@ export default function NamespaceHeader({ namespace, children }) {
|
|
|
166
380
|
<circle cx="6" cy="18" r="3"></circle>
|
|
167
381
|
<path d="M18 9a9 9 0 0 1-9 9"></path>
|
|
168
382
|
</svg>
|
|
169
|
-
Git
|
|
383
|
+
Deployed from Git
|
|
170
384
|
</>
|
|
171
385
|
) : (
|
|
172
386
|
<>
|
|
@@ -437,12 +651,209 @@ export default function NamespaceHeader({ namespace, children }) {
|
|
|
437
651
|
)}
|
|
438
652
|
</div>
|
|
439
653
|
|
|
440
|
-
{/* Right side actions
|
|
441
|
-
{
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
654
|
+
{/* Right side: git actions + children */}
|
|
655
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
|
|
656
|
+
{/* Git controls for non-branch namespaces */}
|
|
657
|
+
{namespace && !isBranchNamespace && !gitConfigLoading && (
|
|
658
|
+
<>
|
|
659
|
+
<button
|
|
660
|
+
style={buttonStyle}
|
|
661
|
+
onClick={() => setShowGitSettings(true)}
|
|
662
|
+
title="Git Settings"
|
|
663
|
+
>
|
|
664
|
+
<svg
|
|
665
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
666
|
+
width="14"
|
|
667
|
+
height="14"
|
|
668
|
+
viewBox="0 0 24 24"
|
|
669
|
+
fill="none"
|
|
670
|
+
stroke="currentColor"
|
|
671
|
+
strokeWidth="2"
|
|
672
|
+
strokeLinecap="round"
|
|
673
|
+
strokeLinejoin="round"
|
|
674
|
+
>
|
|
675
|
+
<circle cx="12" cy="12" r="3" />
|
|
676
|
+
<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" />
|
|
677
|
+
</svg>
|
|
678
|
+
Git Settings
|
|
679
|
+
</button>
|
|
680
|
+
{hasGitConfig ? (
|
|
681
|
+
<button
|
|
682
|
+
style={primaryButtonStyle}
|
|
683
|
+
onClick={() => setShowCreateBranch(true)}
|
|
684
|
+
>
|
|
685
|
+
<svg
|
|
686
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
687
|
+
width="14"
|
|
688
|
+
height="14"
|
|
689
|
+
viewBox="0 0 24 24"
|
|
690
|
+
fill="none"
|
|
691
|
+
stroke="currentColor"
|
|
692
|
+
strokeWidth="2"
|
|
693
|
+
strokeLinecap="round"
|
|
694
|
+
strokeLinejoin="round"
|
|
695
|
+
>
|
|
696
|
+
<line x1="12" y1="5" x2="12" y2="19" />
|
|
697
|
+
<line x1="5" y1="12" x2="19" y2="12" />
|
|
698
|
+
</svg>
|
|
699
|
+
New Branch
|
|
700
|
+
</button>
|
|
701
|
+
) : (
|
|
702
|
+
<></>
|
|
703
|
+
)}
|
|
704
|
+
</>
|
|
705
|
+
)}
|
|
706
|
+
|
|
707
|
+
{/* Git controls for branch namespaces */}
|
|
708
|
+
{isBranchNamespace && hasGitConfig && (
|
|
709
|
+
<>
|
|
710
|
+
<button style={buttonStyle} onClick={() => setShowSyncToGit(true)}>
|
|
711
|
+
<svg
|
|
712
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
713
|
+
width="14"
|
|
714
|
+
height="14"
|
|
715
|
+
viewBox="0 0 24 24"
|
|
716
|
+
fill="none"
|
|
717
|
+
stroke="currentColor"
|
|
718
|
+
strokeWidth="2"
|
|
719
|
+
strokeLinecap="round"
|
|
720
|
+
strokeLinejoin="round"
|
|
721
|
+
>
|
|
722
|
+
<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" />
|
|
723
|
+
</svg>
|
|
724
|
+
Sync to Git
|
|
725
|
+
</button>
|
|
726
|
+
{existingPR ? (
|
|
727
|
+
<a
|
|
728
|
+
href={existingPR.pr_url}
|
|
729
|
+
target="_blank"
|
|
730
|
+
rel="noopener noreferrer"
|
|
731
|
+
style={{
|
|
732
|
+
...primaryButtonStyle,
|
|
733
|
+
textDecoration: 'none',
|
|
734
|
+
backgroundColor: '#16a34a',
|
|
735
|
+
borderColor: '#16a34a',
|
|
736
|
+
}}
|
|
737
|
+
>
|
|
738
|
+
<svg
|
|
739
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
740
|
+
width="14"
|
|
741
|
+
height="14"
|
|
742
|
+
viewBox="0 0 24 24"
|
|
743
|
+
fill="none"
|
|
744
|
+
stroke="currentColor"
|
|
745
|
+
strokeWidth="2"
|
|
746
|
+
strokeLinecap="round"
|
|
747
|
+
strokeLinejoin="round"
|
|
748
|
+
>
|
|
749
|
+
<circle cx="18" cy="18" r="3" />
|
|
750
|
+
<circle cx="6" cy="6" r="3" />
|
|
751
|
+
<path d="M13 6h3a2 2 0 0 1 2 2v7" />
|
|
752
|
+
<line x1="6" y1="9" x2="6" y2="21" />
|
|
753
|
+
</svg>
|
|
754
|
+
View PR #{existingPR.pr_number}
|
|
755
|
+
</a>
|
|
756
|
+
) : (
|
|
757
|
+
<button
|
|
758
|
+
style={primaryButtonStyle}
|
|
759
|
+
onClick={() => setShowCreatePR(true)}
|
|
760
|
+
>
|
|
761
|
+
<svg
|
|
762
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
763
|
+
width="14"
|
|
764
|
+
height="14"
|
|
765
|
+
viewBox="0 0 24 24"
|
|
766
|
+
fill="none"
|
|
767
|
+
stroke="currentColor"
|
|
768
|
+
strokeWidth="2"
|
|
769
|
+
strokeLinecap="round"
|
|
770
|
+
strokeLinejoin="round"
|
|
771
|
+
>
|
|
772
|
+
<circle cx="18" cy="18" r="3" />
|
|
773
|
+
<circle cx="6" cy="6" r="3" />
|
|
774
|
+
<path d="M13 6h3a2 2 0 0 1 2 2v7" />
|
|
775
|
+
<line x1="6" y1="9" x2="6" y2="21" />
|
|
776
|
+
</svg>
|
|
777
|
+
Create PR
|
|
778
|
+
</button>
|
|
779
|
+
)}
|
|
780
|
+
<button
|
|
781
|
+
style={{
|
|
782
|
+
...buttonStyle,
|
|
783
|
+
color: '#dc2626',
|
|
784
|
+
borderColor: '#fecaca',
|
|
785
|
+
}}
|
|
786
|
+
onClick={() => setShowDeleteBranch(true)}
|
|
787
|
+
title="Delete Branch"
|
|
788
|
+
>
|
|
789
|
+
<svg
|
|
790
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
791
|
+
width="14"
|
|
792
|
+
height="14"
|
|
793
|
+
viewBox="0 0 24 24"
|
|
794
|
+
fill="none"
|
|
795
|
+
stroke="currentColor"
|
|
796
|
+
strokeWidth="2"
|
|
797
|
+
strokeLinecap="round"
|
|
798
|
+
strokeLinejoin="round"
|
|
799
|
+
>
|
|
800
|
+
<path d="M3 6h18" />
|
|
801
|
+
<path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6" />
|
|
802
|
+
<path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2" />
|
|
803
|
+
</svg>
|
|
804
|
+
</button>
|
|
805
|
+
</>
|
|
806
|
+
)}
|
|
807
|
+
|
|
808
|
+
{/* Additional actions passed as children */}
|
|
809
|
+
{children}
|
|
810
|
+
</div>
|
|
811
|
+
|
|
812
|
+
{/* Modals */}
|
|
813
|
+
<GitSettingsModal
|
|
814
|
+
isOpen={showGitSettings}
|
|
815
|
+
onClose={() => setShowGitSettings(false)}
|
|
816
|
+
onSave={handleSaveGitConfig}
|
|
817
|
+
onRemove={handleRemoveGitConfig}
|
|
818
|
+
currentConfig={gitConfig}
|
|
819
|
+
namespace={namespace}
|
|
820
|
+
/>
|
|
821
|
+
|
|
822
|
+
<CreateBranchModal
|
|
823
|
+
isOpen={showCreateBranch}
|
|
824
|
+
onClose={() => setShowCreateBranch(false)}
|
|
825
|
+
onCreate={handleCreateBranch}
|
|
826
|
+
namespace={namespace}
|
|
827
|
+
gitBranch={gitConfig?.git_branch}
|
|
828
|
+
/>
|
|
829
|
+
|
|
830
|
+
<SyncToGitModal
|
|
831
|
+
isOpen={showSyncToGit}
|
|
832
|
+
onClose={() => setShowSyncToGit(false)}
|
|
833
|
+
onSync={handleSyncToGit}
|
|
834
|
+
namespace={namespace}
|
|
835
|
+
gitBranch={gitConfig?.git_branch}
|
|
836
|
+
repoPath={gitConfig?.github_repo_path}
|
|
837
|
+
/>
|
|
838
|
+
|
|
839
|
+
<CreatePRModal
|
|
840
|
+
isOpen={showCreatePR}
|
|
841
|
+
onClose={() => setShowCreatePR(false)}
|
|
842
|
+
onCreate={handleCreatePR}
|
|
843
|
+
namespace={namespace}
|
|
844
|
+
gitBranch={gitConfig?.git_branch}
|
|
845
|
+
parentBranch={parentGitConfig?.git_branch}
|
|
846
|
+
repoPath={gitConfig?.github_repo_path}
|
|
847
|
+
/>
|
|
848
|
+
|
|
849
|
+
<DeleteBranchModal
|
|
850
|
+
isOpen={showDeleteBranch}
|
|
851
|
+
onClose={() => setShowDeleteBranch(false)}
|
|
852
|
+
onDelete={handleDeleteBranch}
|
|
853
|
+
namespace={namespace}
|
|
854
|
+
gitBranch={gitConfig?.git_branch}
|
|
855
|
+
parentNamespace={gitConfig?.parent_namespace}
|
|
856
|
+
/>
|
|
446
857
|
</div>
|
|
447
858
|
);
|
|
448
859
|
}
|
|
@@ -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
|
}
|