@backstage/plugin-scaffolder 1.17.1 → 1.18.0-next.1
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 +60 -0
- package/alpha/package.json +1 -1
- package/dist/alpha.d.ts +20 -5
- package/dist/alpha.esm.js +55 -97
- package/dist/alpha.esm.js.map +1 -1
- package/dist/esm/{OngoingTask-87c6761c.esm.js → OngoingTask-5a95edc0.esm.js} +199 -446
- package/dist/esm/OngoingTask-5a95edc0.esm.js.map +1 -0
- package/dist/esm/{DryRunResults-c0cd5eb5.esm.js → index-7840abd4.esm.js} +1347 -634
- package/dist/esm/index-7840abd4.esm.js.map +1 -0
- package/dist/esm/routes-1428737e.esm.js +275 -0
- package/dist/esm/routes-1428737e.esm.js.map +1 -0
- package/dist/index.d.ts +187 -18
- package/dist/index.esm.js +171 -17
- package/dist/index.esm.js.map +1 -1
- package/package.json +23 -21
- package/dist/esm/DryRunResults-c0cd5eb5.esm.js.map +0 -1
- package/dist/esm/OngoingTask-87c6761c.esm.js.map +0 -1
- package/dist/esm/Router-5d4d36fb.esm.js +0 -1563
- package/dist/esm/Router-5d4d36fb.esm.js.map +0 -1
- package/dist/esm/index-38156f16.esm.js +0 -876
- package/dist/esm/index-38156f16.esm.js.map +0 -1
- package/dist/types/plugin.d-c637df46.d.ts +0 -214
|
@@ -1,363 +1,183 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { useState, Fragment, useCallback, createContext, useRef, useMemo, useContext, useEffect, Component, Children, memo } from 'react';
|
|
2
|
+
import { useNavigate, Link as Link$1, Navigate, useOutlet, Routes, Route } from 'react-router-dom';
|
|
3
|
+
import { useTemplateSecrets, scaffolderApiRef, useCustomFieldExtensions, useCustomLayouts, SecretsContextProvider } from '@backstage/plugin-scaffolder-react';
|
|
4
|
+
import { E as EntityPicker, a as EntityPickerSchema, b as EntityNamePicker, e as entityNamePickerValidation, c as EntityNamePickerSchema, l as EntityTagsPicker, m as EntityTagsPickerSchema, R as RepoUrlPicker, r as repoPickerValidation, f as RepoUrlPickerSchema, O as OwnerPicker, g as OwnerPickerSchema, j as OwnedEntityPicker, k as OwnedEntityPickerSchema, h as MyGroupsPicker, i as MyGroupsPickerSchema, M as MultiEntityPicker, d as MultiEntityPickerSchema, v as validateMultiEntityPickerValidation, n as OngoingTask } from './OngoingTask-5a95edc0.esm.js';
|
|
5
|
+
import { ScaffolderField, ScaffolderPageContextMenu, TemplateCategoryPicker, TemplateGroups, Workflow, createAsyncValidators, Stepper, Form } from '@backstage/plugin-scaffolder-react/alpha';
|
|
6
|
+
import { InputLabel, Input, makeStyles, Box, Typography, Accordion, AccordionSummary, AccordionDetails, Grid, TableContainer, Paper, Table, TableHead, TableRow, TableCell, TableBody, Collapse, Card, List, MenuItem, ListItemIcon, ListItemText, FormControl, Select, IconButton as IconButton$1, CardHeader, CardContent, Button as Button$1, Tooltip, Divider, createStyles, StepButton, CircularProgress, LinearProgress } from '@material-ui/core';
|
|
7
|
+
import { e as editRouteRef, c as scaffolderListTaskRouteRef, r as rootRouteRef, b as actionsRouteRef, d as registerComponentRouteRef, v as viewTechDocRouteRef, s as selectedTemplateRouteRef, a as scaffolderTaskRouteRef } from './routes-1428737e.esm.js';
|
|
8
|
+
import { Progress, ErrorPage, MarkdownContent, Page, Header, Content, CodeSnippet, StatusError, StatusOK, StatusPending, ErrorPanel, EmptyState, Table as Table$1, Link, DocsIcon, ContentHeader, SupportButton, LogViewer } from '@backstage/core-components';
|
|
2
9
|
import useAsync from 'react-use/lib/useAsync';
|
|
3
|
-
import { scaffolderApiRef, useTaskEventStream, useTemplateSecrets } 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, InputLabel, Input, Card, List, MenuItem, ListItemIcon, ListItemText, Tooltip as Tooltip$1, IconButton, Divider } from '@material-ui/core';
|
|
5
10
|
import classNames from 'classnames';
|
|
6
11
|
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
|
|
7
12
|
import ExpandLessIcon from '@material-ui/icons/ExpandLess';
|
|
8
|
-
import {
|
|
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';
|
|
13
|
+
import { useApi, useRouteRef, useApp, useRouteRefParams, AnalyticsContext, useApiHolder, alertApiRef } from '@backstage/core-plugin-api';
|
|
10
14
|
import Chip from '@material-ui/core/Chip';
|
|
11
|
-
import {
|
|
12
|
-
import { ScaffolderField } from '@backstage/plugin-scaffolder-react/alpha';
|
|
13
|
-
import { entityRouteRef, catalogApiRef, EntityRefLink, CatalogFilterLayout } from '@backstage/plugin-catalog-react';
|
|
15
|
+
import { catalogApiRef, EntityRefLink, CatalogFilterLayout, EntityListProvider, EntitySearchBar, EntityKindPicker, UserListPicker, EntityTagPicker, entityRouteRef, humanizeEntityRef } from '@backstage/plugin-catalog-react';
|
|
14
16
|
import SettingsIcon from '@material-ui/icons/Settings';
|
|
15
17
|
import AllIcon from '@material-ui/icons/FontDownload';
|
|
16
18
|
import { DateTime, Interval } from 'luxon';
|
|
17
19
|
import humanizeDuration from 'humanize-duration';
|
|
18
20
|
import Typography$1 from '@material-ui/core/Typography';
|
|
19
|
-
import { parseEntityRef } from '@backstage/catalog-model';
|
|
20
|
-
import
|
|
21
|
-
import
|
|
22
|
-
import
|
|
23
|
-
import
|
|
24
|
-
import
|
|
25
|
-
import {
|
|
21
|
+
import { parseEntityRef, stringifyEntityRef } from '@backstage/catalog-model';
|
|
22
|
+
import Button from '@material-ui/core/Button';
|
|
23
|
+
import IconButton from '@material-ui/core/IconButton';
|
|
24
|
+
import useMediaQuery from '@material-ui/core/useMediaQuery';
|
|
25
|
+
import CreateComponentIcon from '@material-ui/icons/AddCircleOutline';
|
|
26
|
+
import { catalogEntityCreatePermission } from '@backstage/plugin-catalog-common/alpha';
|
|
27
|
+
import { usePermission } from '@backstage/plugin-permission-react';
|
|
28
|
+
import { StreamLanguage } from '@codemirror/language';
|
|
29
|
+
import { yaml as yaml$1 } from '@codemirror/legacy-modes/mode/yaml';
|
|
26
30
|
import CloseIcon from '@material-ui/icons/Close';
|
|
31
|
+
import CodeMirror from '@uiw/react-codemirror';
|
|
32
|
+
import yaml from 'yaml';
|
|
33
|
+
import { makeStyles as makeStyles$1 } from '@material-ui/core/styles';
|
|
34
|
+
import useDebounce from 'react-use/lib/useDebounce';
|
|
35
|
+
import { useAsync as useAsync$1, useRerender, useKeyboardEvent, usePrevious } from '@react-hookz/web';
|
|
36
|
+
import validator from '@rjsf/validator-ajv8';
|
|
27
37
|
import RefreshIcon from '@material-ui/icons/Refresh';
|
|
28
38
|
import SaveIcon from '@material-ui/icons/Save';
|
|
29
|
-
import
|
|
30
|
-
import
|
|
39
|
+
import TreeView from '@material-ui/lab/TreeView';
|
|
40
|
+
import ChevronRightIcon from '@material-ui/icons/ChevronRight';
|
|
41
|
+
import TreeItem from '@material-ui/lab/TreeItem';
|
|
31
42
|
import { showPanel } from '@codemirror/view';
|
|
32
|
-
import { useAsync as useAsync$1, useRerender, useKeyboardEvent, usePrevious } from '@react-hookz/web';
|
|
33
|
-
import CodeMirror from '@uiw/react-codemirror';
|
|
34
43
|
import Accordion$1 from '@material-ui/core/Accordion';
|
|
35
44
|
import AccordionDetails$1 from '@material-ui/core/AccordionDetails';
|
|
36
45
|
import AccordionSummary$1 from '@material-ui/core/AccordionSummary';
|
|
37
46
|
import Divider$1 from '@material-ui/core/Divider';
|
|
38
|
-
import yaml from 'yaml';
|
|
39
|
-
import IconButton$1 from '@material-ui/core/IconButton';
|
|
40
47
|
import List$1 from '@material-ui/core/List';
|
|
41
48
|
import ListItem from '@material-ui/core/ListItem';
|
|
42
49
|
import ListItemIcon$1 from '@material-ui/core/ListItemIcon';
|
|
43
50
|
import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction';
|
|
44
51
|
import ListItemText$1 from '@material-ui/core/ListItemText';
|
|
45
52
|
import Cancel from '@material-ui/icons/Cancel';
|
|
46
|
-
import
|
|
53
|
+
import CheckIcon from '@material-ui/icons/Check';
|
|
47
54
|
import DeleteIcon from '@material-ui/icons/Delete';
|
|
48
55
|
import DownloadIcon from '@material-ui/icons/GetApp';
|
|
49
56
|
import Box$1 from '@material-ui/core/Box';
|
|
50
57
|
import Tab from '@material-ui/core/Tab';
|
|
51
58
|
import Tabs from '@material-ui/core/Tabs';
|
|
52
|
-
import TreeView from '@material-ui/lab/TreeView';
|
|
53
|
-
import ChevronRightIcon from '@material-ui/icons/ChevronRight';
|
|
54
|
-
import TreeItem from '@material-ui/lab/TreeItem';
|
|
55
59
|
import LanguageIcon from '@material-ui/icons/Language';
|
|
56
|
-
import Grid$1 from '@material-ui/core/Grid';
|
|
57
60
|
import Step from '@material-ui/core/Step';
|
|
58
61
|
import StepLabel from '@material-ui/core/StepLabel';
|
|
59
|
-
import Stepper from '@material-ui/core/Stepper';
|
|
62
|
+
import Stepper$1 from '@material-ui/core/Stepper';
|
|
60
63
|
import FiberManualRecordIcon from '@material-ui/icons/FiberManualRecord';
|
|
61
|
-
import qs from 'qs';
|
|
62
|
-
import { useNavigate } from 'react-router-dom';
|
|
63
64
|
import useInterval from 'react-use/lib/useInterval';
|
|
65
|
+
import Card$1 from '@material-ui/core/Card';
|
|
66
|
+
import CardActionArea from '@material-ui/core/CardActionArea';
|
|
67
|
+
import CardContent$1 from '@material-ui/core/CardContent';
|
|
68
|
+
import Tooltip$1 from '@material-ui/core/Tooltip';
|
|
69
|
+
import InfoOutlinedIcon from '@material-ui/icons/InfoOutlined';
|
|
70
|
+
import 'zod';
|
|
71
|
+
import '@backstage/catalog-client';
|
|
72
|
+
import '@material-ui/core/FormControl';
|
|
73
|
+
import '@material-ui/lab/Autocomplete';
|
|
74
|
+
import '@backstage/integration-react';
|
|
75
|
+
import '@material-ui/core/FormHelperText';
|
|
76
|
+
import '@material-ui/core/Input';
|
|
77
|
+
import '@material-ui/core/InputLabel';
|
|
78
|
+
import 'react-use/lib/useEffectOnce';
|
|
79
|
+
import '@material-ui/lab';
|
|
80
|
+
import 'zod-to-json-schema';
|
|
81
|
+
import '@backstage/errors';
|
|
82
|
+
import 'qs';
|
|
83
|
+
import '@material-ui/icons/Repeat';
|
|
84
|
+
import '@material-ui/icons/Toc';
|
|
85
|
+
import '@material-ui/icons/ControlPoint';
|
|
86
|
+
import '@material-ui/icons/MoreVert';
|
|
87
|
+
import 'zen-observable';
|
|
88
|
+
import 'event-source-polyfill';
|
|
64
89
|
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
)) : null;
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
const useStyles$b = makeStyles({
|
|
81
|
-
svgIcon: {
|
|
82
|
-
display: "inline-block",
|
|
83
|
-
"& svg": {
|
|
84
|
-
display: "inline-block",
|
|
85
|
-
fontSize: "inherit",
|
|
86
|
-
verticalAlign: "baseline"
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
});
|
|
90
|
-
const IconLink = (props) => {
|
|
91
|
-
const { href, text, Icon, ...linkProps } = props;
|
|
92
|
-
const classes = useStyles$b();
|
|
93
|
-
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)));
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
const TaskPageLinks = ({ output }) => {
|
|
97
|
-
const { links = [] } = output;
|
|
98
|
-
const app = useApp();
|
|
99
|
-
const entityRoute = useRouteRef(entityRouteRef);
|
|
100
|
-
const iconResolver = (key) => {
|
|
101
|
-
var _a;
|
|
102
|
-
return key ? (_a = app.getSystemIcon(key)) != null ? _a : LanguageIcon : LanguageIcon;
|
|
103
|
-
};
|
|
104
|
-
return /* @__PURE__ */ React.createElement(Box, { px: 3, pb: 3 }, links.filter(({ url, entityRef }) => url || entityRef).map(({ url, entityRef, title, icon }) => {
|
|
105
|
-
if (entityRef) {
|
|
106
|
-
const entityName = parseEntityRef(entityRef, {
|
|
107
|
-
defaultKind: "<unknown>",
|
|
108
|
-
defaultNamespace: "<unknown>"
|
|
109
|
-
});
|
|
110
|
-
const target = entityRoute(entityName);
|
|
111
|
-
return { title, icon, url: target };
|
|
112
|
-
}
|
|
113
|
-
return { title, icon, url };
|
|
114
|
-
}).map(({ url, title, icon }, i) => /* @__PURE__ */ React.createElement(
|
|
115
|
-
IconLink,
|
|
116
|
-
{
|
|
117
|
-
key: `output-link-${i}`,
|
|
118
|
-
href: url,
|
|
119
|
-
text: title != null ? title : url,
|
|
120
|
-
Icon: iconResolver(icon),
|
|
121
|
-
target: "_blank"
|
|
122
|
-
}
|
|
123
|
-
)));
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
const useStyles$a = makeStyles$1(
|
|
127
|
-
(theme) => createStyles({
|
|
128
|
-
root: {
|
|
129
|
-
width: "100%"
|
|
130
|
-
},
|
|
131
|
-
button: {
|
|
132
|
-
marginBottom: theme.spacing(2),
|
|
133
|
-
marginLeft: theme.spacing(2)
|
|
134
|
-
},
|
|
135
|
-
actionsContainer: {
|
|
136
|
-
marginBottom: theme.spacing(2)
|
|
137
|
-
},
|
|
138
|
-
resetContainer: {
|
|
139
|
-
padding: theme.spacing(3)
|
|
140
|
-
},
|
|
141
|
-
labelWrapper: {
|
|
142
|
-
display: "flex",
|
|
143
|
-
flex: 1,
|
|
144
|
-
flexDirection: "row",
|
|
145
|
-
justifyContent: "space-between"
|
|
146
|
-
},
|
|
147
|
-
stepWrapper: {
|
|
148
|
-
width: "100%"
|
|
149
|
-
}
|
|
150
|
-
})
|
|
151
|
-
);
|
|
152
|
-
const StepTimeTicker = ({ step }) => {
|
|
153
|
-
const [time, setTime] = useState("");
|
|
154
|
-
useInterval(() => {
|
|
155
|
-
if (!step.startedAt) {
|
|
156
|
-
setTime("");
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
|
-
const end = step.endedAt ? DateTime.fromISO(step.endedAt) : DateTime.local();
|
|
160
|
-
const startedAt = DateTime.fromISO(step.startedAt);
|
|
161
|
-
const formatted = Interval.fromDateTimes(startedAt, end).toDuration().valueOf();
|
|
162
|
-
setTime(humanizeDuration(formatted, { round: true }));
|
|
163
|
-
}, 1e3);
|
|
164
|
-
return /* @__PURE__ */ React.createElement(Typography$1, { variant: "caption" }, time);
|
|
165
|
-
};
|
|
166
|
-
const useStepIconStyles = makeStyles$1(
|
|
167
|
-
(theme) => createStyles({
|
|
168
|
-
root: {
|
|
169
|
-
color: theme.palette.text.disabled,
|
|
170
|
-
display: "flex",
|
|
171
|
-
height: 22,
|
|
172
|
-
alignItems: "center"
|
|
173
|
-
},
|
|
174
|
-
completed: {
|
|
175
|
-
color: theme.palette.status.ok
|
|
176
|
-
},
|
|
177
|
-
error: {
|
|
178
|
-
color: theme.palette.status.error
|
|
179
|
-
}
|
|
180
|
-
})
|
|
181
|
-
);
|
|
182
|
-
function TaskStepIconComponent(props) {
|
|
183
|
-
const classes = useStepIconStyles();
|
|
184
|
-
const { active, completed, error } = props;
|
|
185
|
-
const getMiddle = () => {
|
|
186
|
-
if (active) {
|
|
187
|
-
return /* @__PURE__ */ React.createElement(CircularProgress, { size: "24px" });
|
|
188
|
-
}
|
|
189
|
-
if (completed) {
|
|
190
|
-
return /* @__PURE__ */ React.createElement(Check, null);
|
|
191
|
-
}
|
|
192
|
-
if (error) {
|
|
193
|
-
return /* @__PURE__ */ React.createElement(Cancel, null);
|
|
194
|
-
}
|
|
195
|
-
return /* @__PURE__ */ React.createElement(FiberManualRecordIcon, null);
|
|
196
|
-
};
|
|
90
|
+
const SecretInput = (props) => {
|
|
91
|
+
var _a;
|
|
92
|
+
const { setSecrets, secrets } = useTemplateSecrets();
|
|
93
|
+
const {
|
|
94
|
+
name,
|
|
95
|
+
onChange,
|
|
96
|
+
schema: { title, description },
|
|
97
|
+
rawErrors,
|
|
98
|
+
disabled,
|
|
99
|
+
errors,
|
|
100
|
+
required
|
|
101
|
+
} = props;
|
|
197
102
|
return /* @__PURE__ */ React.createElement(
|
|
198
|
-
|
|
103
|
+
ScaffolderField,
|
|
199
104
|
{
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
105
|
+
rawErrors,
|
|
106
|
+
rawDescription: description,
|
|
107
|
+
disabled,
|
|
108
|
+
errors,
|
|
109
|
+
required
|
|
204
110
|
},
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
const TaskStatusStepper = memo(
|
|
209
|
-
(props) => {
|
|
210
|
-
const { steps, currentStepId, onUserStepChange } = props;
|
|
211
|
-
const classes = useStyles$a(props);
|
|
212
|
-
return /* @__PURE__ */ React.createElement("div", { className: classes.root }, /* @__PURE__ */ React.createElement(
|
|
213
|
-
Stepper,
|
|
111
|
+
/* @__PURE__ */ React.createElement(InputLabel, { htmlFor: title }, title),
|
|
112
|
+
/* @__PURE__ */ React.createElement(
|
|
113
|
+
Input,
|
|
214
114
|
{
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
{
|
|
228
|
-
StepIconProps: {
|
|
229
|
-
completed: isCompleted,
|
|
230
|
-
error: isFailed || isCancelled,
|
|
231
|
-
active: isActive
|
|
232
|
-
},
|
|
233
|
-
StepIconComponent: TaskStepIconComponent,
|
|
234
|
-
className: classes.stepWrapper
|
|
235
|
-
},
|
|
236
|
-
/* @__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 }))
|
|
237
|
-
)));
|
|
238
|
-
})
|
|
239
|
-
));
|
|
240
|
-
}
|
|
241
|
-
);
|
|
242
|
-
const hasLinks = ({ links = [] }) => links.length > 0;
|
|
243
|
-
const TaskPage = (props) => {
|
|
244
|
-
const { loadingText } = props;
|
|
245
|
-
const classes = useStyles$a();
|
|
246
|
-
const navigate = useNavigate();
|
|
247
|
-
const rootPath = useRouteRef(rootRouteRef);
|
|
248
|
-
const scaffolderApi = useApi(scaffolderApiRef);
|
|
249
|
-
const templateRoute = useRouteRef(selectedTemplateRouteRef);
|
|
250
|
-
const [userSelectedStepId, setUserSelectedStepId] = useState(void 0);
|
|
251
|
-
const [clickedToCancel, setClickedToCancel] = useState(false);
|
|
252
|
-
const [lastActiveStepId, setLastActiveStepId] = useState(
|
|
253
|
-
void 0
|
|
254
|
-
);
|
|
255
|
-
const { taskId } = useRouteRefParams(scaffolderTaskRouteRef);
|
|
256
|
-
const taskStream = useTaskEventStream(taskId);
|
|
257
|
-
const completed = taskStream.completed;
|
|
258
|
-
const taskCancelled = taskStream.cancelled;
|
|
259
|
-
const steps = useMemo(
|
|
260
|
-
() => {
|
|
261
|
-
var _a, _b;
|
|
262
|
-
return (_b = (_a = taskStream.task) == null ? void 0 : _a.spec.steps.map((step) => {
|
|
263
|
-
var _a2;
|
|
264
|
-
return {
|
|
265
|
-
...step,
|
|
266
|
-
...(_a2 = taskStream == null ? void 0 : taskStream.steps) == null ? void 0 : _a2[step.id]
|
|
267
|
-
};
|
|
268
|
-
})) != null ? _b : [];
|
|
269
|
-
},
|
|
270
|
-
[taskStream]
|
|
115
|
+
id: title,
|
|
116
|
+
"aria-describedby": title,
|
|
117
|
+
onChange: (e) => {
|
|
118
|
+
var _a2, _b;
|
|
119
|
+
onChange(Array((_a2 = e.target) == null ? void 0 : _a2.value.length).fill("*").join(""));
|
|
120
|
+
setSecrets({ [name]: (_b = e.target) == null ? void 0 : _b.value });
|
|
121
|
+
},
|
|
122
|
+
value: (_a = secrets[name]) != null ? _a : "",
|
|
123
|
+
type: "password",
|
|
124
|
+
autoComplete: "off"
|
|
125
|
+
}
|
|
126
|
+
)
|
|
271
127
|
);
|
|
272
|
-
useEffect(() => {
|
|
273
|
-
var _a;
|
|
274
|
-
const mostRecentFailedOrActiveStep = steps.find(
|
|
275
|
-
(step) => ["failed", "processing"].includes(step.status)
|
|
276
|
-
);
|
|
277
|
-
if (completed && !mostRecentFailedOrActiveStep) {
|
|
278
|
-
setLastActiveStepId((_a = steps[steps.length - 1]) == null ? void 0 : _a.id);
|
|
279
|
-
return;
|
|
280
|
-
}
|
|
281
|
-
setLastActiveStepId(mostRecentFailedOrActiveStep == null ? void 0 : mostRecentFailedOrActiveStep.id);
|
|
282
|
-
}, [steps, completed]);
|
|
283
|
-
const currentStepId = userSelectedStepId != null ? userSelectedStepId : lastActiveStepId;
|
|
284
|
-
const logAsString = useMemo(() => {
|
|
285
|
-
if (!currentStepId) {
|
|
286
|
-
return loadingText ? loadingText : "Loading...";
|
|
287
|
-
}
|
|
288
|
-
const log = taskStream.stepLogs[currentStepId];
|
|
289
|
-
if (!(log == null ? void 0 : log.length)) {
|
|
290
|
-
return "Waiting for logs...";
|
|
291
|
-
}
|
|
292
|
-
return log.join("\n");
|
|
293
|
-
}, [taskStream.stepLogs, currentStepId, loadingText]);
|
|
294
|
-
const taskNotFound = taskStream.completed && !taskStream.loading && !taskStream.task;
|
|
295
|
-
const { output } = taskStream;
|
|
296
|
-
const handleStartOver = () => {
|
|
297
|
-
var _a, _b, _c;
|
|
298
|
-
if (!taskStream.task || !((_b = (_a = taskStream.task) == null ? void 0 : _a.spec.templateInfo) == null ? void 0 : _b.entityRef)) {
|
|
299
|
-
navigate(rootPath());
|
|
300
|
-
return;
|
|
301
|
-
}
|
|
302
|
-
const formData = taskStream.task.spec.parameters;
|
|
303
|
-
const { name, namespace } = parseEntityRef(
|
|
304
|
-
(_c = taskStream.task.spec.templateInfo) == null ? void 0 : _c.entityRef
|
|
305
|
-
);
|
|
306
|
-
navigate(
|
|
307
|
-
`${templateRoute({ templateName: name, namespace })}?${qs.stringify({
|
|
308
|
-
formData: JSON.stringify(formData)
|
|
309
|
-
})}`
|
|
310
|
-
);
|
|
311
|
-
};
|
|
312
|
-
const handleCancel = async () => {
|
|
313
|
-
setClickedToCancel(true);
|
|
314
|
-
await scaffolderApi.cancelTask(taskId);
|
|
315
|
-
};
|
|
316
|
-
return /* @__PURE__ */ React.createElement(Page, { themeId: "home" }, /* @__PURE__ */ React.createElement(
|
|
317
|
-
Header,
|
|
318
|
-
{
|
|
319
|
-
pageTitleOverride: `Task ${taskId}`,
|
|
320
|
-
title: "Task Activity",
|
|
321
|
-
subtitle: `Activity for task: ${taskId}`
|
|
322
|
-
}
|
|
323
|
-
), /* @__PURE__ */ React.createElement(Content, null, taskNotFound ? /* @__PURE__ */ React.createElement(
|
|
324
|
-
ErrorPage,
|
|
325
|
-
{
|
|
326
|
-
status: "404",
|
|
327
|
-
statusMessage: "Task not found",
|
|
328
|
-
additionalInfo: "No task found with this ID"
|
|
329
|
-
}
|
|
330
|
-
) : /* @__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(
|
|
331
|
-
TaskStatusStepper,
|
|
332
|
-
{
|
|
333
|
-
steps,
|
|
334
|
-
currentStepId,
|
|
335
|
-
onUserStepChange: setUserSelectedStepId
|
|
336
|
-
}
|
|
337
|
-
), output && hasLinks(output) && /* @__PURE__ */ React.createElement(TaskPageLinks, { output }), /* @__PURE__ */ React.createElement(
|
|
338
|
-
Button,
|
|
339
|
-
{
|
|
340
|
-
className: classes.button,
|
|
341
|
-
onClick: handleStartOver,
|
|
342
|
-
disabled: !completed,
|
|
343
|
-
variant: "contained",
|
|
344
|
-
color: "primary"
|
|
345
|
-
},
|
|
346
|
-
"Start Over"
|
|
347
|
-
), /* @__PURE__ */ React.createElement(
|
|
348
|
-
Button,
|
|
349
|
-
{
|
|
350
|
-
className: classes.button,
|
|
351
|
-
onClick: handleCancel,
|
|
352
|
-
disabled: completed || taskCancelled || clickedToCancel,
|
|
353
|
-
variant: "outlined",
|
|
354
|
-
color: "secondary"
|
|
355
|
-
},
|
|
356
|
-
(taskCancelled || clickedToCancel) && !completed ? "Cancelling..." : "Cancel"
|
|
357
|
-
))), /* @__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 })))))));
|
|
358
128
|
};
|
|
359
129
|
|
|
360
|
-
const
|
|
130
|
+
const DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS = [
|
|
131
|
+
{
|
|
132
|
+
component: EntityPicker,
|
|
133
|
+
name: "EntityPicker",
|
|
134
|
+
schema: EntityPickerSchema
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
component: EntityNamePicker,
|
|
138
|
+
name: "EntityNamePicker",
|
|
139
|
+
validation: entityNamePickerValidation,
|
|
140
|
+
schema: EntityNamePickerSchema
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
component: EntityTagsPicker,
|
|
144
|
+
name: "EntityTagsPicker",
|
|
145
|
+
schema: EntityTagsPickerSchema
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
component: RepoUrlPicker,
|
|
149
|
+
name: "RepoUrlPicker",
|
|
150
|
+
validation: repoPickerValidation,
|
|
151
|
+
schema: RepoUrlPickerSchema
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
component: OwnerPicker,
|
|
155
|
+
name: "OwnerPicker",
|
|
156
|
+
schema: OwnerPickerSchema
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
component: OwnedEntityPicker,
|
|
160
|
+
name: "OwnedEntityPicker",
|
|
161
|
+
schema: OwnedEntityPickerSchema
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
component: MyGroupsPicker,
|
|
165
|
+
name: "MyGroupsPicker",
|
|
166
|
+
schema: MyGroupsPickerSchema
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
component: SecretInput,
|
|
170
|
+
name: "Secret"
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
component: MultiEntityPicker,
|
|
174
|
+
name: "MultiEntityPicker",
|
|
175
|
+
schema: MultiEntityPickerSchema,
|
|
176
|
+
validation: validateMultiEntityPickerValidation
|
|
177
|
+
}
|
|
178
|
+
];
|
|
179
|
+
|
|
180
|
+
const useStyles$f = makeStyles((theme) => ({
|
|
361
181
|
code: {
|
|
362
182
|
fontFamily: "Menlo, monospace",
|
|
363
183
|
padding: theme.spacing(1),
|
|
@@ -393,7 +213,17 @@ const ExamplesTable = (props) => {
|
|
|
393
213
|
};
|
|
394
214
|
const ActionsPage = () => {
|
|
395
215
|
const api = useApi(scaffolderApiRef);
|
|
396
|
-
const
|
|
216
|
+
const navigate = useNavigate();
|
|
217
|
+
const editorLink = useRouteRef(editRouteRef);
|
|
218
|
+
const tasksLink = useRouteRef(scaffolderListTaskRouteRef);
|
|
219
|
+
const createLink = useRouteRef(rootRouteRef);
|
|
220
|
+
const scaffolderPageContextMenuProps = {
|
|
221
|
+
onEditorClicked: () => navigate(editorLink()),
|
|
222
|
+
onActionsClicked: void 0,
|
|
223
|
+
onTasksClicked: () => navigate(tasksLink()),
|
|
224
|
+
onCreateClicked: () => navigate(createLink())
|
|
225
|
+
};
|
|
226
|
+
const classes = useStyles$f();
|
|
397
227
|
const { loading, value, error } = useAsync(async () => {
|
|
398
228
|
return api.listActions();
|
|
399
229
|
});
|
|
@@ -497,95 +327,12 @@ const ActionsPage = () => {
|
|
|
497
327
|
pageTitleOverride: "Create a New Component",
|
|
498
328
|
title: "Installed actions",
|
|
499
329
|
subtitle: "This is the collection of all installed actions"
|
|
500
|
-
}
|
|
501
|
-
), /* @__PURE__ */ React.createElement(Content, null, items));
|
|
502
|
-
};
|
|
503
|
-
|
|
504
|
-
const SecretInput = (props) => {
|
|
505
|
-
var _a;
|
|
506
|
-
const { setSecrets, secrets } = useTemplateSecrets();
|
|
507
|
-
const {
|
|
508
|
-
name,
|
|
509
|
-
onChange,
|
|
510
|
-
schema: { title, description },
|
|
511
|
-
rawErrors,
|
|
512
|
-
disabled,
|
|
513
|
-
errors,
|
|
514
|
-
required
|
|
515
|
-
} = props;
|
|
516
|
-
return /* @__PURE__ */ React.createElement(
|
|
517
|
-
ScaffolderField,
|
|
518
|
-
{
|
|
519
|
-
rawErrors,
|
|
520
|
-
rawDescription: description,
|
|
521
|
-
disabled,
|
|
522
|
-
errors,
|
|
523
|
-
required
|
|
524
330
|
},
|
|
525
|
-
/* @__PURE__ */ React.createElement(
|
|
526
|
-
|
|
527
|
-
Input,
|
|
528
|
-
{
|
|
529
|
-
id: title,
|
|
530
|
-
"aria-describedby": title,
|
|
531
|
-
onChange: (e) => {
|
|
532
|
-
var _a2, _b;
|
|
533
|
-
onChange(Array((_a2 = e.target) == null ? void 0 : _a2.value.length).fill("*").join(""));
|
|
534
|
-
setSecrets({ [name]: (_b = e.target) == null ? void 0 : _b.value });
|
|
535
|
-
},
|
|
536
|
-
value: (_a = secrets[name]) != null ? _a : "",
|
|
537
|
-
type: "password",
|
|
538
|
-
autoComplete: "off"
|
|
539
|
-
}
|
|
540
|
-
)
|
|
541
|
-
);
|
|
331
|
+
/* @__PURE__ */ React.createElement(ScaffolderPageContextMenu, { ...scaffolderPageContextMenuProps })
|
|
332
|
+
), /* @__PURE__ */ React.createElement(Content, null, items));
|
|
542
333
|
};
|
|
543
334
|
|
|
544
|
-
const
|
|
545
|
-
{
|
|
546
|
-
component: EntityPicker,
|
|
547
|
-
name: "EntityPicker",
|
|
548
|
-
schema: EntityPickerSchema
|
|
549
|
-
},
|
|
550
|
-
{
|
|
551
|
-
component: EntityNamePicker,
|
|
552
|
-
name: "EntityNamePicker",
|
|
553
|
-
validation: entityNamePickerValidation,
|
|
554
|
-
schema: EntityNamePickerSchema
|
|
555
|
-
},
|
|
556
|
-
{
|
|
557
|
-
component: EntityTagsPicker,
|
|
558
|
-
name: "EntityTagsPicker",
|
|
559
|
-
schema: EntityTagsPickerSchema
|
|
560
|
-
},
|
|
561
|
-
{
|
|
562
|
-
component: RepoUrlPicker,
|
|
563
|
-
name: "RepoUrlPicker",
|
|
564
|
-
validation: repoPickerValidation,
|
|
565
|
-
schema: RepoUrlPickerSchema
|
|
566
|
-
},
|
|
567
|
-
{
|
|
568
|
-
component: OwnerPicker,
|
|
569
|
-
name: "OwnerPicker",
|
|
570
|
-
schema: OwnerPickerSchema
|
|
571
|
-
},
|
|
572
|
-
{
|
|
573
|
-
component: OwnedEntityPicker,
|
|
574
|
-
name: "OwnedEntityPicker",
|
|
575
|
-
schema: OwnedEntityPickerSchema
|
|
576
|
-
},
|
|
577
|
-
{
|
|
578
|
-
component: MyGroupsPicker,
|
|
579
|
-
name: "MyGroupsPicker",
|
|
580
|
-
schema: MyGroupsPickerSchema
|
|
581
|
-
},
|
|
582
|
-
{
|
|
583
|
-
component: SecretInput,
|
|
584
|
-
name: "Secret"
|
|
585
|
-
}
|
|
586
|
-
];
|
|
587
|
-
|
|
588
|
-
const useStyles$8 = makeStyles(
|
|
335
|
+
const useStyles$e = makeStyles(
|
|
589
336
|
(theme) => ({
|
|
590
337
|
root: {
|
|
591
338
|
backgroundColor: "rgba(0, 0, 0, .11)",
|
|
@@ -634,7 +381,7 @@ function getFilterGroups() {
|
|
|
634
381
|
}
|
|
635
382
|
const OwnerListPicker = (props) => {
|
|
636
383
|
const { filter, onSelectOwner } = props;
|
|
637
|
-
const classes = useStyles$
|
|
384
|
+
const classes = useStyles$e();
|
|
638
385
|
const filterGroups = getFilterGroups();
|
|
639
386
|
return /* @__PURE__ */ React.createElement(Card, { className: classes.root }, filterGroups.map((group) => /* @__PURE__ */ React.createElement(Fragment, { key: group.name }, /* @__PURE__ */ React.createElement(
|
|
640
387
|
Typography,
|
|
@@ -793,14 +540,184 @@ const ListTaskPageContent = (props) => {
|
|
|
793
540
|
)));
|
|
794
541
|
};
|
|
795
542
|
const ListTasksPage = (props) => {
|
|
543
|
+
const navigate = useNavigate();
|
|
544
|
+
const editorLink = useRouteRef(editRouteRef);
|
|
545
|
+
const actionsLink = useRouteRef(actionsRouteRef);
|
|
546
|
+
const createLink = useRouteRef(rootRouteRef);
|
|
547
|
+
const scaffolderPageContextMenuProps = {
|
|
548
|
+
onEditorClicked: () => navigate(editorLink()),
|
|
549
|
+
onActionsClicked: () => navigate(actionsLink()),
|
|
550
|
+
onTasksClicked: void 0,
|
|
551
|
+
onCreateClicked: () => navigate(createLink())
|
|
552
|
+
};
|
|
796
553
|
return /* @__PURE__ */ React.createElement(Page, { themeId: "home" }, /* @__PURE__ */ React.createElement(
|
|
797
554
|
Header,
|
|
798
555
|
{
|
|
799
|
-
pageTitleOverride: "Templates Tasks",
|
|
800
|
-
title:
|
|
801
|
-
subtitle: "All tasks that have been started"
|
|
556
|
+
pageTitleOverride: "Templates Tasks",
|
|
557
|
+
title: "List template tasks",
|
|
558
|
+
subtitle: "All tasks that have been started"
|
|
559
|
+
},
|
|
560
|
+
/* @__PURE__ */ React.createElement(ScaffolderPageContextMenu, { ...scaffolderPageContextMenuProps })
|
|
561
|
+
), /* @__PURE__ */ React.createElement(Content, null, /* @__PURE__ */ React.createElement(ListTaskPageContent, { ...props })));
|
|
562
|
+
};
|
|
563
|
+
|
|
564
|
+
const RegisterExistingButton = (props) => {
|
|
565
|
+
const { title, to } = props;
|
|
566
|
+
const { allowed } = usePermission({
|
|
567
|
+
permission: catalogEntityCreatePermission
|
|
568
|
+
});
|
|
569
|
+
const isXSScreen = useMediaQuery(
|
|
570
|
+
(theme) => theme.breakpoints.down("xs")
|
|
571
|
+
);
|
|
572
|
+
if (!to || !allowed) {
|
|
573
|
+
return null;
|
|
574
|
+
}
|
|
575
|
+
return isXSScreen ? /* @__PURE__ */ React.createElement(
|
|
576
|
+
IconButton,
|
|
577
|
+
{
|
|
578
|
+
component: Link$1,
|
|
579
|
+
color: "primary",
|
|
580
|
+
title,
|
|
581
|
+
size: "small",
|
|
582
|
+
to
|
|
583
|
+
},
|
|
584
|
+
/* @__PURE__ */ React.createElement(CreateComponentIcon, null)
|
|
585
|
+
) : /* @__PURE__ */ React.createElement(Button, { component: Link$1, variant: "contained", color: "primary", to }, title);
|
|
586
|
+
};
|
|
587
|
+
|
|
588
|
+
const defaultGroup = {
|
|
589
|
+
title: "Templates",
|
|
590
|
+
filter: () => true
|
|
591
|
+
};
|
|
592
|
+
const createGroupsWithOther = (groups) => [
|
|
593
|
+
...groups,
|
|
594
|
+
{
|
|
595
|
+
title: "Other Templates",
|
|
596
|
+
filter: (e) => ![...groups].some(({ filter }) => filter(e))
|
|
597
|
+
}
|
|
598
|
+
];
|
|
599
|
+
const TemplateListPage = (props) => {
|
|
600
|
+
var _a, _b, _c;
|
|
601
|
+
const registerComponentLink = useRouteRef(registerComponentRouteRef);
|
|
602
|
+
const {
|
|
603
|
+
TemplateCardComponent,
|
|
604
|
+
groups: givenGroups = [],
|
|
605
|
+
templateFilter,
|
|
606
|
+
headerOptions
|
|
607
|
+
} = props;
|
|
608
|
+
const navigate = useNavigate();
|
|
609
|
+
const editorLink = useRouteRef(editRouteRef);
|
|
610
|
+
const actionsLink = useRouteRef(actionsRouteRef);
|
|
611
|
+
const tasksLink = useRouteRef(scaffolderListTaskRouteRef);
|
|
612
|
+
const viewTechDocsLink = useRouteRef(viewTechDocRouteRef);
|
|
613
|
+
const templateRoute = useRouteRef(selectedTemplateRouteRef);
|
|
614
|
+
const app = useApp();
|
|
615
|
+
const groups = givenGroups.length ? createGroupsWithOther(givenGroups) : [defaultGroup];
|
|
616
|
+
const scaffolderPageContextMenuProps = {
|
|
617
|
+
onEditorClicked: ((_a = props == null ? void 0 : props.contextMenu) == null ? void 0 : _a.editor) !== false ? () => navigate(editorLink()) : void 0,
|
|
618
|
+
onActionsClicked: ((_b = props == null ? void 0 : props.contextMenu) == null ? void 0 : _b.actions) !== false ? () => navigate(actionsLink()) : void 0,
|
|
619
|
+
onTasksClicked: ((_c = props == null ? void 0 : props.contextMenu) == null ? void 0 : _c.tasks) !== false ? () => navigate(tasksLink()) : void 0
|
|
620
|
+
};
|
|
621
|
+
const additionalLinksForEntity = useCallback(
|
|
622
|
+
(template) => {
|
|
623
|
+
var _a2, _b2;
|
|
624
|
+
const { kind, namespace, name } = parseEntityRef(
|
|
625
|
+
stringifyEntityRef(template)
|
|
626
|
+
);
|
|
627
|
+
return ((_a2 = template.metadata.annotations) == null ? void 0 : _a2["backstage.io/techdocs-ref"]) && viewTechDocsLink ? [
|
|
628
|
+
{
|
|
629
|
+
icon: (_b2 = app.getSystemIcon("docs")) != null ? _b2 : DocsIcon,
|
|
630
|
+
text: "View TechDocs",
|
|
631
|
+
url: viewTechDocsLink({ kind, namespace, name })
|
|
632
|
+
}
|
|
633
|
+
] : [];
|
|
634
|
+
},
|
|
635
|
+
[app, viewTechDocsLink]
|
|
636
|
+
);
|
|
637
|
+
const onTemplateSelected = useCallback(
|
|
638
|
+
(template) => {
|
|
639
|
+
const { namespace, name } = parseEntityRef(stringifyEntityRef(template));
|
|
640
|
+
navigate(templateRoute({ namespace, templateName: name }));
|
|
641
|
+
},
|
|
642
|
+
[navigate, templateRoute]
|
|
643
|
+
);
|
|
644
|
+
return /* @__PURE__ */ React.createElement(EntityListProvider, null, /* @__PURE__ */ React.createElement(Page, { themeId: "home" }, /* @__PURE__ */ React.createElement(
|
|
645
|
+
Header,
|
|
646
|
+
{
|
|
647
|
+
pageTitleOverride: "Create a new component",
|
|
648
|
+
title: "Create a new component",
|
|
649
|
+
subtitle: "Create new software components using standard templates in your organization",
|
|
650
|
+
...headerOptions
|
|
651
|
+
},
|
|
652
|
+
/* @__PURE__ */ React.createElement(ScaffolderPageContextMenu, { ...scaffolderPageContextMenuProps })
|
|
653
|
+
), /* @__PURE__ */ React.createElement(Content, null, /* @__PURE__ */ React.createElement(ContentHeader, { title: "Available Templates" }, /* @__PURE__ */ React.createElement(
|
|
654
|
+
RegisterExistingButton,
|
|
655
|
+
{
|
|
656
|
+
title: "Register Existing Component",
|
|
657
|
+
to: registerComponentLink && registerComponentLink()
|
|
658
|
+
}
|
|
659
|
+
), /* @__PURE__ */ React.createElement(SupportButton, null, "Create new software components using standard templates. Different templates create different kinds of components (services, websites, documentation, ...).")), /* @__PURE__ */ React.createElement(CatalogFilterLayout, null, /* @__PURE__ */ React.createElement(CatalogFilterLayout.Filters, null, /* @__PURE__ */ React.createElement(EntitySearchBar, null), /* @__PURE__ */ React.createElement(EntityKindPicker, { initialFilter: "template", hidden: true }), /* @__PURE__ */ React.createElement(
|
|
660
|
+
UserListPicker,
|
|
661
|
+
{
|
|
662
|
+
initialFilter: "all",
|
|
663
|
+
availableFilters: ["all", "starred"]
|
|
664
|
+
}
|
|
665
|
+
), /* @__PURE__ */ React.createElement(TemplateCategoryPicker, null), /* @__PURE__ */ React.createElement(EntityTagPicker, null)), /* @__PURE__ */ React.createElement(CatalogFilterLayout.Content, null, /* @__PURE__ */ React.createElement(
|
|
666
|
+
TemplateGroups,
|
|
667
|
+
{
|
|
668
|
+
groups,
|
|
669
|
+
templateFilter,
|
|
670
|
+
TemplateCardComponent,
|
|
671
|
+
onTemplateSelected,
|
|
672
|
+
additionalLinksForEntity
|
|
673
|
+
}
|
|
674
|
+
))))));
|
|
675
|
+
};
|
|
676
|
+
|
|
677
|
+
const TemplateWizardPage = (props) => {
|
|
678
|
+
const rootRef = useRouteRef(rootRouteRef);
|
|
679
|
+
const taskRoute = useRouteRef(scaffolderTaskRouteRef);
|
|
680
|
+
const { secrets } = useTemplateSecrets();
|
|
681
|
+
const scaffolderApi = useApi(scaffolderApiRef);
|
|
682
|
+
const navigate = useNavigate();
|
|
683
|
+
const { templateName, namespace } = useRouteRefParams(
|
|
684
|
+
selectedTemplateRouteRef
|
|
685
|
+
);
|
|
686
|
+
const templateRef = stringifyEntityRef({
|
|
687
|
+
kind: "Template",
|
|
688
|
+
namespace,
|
|
689
|
+
name: templateName
|
|
690
|
+
});
|
|
691
|
+
const onCreate = async (values) => {
|
|
692
|
+
const { taskId } = await scaffolderApi.scaffold({
|
|
693
|
+
templateRef,
|
|
694
|
+
values,
|
|
695
|
+
secrets
|
|
696
|
+
});
|
|
697
|
+
navigate(taskRoute({ taskId }));
|
|
698
|
+
};
|
|
699
|
+
const onError = () => /* @__PURE__ */ React.createElement(Navigate, { to: rootRef() });
|
|
700
|
+
return /* @__PURE__ */ React.createElement(AnalyticsContext, { attributes: { entityRef: templateRef } }, /* @__PURE__ */ React.createElement(Page, { themeId: "website" }, /* @__PURE__ */ React.createElement(
|
|
701
|
+
Header,
|
|
702
|
+
{
|
|
703
|
+
pageTitleOverride: "Create a new component",
|
|
704
|
+
title: "Create a new component",
|
|
705
|
+
subtitle: "Create new software components using standard templates in your organization",
|
|
706
|
+
...props.headerOptions
|
|
802
707
|
}
|
|
803
|
-
), /* @__PURE__ */ React.createElement(
|
|
708
|
+
), /* @__PURE__ */ React.createElement(
|
|
709
|
+
Workflow,
|
|
710
|
+
{
|
|
711
|
+
namespace,
|
|
712
|
+
templateName,
|
|
713
|
+
onCreate,
|
|
714
|
+
components: props.components,
|
|
715
|
+
onError,
|
|
716
|
+
extensions: props.customFieldExtensions,
|
|
717
|
+
formProps: props.formProps,
|
|
718
|
+
layouts: props.layouts
|
|
719
|
+
}
|
|
720
|
+
)));
|
|
804
721
|
};
|
|
805
722
|
|
|
806
723
|
const showDirectoryPicker = window.showDirectoryPicker;
|
|
@@ -857,91 +774,113 @@ class WebFileSystemAccess {
|
|
|
857
774
|
}
|
|
858
775
|
}
|
|
859
776
|
|
|
860
|
-
const
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
position: "relative",
|
|
867
|
-
maxWidth: 340,
|
|
868
|
-
marginTop: theme.spacing(4),
|
|
869
|
-
margin: theme.spacing(0, 2)
|
|
870
|
-
},
|
|
871
|
-
infoIcon: {
|
|
872
|
-
position: "absolute",
|
|
873
|
-
top: theme.spacing(1),
|
|
874
|
-
right: theme.spacing(1)
|
|
777
|
+
const MAX_CONTENT_SIZE = 64 * 1024;
|
|
778
|
+
const CHUNK_SIZE = 32 * 1024;
|
|
779
|
+
const DryRunContext = createContext(void 0);
|
|
780
|
+
function base64EncodeContent(content) {
|
|
781
|
+
if (content.length > MAX_CONTENT_SIZE) {
|
|
782
|
+
return window.btoa("<file too large>");
|
|
875
783
|
}
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
{
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
784
|
+
try {
|
|
785
|
+
return window.btoa(content);
|
|
786
|
+
} catch {
|
|
787
|
+
const decoder = new TextEncoder();
|
|
788
|
+
const buffer = decoder.encode(content);
|
|
789
|
+
const chunks = new Array();
|
|
790
|
+
for (let offset = 0; offset < buffer.length; offset += CHUNK_SIZE) {
|
|
791
|
+
chunks.push(
|
|
792
|
+
String.fromCharCode(...buffer.slice(offset, offset + CHUNK_SIZE))
|
|
793
|
+
);
|
|
794
|
+
}
|
|
795
|
+
return window.btoa(chunks.join(""));
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
function DryRunProvider(props) {
|
|
799
|
+
const scaffolderApi = useApi(scaffolderApiRef);
|
|
800
|
+
const [state, setState] = useState({
|
|
801
|
+
results: [],
|
|
802
|
+
selectedResult: void 0
|
|
803
|
+
});
|
|
804
|
+
const idRef = useRef(1);
|
|
805
|
+
const selectResult = useCallback((id) => {
|
|
806
|
+
setState((prevState) => {
|
|
807
|
+
const result = prevState.results.find((r) => r.id === id);
|
|
808
|
+
if (result === prevState.selectedResult) {
|
|
809
|
+
return prevState;
|
|
887
810
|
}
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
/* @__PURE__ */ React.createElement(InfoOutlinedIcon, null)
|
|
914
|
-
)));
|
|
915
|
-
const cardFormEditor = /* @__PURE__ */ React.createElement(Card$1, { className: classes.card, elevation: 4 }, /* @__PURE__ */ React.createElement(CardActionArea, { onClick: () => {
|
|
916
|
-
var _a;
|
|
917
|
-
return (_a = props.onSelect) == null ? void 0 : _a.call(props, "form");
|
|
918
|
-
} }, /* @__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."))));
|
|
919
|
-
const cardFieldExplorer = /* @__PURE__ */ React.createElement(Card$1, { className: classes.card, elevation: 4 }, /* @__PURE__ */ React.createElement(CardActionArea, { onClick: () => {
|
|
920
|
-
var _a;
|
|
921
|
-
return (_a = props.onSelect) == null ? void 0 : _a.call(props, "field-explorer");
|
|
922
|
-
} }, /* @__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."))));
|
|
923
|
-
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(
|
|
924
|
-
"div",
|
|
925
|
-
{
|
|
926
|
-
style: {
|
|
927
|
-
display: "flex",
|
|
928
|
-
flexFlow: "row wrap",
|
|
929
|
-
alignItems: "flex-start",
|
|
930
|
-
justifyContent: "center",
|
|
931
|
-
alignContent: "flex-start"
|
|
811
|
+
return {
|
|
812
|
+
results: prevState.results,
|
|
813
|
+
selectedResult: result
|
|
814
|
+
};
|
|
815
|
+
});
|
|
816
|
+
}, []);
|
|
817
|
+
const deleteResult = useCallback((id) => {
|
|
818
|
+
setState((prevState) => {
|
|
819
|
+
var _a;
|
|
820
|
+
const index = prevState.results.findIndex((r) => r.id === id);
|
|
821
|
+
if (index === -1) {
|
|
822
|
+
return prevState;
|
|
823
|
+
}
|
|
824
|
+
const newResults = prevState.results.slice();
|
|
825
|
+
const [deleted] = newResults.splice(index, 1);
|
|
826
|
+
return {
|
|
827
|
+
results: newResults,
|
|
828
|
+
selectedResult: ((_a = prevState.selectedResult) == null ? void 0 : _a.id) === deleted.id ? newResults[0] : prevState.selectedResult
|
|
829
|
+
};
|
|
830
|
+
});
|
|
831
|
+
}, []);
|
|
832
|
+
const execute = useCallback(
|
|
833
|
+
async (options) => {
|
|
834
|
+
if (!scaffolderApi.dryRun) {
|
|
835
|
+
throw new Error("Scaffolder API does not support dry-run");
|
|
932
836
|
}
|
|
837
|
+
const parsed = yaml.parse(options.templateContent);
|
|
838
|
+
const response = await scaffolderApi.dryRun({
|
|
839
|
+
template: parsed,
|
|
840
|
+
values: options.values,
|
|
841
|
+
secrets: {},
|
|
842
|
+
directoryContents: options.files.map((file) => ({
|
|
843
|
+
path: file.path,
|
|
844
|
+
base64Content: base64EncodeContent(file.content)
|
|
845
|
+
}))
|
|
846
|
+
});
|
|
847
|
+
const result = {
|
|
848
|
+
...response,
|
|
849
|
+
id: idRef.current++
|
|
850
|
+
};
|
|
851
|
+
setState((prevState) => {
|
|
852
|
+
var _a;
|
|
853
|
+
return {
|
|
854
|
+
results: [...prevState.results, result],
|
|
855
|
+
selectedResult: (_a = prevState.selectedResult) != null ? _a : result
|
|
856
|
+
};
|
|
857
|
+
});
|
|
933
858
|
},
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
859
|
+
[scaffolderApi]
|
|
860
|
+
);
|
|
861
|
+
const dryRun = useMemo(
|
|
862
|
+
() => ({
|
|
863
|
+
...state,
|
|
864
|
+
selectResult,
|
|
865
|
+
deleteResult,
|
|
866
|
+
execute
|
|
867
|
+
}),
|
|
868
|
+
[state, selectResult, deleteResult, execute]
|
|
869
|
+
);
|
|
870
|
+
return /* @__PURE__ */ React.createElement(DryRunContext.Provider, { value: dryRun }, props.children);
|
|
871
|
+
}
|
|
872
|
+
function useDryRun() {
|
|
873
|
+
const value = useContext(DryRunContext);
|
|
874
|
+
if (!value) {
|
|
875
|
+
throw new Error("must be used within a DryRunProvider");
|
|
876
|
+
}
|
|
877
|
+
return value;
|
|
939
878
|
}
|
|
940
879
|
|
|
941
|
-
var __defProp = Object.defineProperty;
|
|
942
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
943
|
-
var __publicField = (obj, key, value) => {
|
|
944
|
-
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
880
|
+
var __defProp$1 = Object.defineProperty;
|
|
881
|
+
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
882
|
+
var __publicField$1 = (obj, key, value) => {
|
|
883
|
+
__defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
945
884
|
return value;
|
|
946
885
|
};
|
|
947
886
|
var __accessCheck = (obj, member, msg) => {
|
|
@@ -1026,7 +965,7 @@ class DirectoryEditorManager {
|
|
|
1026
965
|
__privateAdd(this, _listeners, /* @__PURE__ */ new Set());
|
|
1027
966
|
__privateAdd(this, _files, []);
|
|
1028
967
|
__privateAdd(this, _selectedFile, void 0);
|
|
1029
|
-
__publicField(this, "setSelectedFile", (path) => {
|
|
968
|
+
__publicField$1(this, "setSelectedFile", (path) => {
|
|
1030
969
|
const prev = __privateGet(this, _selectedFile);
|
|
1031
970
|
const next = __privateGet(this, _files).find((file) => file.path === path);
|
|
1032
971
|
if (prev !== next) {
|
|
@@ -1118,110 +1057,299 @@ function DirectoryEditorProvider(props) {
|
|
|
1118
1057
|
return /* @__PURE__ */ React.createElement(DirectoryEditorContext.Provider, { value: result }, props.children);
|
|
1119
1058
|
}
|
|
1120
1059
|
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1060
|
+
var __defProp = Object.defineProperty;
|
|
1061
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1062
|
+
var __publicField = (obj, key, value) => {
|
|
1063
|
+
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1064
|
+
return value;
|
|
1065
|
+
};
|
|
1066
|
+
const useStyles$d = makeStyles$1({
|
|
1067
|
+
containerWrapper: {
|
|
1068
|
+
position: "relative",
|
|
1069
|
+
width: "100%",
|
|
1070
|
+
height: "100%"
|
|
1071
|
+
},
|
|
1072
|
+
container: {
|
|
1073
|
+
position: "absolute",
|
|
1074
|
+
top: 0,
|
|
1075
|
+
bottom: 0,
|
|
1076
|
+
left: 0,
|
|
1077
|
+
right: 0,
|
|
1078
|
+
overflow: "auto"
|
|
1127
1079
|
}
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1080
|
+
});
|
|
1081
|
+
class ErrorBoundary extends Component {
|
|
1082
|
+
constructor() {
|
|
1083
|
+
super(...arguments);
|
|
1084
|
+
__publicField(this, "state", {
|
|
1085
|
+
shouldRender: true
|
|
1086
|
+
});
|
|
1087
|
+
}
|
|
1088
|
+
componentDidUpdate(prevProps) {
|
|
1089
|
+
if (prevProps.invalidator !== this.props.invalidator) {
|
|
1090
|
+
this.setState({ shouldRender: true });
|
|
1138
1091
|
}
|
|
1139
|
-
return window.btoa(chunks.join(""));
|
|
1140
1092
|
}
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
}
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
}
|
|
1161
|
-
const
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1093
|
+
componentDidCatch(error) {
|
|
1094
|
+
this.props.setErrorText(error.message);
|
|
1095
|
+
this.setState({ shouldRender: false });
|
|
1096
|
+
}
|
|
1097
|
+
render() {
|
|
1098
|
+
return this.state.shouldRender ? this.props.children : null;
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
function isJsonObject(value) {
|
|
1102
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1103
|
+
}
|
|
1104
|
+
function TemplateEditorForm(props) {
|
|
1105
|
+
const {
|
|
1106
|
+
content,
|
|
1107
|
+
contentIsSpec,
|
|
1108
|
+
onDryRun,
|
|
1109
|
+
setErrorText,
|
|
1110
|
+
fieldExtensions = [],
|
|
1111
|
+
layouts = []
|
|
1112
|
+
} = props;
|
|
1113
|
+
const classes = useStyles$d();
|
|
1114
|
+
const apiHolder = useApiHolder();
|
|
1115
|
+
const [steps, setSteps] = useState();
|
|
1116
|
+
const fields = useMemo(() => {
|
|
1117
|
+
return Object.fromEntries(
|
|
1118
|
+
fieldExtensions.map(({ name, component }) => [name, component])
|
|
1119
|
+
);
|
|
1120
|
+
}, [fieldExtensions]);
|
|
1121
|
+
useDebounce(
|
|
1122
|
+
() => {
|
|
1123
|
+
try {
|
|
1124
|
+
if (!content) {
|
|
1125
|
+
setSteps(void 0);
|
|
1126
|
+
return;
|
|
1127
|
+
}
|
|
1128
|
+
const parsed = yaml.parseAllDocuments(content).filter((c) => c).map((c) => c.toJSON())[0];
|
|
1129
|
+
if (!isJsonObject(parsed)) {
|
|
1130
|
+
setSteps(void 0);
|
|
1131
|
+
return;
|
|
1132
|
+
}
|
|
1133
|
+
let rootObj = parsed;
|
|
1134
|
+
if (!contentIsSpec) {
|
|
1135
|
+
const isTemplate = String(parsed.kind).toLocaleLowerCase("en-US") === "template";
|
|
1136
|
+
if (!isTemplate) {
|
|
1137
|
+
setSteps(void 0);
|
|
1138
|
+
return;
|
|
1139
|
+
}
|
|
1140
|
+
rootObj = isJsonObject(parsed.spec) ? parsed.spec : {};
|
|
1141
|
+
}
|
|
1142
|
+
const { parameters } = rootObj;
|
|
1143
|
+
if (!Array.isArray(parameters)) {
|
|
1144
|
+
setErrorText("Template parameters must be an array");
|
|
1145
|
+
setSteps(void 0);
|
|
1146
|
+
return;
|
|
1147
|
+
}
|
|
1148
|
+
const fieldValidators = Object.fromEntries(
|
|
1149
|
+
fieldExtensions.map(({ name, validation }) => [name, validation])
|
|
1150
|
+
);
|
|
1151
|
+
setErrorText();
|
|
1152
|
+
setSteps(
|
|
1153
|
+
parameters.flatMap(
|
|
1154
|
+
(param) => isJsonObject(param) ? [
|
|
1155
|
+
{
|
|
1156
|
+
title: String(param.title),
|
|
1157
|
+
schema: param,
|
|
1158
|
+
validate: createAsyncValidators(param, fieldValidators, {
|
|
1159
|
+
apiHolder
|
|
1160
|
+
})
|
|
1161
|
+
}
|
|
1162
|
+
] : []
|
|
1163
|
+
)
|
|
1164
|
+
);
|
|
1165
|
+
} catch (e) {
|
|
1166
|
+
setErrorText(e.message);
|
|
1180
1167
|
}
|
|
1181
|
-
const parsed = yaml.parse(options.templateContent);
|
|
1182
|
-
const response = await scaffolderApi.dryRun({
|
|
1183
|
-
template: parsed,
|
|
1184
|
-
values: options.values,
|
|
1185
|
-
secrets: {},
|
|
1186
|
-
directoryContents: options.files.map((file) => ({
|
|
1187
|
-
path: file.path,
|
|
1188
|
-
base64Content: base64EncodeContent(file.content)
|
|
1189
|
-
}))
|
|
1190
|
-
});
|
|
1191
|
-
const result = {
|
|
1192
|
-
...response,
|
|
1193
|
-
id: idRef.current++
|
|
1194
|
-
};
|
|
1195
|
-
setState((prevState) => {
|
|
1196
|
-
var _a;
|
|
1197
|
-
return {
|
|
1198
|
-
results: [...prevState.results, result],
|
|
1199
|
-
selectedResult: (_a = prevState.selectedResult) != null ? _a : result
|
|
1200
|
-
};
|
|
1201
|
-
});
|
|
1202
1168
|
},
|
|
1203
|
-
|
|
1169
|
+
250,
|
|
1170
|
+
[contentIsSpec, content, apiHolder]
|
|
1204
1171
|
);
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1172
|
+
if (!steps) {
|
|
1173
|
+
return null;
|
|
1174
|
+
}
|
|
1175
|
+
return /* @__PURE__ */ React.createElement("div", { className: classes.containerWrapper }, /* @__PURE__ */ React.createElement("div", { className: classes.container }, /* @__PURE__ */ React.createElement(ErrorBoundary, { invalidator: steps, setErrorText }, /* @__PURE__ */ React.createElement(
|
|
1176
|
+
Stepper,
|
|
1177
|
+
{
|
|
1178
|
+
manifest: { steps, title: "Template Editor" },
|
|
1179
|
+
extensions: fieldExtensions,
|
|
1180
|
+
components: fields,
|
|
1181
|
+
onCreate: async (options) => {
|
|
1182
|
+
await (onDryRun == null ? void 0 : onDryRun(options));
|
|
1183
|
+
},
|
|
1184
|
+
layouts
|
|
1185
|
+
}
|
|
1186
|
+
))));
|
|
1187
|
+
}
|
|
1188
|
+
function TemplateEditorFormDirectoryEditorDryRun(props) {
|
|
1189
|
+
const { setErrorText, fieldExtensions = [], layouts } = props;
|
|
1190
|
+
const dryRun = useDryRun();
|
|
1191
|
+
const directoryEditor = useDirectoryEditor();
|
|
1192
|
+
const { selectedFile } = directoryEditor;
|
|
1193
|
+
const handleDryRun = async (data) => {
|
|
1194
|
+
if (!selectedFile) {
|
|
1195
|
+
return;
|
|
1196
|
+
}
|
|
1197
|
+
try {
|
|
1198
|
+
await dryRun.execute({
|
|
1199
|
+
templateContent: selectedFile.content,
|
|
1200
|
+
values: data,
|
|
1201
|
+
files: directoryEditor.files
|
|
1202
|
+
});
|
|
1203
|
+
setErrorText();
|
|
1204
|
+
} catch (e) {
|
|
1205
|
+
setErrorText(String(e.cause || e));
|
|
1206
|
+
throw e;
|
|
1207
|
+
}
|
|
1208
|
+
};
|
|
1209
|
+
const content = selectedFile && selectedFile.path.match(/\.ya?ml$/) ? selectedFile.content : void 0;
|
|
1210
|
+
return /* @__PURE__ */ React.createElement(
|
|
1211
|
+
TemplateEditorForm,
|
|
1212
|
+
{
|
|
1213
|
+
onDryRun: handleDryRun,
|
|
1214
|
+
fieldExtensions,
|
|
1215
|
+
setErrorText,
|
|
1216
|
+
content,
|
|
1217
|
+
layouts
|
|
1218
|
+
}
|
|
1213
1219
|
);
|
|
1214
|
-
return /* @__PURE__ */ React.createElement(DryRunContext.Provider, { value: dryRun }, props.children);
|
|
1215
1220
|
}
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1221
|
+
TemplateEditorForm.DirectoryEditorDryRun = TemplateEditorFormDirectoryEditorDryRun;
|
|
1222
|
+
|
|
1223
|
+
const useStyles$c = makeStyles((theme) => ({
|
|
1224
|
+
root: {
|
|
1225
|
+
gridArea: "pageContent",
|
|
1226
|
+
display: "grid",
|
|
1227
|
+
gridTemplateAreas: `
|
|
1228
|
+
"controls controls"
|
|
1229
|
+
"fieldForm preview"
|
|
1230
|
+
`,
|
|
1231
|
+
gridTemplateRows: "auto 1fr",
|
|
1232
|
+
gridTemplateColumns: "1fr 1fr"
|
|
1233
|
+
},
|
|
1234
|
+
controls: {
|
|
1235
|
+
gridArea: "controls",
|
|
1236
|
+
display: "flex",
|
|
1237
|
+
flexFlow: "row nowrap",
|
|
1238
|
+
alignItems: "center",
|
|
1239
|
+
margin: theme.spacing(1)
|
|
1240
|
+
},
|
|
1241
|
+
fieldForm: {
|
|
1242
|
+
gridArea: "fieldForm"
|
|
1243
|
+
},
|
|
1244
|
+
preview: {
|
|
1245
|
+
gridArea: "preview"
|
|
1220
1246
|
}
|
|
1221
|
-
|
|
1222
|
-
|
|
1247
|
+
}));
|
|
1248
|
+
const CustomFieldExplorer = ({
|
|
1249
|
+
customFieldExtensions = [],
|
|
1250
|
+
onClose
|
|
1251
|
+
}) => {
|
|
1252
|
+
var _a, _b;
|
|
1253
|
+
const classes = useStyles$c();
|
|
1254
|
+
const fieldOptions = customFieldExtensions.filter((field) => !!field.schema);
|
|
1255
|
+
const [selectedField, setSelectedField] = useState(fieldOptions[0]);
|
|
1256
|
+
const [fieldFormState, setFieldFormState] = useState({});
|
|
1257
|
+
const [refreshKey, setRefreshKey] = useState(Date.now());
|
|
1258
|
+
const sampleFieldTemplate = useMemo(
|
|
1259
|
+
() => {
|
|
1260
|
+
var _a2, _b2;
|
|
1261
|
+
return yaml.stringify({
|
|
1262
|
+
parameters: [
|
|
1263
|
+
{
|
|
1264
|
+
title: `${selectedField.name} Example`,
|
|
1265
|
+
properties: {
|
|
1266
|
+
[selectedField.name]: {
|
|
1267
|
+
type: (_b2 = (_a2 = selectedField.schema) == null ? void 0 : _a2.returnValue) == null ? void 0 : _b2.type,
|
|
1268
|
+
"ui:field": selectedField.name,
|
|
1269
|
+
"ui:options": fieldFormState
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
]
|
|
1274
|
+
});
|
|
1275
|
+
},
|
|
1276
|
+
[fieldFormState, selectedField]
|
|
1277
|
+
);
|
|
1278
|
+
const fieldComponents = useMemo(() => {
|
|
1279
|
+
return Object.fromEntries(
|
|
1280
|
+
customFieldExtensions.map(({ name, component }) => [name, component])
|
|
1281
|
+
);
|
|
1282
|
+
}, [customFieldExtensions]);
|
|
1283
|
+
const handleSelectionChange = useCallback(
|
|
1284
|
+
(selection) => {
|
|
1285
|
+
setSelectedField(selection);
|
|
1286
|
+
setFieldFormState({});
|
|
1287
|
+
},
|
|
1288
|
+
[setFieldFormState, setSelectedField]
|
|
1289
|
+
);
|
|
1290
|
+
const handleFieldConfigChange = useCallback(
|
|
1291
|
+
(state) => {
|
|
1292
|
+
setFieldFormState(state);
|
|
1293
|
+
setRefreshKey(Date.now());
|
|
1294
|
+
},
|
|
1295
|
+
[setFieldFormState, setRefreshKey]
|
|
1296
|
+
);
|
|
1297
|
+
return /* @__PURE__ */ React.createElement("main", { className: classes.root }, /* @__PURE__ */ React.createElement("div", { className: classes.controls }, /* @__PURE__ */ React.createElement(FormControl, { variant: "outlined", size: "small", fullWidth: true }, /* @__PURE__ */ React.createElement(InputLabel, { id: "select-field-label" }, "Choose Custom Field Extension"), /* @__PURE__ */ React.createElement(
|
|
1298
|
+
Select,
|
|
1299
|
+
{
|
|
1300
|
+
value: selectedField,
|
|
1301
|
+
label: "Choose Custom Field Extension",
|
|
1302
|
+
labelId: "select-field-label",
|
|
1303
|
+
onChange: (e) => handleSelectionChange(e.target.value)
|
|
1304
|
+
},
|
|
1305
|
+
fieldOptions.map((option, idx) => /* @__PURE__ */ React.createElement(MenuItem, { key: idx, value: option }, option.name))
|
|
1306
|
+
)), /* @__PURE__ */ React.createElement(IconButton$1, { size: "medium", onClick: onClose, "aria-label": "Close" }, /* @__PURE__ */ React.createElement(CloseIcon, null))), /* @__PURE__ */ React.createElement("div", { className: classes.fieldForm }, /* @__PURE__ */ React.createElement(Card, null, /* @__PURE__ */ React.createElement(CardHeader, { title: "Field Options" }), /* @__PURE__ */ React.createElement(CardContent, null, /* @__PURE__ */ React.createElement(
|
|
1307
|
+
Form,
|
|
1308
|
+
{
|
|
1309
|
+
showErrorList: false,
|
|
1310
|
+
fields: { ...fieldComponents },
|
|
1311
|
+
noHtml5Validate: true,
|
|
1312
|
+
formData: fieldFormState,
|
|
1313
|
+
formContext: { fieldFormState },
|
|
1314
|
+
onSubmit: (e) => handleFieldConfigChange(e.formData),
|
|
1315
|
+
validator,
|
|
1316
|
+
schema: ((_a = selectedField.schema) == null ? void 0 : _a.uiOptions) || {},
|
|
1317
|
+
experimental_defaultFormStateBehavior: {
|
|
1318
|
+
allOf: "populateDefaults"
|
|
1319
|
+
}
|
|
1320
|
+
},
|
|
1321
|
+
/* @__PURE__ */ React.createElement(
|
|
1322
|
+
Button$1,
|
|
1323
|
+
{
|
|
1324
|
+
variant: "contained",
|
|
1325
|
+
color: "primary",
|
|
1326
|
+
type: "submit",
|
|
1327
|
+
disabled: !((_b = selectedField.schema) == null ? void 0 : _b.uiOptions)
|
|
1328
|
+
},
|
|
1329
|
+
"Apply"
|
|
1330
|
+
)
|
|
1331
|
+
)))), /* @__PURE__ */ React.createElement("div", { className: classes.preview }, /* @__PURE__ */ React.createElement(Card, null, /* @__PURE__ */ React.createElement(CardHeader, { title: "Example Template Spec" }), /* @__PURE__ */ React.createElement(CardContent, null, /* @__PURE__ */ React.createElement(
|
|
1332
|
+
CodeMirror,
|
|
1333
|
+
{
|
|
1334
|
+
readOnly: true,
|
|
1335
|
+
theme: "dark",
|
|
1336
|
+
height: "100%",
|
|
1337
|
+
extensions: [StreamLanguage.define(yaml$1)],
|
|
1338
|
+
value: sampleFieldTemplate
|
|
1339
|
+
}
|
|
1340
|
+
))), /* @__PURE__ */ React.createElement(
|
|
1341
|
+
TemplateEditorForm,
|
|
1342
|
+
{
|
|
1343
|
+
key: refreshKey,
|
|
1344
|
+
content: sampleFieldTemplate,
|
|
1345
|
+
contentIsSpec: true,
|
|
1346
|
+
fieldExtensions: customFieldExtensions,
|
|
1347
|
+
setErrorText: () => null
|
|
1348
|
+
}
|
|
1349
|
+
)));
|
|
1350
|
+
};
|
|
1223
1351
|
|
|
1224
|
-
const useStyles$
|
|
1352
|
+
const useStyles$b = makeStyles$1({
|
|
1225
1353
|
root: {
|
|
1226
1354
|
whiteSpace: "nowrap",
|
|
1227
1355
|
overflowY: "auto"
|
|
@@ -1280,7 +1408,7 @@ function FileTreeItem({ entry }) {
|
|
|
1280
1408
|
return /* @__PURE__ */ React.createElement(TreeItem, { nodeId: entry.path, label: entry.name }, entry.children.map((child) => /* @__PURE__ */ React.createElement(FileTreeItem, { key: child.path, entry: child })));
|
|
1281
1409
|
}
|
|
1282
1410
|
function FileBrowser(props) {
|
|
1283
|
-
const classes = useStyles$
|
|
1411
|
+
const classes = useStyles$b();
|
|
1284
1412
|
const fileTree = useMemo(
|
|
1285
1413
|
() => parseFileEntires(props.filePaths),
|
|
1286
1414
|
[props.filePaths]
|
|
@@ -1302,7 +1430,7 @@ function FileBrowser(props) {
|
|
|
1302
1430
|
);
|
|
1303
1431
|
}
|
|
1304
1432
|
|
|
1305
|
-
const useStyles$
|
|
1433
|
+
const useStyles$a = makeStyles((theme) => ({
|
|
1306
1434
|
button: {
|
|
1307
1435
|
padding: theme.spacing(1)
|
|
1308
1436
|
},
|
|
@@ -1321,7 +1449,7 @@ const useStyles$5 = makeStyles((theme) => ({
|
|
|
1321
1449
|
}));
|
|
1322
1450
|
function TemplateEditorBrowser(props) {
|
|
1323
1451
|
var _a, _b;
|
|
1324
|
-
const classes = useStyles$
|
|
1452
|
+
const classes = useStyles$a();
|
|
1325
1453
|
const directoryEditor = useDirectoryEditor();
|
|
1326
1454
|
const changedFiles = directoryEditor.files.filter((file) => file.dirty);
|
|
1327
1455
|
const handleClose = () => {
|
|
@@ -1338,22 +1466,22 @@ function TemplateEditorBrowser(props) {
|
|
|
1338
1466
|
}
|
|
1339
1467
|
props.onClose();
|
|
1340
1468
|
};
|
|
1341
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { className: classes.buttons }, /* @__PURE__ */ React.createElement(Tooltip
|
|
1342
|
-
IconButton,
|
|
1469
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { className: classes.buttons }, /* @__PURE__ */ React.createElement(Tooltip, { title: "Save all files" }, /* @__PURE__ */ React.createElement(
|
|
1470
|
+
IconButton$1,
|
|
1343
1471
|
{
|
|
1344
1472
|
className: classes.button,
|
|
1345
1473
|
disabled: directoryEditor.files.every((file) => !file.dirty),
|
|
1346
1474
|
onClick: () => directoryEditor.save()
|
|
1347
1475
|
},
|
|
1348
1476
|
/* @__PURE__ */ React.createElement(SaveIcon, null)
|
|
1349
|
-
)), /* @__PURE__ */ React.createElement(Tooltip
|
|
1350
|
-
IconButton,
|
|
1477
|
+
)), /* @__PURE__ */ React.createElement(Tooltip, { title: "Reload directory" }, /* @__PURE__ */ React.createElement(
|
|
1478
|
+
IconButton$1,
|
|
1351
1479
|
{
|
|
1352
1480
|
className: classes.button,
|
|
1353
1481
|
onClick: () => directoryEditor.reload()
|
|
1354
1482
|
},
|
|
1355
1483
|
/* @__PURE__ */ React.createElement(RefreshIcon, null)
|
|
1356
|
-
)), /* @__PURE__ */ React.createElement("div", { className: classes.buttonsGap }), /* @__PURE__ */ React.createElement(Tooltip
|
|
1484
|
+
)), /* @__PURE__ */ React.createElement("div", { className: classes.buttonsGap }), /* @__PURE__ */ React.createElement(Tooltip, { title: "Close directory" }, /* @__PURE__ */ React.createElement(IconButton$1, { className: classes.button, onClick: handleClose }, /* @__PURE__ */ React.createElement(CloseIcon, null)))), /* @__PURE__ */ React.createElement(Divider, { className: classes.buttonsDivider }), /* @__PURE__ */ React.createElement(
|
|
1357
1485
|
FileBrowser,
|
|
1358
1486
|
{
|
|
1359
1487
|
selected: (_b = (_a = directoryEditor.selectedFile) == null ? void 0 : _a.path) != null ? _b : "",
|
|
@@ -1363,7 +1491,7 @@ function TemplateEditorBrowser(props) {
|
|
|
1363
1491
|
));
|
|
1364
1492
|
}
|
|
1365
1493
|
|
|
1366
|
-
const useStyles$
|
|
1494
|
+
const useStyles$9 = makeStyles((theme) => ({
|
|
1367
1495
|
container: {
|
|
1368
1496
|
position: "relative",
|
|
1369
1497
|
width: "100%",
|
|
@@ -1392,7 +1520,7 @@ const useStyles$4 = makeStyles((theme) => ({
|
|
|
1392
1520
|
}));
|
|
1393
1521
|
function TemplateEditorTextArea(props) {
|
|
1394
1522
|
const { errorText } = props;
|
|
1395
|
-
const classes = useStyles$
|
|
1523
|
+
const classes = useStyles$9();
|
|
1396
1524
|
const panelExtension = useMemo(() => {
|
|
1397
1525
|
if (!errorText) {
|
|
1398
1526
|
return showPanel.of(null);
|
|
@@ -1421,8 +1549,8 @@ function TemplateEditorTextArea(props) {
|
|
|
1421
1549
|
value: props.content,
|
|
1422
1550
|
onChange: props.onUpdate
|
|
1423
1551
|
}
|
|
1424
|
-
), (props.onSave || props.onReload) && /* @__PURE__ */ React.createElement("div", { className: classes.floatingButtons }, /* @__PURE__ */ React.createElement(Paper, null, props.onSave && /* @__PURE__ */ React.createElement(Tooltip
|
|
1425
|
-
IconButton,
|
|
1552
|
+
), (props.onSave || props.onReload) && /* @__PURE__ */ React.createElement("div", { className: classes.floatingButtons }, /* @__PURE__ */ React.createElement(Paper, null, props.onSave && /* @__PURE__ */ React.createElement(Tooltip, { title: "Save file" }, /* @__PURE__ */ React.createElement(
|
|
1553
|
+
IconButton$1,
|
|
1426
1554
|
{
|
|
1427
1555
|
className: classes.floatingButton,
|
|
1428
1556
|
onClick: () => {
|
|
@@ -1431,8 +1559,8 @@ function TemplateEditorTextArea(props) {
|
|
|
1431
1559
|
}
|
|
1432
1560
|
},
|
|
1433
1561
|
/* @__PURE__ */ React.createElement(SaveIcon, null)
|
|
1434
|
-
)), props.onReload && /* @__PURE__ */ React.createElement(Tooltip
|
|
1435
|
-
IconButton,
|
|
1562
|
+
)), props.onReload && /* @__PURE__ */ React.createElement(Tooltip, { title: "Reload file" }, /* @__PURE__ */ React.createElement(
|
|
1563
|
+
IconButton$1,
|
|
1436
1564
|
{
|
|
1437
1565
|
className: classes.floatingButton,
|
|
1438
1566
|
onClick: () => {
|
|
@@ -1476,7 +1604,7 @@ function downloadBlob(blob, name) {
|
|
|
1476
1604
|
a.remove();
|
|
1477
1605
|
}
|
|
1478
1606
|
|
|
1479
|
-
const useStyles$
|
|
1607
|
+
const useStyles$8 = makeStyles$1((theme) => ({
|
|
1480
1608
|
root: {
|
|
1481
1609
|
overflowY: "auto",
|
|
1482
1610
|
background: theme.palette.background.default
|
|
@@ -1493,7 +1621,7 @@ const useStyles$3 = makeStyles$1((theme) => ({
|
|
|
1493
1621
|
}
|
|
1494
1622
|
}));
|
|
1495
1623
|
function DryRunResultsList() {
|
|
1496
|
-
const classes = useStyles$
|
|
1624
|
+
const classes = useStyles$8();
|
|
1497
1625
|
const dryRun = useDryRun();
|
|
1498
1626
|
return /* @__PURE__ */ React.createElement(List$1, { className: classes.root, dense: true }, dryRun.results.map((result) => {
|
|
1499
1627
|
var _a;
|
|
@@ -1520,11 +1648,11 @@ function DryRunResultsList() {
|
|
|
1520
1648
|
{
|
|
1521
1649
|
className: failed ? classes.iconFailure : classes.iconSuccess
|
|
1522
1650
|
},
|
|
1523
|
-
failed ? /* @__PURE__ */ React.createElement(Cancel, null) : /* @__PURE__ */ React.createElement(
|
|
1651
|
+
failed ? /* @__PURE__ */ React.createElement(Cancel, null) : /* @__PURE__ */ React.createElement(CheckIcon, null)
|
|
1524
1652
|
),
|
|
1525
1653
|
/* @__PURE__ */ React.createElement(ListItemText$1, { primary: `Result ${result.id}` }),
|
|
1526
1654
|
/* @__PURE__ */ React.createElement(ListItemSecondaryAction, null, /* @__PURE__ */ React.createElement(
|
|
1527
|
-
IconButton
|
|
1655
|
+
IconButton,
|
|
1528
1656
|
{
|
|
1529
1657
|
edge: "end",
|
|
1530
1658
|
"aria-label": "download",
|
|
@@ -1534,7 +1662,7 @@ function DryRunResultsList() {
|
|
|
1534
1662
|
},
|
|
1535
1663
|
/* @__PURE__ */ React.createElement(DownloadIcon, null)
|
|
1536
1664
|
), /* @__PURE__ */ React.createElement(
|
|
1537
|
-
IconButton
|
|
1665
|
+
IconButton,
|
|
1538
1666
|
{
|
|
1539
1667
|
edge: "end",
|
|
1540
1668
|
"aria-label": "delete",
|
|
@@ -1556,32 +1684,195 @@ async function downloadDirectoryContents(directoryContents, name) {
|
|
|
1556
1684
|
const blob = await zip.generateAsync({ type: "blob" });
|
|
1557
1685
|
downloadBlob(blob, name);
|
|
1558
1686
|
}
|
|
1559
|
-
|
|
1560
|
-
const useStyles$
|
|
1561
|
-
root: {
|
|
1562
|
-
display: "grid",
|
|
1563
|
-
gridTemplateColumns: "280px auto 3fr",
|
|
1564
|
-
gridTemplateRows: "1fr"
|
|
1565
|
-
},
|
|
1566
|
-
child: {
|
|
1567
|
-
overflowY: "auto",
|
|
1568
|
-
height: "100%",
|
|
1569
|
-
minHeight: 0
|
|
1570
|
-
},
|
|
1571
|
-
firstChild: {
|
|
1572
|
-
background: theme.palette.background.paper
|
|
1573
|
-
}
|
|
1574
|
-
}));
|
|
1575
|
-
function DryRunResultsSplitView(props) {
|
|
1576
|
-
const classes = useStyles$
|
|
1577
|
-
const childArray = Children.toArray(props.children);
|
|
1578
|
-
if (childArray.length !== 2) {
|
|
1579
|
-
throw new Error("must have exactly 2 children");
|
|
1687
|
+
|
|
1688
|
+
const useStyles$7 = makeStyles$1((theme) => ({
|
|
1689
|
+
root: {
|
|
1690
|
+
display: "grid",
|
|
1691
|
+
gridTemplateColumns: "280px auto 3fr",
|
|
1692
|
+
gridTemplateRows: "1fr"
|
|
1693
|
+
},
|
|
1694
|
+
child: {
|
|
1695
|
+
overflowY: "auto",
|
|
1696
|
+
height: "100%",
|
|
1697
|
+
minHeight: 0
|
|
1698
|
+
},
|
|
1699
|
+
firstChild: {
|
|
1700
|
+
background: theme.palette.background.paper
|
|
1701
|
+
}
|
|
1702
|
+
}));
|
|
1703
|
+
function DryRunResultsSplitView(props) {
|
|
1704
|
+
const classes = useStyles$7();
|
|
1705
|
+
const childArray = Children.toArray(props.children);
|
|
1706
|
+
if (childArray.length !== 2) {
|
|
1707
|
+
throw new Error("must have exactly 2 children");
|
|
1708
|
+
}
|
|
1709
|
+
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]));
|
|
1710
|
+
}
|
|
1711
|
+
|
|
1712
|
+
const useStyles$6 = makeStyles({
|
|
1713
|
+
svgIcon: {
|
|
1714
|
+
display: "inline-block",
|
|
1715
|
+
"& svg": {
|
|
1716
|
+
display: "inline-block",
|
|
1717
|
+
fontSize: "inherit",
|
|
1718
|
+
verticalAlign: "baseline"
|
|
1719
|
+
}
|
|
1720
|
+
}
|
|
1721
|
+
});
|
|
1722
|
+
const IconLink = (props) => {
|
|
1723
|
+
const { href, text, Icon, ...linkProps } = props;
|
|
1724
|
+
const classes = useStyles$6();
|
|
1725
|
+
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)));
|
|
1726
|
+
};
|
|
1727
|
+
|
|
1728
|
+
const TaskPageLinks = ({ output }) => {
|
|
1729
|
+
const { links = [] } = output;
|
|
1730
|
+
const app = useApp();
|
|
1731
|
+
const entityRoute = useRouteRef(entityRouteRef);
|
|
1732
|
+
const iconResolver = (key) => {
|
|
1733
|
+
var _a;
|
|
1734
|
+
return key ? (_a = app.getSystemIcon(key)) != null ? _a : LanguageIcon : LanguageIcon;
|
|
1735
|
+
};
|
|
1736
|
+
return /* @__PURE__ */ React.createElement(Box, { px: 3, pb: 3 }, links.filter(({ url, entityRef }) => url || entityRef).map(({ url, entityRef, title, icon }) => {
|
|
1737
|
+
if (entityRef) {
|
|
1738
|
+
const entityName = parseEntityRef(entityRef, {
|
|
1739
|
+
defaultKind: "<unknown>",
|
|
1740
|
+
defaultNamespace: "<unknown>"
|
|
1741
|
+
});
|
|
1742
|
+
const target = entityRoute(entityName);
|
|
1743
|
+
return { title, icon, url: target };
|
|
1744
|
+
}
|
|
1745
|
+
return { title, icon, url };
|
|
1746
|
+
}).map(({ url, title, icon }, i) => /* @__PURE__ */ React.createElement(
|
|
1747
|
+
IconLink,
|
|
1748
|
+
{
|
|
1749
|
+
key: `output-link-${i}`,
|
|
1750
|
+
href: url,
|
|
1751
|
+
text: title != null ? title : url,
|
|
1752
|
+
Icon: iconResolver(icon),
|
|
1753
|
+
target: "_blank"
|
|
1754
|
+
}
|
|
1755
|
+
)));
|
|
1756
|
+
};
|
|
1757
|
+
|
|
1758
|
+
const useStyles$5 = makeStyles(
|
|
1759
|
+
(theme) => createStyles({
|
|
1760
|
+
root: {
|
|
1761
|
+
width: "100%"
|
|
1762
|
+
},
|
|
1763
|
+
button: {
|
|
1764
|
+
marginBottom: theme.spacing(2),
|
|
1765
|
+
marginLeft: theme.spacing(2)
|
|
1766
|
+
},
|
|
1767
|
+
actionsContainer: {
|
|
1768
|
+
marginBottom: theme.spacing(2)
|
|
1769
|
+
},
|
|
1770
|
+
resetContainer: {
|
|
1771
|
+
padding: theme.spacing(3)
|
|
1772
|
+
},
|
|
1773
|
+
labelWrapper: {
|
|
1774
|
+
display: "flex",
|
|
1775
|
+
flex: 1,
|
|
1776
|
+
flexDirection: "row",
|
|
1777
|
+
justifyContent: "space-between"
|
|
1778
|
+
},
|
|
1779
|
+
stepWrapper: {
|
|
1780
|
+
width: "100%"
|
|
1781
|
+
}
|
|
1782
|
+
})
|
|
1783
|
+
);
|
|
1784
|
+
const useStepIconStyles = makeStyles(
|
|
1785
|
+
(theme) => createStyles({
|
|
1786
|
+
root: {
|
|
1787
|
+
color: theme.palette.text.disabled,
|
|
1788
|
+
display: "flex",
|
|
1789
|
+
height: 22,
|
|
1790
|
+
alignItems: "center"
|
|
1791
|
+
},
|
|
1792
|
+
completed: {
|
|
1793
|
+
color: theme.palette.status.ok
|
|
1794
|
+
},
|
|
1795
|
+
error: {
|
|
1796
|
+
color: theme.palette.status.error
|
|
1797
|
+
}
|
|
1798
|
+
})
|
|
1799
|
+
);
|
|
1800
|
+
const StepTimeTicker = ({ step }) => {
|
|
1801
|
+
const [time, setTime] = useState("");
|
|
1802
|
+
useInterval(() => {
|
|
1803
|
+
if (!step.startedAt) {
|
|
1804
|
+
setTime("");
|
|
1805
|
+
return;
|
|
1806
|
+
}
|
|
1807
|
+
const end = step.endedAt ? DateTime.fromISO(step.endedAt) : DateTime.local();
|
|
1808
|
+
const startedAt = DateTime.fromISO(step.startedAt);
|
|
1809
|
+
const formatted = Interval.fromDateTimes(startedAt, end).toDuration().valueOf();
|
|
1810
|
+
setTime(humanizeDuration(formatted, { round: true }));
|
|
1811
|
+
}, 1e3);
|
|
1812
|
+
return /* @__PURE__ */ React.createElement(Typography$1, { variant: "caption" }, time);
|
|
1813
|
+
};
|
|
1814
|
+
function TaskStepIconComponent(props) {
|
|
1815
|
+
const classes = useStepIconStyles();
|
|
1816
|
+
const { active, completed, error } = props;
|
|
1817
|
+
const getMiddle = () => {
|
|
1818
|
+
if (active) {
|
|
1819
|
+
return /* @__PURE__ */ React.createElement(CircularProgress, { size: "24px" });
|
|
1820
|
+
}
|
|
1821
|
+
if (completed) {
|
|
1822
|
+
return /* @__PURE__ */ React.createElement(CheckIcon, null);
|
|
1823
|
+
}
|
|
1824
|
+
if (error) {
|
|
1825
|
+
return /* @__PURE__ */ React.createElement(Cancel, null);
|
|
1826
|
+
}
|
|
1827
|
+
return /* @__PURE__ */ React.createElement(FiberManualRecordIcon, null);
|
|
1828
|
+
};
|
|
1829
|
+
return /* @__PURE__ */ React.createElement(
|
|
1830
|
+
"div",
|
|
1831
|
+
{
|
|
1832
|
+
className: classNames(classes.root, {
|
|
1833
|
+
[classes.completed]: completed,
|
|
1834
|
+
[classes.error]: error
|
|
1835
|
+
})
|
|
1836
|
+
},
|
|
1837
|
+
getMiddle()
|
|
1838
|
+
);
|
|
1839
|
+
}
|
|
1840
|
+
const TaskStatusStepper = memo(
|
|
1841
|
+
(props) => {
|
|
1842
|
+
const { steps, currentStepId, onUserStepChange } = props;
|
|
1843
|
+
const classes = useStyles$5(props);
|
|
1844
|
+
return /* @__PURE__ */ React.createElement("div", { className: classes.root }, /* @__PURE__ */ React.createElement(
|
|
1845
|
+
Stepper$1,
|
|
1846
|
+
{
|
|
1847
|
+
activeStep: steps.findIndex((s) => s.id === currentStepId),
|
|
1848
|
+
orientation: "vertical",
|
|
1849
|
+
nonLinear: true
|
|
1850
|
+
},
|
|
1851
|
+
steps.map((step, index) => {
|
|
1852
|
+
const isCancelled = step.status === "cancelled";
|
|
1853
|
+
const isActive = step.status === "processing";
|
|
1854
|
+
const isCompleted = step.status === "completed";
|
|
1855
|
+
const isFailed = step.status === "failed";
|
|
1856
|
+
const isSkipped = step.status === "skipped";
|
|
1857
|
+
return /* @__PURE__ */ React.createElement(Step, { key: String(index), expanded: true }, /* @__PURE__ */ React.createElement(StepButton, { onClick: () => onUserStepChange(step.id) }, /* @__PURE__ */ React.createElement(
|
|
1858
|
+
StepLabel,
|
|
1859
|
+
{
|
|
1860
|
+
StepIconProps: {
|
|
1861
|
+
completed: isCompleted,
|
|
1862
|
+
error: isFailed || isCancelled,
|
|
1863
|
+
active: isActive
|
|
1864
|
+
},
|
|
1865
|
+
StepIconComponent: TaskStepIconComponent,
|
|
1866
|
+
className: classes.stepWrapper
|
|
1867
|
+
},
|
|
1868
|
+
/* @__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 }))
|
|
1869
|
+
)));
|
|
1870
|
+
})
|
|
1871
|
+
));
|
|
1580
1872
|
}
|
|
1581
|
-
|
|
1582
|
-
}
|
|
1873
|
+
);
|
|
1583
1874
|
|
|
1584
|
-
const useStyles$
|
|
1875
|
+
const useStyles$4 = makeStyles$1({
|
|
1585
1876
|
root: {
|
|
1586
1877
|
display: "flex",
|
|
1587
1878
|
flexFlow: "column nowrap"
|
|
@@ -1607,7 +1898,7 @@ const useStyles$1 = makeStyles$1({
|
|
|
1607
1898
|
}
|
|
1608
1899
|
});
|
|
1609
1900
|
function FilesContent() {
|
|
1610
|
-
const classes = useStyles$
|
|
1901
|
+
const classes = useStyles$4();
|
|
1611
1902
|
const { selectedResult } = useDryRun();
|
|
1612
1903
|
const [selectedPath, setSelectedPath] = useState("");
|
|
1613
1904
|
const selectedFile = selectedResult == null ? void 0 : selectedResult.directoryContents.find(
|
|
@@ -1683,7 +1974,7 @@ function LogContent() {
|
|
|
1683
1974
|
}
|
|
1684
1975
|
function OutputContent() {
|
|
1685
1976
|
var _a, _b;
|
|
1686
|
-
const classes = useStyles$
|
|
1977
|
+
const classes = useStyles$4();
|
|
1687
1978
|
const { selectedResult } = useDryRun();
|
|
1688
1979
|
if (!selectedResult) {
|
|
1689
1980
|
return null;
|
|
@@ -1701,14 +1992,14 @@ function OutputContent() {
|
|
|
1701
1992
|
));
|
|
1702
1993
|
}
|
|
1703
1994
|
function DryRunResultsView() {
|
|
1704
|
-
const classes = useStyles$
|
|
1995
|
+
const classes = useStyles$4();
|
|
1705
1996
|
const [selectedTab, setSelectedTab] = useState(
|
|
1706
1997
|
"files"
|
|
1707
1998
|
);
|
|
1708
1999
|
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))));
|
|
1709
2000
|
}
|
|
1710
2001
|
|
|
1711
|
-
const useStyles = makeStyles$1((theme) => ({
|
|
2002
|
+
const useStyles$3 = makeStyles$1((theme) => ({
|
|
1712
2003
|
header: {
|
|
1713
2004
|
height: 48,
|
|
1714
2005
|
minHeight: 0,
|
|
@@ -1727,7 +2018,7 @@ const useStyles = makeStyles$1((theme) => ({
|
|
|
1727
2018
|
}
|
|
1728
2019
|
}));
|
|
1729
2020
|
function DryRunResults() {
|
|
1730
|
-
const classes = useStyles();
|
|
2021
|
+
const classes = useStyles$3();
|
|
1731
2022
|
const dryRun = useDryRun();
|
|
1732
2023
|
const [expanded, setExpanded] = useState(false);
|
|
1733
2024
|
const [hidden, setHidden] = useState(true);
|
|
@@ -1763,5 +2054,427 @@ function DryRunResults() {
|
|
|
1763
2054
|
));
|
|
1764
2055
|
}
|
|
1765
2056
|
|
|
1766
|
-
|
|
1767
|
-
|
|
2057
|
+
const useStyles$2 = makeStyles({
|
|
2058
|
+
// Reset and fix sizing to make sure scrolling behaves correctly
|
|
2059
|
+
root: {
|
|
2060
|
+
gridArea: "pageContent",
|
|
2061
|
+
display: "grid",
|
|
2062
|
+
gridTemplateAreas: `
|
|
2063
|
+
"browser editor preview"
|
|
2064
|
+
"results results results"
|
|
2065
|
+
`,
|
|
2066
|
+
gridTemplateColumns: "1fr 3fr 2fr",
|
|
2067
|
+
gridTemplateRows: "1fr auto"
|
|
2068
|
+
},
|
|
2069
|
+
browser: {
|
|
2070
|
+
gridArea: "browser",
|
|
2071
|
+
overflow: "auto"
|
|
2072
|
+
},
|
|
2073
|
+
editor: {
|
|
2074
|
+
gridArea: "editor",
|
|
2075
|
+
overflow: "auto"
|
|
2076
|
+
},
|
|
2077
|
+
preview: {
|
|
2078
|
+
gridArea: "preview",
|
|
2079
|
+
overflow: "auto"
|
|
2080
|
+
},
|
|
2081
|
+
results: {
|
|
2082
|
+
gridArea: "results"
|
|
2083
|
+
}
|
|
2084
|
+
});
|
|
2085
|
+
const TemplateEditor = (props) => {
|
|
2086
|
+
const classes = useStyles$2();
|
|
2087
|
+
const [errorText, setErrorText] = useState();
|
|
2088
|
+
return /* @__PURE__ */ React.createElement(DirectoryEditorProvider, { directory: props.directory }, /* @__PURE__ */ React.createElement(DryRunProvider, null, /* @__PURE__ */ React.createElement("main", { className: classes.root }, /* @__PURE__ */ React.createElement("section", { className: classes.browser }, /* @__PURE__ */ React.createElement(TemplateEditorBrowser, { onClose: props.onClose })), /* @__PURE__ */ React.createElement("section", { className: classes.editor }, /* @__PURE__ */ React.createElement(TemplateEditorTextArea.DirectoryEditor, { errorText })), /* @__PURE__ */ React.createElement("section", { className: classes.preview }, /* @__PURE__ */ React.createElement(
|
|
2089
|
+
TemplateEditorForm.DirectoryEditorDryRun,
|
|
2090
|
+
{
|
|
2091
|
+
setErrorText,
|
|
2092
|
+
fieldExtensions: props.fieldExtensions,
|
|
2093
|
+
layouts: props.layouts
|
|
2094
|
+
}
|
|
2095
|
+
)), /* @__PURE__ */ React.createElement("section", { className: classes.results }, /* @__PURE__ */ React.createElement(DryRunResults, null)))));
|
|
2096
|
+
};
|
|
2097
|
+
|
|
2098
|
+
const EXAMPLE_TEMPLATE_PARAMS_YAML = `# Edit the template parameters below to see how they will render in the scaffolder form UI
|
|
2099
|
+
parameters:
|
|
2100
|
+
- title: Fill in some steps
|
|
2101
|
+
required:
|
|
2102
|
+
- name
|
|
2103
|
+
properties:
|
|
2104
|
+
name:
|
|
2105
|
+
title: Name
|
|
2106
|
+
type: string
|
|
2107
|
+
description: Unique name of the component
|
|
2108
|
+
owner:
|
|
2109
|
+
title: Owner
|
|
2110
|
+
type: string
|
|
2111
|
+
description: Owner of the component
|
|
2112
|
+
ui:field: OwnerPicker
|
|
2113
|
+
ui:options:
|
|
2114
|
+
catalogFilter:
|
|
2115
|
+
kind: Group
|
|
2116
|
+
- title: Choose a location
|
|
2117
|
+
required:
|
|
2118
|
+
- repoUrl
|
|
2119
|
+
properties:
|
|
2120
|
+
repoUrl:
|
|
2121
|
+
title: Repository Location
|
|
2122
|
+
type: string
|
|
2123
|
+
ui:field: RepoUrlPicker
|
|
2124
|
+
ui:options:
|
|
2125
|
+
allowedHosts:
|
|
2126
|
+
- github.com
|
|
2127
|
+
steps:
|
|
2128
|
+
- id: fetch-base
|
|
2129
|
+
name: Fetch Base
|
|
2130
|
+
action: fetch:template
|
|
2131
|
+
input:
|
|
2132
|
+
url: ./template
|
|
2133
|
+
values:
|
|
2134
|
+
name: \${{parameters.name}}
|
|
2135
|
+
`;
|
|
2136
|
+
const useStyles$1 = makeStyles((theme) => ({
|
|
2137
|
+
root: {
|
|
2138
|
+
gridArea: "pageContent",
|
|
2139
|
+
display: "grid",
|
|
2140
|
+
gridTemplateAreas: `
|
|
2141
|
+
"controls controls"
|
|
2142
|
+
"textArea preview"
|
|
2143
|
+
`,
|
|
2144
|
+
gridTemplateRows: "auto 1fr",
|
|
2145
|
+
gridTemplateColumns: "1fr 1fr"
|
|
2146
|
+
},
|
|
2147
|
+
controls: {
|
|
2148
|
+
gridArea: "controls",
|
|
2149
|
+
display: "flex",
|
|
2150
|
+
flexFlow: "row nowrap",
|
|
2151
|
+
alignItems: "center",
|
|
2152
|
+
margin: theme.spacing(1)
|
|
2153
|
+
},
|
|
2154
|
+
textArea: {
|
|
2155
|
+
gridArea: "textArea"
|
|
2156
|
+
},
|
|
2157
|
+
preview: {
|
|
2158
|
+
gridArea: "preview"
|
|
2159
|
+
}
|
|
2160
|
+
}));
|
|
2161
|
+
const TemplateFormPreviewer = ({
|
|
2162
|
+
defaultPreviewTemplate = EXAMPLE_TEMPLATE_PARAMS_YAML,
|
|
2163
|
+
customFieldExtensions = [],
|
|
2164
|
+
onClose,
|
|
2165
|
+
layouts = []
|
|
2166
|
+
}) => {
|
|
2167
|
+
const classes = useStyles$1();
|
|
2168
|
+
const alertApi = useApi(alertApiRef);
|
|
2169
|
+
const catalogApi = useApi(catalogApiRef);
|
|
2170
|
+
const [selectedTemplate, setSelectedTemplate] = useState("");
|
|
2171
|
+
const [errorText, setErrorText] = useState();
|
|
2172
|
+
const [templateOptions, setTemplateOptions] = useState([]);
|
|
2173
|
+
const [templateYaml, setTemplateYaml] = useState(defaultPreviewTemplate);
|
|
2174
|
+
const { loading } = useAsync(
|
|
2175
|
+
() => catalogApi.getEntities({
|
|
2176
|
+
filter: { kind: "template" },
|
|
2177
|
+
fields: [
|
|
2178
|
+
"kind",
|
|
2179
|
+
"metadata.namespace",
|
|
2180
|
+
"metadata.name",
|
|
2181
|
+
"metadata.title",
|
|
2182
|
+
"spec.parameters",
|
|
2183
|
+
"spec.steps",
|
|
2184
|
+
"spec.output"
|
|
2185
|
+
]
|
|
2186
|
+
}).then(
|
|
2187
|
+
({ items }) => setTemplateOptions(
|
|
2188
|
+
items.map((template) => {
|
|
2189
|
+
var _a;
|
|
2190
|
+
return {
|
|
2191
|
+
label: (_a = template.metadata.title) != null ? _a : humanizeEntityRef(template, { defaultKind: "template" }),
|
|
2192
|
+
value: template
|
|
2193
|
+
};
|
|
2194
|
+
})
|
|
2195
|
+
)
|
|
2196
|
+
).catch(
|
|
2197
|
+
(e) => alertApi.post({
|
|
2198
|
+
message: `Error loading exisiting templates: ${e.message}`,
|
|
2199
|
+
severity: "error"
|
|
2200
|
+
})
|
|
2201
|
+
),
|
|
2202
|
+
[catalogApi]
|
|
2203
|
+
);
|
|
2204
|
+
const handleSelectChange = useCallback(
|
|
2205
|
+
// TODO(Rugvip): Afaik this should be Entity, but didn't want to make runtime changes while fixing types
|
|
2206
|
+
(selected) => {
|
|
2207
|
+
setSelectedTemplate(selected);
|
|
2208
|
+
setTemplateYaml(yaml.stringify(selected.spec));
|
|
2209
|
+
},
|
|
2210
|
+
[setTemplateYaml]
|
|
2211
|
+
);
|
|
2212
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, loading && /* @__PURE__ */ React.createElement(LinearProgress, null), /* @__PURE__ */ React.createElement("main", { className: classes.root }, /* @__PURE__ */ React.createElement("div", { className: classes.controls }, /* @__PURE__ */ React.createElement(FormControl, { variant: "outlined", size: "small", fullWidth: true }, /* @__PURE__ */ React.createElement(InputLabel, { id: "select-template-label" }, "Load Existing Template"), /* @__PURE__ */ React.createElement(
|
|
2213
|
+
Select,
|
|
2214
|
+
{
|
|
2215
|
+
value: selectedTemplate,
|
|
2216
|
+
label: "Load Existing Template",
|
|
2217
|
+
labelId: "select-template-label",
|
|
2218
|
+
onChange: (e) => handleSelectChange(e.target.value)
|
|
2219
|
+
},
|
|
2220
|
+
templateOptions.map((option, idx) => /* @__PURE__ */ React.createElement(MenuItem, { key: idx, value: option.value }, option.label))
|
|
2221
|
+
)), /* @__PURE__ */ React.createElement(IconButton$1, { size: "medium", onClick: onClose }, /* @__PURE__ */ React.createElement(CloseIcon, null))), /* @__PURE__ */ React.createElement("div", { className: classes.textArea }, /* @__PURE__ */ React.createElement(
|
|
2222
|
+
TemplateEditorTextArea,
|
|
2223
|
+
{
|
|
2224
|
+
content: templateYaml,
|
|
2225
|
+
onUpdate: setTemplateYaml,
|
|
2226
|
+
errorText
|
|
2227
|
+
}
|
|
2228
|
+
)), /* @__PURE__ */ React.createElement("div", { className: classes.preview }, /* @__PURE__ */ React.createElement(
|
|
2229
|
+
TemplateEditorForm,
|
|
2230
|
+
{
|
|
2231
|
+
content: templateYaml,
|
|
2232
|
+
contentIsSpec: true,
|
|
2233
|
+
fieldExtensions: customFieldExtensions,
|
|
2234
|
+
setErrorText,
|
|
2235
|
+
layouts
|
|
2236
|
+
}
|
|
2237
|
+
))));
|
|
2238
|
+
};
|
|
2239
|
+
|
|
2240
|
+
const useStyles = makeStyles$1((theme) => ({
|
|
2241
|
+
introText: {
|
|
2242
|
+
textAlign: "center",
|
|
2243
|
+
marginTop: theme.spacing(2)
|
|
2244
|
+
},
|
|
2245
|
+
card: {
|
|
2246
|
+
position: "relative",
|
|
2247
|
+
maxWidth: 340,
|
|
2248
|
+
marginTop: theme.spacing(4),
|
|
2249
|
+
margin: theme.spacing(0, 2)
|
|
2250
|
+
},
|
|
2251
|
+
infoIcon: {
|
|
2252
|
+
position: "absolute",
|
|
2253
|
+
top: theme.spacing(1),
|
|
2254
|
+
right: theme.spacing(1)
|
|
2255
|
+
}
|
|
2256
|
+
}));
|
|
2257
|
+
function TemplateEditorIntro(props) {
|
|
2258
|
+
const classes = useStyles();
|
|
2259
|
+
const supportsLoad = WebFileSystemAccess.isSupported();
|
|
2260
|
+
const cardLoadLocal = /* @__PURE__ */ React.createElement(Card$1, { className: classes.card, elevation: 4 }, /* @__PURE__ */ React.createElement(
|
|
2261
|
+
CardActionArea,
|
|
2262
|
+
{
|
|
2263
|
+
disabled: !supportsLoad,
|
|
2264
|
+
onClick: () => {
|
|
2265
|
+
var _a;
|
|
2266
|
+
return (_a = props.onSelect) == null ? void 0 : _a.call(props, "local");
|
|
2267
|
+
}
|
|
2268
|
+
},
|
|
2269
|
+
/* @__PURE__ */ React.createElement(CardContent$1, null, /* @__PURE__ */ React.createElement(
|
|
2270
|
+
Typography$1,
|
|
2271
|
+
{
|
|
2272
|
+
variant: "h4",
|
|
2273
|
+
component: "h3",
|
|
2274
|
+
gutterBottom: true,
|
|
2275
|
+
color: supportsLoad ? void 0 : "textSecondary",
|
|
2276
|
+
style: { display: "flex", flexFlow: "row nowrap" }
|
|
2277
|
+
},
|
|
2278
|
+
"Load Template Directory"
|
|
2279
|
+
), /* @__PURE__ */ React.createElement(
|
|
2280
|
+
Typography$1,
|
|
2281
|
+
{
|
|
2282
|
+
variant: "body1",
|
|
2283
|
+
color: supportsLoad ? void 0 : "textSecondary"
|
|
2284
|
+
},
|
|
2285
|
+
"Load a local template directory, allowing you to both edit and try executing your own template."
|
|
2286
|
+
))
|
|
2287
|
+
), !supportsLoad && /* @__PURE__ */ React.createElement("div", { className: classes.infoIcon }, /* @__PURE__ */ React.createElement(
|
|
2288
|
+
Tooltip$1,
|
|
2289
|
+
{
|
|
2290
|
+
placement: "top",
|
|
2291
|
+
title: "Only supported in some Chromium-based browsers"
|
|
2292
|
+
},
|
|
2293
|
+
/* @__PURE__ */ React.createElement(InfoOutlinedIcon, null)
|
|
2294
|
+
)));
|
|
2295
|
+
const cardFormEditor = /* @__PURE__ */ React.createElement(Card$1, { className: classes.card, elevation: 4 }, /* @__PURE__ */ React.createElement(CardActionArea, { onClick: () => {
|
|
2296
|
+
var _a;
|
|
2297
|
+
return (_a = props.onSelect) == null ? void 0 : _a.call(props, "form");
|
|
2298
|
+
} }, /* @__PURE__ */ React.createElement(CardContent$1, 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."))));
|
|
2299
|
+
const cardFieldExplorer = /* @__PURE__ */ React.createElement(Card$1, { className: classes.card, elevation: 4 }, /* @__PURE__ */ React.createElement(CardActionArea, { onClick: () => {
|
|
2300
|
+
var _a;
|
|
2301
|
+
return (_a = props.onSelect) == null ? void 0 : _a.call(props, "field-explorer");
|
|
2302
|
+
} }, /* @__PURE__ */ React.createElement(CardContent$1, 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."))));
|
|
2303
|
+
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(
|
|
2304
|
+
"div",
|
|
2305
|
+
{
|
|
2306
|
+
style: {
|
|
2307
|
+
display: "flex",
|
|
2308
|
+
flexFlow: "row wrap",
|
|
2309
|
+
alignItems: "flex-start",
|
|
2310
|
+
justifyContent: "center",
|
|
2311
|
+
alignContent: "flex-start"
|
|
2312
|
+
}
|
|
2313
|
+
},
|
|
2314
|
+
supportsLoad && cardLoadLocal,
|
|
2315
|
+
cardFormEditor,
|
|
2316
|
+
!supportsLoad && cardLoadLocal,
|
|
2317
|
+
cardFieldExplorer
|
|
2318
|
+
));
|
|
2319
|
+
}
|
|
2320
|
+
|
|
2321
|
+
function TemplateEditorPage(props) {
|
|
2322
|
+
const [selection, setSelection] = useState();
|
|
2323
|
+
const navigate = useNavigate();
|
|
2324
|
+
const actionsLink = useRouteRef(actionsRouteRef);
|
|
2325
|
+
const tasksLink = useRouteRef(scaffolderListTaskRouteRef);
|
|
2326
|
+
const createLink = useRouteRef(rootRouteRef);
|
|
2327
|
+
const scaffolderPageContextMenuProps = {
|
|
2328
|
+
onEditorClicked: void 0,
|
|
2329
|
+
onActionsClicked: () => navigate(actionsLink()),
|
|
2330
|
+
onTasksClicked: () => navigate(tasksLink()),
|
|
2331
|
+
onCreateClicked: () => navigate(createLink())
|
|
2332
|
+
};
|
|
2333
|
+
let content = null;
|
|
2334
|
+
if ((selection == null ? void 0 : selection.type) === "local") {
|
|
2335
|
+
content = /* @__PURE__ */ React.createElement(
|
|
2336
|
+
TemplateEditor,
|
|
2337
|
+
{
|
|
2338
|
+
directory: selection.directory,
|
|
2339
|
+
fieldExtensions: props.customFieldExtensions,
|
|
2340
|
+
onClose: () => setSelection(void 0),
|
|
2341
|
+
layouts: props.layouts
|
|
2342
|
+
}
|
|
2343
|
+
);
|
|
2344
|
+
} else if ((selection == null ? void 0 : selection.type) === "form") {
|
|
2345
|
+
content = /* @__PURE__ */ React.createElement(
|
|
2346
|
+
TemplateFormPreviewer,
|
|
2347
|
+
{
|
|
2348
|
+
defaultPreviewTemplate: props.defaultPreviewTemplate,
|
|
2349
|
+
customFieldExtensions: props.customFieldExtensions,
|
|
2350
|
+
onClose: () => setSelection(void 0),
|
|
2351
|
+
layouts: props.layouts
|
|
2352
|
+
}
|
|
2353
|
+
);
|
|
2354
|
+
} else if ((selection == null ? void 0 : selection.type) === "field-explorer") {
|
|
2355
|
+
content = /* @__PURE__ */ React.createElement(
|
|
2356
|
+
CustomFieldExplorer,
|
|
2357
|
+
{
|
|
2358
|
+
customFieldExtensions: props.customFieldExtensions,
|
|
2359
|
+
onClose: () => setSelection(void 0)
|
|
2360
|
+
}
|
|
2361
|
+
);
|
|
2362
|
+
} else {
|
|
2363
|
+
content = /* @__PURE__ */ React.createElement(Content, null, /* @__PURE__ */ React.createElement(
|
|
2364
|
+
TemplateEditorIntro,
|
|
2365
|
+
{
|
|
2366
|
+
onSelect: (option) => {
|
|
2367
|
+
if (option === "local") {
|
|
2368
|
+
WebFileSystemAccess.requestDirectoryAccess().then((directory) => setSelection({ type: "local", directory })).catch(() => {
|
|
2369
|
+
});
|
|
2370
|
+
} else if (option === "form") {
|
|
2371
|
+
setSelection({ type: "form" });
|
|
2372
|
+
} else if (option === "field-explorer") {
|
|
2373
|
+
setSelection({ type: "field-explorer" });
|
|
2374
|
+
}
|
|
2375
|
+
}
|
|
2376
|
+
}
|
|
2377
|
+
));
|
|
2378
|
+
}
|
|
2379
|
+
return /* @__PURE__ */ React.createElement(Page, { themeId: "home" }, /* @__PURE__ */ React.createElement(
|
|
2380
|
+
Header,
|
|
2381
|
+
{
|
|
2382
|
+
title: "Template Editor",
|
|
2383
|
+
subtitle: "Edit, preview, and try out templates and template forms"
|
|
2384
|
+
},
|
|
2385
|
+
/* @__PURE__ */ React.createElement(ScaffolderPageContextMenu, { ...scaffolderPageContextMenuProps })
|
|
2386
|
+
), content);
|
|
2387
|
+
}
|
|
2388
|
+
|
|
2389
|
+
const Router = (props) => {
|
|
2390
|
+
const {
|
|
2391
|
+
components: {
|
|
2392
|
+
TemplateCardComponent,
|
|
2393
|
+
TaskPageComponent = OngoingTask,
|
|
2394
|
+
ReviewStepComponent,
|
|
2395
|
+
EXPERIMENTAL_TemplateOutputsComponent: TemplateOutputsComponent,
|
|
2396
|
+
EXPERIMENTAL_TemplateListPageComponent: TemplateListPageComponent = TemplateListPage,
|
|
2397
|
+
EXPERIMENTAL_TemplateWizardPageComponent: TemplateWizardPageComponent = TemplateWizardPage
|
|
2398
|
+
} = {}
|
|
2399
|
+
} = props;
|
|
2400
|
+
const outlet = useOutlet() || props.children;
|
|
2401
|
+
const customFieldExtensions = useCustomFieldExtensions(outlet);
|
|
2402
|
+
const fieldExtensions = [
|
|
2403
|
+
...customFieldExtensions,
|
|
2404
|
+
...DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS.filter(
|
|
2405
|
+
({ name }) => !customFieldExtensions.some(
|
|
2406
|
+
(customFieldExtension) => customFieldExtension.name === name
|
|
2407
|
+
)
|
|
2408
|
+
)
|
|
2409
|
+
];
|
|
2410
|
+
const customLayouts = useCustomLayouts(outlet);
|
|
2411
|
+
return /* @__PURE__ */ React.createElement(Routes, null, /* @__PURE__ */ React.createElement(
|
|
2412
|
+
Route,
|
|
2413
|
+
{
|
|
2414
|
+
path: "/",
|
|
2415
|
+
element: /* @__PURE__ */ React.createElement(
|
|
2416
|
+
TemplateListPageComponent,
|
|
2417
|
+
{
|
|
2418
|
+
TemplateCardComponent,
|
|
2419
|
+
contextMenu: props.contextMenu,
|
|
2420
|
+
groups: props.groups,
|
|
2421
|
+
templateFilter: props.templateFilter,
|
|
2422
|
+
headerOptions: props.headerOptions
|
|
2423
|
+
}
|
|
2424
|
+
)
|
|
2425
|
+
}
|
|
2426
|
+
), /* @__PURE__ */ React.createElement(
|
|
2427
|
+
Route,
|
|
2428
|
+
{
|
|
2429
|
+
path: selectedTemplateRouteRef.path,
|
|
2430
|
+
element: /* @__PURE__ */ React.createElement(SecretsContextProvider, null, /* @__PURE__ */ React.createElement(
|
|
2431
|
+
TemplateWizardPageComponent,
|
|
2432
|
+
{
|
|
2433
|
+
headerOptions: props.headerOptions,
|
|
2434
|
+
customFieldExtensions: fieldExtensions,
|
|
2435
|
+
layouts: customLayouts,
|
|
2436
|
+
components: { ReviewStepComponent },
|
|
2437
|
+
formProps: props.formProps
|
|
2438
|
+
}
|
|
2439
|
+
))
|
|
2440
|
+
}
|
|
2441
|
+
), /* @__PURE__ */ React.createElement(
|
|
2442
|
+
Route,
|
|
2443
|
+
{
|
|
2444
|
+
path: scaffolderTaskRouteRef.path,
|
|
2445
|
+
element: /* @__PURE__ */ React.createElement(
|
|
2446
|
+
TaskPageComponent,
|
|
2447
|
+
{
|
|
2448
|
+
TemplateOutputsComponent
|
|
2449
|
+
}
|
|
2450
|
+
)
|
|
2451
|
+
}
|
|
2452
|
+
), /* @__PURE__ */ React.createElement(
|
|
2453
|
+
Route,
|
|
2454
|
+
{
|
|
2455
|
+
path: editRouteRef.path,
|
|
2456
|
+
element: /* @__PURE__ */ React.createElement(SecretsContextProvider, null, /* @__PURE__ */ React.createElement(
|
|
2457
|
+
TemplateEditorPage,
|
|
2458
|
+
{
|
|
2459
|
+
customFieldExtensions: fieldExtensions,
|
|
2460
|
+
layouts: customLayouts
|
|
2461
|
+
}
|
|
2462
|
+
))
|
|
2463
|
+
}
|
|
2464
|
+
), /* @__PURE__ */ React.createElement(Route, { path: actionsRouteRef.path, element: /* @__PURE__ */ React.createElement(ActionsPage, null) }), /* @__PURE__ */ React.createElement(
|
|
2465
|
+
Route,
|
|
2466
|
+
{
|
|
2467
|
+
path: scaffolderListTaskRouteRef.path,
|
|
2468
|
+
element: /* @__PURE__ */ React.createElement(ListTasksPage, null)
|
|
2469
|
+
}
|
|
2470
|
+
), /* @__PURE__ */ React.createElement(
|
|
2471
|
+
Route,
|
|
2472
|
+
{
|
|
2473
|
+
path: "*",
|
|
2474
|
+
element: /* @__PURE__ */ React.createElement(ErrorPage, { status: "404", statusMessage: "Page not found" })
|
|
2475
|
+
}
|
|
2476
|
+
));
|
|
2477
|
+
};
|
|
2478
|
+
|
|
2479
|
+
export { Router };
|
|
2480
|
+
//# sourceMappingURL=index-7840abd4.esm.js.map
|