@backstage/plugin-scaffolder 1.15.1 → 1.16.0-next.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/CHANGELOG.md +32 -0
- package/alpha/package.json +1 -1
- package/dist/alpha.d.ts +36 -10
- package/dist/alpha.esm.js +87 -11
- package/dist/alpha.esm.js.map +1 -1
- package/dist/esm/{ListTasksPage-b7beed35.esm.js → DryRunResults-a4d44358.esm.js} +1132 -829
- package/dist/esm/DryRunResults-a4d44358.esm.js.map +1 -0
- package/dist/esm/{plugin-76d8b756.esm.js → OngoingTask-8acb140b.esm.js} +292 -11
- package/dist/esm/OngoingTask-8acb140b.esm.js.map +1 -0
- package/dist/esm/{Router-f5f81642.esm.js → Router-b60d8000.esm.js} +172 -168
- package/dist/esm/Router-b60d8000.esm.js.map +1 -0
- package/dist/esm/{index-e1da2925.esm.js → index-52e5acc5.esm.js} +79 -279
- package/dist/esm/index-52e5acc5.esm.js.map +1 -0
- package/dist/index.d.ts +17 -14
- package/dist/index.esm.js +9 -17
- package/dist/index.esm.js.map +1 -1
- package/dist/types/{plugin.d-2d1240f7.d.ts → plugin.d-63255bd3.d.ts} +43 -76
- package/package.json +19 -20
- package/dist/esm/ListTasksPage-b7beed35.esm.js.map +0 -1
- package/dist/esm/Router-f5f81642.esm.js.map +0 -1
- package/dist/esm/TaskPage-d1a669e0.esm.js +0 -322
- package/dist/esm/TaskPage-d1a669e0.esm.js.map +0 -1
- package/dist/esm/TemplateTypePicker-efec8c34.esm.js +0 -66
- package/dist/esm/TemplateTypePicker-efec8c34.esm.js.map +0 -1
- package/dist/esm/index-e1da2925.esm.js.map +0 -1
- package/dist/esm/plugin-76d8b756.esm.js.map +0 -1
|
@@ -1,57 +1,360 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { useRef, useEffect, memo, useState, useMemo, Fragment, createContext, useContext, useCallback, Children } from 'react';
|
|
2
2
|
import useAsync from 'react-use/lib/useAsync';
|
|
3
|
-
import { scaffolderApiRef } from '@backstage/plugin-scaffolder-react';
|
|
4
|
-
import { makeStyles,
|
|
3
|
+
import { scaffolderApiRef, useTaskEventStream } from '@backstage/plugin-scaffolder-react';
|
|
4
|
+
import { Box, makeStyles, Grid, Typography, StepButton, CircularProgress, Paper, Button, Accordion, AccordionSummary, AccordionDetails, TableContainer, Table, TableHead, TableRow, TableCell, TableBody, Collapse, Card, List, MenuItem, ListItemIcon, ListItemText, Tooltip as Tooltip$1, IconButton, Divider } from '@material-ui/core';
|
|
5
5
|
import classNames from 'classnames';
|
|
6
6
|
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
|
|
7
7
|
import ExpandLessIcon from '@material-ui/icons/ExpandLess';
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
8
|
+
import { useApp, useRouteRef, useApi, useRouteRefParams } from '@backstage/core-plugin-api';
|
|
9
|
+
import { DismissableBanner, Link, Page, Header, Content, ErrorPage, Progress, LogViewer, MarkdownContent, CodeSnippet, StatusError, StatusOK, StatusPending, Lifecycle, ErrorPanel, EmptyState, Table as Table$1 } from '@backstage/core-components';
|
|
10
10
|
import Chip from '@material-ui/core/Chip';
|
|
11
|
-
import
|
|
11
|
+
import { r as rootRouteRef, o as selectedTemplateRouteRef, w as scaffolderTaskRouteRef, y as EntityPicker, z as EntityPickerSchema, A as EntityNamePicker, B as entityNamePickerValidation, C as EntityNamePickerSchema, D as EntityTagsPicker, F as EntityTagsPickerSchema, G as RepoUrlPicker, i as repoPickerValidation, H as RepoUrlPickerSchema, I as OwnerPicker, J as OwnerPickerSchema, K as OwnedEntityPicker, N as OwnedEntityPickerSchema, P as MyGroupsPicker, l as MyGroupsPickerSchema } from './OngoingTask-8acb140b.esm.js';
|
|
12
|
+
import { entityRouteRef, catalogApiRef, EntityRefLink, CatalogFilterLayout } from '@backstage/plugin-catalog-react';
|
|
13
|
+
import SettingsIcon from '@material-ui/icons/Settings';
|
|
14
|
+
import AllIcon from '@material-ui/icons/FontDownload';
|
|
15
|
+
import { DateTime, Interval } from 'luxon';
|
|
16
|
+
import humanizeDuration from 'humanize-duration';
|
|
17
|
+
import Typography$1 from '@material-ui/core/Typography';
|
|
18
|
+
import { parseEntityRef } from '@backstage/catalog-model';
|
|
19
|
+
import Card$1 from '@material-ui/core/Card';
|
|
12
20
|
import CardActionArea from '@material-ui/core/CardActionArea';
|
|
13
21
|
import CardContent from '@material-ui/core/CardContent';
|
|
14
22
|
import Tooltip from '@material-ui/core/Tooltip';
|
|
15
|
-
import Typography$1 from '@material-ui/core/Typography';
|
|
16
23
|
import InfoOutlinedIcon from '@material-ui/icons/InfoOutlined';
|
|
17
|
-
import { makeStyles as makeStyles$1 } from '@material-ui/core/styles';
|
|
24
|
+
import { makeStyles as makeStyles$1, createStyles } from '@material-ui/core/styles';
|
|
25
|
+
import CloseIcon from '@material-ui/icons/Close';
|
|
26
|
+
import RefreshIcon from '@material-ui/icons/Refresh';
|
|
27
|
+
import SaveIcon from '@material-ui/icons/Save';
|
|
28
|
+
import { StreamLanguage } from '@codemirror/language';
|
|
29
|
+
import { yaml as yaml$1 } from '@codemirror/legacy-modes/mode/yaml';
|
|
30
|
+
import { showPanel } from '@codemirror/view';
|
|
31
|
+
import { useAsync as useAsync$1, useRerender, useKeyboardEvent, usePrevious } from '@react-hookz/web';
|
|
32
|
+
import CodeMirror from '@uiw/react-codemirror';
|
|
18
33
|
import Accordion$1 from '@material-ui/core/Accordion';
|
|
19
34
|
import AccordionDetails$1 from '@material-ui/core/AccordionDetails';
|
|
20
35
|
import AccordionSummary$1 from '@material-ui/core/AccordionSummary';
|
|
21
|
-
import Divider from '@material-ui/core/Divider';
|
|
22
|
-
import { useAsync as useAsync$1, useRerender, usePrevious, useKeyboardEvent } from '@react-hookz/web';
|
|
36
|
+
import Divider$1 from '@material-ui/core/Divider';
|
|
23
37
|
import yaml from 'yaml';
|
|
24
|
-
import IconButton from '@material-ui/core/IconButton';
|
|
25
|
-
import List from '@material-ui/core/List';
|
|
38
|
+
import IconButton$1 from '@material-ui/core/IconButton';
|
|
39
|
+
import List$1 from '@material-ui/core/List';
|
|
26
40
|
import ListItem from '@material-ui/core/ListItem';
|
|
27
|
-
import ListItemIcon from '@material-ui/core/ListItemIcon';
|
|
41
|
+
import ListItemIcon$1 from '@material-ui/core/ListItemIcon';
|
|
28
42
|
import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction';
|
|
29
|
-
import ListItemText from '@material-ui/core/ListItemText';
|
|
43
|
+
import ListItemText$1 from '@material-ui/core/ListItemText';
|
|
30
44
|
import Cancel from '@material-ui/icons/Cancel';
|
|
31
45
|
import Check from '@material-ui/icons/Check';
|
|
32
46
|
import DeleteIcon from '@material-ui/icons/Delete';
|
|
33
47
|
import DownloadIcon from '@material-ui/icons/GetApp';
|
|
34
|
-
import { StreamLanguage } from '@codemirror/language';
|
|
35
|
-
import { yaml as yaml$1 } from '@codemirror/legacy-modes/mode/yaml';
|
|
36
48
|
import Box$1 from '@material-ui/core/Box';
|
|
37
49
|
import Tab from '@material-ui/core/Tab';
|
|
38
50
|
import Tabs from '@material-ui/core/Tabs';
|
|
39
|
-
import CodeMirror from '@uiw/react-codemirror';
|
|
40
|
-
import { a as TaskStatusStepper, b as TaskPageLinks } from './TaskPage-d1a669e0.esm.js';
|
|
41
|
-
import CloseIcon from '@material-ui/icons/Close';
|
|
42
|
-
import RefreshIcon from '@material-ui/icons/Refresh';
|
|
43
|
-
import SaveIcon from '@material-ui/icons/Save';
|
|
44
51
|
import TreeView from '@material-ui/lab/TreeView';
|
|
45
52
|
import ChevronRightIcon from '@material-ui/icons/ChevronRight';
|
|
46
53
|
import TreeItem from '@material-ui/lab/TreeItem';
|
|
47
|
-
import
|
|
48
|
-
import
|
|
49
|
-
import
|
|
50
|
-
import
|
|
51
|
-
import
|
|
52
|
-
import
|
|
53
|
-
import
|
|
54
|
-
import {
|
|
54
|
+
import LanguageIcon from '@material-ui/icons/Language';
|
|
55
|
+
import Grid$1 from '@material-ui/core/Grid';
|
|
56
|
+
import Step from '@material-ui/core/Step';
|
|
57
|
+
import StepLabel from '@material-ui/core/StepLabel';
|
|
58
|
+
import Stepper from '@material-ui/core/Stepper';
|
|
59
|
+
import FiberManualRecordIcon from '@material-ui/icons/FiberManualRecord';
|
|
60
|
+
import qs from 'qs';
|
|
61
|
+
import { useNavigate } from 'react-router-dom';
|
|
62
|
+
import useInterval from 'react-use/lib/useInterval';
|
|
63
|
+
|
|
64
|
+
const TaskErrors = ({ error }) => {
|
|
65
|
+
const id = useRef("");
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
id.current = String(Math.random());
|
|
68
|
+
}, [error]);
|
|
69
|
+
return error ? /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(
|
|
70
|
+
DismissableBanner,
|
|
71
|
+
{
|
|
72
|
+
id: id.current,
|
|
73
|
+
variant: "warning",
|
|
74
|
+
message: error.message
|
|
75
|
+
}
|
|
76
|
+
)) : null;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const useStyles$b = makeStyles({
|
|
80
|
+
svgIcon: {
|
|
81
|
+
display: "inline-block",
|
|
82
|
+
"& svg": {
|
|
83
|
+
display: "inline-block",
|
|
84
|
+
fontSize: "inherit",
|
|
85
|
+
verticalAlign: "baseline"
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
const IconLink = (props) => {
|
|
90
|
+
const { href, text, Icon, ...linkProps } = props;
|
|
91
|
+
const classes = useStyles$b();
|
|
92
|
+
return /* @__PURE__ */ React.createElement(Grid, { container: true, direction: "row", spacing: 1 }, /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(Typography, { component: "div", className: classes.svgIcon }, Icon ? /* @__PURE__ */ React.createElement(Icon, null) : /* @__PURE__ */ React.createElement(LanguageIcon, null))), /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(Link, { to: href, ...linkProps }, text || href)));
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const TaskPageLinks = ({ output }) => {
|
|
96
|
+
const { links = [] } = output;
|
|
97
|
+
const app = useApp();
|
|
98
|
+
const entityRoute = useRouteRef(entityRouteRef);
|
|
99
|
+
const iconResolver = (key) => {
|
|
100
|
+
var _a;
|
|
101
|
+
return key ? (_a = app.getSystemIcon(key)) != null ? _a : LanguageIcon : LanguageIcon;
|
|
102
|
+
};
|
|
103
|
+
return /* @__PURE__ */ React.createElement(Box, { px: 3, pb: 3 }, links.filter(({ url, entityRef }) => url || entityRef).map(({ url, entityRef, title, icon }) => {
|
|
104
|
+
if (entityRef) {
|
|
105
|
+
const entityName = parseEntityRef(entityRef, {
|
|
106
|
+
defaultKind: "<unknown>",
|
|
107
|
+
defaultNamespace: "<unknown>"
|
|
108
|
+
});
|
|
109
|
+
const target = entityRoute(entityName);
|
|
110
|
+
return { title, icon, url: target };
|
|
111
|
+
}
|
|
112
|
+
return { title, icon, url };
|
|
113
|
+
}).map(({ url, title, icon }, i) => /* @__PURE__ */ React.createElement(
|
|
114
|
+
IconLink,
|
|
115
|
+
{
|
|
116
|
+
key: `output-link-${i}`,
|
|
117
|
+
href: url,
|
|
118
|
+
text: title != null ? title : url,
|
|
119
|
+
Icon: iconResolver(icon),
|
|
120
|
+
target: "_blank"
|
|
121
|
+
}
|
|
122
|
+
)));
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const useStyles$a = makeStyles$1(
|
|
126
|
+
(theme) => createStyles({
|
|
127
|
+
root: {
|
|
128
|
+
width: "100%"
|
|
129
|
+
},
|
|
130
|
+
button: {
|
|
131
|
+
marginBottom: theme.spacing(2),
|
|
132
|
+
marginLeft: theme.spacing(2)
|
|
133
|
+
},
|
|
134
|
+
actionsContainer: {
|
|
135
|
+
marginBottom: theme.spacing(2)
|
|
136
|
+
},
|
|
137
|
+
resetContainer: {
|
|
138
|
+
padding: theme.spacing(3)
|
|
139
|
+
},
|
|
140
|
+
labelWrapper: {
|
|
141
|
+
display: "flex",
|
|
142
|
+
flex: 1,
|
|
143
|
+
flexDirection: "row",
|
|
144
|
+
justifyContent: "space-between"
|
|
145
|
+
},
|
|
146
|
+
stepWrapper: {
|
|
147
|
+
width: "100%"
|
|
148
|
+
}
|
|
149
|
+
})
|
|
150
|
+
);
|
|
151
|
+
const StepTimeTicker = ({ step }) => {
|
|
152
|
+
const [time, setTime] = useState("");
|
|
153
|
+
useInterval(() => {
|
|
154
|
+
if (!step.startedAt) {
|
|
155
|
+
setTime("");
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
const end = step.endedAt ? DateTime.fromISO(step.endedAt) : DateTime.local();
|
|
159
|
+
const startedAt = DateTime.fromISO(step.startedAt);
|
|
160
|
+
const formatted = Interval.fromDateTimes(startedAt, end).toDuration().valueOf();
|
|
161
|
+
setTime(humanizeDuration(formatted, { round: true }));
|
|
162
|
+
}, 1e3);
|
|
163
|
+
return /* @__PURE__ */ React.createElement(Typography$1, { variant: "caption" }, time);
|
|
164
|
+
};
|
|
165
|
+
const useStepIconStyles = makeStyles$1(
|
|
166
|
+
(theme) => createStyles({
|
|
167
|
+
root: {
|
|
168
|
+
color: theme.palette.text.disabled,
|
|
169
|
+
display: "flex",
|
|
170
|
+
height: 22,
|
|
171
|
+
alignItems: "center"
|
|
172
|
+
},
|
|
173
|
+
completed: {
|
|
174
|
+
color: theme.palette.status.ok
|
|
175
|
+
},
|
|
176
|
+
error: {
|
|
177
|
+
color: theme.palette.status.error
|
|
178
|
+
}
|
|
179
|
+
})
|
|
180
|
+
);
|
|
181
|
+
function TaskStepIconComponent(props) {
|
|
182
|
+
const classes = useStepIconStyles();
|
|
183
|
+
const { active, completed, error } = props;
|
|
184
|
+
const getMiddle = () => {
|
|
185
|
+
if (active) {
|
|
186
|
+
return /* @__PURE__ */ React.createElement(CircularProgress, { size: "24px" });
|
|
187
|
+
}
|
|
188
|
+
if (completed) {
|
|
189
|
+
return /* @__PURE__ */ React.createElement(Check, null);
|
|
190
|
+
}
|
|
191
|
+
if (error) {
|
|
192
|
+
return /* @__PURE__ */ React.createElement(Cancel, null);
|
|
193
|
+
}
|
|
194
|
+
return /* @__PURE__ */ React.createElement(FiberManualRecordIcon, null);
|
|
195
|
+
};
|
|
196
|
+
return /* @__PURE__ */ React.createElement(
|
|
197
|
+
"div",
|
|
198
|
+
{
|
|
199
|
+
className: classNames(classes.root, {
|
|
200
|
+
[classes.completed]: completed,
|
|
201
|
+
[classes.error]: error
|
|
202
|
+
})
|
|
203
|
+
},
|
|
204
|
+
getMiddle()
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
const TaskStatusStepper = memo(
|
|
208
|
+
(props) => {
|
|
209
|
+
const { steps, currentStepId, onUserStepChange } = props;
|
|
210
|
+
const classes = useStyles$a(props);
|
|
211
|
+
return /* @__PURE__ */ React.createElement("div", { className: classes.root }, /* @__PURE__ */ React.createElement(
|
|
212
|
+
Stepper,
|
|
213
|
+
{
|
|
214
|
+
activeStep: steps.findIndex((s) => s.id === currentStepId),
|
|
215
|
+
orientation: "vertical",
|
|
216
|
+
nonLinear: true
|
|
217
|
+
},
|
|
218
|
+
steps.map((step, index) => {
|
|
219
|
+
const isCancelled = step.status === "cancelled";
|
|
220
|
+
const isActive = step.status === "processing";
|
|
221
|
+
const isCompleted = step.status === "completed";
|
|
222
|
+
const isFailed = step.status === "failed";
|
|
223
|
+
const isSkipped = step.status === "skipped";
|
|
224
|
+
return /* @__PURE__ */ React.createElement(Step, { key: String(index), expanded: true }, /* @__PURE__ */ React.createElement(StepButton, { onClick: () => onUserStepChange(step.id) }, /* @__PURE__ */ React.createElement(
|
|
225
|
+
StepLabel,
|
|
226
|
+
{
|
|
227
|
+
StepIconProps: {
|
|
228
|
+
completed: isCompleted,
|
|
229
|
+
error: isFailed || isCancelled,
|
|
230
|
+
active: isActive
|
|
231
|
+
},
|
|
232
|
+
StepIconComponent: TaskStepIconComponent,
|
|
233
|
+
className: classes.stepWrapper
|
|
234
|
+
},
|
|
235
|
+
/* @__PURE__ */ React.createElement("div", { className: classes.labelWrapper }, /* @__PURE__ */ React.createElement(Typography$1, { variant: "subtitle2" }, step.name), isSkipped ? /* @__PURE__ */ React.createElement(Typography$1, { variant: "caption" }, "Skipped") : /* @__PURE__ */ React.createElement(StepTimeTicker, { step }))
|
|
236
|
+
)));
|
|
237
|
+
})
|
|
238
|
+
));
|
|
239
|
+
}
|
|
240
|
+
);
|
|
241
|
+
const hasLinks = ({ links = [] }) => links.length > 0;
|
|
242
|
+
const TaskPage = (props) => {
|
|
243
|
+
const { loadingText } = props;
|
|
244
|
+
const classes = useStyles$a();
|
|
245
|
+
const navigate = useNavigate();
|
|
246
|
+
const rootPath = useRouteRef(rootRouteRef);
|
|
247
|
+
const scaffolderApi = useApi(scaffolderApiRef);
|
|
248
|
+
const templateRoute = useRouteRef(selectedTemplateRouteRef);
|
|
249
|
+
const [userSelectedStepId, setUserSelectedStepId] = useState(void 0);
|
|
250
|
+
const [clickedToCancel, setClickedToCancel] = useState(false);
|
|
251
|
+
const [lastActiveStepId, setLastActiveStepId] = useState(
|
|
252
|
+
void 0
|
|
253
|
+
);
|
|
254
|
+
const { taskId } = useRouteRefParams(scaffolderTaskRouteRef);
|
|
255
|
+
const taskStream = useTaskEventStream(taskId);
|
|
256
|
+
const completed = taskStream.completed;
|
|
257
|
+
const taskCancelled = taskStream.cancelled;
|
|
258
|
+
const steps = useMemo(
|
|
259
|
+
() => {
|
|
260
|
+
var _a, _b;
|
|
261
|
+
return (_b = (_a = taskStream.task) == null ? void 0 : _a.spec.steps.map((step) => {
|
|
262
|
+
var _a2;
|
|
263
|
+
return {
|
|
264
|
+
...step,
|
|
265
|
+
...(_a2 = taskStream == null ? void 0 : taskStream.steps) == null ? void 0 : _a2[step.id]
|
|
266
|
+
};
|
|
267
|
+
})) != null ? _b : [];
|
|
268
|
+
},
|
|
269
|
+
[taskStream]
|
|
270
|
+
);
|
|
271
|
+
useEffect(() => {
|
|
272
|
+
var _a;
|
|
273
|
+
const mostRecentFailedOrActiveStep = steps.find(
|
|
274
|
+
(step) => ["failed", "processing"].includes(step.status)
|
|
275
|
+
);
|
|
276
|
+
if (completed && !mostRecentFailedOrActiveStep) {
|
|
277
|
+
setLastActiveStepId((_a = steps[steps.length - 1]) == null ? void 0 : _a.id);
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
setLastActiveStepId(mostRecentFailedOrActiveStep == null ? void 0 : mostRecentFailedOrActiveStep.id);
|
|
281
|
+
}, [steps, completed]);
|
|
282
|
+
const currentStepId = userSelectedStepId != null ? userSelectedStepId : lastActiveStepId;
|
|
283
|
+
const logAsString = useMemo(() => {
|
|
284
|
+
if (!currentStepId) {
|
|
285
|
+
return loadingText ? loadingText : "Loading...";
|
|
286
|
+
}
|
|
287
|
+
const log = taskStream.stepLogs[currentStepId];
|
|
288
|
+
if (!(log == null ? void 0 : log.length)) {
|
|
289
|
+
return "Waiting for logs...";
|
|
290
|
+
}
|
|
291
|
+
return log.join("\n");
|
|
292
|
+
}, [taskStream.stepLogs, currentStepId, loadingText]);
|
|
293
|
+
const taskNotFound = taskStream.completed && !taskStream.loading && !taskStream.task;
|
|
294
|
+
const { output } = taskStream;
|
|
295
|
+
const handleStartOver = () => {
|
|
296
|
+
var _a, _b, _c;
|
|
297
|
+
if (!taskStream.task || !((_b = (_a = taskStream.task) == null ? void 0 : _a.spec.templateInfo) == null ? void 0 : _b.entityRef)) {
|
|
298
|
+
navigate(rootPath());
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
const formData = taskStream.task.spec.parameters;
|
|
302
|
+
const { name, namespace } = parseEntityRef(
|
|
303
|
+
(_c = taskStream.task.spec.templateInfo) == null ? void 0 : _c.entityRef
|
|
304
|
+
);
|
|
305
|
+
navigate(
|
|
306
|
+
`${templateRoute({ templateName: name, namespace })}?${qs.stringify({
|
|
307
|
+
formData: JSON.stringify(formData)
|
|
308
|
+
})}`
|
|
309
|
+
);
|
|
310
|
+
};
|
|
311
|
+
const handleCancel = async () => {
|
|
312
|
+
setClickedToCancel(true);
|
|
313
|
+
await scaffolderApi.cancelTask(taskId);
|
|
314
|
+
};
|
|
315
|
+
return /* @__PURE__ */ React.createElement(Page, { themeId: "home" }, /* @__PURE__ */ React.createElement(
|
|
316
|
+
Header,
|
|
317
|
+
{
|
|
318
|
+
pageTitleOverride: `Task ${taskId}`,
|
|
319
|
+
title: "Task Activity",
|
|
320
|
+
subtitle: `Activity for task: ${taskId}`
|
|
321
|
+
}
|
|
322
|
+
), /* @__PURE__ */ React.createElement(Content, null, taskNotFound ? /* @__PURE__ */ React.createElement(
|
|
323
|
+
ErrorPage,
|
|
324
|
+
{
|
|
325
|
+
status: "404",
|
|
326
|
+
statusMessage: "Task not found",
|
|
327
|
+
additionalInfo: "No task found with this ID"
|
|
328
|
+
}
|
|
329
|
+
) : /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement(Grid$1, { container: true }, /* @__PURE__ */ React.createElement(Grid$1, { item: true, xs: 3 }, /* @__PURE__ */ React.createElement(Paper, null, /* @__PURE__ */ React.createElement(
|
|
330
|
+
TaskStatusStepper,
|
|
331
|
+
{
|
|
332
|
+
steps,
|
|
333
|
+
currentStepId,
|
|
334
|
+
onUserStepChange: setUserSelectedStepId
|
|
335
|
+
}
|
|
336
|
+
), output && hasLinks(output) && /* @__PURE__ */ React.createElement(TaskPageLinks, { output }), /* @__PURE__ */ React.createElement(
|
|
337
|
+
Button,
|
|
338
|
+
{
|
|
339
|
+
className: classes.button,
|
|
340
|
+
onClick: handleStartOver,
|
|
341
|
+
disabled: !completed,
|
|
342
|
+
variant: "contained",
|
|
343
|
+
color: "primary"
|
|
344
|
+
},
|
|
345
|
+
"Start Over"
|
|
346
|
+
), /* @__PURE__ */ React.createElement(
|
|
347
|
+
Button,
|
|
348
|
+
{
|
|
349
|
+
className: classes.button,
|
|
350
|
+
onClick: handleCancel,
|
|
351
|
+
disabled: completed || taskCancelled || clickedToCancel,
|
|
352
|
+
variant: "outlined",
|
|
353
|
+
color: "secondary"
|
|
354
|
+
},
|
|
355
|
+
(taskCancelled || clickedToCancel) && !completed ? "Cancelling..." : "Cancel"
|
|
356
|
+
))), /* @__PURE__ */ React.createElement(Grid$1, { item: true, xs: 9 }, !currentStepId && /* @__PURE__ */ React.createElement(Progress, null), /* @__PURE__ */ React.createElement("div", { style: { height: "80vh" } }, /* @__PURE__ */ React.createElement(TaskErrors, { error: taskStream.error }), /* @__PURE__ */ React.createElement(LogViewer, { text: logAsString })))))));
|
|
357
|
+
};
|
|
55
358
|
|
|
56
359
|
const useStyles$9 = makeStyles((theme) => ({
|
|
57
360
|
code: {
|
|
@@ -197,168 +500,508 @@ const ActionsPage = () => {
|
|
|
197
500
|
), /* @__PURE__ */ React.createElement(Content, null, items));
|
|
198
501
|
};
|
|
199
502
|
|
|
200
|
-
const
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
503
|
+
const DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS = [
|
|
504
|
+
{
|
|
505
|
+
component: EntityPicker,
|
|
506
|
+
name: "EntityPicker",
|
|
507
|
+
schema: EntityPickerSchema
|
|
508
|
+
},
|
|
509
|
+
{
|
|
510
|
+
component: EntityNamePicker,
|
|
511
|
+
name: "EntityNamePicker",
|
|
512
|
+
validation: entityNamePickerValidation,
|
|
513
|
+
schema: EntityNamePickerSchema
|
|
514
|
+
},
|
|
515
|
+
{
|
|
516
|
+
component: EntityTagsPicker,
|
|
517
|
+
name: "EntityTagsPicker",
|
|
518
|
+
schema: EntityTagsPickerSchema
|
|
519
|
+
},
|
|
520
|
+
{
|
|
521
|
+
component: RepoUrlPicker,
|
|
522
|
+
name: "RepoUrlPicker",
|
|
523
|
+
validation: repoPickerValidation,
|
|
524
|
+
schema: RepoUrlPickerSchema
|
|
525
|
+
},
|
|
526
|
+
{
|
|
527
|
+
component: OwnerPicker,
|
|
528
|
+
name: "OwnerPicker",
|
|
529
|
+
schema: OwnerPickerSchema
|
|
530
|
+
},
|
|
531
|
+
{
|
|
532
|
+
component: OwnedEntityPicker,
|
|
533
|
+
name: "OwnedEntityPicker",
|
|
534
|
+
schema: OwnedEntityPickerSchema
|
|
535
|
+
},
|
|
536
|
+
{
|
|
537
|
+
component: MyGroupsPicker,
|
|
538
|
+
name: "MyGroupsPicker",
|
|
539
|
+
schema: MyGroupsPickerSchema
|
|
218
540
|
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
541
|
+
];
|
|
542
|
+
|
|
543
|
+
const useStyles$8 = makeStyles(
|
|
544
|
+
(theme) => ({
|
|
545
|
+
root: {
|
|
546
|
+
backgroundColor: "rgba(0, 0, 0, .11)",
|
|
547
|
+
boxShadow: "none",
|
|
548
|
+
margin: theme.spacing(1, 0, 1, 0)
|
|
549
|
+
},
|
|
550
|
+
title: {
|
|
551
|
+
margin: theme.spacing(1, 0, 0, 1),
|
|
552
|
+
textTransform: "uppercase",
|
|
553
|
+
fontSize: 12,
|
|
554
|
+
fontWeight: "bold"
|
|
555
|
+
},
|
|
556
|
+
listIcon: {
|
|
557
|
+
minWidth: 30,
|
|
558
|
+
color: theme.palette.text.primary
|
|
559
|
+
},
|
|
560
|
+
menuItem: {
|
|
561
|
+
minHeight: theme.spacing(6)
|
|
562
|
+
},
|
|
563
|
+
groupWrapper: {
|
|
564
|
+
margin: theme.spacing(1, 1, 2, 1)
|
|
223
565
|
}
|
|
224
|
-
|
|
566
|
+
}),
|
|
567
|
+
{
|
|
568
|
+
name: "ScaffolderReactOwnerListPicker"
|
|
225
569
|
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
570
|
+
);
|
|
571
|
+
function getFilterGroups() {
|
|
572
|
+
return [
|
|
573
|
+
{
|
|
574
|
+
name: "Task Owner",
|
|
575
|
+
items: [
|
|
576
|
+
{
|
|
577
|
+
id: "owned",
|
|
578
|
+
label: "Owned",
|
|
579
|
+
icon: SettingsIcon
|
|
580
|
+
},
|
|
581
|
+
{
|
|
582
|
+
id: "all",
|
|
583
|
+
label: "All",
|
|
584
|
+
icon: AllIcon
|
|
233
585
|
}
|
|
234
|
-
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
class WebFileSystemAccess {
|
|
240
|
-
static isSupported() {
|
|
241
|
-
return Boolean(showDirectoryPicker);
|
|
242
|
-
}
|
|
243
|
-
static async requestDirectoryAccess() {
|
|
244
|
-
if (!showDirectoryPicker) {
|
|
245
|
-
throw new Error("File system access is not supported");
|
|
586
|
+
]
|
|
246
587
|
}
|
|
247
|
-
|
|
248
|
-
return new WebDirectoryAccess(handle);
|
|
249
|
-
}
|
|
250
|
-
constructor() {
|
|
251
|
-
}
|
|
588
|
+
];
|
|
252
589
|
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
590
|
+
const OwnerListPicker = (props) => {
|
|
591
|
+
const { filter, onSelectOwner } = props;
|
|
592
|
+
const classes = useStyles$8();
|
|
593
|
+
const filterGroups = getFilterGroups();
|
|
594
|
+
return /* @__PURE__ */ React.createElement(Card, { className: classes.root }, filterGroups.map((group) => /* @__PURE__ */ React.createElement(Fragment, { key: group.name }, /* @__PURE__ */ React.createElement(
|
|
595
|
+
Typography,
|
|
596
|
+
{
|
|
597
|
+
variant: "subtitle2",
|
|
598
|
+
component: "span",
|
|
599
|
+
className: classes.title
|
|
600
|
+
},
|
|
601
|
+
group.name
|
|
602
|
+
), /* @__PURE__ */ React.createElement(Card, { className: classes.groupWrapper }, /* @__PURE__ */ React.createElement(List, { disablePadding: true, dense: true, role: "menu" }, group.items.map((item) => /* @__PURE__ */ React.createElement(
|
|
603
|
+
MenuItem,
|
|
604
|
+
{
|
|
605
|
+
key: item.id,
|
|
606
|
+
button: true,
|
|
607
|
+
divider: true,
|
|
608
|
+
ContainerProps: { role: "menuitem" },
|
|
609
|
+
onClick: () => onSelectOwner(item.id),
|
|
610
|
+
selected: item.id === filter,
|
|
611
|
+
className: classes.menuItem,
|
|
612
|
+
"data-testid": `owner-picker-${item.id}`
|
|
613
|
+
},
|
|
614
|
+
item.icon && /* @__PURE__ */ React.createElement(ListItemIcon, { className: classes.listIcon }, /* @__PURE__ */ React.createElement(item.icon, { fontSize: "small" })),
|
|
615
|
+
/* @__PURE__ */ React.createElement(ListItemText, null, /* @__PURE__ */ React.createElement(Typography, { variant: "body1" }, item.label))
|
|
616
|
+
)))))));
|
|
272
617
|
};
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
618
|
+
|
|
619
|
+
const CreatedAtColumn = ({ createdAt }) => {
|
|
620
|
+
const createdAtTime = DateTime.fromISO(createdAt);
|
|
621
|
+
const formatted = Interval.fromDateTimes(createdAtTime, DateTime.local()).toDuration().valueOf();
|
|
622
|
+
return /* @__PURE__ */ React.createElement(Typography$1, { paragraph: true }, humanizeDuration(formatted, { round: true }), " ago");
|
|
277
623
|
};
|
|
278
|
-
|
|
279
|
-
const
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
__privateSet(this, _signalUpdate, signalUpdate);
|
|
289
|
-
}
|
|
290
|
-
get path() {
|
|
291
|
-
return __privateGet(this, _access).path;
|
|
624
|
+
|
|
625
|
+
const OwnerEntityColumn = ({ entityRef }) => {
|
|
626
|
+
var _a, _b, _c;
|
|
627
|
+
const catalogApi = useApi(catalogApiRef);
|
|
628
|
+
const { value, loading, error } = useAsync(
|
|
629
|
+
() => catalogApi.getEntityByRef(entityRef || ""),
|
|
630
|
+
[catalogApi, entityRef]
|
|
631
|
+
);
|
|
632
|
+
if (!entityRef) {
|
|
633
|
+
return /* @__PURE__ */ React.createElement(Typography$1, { paragraph: true }, "Unknown");
|
|
292
634
|
}
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
return (_a = __privateGet(this, _content)) != null ? _a : MAX_SIZE_MESSAGE;
|
|
635
|
+
if (loading || error) {
|
|
636
|
+
return null;
|
|
296
637
|
}
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
638
|
+
return /* @__PURE__ */ React.createElement(
|
|
639
|
+
EntityRefLink,
|
|
640
|
+
{
|
|
641
|
+
entityRef: parseEntityRef(entityRef),
|
|
642
|
+
title: (_c = (_b = (_a = value == null ? void 0 : value.spec) == null ? void 0 : _a.profile) == null ? void 0 : _b.displayName) != null ? _c : value == null ? void 0 : value.metadata.name
|
|
300
643
|
}
|
|
301
|
-
|
|
302
|
-
|
|
644
|
+
);
|
|
645
|
+
};
|
|
646
|
+
|
|
647
|
+
const TaskStatusColumn = ({ status }) => {
|
|
648
|
+
switch (status) {
|
|
649
|
+
case "processing":
|
|
650
|
+
return /* @__PURE__ */ React.createElement(StatusPending, null, status);
|
|
651
|
+
case "completed":
|
|
652
|
+
return /* @__PURE__ */ React.createElement(StatusOK, null, status);
|
|
653
|
+
case "error":
|
|
654
|
+
default:
|
|
655
|
+
return /* @__PURE__ */ React.createElement(StatusError, null, status);
|
|
303
656
|
}
|
|
304
|
-
|
|
305
|
-
|
|
657
|
+
};
|
|
658
|
+
|
|
659
|
+
const TemplateTitleColumn = ({ entityRef }) => {
|
|
660
|
+
const scaffolder = useApi(scaffolderApiRef);
|
|
661
|
+
const { value, loading, error } = useAsync(
|
|
662
|
+
() => scaffolder.getTemplateParameterSchema(entityRef || ""),
|
|
663
|
+
[scaffolder, entityRef]
|
|
664
|
+
);
|
|
665
|
+
if (loading || error || !entityRef) {
|
|
666
|
+
return null;
|
|
306
667
|
}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
668
|
+
return /* @__PURE__ */ React.createElement(EntityRefLink, { entityRef: parseEntityRef(entityRef), title: value == null ? void 0 : value.title });
|
|
669
|
+
};
|
|
670
|
+
|
|
671
|
+
const ListTaskPageContent = (props) => {
|
|
672
|
+
var _a;
|
|
673
|
+
const { initiallySelectedFilter = "owned" } = props;
|
|
674
|
+
const scaffolderApi = useApi(scaffolderApiRef);
|
|
675
|
+
const rootLink = useRouteRef(rootRouteRef);
|
|
676
|
+
const [ownerFilter, setOwnerFilter] = useState(initiallySelectedFilter);
|
|
677
|
+
const { value, loading, error } = useAsync(() => {
|
|
678
|
+
var _a2;
|
|
679
|
+
if (scaffolderApi.listTasks) {
|
|
680
|
+
return (_a2 = scaffolderApi.listTasks) == null ? void 0 : _a2.call(scaffolderApi, { filterByOwnership: ownerFilter });
|
|
312
681
|
}
|
|
682
|
+
console.warn(
|
|
683
|
+
"listTasks is not implemented in the scaffolderApi, please make sure to implement this method."
|
|
684
|
+
);
|
|
685
|
+
return Promise.resolve({ tasks: [] });
|
|
686
|
+
}, [scaffolderApi, ownerFilter]);
|
|
687
|
+
if (loading) {
|
|
688
|
+
return /* @__PURE__ */ React.createElement(Progress, null);
|
|
313
689
|
}
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
690
|
+
if (error) {
|
|
691
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(ErrorPanel, { error }), /* @__PURE__ */ React.createElement(
|
|
692
|
+
EmptyState,
|
|
693
|
+
{
|
|
694
|
+
missing: "info",
|
|
695
|
+
title: "No information to display",
|
|
696
|
+
description: "There is no Tasks or there was an issue communicating with backend."
|
|
321
697
|
}
|
|
322
|
-
|
|
698
|
+
));
|
|
699
|
+
}
|
|
700
|
+
return /* @__PURE__ */ React.createElement(CatalogFilterLayout, null, /* @__PURE__ */ React.createElement(CatalogFilterLayout.Filters, null, /* @__PURE__ */ React.createElement(
|
|
701
|
+
OwnerListPicker,
|
|
702
|
+
{
|
|
703
|
+
filter: ownerFilter,
|
|
704
|
+
onSelectOwner: (id) => setOwnerFilter(id)
|
|
323
705
|
}
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
706
|
+
)), /* @__PURE__ */ React.createElement(CatalogFilterLayout.Content, null, /* @__PURE__ */ React.createElement(
|
|
707
|
+
Table$1,
|
|
708
|
+
{
|
|
709
|
+
data: (_a = value == null ? void 0 : value.tasks) != null ? _a : [],
|
|
710
|
+
title: "Tasks",
|
|
711
|
+
columns: [
|
|
712
|
+
{
|
|
713
|
+
title: "Task ID",
|
|
714
|
+
field: "id",
|
|
715
|
+
render: (row) => /* @__PURE__ */ React.createElement(Link, { to: `${rootLink()}/tasks/${row.id}` }, row.id)
|
|
716
|
+
},
|
|
717
|
+
{
|
|
718
|
+
title: "Template",
|
|
719
|
+
render: (row) => {
|
|
720
|
+
var _a2;
|
|
721
|
+
return /* @__PURE__ */ React.createElement(
|
|
722
|
+
TemplateTitleColumn,
|
|
723
|
+
{
|
|
724
|
+
entityRef: (_a2 = row.spec.templateInfo) == null ? void 0 : _a2.entityRef
|
|
725
|
+
}
|
|
726
|
+
);
|
|
727
|
+
}
|
|
728
|
+
},
|
|
729
|
+
{
|
|
730
|
+
title: "Created",
|
|
731
|
+
field: "createdAt",
|
|
732
|
+
render: (row) => /* @__PURE__ */ React.createElement(CreatedAtColumn, { createdAt: row.createdAt })
|
|
733
|
+
},
|
|
734
|
+
{
|
|
735
|
+
title: "Owner",
|
|
736
|
+
field: "createdBy",
|
|
737
|
+
render: (row) => {
|
|
738
|
+
var _a2, _b;
|
|
739
|
+
return /* @__PURE__ */ React.createElement(OwnerEntityColumn, { entityRef: (_b = (_a2 = row.spec) == null ? void 0 : _a2.user) == null ? void 0 : _b.ref });
|
|
740
|
+
}
|
|
741
|
+
},
|
|
742
|
+
{
|
|
743
|
+
title: "Status",
|
|
744
|
+
field: "status",
|
|
745
|
+
render: (row) => /* @__PURE__ */ React.createElement(TaskStatusColumn, { status: row.status })
|
|
746
|
+
}
|
|
747
|
+
]
|
|
748
|
+
}
|
|
749
|
+
)));
|
|
750
|
+
};
|
|
751
|
+
const ListTasksPage = (props) => {
|
|
752
|
+
return /* @__PURE__ */ React.createElement(Page, { themeId: "home" }, /* @__PURE__ */ React.createElement(
|
|
753
|
+
Header,
|
|
754
|
+
{
|
|
755
|
+
pageTitleOverride: "Templates Tasks",
|
|
756
|
+
title: /* @__PURE__ */ React.createElement(React.Fragment, null, "List template tasks ", /* @__PURE__ */ React.createElement(Lifecycle, { shorthand: true, alpha: true })),
|
|
757
|
+
subtitle: "All tasks that have been started"
|
|
329
758
|
}
|
|
759
|
+
), /* @__PURE__ */ React.createElement(Content, null, /* @__PURE__ */ React.createElement(ListTaskPageContent, { ...props })));
|
|
760
|
+
};
|
|
761
|
+
|
|
762
|
+
const showDirectoryPicker = window.showDirectoryPicker;
|
|
763
|
+
class WebFileAccess {
|
|
764
|
+
constructor(path, handle) {
|
|
765
|
+
this.path = path;
|
|
766
|
+
this.handle = handle;
|
|
330
767
|
}
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
_signalUpdate = new WeakMap();
|
|
334
|
-
_content = new WeakMap();
|
|
335
|
-
_savedContent = new WeakMap();
|
|
336
|
-
class DirectoryEditorManager {
|
|
337
|
-
constructor(access) {
|
|
338
|
-
__privateAdd(this, _access2, void 0);
|
|
339
|
-
__privateAdd(this, _listeners, /* @__PURE__ */ new Set());
|
|
340
|
-
__privateAdd(this, _files, []);
|
|
341
|
-
__privateAdd(this, _selectedFile, void 0);
|
|
342
|
-
__publicField(this, "setSelectedFile", (path) => {
|
|
343
|
-
const prev = __privateGet(this, _selectedFile);
|
|
344
|
-
const next = __privateGet(this, _files).find((file) => file.path === path);
|
|
345
|
-
if (prev !== next) {
|
|
346
|
-
__privateSet(this, _selectedFile, next);
|
|
347
|
-
__privateGet(this, _signalUpdate2).call(this);
|
|
348
|
-
}
|
|
349
|
-
});
|
|
350
|
-
__privateAdd(this, _signalUpdate2, () => {
|
|
351
|
-
__privateGet(this, _listeners).forEach((listener) => listener());
|
|
352
|
-
});
|
|
353
|
-
__privateSet(this, _access2, access);
|
|
768
|
+
file() {
|
|
769
|
+
return this.handle.getFile();
|
|
354
770
|
}
|
|
355
|
-
|
|
356
|
-
|
|
771
|
+
async save(data) {
|
|
772
|
+
const writable = await this.handle.createWritable();
|
|
773
|
+
await writable.write(data);
|
|
774
|
+
await writable.close();
|
|
357
775
|
}
|
|
358
|
-
|
|
359
|
-
|
|
776
|
+
}
|
|
777
|
+
class WebDirectoryAccess {
|
|
778
|
+
constructor(handle) {
|
|
779
|
+
this.handle = handle;
|
|
360
780
|
}
|
|
361
|
-
|
|
781
|
+
async listFiles() {
|
|
782
|
+
const content = [];
|
|
783
|
+
for await (const entry of this.listDirectoryContents(this.handle)) {
|
|
784
|
+
content.push(entry);
|
|
785
|
+
}
|
|
786
|
+
return content;
|
|
787
|
+
}
|
|
788
|
+
async *listDirectoryContents(dirHandle, basePath = []) {
|
|
789
|
+
for await (const handle of dirHandle.values()) {
|
|
790
|
+
if (handle.kind === "file") {
|
|
791
|
+
yield new WebFileAccess([...basePath, handle.name].join("/"), handle);
|
|
792
|
+
} else if (handle.kind === "directory") {
|
|
793
|
+
if (handle.name === ".git") {
|
|
794
|
+
continue;
|
|
795
|
+
}
|
|
796
|
+
yield* this.listDirectoryContents(handle, [...basePath, handle.name]);
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
class WebFileSystemAccess {
|
|
802
|
+
static isSupported() {
|
|
803
|
+
return Boolean(showDirectoryPicker);
|
|
804
|
+
}
|
|
805
|
+
static async requestDirectoryAccess() {
|
|
806
|
+
if (!showDirectoryPicker) {
|
|
807
|
+
throw new Error("File system access is not supported");
|
|
808
|
+
}
|
|
809
|
+
const handle = await showDirectoryPicker();
|
|
810
|
+
return new WebDirectoryAccess(handle);
|
|
811
|
+
}
|
|
812
|
+
constructor() {
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
const useStyles$7 = makeStyles$1((theme) => ({
|
|
817
|
+
introText: {
|
|
818
|
+
textAlign: "center",
|
|
819
|
+
marginTop: theme.spacing(2)
|
|
820
|
+
},
|
|
821
|
+
card: {
|
|
822
|
+
position: "relative",
|
|
823
|
+
maxWidth: 340,
|
|
824
|
+
marginTop: theme.spacing(4),
|
|
825
|
+
margin: theme.spacing(0, 2)
|
|
826
|
+
},
|
|
827
|
+
infoIcon: {
|
|
828
|
+
position: "absolute",
|
|
829
|
+
top: theme.spacing(1),
|
|
830
|
+
right: theme.spacing(1)
|
|
831
|
+
}
|
|
832
|
+
}));
|
|
833
|
+
function TemplateEditorIntro(props) {
|
|
834
|
+
const classes = useStyles$7();
|
|
835
|
+
const supportsLoad = WebFileSystemAccess.isSupported();
|
|
836
|
+
const cardLoadLocal = /* @__PURE__ */ React.createElement(Card$1, { className: classes.card, elevation: 4 }, /* @__PURE__ */ React.createElement(
|
|
837
|
+
CardActionArea,
|
|
838
|
+
{
|
|
839
|
+
disabled: !supportsLoad,
|
|
840
|
+
onClick: () => {
|
|
841
|
+
var _a;
|
|
842
|
+
return (_a = props.onSelect) == null ? void 0 : _a.call(props, "local");
|
|
843
|
+
}
|
|
844
|
+
},
|
|
845
|
+
/* @__PURE__ */ React.createElement(CardContent, null, /* @__PURE__ */ React.createElement(
|
|
846
|
+
Typography$1,
|
|
847
|
+
{
|
|
848
|
+
variant: "h4",
|
|
849
|
+
component: "h3",
|
|
850
|
+
gutterBottom: true,
|
|
851
|
+
color: supportsLoad ? void 0 : "textSecondary",
|
|
852
|
+
style: { display: "flex", flexFlow: "row nowrap" }
|
|
853
|
+
},
|
|
854
|
+
"Load Template Directory"
|
|
855
|
+
), /* @__PURE__ */ React.createElement(
|
|
856
|
+
Typography$1,
|
|
857
|
+
{
|
|
858
|
+
variant: "body1",
|
|
859
|
+
color: supportsLoad ? void 0 : "textSecondary"
|
|
860
|
+
},
|
|
861
|
+
"Load a local template directory, allowing you to both edit and try executing your own template."
|
|
862
|
+
))
|
|
863
|
+
), !supportsLoad && /* @__PURE__ */ React.createElement("div", { className: classes.infoIcon }, /* @__PURE__ */ React.createElement(
|
|
864
|
+
Tooltip,
|
|
865
|
+
{
|
|
866
|
+
placement: "top",
|
|
867
|
+
title: "Only supported in some Chromium-based browsers"
|
|
868
|
+
},
|
|
869
|
+
/* @__PURE__ */ React.createElement(InfoOutlinedIcon, null)
|
|
870
|
+
)));
|
|
871
|
+
const cardFormEditor = /* @__PURE__ */ React.createElement(Card$1, { className: classes.card, elevation: 4 }, /* @__PURE__ */ React.createElement(CardActionArea, { onClick: () => {
|
|
872
|
+
var _a;
|
|
873
|
+
return (_a = props.onSelect) == null ? void 0 : _a.call(props, "form");
|
|
874
|
+
} }, /* @__PURE__ */ React.createElement(CardContent, null, /* @__PURE__ */ React.createElement(Typography$1, { variant: "h4", component: "h3", gutterBottom: true }, "Edit Template Form"), /* @__PURE__ */ React.createElement(Typography$1, { variant: "body1" }, "Preview and edit a template form, either using a sample template or by loading a template from the catalog."))));
|
|
875
|
+
const cardFieldExplorer = /* @__PURE__ */ React.createElement(Card$1, { className: classes.card, elevation: 4 }, /* @__PURE__ */ React.createElement(CardActionArea, { onClick: () => {
|
|
876
|
+
var _a;
|
|
877
|
+
return (_a = props.onSelect) == null ? void 0 : _a.call(props, "field-explorer");
|
|
878
|
+
} }, /* @__PURE__ */ React.createElement(CardContent, null, /* @__PURE__ */ React.createElement(Typography$1, { variant: "h4", component: "h3", gutterBottom: true }, "Custom Field Explorer"), /* @__PURE__ */ React.createElement(Typography$1, { variant: "body1" }, "View and play around with available installed custom field extensions."))));
|
|
879
|
+
return /* @__PURE__ */ React.createElement("div", { style: props.style }, /* @__PURE__ */ React.createElement(Typography$1, { variant: "h4", component: "h2", className: classes.introText }, "Get started by choosing one of the options below"), /* @__PURE__ */ React.createElement(
|
|
880
|
+
"div",
|
|
881
|
+
{
|
|
882
|
+
style: {
|
|
883
|
+
display: "flex",
|
|
884
|
+
flexFlow: "row wrap",
|
|
885
|
+
alignItems: "flex-start",
|
|
886
|
+
justifyContent: "center",
|
|
887
|
+
alignContent: "flex-start"
|
|
888
|
+
}
|
|
889
|
+
},
|
|
890
|
+
supportsLoad && cardLoadLocal,
|
|
891
|
+
cardFormEditor,
|
|
892
|
+
!supportsLoad && cardLoadLocal,
|
|
893
|
+
cardFieldExplorer
|
|
894
|
+
));
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
var __defProp = Object.defineProperty;
|
|
898
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
899
|
+
var __publicField = (obj, key, value) => {
|
|
900
|
+
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
901
|
+
return value;
|
|
902
|
+
};
|
|
903
|
+
var __accessCheck = (obj, member, msg) => {
|
|
904
|
+
if (!member.has(obj))
|
|
905
|
+
throw TypeError("Cannot " + msg);
|
|
906
|
+
};
|
|
907
|
+
var __privateGet = (obj, member, getter) => {
|
|
908
|
+
__accessCheck(obj, member, "read from private field");
|
|
909
|
+
return getter ? getter.call(obj) : member.get(obj);
|
|
910
|
+
};
|
|
911
|
+
var __privateAdd = (obj, member, value) => {
|
|
912
|
+
if (member.has(obj))
|
|
913
|
+
throw TypeError("Cannot add the same private member more than once");
|
|
914
|
+
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
915
|
+
};
|
|
916
|
+
var __privateSet = (obj, member, value, setter) => {
|
|
917
|
+
__accessCheck(obj, member, "write to private field");
|
|
918
|
+
setter ? setter.call(obj, value) : member.set(obj, value);
|
|
919
|
+
return value;
|
|
920
|
+
};
|
|
921
|
+
var _access, _signalUpdate, _content, _savedContent, _access2, _listeners, _files, _selectedFile, _signalUpdate2;
|
|
922
|
+
const MAX_SIZE = 1024 * 1024;
|
|
923
|
+
const MAX_SIZE_MESSAGE = "This file is too large to be displayed";
|
|
924
|
+
class DirectoryEditorFileManager {
|
|
925
|
+
constructor(access, signalUpdate) {
|
|
926
|
+
__privateAdd(this, _access, void 0);
|
|
927
|
+
__privateAdd(this, _signalUpdate, void 0);
|
|
928
|
+
__privateAdd(this, _content, void 0);
|
|
929
|
+
__privateAdd(this, _savedContent, void 0);
|
|
930
|
+
__privateSet(this, _access, access);
|
|
931
|
+
__privateSet(this, _signalUpdate, signalUpdate);
|
|
932
|
+
}
|
|
933
|
+
get path() {
|
|
934
|
+
return __privateGet(this, _access).path;
|
|
935
|
+
}
|
|
936
|
+
get content() {
|
|
937
|
+
var _a;
|
|
938
|
+
return (_a = __privateGet(this, _content)) != null ? _a : MAX_SIZE_MESSAGE;
|
|
939
|
+
}
|
|
940
|
+
updateContent(content) {
|
|
941
|
+
if (__privateGet(this, _content) === void 0) {
|
|
942
|
+
return;
|
|
943
|
+
}
|
|
944
|
+
__privateSet(this, _content, content);
|
|
945
|
+
__privateGet(this, _signalUpdate).call(this);
|
|
946
|
+
}
|
|
947
|
+
get dirty() {
|
|
948
|
+
return __privateGet(this, _content) !== __privateGet(this, _savedContent);
|
|
949
|
+
}
|
|
950
|
+
async save() {
|
|
951
|
+
if (__privateGet(this, _content) !== void 0) {
|
|
952
|
+
await __privateGet(this, _access).save(__privateGet(this, _content));
|
|
953
|
+
__privateSet(this, _savedContent, __privateGet(this, _content));
|
|
954
|
+
__privateGet(this, _signalUpdate).call(this);
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
async reload() {
|
|
958
|
+
const file = await __privateGet(this, _access).file();
|
|
959
|
+
if (file.size > MAX_SIZE) {
|
|
960
|
+
if (__privateGet(this, _content) !== void 0) {
|
|
961
|
+
__privateSet(this, _content, void 0);
|
|
962
|
+
__privateSet(this, _savedContent, void 0);
|
|
963
|
+
__privateGet(this, _signalUpdate).call(this);
|
|
964
|
+
}
|
|
965
|
+
return;
|
|
966
|
+
}
|
|
967
|
+
const content = await file.text();
|
|
968
|
+
if (__privateGet(this, _content) !== content) {
|
|
969
|
+
__privateSet(this, _content, content);
|
|
970
|
+
__privateSet(this, _savedContent, content);
|
|
971
|
+
__privateGet(this, _signalUpdate).call(this);
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
_access = new WeakMap();
|
|
976
|
+
_signalUpdate = new WeakMap();
|
|
977
|
+
_content = new WeakMap();
|
|
978
|
+
_savedContent = new WeakMap();
|
|
979
|
+
class DirectoryEditorManager {
|
|
980
|
+
constructor(access) {
|
|
981
|
+
__privateAdd(this, _access2, void 0);
|
|
982
|
+
__privateAdd(this, _listeners, /* @__PURE__ */ new Set());
|
|
983
|
+
__privateAdd(this, _files, []);
|
|
984
|
+
__privateAdd(this, _selectedFile, void 0);
|
|
985
|
+
__publicField(this, "setSelectedFile", (path) => {
|
|
986
|
+
const prev = __privateGet(this, _selectedFile);
|
|
987
|
+
const next = __privateGet(this, _files).find((file) => file.path === path);
|
|
988
|
+
if (prev !== next) {
|
|
989
|
+
__privateSet(this, _selectedFile, next);
|
|
990
|
+
__privateGet(this, _signalUpdate2).call(this);
|
|
991
|
+
}
|
|
992
|
+
});
|
|
993
|
+
__privateAdd(this, _signalUpdate2, () => {
|
|
994
|
+
__privateGet(this, _listeners).forEach((listener) => listener());
|
|
995
|
+
});
|
|
996
|
+
__privateSet(this, _access2, access);
|
|
997
|
+
}
|
|
998
|
+
get files() {
|
|
999
|
+
return __privateGet(this, _files);
|
|
1000
|
+
}
|
|
1001
|
+
get selectedFile() {
|
|
1002
|
+
return __privateGet(this, _selectedFile);
|
|
1003
|
+
}
|
|
1004
|
+
get dirty() {
|
|
362
1005
|
return __privateGet(this, _files).some((file) => file.dirty);
|
|
363
1006
|
}
|
|
364
1007
|
async save() {
|
|
@@ -534,181 +1177,10 @@ function useDryRun() {
|
|
|
534
1177
|
return value;
|
|
535
1178
|
}
|
|
536
1179
|
|
|
537
|
-
const useStyles$
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
},
|
|
542
|
-
card: {
|
|
543
|
-
position: "relative",
|
|
544
|
-
maxWidth: 340,
|
|
545
|
-
marginTop: theme.spacing(4),
|
|
546
|
-
margin: theme.spacing(0, 2)
|
|
547
|
-
},
|
|
548
|
-
infoIcon: {
|
|
549
|
-
position: "absolute",
|
|
550
|
-
top: theme.spacing(1),
|
|
551
|
-
right: theme.spacing(1)
|
|
552
|
-
}
|
|
553
|
-
}));
|
|
554
|
-
function TemplateEditorIntro(props) {
|
|
555
|
-
const classes = useStyles$8();
|
|
556
|
-
const supportsLoad = WebFileSystemAccess.isSupported();
|
|
557
|
-
const cardLoadLocal = /* @__PURE__ */ React.createElement(Card, { className: classes.card, elevation: 4 }, /* @__PURE__ */ React.createElement(
|
|
558
|
-
CardActionArea,
|
|
559
|
-
{
|
|
560
|
-
disabled: !supportsLoad,
|
|
561
|
-
onClick: () => {
|
|
562
|
-
var _a;
|
|
563
|
-
return (_a = props.onSelect) == null ? void 0 : _a.call(props, "local");
|
|
564
|
-
}
|
|
565
|
-
},
|
|
566
|
-
/* @__PURE__ */ React.createElement(CardContent, null, /* @__PURE__ */ React.createElement(
|
|
567
|
-
Typography$1,
|
|
568
|
-
{
|
|
569
|
-
variant: "h4",
|
|
570
|
-
component: "h3",
|
|
571
|
-
gutterBottom: true,
|
|
572
|
-
color: supportsLoad ? void 0 : "textSecondary",
|
|
573
|
-
style: { display: "flex", flexFlow: "row nowrap" }
|
|
574
|
-
},
|
|
575
|
-
"Load Template Directory"
|
|
576
|
-
), /* @__PURE__ */ React.createElement(
|
|
577
|
-
Typography$1,
|
|
578
|
-
{
|
|
579
|
-
variant: "body1",
|
|
580
|
-
color: supportsLoad ? void 0 : "textSecondary"
|
|
581
|
-
},
|
|
582
|
-
"Load a local template directory, allowing you to both edit and try executing your own template."
|
|
583
|
-
))
|
|
584
|
-
), !supportsLoad && /* @__PURE__ */ React.createElement("div", { className: classes.infoIcon }, /* @__PURE__ */ React.createElement(
|
|
585
|
-
Tooltip,
|
|
586
|
-
{
|
|
587
|
-
placement: "top",
|
|
588
|
-
title: "Only supported in some Chromium-based browsers"
|
|
589
|
-
},
|
|
590
|
-
/* @__PURE__ */ React.createElement(InfoOutlinedIcon, null)
|
|
591
|
-
)));
|
|
592
|
-
const cardFormEditor = /* @__PURE__ */ React.createElement(Card, { className: classes.card, elevation: 4 }, /* @__PURE__ */ React.createElement(CardActionArea, { onClick: () => {
|
|
593
|
-
var _a;
|
|
594
|
-
return (_a = props.onSelect) == null ? void 0 : _a.call(props, "form");
|
|
595
|
-
} }, /* @__PURE__ */ React.createElement(CardContent, null, /* @__PURE__ */ React.createElement(Typography$1, { variant: "h4", component: "h3", gutterBottom: true }, "Edit Template Form"), /* @__PURE__ */ React.createElement(Typography$1, { variant: "body1" }, "Preview and edit a template form, either using a sample template or by loading a template from the catalog."))));
|
|
596
|
-
const cardFieldExplorer = /* @__PURE__ */ React.createElement(Card, { className: classes.card, elevation: 4 }, /* @__PURE__ */ React.createElement(CardActionArea, { onClick: () => {
|
|
597
|
-
var _a;
|
|
598
|
-
return (_a = props.onSelect) == null ? void 0 : _a.call(props, "field-explorer");
|
|
599
|
-
} }, /* @__PURE__ */ React.createElement(CardContent, null, /* @__PURE__ */ React.createElement(Typography$1, { variant: "h4", component: "h3", gutterBottom: true }, "Custom Field Explorer"), /* @__PURE__ */ React.createElement(Typography$1, { variant: "body1" }, "View and play around with available installed custom field extensions."))));
|
|
600
|
-
return /* @__PURE__ */ React.createElement("div", { style: props.style }, /* @__PURE__ */ React.createElement(Typography$1, { variant: "h4", component: "h2", className: classes.introText }, "Get started by choosing one of the options below"), /* @__PURE__ */ React.createElement(
|
|
601
|
-
"div",
|
|
602
|
-
{
|
|
603
|
-
style: {
|
|
604
|
-
display: "flex",
|
|
605
|
-
flexFlow: "row wrap",
|
|
606
|
-
alignItems: "flex-start",
|
|
607
|
-
justifyContent: "center",
|
|
608
|
-
alignContent: "flex-start"
|
|
609
|
-
}
|
|
610
|
-
},
|
|
611
|
-
supportsLoad && cardLoadLocal,
|
|
612
|
-
cardFormEditor,
|
|
613
|
-
!supportsLoad && cardLoadLocal,
|
|
614
|
-
cardFieldExplorer
|
|
615
|
-
));
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
function downloadBlob(blob, name) {
|
|
619
|
-
const a = document.createElement("a");
|
|
620
|
-
a.href = URL.createObjectURL(blob);
|
|
621
|
-
a.download = name;
|
|
622
|
-
a.click();
|
|
623
|
-
URL.revokeObjectURL(a.href);
|
|
624
|
-
a.remove();
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
const useStyles$7 = makeStyles$1((theme) => ({
|
|
628
|
-
root: {
|
|
629
|
-
overflowY: "auto",
|
|
630
|
-
background: theme.palette.background.default
|
|
631
|
-
},
|
|
632
|
-
iconSuccess: {
|
|
633
|
-
minWidth: 0,
|
|
634
|
-
marginRight: theme.spacing(1),
|
|
635
|
-
color: theme.palette.status.ok
|
|
636
|
-
},
|
|
637
|
-
iconFailure: {
|
|
638
|
-
minWidth: 0,
|
|
639
|
-
marginRight: theme.spacing(1),
|
|
640
|
-
color: theme.palette.status.error
|
|
641
|
-
}
|
|
642
|
-
}));
|
|
643
|
-
function DryRunResultsList() {
|
|
644
|
-
const classes = useStyles$7();
|
|
645
|
-
const dryRun = useDryRun();
|
|
646
|
-
return /* @__PURE__ */ React.createElement(List, { className: classes.root, dense: true }, dryRun.results.map((result) => {
|
|
647
|
-
var _a;
|
|
648
|
-
const failed = result.log.some((l) => l.body.status === "failed");
|
|
649
|
-
let isLoading = false;
|
|
650
|
-
async function downloadResult() {
|
|
651
|
-
isLoading = true;
|
|
652
|
-
await downloadDirectoryContents(
|
|
653
|
-
result.directoryContents,
|
|
654
|
-
`dry-run-result-${result.id}.zip`
|
|
655
|
-
);
|
|
656
|
-
isLoading = false;
|
|
657
|
-
}
|
|
658
|
-
return /* @__PURE__ */ React.createElement(
|
|
659
|
-
ListItem,
|
|
660
|
-
{
|
|
661
|
-
button: true,
|
|
662
|
-
key: result.id,
|
|
663
|
-
selected: ((_a = dryRun.selectedResult) == null ? void 0 : _a.id) === result.id,
|
|
664
|
-
onClick: () => dryRun.selectResult(result.id)
|
|
665
|
-
},
|
|
666
|
-
/* @__PURE__ */ React.createElement(
|
|
667
|
-
ListItemIcon,
|
|
668
|
-
{
|
|
669
|
-
className: failed ? classes.iconFailure : classes.iconSuccess
|
|
670
|
-
},
|
|
671
|
-
failed ? /* @__PURE__ */ React.createElement(Cancel, null) : /* @__PURE__ */ React.createElement(Check, null)
|
|
672
|
-
),
|
|
673
|
-
/* @__PURE__ */ React.createElement(ListItemText, { primary: `Result ${result.id}` }),
|
|
674
|
-
/* @__PURE__ */ React.createElement(ListItemSecondaryAction, null, /* @__PURE__ */ React.createElement(
|
|
675
|
-
IconButton,
|
|
676
|
-
{
|
|
677
|
-
edge: "end",
|
|
678
|
-
"aria-label": "download",
|
|
679
|
-
title: "Download as .zip",
|
|
680
|
-
disabled: isLoading,
|
|
681
|
-
onClick: () => downloadResult()
|
|
682
|
-
},
|
|
683
|
-
/* @__PURE__ */ React.createElement(DownloadIcon, null)
|
|
684
|
-
), /* @__PURE__ */ React.createElement(
|
|
685
|
-
IconButton,
|
|
686
|
-
{
|
|
687
|
-
edge: "end",
|
|
688
|
-
"aria-label": "delete",
|
|
689
|
-
title: "Delete result",
|
|
690
|
-
onClick: () => dryRun.deleteResult(result.id)
|
|
691
|
-
},
|
|
692
|
-
/* @__PURE__ */ React.createElement(DeleteIcon, null)
|
|
693
|
-
))
|
|
694
|
-
);
|
|
695
|
-
}));
|
|
696
|
-
}
|
|
697
|
-
async function downloadDirectoryContents(directoryContents, name) {
|
|
698
|
-
const { default: JSZip } = await import('jszip');
|
|
699
|
-
const zip = new JSZip();
|
|
700
|
-
for (const d of directoryContents) {
|
|
701
|
-
const converted = atob(d.base64Content);
|
|
702
|
-
await zip.file(d.path, converted);
|
|
703
|
-
}
|
|
704
|
-
const blob = await zip.generateAsync({ type: "blob" });
|
|
705
|
-
downloadBlob(blob, name);
|
|
706
|
-
}
|
|
707
|
-
|
|
708
|
-
const useStyles$6 = makeStyles$1({
|
|
709
|
-
root: {
|
|
710
|
-
whiteSpace: "nowrap",
|
|
711
|
-
overflowY: "auto"
|
|
1180
|
+
const useStyles$6 = makeStyles$1({
|
|
1181
|
+
root: {
|
|
1182
|
+
whiteSpace: "nowrap",
|
|
1183
|
+
overflowY: "auto"
|
|
712
1184
|
}
|
|
713
1185
|
});
|
|
714
1186
|
function parseFileEntires(paths) {
|
|
@@ -786,72 +1258,327 @@ function FileBrowser(props) {
|
|
|
786
1258
|
);
|
|
787
1259
|
}
|
|
788
1260
|
|
|
789
|
-
const useStyles$5 = makeStyles
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
gridTemplateColumns: "280px auto 3fr",
|
|
793
|
-
gridTemplateRows: "1fr"
|
|
1261
|
+
const useStyles$5 = makeStyles((theme) => ({
|
|
1262
|
+
button: {
|
|
1263
|
+
padding: theme.spacing(1)
|
|
794
1264
|
},
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
1265
|
+
buttons: {
|
|
1266
|
+
display: "flex",
|
|
1267
|
+
flexFlow: "row nowrap",
|
|
1268
|
+
alignItems: "center",
|
|
1269
|
+
justifyContent: "flex-start"
|
|
799
1270
|
},
|
|
800
|
-
|
|
801
|
-
|
|
1271
|
+
buttonsGap: {
|
|
1272
|
+
flex: "1 1 auto"
|
|
1273
|
+
},
|
|
1274
|
+
buttonsDivider: {
|
|
1275
|
+
marginBottom: theme.spacing(1)
|
|
802
1276
|
}
|
|
803
1277
|
}));
|
|
804
|
-
function
|
|
1278
|
+
function TemplateEditorBrowser(props) {
|
|
1279
|
+
var _a, _b;
|
|
805
1280
|
const classes = useStyles$5();
|
|
806
|
-
const
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
1281
|
+
const directoryEditor = useDirectoryEditor();
|
|
1282
|
+
const changedFiles = directoryEditor.files.filter((file) => file.dirty);
|
|
1283
|
+
const handleClose = () => {
|
|
1284
|
+
if (!props.onClose) {
|
|
1285
|
+
return;
|
|
1286
|
+
}
|
|
1287
|
+
if (changedFiles.length > 0) {
|
|
1288
|
+
const accepted = window.confirm(
|
|
1289
|
+
"Are you sure? Unsaved changes will be lost"
|
|
1290
|
+
);
|
|
1291
|
+
if (!accepted) {
|
|
1292
|
+
return;
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
props.onClose();
|
|
1296
|
+
};
|
|
1297
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { className: classes.buttons }, /* @__PURE__ */ React.createElement(Tooltip$1, { title: "Save all files" }, /* @__PURE__ */ React.createElement(
|
|
1298
|
+
IconButton,
|
|
1299
|
+
{
|
|
1300
|
+
className: classes.button,
|
|
1301
|
+
disabled: directoryEditor.files.every((file) => !file.dirty),
|
|
1302
|
+
onClick: () => directoryEditor.save()
|
|
1303
|
+
},
|
|
1304
|
+
/* @__PURE__ */ React.createElement(SaveIcon, null)
|
|
1305
|
+
)), /* @__PURE__ */ React.createElement(Tooltip$1, { title: "Reload directory" }, /* @__PURE__ */ React.createElement(
|
|
1306
|
+
IconButton,
|
|
1307
|
+
{
|
|
1308
|
+
className: classes.button,
|
|
1309
|
+
onClick: () => directoryEditor.reload()
|
|
1310
|
+
},
|
|
1311
|
+
/* @__PURE__ */ React.createElement(RefreshIcon, null)
|
|
1312
|
+
)), /* @__PURE__ */ React.createElement("div", { className: classes.buttonsGap }), /* @__PURE__ */ React.createElement(Tooltip$1, { title: "Close directory" }, /* @__PURE__ */ React.createElement(IconButton, { className: classes.button, onClick: handleClose }, /* @__PURE__ */ React.createElement(CloseIcon, null)))), /* @__PURE__ */ React.createElement(Divider, { className: classes.buttonsDivider }), /* @__PURE__ */ React.createElement(
|
|
1313
|
+
FileBrowser,
|
|
1314
|
+
{
|
|
1315
|
+
selected: (_b = (_a = directoryEditor.selectedFile) == null ? void 0 : _a.path) != null ? _b : "",
|
|
1316
|
+
onSelect: directoryEditor.setSelectedFile,
|
|
1317
|
+
filePaths: directoryEditor.files.map((file) => file.path)
|
|
1318
|
+
}
|
|
1319
|
+
));
|
|
811
1320
|
}
|
|
812
1321
|
|
|
813
|
-
const useStyles$4 = makeStyles
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
contentWrapper: {
|
|
819
|
-
flex: 1,
|
|
820
|
-
position: "relative"
|
|
1322
|
+
const useStyles$4 = makeStyles((theme) => ({
|
|
1323
|
+
container: {
|
|
1324
|
+
position: "relative",
|
|
1325
|
+
width: "100%",
|
|
1326
|
+
height: "100%"
|
|
821
1327
|
},
|
|
822
|
-
|
|
1328
|
+
codeMirror: {
|
|
823
1329
|
position: "absolute",
|
|
824
1330
|
top: 0,
|
|
825
|
-
left: 0,
|
|
826
|
-
right: 0,
|
|
827
1331
|
bottom: 0,
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
flex: 1
|
|
831
|
-
}
|
|
1332
|
+
left: 0,
|
|
1333
|
+
right: 0
|
|
832
1334
|
},
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
1335
|
+
errorPanel: {
|
|
1336
|
+
color: theme.palette.error.main,
|
|
1337
|
+
lineHeight: 2,
|
|
1338
|
+
margin: theme.spacing(0, 1)
|
|
1339
|
+
},
|
|
1340
|
+
floatingButtons: {
|
|
1341
|
+
position: "absolute",
|
|
1342
|
+
top: theme.spacing(1),
|
|
1343
|
+
right: theme.spacing(3)
|
|
1344
|
+
},
|
|
1345
|
+
floatingButton: {
|
|
1346
|
+
padding: theme.spacing(1)
|
|
836
1347
|
}
|
|
837
|
-
});
|
|
838
|
-
function
|
|
1348
|
+
}));
|
|
1349
|
+
function TemplateEditorTextArea(props) {
|
|
1350
|
+
const { errorText } = props;
|
|
839
1351
|
const classes = useStyles$4();
|
|
840
|
-
const
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
1352
|
+
const panelExtension = useMemo(() => {
|
|
1353
|
+
if (!errorText) {
|
|
1354
|
+
return showPanel.of(null);
|
|
1355
|
+
}
|
|
1356
|
+
const dom = document.createElement("div");
|
|
1357
|
+
dom.classList.add(classes.errorPanel);
|
|
1358
|
+
dom.textContent = errorText;
|
|
1359
|
+
return showPanel.of(() => ({ dom, bottom: true }));
|
|
1360
|
+
}, [classes, errorText]);
|
|
1361
|
+
useKeyboardEvent(
|
|
1362
|
+
(e) => e.key === "s" && (e.ctrlKey || e.metaKey),
|
|
1363
|
+
(e) => {
|
|
1364
|
+
e.preventDefault();
|
|
1365
|
+
if (props.onSave) {
|
|
1366
|
+
props.onSave();
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
);
|
|
1370
|
+
return /* @__PURE__ */ React.createElement("div", { className: classes.container }, /* @__PURE__ */ React.createElement(
|
|
1371
|
+
CodeMirror,
|
|
1372
|
+
{
|
|
1373
|
+
className: classes.codeMirror,
|
|
1374
|
+
theme: "dark",
|
|
1375
|
+
height: "100%",
|
|
1376
|
+
extensions: [StreamLanguage.define(yaml$1), panelExtension],
|
|
1377
|
+
value: props.content,
|
|
1378
|
+
onChange: props.onUpdate
|
|
1379
|
+
}
|
|
1380
|
+
), (props.onSave || props.onReload) && /* @__PURE__ */ React.createElement("div", { className: classes.floatingButtons }, /* @__PURE__ */ React.createElement(Paper, null, props.onSave && /* @__PURE__ */ React.createElement(Tooltip$1, { title: "Save file" }, /* @__PURE__ */ React.createElement(
|
|
1381
|
+
IconButton,
|
|
1382
|
+
{
|
|
1383
|
+
className: classes.floatingButton,
|
|
1384
|
+
onClick: () => {
|
|
1385
|
+
var _a;
|
|
1386
|
+
return (_a = props.onSave) == null ? void 0 : _a.call(props);
|
|
1387
|
+
}
|
|
1388
|
+
},
|
|
1389
|
+
/* @__PURE__ */ React.createElement(SaveIcon, null)
|
|
1390
|
+
)), props.onReload && /* @__PURE__ */ React.createElement(Tooltip$1, { title: "Reload file" }, /* @__PURE__ */ React.createElement(
|
|
1391
|
+
IconButton,
|
|
1392
|
+
{
|
|
1393
|
+
className: classes.floatingButton,
|
|
1394
|
+
onClick: () => {
|
|
1395
|
+
var _a;
|
|
1396
|
+
return (_a = props.onReload) == null ? void 0 : _a.call(props);
|
|
1397
|
+
}
|
|
1398
|
+
},
|
|
1399
|
+
/* @__PURE__ */ React.createElement(RefreshIcon, null)
|
|
1400
|
+
)))));
|
|
1401
|
+
}
|
|
1402
|
+
function TemplateEditorDirectoryEditorTextArea(props) {
|
|
1403
|
+
var _a, _b;
|
|
1404
|
+
const directoryEditor = useDirectoryEditor();
|
|
1405
|
+
const actions = ((_a = directoryEditor.selectedFile) == null ? void 0 : _a.dirty) ? {
|
|
1406
|
+
onSave: () => directoryEditor.save(),
|
|
1407
|
+
onReload: () => directoryEditor.reload()
|
|
1408
|
+
} : {
|
|
1409
|
+
onReload: () => directoryEditor.reload()
|
|
1410
|
+
};
|
|
1411
|
+
return /* @__PURE__ */ React.createElement(
|
|
1412
|
+
TemplateEditorTextArea,
|
|
1413
|
+
{
|
|
1414
|
+
errorText: props.errorText,
|
|
1415
|
+
content: (_b = directoryEditor.selectedFile) == null ? void 0 : _b.content,
|
|
1416
|
+
onUpdate: (content) => {
|
|
1417
|
+
var _a2;
|
|
1418
|
+
return (_a2 = directoryEditor.selectedFile) == null ? void 0 : _a2.updateContent(content);
|
|
1419
|
+
},
|
|
1420
|
+
...actions
|
|
1421
|
+
}
|
|
1422
|
+
);
|
|
1423
|
+
}
|
|
1424
|
+
TemplateEditorTextArea.DirectoryEditor = TemplateEditorDirectoryEditorTextArea;
|
|
1425
|
+
|
|
1426
|
+
function downloadBlob(blob, name) {
|
|
1427
|
+
const a = document.createElement("a");
|
|
1428
|
+
a.href = URL.createObjectURL(blob);
|
|
1429
|
+
a.download = name;
|
|
1430
|
+
a.click();
|
|
1431
|
+
URL.revokeObjectURL(a.href);
|
|
1432
|
+
a.remove();
|
|
1433
|
+
}
|
|
1434
|
+
|
|
1435
|
+
const useStyles$3 = makeStyles$1((theme) => ({
|
|
1436
|
+
root: {
|
|
1437
|
+
overflowY: "auto",
|
|
1438
|
+
background: theme.palette.background.default
|
|
1439
|
+
},
|
|
1440
|
+
iconSuccess: {
|
|
1441
|
+
minWidth: 0,
|
|
1442
|
+
marginRight: theme.spacing(1),
|
|
1443
|
+
color: theme.palette.status.ok
|
|
1444
|
+
},
|
|
1445
|
+
iconFailure: {
|
|
1446
|
+
minWidth: 0,
|
|
1447
|
+
marginRight: theme.spacing(1),
|
|
1448
|
+
color: theme.palette.status.error
|
|
1449
|
+
}
|
|
1450
|
+
}));
|
|
1451
|
+
function DryRunResultsList() {
|
|
1452
|
+
const classes = useStyles$3();
|
|
1453
|
+
const dryRun = useDryRun();
|
|
1454
|
+
return /* @__PURE__ */ React.createElement(List$1, { className: classes.root, dense: true }, dryRun.results.map((result) => {
|
|
1455
|
+
var _a;
|
|
1456
|
+
const failed = result.log.some((l) => l.body.status === "failed");
|
|
1457
|
+
let isLoading = false;
|
|
1458
|
+
async function downloadResult() {
|
|
1459
|
+
isLoading = true;
|
|
1460
|
+
await downloadDirectoryContents(
|
|
1461
|
+
result.directoryContents,
|
|
1462
|
+
`dry-run-result-${result.id}.zip`
|
|
1463
|
+
);
|
|
1464
|
+
isLoading = false;
|
|
1465
|
+
}
|
|
1466
|
+
return /* @__PURE__ */ React.createElement(
|
|
1467
|
+
ListItem,
|
|
1468
|
+
{
|
|
1469
|
+
button: true,
|
|
1470
|
+
key: result.id,
|
|
1471
|
+
selected: ((_a = dryRun.selectedResult) == null ? void 0 : _a.id) === result.id,
|
|
1472
|
+
onClick: () => dryRun.selectResult(result.id)
|
|
1473
|
+
},
|
|
1474
|
+
/* @__PURE__ */ React.createElement(
|
|
1475
|
+
ListItemIcon$1,
|
|
1476
|
+
{
|
|
1477
|
+
className: failed ? classes.iconFailure : classes.iconSuccess
|
|
1478
|
+
},
|
|
1479
|
+
failed ? /* @__PURE__ */ React.createElement(Cancel, null) : /* @__PURE__ */ React.createElement(Check, null)
|
|
1480
|
+
),
|
|
1481
|
+
/* @__PURE__ */ React.createElement(ListItemText$1, { primary: `Result ${result.id}` }),
|
|
1482
|
+
/* @__PURE__ */ React.createElement(ListItemSecondaryAction, null, /* @__PURE__ */ React.createElement(
|
|
1483
|
+
IconButton$1,
|
|
1484
|
+
{
|
|
1485
|
+
edge: "end",
|
|
1486
|
+
"aria-label": "download",
|
|
1487
|
+
title: "Download as .zip",
|
|
1488
|
+
disabled: isLoading,
|
|
1489
|
+
onClick: () => downloadResult()
|
|
1490
|
+
},
|
|
1491
|
+
/* @__PURE__ */ React.createElement(DownloadIcon, null)
|
|
1492
|
+
), /* @__PURE__ */ React.createElement(
|
|
1493
|
+
IconButton$1,
|
|
1494
|
+
{
|
|
1495
|
+
edge: "end",
|
|
1496
|
+
"aria-label": "delete",
|
|
1497
|
+
title: "Delete result",
|
|
1498
|
+
onClick: () => dryRun.deleteResult(result.id)
|
|
1499
|
+
},
|
|
1500
|
+
/* @__PURE__ */ React.createElement(DeleteIcon, null)
|
|
1501
|
+
))
|
|
1502
|
+
);
|
|
1503
|
+
}));
|
|
1504
|
+
}
|
|
1505
|
+
async function downloadDirectoryContents(directoryContents, name) {
|
|
1506
|
+
const { default: JSZip } = await import('jszip');
|
|
1507
|
+
const zip = new JSZip();
|
|
1508
|
+
for (const d of directoryContents) {
|
|
1509
|
+
const converted = atob(d.base64Content);
|
|
1510
|
+
await zip.file(d.path, converted);
|
|
1511
|
+
}
|
|
1512
|
+
const blob = await zip.generateAsync({ type: "blob" });
|
|
1513
|
+
downloadBlob(blob, name);
|
|
1514
|
+
}
|
|
1515
|
+
|
|
1516
|
+
const useStyles$2 = makeStyles$1((theme) => ({
|
|
1517
|
+
root: {
|
|
1518
|
+
display: "grid",
|
|
1519
|
+
gridTemplateColumns: "280px auto 3fr",
|
|
1520
|
+
gridTemplateRows: "1fr"
|
|
1521
|
+
},
|
|
1522
|
+
child: {
|
|
1523
|
+
overflowY: "auto",
|
|
1524
|
+
height: "100%",
|
|
1525
|
+
minHeight: 0
|
|
1526
|
+
},
|
|
1527
|
+
firstChild: {
|
|
1528
|
+
background: theme.palette.background.paper
|
|
1529
|
+
}
|
|
1530
|
+
}));
|
|
1531
|
+
function DryRunResultsSplitView(props) {
|
|
1532
|
+
const classes = useStyles$2();
|
|
1533
|
+
const childArray = Children.toArray(props.children);
|
|
1534
|
+
if (childArray.length !== 2) {
|
|
1535
|
+
throw new Error("must have exactly 2 children");
|
|
1536
|
+
}
|
|
1537
|
+
return /* @__PURE__ */ React.createElement("div", { className: classes.root }, /* @__PURE__ */ React.createElement("div", { className: classNames(classes.child, classes.firstChild) }, childArray[0]), /* @__PURE__ */ React.createElement(Divider$1, { orientation: "horizontal" }), /* @__PURE__ */ React.createElement("div", { className: classes.child }, childArray[1]));
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1540
|
+
const useStyles$1 = makeStyles$1({
|
|
1541
|
+
root: {
|
|
1542
|
+
display: "flex",
|
|
1543
|
+
flexFlow: "column nowrap"
|
|
1544
|
+
},
|
|
1545
|
+
contentWrapper: {
|
|
1546
|
+
flex: 1,
|
|
1547
|
+
position: "relative"
|
|
1548
|
+
},
|
|
1549
|
+
content: {
|
|
1550
|
+
position: "absolute",
|
|
1551
|
+
top: 0,
|
|
1552
|
+
left: 0,
|
|
1553
|
+
right: 0,
|
|
1554
|
+
bottom: 0,
|
|
1555
|
+
display: "flex",
|
|
1556
|
+
"& > *": {
|
|
1557
|
+
flex: 1
|
|
1558
|
+
}
|
|
1559
|
+
},
|
|
1560
|
+
codeMirror: {
|
|
1561
|
+
height: "100%",
|
|
1562
|
+
overflowY: "auto"
|
|
1563
|
+
}
|
|
1564
|
+
});
|
|
1565
|
+
function FilesContent() {
|
|
1566
|
+
const classes = useStyles$1();
|
|
1567
|
+
const { selectedResult } = useDryRun();
|
|
1568
|
+
const [selectedPath, setSelectedPath] = useState("");
|
|
1569
|
+
const selectedFile = selectedResult == null ? void 0 : selectedResult.directoryContents.find(
|
|
1570
|
+
(f) => f.path === selectedPath
|
|
1571
|
+
);
|
|
1572
|
+
useEffect(() => {
|
|
1573
|
+
if (selectedResult) {
|
|
1574
|
+
const [firstFile] = selectedResult.directoryContents;
|
|
1575
|
+
if (firstFile) {
|
|
1576
|
+
setSelectedPath(firstFile.path);
|
|
1577
|
+
} else {
|
|
1578
|
+
setSelectedPath("");
|
|
1579
|
+
}
|
|
1580
|
+
}
|
|
1581
|
+
return void 0;
|
|
855
1582
|
}, [selectedResult]);
|
|
856
1583
|
if (!selectedResult) {
|
|
857
1584
|
return null;
|
|
@@ -912,7 +1639,7 @@ function LogContent() {
|
|
|
912
1639
|
}
|
|
913
1640
|
function OutputContent() {
|
|
914
1641
|
var _a, _b;
|
|
915
|
-
const classes = useStyles$
|
|
1642
|
+
const classes = useStyles$1();
|
|
916
1643
|
const { selectedResult } = useDryRun();
|
|
917
1644
|
if (!selectedResult) {
|
|
918
1645
|
return null;
|
|
@@ -930,14 +1657,14 @@ function OutputContent() {
|
|
|
930
1657
|
));
|
|
931
1658
|
}
|
|
932
1659
|
function DryRunResultsView() {
|
|
933
|
-
const classes = useStyles$
|
|
1660
|
+
const classes = useStyles$1();
|
|
934
1661
|
const [selectedTab, setSelectedTab] = useState(
|
|
935
1662
|
"files"
|
|
936
1663
|
);
|
|
937
|
-
return /* @__PURE__ */ React.createElement("div", { className: classes.root }, /* @__PURE__ */ React.createElement(Tabs, { value: selectedTab, onChange: (_, v) => setSelectedTab(v) }, /* @__PURE__ */ React.createElement(Tab, { value: "files", label: "Files" }), /* @__PURE__ */ React.createElement(Tab, { value: "log", label: "Log" }), /* @__PURE__ */ React.createElement(Tab, { value: "output", label: "Output" })), /* @__PURE__ */ React.createElement(Divider, null), /* @__PURE__ */ React.createElement("div", { className: classes.contentWrapper }, /* @__PURE__ */ React.createElement("div", { className: classes.content }, selectedTab === "files" && /* @__PURE__ */ React.createElement(FilesContent, null), selectedTab === "log" && /* @__PURE__ */ React.createElement(LogContent, null), selectedTab === "output" && /* @__PURE__ */ React.createElement(OutputContent, null))));
|
|
1664
|
+
return /* @__PURE__ */ React.createElement("div", { className: classes.root }, /* @__PURE__ */ React.createElement(Tabs, { value: selectedTab, onChange: (_, v) => setSelectedTab(v) }, /* @__PURE__ */ React.createElement(Tab, { value: "files", label: "Files" }), /* @__PURE__ */ React.createElement(Tab, { value: "log", label: "Log" }), /* @__PURE__ */ React.createElement(Tab, { value: "output", label: "Output" })), /* @__PURE__ */ React.createElement(Divider$1, null), /* @__PURE__ */ React.createElement("div", { className: classes.contentWrapper }, /* @__PURE__ */ React.createElement("div", { className: classes.content }, selectedTab === "files" && /* @__PURE__ */ React.createElement(FilesContent, null), selectedTab === "log" && /* @__PURE__ */ React.createElement(LogContent, null), selectedTab === "output" && /* @__PURE__ */ React.createElement(OutputContent, null))));
|
|
938
1665
|
}
|
|
939
1666
|
|
|
940
|
-
const useStyles
|
|
1667
|
+
const useStyles = makeStyles$1((theme) => ({
|
|
941
1668
|
header: {
|
|
942
1669
|
height: 48,
|
|
943
1670
|
minHeight: 0,
|
|
@@ -956,7 +1683,7 @@ const useStyles$3 = makeStyles$1((theme) => ({
|
|
|
956
1683
|
}
|
|
957
1684
|
}));
|
|
958
1685
|
function DryRunResults() {
|
|
959
|
-
const classes = useStyles
|
|
1686
|
+
const classes = useStyles();
|
|
960
1687
|
const dryRun = useDryRun();
|
|
961
1688
|
const [expanded, setExpanded] = useState(false);
|
|
962
1689
|
const [hidden, setHidden] = useState(true);
|
|
@@ -987,434 +1714,10 @@ function DryRunResults() {
|
|
|
987
1714
|
},
|
|
988
1715
|
/* @__PURE__ */ React.createElement(Typography$1, null, "Dry-run results")
|
|
989
1716
|
),
|
|
990
|
-
/* @__PURE__ */ React.createElement(Divider, { orientation: "horizontal" }),
|
|
991
|
-
/* @__PURE__ */ React.createElement(AccordionDetails$1, { className: classes.content }, /* @__PURE__ */ React.createElement(DryRunResultsList, null), /* @__PURE__ */ React.createElement(Divider, { orientation: "horizontal" }), /* @__PURE__ */ React.createElement(DryRunResultsView, null))
|
|
1717
|
+
/* @__PURE__ */ React.createElement(Divider$1, { orientation: "horizontal" }),
|
|
1718
|
+
/* @__PURE__ */ React.createElement(AccordionDetails$1, { className: classes.content }, /* @__PURE__ */ React.createElement(DryRunResultsList, null), /* @__PURE__ */ React.createElement(Divider$1, { orientation: "horizontal" }), /* @__PURE__ */ React.createElement(DryRunResultsView, null))
|
|
992
1719
|
));
|
|
993
1720
|
}
|
|
994
1721
|
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
padding: theme.spacing(1)
|
|
998
|
-
},
|
|
999
|
-
buttons: {
|
|
1000
|
-
display: "flex",
|
|
1001
|
-
flexFlow: "row nowrap",
|
|
1002
|
-
alignItems: "center",
|
|
1003
|
-
justifyContent: "flex-start"
|
|
1004
|
-
},
|
|
1005
|
-
buttonsGap: {
|
|
1006
|
-
flex: "1 1 auto"
|
|
1007
|
-
},
|
|
1008
|
-
buttonsDivider: {
|
|
1009
|
-
marginBottom: theme.spacing(1)
|
|
1010
|
-
}
|
|
1011
|
-
}));
|
|
1012
|
-
function TemplateEditorBrowser(props) {
|
|
1013
|
-
var _a, _b;
|
|
1014
|
-
const classes = useStyles$2();
|
|
1015
|
-
const directoryEditor = useDirectoryEditor();
|
|
1016
|
-
const changedFiles = directoryEditor.files.filter((file) => file.dirty);
|
|
1017
|
-
const handleClose = () => {
|
|
1018
|
-
if (!props.onClose) {
|
|
1019
|
-
return;
|
|
1020
|
-
}
|
|
1021
|
-
if (changedFiles.length > 0) {
|
|
1022
|
-
const accepted = window.confirm(
|
|
1023
|
-
"Are you sure? Unsaved changes will be lost"
|
|
1024
|
-
);
|
|
1025
|
-
if (!accepted) {
|
|
1026
|
-
return;
|
|
1027
|
-
}
|
|
1028
|
-
}
|
|
1029
|
-
props.onClose();
|
|
1030
|
-
};
|
|
1031
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { className: classes.buttons }, /* @__PURE__ */ React.createElement(Tooltip$1, { title: "Save all files" }, /* @__PURE__ */ React.createElement(
|
|
1032
|
-
IconButton$1,
|
|
1033
|
-
{
|
|
1034
|
-
className: classes.button,
|
|
1035
|
-
disabled: directoryEditor.files.every((file) => !file.dirty),
|
|
1036
|
-
onClick: () => directoryEditor.save()
|
|
1037
|
-
},
|
|
1038
|
-
/* @__PURE__ */ React.createElement(SaveIcon, null)
|
|
1039
|
-
)), /* @__PURE__ */ React.createElement(Tooltip$1, { title: "Reload directory" }, /* @__PURE__ */ React.createElement(
|
|
1040
|
-
IconButton$1,
|
|
1041
|
-
{
|
|
1042
|
-
className: classes.button,
|
|
1043
|
-
onClick: () => directoryEditor.reload()
|
|
1044
|
-
},
|
|
1045
|
-
/* @__PURE__ */ React.createElement(RefreshIcon, null)
|
|
1046
|
-
)), /* @__PURE__ */ React.createElement("div", { className: classes.buttonsGap }), /* @__PURE__ */ React.createElement(Tooltip$1, { title: "Close directory" }, /* @__PURE__ */ React.createElement(IconButton$1, { className: classes.button, onClick: handleClose }, /* @__PURE__ */ React.createElement(CloseIcon, null)))), /* @__PURE__ */ React.createElement(Divider$1, { className: classes.buttonsDivider }), /* @__PURE__ */ React.createElement(
|
|
1047
|
-
FileBrowser,
|
|
1048
|
-
{
|
|
1049
|
-
selected: (_b = (_a = directoryEditor.selectedFile) == null ? void 0 : _a.path) != null ? _b : "",
|
|
1050
|
-
onSelect: directoryEditor.setSelectedFile,
|
|
1051
|
-
filePaths: directoryEditor.files.map((file) => file.path)
|
|
1052
|
-
}
|
|
1053
|
-
));
|
|
1054
|
-
}
|
|
1055
|
-
|
|
1056
|
-
const useStyles$1 = makeStyles((theme) => ({
|
|
1057
|
-
container: {
|
|
1058
|
-
position: "relative",
|
|
1059
|
-
width: "100%",
|
|
1060
|
-
height: "100%"
|
|
1061
|
-
},
|
|
1062
|
-
codeMirror: {
|
|
1063
|
-
position: "absolute",
|
|
1064
|
-
top: 0,
|
|
1065
|
-
bottom: 0,
|
|
1066
|
-
left: 0,
|
|
1067
|
-
right: 0
|
|
1068
|
-
},
|
|
1069
|
-
errorPanel: {
|
|
1070
|
-
color: theme.palette.error.main,
|
|
1071
|
-
lineHeight: 2,
|
|
1072
|
-
margin: theme.spacing(0, 1)
|
|
1073
|
-
},
|
|
1074
|
-
floatingButtons: {
|
|
1075
|
-
position: "absolute",
|
|
1076
|
-
top: theme.spacing(1),
|
|
1077
|
-
right: theme.spacing(3)
|
|
1078
|
-
},
|
|
1079
|
-
floatingButton: {
|
|
1080
|
-
padding: theme.spacing(1)
|
|
1081
|
-
}
|
|
1082
|
-
}));
|
|
1083
|
-
function TemplateEditorTextArea(props) {
|
|
1084
|
-
const { errorText } = props;
|
|
1085
|
-
const classes = useStyles$1();
|
|
1086
|
-
const panelExtension = useMemo(() => {
|
|
1087
|
-
if (!errorText) {
|
|
1088
|
-
return showPanel.of(null);
|
|
1089
|
-
}
|
|
1090
|
-
const dom = document.createElement("div");
|
|
1091
|
-
dom.classList.add(classes.errorPanel);
|
|
1092
|
-
dom.textContent = errorText;
|
|
1093
|
-
return showPanel.of(() => ({ dom, bottom: true }));
|
|
1094
|
-
}, [classes, errorText]);
|
|
1095
|
-
useKeyboardEvent(
|
|
1096
|
-
(e) => e.key === "s" && (e.ctrlKey || e.metaKey),
|
|
1097
|
-
(e) => {
|
|
1098
|
-
e.preventDefault();
|
|
1099
|
-
if (props.onSave) {
|
|
1100
|
-
props.onSave();
|
|
1101
|
-
}
|
|
1102
|
-
}
|
|
1103
|
-
);
|
|
1104
|
-
return /* @__PURE__ */ React.createElement("div", { className: classes.container }, /* @__PURE__ */ React.createElement(
|
|
1105
|
-
CodeMirror,
|
|
1106
|
-
{
|
|
1107
|
-
className: classes.codeMirror,
|
|
1108
|
-
theme: "dark",
|
|
1109
|
-
height: "100%",
|
|
1110
|
-
extensions: [StreamLanguage.define(yaml$1), panelExtension],
|
|
1111
|
-
value: props.content,
|
|
1112
|
-
onChange: props.onUpdate
|
|
1113
|
-
}
|
|
1114
|
-
), (props.onSave || props.onReload) && /* @__PURE__ */ React.createElement("div", { className: classes.floatingButtons }, /* @__PURE__ */ React.createElement(Paper, null, props.onSave && /* @__PURE__ */ React.createElement(Tooltip$1, { title: "Save file" }, /* @__PURE__ */ React.createElement(
|
|
1115
|
-
IconButton$1,
|
|
1116
|
-
{
|
|
1117
|
-
className: classes.floatingButton,
|
|
1118
|
-
onClick: () => {
|
|
1119
|
-
var _a;
|
|
1120
|
-
return (_a = props.onSave) == null ? void 0 : _a.call(props);
|
|
1121
|
-
}
|
|
1122
|
-
},
|
|
1123
|
-
/* @__PURE__ */ React.createElement(SaveIcon, null)
|
|
1124
|
-
)), props.onReload && /* @__PURE__ */ React.createElement(Tooltip$1, { title: "Reload file" }, /* @__PURE__ */ React.createElement(
|
|
1125
|
-
IconButton$1,
|
|
1126
|
-
{
|
|
1127
|
-
className: classes.floatingButton,
|
|
1128
|
-
onClick: () => {
|
|
1129
|
-
var _a;
|
|
1130
|
-
return (_a = props.onReload) == null ? void 0 : _a.call(props);
|
|
1131
|
-
}
|
|
1132
|
-
},
|
|
1133
|
-
/* @__PURE__ */ React.createElement(RefreshIcon, null)
|
|
1134
|
-
)))));
|
|
1135
|
-
}
|
|
1136
|
-
function TemplateEditorDirectoryEditorTextArea(props) {
|
|
1137
|
-
var _a, _b;
|
|
1138
|
-
const directoryEditor = useDirectoryEditor();
|
|
1139
|
-
const actions = ((_a = directoryEditor.selectedFile) == null ? void 0 : _a.dirty) ? {
|
|
1140
|
-
onSave: () => directoryEditor.save(),
|
|
1141
|
-
onReload: () => directoryEditor.reload()
|
|
1142
|
-
} : {
|
|
1143
|
-
onReload: () => directoryEditor.reload()
|
|
1144
|
-
};
|
|
1145
|
-
return /* @__PURE__ */ React.createElement(
|
|
1146
|
-
TemplateEditorTextArea,
|
|
1147
|
-
{
|
|
1148
|
-
errorText: props.errorText,
|
|
1149
|
-
content: (_b = directoryEditor.selectedFile) == null ? void 0 : _b.content,
|
|
1150
|
-
onUpdate: (content) => {
|
|
1151
|
-
var _a2;
|
|
1152
|
-
return (_a2 = directoryEditor.selectedFile) == null ? void 0 : _a2.updateContent(content);
|
|
1153
|
-
},
|
|
1154
|
-
...actions
|
|
1155
|
-
}
|
|
1156
|
-
);
|
|
1157
|
-
}
|
|
1158
|
-
TemplateEditorTextArea.DirectoryEditor = TemplateEditorDirectoryEditorTextArea;
|
|
1159
|
-
|
|
1160
|
-
const DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS = [
|
|
1161
|
-
{
|
|
1162
|
-
component: EntityPicker,
|
|
1163
|
-
name: "EntityPicker",
|
|
1164
|
-
schema: EntityPickerSchema
|
|
1165
|
-
},
|
|
1166
|
-
{
|
|
1167
|
-
component: EntityNamePicker,
|
|
1168
|
-
name: "EntityNamePicker",
|
|
1169
|
-
validation: entityNamePickerValidation,
|
|
1170
|
-
schema: EntityNamePickerSchema
|
|
1171
|
-
},
|
|
1172
|
-
{
|
|
1173
|
-
component: EntityTagsPicker,
|
|
1174
|
-
name: "EntityTagsPicker",
|
|
1175
|
-
schema: EntityTagsPickerSchema
|
|
1176
|
-
},
|
|
1177
|
-
{
|
|
1178
|
-
component: RepoUrlPicker,
|
|
1179
|
-
name: "RepoUrlPicker",
|
|
1180
|
-
validation: repoPickerValidation,
|
|
1181
|
-
schema: RepoUrlPickerSchema
|
|
1182
|
-
},
|
|
1183
|
-
{
|
|
1184
|
-
component: OwnerPicker,
|
|
1185
|
-
name: "OwnerPicker",
|
|
1186
|
-
schema: OwnerPickerSchema
|
|
1187
|
-
},
|
|
1188
|
-
{
|
|
1189
|
-
component: OwnedEntityPicker,
|
|
1190
|
-
name: "OwnedEntityPicker",
|
|
1191
|
-
schema: OwnedEntityPickerSchema
|
|
1192
|
-
},
|
|
1193
|
-
{
|
|
1194
|
-
component: MyGroupsPicker,
|
|
1195
|
-
name: "MyGroupsPicker",
|
|
1196
|
-
schema: MyGroupsPickerSchema
|
|
1197
|
-
}
|
|
1198
|
-
];
|
|
1199
|
-
|
|
1200
|
-
const useStyles = makeStyles(
|
|
1201
|
-
(theme) => ({
|
|
1202
|
-
root: {
|
|
1203
|
-
backgroundColor: "rgba(0, 0, 0, .11)",
|
|
1204
|
-
boxShadow: "none",
|
|
1205
|
-
margin: theme.spacing(1, 0, 1, 0)
|
|
1206
|
-
},
|
|
1207
|
-
title: {
|
|
1208
|
-
margin: theme.spacing(1, 0, 0, 1),
|
|
1209
|
-
textTransform: "uppercase",
|
|
1210
|
-
fontSize: 12,
|
|
1211
|
-
fontWeight: "bold"
|
|
1212
|
-
},
|
|
1213
|
-
listIcon: {
|
|
1214
|
-
minWidth: 30,
|
|
1215
|
-
color: theme.palette.text.primary
|
|
1216
|
-
},
|
|
1217
|
-
menuItem: {
|
|
1218
|
-
minHeight: theme.spacing(6)
|
|
1219
|
-
},
|
|
1220
|
-
groupWrapper: {
|
|
1221
|
-
margin: theme.spacing(1, 1, 2, 1)
|
|
1222
|
-
}
|
|
1223
|
-
}),
|
|
1224
|
-
{
|
|
1225
|
-
name: "ScaffolderReactOwnerListPicker"
|
|
1226
|
-
}
|
|
1227
|
-
);
|
|
1228
|
-
function getFilterGroups() {
|
|
1229
|
-
return [
|
|
1230
|
-
{
|
|
1231
|
-
name: "Task Owner",
|
|
1232
|
-
items: [
|
|
1233
|
-
{
|
|
1234
|
-
id: "owned",
|
|
1235
|
-
label: "Owned",
|
|
1236
|
-
icon: SettingsIcon
|
|
1237
|
-
},
|
|
1238
|
-
{
|
|
1239
|
-
id: "all",
|
|
1240
|
-
label: "All",
|
|
1241
|
-
icon: AllIcon
|
|
1242
|
-
}
|
|
1243
|
-
]
|
|
1244
|
-
}
|
|
1245
|
-
];
|
|
1246
|
-
}
|
|
1247
|
-
const OwnerListPicker = (props) => {
|
|
1248
|
-
const { filter, onSelectOwner } = props;
|
|
1249
|
-
const classes = useStyles();
|
|
1250
|
-
const filterGroups = getFilterGroups();
|
|
1251
|
-
return /* @__PURE__ */ React.createElement(Card$1, { className: classes.root }, filterGroups.map((group) => /* @__PURE__ */ React.createElement(Fragment, { key: group.name }, /* @__PURE__ */ React.createElement(
|
|
1252
|
-
Typography,
|
|
1253
|
-
{
|
|
1254
|
-
variant: "subtitle2",
|
|
1255
|
-
component: "span",
|
|
1256
|
-
className: classes.title
|
|
1257
|
-
},
|
|
1258
|
-
group.name
|
|
1259
|
-
), /* @__PURE__ */ React.createElement(Card$1, { className: classes.groupWrapper }, /* @__PURE__ */ React.createElement(List$1, { disablePadding: true, dense: true, role: "menu" }, group.items.map((item) => /* @__PURE__ */ React.createElement(
|
|
1260
|
-
MenuItem,
|
|
1261
|
-
{
|
|
1262
|
-
key: item.id,
|
|
1263
|
-
button: true,
|
|
1264
|
-
divider: true,
|
|
1265
|
-
ContainerProps: { role: "menuitem" },
|
|
1266
|
-
onClick: () => onSelectOwner(item.id),
|
|
1267
|
-
selected: item.id === filter,
|
|
1268
|
-
className: classes.menuItem,
|
|
1269
|
-
"data-testid": `owner-picker-${item.id}`
|
|
1270
|
-
},
|
|
1271
|
-
item.icon && /* @__PURE__ */ React.createElement(ListItemIcon$1, { className: classes.listIcon }, /* @__PURE__ */ React.createElement(item.icon, { fontSize: "small" })),
|
|
1272
|
-
/* @__PURE__ */ React.createElement(ListItemText$1, null, /* @__PURE__ */ React.createElement(Typography, { variant: "body1" }, item.label))
|
|
1273
|
-
)))))));
|
|
1274
|
-
};
|
|
1275
|
-
|
|
1276
|
-
const CreatedAtColumn = ({ createdAt }) => {
|
|
1277
|
-
const createdAtTime = DateTime.fromISO(createdAt);
|
|
1278
|
-
const formatted = Interval.fromDateTimes(createdAtTime, DateTime.local()).toDuration().valueOf();
|
|
1279
|
-
return /* @__PURE__ */ React.createElement(Typography$1, { paragraph: true }, humanizeDuration(formatted, { round: true }), " ago");
|
|
1280
|
-
};
|
|
1281
|
-
|
|
1282
|
-
const OwnerEntityColumn = ({ entityRef }) => {
|
|
1283
|
-
var _a, _b, _c;
|
|
1284
|
-
const catalogApi = useApi(catalogApiRef);
|
|
1285
|
-
const { value, loading, error } = useAsync(
|
|
1286
|
-
() => catalogApi.getEntityByRef(entityRef || ""),
|
|
1287
|
-
[catalogApi, entityRef]
|
|
1288
|
-
);
|
|
1289
|
-
if (!entityRef) {
|
|
1290
|
-
return /* @__PURE__ */ React.createElement(Typography$1, { paragraph: true }, "Unknown");
|
|
1291
|
-
}
|
|
1292
|
-
if (loading || error) {
|
|
1293
|
-
return null;
|
|
1294
|
-
}
|
|
1295
|
-
return /* @__PURE__ */ React.createElement(
|
|
1296
|
-
EntityRefLink,
|
|
1297
|
-
{
|
|
1298
|
-
entityRef: parseEntityRef(entityRef),
|
|
1299
|
-
title: (_c = (_b = (_a = value == null ? void 0 : value.spec) == null ? void 0 : _a.profile) == null ? void 0 : _b.displayName) != null ? _c : value == null ? void 0 : value.metadata.name
|
|
1300
|
-
}
|
|
1301
|
-
);
|
|
1302
|
-
};
|
|
1303
|
-
|
|
1304
|
-
const TaskStatusColumn = ({ status }) => {
|
|
1305
|
-
switch (status) {
|
|
1306
|
-
case "processing":
|
|
1307
|
-
return /* @__PURE__ */ React.createElement(StatusPending, null, status);
|
|
1308
|
-
case "completed":
|
|
1309
|
-
return /* @__PURE__ */ React.createElement(StatusOK, null, status);
|
|
1310
|
-
case "error":
|
|
1311
|
-
default:
|
|
1312
|
-
return /* @__PURE__ */ React.createElement(StatusError, null, status);
|
|
1313
|
-
}
|
|
1314
|
-
};
|
|
1315
|
-
|
|
1316
|
-
const TemplateTitleColumn = ({ entityRef }) => {
|
|
1317
|
-
const scaffolder = useApi(scaffolderApiRef);
|
|
1318
|
-
const { value, loading, error } = useAsync(
|
|
1319
|
-
() => scaffolder.getTemplateParameterSchema(entityRef || ""),
|
|
1320
|
-
[scaffolder, entityRef]
|
|
1321
|
-
);
|
|
1322
|
-
if (loading || error || !entityRef) {
|
|
1323
|
-
return null;
|
|
1324
|
-
}
|
|
1325
|
-
return /* @__PURE__ */ React.createElement(EntityRefLink, { entityRef: parseEntityRef(entityRef), title: value == null ? void 0 : value.title });
|
|
1326
|
-
};
|
|
1327
|
-
|
|
1328
|
-
const ListTaskPageContent = (props) => {
|
|
1329
|
-
var _a;
|
|
1330
|
-
const { initiallySelectedFilter = "owned" } = props;
|
|
1331
|
-
const scaffolderApi = useApi(scaffolderApiRef);
|
|
1332
|
-
const rootLink = useRouteRef(rootRouteRef);
|
|
1333
|
-
const [ownerFilter, setOwnerFilter] = useState(initiallySelectedFilter);
|
|
1334
|
-
const { value, loading, error } = useAsync(() => {
|
|
1335
|
-
var _a2;
|
|
1336
|
-
if (scaffolderApi.listTasks) {
|
|
1337
|
-
return (_a2 = scaffolderApi.listTasks) == null ? void 0 : _a2.call(scaffolderApi, { filterByOwnership: ownerFilter });
|
|
1338
|
-
}
|
|
1339
|
-
console.warn(
|
|
1340
|
-
"listTasks is not implemented in the scaffolderApi, please make sure to implement this method."
|
|
1341
|
-
);
|
|
1342
|
-
return Promise.resolve({ tasks: [] });
|
|
1343
|
-
}, [scaffolderApi, ownerFilter]);
|
|
1344
|
-
if (loading) {
|
|
1345
|
-
return /* @__PURE__ */ React.createElement(Progress, null);
|
|
1346
|
-
}
|
|
1347
|
-
if (error) {
|
|
1348
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(ErrorPanel, { error }), /* @__PURE__ */ React.createElement(
|
|
1349
|
-
EmptyState,
|
|
1350
|
-
{
|
|
1351
|
-
missing: "info",
|
|
1352
|
-
title: "No information to display",
|
|
1353
|
-
description: "There is no Tasks or there was an issue communicating with backend."
|
|
1354
|
-
}
|
|
1355
|
-
));
|
|
1356
|
-
}
|
|
1357
|
-
return /* @__PURE__ */ React.createElement(CatalogFilterLayout, null, /* @__PURE__ */ React.createElement(CatalogFilterLayout.Filters, null, /* @__PURE__ */ React.createElement(
|
|
1358
|
-
OwnerListPicker,
|
|
1359
|
-
{
|
|
1360
|
-
filter: ownerFilter,
|
|
1361
|
-
onSelectOwner: (id) => setOwnerFilter(id)
|
|
1362
|
-
}
|
|
1363
|
-
)), /* @__PURE__ */ React.createElement(CatalogFilterLayout.Content, null, /* @__PURE__ */ React.createElement(
|
|
1364
|
-
Table$1,
|
|
1365
|
-
{
|
|
1366
|
-
data: (_a = value == null ? void 0 : value.tasks) != null ? _a : [],
|
|
1367
|
-
title: "Tasks",
|
|
1368
|
-
columns: [
|
|
1369
|
-
{
|
|
1370
|
-
title: "Task ID",
|
|
1371
|
-
field: "id",
|
|
1372
|
-
render: (row) => /* @__PURE__ */ React.createElement(Link, { to: `${rootLink()}/tasks/${row.id}` }, row.id)
|
|
1373
|
-
},
|
|
1374
|
-
{
|
|
1375
|
-
title: "Template",
|
|
1376
|
-
render: (row) => {
|
|
1377
|
-
var _a2;
|
|
1378
|
-
return /* @__PURE__ */ React.createElement(
|
|
1379
|
-
TemplateTitleColumn,
|
|
1380
|
-
{
|
|
1381
|
-
entityRef: (_a2 = row.spec.templateInfo) == null ? void 0 : _a2.entityRef
|
|
1382
|
-
}
|
|
1383
|
-
);
|
|
1384
|
-
}
|
|
1385
|
-
},
|
|
1386
|
-
{
|
|
1387
|
-
title: "Created",
|
|
1388
|
-
field: "createdAt",
|
|
1389
|
-
render: (row) => /* @__PURE__ */ React.createElement(CreatedAtColumn, { createdAt: row.createdAt })
|
|
1390
|
-
},
|
|
1391
|
-
{
|
|
1392
|
-
title: "Owner",
|
|
1393
|
-
field: "createdBy",
|
|
1394
|
-
render: (row) => {
|
|
1395
|
-
var _a2, _b;
|
|
1396
|
-
return /* @__PURE__ */ React.createElement(OwnerEntityColumn, { entityRef: (_b = (_a2 = row.spec) == null ? void 0 : _a2.user) == null ? void 0 : _b.ref });
|
|
1397
|
-
}
|
|
1398
|
-
},
|
|
1399
|
-
{
|
|
1400
|
-
title: "Status",
|
|
1401
|
-
field: "status",
|
|
1402
|
-
render: (row) => /* @__PURE__ */ React.createElement(TaskStatusColumn, { status: row.status })
|
|
1403
|
-
}
|
|
1404
|
-
]
|
|
1405
|
-
}
|
|
1406
|
-
)));
|
|
1407
|
-
};
|
|
1408
|
-
const ListTasksPage = (props) => {
|
|
1409
|
-
return /* @__PURE__ */ React.createElement(Page, { themeId: "home" }, /* @__PURE__ */ React.createElement(
|
|
1410
|
-
Header,
|
|
1411
|
-
{
|
|
1412
|
-
pageTitleOverride: "Templates Tasks",
|
|
1413
|
-
title: /* @__PURE__ */ React.createElement(React.Fragment, null, "List template tasks ", /* @__PURE__ */ React.createElement(Lifecycle, { shorthand: true, alpha: true })),
|
|
1414
|
-
subtitle: "All tasks that have been started"
|
|
1415
|
-
}
|
|
1416
|
-
), /* @__PURE__ */ React.createElement(Content, null, /* @__PURE__ */ React.createElement(ListTaskPageContent, { ...props })));
|
|
1417
|
-
};
|
|
1418
|
-
|
|
1419
|
-
export { ActionsPage as A, DirectoryEditorProvider as D, ListTasksPage as L, TemplateEditorBrowser as T, WebFileSystemAccess as W, useDirectoryEditor as a, DryRunProvider as b, TemplateEditorTextArea as c, DryRunResults as d, TemplateEditorIntro as e, DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS as f, useDryRun as u };
|
|
1420
|
-
//# sourceMappingURL=ListTasksPage-b7beed35.esm.js.map
|
|
1722
|
+
export { ActionsPage as A, DirectoryEditorProvider as D, ListTasksPage as L, TemplateEditorBrowser as T, WebFileSystemAccess as W, useDirectoryEditor as a, DryRunProvider as b, TemplateEditorTextArea as c, DryRunResults as d, TemplateEditorIntro as e, DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS as f, TaskPage as g, useDryRun as u };
|
|
1723
|
+
//# sourceMappingURL=DryRunResults-a4d44358.esm.js.map
|