@backstage/plugin-scaffolder 1.13.0-next.0 → 1.13.0-next.2
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 +50 -0
- package/alpha/package.json +1 -1
- package/dist/alpha.d.ts +12 -70
- package/dist/alpha.esm.js +21 -18
- package/dist/alpha.esm.js.map +1 -1
- package/dist/esm/{alpha/ListTasksPage-a9fab591.esm.js → ListTasksPage-caaca86d.esm.js} +3 -2
- package/dist/esm/ListTasksPage-caaca86d.esm.js.map +1 -0
- package/dist/esm/{index/Router-f32000f9.esm.js → Router-f509f2e0.esm.js} +19 -16
- package/dist/esm/Router-f509f2e0.esm.js.map +1 -0
- package/dist/esm/{index/index-8321766a.esm.js → TaskPage-f304e0fc.esm.js} +31 -88
- package/dist/esm/TaskPage-f304e0fc.esm.js.map +1 -0
- package/dist/esm/{index/ListTasksPage-64779a2d.esm.js → TemplateEditorIntro-f7f6d664.esm.js} +396 -530
- package/dist/esm/TemplateEditorIntro-f7f6d664.esm.js.map +1 -0
- package/dist/esm/{index/index-e3edaa49.esm.js → TemplateFormPreviewer-299c316c.esm.js} +18 -379
- package/dist/esm/TemplateFormPreviewer-299c316c.esm.js.map +1 -0
- package/dist/esm/TemplateTypePicker-4f07b216.esm.js +58 -0
- package/dist/esm/TemplateTypePicker-4f07b216.esm.js.map +1 -0
- package/dist/esm/{alpha/index-d45f106a.esm.js → index-64f5b7a5.esm.js} +26 -23
- package/dist/esm/index-64f5b7a5.esm.js.map +1 -0
- package/dist/index.d.ts +46 -205
- package/dist/index.esm.js +19 -7
- package/dist/index.esm.js.map +1 -1
- package/dist/types/plugin.d-7a7914d1.d.ts +232 -0
- package/package.json +24 -22
- package/dist/esm/alpha/ListTasksPage-a9fab591.esm.js.map +0 -1
- package/dist/esm/alpha/Router-ea3122d2.esm.js +0 -1581
- package/dist/esm/alpha/Router-ea3122d2.esm.js.map +0 -1
- package/dist/esm/alpha/alpha-0764fae7.esm.js +0 -3410
- package/dist/esm/alpha/alpha-0764fae7.esm.js.map +0 -1
- package/dist/esm/alpha/index-d45f106a.esm.js.map +0 -1
- package/dist/esm/index/ListTasksPage-64779a2d.esm.js.map +0 -1
- package/dist/esm/index/Router-f32000f9.esm.js.map +0 -1
- package/dist/esm/index/index-8321766a.esm.js.map +0 -1
- package/dist/esm/index/index-e3edaa49.esm.js.map +0 -1
|
@@ -1,246 +1,28 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import
|
|
8
|
-
import IconButton from '@material-ui/core/IconButton';
|
|
9
|
-
import useMediaQuery from '@material-ui/core/useMediaQuery';
|
|
10
|
-
import AddCircleOutline from '@material-ui/icons/AddCircleOutline';
|
|
11
|
-
import { catalogEntityCreatePermission } from '@backstage/plugin-catalog-common/alpha';
|
|
12
|
-
import { usePermission } from '@backstage/plugin-permission-react';
|
|
13
|
-
import { r as registerComponentRouteRef, e as editRouteRef, a as actionsRouteRef, b as scaffolderListTaskRouteRef, v as viewTechDocRouteRef, s as selectedTemplateRouteRef, d as rootRouteRef, c as scaffolderTaskRouteRef } from './index-8321766a.esm.js';
|
|
14
|
-
import { parseEntityRef, stringifyEntityRef } from '@backstage/catalog-model';
|
|
15
|
-
import { useTemplateSecrets, scaffolderApiRef, useTaskEventStream, useCustomFieldExtensions, useCustomLayouts, SecretsContextProvider } from '@backstage/plugin-scaffolder-react';
|
|
16
|
-
import { u as useDryRun, a as useDirectoryEditor, D as DirectoryEditorProvider, b as DryRunProvider, T as TemplateEditorBrowser, c as TemplateEditorTextArea, d as DryRunResults, e as TemplateEditorIntro, W as WebFileSystemAccess, f as DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS, A as ActionsPage, L as ListTasksPage } from './ListTasksPage-64779a2d.esm.js';
|
|
17
|
-
import { makeStyles, IconButton as IconButton$1, Popover, MenuList, MenuItem, ListItemIcon, ListItemText, Box, Paper, FormControl, InputLabel, Select, Card, CardHeader, CardContent, Button as Button$1, LinearProgress } from '@material-ui/core';
|
|
1
|
+
import React, { useState, useMemo, useEffect, useCallback, Component } from 'react';
|
|
2
|
+
import { Page, Header, Content, ErrorPanel } from '@backstage/core-components';
|
|
3
|
+
import { useParams, useNavigate } from 'react-router-dom';
|
|
4
|
+
import { makeStyles, IconButton, Popover, MenuList, MenuItem, ListItemIcon, ListItemText, Box, Paper, FormControl, InputLabel, Select, Card, CardHeader, CardContent, Button, LinearProgress } from '@material-ui/core';
|
|
5
|
+
import { scaffolderApiRef, useTaskEventStream } from '@backstage/plugin-scaffolder-react';
|
|
6
|
+
import { k as selectedTemplateRouteRef } from './TaskPage-f304e0fc.esm.js';
|
|
7
|
+
import { useApi, useRouteRef, useApiHolder, alertApiRef } from '@backstage/core-plugin-api';
|
|
18
8
|
import qs from 'qs';
|
|
19
9
|
import { useAsync } from '@react-hookz/web';
|
|
20
10
|
import Cancel from '@material-ui/icons/Cancel';
|
|
21
11
|
import Retry from '@material-ui/icons/Repeat';
|
|
22
12
|
import Toc from '@material-ui/icons/Toc';
|
|
23
13
|
import MoreVert from '@material-ui/icons/MoreVert';
|
|
14
|
+
import { DefaultTemplateOutputs, TaskSteps, TaskLogStream, Stepper, Form } from '@backstage/plugin-scaffolder-react/alpha';
|
|
24
15
|
import { StreamLanguage } from '@codemirror/language';
|
|
25
16
|
import { yaml as yaml$1 } from '@codemirror/legacy-modes/mode/yaml';
|
|
26
17
|
import CloseIcon from '@material-ui/icons/Close';
|
|
27
18
|
import CodeMirror from '@uiw/react-codemirror';
|
|
28
19
|
import yaml from 'yaml';
|
|
29
|
-
import { makeStyles as makeStyles$1 } from '@material-ui/core/styles';
|
|
30
|
-
import useDebounce from 'react-use/lib/useDebounce';
|
|
31
20
|
import validator from '@rjsf/validator-ajv8';
|
|
21
|
+
import { u as useDryRun, a as useDirectoryEditor, D as DirectoryEditorProvider, b as DryRunProvider, T as TemplateEditorBrowser, c as TemplateEditorTextArea, d as DryRunResults } from './TemplateEditorIntro-f7f6d664.esm.js';
|
|
22
|
+
import { catalogApiRef, humanizeEntityRef } from '@backstage/plugin-catalog-react';
|
|
32
23
|
import useAsync$1 from 'react-use/lib/useAsync';
|
|
33
|
-
import '@
|
|
34
|
-
import '
|
|
35
|
-
import '@backstage/integration-react';
|
|
36
|
-
import '@backstage/catalog-client';
|
|
37
|
-
import '@material-ui/core/FormControl';
|
|
38
|
-
import '@material-ui/lab/Autocomplete';
|
|
39
|
-
import 'zod';
|
|
40
|
-
import 'zod-to-json-schema';
|
|
41
|
-
import '@material-ui/core/FormHelperText';
|
|
42
|
-
import '@material-ui/core/Input';
|
|
43
|
-
import '@material-ui/core/InputLabel';
|
|
44
|
-
import 'react-use/lib/useEffectOnce';
|
|
45
|
-
import '@material-ui/lab';
|
|
46
|
-
import 'lodash/capitalize';
|
|
47
|
-
import '@material-ui/icons/CheckBox';
|
|
48
|
-
import '@material-ui/icons/CheckBoxOutlineBlank';
|
|
49
|
-
import '@material-ui/icons/ExpandMore';
|
|
50
|
-
import '@material-ui/core/Grid';
|
|
51
|
-
import '@material-ui/core/Step';
|
|
52
|
-
import '@material-ui/core/StepLabel';
|
|
53
|
-
import '@material-ui/core/Stepper';
|
|
54
|
-
import '@material-ui/core/Typography';
|
|
55
|
-
import '@material-ui/icons/Check';
|
|
56
|
-
import '@material-ui/icons/FiberManualRecord';
|
|
57
|
-
import 'classnames';
|
|
58
|
-
import 'luxon';
|
|
59
|
-
import 'react-use/lib/useInterval';
|
|
60
|
-
import '@material-ui/icons/Language';
|
|
61
|
-
import '@material-ui/core/Card';
|
|
62
|
-
import '@material-ui/core/CardActionArea';
|
|
63
|
-
import '@material-ui/core/CardContent';
|
|
64
|
-
import '@material-ui/core/Tooltip';
|
|
65
|
-
import '@material-ui/icons/InfoOutlined';
|
|
66
|
-
import '@material-ui/core/Accordion';
|
|
67
|
-
import '@material-ui/core/AccordionDetails';
|
|
68
|
-
import '@material-ui/core/AccordionSummary';
|
|
69
|
-
import '@material-ui/core/Divider';
|
|
70
|
-
import '@material-ui/icons/ExpandLess';
|
|
71
|
-
import '@material-ui/core/List';
|
|
72
|
-
import '@material-ui/core/ListItem';
|
|
73
|
-
import '@material-ui/core/ListItemIcon';
|
|
74
|
-
import '@material-ui/core/ListItemSecondaryAction';
|
|
75
|
-
import '@material-ui/core/ListItemText';
|
|
76
|
-
import '@material-ui/icons/Delete';
|
|
77
|
-
import '@material-ui/core/Box';
|
|
78
|
-
import '@material-ui/core/Tab';
|
|
79
|
-
import '@material-ui/core/Tabs';
|
|
80
|
-
import '@material-ui/icons/Refresh';
|
|
81
|
-
import '@material-ui/icons/Save';
|
|
82
|
-
import '@material-ui/lab/TreeView';
|
|
83
|
-
import '@material-ui/icons/ChevronRight';
|
|
84
|
-
import '@material-ui/lab/TreeItem';
|
|
85
|
-
import '@codemirror/view';
|
|
86
|
-
import '@material-ui/icons/Settings';
|
|
87
|
-
import '@material-ui/icons/FontDownload';
|
|
88
|
-
import 'humanize-duration';
|
|
89
|
-
|
|
90
|
-
const RegisterExistingButton = (props) => {
|
|
91
|
-
const { title, to } = props;
|
|
92
|
-
const { allowed } = usePermission({
|
|
93
|
-
permission: catalogEntityCreatePermission
|
|
94
|
-
});
|
|
95
|
-
const isXSScreen = useMediaQuery(
|
|
96
|
-
(theme) => theme.breakpoints.down("xs")
|
|
97
|
-
);
|
|
98
|
-
if (!to || !allowed) {
|
|
99
|
-
return null;
|
|
100
|
-
}
|
|
101
|
-
return isXSScreen ? /* @__PURE__ */ React.createElement(
|
|
102
|
-
IconButton,
|
|
103
|
-
{
|
|
104
|
-
component: Link,
|
|
105
|
-
color: "primary",
|
|
106
|
-
title,
|
|
107
|
-
size: "small",
|
|
108
|
-
to
|
|
109
|
-
},
|
|
110
|
-
/* @__PURE__ */ React.createElement(AddCircleOutline, null)
|
|
111
|
-
) : /* @__PURE__ */ React.createElement(Button, { component: Link, variant: "contained", color: "primary", to }, title);
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
const defaultGroup = {
|
|
115
|
-
title: "Templates",
|
|
116
|
-
filter: () => true
|
|
117
|
-
};
|
|
118
|
-
const createGroupsWithOther = (groups) => [
|
|
119
|
-
...groups,
|
|
120
|
-
{
|
|
121
|
-
title: "Other Templates",
|
|
122
|
-
filter: (e) => ![...groups].some(({ filter }) => filter(e))
|
|
123
|
-
}
|
|
124
|
-
];
|
|
125
|
-
const TemplateListPage = (props) => {
|
|
126
|
-
var _a, _b, _c;
|
|
127
|
-
const registerComponentLink = useRouteRef(registerComponentRouteRef);
|
|
128
|
-
const {
|
|
129
|
-
TemplateCardComponent,
|
|
130
|
-
groups: givenGroups = [],
|
|
131
|
-
templateFilter
|
|
132
|
-
} = props;
|
|
133
|
-
const navigate = useNavigate();
|
|
134
|
-
const editorLink = useRouteRef(editRouteRef);
|
|
135
|
-
const actionsLink = useRouteRef(actionsRouteRef);
|
|
136
|
-
const tasksLink = useRouteRef(scaffolderListTaskRouteRef);
|
|
137
|
-
const viewTechDocsLink = useRouteRef(viewTechDocRouteRef);
|
|
138
|
-
const templateRoute = useRouteRef(selectedTemplateRouteRef);
|
|
139
|
-
const app = useApp();
|
|
140
|
-
const groups = givenGroups.length ? createGroupsWithOther(givenGroups) : [defaultGroup];
|
|
141
|
-
const scaffolderPageContextMenuProps = {
|
|
142
|
-
onEditorClicked: ((_a = props == null ? void 0 : props.contextMenu) == null ? void 0 : _a.editor) !== false ? () => navigate(editorLink()) : void 0,
|
|
143
|
-
onActionsClicked: ((_b = props == null ? void 0 : props.contextMenu) == null ? void 0 : _b.actions) !== false ? () => navigate(actionsLink()) : void 0,
|
|
144
|
-
onTasksClicked: ((_c = props == null ? void 0 : props.contextMenu) == null ? void 0 : _c.tasks) !== false ? () => navigate(tasksLink()) : void 0
|
|
145
|
-
};
|
|
146
|
-
const additionalLinksForEntity = useCallback(
|
|
147
|
-
(template) => {
|
|
148
|
-
var _a2, _b2;
|
|
149
|
-
const { kind, namespace, name } = parseEntityRef(
|
|
150
|
-
stringifyEntityRef(template)
|
|
151
|
-
);
|
|
152
|
-
return ((_a2 = template.metadata.annotations) == null ? void 0 : _a2["backstage.io/techdocs-ref"]) && viewTechDocsLink ? [
|
|
153
|
-
{
|
|
154
|
-
icon: (_b2 = app.getSystemIcon("docs")) != null ? _b2 : DocsIcon,
|
|
155
|
-
text: "View TechDocs",
|
|
156
|
-
url: viewTechDocsLink({ kind, namespace, name })
|
|
157
|
-
}
|
|
158
|
-
] : [];
|
|
159
|
-
},
|
|
160
|
-
[app, viewTechDocsLink]
|
|
161
|
-
);
|
|
162
|
-
const onTemplateSelected = useCallback(
|
|
163
|
-
(template) => {
|
|
164
|
-
const { namespace, name } = parseEntityRef(stringifyEntityRef(template));
|
|
165
|
-
navigate(templateRoute({ namespace, templateName: name }));
|
|
166
|
-
},
|
|
167
|
-
[navigate, templateRoute]
|
|
168
|
-
);
|
|
169
|
-
return /* @__PURE__ */ React.createElement(EntityListProvider, null, /* @__PURE__ */ React.createElement(Page, { themeId: "website" }, /* @__PURE__ */ React.createElement(
|
|
170
|
-
Header,
|
|
171
|
-
{
|
|
172
|
-
pageTitleOverride: "Create a new component",
|
|
173
|
-
title: "Create a new component",
|
|
174
|
-
subtitle: "Create new software components using standard templates in your organization"
|
|
175
|
-
},
|
|
176
|
-
/* @__PURE__ */ React.createElement(ScaffolderPageContextMenu, { ...scaffolderPageContextMenuProps })
|
|
177
|
-
), /* @__PURE__ */ React.createElement(Content, null, /* @__PURE__ */ React.createElement(ContentHeader, { title: "Available Templates" }, /* @__PURE__ */ React.createElement(
|
|
178
|
-
RegisterExistingButton,
|
|
179
|
-
{
|
|
180
|
-
title: "Register Existing Component",
|
|
181
|
-
to: registerComponentLink && registerComponentLink()
|
|
182
|
-
}
|
|
183
|
-
), /* @__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(
|
|
184
|
-
UserListPicker,
|
|
185
|
-
{
|
|
186
|
-
initialFilter: "all",
|
|
187
|
-
availableFilters: ["all", "starred"]
|
|
188
|
-
}
|
|
189
|
-
), /* @__PURE__ */ React.createElement(TemplateCategoryPicker, null), /* @__PURE__ */ React.createElement(EntityTagPicker, null)), /* @__PURE__ */ React.createElement(CatalogFilterLayout.Content, null, /* @__PURE__ */ React.createElement(
|
|
190
|
-
TemplateGroups,
|
|
191
|
-
{
|
|
192
|
-
groups,
|
|
193
|
-
templateFilter,
|
|
194
|
-
TemplateCardComponent,
|
|
195
|
-
onTemplateSelected,
|
|
196
|
-
additionalLinksForEntity
|
|
197
|
-
}
|
|
198
|
-
))))));
|
|
199
|
-
};
|
|
200
|
-
|
|
201
|
-
const TemplateWizardPage = (props) => {
|
|
202
|
-
const rootRef = useRouteRef(rootRouteRef);
|
|
203
|
-
const taskRoute = useRouteRef(scaffolderTaskRouteRef);
|
|
204
|
-
const { secrets } = useTemplateSecrets();
|
|
205
|
-
const scaffolderApi = useApi(scaffolderApiRef);
|
|
206
|
-
const navigate = useNavigate();
|
|
207
|
-
const { templateName, namespace } = useRouteRefParams(
|
|
208
|
-
selectedTemplateRouteRef
|
|
209
|
-
);
|
|
210
|
-
const templateRef = stringifyEntityRef({
|
|
211
|
-
kind: "Template",
|
|
212
|
-
namespace,
|
|
213
|
-
name: templateName
|
|
214
|
-
});
|
|
215
|
-
const onCreate = async (values) => {
|
|
216
|
-
const { taskId } = await scaffolderApi.scaffold({
|
|
217
|
-
templateRef,
|
|
218
|
-
values,
|
|
219
|
-
secrets
|
|
220
|
-
});
|
|
221
|
-
navigate(taskRoute({ taskId }));
|
|
222
|
-
};
|
|
223
|
-
const onError = () => /* @__PURE__ */ React.createElement(Navigate, { to: rootRef() });
|
|
224
|
-
return /* @__PURE__ */ React.createElement(AnalyticsContext, { attributes: { entityRef: templateRef } }, /* @__PURE__ */ React.createElement(Page, { themeId: "website" }, /* @__PURE__ */ React.createElement(
|
|
225
|
-
Header,
|
|
226
|
-
{
|
|
227
|
-
pageTitleOverride: "Create a new component",
|
|
228
|
-
title: "Create a new component",
|
|
229
|
-
subtitle: "Create new software components using standard templates in your organization"
|
|
230
|
-
}
|
|
231
|
-
), /* @__PURE__ */ React.createElement(
|
|
232
|
-
Workflow,
|
|
233
|
-
{
|
|
234
|
-
namespace,
|
|
235
|
-
templateName,
|
|
236
|
-
onCreate,
|
|
237
|
-
onError,
|
|
238
|
-
extensions: props.customFieldExtensions,
|
|
239
|
-
FormProps: props.FormProps,
|
|
240
|
-
layouts: props.layouts
|
|
241
|
-
}
|
|
242
|
-
)));
|
|
243
|
-
};
|
|
24
|
+
import { makeStyles as makeStyles$1 } from '@material-ui/core/styles';
|
|
25
|
+
import useDebounce from 'react-use/lib/useDebounce';
|
|
244
26
|
|
|
245
27
|
const useStyles$5 = makeStyles((theme) => ({
|
|
246
28
|
button: {
|
|
@@ -258,7 +40,7 @@ const ContextMenu = (props) => {
|
|
|
258
40
|
}
|
|
259
41
|
});
|
|
260
42
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
|
|
261
|
-
IconButton
|
|
43
|
+
IconButton,
|
|
262
44
|
{
|
|
263
45
|
"aria-label": "more",
|
|
264
46
|
"aria-controls": "long-menu",
|
|
@@ -619,7 +401,7 @@ const CustomFieldExplorer = ({
|
|
|
619
401
|
onChange: (e) => handleSelectionChange(e.target.value)
|
|
620
402
|
},
|
|
621
403
|
fieldOptions.map((option, idx) => /* @__PURE__ */ React.createElement(MenuItem, { key: idx, value: option }, option.name))
|
|
622
|
-
)), /* @__PURE__ */ React.createElement(IconButton
|
|
404
|
+
)), /* @__PURE__ */ React.createElement(IconButton, { size: "medium", onClick: onClose }, /* @__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(
|
|
623
405
|
Form,
|
|
624
406
|
{
|
|
625
407
|
showErrorList: false,
|
|
@@ -632,7 +414,7 @@ const CustomFieldExplorer = ({
|
|
|
632
414
|
schema: ((_a = selectedField.schema) == null ? void 0 : _a.uiOptions) || {}
|
|
633
415
|
},
|
|
634
416
|
/* @__PURE__ */ React.createElement(
|
|
635
|
-
Button
|
|
417
|
+
Button,
|
|
636
418
|
{
|
|
637
419
|
variant: "contained",
|
|
638
420
|
color: "primary",
|
|
@@ -825,7 +607,7 @@ const TemplateFormPreviewer = ({
|
|
|
825
607
|
onChange: (e) => handleSelectChange(e.target.value)
|
|
826
608
|
},
|
|
827
609
|
templateOptions.map((option, idx) => /* @__PURE__ */ React.createElement(MenuItem, { key: idx, value: option.value }, option.label))
|
|
828
|
-
)), /* @__PURE__ */ React.createElement(IconButton
|
|
610
|
+
)), /* @__PURE__ */ React.createElement(IconButton, { size: "medium", onClick: onClose }, /* @__PURE__ */ React.createElement(CloseIcon, null))), /* @__PURE__ */ React.createElement("div", { className: classes.textArea }, /* @__PURE__ */ React.createElement(
|
|
829
611
|
TemplateEditorTextArea,
|
|
830
612
|
{
|
|
831
613
|
content: templateYaml,
|
|
@@ -844,148 +626,5 @@ const TemplateFormPreviewer = ({
|
|
|
844
626
|
))));
|
|
845
627
|
};
|
|
846
628
|
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
let content = null;
|
|
850
|
-
if ((selection == null ? void 0 : selection.type) === "local") {
|
|
851
|
-
content = /* @__PURE__ */ React.createElement(
|
|
852
|
-
TemplateEditor,
|
|
853
|
-
{
|
|
854
|
-
directory: selection.directory,
|
|
855
|
-
fieldExtensions: props.customFieldExtensions,
|
|
856
|
-
onClose: () => setSelection(void 0),
|
|
857
|
-
layouts: props.layouts
|
|
858
|
-
}
|
|
859
|
-
);
|
|
860
|
-
} else if ((selection == null ? void 0 : selection.type) === "form") {
|
|
861
|
-
content = /* @__PURE__ */ React.createElement(
|
|
862
|
-
TemplateFormPreviewer,
|
|
863
|
-
{
|
|
864
|
-
defaultPreviewTemplate: props.defaultPreviewTemplate,
|
|
865
|
-
customFieldExtensions: props.customFieldExtensions,
|
|
866
|
-
onClose: () => setSelection(void 0),
|
|
867
|
-
layouts: props.layouts
|
|
868
|
-
}
|
|
869
|
-
);
|
|
870
|
-
} else if ((selection == null ? void 0 : selection.type) === "field-explorer") {
|
|
871
|
-
content = /* @__PURE__ */ React.createElement(
|
|
872
|
-
CustomFieldExplorer,
|
|
873
|
-
{
|
|
874
|
-
customFieldExtensions: props.customFieldExtensions,
|
|
875
|
-
onClose: () => setSelection(void 0)
|
|
876
|
-
}
|
|
877
|
-
);
|
|
878
|
-
} else {
|
|
879
|
-
content = /* @__PURE__ */ React.createElement(Content, null, /* @__PURE__ */ React.createElement(
|
|
880
|
-
TemplateEditorIntro,
|
|
881
|
-
{
|
|
882
|
-
onSelect: (option) => {
|
|
883
|
-
if (option === "local") {
|
|
884
|
-
WebFileSystemAccess.requestDirectoryAccess().then((directory) => setSelection({ type: "local", directory })).catch(() => {
|
|
885
|
-
});
|
|
886
|
-
} else if (option === "form") {
|
|
887
|
-
setSelection({ type: "form" });
|
|
888
|
-
} else if (option === "field-explorer") {
|
|
889
|
-
setSelection({ type: "field-explorer" });
|
|
890
|
-
}
|
|
891
|
-
}
|
|
892
|
-
}
|
|
893
|
-
));
|
|
894
|
-
}
|
|
895
|
-
return /* @__PURE__ */ React.createElement(Page, { themeId: "home" }, /* @__PURE__ */ React.createElement(
|
|
896
|
-
Header,
|
|
897
|
-
{
|
|
898
|
-
title: "Template Editor",
|
|
899
|
-
subtitle: "Edit, preview, and try out templates and template forms"
|
|
900
|
-
}
|
|
901
|
-
), content);
|
|
902
|
-
}
|
|
903
|
-
|
|
904
|
-
const Router = (props) => {
|
|
905
|
-
const {
|
|
906
|
-
components: {
|
|
907
|
-
TemplateCardComponent,
|
|
908
|
-
TemplateOutputsComponent,
|
|
909
|
-
TaskPageComponent = OngoingTask,
|
|
910
|
-
TemplateListPageComponent = TemplateListPage,
|
|
911
|
-
TemplateWizardPageComponent = TemplateWizardPage
|
|
912
|
-
} = {}
|
|
913
|
-
} = props;
|
|
914
|
-
const outlet = useOutlet() || props.children;
|
|
915
|
-
const customFieldExtensions = useCustomFieldExtensions(outlet);
|
|
916
|
-
const fieldExtensions = [
|
|
917
|
-
...customFieldExtensions,
|
|
918
|
-
...DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS.filter(
|
|
919
|
-
({ name }) => !customFieldExtensions.some(
|
|
920
|
-
(customFieldExtension) => customFieldExtension.name === name
|
|
921
|
-
)
|
|
922
|
-
)
|
|
923
|
-
];
|
|
924
|
-
const customLayouts = useCustomLayouts(outlet);
|
|
925
|
-
return /* @__PURE__ */ React.createElement(Routes, null, /* @__PURE__ */ React.createElement(
|
|
926
|
-
Route,
|
|
927
|
-
{
|
|
928
|
-
path: "/",
|
|
929
|
-
element: /* @__PURE__ */ React.createElement(
|
|
930
|
-
TemplateListPageComponent,
|
|
931
|
-
{
|
|
932
|
-
TemplateCardComponent,
|
|
933
|
-
contextMenu: props.contextMenu,
|
|
934
|
-
groups: props.groups,
|
|
935
|
-
templateFilter: props.templateFilter
|
|
936
|
-
}
|
|
937
|
-
)
|
|
938
|
-
}
|
|
939
|
-
), /* @__PURE__ */ React.createElement(
|
|
940
|
-
Route,
|
|
941
|
-
{
|
|
942
|
-
path: selectedTemplateRouteRef.path,
|
|
943
|
-
element: /* @__PURE__ */ React.createElement(SecretsContextProvider, null, /* @__PURE__ */ React.createElement(
|
|
944
|
-
TemplateWizardPageComponent,
|
|
945
|
-
{
|
|
946
|
-
customFieldExtensions: fieldExtensions,
|
|
947
|
-
layouts: customLayouts,
|
|
948
|
-
FormProps: props.FormProps
|
|
949
|
-
}
|
|
950
|
-
))
|
|
951
|
-
}
|
|
952
|
-
), /* @__PURE__ */ React.createElement(
|
|
953
|
-
Route,
|
|
954
|
-
{
|
|
955
|
-
path: scaffolderTaskRouteRef.path,
|
|
956
|
-
element: /* @__PURE__ */ React.createElement(
|
|
957
|
-
TaskPageComponent,
|
|
958
|
-
{
|
|
959
|
-
TemplateOutputsComponent
|
|
960
|
-
}
|
|
961
|
-
)
|
|
962
|
-
}
|
|
963
|
-
), /* @__PURE__ */ React.createElement(
|
|
964
|
-
Route,
|
|
965
|
-
{
|
|
966
|
-
path: editRouteRef.path,
|
|
967
|
-
element: /* @__PURE__ */ React.createElement(SecretsContextProvider, null, /* @__PURE__ */ React.createElement(
|
|
968
|
-
TemplateEditorPage,
|
|
969
|
-
{
|
|
970
|
-
customFieldExtensions: fieldExtensions,
|
|
971
|
-
layouts: customLayouts
|
|
972
|
-
}
|
|
973
|
-
))
|
|
974
|
-
}
|
|
975
|
-
), /* @__PURE__ */ React.createElement(Route, { path: actionsRouteRef.path, element: /* @__PURE__ */ React.createElement(ActionsPage, null) }), /* @__PURE__ */ React.createElement(
|
|
976
|
-
Route,
|
|
977
|
-
{
|
|
978
|
-
path: scaffolderListTaskRouteRef.path,
|
|
979
|
-
element: /* @__PURE__ */ React.createElement(ListTasksPage, null)
|
|
980
|
-
}
|
|
981
|
-
), /* @__PURE__ */ React.createElement(
|
|
982
|
-
Route,
|
|
983
|
-
{
|
|
984
|
-
path: "*",
|
|
985
|
-
element: /* @__PURE__ */ React.createElement(ErrorPage, { status: "404", statusMessage: "Page not found" })
|
|
986
|
-
}
|
|
987
|
-
));
|
|
988
|
-
};
|
|
989
|
-
|
|
990
|
-
export { Router };
|
|
991
|
-
//# sourceMappingURL=index-e3edaa49.esm.js.map
|
|
629
|
+
export { CustomFieldExplorer as C, OngoingTask as O, TemplateEditor as T, TemplateFormPreviewer as a };
|
|
630
|
+
//# sourceMappingURL=TemplateFormPreviewer-299c316c.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TemplateFormPreviewer-299c316c.esm.js","sources":["../../src/next/OngoingTask/ContextMenu.tsx","../../src/next/OngoingTask/OngoingTask.tsx","../../src/next/TemplateEditorPage/TemplateEditorForm.tsx","../../src/next/TemplateEditorPage/CustomFieldExplorer.tsx","../../src/next/TemplateEditorPage/TemplateEditor.tsx","../../src/next/TemplateEditorPage/TemplateFormPreviewer.tsx"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { BackstageTheme } from '@backstage/theme';\nimport {\n IconButton,\n ListItemIcon,\n ListItemText,\n makeStyles,\n MenuItem,\n MenuList,\n Popover,\n} from '@material-ui/core';\nimport { useAsync } from '@react-hookz/web';\nimport Cancel from '@material-ui/icons/Cancel';\nimport Retry from '@material-ui/icons/Repeat';\nimport Toc from '@material-ui/icons/Toc';\nimport MoreVert from '@material-ui/icons/MoreVert';\nimport React, { useState } from 'react';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { scaffolderApiRef } from '@backstage/plugin-scaffolder-react';\n\ntype ContextMenuProps = {\n cancelEnabled?: boolean;\n logsVisible?: boolean;\n onStartOver?: () => void;\n onToggleLogs?: (state: boolean) => void;\n taskId?: string;\n};\n\nconst useStyles = makeStyles((theme: BackstageTheme) => ({\n button: {\n color: theme.palette.common.white,\n },\n}));\n\nexport const ContextMenu = (props: ContextMenuProps) => {\n const { cancelEnabled, logsVisible, onStartOver, onToggleLogs, taskId } =\n props;\n const classes = useStyles();\n const scaffolderApi = useApi(scaffolderApiRef);\n const [anchorEl, setAnchorEl] = useState<HTMLButtonElement>();\n\n const [{ status: cancelStatus }, { execute: cancel }] = useAsync(async () => {\n if (taskId) {\n await scaffolderApi.cancelTask(taskId);\n }\n });\n\n return (\n <>\n <IconButton\n aria-label=\"more\"\n aria-controls=\"long-menu\"\n aria-haspopup=\"true\"\n onClick={(event: React.SyntheticEvent<HTMLButtonElement>) => {\n setAnchorEl(event.currentTarget);\n }}\n data-testid=\"menu-button\"\n color=\"inherit\"\n className={classes.button}\n >\n <MoreVert />\n </IconButton>\n <Popover\n open={Boolean(anchorEl)}\n onClose={() => setAnchorEl(undefined)}\n anchorEl={anchorEl}\n anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}\n transformOrigin={{ vertical: 'top', horizontal: 'right' }}\n >\n <MenuList>\n <MenuItem onClick={() => onToggleLogs?.(!logsVisible)}>\n <ListItemIcon>\n <Toc fontSize=\"small\" />\n </ListItemIcon>\n <ListItemText primary={logsVisible ? 'Hide Logs' : 'Show Logs'} />\n </MenuItem>\n <MenuItem onClick={onStartOver}>\n <ListItemIcon>\n <Retry fontSize=\"small\" />\n </ListItemIcon>\n <ListItemText primary=\"Start Over\" />\n </MenuItem>\n <MenuItem\n onClick={cancel}\n disabled={!cancelEnabled || cancelStatus !== 'not-executed'}\n data-testid=\"cancel-task\"\n >\n <ListItemIcon>\n <Cancel fontSize=\"small\" />\n </ListItemIcon>\n <ListItemText primary=\"Cancel\" />\n </MenuItem>\n </MenuList>\n </Popover>\n </>\n );\n};\n","/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React, { useCallback, useEffect, useMemo, useState } from 'react';\nimport { Content, ErrorPanel, Header, Page } from '@backstage/core-components';\nimport { useNavigate, useParams } from 'react-router-dom';\nimport { Box, makeStyles, Paper } from '@material-ui/core';\nimport {\n ScaffolderTaskOutput,\n useTaskEventStream,\n} from '@backstage/plugin-scaffolder-react';\nimport { selectedTemplateRouteRef } from '../../routes';\nimport { useRouteRef } from '@backstage/core-plugin-api';\nimport qs from 'qs';\nimport { ContextMenu } from './ContextMenu';\nimport {\n DefaultTemplateOutputs,\n TaskLogStream,\n TaskSteps,\n} from '@backstage/plugin-scaffolder-react/alpha';\n\nconst useStyles = makeStyles({\n contentWrapper: {\n display: 'flex',\n flexDirection: 'column',\n },\n});\n\nexport const OngoingTask = (props: {\n TemplateOutputsComponent?: React.ComponentType<{\n output?: ScaffolderTaskOutput;\n }>;\n}) => {\n // todo(blam): check that task Id actually exists, and that it's valid. otherwise redirect to something more useful.\n const { taskId } = useParams();\n const templateRouteRef = useRouteRef(selectedTemplateRouteRef);\n const navigate = useNavigate();\n const taskStream = useTaskEventStream(taskId!);\n const classes = useStyles();\n const steps = useMemo(\n () =>\n taskStream.task?.spec.steps.map(step => ({\n ...step,\n ...taskStream?.steps?.[step.id],\n })) ?? [],\n [taskStream],\n );\n\n const [logsVisible, setLogVisibleState] = useState(false);\n\n useEffect(() => {\n if (taskStream.error) {\n setLogVisibleState(true);\n }\n }, [taskStream.error]);\n\n const activeStep = useMemo(() => {\n for (let i = steps.length - 1; i >= 0; i--) {\n if (steps[i].status !== 'open') {\n return i;\n }\n }\n\n return 0;\n }, [steps]);\n\n const startOver = useCallback(() => {\n const { namespace, name } =\n taskStream.task?.spec.templateInfo?.entity?.metadata ?? {};\n\n const formData = taskStream.task?.spec.parameters ?? {};\n\n if (!namespace || !name) {\n return;\n }\n\n navigate({\n pathname: templateRouteRef({\n namespace,\n templateName: name,\n }),\n search: `?${qs.stringify({ formData: JSON.stringify(formData) })}`,\n });\n }, [\n navigate,\n taskStream.task?.spec.parameters,\n taskStream.task?.spec.templateInfo?.entity?.metadata,\n templateRouteRef,\n ]);\n\n const Outputs = props.TemplateOutputsComponent ?? DefaultTemplateOutputs;\n\n const templateName =\n taskStream.task?.spec.templateInfo?.entity?.metadata.name;\n\n const cancelEnabled = !(taskStream.cancelled || taskStream.completed);\n\n return (\n <Page themeId=\"website\">\n <Header\n pageTitleOverride={`Run of ${templateName}`}\n title={\n <div>\n Run of <code>{templateName}</code>\n </div>\n }\n subtitle={`Task ${taskId}`}\n >\n <ContextMenu\n cancelEnabled={cancelEnabled}\n logsVisible={logsVisible}\n onStartOver={startOver}\n onToggleLogs={setLogVisibleState}\n taskId={taskId}\n />\n </Header>\n <Content className={classes.contentWrapper}>\n {taskStream.error ? (\n <Box paddingBottom={2}>\n <ErrorPanel\n error={taskStream.error}\n title={taskStream.error.message}\n />\n </Box>\n ) : null}\n\n <Box paddingBottom={2}>\n <TaskSteps\n steps={steps}\n activeStep={activeStep}\n isComplete={taskStream.completed}\n isError={Boolean(taskStream.error)}\n />\n </Box>\n\n <Outputs output={taskStream.output} />\n\n {logsVisible ? (\n <Box paddingBottom={2} height=\"100%\">\n <Paper style={{ height: '100%' }}>\n <Box padding={2} height=\"100%\">\n <TaskLogStream logs={taskStream.stepLogs} />\n </Box>\n </Paper>\n </Box>\n ) : null}\n </Content>\n </Page>\n );\n};\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useApiHolder } from '@backstage/core-plugin-api';\nimport { JsonObject, JsonValue } from '@backstage/types';\nimport { makeStyles } from '@material-ui/core/styles';\nimport React, { Component, ReactNode, useState } from 'react';\nimport useDebounce from 'react-use/lib/useDebounce';\nimport yaml from 'yaml';\nimport {\n LayoutOptions,\n TemplateParameterSchema,\n} from '@backstage/plugin-scaffolder-react';\nimport {\n NextFieldExtensionOptions,\n Stepper,\n} from '@backstage/plugin-scaffolder-react/alpha';\nimport { useDryRun } from '../../components/TemplateEditorPage/DryRunContext';\nimport { useDirectoryEditor } from '../../components/TemplateEditorPage/DirectoryEditorContext';\n\nconst useStyles = makeStyles({\n containerWrapper: {\n position: 'relative',\n width: '100%',\n height: '100%',\n },\n container: {\n position: 'absolute',\n top: 0,\n bottom: 0,\n left: 0,\n right: 0,\n overflow: 'auto',\n },\n});\n\ninterface ErrorBoundaryProps {\n invalidator: unknown;\n setErrorText(errorText: string | undefined): void;\n children: ReactNode;\n}\n\ninterface ErrorBoundaryState {\n shouldRender: boolean;\n}\n\nclass ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {\n state = {\n shouldRender: true,\n };\n\n componentDidUpdate(prevProps: { invalidator: unknown }) {\n if (prevProps.invalidator !== this.props.invalidator) {\n this.setState({ shouldRender: true });\n }\n }\n\n componentDidCatch(error: Error) {\n this.props.setErrorText(error.message);\n this.setState({ shouldRender: false });\n }\n\n render() {\n return this.state.shouldRender ? this.props.children : null;\n }\n}\n\ninterface TemplateEditorFormProps {\n content?: string;\n /** Setting this to true will cause the content to be parsed as if it is the template entity spec */\n contentIsSpec?: boolean;\n setErrorText: (errorText?: string) => void;\n onDryRun?: (data: JsonObject) => Promise<void>;\n fieldExtensions?: NextFieldExtensionOptions<any, any>[];\n layouts?: LayoutOptions[];\n}\n\nfunction isJsonObject(value: JsonValue | undefined): value is JsonObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/** Shows the a template form that is parsed from the provided content */\nexport function TemplateEditorForm(props: TemplateEditorFormProps) {\n const {\n content,\n contentIsSpec,\n onDryRun,\n setErrorText,\n fieldExtensions = [],\n layouts = [],\n } = props;\n const classes = useStyles();\n const apiHolder = useApiHolder();\n\n const [steps, setSteps] = useState<TemplateParameterSchema['steps']>();\n\n useDebounce(\n () => {\n try {\n if (!content) {\n setSteps(undefined);\n return;\n }\n const parsed: JsonValue = yaml.parse(content);\n\n if (!isJsonObject(parsed)) {\n setSteps(undefined);\n return;\n }\n\n let rootObj = parsed;\n if (!contentIsSpec) {\n const isTemplate =\n String(parsed.kind).toLocaleLowerCase('en-US') === 'template';\n if (!isTemplate) {\n setSteps(undefined);\n return;\n }\n\n rootObj = isJsonObject(parsed.spec) ? parsed.spec : {};\n }\n\n const { parameters } = rootObj;\n\n if (!Array.isArray(parameters)) {\n setErrorText('Template parameters must be an array');\n setSteps(undefined);\n return;\n }\n\n setErrorText();\n setSteps(\n parameters.flatMap(param =>\n isJsonObject(param)\n ? [\n {\n title: String(param.title),\n schema: param,\n },\n ]\n : [],\n ),\n );\n } catch (e) {\n setErrorText(e.message);\n }\n },\n 250,\n [contentIsSpec, content, apiHolder],\n );\n\n if (!steps) {\n return null;\n }\n\n return (\n <div className={classes.containerWrapper}>\n <div className={classes.container}>\n <ErrorBoundary invalidator={steps} setErrorText={setErrorText}>\n <Stepper\n manifest={{ steps, title: 'Template Editor' }}\n extensions={fieldExtensions}\n onCreate={async data => {\n await onDryRun?.(data);\n }}\n layouts={layouts}\n components={{ createButtonText: onDryRun && 'Try It' }}\n />\n </ErrorBoundary>\n </div>\n </div>\n );\n}\n\n/** A version of the TemplateEditorForm that is connected to the DirectoryEditor and DryRun contexts */\nexport function TemplateEditorFormDirectoryEditorDryRun(\n props: Pick<\n TemplateEditorFormProps,\n 'setErrorText' | 'fieldExtensions' | 'layouts'\n >,\n) {\n const { setErrorText, fieldExtensions = [], layouts } = props;\n const dryRun = useDryRun();\n\n const directoryEditor = useDirectoryEditor();\n const { selectedFile } = directoryEditor;\n\n const handleDryRun = async (values: JsonObject) => {\n if (!selectedFile) {\n return;\n }\n\n try {\n await dryRun.execute({\n templateContent: selectedFile.content,\n values,\n files: directoryEditor.files,\n });\n setErrorText();\n } catch (e) {\n setErrorText(String(e.cause || e));\n throw e;\n }\n };\n\n const content =\n selectedFile && selectedFile.path.match(/\\.ya?ml$/)\n ? selectedFile.content\n : undefined;\n\n return (\n <TemplateEditorForm\n onDryRun={handleDryRun}\n fieldExtensions={fieldExtensions}\n setErrorText={setErrorText}\n content={content}\n layouts={layouts}\n />\n );\n}\n\nTemplateEditorForm.DirectoryEditorDryRun =\n TemplateEditorFormDirectoryEditorDryRun;\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { StreamLanguage } from '@codemirror/language';\nimport { yaml as yamlSupport } from '@codemirror/legacy-modes/mode/yaml';\nimport {\n Button,\n Card,\n CardContent,\n CardHeader,\n FormControl,\n IconButton,\n InputLabel,\n makeStyles,\n MenuItem,\n Select,\n} from '@material-ui/core';\nimport CloseIcon from '@material-ui/icons/Close';\nimport CodeMirror from '@uiw/react-codemirror';\nimport React, { useCallback, useMemo, useState } from 'react';\nimport yaml from 'yaml';\nimport {\n NextFieldExtensionOptions,\n Form,\n} from '@backstage/plugin-scaffolder-react/alpha';\nimport { TemplateEditorForm } from './TemplateEditorForm';\nimport validator from '@rjsf/validator-ajv8';\n\nconst useStyles = makeStyles(theme => ({\n root: {\n gridArea: 'pageContent',\n display: 'grid',\n gridTemplateAreas: `\n \"controls controls\"\n \"fieldForm preview\"\n `,\n gridTemplateRows: 'auto 1fr',\n gridTemplateColumns: '1fr 1fr',\n },\n controls: {\n gridArea: 'controls',\n display: 'flex',\n flexFlow: 'row nowrap',\n alignItems: 'center',\n margin: theme.spacing(1),\n },\n fieldForm: {\n gridArea: 'fieldForm',\n },\n preview: {\n gridArea: 'preview',\n },\n}));\n\nexport const CustomFieldExplorer = ({\n customFieldExtensions = [],\n onClose,\n}: {\n customFieldExtensions?: NextFieldExtensionOptions<any, any>[];\n onClose?: () => void;\n}) => {\n const classes = useStyles();\n const fieldOptions = customFieldExtensions.filter(field => !!field.schema);\n const [selectedField, setSelectedField] = useState(fieldOptions[0]);\n const [fieldFormState, setFieldFormState] = useState({});\n const [refreshKey, setRefreshKey] = useState(Date.now());\n const sampleFieldTemplate = useMemo(\n () =>\n yaml.stringify({\n parameters: [\n {\n title: `${selectedField.name} Example`,\n properties: {\n [selectedField.name]: {\n type: selectedField.schema?.returnValue?.type,\n 'ui:field': selectedField.name,\n 'ui:options': fieldFormState,\n },\n },\n },\n ],\n }),\n [fieldFormState, selectedField],\n );\n\n const fieldComponents = useMemo(() => {\n return Object.fromEntries(\n customFieldExtensions.map(({ name, component }) => [name, component]),\n );\n }, [customFieldExtensions]);\n\n const handleSelectionChange = useCallback(\n selection => {\n setSelectedField(selection);\n setFieldFormState({});\n },\n [setFieldFormState, setSelectedField],\n );\n\n const handleFieldConfigChange = useCallback(\n state => {\n setFieldFormState(state);\n // Force TemplateEditorForm to re-render since some fields\n // may not be responsive to ui:option changes\n setRefreshKey(Date.now());\n },\n [setFieldFormState, setRefreshKey],\n );\n\n return (\n <main className={classes.root}>\n <div className={classes.controls}>\n <FormControl variant=\"outlined\" size=\"small\" fullWidth>\n <InputLabel id=\"select-field-label\">\n Choose Custom Field Extension\n </InputLabel>\n <Select\n value={selectedField}\n label=\"Choose Custom Field Extension\"\n labelId=\"select-field-label\"\n onChange={e => handleSelectionChange(e.target.value)}\n >\n {fieldOptions.map((option, idx) => (\n <MenuItem key={idx} value={option as any}>\n {option.name}\n </MenuItem>\n ))}\n </Select>\n </FormControl>\n\n <IconButton size=\"medium\" onClick={onClose}>\n <CloseIcon />\n </IconButton>\n </div>\n <div className={classes.fieldForm}>\n <Card>\n <CardHeader title=\"Field Options\" />\n <CardContent>\n <Form\n showErrorList={false}\n fields={{ ...fieldComponents }}\n noHtml5Validate\n formData={fieldFormState}\n formContext={{ fieldFormState }}\n onSubmit={e => handleFieldConfigChange(e.formData)}\n validator={validator}\n schema={selectedField.schema?.uiOptions || {}}\n >\n <Button\n variant=\"contained\"\n color=\"primary\"\n type=\"submit\"\n disabled={!selectedField.schema?.uiOptions}\n >\n Apply\n </Button>\n </Form>\n </CardContent>\n </Card>\n </div>\n <div className={classes.preview}>\n <Card>\n <CardHeader title=\"Example Template Spec\" />\n <CardContent>\n <CodeMirror\n readOnly\n theme=\"dark\"\n height=\"100%\"\n extensions={[StreamLanguage.define(yamlSupport)]}\n value={sampleFieldTemplate}\n />\n </CardContent>\n </Card>\n <TemplateEditorForm\n key={refreshKey}\n content={sampleFieldTemplate}\n contentIsSpec\n fieldExtensions={customFieldExtensions}\n setErrorText={() => null}\n />\n </div>\n </main>\n );\n};\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { makeStyles } from '@material-ui/core';\nimport React, { useState } from 'react';\nimport type { LayoutOptions } from '@backstage/plugin-scaffolder-react';\nimport { NextFieldExtensionOptions } from '@backstage/plugin-scaffolder-react/alpha';\nimport { TemplateDirectoryAccess } from '../../lib/filesystem';\nimport { DirectoryEditorProvider } from '../../components/TemplateEditorPage/DirectoryEditorContext';\nimport { DryRunProvider } from '../../components/TemplateEditorPage/DryRunContext';\nimport { DryRunResults } from '../../components/TemplateEditorPage/DryRunResults';\nimport { TemplateEditorBrowser } from '../../components/TemplateEditorPage/TemplateEditorBrowser';\nimport { TemplateEditorForm } from './TemplateEditorForm';\nimport { TemplateEditorTextArea } from '../../components/TemplateEditorPage/TemplateEditorTextArea';\n\nconst useStyles = makeStyles({\n // Reset and fix sizing to make sure scrolling behaves correctly\n root: {\n gridArea: 'pageContent',\n\n display: 'grid',\n gridTemplateAreas: `\n \"browser editor preview\"\n \"results results results\"\n `,\n gridTemplateColumns: '1fr 3fr 2fr',\n gridTemplateRows: '1fr auto',\n },\n browser: {\n gridArea: 'browser',\n overflow: 'auto',\n },\n editor: {\n gridArea: 'editor',\n overflow: 'auto',\n },\n preview: {\n gridArea: 'preview',\n overflow: 'auto',\n },\n results: {\n gridArea: 'results',\n },\n});\n\nexport const TemplateEditor = (props: {\n directory: TemplateDirectoryAccess;\n fieldExtensions?: NextFieldExtensionOptions<any, any>[];\n layouts?: LayoutOptions[];\n onClose?: () => void;\n}) => {\n const classes = useStyles();\n\n const [errorText, setErrorText] = useState<string>();\n\n return (\n <DirectoryEditorProvider directory={props.directory}>\n <DryRunProvider>\n <main className={classes.root}>\n <section className={classes.browser}>\n <TemplateEditorBrowser onClose={props.onClose} />\n </section>\n <section className={classes.editor}>\n <TemplateEditorTextArea.DirectoryEditor errorText={errorText} />\n </section>\n <section className={classes.preview}>\n <TemplateEditorForm.DirectoryEditorDryRun\n setErrorText={setErrorText}\n fieldExtensions={props.fieldExtensions}\n layouts={props.layouts}\n />\n </section>\n <section className={classes.results}>\n <DryRunResults />\n </section>\n </main>\n </DryRunProvider>\n </DirectoryEditorProvider>\n );\n};\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { Entity } from '@backstage/catalog-model';\nimport { alertApiRef, useApi } from '@backstage/core-plugin-api';\nimport {\n catalogApiRef,\n humanizeEntityRef,\n} from '@backstage/plugin-catalog-react';\nimport {\n FormControl,\n IconButton,\n InputLabel,\n LinearProgress,\n makeStyles,\n MenuItem,\n Select,\n} from '@material-ui/core';\nimport CloseIcon from '@material-ui/icons/Close';\nimport React, { useCallback, useState } from 'react';\nimport useAsync from 'react-use/lib/useAsync';\nimport yaml from 'yaml';\nimport { type LayoutOptions } from '@backstage/plugin-scaffolder-react';\nimport { NextFieldExtensionOptions } from '@backstage/plugin-scaffolder-react/alpha';\nimport { TemplateEditorForm } from './TemplateEditorForm';\nimport { TemplateEditorTextArea } from '../../components/TemplateEditorPage/TemplateEditorTextArea';\n\nconst EXAMPLE_TEMPLATE_PARAMS_YAML = `# Edit the template parameters below to see how they will render in the scaffolder form UI\nparameters:\n - title: Fill in some steps\n required:\n - name\n properties:\n name:\n title: Name\n type: string\n description: Unique name of the component\n owner:\n title: Owner\n type: string\n description: Owner of the component\n ui:field: OwnerPicker\n ui:options:\n catalogFilter:\n kind: Group\n - title: Choose a location\n required:\n - repoUrl\n properties:\n repoUrl:\n title: Repository Location\n type: string\n ui:field: RepoUrlPicker\n ui:options:\n allowedHosts:\n - github.com\nsteps:\n - id: fetch-base\n name: Fetch Base\n action: fetch:template\n input:\n url: ./template\n values:\n name: \\${{parameters.name}}\n`;\n\ntype TemplateOption = {\n label: string;\n value: Entity;\n};\n\nconst useStyles = makeStyles(theme => ({\n root: {\n gridArea: 'pageContent',\n display: 'grid',\n gridTemplateAreas: `\n \"controls controls\"\n \"textArea preview\"\n `,\n gridTemplateRows: 'auto 1fr',\n gridTemplateColumns: '1fr 1fr',\n },\n controls: {\n gridArea: 'controls',\n display: 'flex',\n flexFlow: 'row nowrap',\n alignItems: 'center',\n margin: theme.spacing(1),\n },\n textArea: {\n gridArea: 'textArea',\n },\n preview: {\n gridArea: 'preview',\n },\n}));\n\nexport const TemplateFormPreviewer = ({\n defaultPreviewTemplate = EXAMPLE_TEMPLATE_PARAMS_YAML,\n customFieldExtensions = [],\n onClose,\n layouts = [],\n}: {\n defaultPreviewTemplate?: string;\n customFieldExtensions?: NextFieldExtensionOptions<any, any>[];\n onClose?: () => void;\n layouts?: LayoutOptions[];\n}) => {\n const classes = useStyles();\n const alertApi = useApi(alertApiRef);\n const catalogApi = useApi(catalogApiRef);\n const [selectedTemplate, setSelectedTemplate] = useState('');\n const [errorText, setErrorText] = useState<string>();\n const [templateOptions, setTemplateOptions] = useState<TemplateOption[]>([]);\n const [templateYaml, setTemplateYaml] = useState(defaultPreviewTemplate);\n\n const { loading } = useAsync(\n () =>\n catalogApi\n .getEntities({\n filter: { kind: 'template' },\n fields: [\n 'kind',\n 'metadata.namespace',\n 'metadata.name',\n 'metadata.title',\n 'spec.parameters',\n 'spec.steps',\n 'spec.output',\n ],\n })\n .then(({ items }) =>\n setTemplateOptions(\n items.map(template => ({\n label:\n template.metadata.title ??\n humanizeEntityRef(template, { defaultKind: 'template' }),\n value: template,\n })),\n ),\n )\n .catch(e =>\n alertApi.post({\n message: `Error loading exisiting templates: ${e.message}`,\n severity: 'error',\n }),\n ),\n [catalogApi],\n );\n\n const handleSelectChange = useCallback(\n selected => {\n setSelectedTemplate(selected);\n setTemplateYaml(yaml.stringify(selected.spec));\n },\n [setTemplateYaml],\n );\n\n return (\n <>\n {loading && <LinearProgress />}\n <main className={classes.root}>\n <div className={classes.controls}>\n <FormControl variant=\"outlined\" size=\"small\" fullWidth>\n <InputLabel id=\"select-template-label\">\n Load Existing Template\n </InputLabel>\n <Select\n value={selectedTemplate}\n label=\"Load Existing Template\"\n labelId=\"select-template-label\"\n onChange={e => handleSelectChange(e.target.value)}\n >\n {templateOptions.map((option, idx) => (\n <MenuItem key={idx} value={option.value as any}>\n {option.label}\n </MenuItem>\n ))}\n </Select>\n </FormControl>\n\n <IconButton size=\"medium\" onClick={onClose}>\n <CloseIcon />\n </IconButton>\n </div>\n <div className={classes.textArea}>\n <TemplateEditorTextArea\n content={templateYaml}\n onUpdate={setTemplateYaml}\n errorText={errorText}\n />\n </div>\n <div className={classes.preview}>\n <TemplateEditorForm\n content={templateYaml}\n contentIsSpec\n fieldExtensions={customFieldExtensions}\n setErrorText={setErrorText}\n layouts={layouts}\n />\n </div>\n </main>\n </>\n );\n};\n"],"names":["useStyles","_a","_b","_c","_d","_e","_f","makeStyles","yamlSupport","useAsync"],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import capitalize from 'lodash/capitalize';
|
|
3
|
+
import { Progress } from '@backstage/core-components';
|
|
4
|
+
import { Box, Typography, FormControlLabel, Checkbox, TextField } from '@material-ui/core';
|
|
5
|
+
import CheckBoxIcon from '@material-ui/icons/CheckBox';
|
|
6
|
+
import CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank';
|
|
7
|
+
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
|
|
8
|
+
import { Autocomplete } from '@material-ui/lab';
|
|
9
|
+
import { useEntityTypeFilter } from '@backstage/plugin-catalog-react';
|
|
10
|
+
import { useApi, alertApiRef } from '@backstage/core-plugin-api';
|
|
11
|
+
|
|
12
|
+
const icon = /* @__PURE__ */ React.createElement(CheckBoxOutlineBlankIcon, { fontSize: "small" });
|
|
13
|
+
const checkedIcon = /* @__PURE__ */ React.createElement(CheckBoxIcon, { fontSize: "small" });
|
|
14
|
+
const TemplateTypePicker = () => {
|
|
15
|
+
const alertApi = useApi(alertApiRef);
|
|
16
|
+
const { error, loading, availableTypes, selectedTypes, setSelectedTypes } = useEntityTypeFilter();
|
|
17
|
+
if (loading)
|
|
18
|
+
return /* @__PURE__ */ React.createElement(Progress, null);
|
|
19
|
+
if (!availableTypes)
|
|
20
|
+
return null;
|
|
21
|
+
if (error) {
|
|
22
|
+
alertApi.post({
|
|
23
|
+
message: `Failed to load entity types`,
|
|
24
|
+
severity: "error"
|
|
25
|
+
});
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
return /* @__PURE__ */ React.createElement(Box, { pb: 1, pt: 1 }, /* @__PURE__ */ React.createElement(Typography, { variant: "button" }, "Categories"), /* @__PURE__ */ React.createElement(
|
|
29
|
+
Autocomplete,
|
|
30
|
+
{
|
|
31
|
+
multiple: true,
|
|
32
|
+
"aria-label": "Categories",
|
|
33
|
+
options: availableTypes,
|
|
34
|
+
value: selectedTypes,
|
|
35
|
+
onChange: (_, value) => setSelectedTypes(value),
|
|
36
|
+
renderOption: (option, { selected }) => /* @__PURE__ */ React.createElement(
|
|
37
|
+
FormControlLabel,
|
|
38
|
+
{
|
|
39
|
+
control: /* @__PURE__ */ React.createElement(
|
|
40
|
+
Checkbox,
|
|
41
|
+
{
|
|
42
|
+
icon,
|
|
43
|
+
checkedIcon,
|
|
44
|
+
checked: selected
|
|
45
|
+
}
|
|
46
|
+
),
|
|
47
|
+
label: capitalize(option)
|
|
48
|
+
}
|
|
49
|
+
),
|
|
50
|
+
size: "small",
|
|
51
|
+
popupIcon: /* @__PURE__ */ React.createElement(ExpandMoreIcon, { "data-testid": "categories-picker-expand" }),
|
|
52
|
+
renderInput: (params) => /* @__PURE__ */ React.createElement(TextField, { ...params, variant: "outlined" })
|
|
53
|
+
}
|
|
54
|
+
));
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export { TemplateTypePicker as T };
|
|
58
|
+
//# sourceMappingURL=TemplateTypePicker-4f07b216.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TemplateTypePicker-4f07b216.esm.js","sources":["../../src/components/TemplateTypePicker/TemplateTypePicker.tsx"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport capitalize from 'lodash/capitalize';\nimport { Progress } from '@backstage/core-components';\nimport {\n Box,\n Checkbox,\n FormControlLabel,\n TextField,\n Typography,\n} from '@material-ui/core';\nimport CheckBoxIcon from '@material-ui/icons/CheckBox';\nimport CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank';\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\nimport { Autocomplete } from '@material-ui/lab';\nimport { useEntityTypeFilter } from '@backstage/plugin-catalog-react';\nimport { alertApiRef, useApi } from '@backstage/core-plugin-api';\n\nconst icon = <CheckBoxOutlineBlankIcon fontSize=\"small\" />;\nconst checkedIcon = <CheckBoxIcon fontSize=\"small\" />;\n\n/**\n * The component to select the `type` of `Template` that you will see in the table.\n *\n * @public\n */\nexport const TemplateTypePicker = () => {\n const alertApi = useApi(alertApiRef);\n const { error, loading, availableTypes, selectedTypes, setSelectedTypes } =\n useEntityTypeFilter();\n\n if (loading) return <Progress />;\n\n if (!availableTypes) return null;\n\n if (error) {\n alertApi.post({\n message: `Failed to load entity types`,\n severity: 'error',\n });\n return null;\n }\n\n return (\n <Box pb={1} pt={1}>\n <Typography variant=\"button\">Categories</Typography>\n <Autocomplete\n multiple\n aria-label=\"Categories\"\n options={availableTypes}\n value={selectedTypes}\n onChange={(_: object, value: string[]) => setSelectedTypes(value)}\n renderOption={(option, { selected }) => (\n <FormControlLabel\n control={\n <Checkbox\n icon={icon}\n checkedIcon={checkedIcon}\n checked={selected}\n />\n }\n label={capitalize(option)}\n />\n )}\n size=\"small\"\n popupIcon={<ExpandMoreIcon data-testid=\"categories-picker-expand\" />}\n renderInput={params => <TextField {...params} variant=\"outlined\" />}\n />\n </Box>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;AAiCA,MAAM,IAAO,mBAAA,KAAA,CAAA,aAAA,CAAC,wBAAyB,EAAA,EAAA,QAAA,EAAS,OAAQ,EAAA,CAAA,CAAA;AACxD,MAAM,WAAc,mBAAA,KAAA,CAAA,aAAA,CAAC,YAAa,EAAA,EAAA,QAAA,EAAS,OAAQ,EAAA,CAAA,CAAA;AAO5C,MAAM,qBAAqB,MAAM;AACtC,EAAM,MAAA,QAAA,GAAW,OAAO,WAAW,CAAA,CAAA;AACnC,EAAA,MAAM,EAAE,KAAO,EAAA,OAAA,EAAS,gBAAgB,aAAe,EAAA,gBAAA,KACrD,mBAAoB,EAAA,CAAA;AAEtB,EAAI,IAAA,OAAA;AAAS,IAAA,2CAAQ,QAAS,EAAA,IAAA,CAAA,CAAA;AAE9B,EAAA,IAAI,CAAC,cAAA;AAAgB,IAAO,OAAA,IAAA,CAAA;AAE5B,EAAA,IAAI,KAAO,EAAA;AACT,IAAA,QAAA,CAAS,IAAK,CAAA;AAAA,MACZ,OAAS,EAAA,CAAA,2BAAA,CAAA;AAAA,MACT,QAAU,EAAA,OAAA;AAAA,KACX,CAAA,CAAA;AACD,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAEA,EACE,uBAAA,KAAA,CAAA,aAAA,CAAC,GAAI,EAAA,EAAA,EAAA,EAAI,CAAG,EAAA,EAAA,EAAI,CACd,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,UAAW,EAAA,EAAA,OAAA,EAAQ,QAAS,EAAA,EAAA,YAAU,CACvC,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,YAAA;AAAA,IAAA;AAAA,MACC,QAAQ,EAAA,IAAA;AAAA,MACR,YAAW,EAAA,YAAA;AAAA,MACX,OAAS,EAAA,cAAA;AAAA,MACT,KAAO,EAAA,aAAA;AAAA,MACP,QAAU,EAAA,CAAC,CAAW,EAAA,KAAA,KAAoB,iBAAiB,KAAK,CAAA;AAAA,MAChE,YAAc,EAAA,CAAC,MAAQ,EAAA,EAAE,UACvB,qBAAA,KAAA,CAAA,aAAA;AAAA,QAAC,gBAAA;AAAA,QAAA;AAAA,UACC,OACE,kBAAA,KAAA,CAAA,aAAA;AAAA,YAAC,QAAA;AAAA,YAAA;AAAA,cACC,IAAA;AAAA,cACA,WAAA;AAAA,cACA,OAAS,EAAA,QAAA;AAAA,aAAA;AAAA,WACX;AAAA,UAEF,KAAA,EAAO,WAAW,MAAM,CAAA;AAAA,SAAA;AAAA,OAC1B;AAAA,MAEF,IAAK,EAAA,OAAA;AAAA,MACL,SAAW,kBAAA,KAAA,CAAA,aAAA,CAAC,cAAe,EAAA,EAAA,aAAA,EAAY,0BAA2B,EAAA,CAAA;AAAA,MAClE,aAAa,CAAU,MAAA,qBAAA,KAAA,CAAA,aAAA,CAAC,aAAW,GAAG,MAAA,EAAQ,SAAQ,UAAW,EAAA,CAAA;AAAA,KAAA;AAAA,GAErE,CAAA,CAAA;AAEJ;;;;"}
|