@backstage/plugin-scaffolder 0.15.0 → 1.0.1-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 +59 -0
- package/alpha/package.json +6 -0
- package/dist/esm/{Router-47c9a9ee.esm.js → Router-9a3e085b.esm.js} +191 -64
- package/dist/esm/Router-9a3e085b.esm.js.map +1 -0
- package/dist/esm/default-4cf122e1.esm.js +33 -0
- package/dist/esm/default-4cf122e1.esm.js.map +1 -0
- package/dist/esm/{index-ced3b204.esm.js → index-ae0b91e4.esm.js} +10 -8
- package/dist/esm/index-ae0b91e4.esm.js.map +1 -0
- package/dist/esm/index-d6a70531.esm.js +338 -0
- package/dist/esm/index-d6a70531.esm.js.map +1 -0
- package/dist/index.alpha.d.ts +498 -0
- package/dist/index.beta.d.ts +475 -0
- package/dist/index.d.ts +277 -226
- package/dist/index.esm.js +1 -1
- package/package.json +31 -24
- package/dist/esm/Router-47c9a9ee.esm.js.map +0 -1
- package/dist/esm/index-ced3b204.esm.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,64 @@
|
|
|
1
1
|
# @backstage/plugin-scaffolder
|
|
2
2
|
|
|
3
|
+
## 1.0.1-next.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 4431873583: Update `usePermission` usage.
|
|
8
|
+
- Updated dependencies
|
|
9
|
+
- @backstage/integration@1.1.0-next.1
|
|
10
|
+
- @backstage/plugin-permission-react@0.4.0-next.0
|
|
11
|
+
- @backstage/plugin-catalog-react@1.0.1-next.1
|
|
12
|
+
- @backstage/plugin-catalog-common@1.0.1-next.1
|
|
13
|
+
- @backstage/integration-react@1.0.1-next.1
|
|
14
|
+
|
|
15
|
+
## 1.0.1-next.0
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- d34900af81: Added a new `NextScaffolderRouter` which will eventually replace the exiting router
|
|
20
|
+
- Updated dependencies
|
|
21
|
+
- @backstage/catalog-model@1.0.1-next.0
|
|
22
|
+
- @backstage/integration@1.0.1-next.0
|
|
23
|
+
- @backstage/plugin-catalog-react@1.0.1-next.0
|
|
24
|
+
- @backstage/core-components@0.9.3-next.0
|
|
25
|
+
- @backstage/catalog-client@1.0.1-next.0
|
|
26
|
+
- @backstage/plugin-scaffolder-common@1.0.1-next.0
|
|
27
|
+
- @backstage/integration-react@1.0.1-next.0
|
|
28
|
+
- @backstage/plugin-catalog-common@1.0.1-next.0
|
|
29
|
+
|
|
30
|
+
## 1.0.0
|
|
31
|
+
|
|
32
|
+
### Major Changes
|
|
33
|
+
|
|
34
|
+
- b58c70c223: This package has been promoted to v1.0! To understand how this change affects the package, please check out our [versioning policy](https://backstage.io/docs/overview/versioning-policy).
|
|
35
|
+
|
|
36
|
+
### Minor Changes
|
|
37
|
+
|
|
38
|
+
- 9a408928a1: **BREAKING**: Removed the unused `titleComponent` property of `groups` passed to the `ScaffolderPage`. The property was already ignored, but existing usage should migrated to use the `title` property instead, which now accepts any `ReactNode`.
|
|
39
|
+
|
|
40
|
+
### Patch Changes
|
|
41
|
+
|
|
42
|
+
- 9b7e361783: Remove beta labels
|
|
43
|
+
- a422d7ce5e: chore(deps): bump `@testing-library/react` from 11.2.6 to 12.1.3
|
|
44
|
+
- 20a262c214: The `ScaffolderPage` now uses the `CatalogFilterLayout`, which means the filters are put in a drawer on smaller screens.
|
|
45
|
+
- f24ef7864e: Minor typo fixes
|
|
46
|
+
- d8716924d6: Implement a template preview page (`/create/preview`) to test creating form UIs
|
|
47
|
+
- Updated dependencies
|
|
48
|
+
- @backstage/core-components@0.9.2
|
|
49
|
+
- @backstage/core-plugin-api@1.0.0
|
|
50
|
+
- @backstage/integration-react@1.0.0
|
|
51
|
+
- @backstage/plugin-catalog-react@1.0.0
|
|
52
|
+
- @backstage/plugin-permission-react@0.3.4
|
|
53
|
+
- @backstage/catalog-model@1.0.0
|
|
54
|
+
- @backstage/plugin-scaffolder-common@1.0.0
|
|
55
|
+
- @backstage/integration@1.0.0
|
|
56
|
+
- @backstage/catalog-client@1.0.0
|
|
57
|
+
- @backstage/config@1.0.0
|
|
58
|
+
- @backstage/errors@1.0.0
|
|
59
|
+
- @backstage/types@1.0.0
|
|
60
|
+
- @backstage/plugin-catalog-common@1.0.0
|
|
61
|
+
|
|
3
62
|
## 0.15.0
|
|
4
63
|
|
|
5
64
|
### Minor Changes
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import React, { useState, useContext, useCallback } from 'react';
|
|
2
2
|
import { useNavigate, Navigate, useOutlet, Routes, Route } from 'react-router';
|
|
3
|
-
import { ItemCardHeader, MarkdownContent, Button, ContentHeader, Progress, WarningPanel, Link as Link$1, Content, ItemCardGrid, Page, Header,
|
|
4
|
-
import { useRouteRef, useApi, errorApiRef, featureFlagsApiRef, useApiHolder, useElementFilter } from '@backstage/core-plugin-api';
|
|
5
|
-
import { getEntityRelations, getEntitySourceLocation, FavoriteEntity, EntityRefLinks, useEntityList, EntityListProvider, EntitySearchBar, EntityKindPicker, UserListPicker, EntityTagPicker } from '@backstage/plugin-catalog-react';
|
|
6
|
-
import {
|
|
7
|
-
import { E as EntityPicker, a as EntityNamePicker, e as entityNamePickerValidation, b as EntityTagsPicker, R as RepoUrlPicker, r as repoPickerValidation, O as OwnerPicker, c as OwnedEntityPicker, s as selectedTemplateRouteRef, d as registerComponentRouteRef, T as TemplateTypePicker, S as SecretsContext, f as scaffolderApiRef, g as scaffolderTaskRouteRef, h as rootRouteRef, F as FIELD_EXTENSION_WRAPPER_KEY, i as FIELD_EXTENSION_KEY, j as SecretsContextProvider, k as TaskPage } from './index-ced3b204.esm.js';
|
|
3
|
+
import { ItemCardHeader, MarkdownContent, Button, ContentHeader, Progress, WarningPanel, Link as Link$1, Content, ItemCardGrid, Page, Header, CreateButton, SupportButton, StructuredMetadataTable, InfoCard, ErrorPage } from '@backstage/core-components';
|
|
4
|
+
import { useRouteRef, useApi, errorApiRef, featureFlagsApiRef, useApiHolder, alertApiRef, useElementFilter } from '@backstage/core-plugin-api';
|
|
5
|
+
import { getEntityRelations, getEntitySourceLocation, FavoriteEntity, EntityRefLinks, useEntityList, EntityListProvider, CatalogFilterLayout, EntitySearchBar, EntityKindPicker, UserListPicker, EntityTagPicker, catalogApiRef, humanizeEntityRef } from '@backstage/plugin-catalog-react';
|
|
6
|
+
import { s as selectedTemplateRouteRef, r as registerComponentRouteRef, T as TemplateTypePicker, S as SecretsContext, a as scaffolderApiRef, b as scaffolderTaskRouteRef, c as rootRouteRef, F as FIELD_EXTENSION_WRAPPER_KEY, d as FIELD_EXTENSION_KEY, e as SecretsContextProvider, f as TaskPage } from './index-ae0b91e4.esm.js';
|
|
8
7
|
import { RELATION_OWNED_BY, stringifyEntityRef } from '@backstage/catalog-model';
|
|
8
|
+
import { makeStyles, useTheme, Card, CardMedia, CardContent, Box, Typography, Chip, CardActions, IconButton, Tooltip, Link, Stepper, Step, StepLabel, StepContent, Button as Button$1, Paper, LinearProgress, TableContainer, Table, TableHead, TableRow, TableCell, TableBody, Grid, FormControl, InputLabel, Select, MenuItem } from '@material-ui/core';
|
|
9
9
|
import { scmIntegrationsApiRef, ScmIntegrationIcon } from '@backstage/integration-react';
|
|
10
10
|
import WarningIcon from '@material-ui/icons/Warning';
|
|
11
11
|
import { catalogEntityCreatePermission } from '@backstage/plugin-catalog-common';
|
|
@@ -17,6 +17,13 @@ import { withTheme } from '@rjsf/core';
|
|
|
17
17
|
import { Theme } from '@rjsf/material-ui';
|
|
18
18
|
import cloneDeep from 'lodash/cloneDeep';
|
|
19
19
|
import classNames from 'classnames';
|
|
20
|
+
import useDebounce from 'react-use/lib/useDebounce';
|
|
21
|
+
import { yaml as yaml$1 } from '@codemirror/legacy-modes/mode/yaml';
|
|
22
|
+
import { showPanel } from '@codemirror/panel';
|
|
23
|
+
import { StreamLanguage } from '@codemirror/stream-parser';
|
|
24
|
+
import CodeMirror from '@uiw/react-codemirror';
|
|
25
|
+
import yaml from 'yaml';
|
|
26
|
+
import { D as DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS } from './default-4cf122e1.esm.js';
|
|
20
27
|
import '@backstage/errors';
|
|
21
28
|
import 'zen-observable';
|
|
22
29
|
import '@material-ui/core/FormControl';
|
|
@@ -26,7 +33,6 @@ import '@material-ui/lab';
|
|
|
26
33
|
import '@material-ui/core/FormHelperText';
|
|
27
34
|
import '@material-ui/core/Input';
|
|
28
35
|
import '@material-ui/core/InputLabel';
|
|
29
|
-
import 'react-use/lib/useDebounce';
|
|
30
36
|
import 'lodash/capitalize';
|
|
31
37
|
import '@material-ui/icons/CheckBox';
|
|
32
38
|
import '@material-ui/icons/CheckBoxOutlineBlank';
|
|
@@ -45,35 +51,6 @@ import 'react-use/lib/useInterval';
|
|
|
45
51
|
import 'use-immer';
|
|
46
52
|
import '@material-ui/icons/Language';
|
|
47
53
|
|
|
48
|
-
const DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS = [
|
|
49
|
-
{
|
|
50
|
-
component: EntityPicker,
|
|
51
|
-
name: "EntityPicker"
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
component: EntityNamePicker,
|
|
55
|
-
name: "EntityNamePicker",
|
|
56
|
-
validation: entityNamePickerValidation
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
component: EntityTagsPicker,
|
|
60
|
-
name: "EntityTagsPicker"
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
component: RepoUrlPicker,
|
|
64
|
-
name: "RepoUrlPicker",
|
|
65
|
-
validation: repoPickerValidation
|
|
66
|
-
},
|
|
67
|
-
{
|
|
68
|
-
component: OwnerPicker,
|
|
69
|
-
name: "OwnerPicker"
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
component: OwnedEntityPicker,
|
|
73
|
-
name: "OwnedEntityPicker"
|
|
74
|
-
}
|
|
75
|
-
];
|
|
76
|
-
|
|
77
54
|
const useStyles$2 = makeStyles((theme) => ({
|
|
78
55
|
cardHeader: {
|
|
79
56
|
position: "relative"
|
|
@@ -210,10 +187,6 @@ const TemplateList = ({
|
|
|
210
187
|
const Card = TemplateCardComponent || TemplateCard;
|
|
211
188
|
const maybeFilteredEntities = group ? entities.filter((e) => group.filter(e)) : entities;
|
|
212
189
|
const titleComponent = (() => {
|
|
213
|
-
if (group == null ? void 0 : group.titleComponent) {
|
|
214
|
-
console.warn("DEPRECATED: group.titleComponent is now deprecated. Use group.title instead, it can be a string or a react component");
|
|
215
|
-
return group == null ? void 0 : group.titleComponent;
|
|
216
|
-
}
|
|
217
190
|
if (group && group.title) {
|
|
218
191
|
if (typeof group.title === "string") {
|
|
219
192
|
return /* @__PURE__ */ React.createElement(ContentHeader, {
|
|
@@ -242,19 +215,10 @@ const TemplateList = ({
|
|
|
242
215
|
})))));
|
|
243
216
|
};
|
|
244
217
|
|
|
245
|
-
const useStyles$1 = makeStyles((theme) => ({
|
|
246
|
-
contentWrapper: {
|
|
247
|
-
display: "grid",
|
|
248
|
-
gridTemplateAreas: "'filters' 'grid'",
|
|
249
|
-
gridTemplateColumns: "250px 1fr",
|
|
250
|
-
gridColumnGap: theme.spacing(2)
|
|
251
|
-
}
|
|
252
|
-
}));
|
|
253
218
|
const ScaffolderPageContents = ({
|
|
254
219
|
TemplateCardComponent,
|
|
255
220
|
groups
|
|
256
221
|
}) => {
|
|
257
|
-
const styles = useStyles$1();
|
|
258
222
|
const registerComponentLink = useRouteRef(registerComponentRouteRef);
|
|
259
223
|
const otherTemplatesGroup = {
|
|
260
224
|
title: groups ? "Other Templates" : "Templates",
|
|
@@ -263,29 +227,27 @@ const ScaffolderPageContents = ({
|
|
|
263
227
|
return !filtered.some((result) => result === true);
|
|
264
228
|
}
|
|
265
229
|
};
|
|
266
|
-
const { allowed } = usePermission(
|
|
230
|
+
const { allowed } = usePermission({
|
|
231
|
+
permission: catalogEntityCreatePermission
|
|
232
|
+
});
|
|
267
233
|
return /* @__PURE__ */ React.createElement(Page, {
|
|
268
234
|
themeId: "home"
|
|
269
235
|
}, /* @__PURE__ */ React.createElement(Header, {
|
|
270
236
|
pageTitleOverride: "Create a New Component",
|
|
271
|
-
title:
|
|
272
|
-
shorthand: true
|
|
273
|
-
})),
|
|
237
|
+
title: "Create a New Component",
|
|
274
238
|
subtitle: "Create new software components using standard templates"
|
|
275
239
|
}), /* @__PURE__ */ React.createElement(Content, null, /* @__PURE__ */ React.createElement(ContentHeader, {
|
|
276
240
|
title: "Available Templates"
|
|
277
241
|
}, allowed && /* @__PURE__ */ React.createElement(CreateButton, {
|
|
278
242
|
title: "Register Existing Component",
|
|
279
243
|
to: registerComponentLink && registerComponentLink()
|
|
280
|
-
}), /* @__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(
|
|
281
|
-
className: styles.contentWrapper
|
|
282
|
-
}, /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement(EntitySearchBar, null), /* @__PURE__ */ React.createElement(EntityKindPicker, {
|
|
244
|
+
}), /* @__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, {
|
|
283
245
|
initialFilter: "template",
|
|
284
246
|
hidden: true
|
|
285
247
|
}), /* @__PURE__ */ React.createElement(UserListPicker, {
|
|
286
248
|
initialFilter: "all",
|
|
287
249
|
availableFilters: ["all", "starred"]
|
|
288
|
-
}), /* @__PURE__ */ React.createElement(TemplateTypePicker, null), /* @__PURE__ */ React.createElement(EntityTagPicker, null)), /* @__PURE__ */ React.createElement(
|
|
250
|
+
}), /* @__PURE__ */ React.createElement(TemplateTypePicker, null), /* @__PURE__ */ React.createElement(EntityTagPicker, null)), /* @__PURE__ */ React.createElement(CatalogFilterLayout.Content, null, groups && groups.map((group, index) => /* @__PURE__ */ React.createElement(TemplateList, {
|
|
289
251
|
key: index,
|
|
290
252
|
TemplateCardComponent,
|
|
291
253
|
group
|
|
@@ -477,6 +439,9 @@ const MultistepJsonForm = (props) => {
|
|
|
477
439
|
};
|
|
478
440
|
const handleBack = () => setActiveStep(Math.max(activeStep - 1, 0));
|
|
479
441
|
const handleCreate = async () => {
|
|
442
|
+
if (!onFinish) {
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
480
445
|
setDisableButtons(true);
|
|
481
446
|
try {
|
|
482
447
|
await onFinish();
|
|
@@ -541,7 +506,7 @@ const MultistepJsonForm = (props) => {
|
|
|
541
506
|
variant: "contained",
|
|
542
507
|
color: "primary",
|
|
543
508
|
onClick: handleCreate,
|
|
544
|
-
disabled: disableButtons
|
|
509
|
+
disabled: !onFinish || disableButtons
|
|
545
510
|
}, "Create"))));
|
|
546
511
|
};
|
|
547
512
|
|
|
@@ -639,9 +604,7 @@ const TemplatePage = ({
|
|
|
639
604
|
themeId: "home"
|
|
640
605
|
}, /* @__PURE__ */ React.createElement(Header, {
|
|
641
606
|
pageTitleOverride: "Create a New Component",
|
|
642
|
-
title:
|
|
643
|
-
shorthand: true
|
|
644
|
-
})),
|
|
607
|
+
title: "Create a New Component",
|
|
645
608
|
subtitle: "Create new software components using standard templates"
|
|
646
609
|
}), /* @__PURE__ */ React.createElement(Content, null, loading && /* @__PURE__ */ React.createElement(LinearProgress, {
|
|
647
610
|
"data-testid": "loading-progress"
|
|
@@ -664,7 +627,7 @@ const TemplatePage = ({
|
|
|
664
627
|
}))));
|
|
665
628
|
};
|
|
666
629
|
|
|
667
|
-
const useStyles = makeStyles((theme) => ({
|
|
630
|
+
const useStyles$1 = makeStyles((theme) => ({
|
|
668
631
|
code: {
|
|
669
632
|
fontFamily: "Menlo, monospace",
|
|
670
633
|
padding: theme.spacing(1),
|
|
@@ -687,7 +650,7 @@ const useStyles = makeStyles((theme) => ({
|
|
|
687
650
|
}));
|
|
688
651
|
const ActionsPage = () => {
|
|
689
652
|
const api = useApi(scaffolderApiRef);
|
|
690
|
-
const classes = useStyles();
|
|
653
|
+
const classes = useStyles$1();
|
|
691
654
|
const { loading, value, error } = useAsync(async () => {
|
|
692
655
|
return api.listActions();
|
|
693
656
|
});
|
|
@@ -772,8 +735,166 @@ const ActionsPage = () => {
|
|
|
772
735
|
}), /* @__PURE__ */ React.createElement(Content, null, items));
|
|
773
736
|
};
|
|
774
737
|
|
|
738
|
+
const EXAMPLE_TEMPLATE_PARAMS_YAML = `# Edit the template parameters below to see how they will render in the scaffolder form UI
|
|
739
|
+
parameters:
|
|
740
|
+
- title: Fill in some steps
|
|
741
|
+
required:
|
|
742
|
+
- name
|
|
743
|
+
properties:
|
|
744
|
+
name:
|
|
745
|
+
title: Name
|
|
746
|
+
type: string
|
|
747
|
+
description: Unique name of the component
|
|
748
|
+
owner:
|
|
749
|
+
title: Owner
|
|
750
|
+
type: string
|
|
751
|
+
description: Owner of the component
|
|
752
|
+
ui:field: OwnerPicker
|
|
753
|
+
ui:options:
|
|
754
|
+
allowedKinds:
|
|
755
|
+
- Group
|
|
756
|
+
- title: Choose a location
|
|
757
|
+
required:
|
|
758
|
+
- repoUrl
|
|
759
|
+
properties:
|
|
760
|
+
repoUrl:
|
|
761
|
+
title: Repository Location
|
|
762
|
+
type: string
|
|
763
|
+
ui:field: RepoUrlPicker
|
|
764
|
+
ui:options:
|
|
765
|
+
allowedHosts:
|
|
766
|
+
- github.com
|
|
767
|
+
`;
|
|
768
|
+
const useStyles = makeStyles({
|
|
769
|
+
templateSelect: {
|
|
770
|
+
marginBottom: "10px"
|
|
771
|
+
},
|
|
772
|
+
grid: {
|
|
773
|
+
height: "100%"
|
|
774
|
+
},
|
|
775
|
+
codeMirror: {
|
|
776
|
+
height: "95%"
|
|
777
|
+
}
|
|
778
|
+
});
|
|
779
|
+
const TemplatePreviewPage = ({
|
|
780
|
+
defaultPreviewTemplate = EXAMPLE_TEMPLATE_PARAMS_YAML,
|
|
781
|
+
customFieldExtensions = []
|
|
782
|
+
}) => {
|
|
783
|
+
const classes = useStyles();
|
|
784
|
+
const alertApi = useApi(alertApiRef);
|
|
785
|
+
const catalogApi = useApi(catalogApiRef);
|
|
786
|
+
const apiHolder = useApiHolder();
|
|
787
|
+
const [selectedTemplate, setSelectedTemplate] = useState("");
|
|
788
|
+
const [schema, setSchema] = useState({
|
|
789
|
+
title: "",
|
|
790
|
+
steps: []
|
|
791
|
+
});
|
|
792
|
+
const [templateOptions, setTemplateOptions] = useState([]);
|
|
793
|
+
const [templateYaml, setTemplateYaml] = useState(defaultPreviewTemplate);
|
|
794
|
+
const [formState, setFormState] = useState({});
|
|
795
|
+
const { loading } = useAsync(() => catalogApi.getEntities({
|
|
796
|
+
filter: { kind: "template" },
|
|
797
|
+
fields: [
|
|
798
|
+
"kind",
|
|
799
|
+
"metadata.namespace",
|
|
800
|
+
"metadata.name",
|
|
801
|
+
"metadata.title",
|
|
802
|
+
"spec.parameters"
|
|
803
|
+
]
|
|
804
|
+
}).then(({ items }) => setTemplateOptions(items.map((template) => {
|
|
805
|
+
var _a;
|
|
806
|
+
return {
|
|
807
|
+
label: (_a = template.metadata.title) != null ? _a : humanizeEntityRef(template, { defaultKind: "template" }),
|
|
808
|
+
value: template
|
|
809
|
+
};
|
|
810
|
+
}))).catch((e) => alertApi.post({
|
|
811
|
+
message: `Error loading exisiting templates: ${e.message}`,
|
|
812
|
+
severity: "error"
|
|
813
|
+
})), [catalogApi]);
|
|
814
|
+
const errorPanel = document.createElement("div");
|
|
815
|
+
errorPanel.style.color = "red";
|
|
816
|
+
useDebounce(() => {
|
|
817
|
+
try {
|
|
818
|
+
const parsedTemplate = yaml.parse(templateYaml);
|
|
819
|
+
setSchema({
|
|
820
|
+
title: "Preview",
|
|
821
|
+
steps: parsedTemplate.parameters.map((param) => ({
|
|
822
|
+
title: param.title,
|
|
823
|
+
schema: param
|
|
824
|
+
}))
|
|
825
|
+
});
|
|
826
|
+
setFormState({});
|
|
827
|
+
} catch (e) {
|
|
828
|
+
errorPanel.textContent = e.message;
|
|
829
|
+
}
|
|
830
|
+
}, 250, [setFormState, setSchema, templateYaml]);
|
|
831
|
+
const handleSelectChange = useCallback((selected) => {
|
|
832
|
+
setSelectedTemplate(selected);
|
|
833
|
+
setTemplateYaml(yaml.stringify(selected.spec));
|
|
834
|
+
}, [setTemplateYaml]);
|
|
835
|
+
const handleFormReset = () => setFormState({});
|
|
836
|
+
const handleFormChange = useCallback((e) => setFormState(e.formData), [setFormState]);
|
|
837
|
+
const handleCodeChange = useCallback((code) => {
|
|
838
|
+
setTemplateYaml(code);
|
|
839
|
+
}, [setTemplateYaml]);
|
|
840
|
+
const customFieldComponents = Object.fromEntries(customFieldExtensions.map(({ name, component }) => [name, component]));
|
|
841
|
+
const customFieldValidators = Object.fromEntries(customFieldExtensions.map(({ name, validation }) => [name, validation]));
|
|
842
|
+
return /* @__PURE__ */ React.createElement(Page, {
|
|
843
|
+
themeId: "home"
|
|
844
|
+
}, /* @__PURE__ */ React.createElement(Header, {
|
|
845
|
+
title: "Template Preview",
|
|
846
|
+
subtitle: "Preview your template parameter UI"
|
|
847
|
+
}), /* @__PURE__ */ React.createElement(Content, null, loading && /* @__PURE__ */ React.createElement(LinearProgress, null), /* @__PURE__ */ React.createElement(Grid, {
|
|
848
|
+
container: true,
|
|
849
|
+
className: classes.grid
|
|
850
|
+
}, /* @__PURE__ */ React.createElement(Grid, {
|
|
851
|
+
item: true,
|
|
852
|
+
xs: 6
|
|
853
|
+
}, /* @__PURE__ */ React.createElement(FormControl, {
|
|
854
|
+
className: classes.templateSelect,
|
|
855
|
+
variant: "outlined",
|
|
856
|
+
fullWidth: true
|
|
857
|
+
}, /* @__PURE__ */ React.createElement(InputLabel, {
|
|
858
|
+
id: "select-template-label"
|
|
859
|
+
}, "Load Existing Template"), /* @__PURE__ */ React.createElement(Select, {
|
|
860
|
+
value: selectedTemplate,
|
|
861
|
+
label: "Load Existing Template",
|
|
862
|
+
labelId: "select-template-label",
|
|
863
|
+
onChange: (e) => handleSelectChange(e.target.value)
|
|
864
|
+
}, templateOptions.map((option, idx) => /* @__PURE__ */ React.createElement(MenuItem, {
|
|
865
|
+
key: idx,
|
|
866
|
+
value: option.value
|
|
867
|
+
}, option.label)))), /* @__PURE__ */ React.createElement(CodeMirror, {
|
|
868
|
+
className: classes.codeMirror,
|
|
869
|
+
value: templateYaml,
|
|
870
|
+
theme: "dark",
|
|
871
|
+
height: "100%",
|
|
872
|
+
extensions: [
|
|
873
|
+
StreamLanguage.define(yaml$1),
|
|
874
|
+
showPanel.of(() => ({ dom: errorPanel, top: true }))
|
|
875
|
+
],
|
|
876
|
+
onChange: handleCodeChange
|
|
877
|
+
})), /* @__PURE__ */ React.createElement(Grid, {
|
|
878
|
+
item: true,
|
|
879
|
+
xs: 6
|
|
880
|
+
}, schema && /* @__PURE__ */ React.createElement(InfoCard, {
|
|
881
|
+
key: JSON.stringify(schema)
|
|
882
|
+
}, /* @__PURE__ */ React.createElement(MultistepJsonForm, {
|
|
883
|
+
formData: formState,
|
|
884
|
+
fields: customFieldComponents,
|
|
885
|
+
onChange: handleFormChange,
|
|
886
|
+
onReset: handleFormReset,
|
|
887
|
+
steps: schema.steps.map((step) => {
|
|
888
|
+
return {
|
|
889
|
+
...step,
|
|
890
|
+
validate: createValidator(step.schema, customFieldValidators, { apiHolder })
|
|
891
|
+
};
|
|
892
|
+
})
|
|
893
|
+
}))))));
|
|
894
|
+
};
|
|
895
|
+
|
|
775
896
|
const Router = (props) => {
|
|
776
|
-
const { groups, components = {} } = props;
|
|
897
|
+
const { groups, components = {}, defaultPreviewTemplate } = props;
|
|
777
898
|
const { TemplateCardComponent, TaskPageComponent } = components;
|
|
778
899
|
const outlet = useOutlet();
|
|
779
900
|
const TaskPageElement = TaskPageComponent != null ? TaskPageComponent : TaskPage;
|
|
@@ -803,8 +924,14 @@ const Router = (props) => {
|
|
|
803
924
|
}), /* @__PURE__ */ React.createElement(Route, {
|
|
804
925
|
path: "/actions",
|
|
805
926
|
element: /* @__PURE__ */ React.createElement(ActionsPage, null)
|
|
927
|
+
}), /* @__PURE__ */ React.createElement(Route, {
|
|
928
|
+
path: "/preview",
|
|
929
|
+
element: /* @__PURE__ */ React.createElement(SecretsContextProvider, null, /* @__PURE__ */ React.createElement(TemplatePreviewPage, {
|
|
930
|
+
defaultPreviewTemplate,
|
|
931
|
+
customFieldExtensions: fieldExtensions
|
|
932
|
+
}))
|
|
806
933
|
}));
|
|
807
934
|
};
|
|
808
935
|
|
|
809
936
|
export { Router };
|
|
810
|
-
//# sourceMappingURL=Router-
|
|
937
|
+
//# sourceMappingURL=Router-9a3e085b.esm.js.map
|