@backstage/plugin-scaffolder 0.12.3 → 0.15.0-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,151 @@
1
1
  # @backstage/plugin-scaffolder
2
2
 
3
+ ## 0.15.0-next.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 310e905998: The following deprecations are now breaking and have been removed:
8
+
9
+ - **BREAKING**: Support for `backstage.io/v1beta2` Software Templates has been removed. Please migrate your legacy templates to the new `scaffolder.backstage.io/v1beta3` `apiVersion` by following the [migration guide](https://backstage.io/docs/features/software-templates/migrating-from-v1beta2-to-v1beta3)
10
+
11
+ - **BREAKING**: Removed the deprecated `TemplateMetadata`. Please use `TemplateInfo` instead.
12
+
13
+ - **BREAKING**: Removed the deprecated `context.baseUrl`. It's now available on `context.templateInfo.baseUrl`.
14
+
15
+ - **BREAKING**: Removed the deprecated `DispatchResult`, use `TaskBrokerDispatchResult` instead.
16
+
17
+ - **BREAKING**: Removed the deprecated `runCommand`, use `executeShellCommond` instead.
18
+
19
+ - **BREAKING**: Removed the deprecated `Status` in favour of `TaskStatus` instead.
20
+
21
+ - **BREAKING**: Removed the deprecated `TaskState` in favour of `CurrentClaimedTask` instead.
22
+
23
+ - 1360f7d73a: **BREAKING**: Removed `ScaffolderTaskOutput.entityRef` and `ScaffolderTaskOutput.remoteUrl`, which both have been deprecated for over a year. Please use the `links` output instead.
24
+ - e63e5a9452: Removed the following previously deprecated exports:
25
+
26
+ - **BREAKING**: Removed the deprecated `TemplateList` component and the `TemplateListProps` type. Please use the `TemplateCard` to create your own list component instead to render these lists.
27
+
28
+ - **BREAKING**: Removed the deprecated `setSecret` method, please use `setSecrets` instead.
29
+
30
+ - **BREAKING**: Removed the deprecated `TemplateCardComponent` and `TaskPageComponent` props from the `ScaffolderPage` component. These are now provided using the `components` prop with the shape `{{ TemplateCardComponent: () => JSX.Element, TaskPageComponent: () => JSX.Element }}`
31
+
32
+ - **BREAKING**: Removed `JobStatus` as this type was actually a legacy type used in `v1alpha` templates and the workflow engine and should no longer be used or depended on.
33
+
34
+ ### Patch Changes
35
+
36
+ - d741c97b98: Render markdown for description in software templates
37
+ - Updated dependencies
38
+ - @backstage/plugin-catalog-react@0.9.0-next.0
39
+ - @backstage/core-components@0.9.1-next.0
40
+ - @backstage/plugin-scaffolder-common@0.3.0-next.0
41
+ - @backstage/catalog-model@0.13.0-next.0
42
+ - @backstage/plugin-catalog-common@0.2.2-next.0
43
+ - @backstage/catalog-client@0.9.0-next.0
44
+ - @backstage/integration-react@0.1.25-next.0
45
+
46
+ ## 0.14.0
47
+
48
+ ### Minor Changes
49
+
50
+ - 1c2755991d: - **BREAKING**: Removed the `FavouriteTemplate` export in favor of the `FavoriteEntity` from `@backstage/plugin-catalog-react`. Please migrate any usages to that component instead if you are creating your own `TemplateCard` page.
51
+ - 86da51cec5: **BREAKING**: Removing the exports of the raw components that back the `CustomFieldExtensions`.
52
+
53
+ ### Patch Changes
54
+
55
+ - f41a293231: - **DEPRECATION**: Deprecated `formatEntityRefTitle` in favor of the new `humanizeEntityRef` method instead. Please migrate to using the new method instead.
56
+ - 55361f3f7b: Added some deprecations as follows:
57
+
58
+ - **DEPRECATED**: `TemplateCardComponent` and `TaskPageComponent` props have been deprecated, and moved to a `components` prop instead. You can pass them in through there instead.
59
+ - **DEPRECATED**: `TemplateList` and `TemplateListProps` has been deprecated. Please use the `TemplateCard` to create your own list component instead.
60
+ - **DEPRECATED**: `setSecret` has been deprecated in favour of `setSecrets` when calling `useTemplateSecrets`
61
+
62
+ Other notable changes:
63
+
64
+ - `scaffolderApi.scaffold()` `values` type has been narrowed from `Record<string, any>` to `Record<string, JsonValue>` instead.
65
+ - Moved all navigation internally over to using `routeRefs` and `subRouteRefs`
66
+
67
+ - Updated dependencies
68
+ - @backstage/catalog-model@0.12.0
69
+ - @backstage/catalog-client@0.8.0
70
+ - @backstage/core-components@0.9.0
71
+ - @backstage/plugin-catalog-react@0.8.0
72
+ - @backstage/plugin-catalog-common@0.2.0
73
+ - @backstage/integration@0.8.0
74
+ - @backstage/core-plugin-api@0.8.0
75
+ - @backstage/plugin-scaffolder-common@0.2.3
76
+ - @backstage/integration-react@0.1.24
77
+ - @backstage/plugin-permission-react@0.3.3
78
+
79
+ ## 0.13.0
80
+
81
+ ### Minor Changes
82
+
83
+ - 50e0242ac2: - **BREAKING** - `scaffolderApi.scaffold()` now takes one `options` argument instead of 3, the existing arguments should just be wrapped up in one object instead.
84
+ - **BREAKING** - `scaffolderApi.scaffold()` now returns an object instead of a single string for the job ID. It's now `{ taskId: string }`
85
+ - **BREAKING** - `scaffolderApi.scaffold()` now takes a `templateRef` instead of `templateName` as an argument in the options. This should be a valid stringified `entityRef`.
86
+ - **BREAKING** - `scaffolderApi.getIntegrationsList` now returns an object `{ integrations: { type: string, title: string, host: string }[] }` instead of just an array.
87
+ - a2589000ee: - **BREAKING** - Removed the `plugin` export, use `scaffolderPlugin` instead.
88
+ - **BREAKING** - Removed the `TextValuePicker` component export, you can inline this component instead as it's a simple wrapper around a `TextField` from `@material-ui/core`.
89
+
90
+ ### Patch Changes
91
+
92
+ - 67a7c02d26: Remove usages of `EntityRef` and `parseEntityName` from `@backstage/catalog-model`
93
+ - 6e1cbc12a6: Updated according to the new `getEntityFacets` catalog API method
94
+ - b776ce5aab: Replaced use of deprecated `useEntityListProvider` hook with `useEntityList`.
95
+ - 0f37cdef19: Migrated over from the deprecated `spec.metadata` to `spec.templateInfo` for the `name` and the `baseUrl` of the template.
96
+ - 50e0242ac2: - Moved the `JSONSchema` type from `@backstage/catalog-model` to `JSONSchema7`.
97
+ - Renamed and prefixed some types ready for exporting.
98
+ - a2589000ee: - Reworking the `FieldExtensionComponentType` so we can export the `ui:schema:options` props in the `api-report.md`.
99
+ - Exporting all of the `UiOptions` types for the `FieldExtensions` so we can see them in the `api-report.md`.
100
+ - Removing the redundant type in the `CustomFieldValidator` union.
101
+ - 2f2543592c: You can now hide sections or fields in your templates based on a feature flag. For example, take this template:
102
+
103
+ ```json
104
+ {
105
+ title: 'my-schema',
106
+ steps: [
107
+ {
108
+ title: 'Fill in some steps',
109
+ schema: {
110
+ title: 'Fill in some steps',
111
+ 'backstage:featureFlag': 'experimental-feature',
112
+ properties: {
113
+ name: {
114
+ title: 'Name',
115
+ type: 'string',
116
+ 'backstage:featureFlag': 'should-show-some-stuff-first-option',
117
+ },
118
+ description: {
119
+ title: 'Description',
120
+ type: 'string',
121
+ description: 'A description for the component',
122
+ },
123
+ owner: {
124
+ title: 'Owner',
125
+ type: 'string',
126
+ description: 'Owner of the component',
127
+ },
128
+ },
129
+ type: 'object',
130
+ },
131
+ },
132
+ }
133
+
134
+ ```
135
+
136
+ If you have a feature flag that is called `experimental-feature` then your first step would be shown if you that feature flag was not active then it wouldn't be shown. The same goes for the properties in the schema. Make sure to use the key `backstage:featureFlag` in your templates if you want to use this functionality.
137
+
138
+ - Updated dependencies
139
+ - @backstage/core-components@0.8.10
140
+ - @backstage/plugin-scaffolder-common@0.2.2
141
+ - @backstage/plugin-catalog-react@0.7.0
142
+ - @backstage/catalog-model@0.11.0
143
+ - @backstage/catalog-client@0.7.2
144
+ - @backstage/core-plugin-api@0.7.0
145
+ - @backstage/integration@0.7.5
146
+ - @backstage/integration-react@0.1.23
147
+ - @backstage/plugin-permission-react@0.3.2
148
+
3
149
  ## 0.12.3
4
150
 
5
151
  ### Patch Changes
@@ -1,10 +1,13 @@
1
1
  import React, { useState, useContext, useCallback } from 'react';
2
- import { useNavigate, Navigate, generatePath, useOutlet, Routes, Route } from 'react-router';
3
- import { Page, Header, Lifecycle, Content, ContentHeader, CreateButton, SupportButton, MarkdownContent, StructuredMetadataTable, InfoCard, Progress, ErrorPage } from '@backstage/core-components';
4
- import { useRouteRef, useApi, errorApiRef, useApiHolder, useElementFilter } from '@backstage/core-plugin-api';
5
- import { EntityListProvider, EntitySearchBar, EntityKindPicker, UserListPicker, EntityTagPicker } from '@backstage/plugin-catalog-react';
6
- import { makeStyles, Stepper, Step, StepLabel, Typography, StepContent, Button, Paper, Box, LinearProgress, TableContainer, Table, TableHead, TableRow, TableCell, TableBody } from '@material-ui/core';
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, d as registerComponentRouteRef, T as TemplateTypePicker, f as TemplateList, S as SecretsContext, s as scaffolderApiRef, g as rootRouteRef, F as FIELD_EXTENSION_WRAPPER_KEY, h as FIELD_EXTENSION_KEY, i as SecretsContextProvider, j as TaskPage } from './index-87e5c74b.esm.js';
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, Lifecycle, CreateButton, SupportButton, StructuredMetadataTable, InfoCard, ErrorPage } from '@backstage/core-components';
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 { 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 } from '@material-ui/core';
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-3fd3ab40.esm.js';
8
+ import { RELATION_OWNED_BY, stringifyEntityRef } from '@backstage/catalog-model';
9
+ import { scmIntegrationsApiRef, ScmIntegrationIcon } from '@backstage/integration-react';
10
+ import WarningIcon from '@material-ui/icons/Warning';
8
11
  import { catalogEntityCreatePermission } from '@backstage/plugin-catalog-common';
9
12
  import { usePermission } from '@backstage/plugin-permission-react';
10
13
  import qs from 'qs';
@@ -12,22 +15,18 @@ import { useParams } from 'react-router-dom';
12
15
  import useAsync from 'react-use/lib/useAsync';
13
16
  import { withTheme } from '@rjsf/core';
14
17
  import { Theme } from '@rjsf/material-ui';
18
+ import cloneDeep from 'lodash/cloneDeep';
15
19
  import classNames from 'classnames';
16
20
  import '@backstage/errors';
17
21
  import 'zen-observable';
18
22
  import '@material-ui/core/FormControl';
19
23
  import '@material-ui/lab/Autocomplete';
20
- import '@backstage/catalog-model';
21
24
  import 'react-use/lib/useEffectOnce';
22
25
  import '@material-ui/lab';
23
- import '@backstage/integration-react';
24
26
  import '@material-ui/core/FormHelperText';
25
27
  import '@material-ui/core/Input';
26
28
  import '@material-ui/core/InputLabel';
27
29
  import 'react-use/lib/useDebounce';
28
- import '@material-ui/icons/Star';
29
- import '@material-ui/icons/StarBorder';
30
- import '@material-ui/icons/Warning';
31
30
  import 'lodash/capitalize';
32
31
  import '@material-ui/icons/CheckBox';
33
32
  import '@material-ui/icons/CheckBoxOutlineBlank';
@@ -75,6 +74,173 @@ const DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS = [
75
74
  }
76
75
  ];
77
76
 
77
+ const useStyles$2 = makeStyles((theme) => ({
78
+ cardHeader: {
79
+ position: "relative"
80
+ },
81
+ title: {
82
+ backgroundImage: ({ backgroundImage }) => backgroundImage
83
+ },
84
+ box: {
85
+ overflow: "hidden",
86
+ textOverflow: "ellipsis",
87
+ display: "-webkit-box",
88
+ "-webkit-line-clamp": 10,
89
+ "-webkit-box-orient": "vertical",
90
+ paddingBottom: "0.8em"
91
+ },
92
+ label: {
93
+ color: theme.palette.text.secondary,
94
+ textTransform: "uppercase",
95
+ fontSize: "0.65rem",
96
+ fontWeight: "bold",
97
+ letterSpacing: 0.5,
98
+ lineHeight: 1,
99
+ paddingBottom: "0.2rem"
100
+ },
101
+ leftButton: {
102
+ marginRight: "auto"
103
+ },
104
+ starButton: {
105
+ position: "absolute",
106
+ top: theme.spacing(0.5),
107
+ right: theme.spacing(0.5),
108
+ padding: "0.25rem"
109
+ }
110
+ }));
111
+ const useDeprecationStyles = makeStyles((theme) => ({
112
+ deprecationIcon: {
113
+ position: "absolute",
114
+ top: theme.spacing(0.5),
115
+ right: theme.spacing(3.5),
116
+ padding: "0.25rem"
117
+ },
118
+ link: {
119
+ color: theme.palette.warning.light
120
+ }
121
+ }));
122
+ const getTemplateCardProps = (template) => {
123
+ var _a, _b, _c, _d, _e;
124
+ return {
125
+ key: template.metadata.uid,
126
+ name: template.metadata.name,
127
+ title: `${(_a = template.metadata.title || template.metadata.name) != null ? _a : ""}`,
128
+ type: (_b = template.spec.type) != null ? _b : "",
129
+ description: (_c = template.metadata.description) != null ? _c : "-",
130
+ tags: (_e = (_d = template.metadata) == null ? void 0 : _d.tags) != null ? _e : []
131
+ };
132
+ };
133
+ const DeprecationWarning = () => {
134
+ const styles = useDeprecationStyles();
135
+ const Title = /* @__PURE__ */ React.createElement(Typography, {
136
+ style: { padding: 10, maxWidth: 300 }
137
+ }, "This template uses a syntax that has been deprecated, and should be migrated to a newer syntax. Click for more info.");
138
+ return /* @__PURE__ */ React.createElement("div", {
139
+ className: styles.deprecationIcon
140
+ }, /* @__PURE__ */ React.createElement(Tooltip, {
141
+ title: Title
142
+ }, /* @__PURE__ */ React.createElement(Link, {
143
+ href: "https://backstage.io/docs/features/software-templates/migrating-from-v1beta2-to-v1beta3",
144
+ className: styles.link
145
+ }, /* @__PURE__ */ React.createElement(WarningIcon, null))));
146
+ };
147
+ const TemplateCard = ({ template, deprecated }) => {
148
+ var _a;
149
+ const backstageTheme = useTheme();
150
+ const templateRoute = useRouteRef(selectedTemplateRouteRef);
151
+ const templateProps = getTemplateCardProps(template);
152
+ const ownedByRelations = getEntityRelations(template, RELATION_OWNED_BY);
153
+ const themeId = backstageTheme.getPageTheme({ themeId: templateProps.type }) ? templateProps.type : "other";
154
+ const theme = backstageTheme.getPageTheme({ themeId });
155
+ const classes = useStyles$2({ backgroundImage: theme.backgroundImage });
156
+ const href = templateRoute({ templateName: templateProps.name });
157
+ const scmIntegrationsApi = useApi(scmIntegrationsApiRef);
158
+ const sourceLocation = getEntitySourceLocation(template, scmIntegrationsApi);
159
+ return /* @__PURE__ */ React.createElement(Card, null, /* @__PURE__ */ React.createElement(CardMedia, {
160
+ className: classes.cardHeader
161
+ }, /* @__PURE__ */ React.createElement(FavoriteEntity, {
162
+ className: classes.starButton,
163
+ entity: template
164
+ }), deprecated && /* @__PURE__ */ React.createElement(DeprecationWarning, null), /* @__PURE__ */ React.createElement(ItemCardHeader, {
165
+ title: templateProps.title,
166
+ subtitle: templateProps.type,
167
+ classes: { root: classes.title }
168
+ })), /* @__PURE__ */ React.createElement(CardContent, {
169
+ style: { display: "grid" }
170
+ }, /* @__PURE__ */ React.createElement(Box, {
171
+ className: classes.box
172
+ }, /* @__PURE__ */ React.createElement(Typography, {
173
+ variant: "body2",
174
+ className: classes.label
175
+ }, "Description"), /* @__PURE__ */ React.createElement(MarkdownContent, {
176
+ content: templateProps.description
177
+ })), /* @__PURE__ */ React.createElement(Box, {
178
+ className: classes.box
179
+ }, /* @__PURE__ */ React.createElement(Typography, {
180
+ variant: "body2",
181
+ className: classes.label
182
+ }, "Owner"), /* @__PURE__ */ React.createElement(EntityRefLinks, {
183
+ entityRefs: ownedByRelations,
184
+ defaultKind: "Group"
185
+ })), /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Typography, {
186
+ variant: "body2",
187
+ className: classes.label
188
+ }, "Tags"), (_a = templateProps.tags) == null ? void 0 : _a.map((tag) => /* @__PURE__ */ React.createElement(Chip, {
189
+ size: "small",
190
+ label: tag,
191
+ key: tag
192
+ })))), /* @__PURE__ */ React.createElement(CardActions, null, sourceLocation && /* @__PURE__ */ React.createElement(IconButton, {
193
+ className: classes.leftButton,
194
+ href: sourceLocation.locationTargetUrl
195
+ }, /* @__PURE__ */ React.createElement(ScmIntegrationIcon, {
196
+ type: sourceLocation.integrationType
197
+ })), /* @__PURE__ */ React.createElement(Button, {
198
+ color: "primary",
199
+ to: href,
200
+ "aria-label": `Choose ${templateProps.title}`
201
+ }, "Choose")));
202
+ };
203
+
204
+ const TemplateList = ({
205
+ TemplateCardComponent,
206
+ group
207
+ }) => {
208
+ const { loading, error, entities } = useEntityList();
209
+ const Card = TemplateCardComponent || TemplateCard;
210
+ const maybeFilteredEntities = group ? entities.filter((e) => group.filter(e)) : entities;
211
+ const titleComponent = (() => {
212
+ if (group == null ? void 0 : group.titleComponent) {
213
+ console.warn("DEPRECATED: group.titleComponent is now deprecated. Use group.title instead, it can be a string or a react component");
214
+ return group == null ? void 0 : group.titleComponent;
215
+ }
216
+ if (group && group.title) {
217
+ if (typeof group.title === "string") {
218
+ return /* @__PURE__ */ React.createElement(ContentHeader, {
219
+ title: group.title
220
+ });
221
+ }
222
+ return group.title;
223
+ }
224
+ return /* @__PURE__ */ React.createElement(ContentHeader, {
225
+ title: "Other Templates"
226
+ });
227
+ })();
228
+ if (group && maybeFilteredEntities.length === 0) {
229
+ return null;
230
+ }
231
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, loading && /* @__PURE__ */ React.createElement(Progress, null), error && /* @__PURE__ */ React.createElement(WarningPanel, {
232
+ title: "Oops! Something went wrong loading the templates"
233
+ }, error.message), !error && !loading && !entities.length && /* @__PURE__ */ React.createElement(Typography, {
234
+ variant: "body2"
235
+ }, "No templates found that match your filter. Learn more about", " ", /* @__PURE__ */ React.createElement(Link$1, {
236
+ to: "https://backstage.io/docs/features/software-templates/adding-templates"
237
+ }, "adding templates"), "."), /* @__PURE__ */ React.createElement(Content, null, titleComponent, /* @__PURE__ */ React.createElement(ItemCardGrid, null, maybeFilteredEntities && (maybeFilteredEntities == null ? void 0 : maybeFilteredEntities.length) > 0 && maybeFilteredEntities.map((template) => /* @__PURE__ */ React.createElement(Card, {
238
+ key: stringifyEntityRef(template),
239
+ template,
240
+ deprecated: template.apiVersion === "backstage.io/v1beta2"
241
+ })))));
242
+ };
243
+
78
244
  const useStyles$1 = makeStyles((theme) => ({
79
245
  contentWrapper: {
80
246
  display: "grid",
@@ -271,18 +437,36 @@ function getReviewData(formData, steps) {
271
437
  }
272
438
  return reviewData;
273
439
  }
274
- const MultistepJsonForm = ({
275
- steps,
276
- formData,
277
- onChange,
278
- onReset,
279
- onFinish,
280
- fields,
281
- widgets
282
- }) => {
440
+ const MultistepJsonForm = (props) => {
441
+ const { formData, onChange, onReset, onFinish, fields, widgets } = props;
283
442
  const [activeStep, setActiveStep] = useState(0);
284
443
  const [disableButtons, setDisableButtons] = useState(false);
285
444
  const errorApi = useApi(errorApiRef);
445
+ const featureFlagApi = useApi(featureFlagsApiRef);
446
+ const featureFlagKey = "backstage:featureFlag";
447
+ const filterOutProperties = (step) => {
448
+ var _a;
449
+ const filteredStep = cloneDeep(step);
450
+ const removedPropertyKeys = [];
451
+ if (filteredStep.schema.properties) {
452
+ filteredStep.schema.properties = Object.fromEntries(Object.entries(filteredStep.schema.properties).filter(([key, value]) => {
453
+ if (value[featureFlagKey]) {
454
+ if (featureFlagApi.isActive(value[featureFlagKey])) {
455
+ return true;
456
+ }
457
+ removedPropertyKeys.push(key);
458
+ return false;
459
+ }
460
+ return true;
461
+ }));
462
+ filteredStep.schema.required = Array.isArray(filteredStep.schema.required) ? (_a = filteredStep.schema.required) == null ? void 0 : _a.filter((r) => !removedPropertyKeys.includes(r)) : filteredStep.schema.required;
463
+ }
464
+ return filteredStep;
465
+ };
466
+ const steps = props.steps.filter((step) => {
467
+ const featureFlag = step.schema[featureFlagKey];
468
+ return typeof featureFlag !== "string" || featureFlagApi.isActive(featureFlag);
469
+ }).map(filterOutProperties);
286
470
  const handleReset = () => {
287
471
  setActiveStep(0);
288
472
  onReset();
@@ -328,10 +512,10 @@ const MultistepJsonForm = ({
328
512
  },
329
513
  ...formProps,
330
514
  ...transformSchemaToProps(schema)
331
- }, /* @__PURE__ */ React.createElement(Button, {
515
+ }, /* @__PURE__ */ React.createElement(Button$1, {
332
516
  disabled: activeStep === 0,
333
517
  onClick: handleBack
334
- }, "Back"), /* @__PURE__ */ React.createElement(Button, {
518
+ }, "Back"), /* @__PURE__ */ React.createElement(Button$1, {
335
519
  variant: "contained",
336
520
  color: "primary",
337
521
  type: "submit"
@@ -346,13 +530,13 @@ const MultistepJsonForm = ({
346
530
  metadata: getReviewData(formData, steps)
347
531
  }), /* @__PURE__ */ React.createElement(Box, {
348
532
  mb: 4
349
- }), /* @__PURE__ */ React.createElement(Button, {
533
+ }), /* @__PURE__ */ React.createElement(Button$1, {
350
534
  onClick: handleBack,
351
535
  disabled: disableButtons
352
- }, "Back"), /* @__PURE__ */ React.createElement(Button, {
536
+ }, "Back"), /* @__PURE__ */ React.createElement(Button$1, {
353
537
  onClick: handleReset,
354
538
  disabled: disableButtons
355
- }, "Reset"), /* @__PURE__ */ React.createElement(Button, {
539
+ }, "Reset"), /* @__PURE__ */ React.createElement(Button$1, {
356
540
  variant: "contained",
357
541
  color: "primary",
358
542
  onClick: handleCreate,
@@ -360,13 +544,9 @@ const MultistepJsonForm = ({
360
544
  }, "Create"))));
361
545
  };
362
546
 
363
- const useTemplateParameterSchema = (templateName) => {
547
+ const useTemplateParameterSchema = (templateRef) => {
364
548
  const scaffolderApi = useApi(scaffolderApiRef);
365
- const { value, loading, error } = useAsync(() => scaffolderApi.getTemplateParameterSchema({
366
- name: templateName,
367
- kind: "template",
368
- namespace: "default"
369
- }), [scaffolderApi, templateName]);
549
+ const { value, loading, error } = useAsync(() => scaffolderApi.getTemplateParameterSchema(templateRef), [scaffolderApi, templateRef]);
370
550
  return { schema: value, loading, error };
371
551
  };
372
552
  function isObject(obj) {
@@ -408,7 +588,8 @@ const TemplatePage = ({
408
588
  const scaffolderApi = useApi(scaffolderApiRef);
409
589
  const { templateName } = useParams();
410
590
  const navigate = useNavigate();
411
- const rootLink = useRouteRef(rootRouteRef);
591
+ const scaffolderTaskRoute = useRouteRef(scaffolderTaskRouteRef);
592
+ const rootRoute = useRouteRef(rootRouteRef);
412
593
  const { schema, loading, error } = useTemplateParameterSchema(templateName);
413
594
  const [formState, setFormState] = useState(() => {
414
595
  var _a;
@@ -425,22 +606,30 @@ const TemplatePage = ({
425
606
  const handleChange = useCallback((e) => setFormState(e.formData), [setFormState]);
426
607
  const handleCreate = async () => {
427
608
  var _a;
428
- const id = await scaffolderApi.scaffold(templateName, formState, secretsContext == null ? void 0 : secretsContext.secrets);
609
+ const { taskId } = await scaffolderApi.scaffold({
610
+ templateRef: stringifyEntityRef({
611
+ name: templateName,
612
+ kind: "template",
613
+ namespace: "default"
614
+ }),
615
+ values: formState,
616
+ secrets: secretsContext == null ? void 0 : secretsContext.secrets
617
+ });
429
618
  const formParams = qs.stringify({ formData: formState }, { addQueryPrefix: true });
430
619
  const newUrl = `${window.location.pathname}${formParams}`;
431
620
  (_a = window.history) == null ? void 0 : _a.replaceState(null, document.title, newUrl);
432
- navigate(generatePath(`${rootLink()}/tasks/:taskId`, { taskId: id }));
621
+ navigate(scaffolderTaskRoute({ taskId }));
433
622
  };
434
623
  if (error) {
435
624
  errorApi.post(new Error(`Failed to load template, ${error}`));
436
625
  return /* @__PURE__ */ React.createElement(Navigate, {
437
- to: rootLink()
626
+ to: rootRoute()
438
627
  });
439
628
  }
440
629
  if (!loading && !schema) {
441
630
  errorApi.post(new Error("Template was not found."));
442
631
  return /* @__PURE__ */ React.createElement(Navigate, {
443
- to: rootLink()
632
+ to: rootRoute()
444
633
  });
445
634
  }
446
635
  const customFieldComponents = Object.fromEntries(customFieldExtensions.map(({ name, component }) => [name, component]));
@@ -582,13 +771,11 @@ const ActionsPage = () => {
582
771
  }), /* @__PURE__ */ React.createElement(Content, null, items));
583
772
  };
584
773
 
585
- const Router = ({
586
- TemplateCardComponent,
587
- TaskPageComponent,
588
- groups
589
- }) => {
774
+ const Router = (props) => {
775
+ const { groups, components = {} } = props;
776
+ const { TemplateCardComponent, TaskPageComponent } = components;
590
777
  const outlet = useOutlet();
591
- const TaskPageElement = TaskPageComponent || TaskPage;
778
+ const TaskPageElement = TaskPageComponent != null ? TaskPageComponent : TaskPage;
592
779
  const customFieldExtensions = useElementFilter(outlet, (elements) => elements.selectByComponentData({
593
780
  key: FIELD_EXTENSION_WRAPPER_KEY
594
781
  }).findComponentData({
@@ -601,8 +788,8 @@ const Router = ({
601
788
  return /* @__PURE__ */ React.createElement(Routes, null, /* @__PURE__ */ React.createElement(Route, {
602
789
  path: "/",
603
790
  element: /* @__PURE__ */ React.createElement(ScaffolderPage, {
604
- TemplateCardComponent,
605
- groups
791
+ groups,
792
+ TemplateCardComponent
606
793
  })
607
794
  }), /* @__PURE__ */ React.createElement(Route, {
608
795
  path: "/templates/:templateName",
@@ -619,4 +806,4 @@ const Router = ({
619
806
  };
620
807
 
621
808
  export { Router };
622
- //# sourceMappingURL=Router-fe84df85.esm.js.map
809
+ //# sourceMappingURL=Router-722c3528.esm.js.map