@backstage/plugin-scaffolder 0.12.2 → 0.14.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 +129 -0
- package/dist/esm/{Router-5df57206.esm.js → Router-ba25f61c.esm.js} +64 -35
- package/dist/esm/Router-ba25f61c.esm.js.map +1 -0
- package/dist/esm/{index-71578268.esm.js → index-da137e20.esm.js} +148 -148
- package/dist/esm/index-da137e20.esm.js.map +1 -0
- package/dist/index.d.ts +162 -111
- package/dist/index.esm.js +3 -5
- package/dist/index.esm.js.map +1 -1
- package/package.json +33 -29
- package/dist/esm/Router-5df57206.esm.js.map +0 -1
- package/dist/esm/index-71578268.esm.js.map +0 -1
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { parseEntityRef, KubernetesValidatorFunctions, makeValidator, RELATION_OWNED_BY, stringifyEntityRef } from '@backstage/catalog-model';
|
|
2
|
+
import { createApiRef, useApi, attachComponentData, createExternalRouteRef, createRouteRef, createSubRouteRef, createPlugin, createApiFactory, discoveryApiRef, fetchApiRef, createRoutableExtension, useRouteRef, alertApiRef, useApp } from '@backstage/core-plugin-api';
|
|
2
3
|
import { ResponseError } from '@backstage/errors';
|
|
3
4
|
import qs from 'qs';
|
|
4
5
|
import ObservableImpl from 'zen-observable';
|
|
5
|
-
import { catalogApiRef,
|
|
6
|
-
import { TextField, FormControl as FormControl$1,
|
|
6
|
+
import { catalogApiRef, humanizeEntityRef, useOwnedEntities, getEntityRelations, getEntitySourceLocation, FavoriteEntity, EntityRefLinks, useEntityList, useEntityTypeFilter, entityRouteRef } from '@backstage/plugin-catalog-react';
|
|
7
|
+
import { TextField, FormControl as FormControl$1, makeStyles, useTheme, Card, CardMedia, CardContent, Box, Typography, Chip, CardActions, IconButton, Tooltip, Link, FormControlLabel, Checkbox, Grid, StepButton, Paper, Button as Button$1, CircularProgress } from '@material-ui/core';
|
|
7
8
|
import FormControl from '@material-ui/core/FormControl';
|
|
8
9
|
import Autocomplete from '@material-ui/lab/Autocomplete';
|
|
9
10
|
import React, { useCallback, useEffect, useState, createContext, useContext, useMemo, memo } from 'react';
|
|
10
11
|
import useAsync from 'react-use/lib/useAsync';
|
|
11
|
-
import { KubernetesValidatorFunctions, makeValidator, RELATION_OWNED_BY, stringifyEntityRef, parseEntityName } from '@backstage/catalog-model';
|
|
12
12
|
import useEffectOnce from 'react-use/lib/useEffectOnce';
|
|
13
13
|
import { Autocomplete as Autocomplete$1 } from '@material-ui/lab';
|
|
14
14
|
import { scmIntegrationsApiRef, scmAuthApiRef, ScmIntegrationIcon } from '@backstage/integration-react';
|
|
@@ -17,10 +17,7 @@ import Input from '@material-ui/core/Input';
|
|
|
17
17
|
import InputLabel from '@material-ui/core/InputLabel';
|
|
18
18
|
import { Select, Progress, ItemCardHeader, Button, ContentHeader, WarningPanel, Link as Link$1, Content, ItemCardGrid, Page, Header, Lifecycle, ErrorPage, LogViewer } from '@backstage/core-components';
|
|
19
19
|
import useDebounce from 'react-use/lib/useDebounce';
|
|
20
|
-
import Star from '@material-ui/icons/Star';
|
|
21
|
-
import StarBorder from '@material-ui/icons/StarBorder';
|
|
22
20
|
import WarningIcon from '@material-ui/icons/Warning';
|
|
23
|
-
import { generatePath, useNavigate, useParams } from 'react-router';
|
|
24
21
|
import capitalize from 'lodash/capitalize';
|
|
25
22
|
import CheckBoxIcon from '@material-ui/icons/CheckBox';
|
|
26
23
|
import CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank';
|
|
@@ -36,6 +33,7 @@ import Check from '@material-ui/icons/Check';
|
|
|
36
33
|
import FiberManualRecordIcon from '@material-ui/icons/FiberManualRecord';
|
|
37
34
|
import classNames from 'classnames';
|
|
38
35
|
import { DateTime, Interval } from 'luxon';
|
|
36
|
+
import { useNavigate, useParams } from 'react-router';
|
|
39
37
|
import useInterval from 'react-use/lib/useInterval';
|
|
40
38
|
import { useImmerReducer } from 'use-immer';
|
|
41
39
|
import LanguageIcon from '@material-ui/icons/Language';
|
|
@@ -52,15 +50,20 @@ class ScaffolderClient {
|
|
|
52
50
|
this.useLongPollingLogs = (_b = options.useLongPollingLogs) != null ? _b : false;
|
|
53
51
|
}
|
|
54
52
|
async getIntegrationsList(options) {
|
|
55
|
-
|
|
53
|
+
const integrations = [
|
|
56
54
|
...this.scmIntegrationsApi.azure.list(),
|
|
57
55
|
...this.scmIntegrationsApi.bitbucket.list(),
|
|
58
56
|
...this.scmIntegrationsApi.github.list(),
|
|
59
57
|
...this.scmIntegrationsApi.gitlab.list()
|
|
60
58
|
].map((c) => ({ type: c.type, title: c.title, host: c.config.host })).filter((c) => options.allowedHosts.includes(c.host));
|
|
59
|
+
return {
|
|
60
|
+
integrations
|
|
61
|
+
};
|
|
61
62
|
}
|
|
62
|
-
async getTemplateParameterSchema(
|
|
63
|
-
const { namespace, kind, name } =
|
|
63
|
+
async getTemplateParameterSchema(templateRef) {
|
|
64
|
+
const { namespace, kind, name } = parseEntityRef(templateRef, {
|
|
65
|
+
defaultKind: "template"
|
|
66
|
+
});
|
|
64
67
|
const baseUrl = await this.discoveryApi.getBaseUrl("scaffolder");
|
|
65
68
|
const templatePath = [namespace, kind, name].map((s) => encodeURIComponent(s)).join("/");
|
|
66
69
|
const url = `${baseUrl}/v2/templates/${templatePath}/parameter-schema`;
|
|
@@ -71,7 +74,8 @@ class ScaffolderClient {
|
|
|
71
74
|
const schema = await response.json();
|
|
72
75
|
return schema;
|
|
73
76
|
}
|
|
74
|
-
async scaffold(
|
|
77
|
+
async scaffold(options) {
|
|
78
|
+
const { templateRef, values, secrets = {} } = options;
|
|
75
79
|
const url = `${await this.discoveryApi.getBaseUrl("scaffolder")}/v2/tasks`;
|
|
76
80
|
const response = await this.fetchApi.fetch(url, {
|
|
77
81
|
method: "POST",
|
|
@@ -79,7 +83,7 @@ class ScaffolderClient {
|
|
|
79
83
|
"Content-Type": "application/json"
|
|
80
84
|
},
|
|
81
85
|
body: JSON.stringify({
|
|
82
|
-
|
|
86
|
+
templateRef,
|
|
83
87
|
values: { ...values },
|
|
84
88
|
secrets
|
|
85
89
|
})
|
|
@@ -90,7 +94,7 @@ class ScaffolderClient {
|
|
|
90
94
|
throw new Error(`Backend request failed, ${status} ${body.trim()}`);
|
|
91
95
|
}
|
|
92
96
|
const { id } = await response.json();
|
|
93
|
-
return id;
|
|
97
|
+
return { taskId: id };
|
|
94
98
|
}
|
|
95
99
|
async getTask(taskId) {
|
|
96
100
|
const baseUrl = await this.discoveryApi.getBaseUrl("scaffolder");
|
|
@@ -184,25 +188,22 @@ class ScaffolderClient {
|
|
|
184
188
|
}
|
|
185
189
|
}
|
|
186
190
|
|
|
187
|
-
const
|
|
188
|
-
var _a, _b;
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
idSchema
|
|
199
|
-
}) => {
|
|
200
|
-
var _a, _b;
|
|
191
|
+
const EntityPicker = (props) => {
|
|
192
|
+
var _a, _b, _c, _d;
|
|
193
|
+
const {
|
|
194
|
+
onChange,
|
|
195
|
+
schema: { title = "Entity", description = "An entity from the catalog" },
|
|
196
|
+
required,
|
|
197
|
+
uiSchema,
|
|
198
|
+
rawErrors,
|
|
199
|
+
formData,
|
|
200
|
+
idSchema
|
|
201
|
+
} = props;
|
|
201
202
|
const allowedKinds = (_a = uiSchema["ui:options"]) == null ? void 0 : _a.allowedKinds;
|
|
202
203
|
const defaultKind = (_b = uiSchema["ui:options"]) == null ? void 0 : _b.defaultKind;
|
|
203
204
|
const catalogApi = useApi(catalogApiRef);
|
|
204
205
|
const { value: entities, loading } = useAsync(() => catalogApi.getEntities(allowedKinds ? { filter: { kind: allowedKinds } } : void 0));
|
|
205
|
-
const entityRefs = entities == null ? void 0 : entities.items.map((e) =>
|
|
206
|
+
const entityRefs = entities == null ? void 0 : entities.items.map((e) => humanizeEntityRef(e, { defaultKind }));
|
|
206
207
|
const onSelect = useCallback((_, value) => {
|
|
207
208
|
onChange(value || "");
|
|
208
209
|
}, [onChange]);
|
|
@@ -223,7 +224,7 @@ const EntityPicker = ({
|
|
|
223
224
|
onChange: onSelect,
|
|
224
225
|
options: entityRefs || [],
|
|
225
226
|
autoSelect: true,
|
|
226
|
-
freeSolo:
|
|
227
|
+
freeSolo: (_d = (_c = uiSchema["ui:options"]) == null ? void 0 : _c.allowArbitraryValues) != null ? _d : true,
|
|
227
228
|
renderInput: (params) => /* @__PURE__ */ React.createElement(TextField, {
|
|
228
229
|
...params,
|
|
229
230
|
label: title,
|
|
@@ -236,35 +237,30 @@ const EntityPicker = ({
|
|
|
236
237
|
}));
|
|
237
238
|
};
|
|
238
239
|
|
|
239
|
-
const
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
...props
|
|
264
|
-
}) => /* @__PURE__ */ React.createElement(TextValuePicker, {
|
|
265
|
-
schema: { title, description },
|
|
266
|
-
...props
|
|
267
|
-
});
|
|
240
|
+
const EntityNamePicker = (props) => {
|
|
241
|
+
const {
|
|
242
|
+
onChange,
|
|
243
|
+
required,
|
|
244
|
+
schema: { title = "Name", description = "Unique name of the component" },
|
|
245
|
+
rawErrors,
|
|
246
|
+
formData,
|
|
247
|
+
uiSchema: { "ui:autofocus": autoFocus },
|
|
248
|
+
idSchema,
|
|
249
|
+
placeholder
|
|
250
|
+
} = props;
|
|
251
|
+
return /* @__PURE__ */ React.createElement(TextField, {
|
|
252
|
+
id: idSchema == null ? void 0 : idSchema.$id,
|
|
253
|
+
label: title,
|
|
254
|
+
placeholder,
|
|
255
|
+
helperText: description,
|
|
256
|
+
required,
|
|
257
|
+
value: formData != null ? formData : "",
|
|
258
|
+
onChange: ({ target: { value } }) => onChange(value),
|
|
259
|
+
margin: "normal",
|
|
260
|
+
error: (rawErrors == null ? void 0 : rawErrors.length) > 0 && !formData,
|
|
261
|
+
inputProps: { autoFocus }
|
|
262
|
+
});
|
|
263
|
+
};
|
|
268
264
|
|
|
269
265
|
const entityNamePickerValidation = (value, validation) => {
|
|
270
266
|
if (!KubernetesValidatorFunctions.isValidObjectName(value)) {
|
|
@@ -272,12 +268,9 @@ const entityNamePickerValidation = (value, validation) => {
|
|
|
272
268
|
}
|
|
273
269
|
};
|
|
274
270
|
|
|
275
|
-
const EntityTagsPicker = ({
|
|
276
|
-
formData,
|
|
277
|
-
onChange,
|
|
278
|
-
uiSchema
|
|
279
|
-
}) => {
|
|
271
|
+
const EntityTagsPicker = (props) => {
|
|
280
272
|
var _a;
|
|
273
|
+
const { formData, onChange, uiSchema } = props;
|
|
281
274
|
const catalogApi = useApi(catalogApiRef);
|
|
282
275
|
const [inputValue, setInputValue] = useState("");
|
|
283
276
|
const [inputError, setInputError] = useState(false);
|
|
@@ -334,12 +327,13 @@ const EntityTagsPicker = ({
|
|
|
334
327
|
}));
|
|
335
328
|
};
|
|
336
329
|
|
|
337
|
-
const OwnerPicker = ({
|
|
338
|
-
schema: { title = "Owner", description = "The owner of the component" },
|
|
339
|
-
uiSchema,
|
|
340
|
-
...props
|
|
341
|
-
}) => {
|
|
330
|
+
const OwnerPicker = (props) => {
|
|
342
331
|
var _a;
|
|
332
|
+
const {
|
|
333
|
+
schema: { title = "Owner", description = "The owner of the component" },
|
|
334
|
+
uiSchema,
|
|
335
|
+
...restProps
|
|
336
|
+
} = props;
|
|
343
337
|
const ownerUiSchema = {
|
|
344
338
|
...uiSchema,
|
|
345
339
|
"ui:options": {
|
|
@@ -351,7 +345,7 @@ const OwnerPicker = ({
|
|
|
351
345
|
}
|
|
352
346
|
};
|
|
353
347
|
return /* @__PURE__ */ React.createElement(EntityPicker, {
|
|
354
|
-
...
|
|
348
|
+
...restProps,
|
|
355
349
|
schema: { title, description },
|
|
356
350
|
uiSchema: ownerUiSchema
|
|
357
351
|
});
|
|
@@ -502,7 +496,7 @@ const BitbucketRepoPicker = (props) => {
|
|
|
502
496
|
const RepoUrlPickerHost = (props) => {
|
|
503
497
|
const { host, hosts, onChange, rawErrors } = props;
|
|
504
498
|
const scaffolderApi = useApi(scaffolderApiRef);
|
|
505
|
-
const { value: integrations, loading } = useAsync(async () => {
|
|
499
|
+
const { value: { integrations } = { integrations: [] }, loading } = useAsync(async () => {
|
|
506
500
|
return await scaffolderApi.getIntegrationsList({
|
|
507
501
|
allowedHosts: hosts != null ? hosts : []
|
|
508
502
|
});
|
|
@@ -591,11 +585,11 @@ const useTemplateSecrets = () => {
|
|
|
591
585
|
if (!value) {
|
|
592
586
|
throw new Error("useTemplateSecrets must be used within a SecretsContextProvider");
|
|
593
587
|
}
|
|
594
|
-
const { setSecrets } = value;
|
|
595
|
-
const
|
|
596
|
-
|
|
597
|
-
}, [
|
|
598
|
-
return { setSecret };
|
|
588
|
+
const { setSecrets: updateSecrets } = value;
|
|
589
|
+
const setSecrets = useCallback((input) => {
|
|
590
|
+
updateSecrets((currentSecrets) => ({ ...currentSecrets, ...input }));
|
|
591
|
+
}, [updateSecrets]);
|
|
592
|
+
return { setSecret: setSecrets, setSecrets };
|
|
599
593
|
};
|
|
600
594
|
|
|
601
595
|
const RepoUrlPicker = (props) => {
|
|
@@ -604,7 +598,7 @@ const RepoUrlPicker = (props) => {
|
|
|
604
598
|
const [state, setState] = useState(parseRepoPickerUrl(formData));
|
|
605
599
|
const integrationApi = useApi(scmIntegrationsApiRef);
|
|
606
600
|
const scmAuthApi = useApi(scmAuthApiRef);
|
|
607
|
-
const {
|
|
601
|
+
const { setSecrets } = useTemplateSecrets();
|
|
608
602
|
const allowedHosts = useMemo(() => {
|
|
609
603
|
var _a2, _b2;
|
|
610
604
|
return (_b2 = (_a2 = uiSchema == null ? void 0 : uiSchema["ui:options"]) == null ? void 0 : _a2.allowedHosts) != null ? _b2 : [];
|
|
@@ -642,7 +636,7 @@ const RepoUrlPicker = (props) => {
|
|
|
642
636
|
customScopes: requestUserCredentials.additionalScopes
|
|
643
637
|
}
|
|
644
638
|
});
|
|
645
|
-
|
|
639
|
+
setSecrets({ [requestUserCredentials.secretsKey]: token });
|
|
646
640
|
}, 500, [state, uiSchema]);
|
|
647
641
|
const hostType = (_b = state.host && ((_a = integrationApi.byHost(state.host)) == null ? void 0 : _a.type)) != null ? _b : null;
|
|
648
642
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(RepoUrlPickerHost, {
|
|
@@ -700,20 +694,21 @@ const repoPickerValidation = (value, validation, context) => {
|
|
|
700
694
|
}
|
|
701
695
|
};
|
|
702
696
|
|
|
703
|
-
const OwnedEntityPicker = ({
|
|
704
|
-
onChange,
|
|
705
|
-
schema: { title = "Entity", description = "An entity from the catalog" },
|
|
706
|
-
required,
|
|
707
|
-
uiSchema,
|
|
708
|
-
rawErrors,
|
|
709
|
-
formData,
|
|
710
|
-
idSchema
|
|
711
|
-
}) => {
|
|
697
|
+
const OwnedEntityPicker = (props) => {
|
|
712
698
|
var _a, _b;
|
|
699
|
+
const {
|
|
700
|
+
onChange,
|
|
701
|
+
schema: { title = "Entity", description = "An entity from the catalog" },
|
|
702
|
+
required,
|
|
703
|
+
uiSchema,
|
|
704
|
+
rawErrors,
|
|
705
|
+
formData,
|
|
706
|
+
idSchema
|
|
707
|
+
} = props;
|
|
713
708
|
const allowedKinds = (_a = uiSchema["ui:options"]) == null ? void 0 : _a.allowedKinds;
|
|
714
709
|
const defaultKind = (_b = uiSchema["ui:options"]) == null ? void 0 : _b.defaultKind;
|
|
715
710
|
const { ownedEntities, loading } = useOwnedEntities(allowedKinds);
|
|
716
|
-
const entityRefs = ownedEntities == null ? void 0 : ownedEntities.items.map((e) =>
|
|
711
|
+
const entityRefs = ownedEntities == null ? void 0 : ownedEntities.items.map((e) => humanizeEntityRef(e, { defaultKind })).filter((n) => n);
|
|
717
712
|
const onSelect = (_, value) => {
|
|
718
713
|
onChange(value || "");
|
|
719
714
|
};
|
|
@@ -762,6 +757,21 @@ const registerComponentRouteRef = createExternalRouteRef({
|
|
|
762
757
|
const rootRouteRef = createRouteRef({
|
|
763
758
|
id: "scaffolder"
|
|
764
759
|
});
|
|
760
|
+
const selectedTemplateRouteRef = createSubRouteRef({
|
|
761
|
+
id: "scaffolder/selected-template",
|
|
762
|
+
parent: rootRouteRef,
|
|
763
|
+
path: "/templates/:templateName"
|
|
764
|
+
});
|
|
765
|
+
const scaffolderTaskRouteRef = createSubRouteRef({
|
|
766
|
+
id: "scaffolder/task",
|
|
767
|
+
parent: rootRouteRef,
|
|
768
|
+
path: "/tasks/:taskId"
|
|
769
|
+
});
|
|
770
|
+
createSubRouteRef({
|
|
771
|
+
id: "scaffolder/actions",
|
|
772
|
+
parent: rootRouteRef,
|
|
773
|
+
path: "/actions"
|
|
774
|
+
});
|
|
765
775
|
|
|
766
776
|
const scaffolderPlugin = createPlugin({
|
|
767
777
|
id: "scaffolder",
|
|
@@ -807,7 +817,7 @@ const OwnerPickerFieldExtension = scaffolderPlugin.provide(createScaffolderField
|
|
|
807
817
|
}));
|
|
808
818
|
const ScaffolderPage = scaffolderPlugin.provide(createRoutableExtension({
|
|
809
819
|
name: "ScaffolderPage",
|
|
810
|
-
component: () => import('./Router-
|
|
820
|
+
component: () => import('./Router-ba25f61c.esm.js').then((m) => m.Router),
|
|
811
821
|
mountPoint: rootRouteRef
|
|
812
822
|
}));
|
|
813
823
|
const OwnedEntityPickerFieldExtension = scaffolderPlugin.provide(createScaffolderFieldExtension({
|
|
@@ -819,39 +829,6 @@ const EntityTagsPickerFieldExtension = scaffolderPlugin.provide(createScaffolder
|
|
|
819
829
|
name: "EntityTagsPicker"
|
|
820
830
|
}));
|
|
821
831
|
|
|
822
|
-
const YellowStar = withStyles({
|
|
823
|
-
root: {
|
|
824
|
-
color: "#f3ba37"
|
|
825
|
-
}
|
|
826
|
-
})(Star);
|
|
827
|
-
const WhiteBorderStar = withStyles({
|
|
828
|
-
root: {
|
|
829
|
-
color: "#ffffff"
|
|
830
|
-
}
|
|
831
|
-
})(StarBorder);
|
|
832
|
-
const useStyles$3 = makeStyles((theme) => ({
|
|
833
|
-
starButton: {
|
|
834
|
-
position: "absolute",
|
|
835
|
-
top: theme.spacing(0.5),
|
|
836
|
-
right: theme.spacing(0.5),
|
|
837
|
-
padding: "0.25rem"
|
|
838
|
-
}
|
|
839
|
-
}));
|
|
840
|
-
const favouriteTemplateTooltip = (isStarred) => isStarred ? "Remove from favorites" : "Add to favorites";
|
|
841
|
-
const favouriteTemplateIcon = (isStarred) => isStarred ? /* @__PURE__ */ React.createElement(YellowStar, null) : /* @__PURE__ */ React.createElement(WhiteBorderStar, null);
|
|
842
|
-
const FavouriteTemplate = (props) => {
|
|
843
|
-
const classes = useStyles$3();
|
|
844
|
-
const { toggleStarredEntity, isStarredEntity } = useStarredEntity(props.entity);
|
|
845
|
-
return /* @__PURE__ */ React.createElement(IconButton, {
|
|
846
|
-
color: "inherit",
|
|
847
|
-
className: classes.starButton,
|
|
848
|
-
...props,
|
|
849
|
-
onClick: () => toggleStarredEntity()
|
|
850
|
-
}, /* @__PURE__ */ React.createElement(Tooltip, {
|
|
851
|
-
title: favouriteTemplateTooltip(isStarredEntity)
|
|
852
|
-
}, favouriteTemplateIcon(isStarredEntity)));
|
|
853
|
-
};
|
|
854
|
-
|
|
855
832
|
const useStyles$2 = makeStyles((theme) => ({
|
|
856
833
|
cardHeader: {
|
|
857
834
|
position: "relative"
|
|
@@ -878,6 +855,12 @@ const useStyles$2 = makeStyles((theme) => ({
|
|
|
878
855
|
},
|
|
879
856
|
leftButton: {
|
|
880
857
|
marginRight: "auto"
|
|
858
|
+
},
|
|
859
|
+
starButton: {
|
|
860
|
+
position: "absolute",
|
|
861
|
+
top: theme.spacing(0.5),
|
|
862
|
+
right: theme.spacing(0.5),
|
|
863
|
+
padding: "0.25rem"
|
|
881
864
|
}
|
|
882
865
|
}));
|
|
883
866
|
const useDeprecationStyles = makeStyles((theme) => ({
|
|
@@ -906,33 +889,32 @@ const DeprecationWarning = () => {
|
|
|
906
889
|
const styles = useDeprecationStyles();
|
|
907
890
|
const Title = /* @__PURE__ */ React.createElement(Typography, {
|
|
908
891
|
style: { padding: 10, maxWidth: 300 }
|
|
909
|
-
}, "This template syntax
|
|
892
|
+
}, "This template uses a syntax that has been deprecated, and should be migrated to a newer syntax. Click for more info.");
|
|
910
893
|
return /* @__PURE__ */ React.createElement("div", {
|
|
911
894
|
className: styles.deprecationIcon
|
|
912
895
|
}, /* @__PURE__ */ React.createElement(Tooltip, {
|
|
913
896
|
title: Title
|
|
914
897
|
}, /* @__PURE__ */ React.createElement(Link, {
|
|
915
|
-
href: "https://backstage.io/docs/features/software-templates/migrating-from-
|
|
898
|
+
href: "https://backstage.io/docs/features/software-templates/migrating-from-v1beta2-to-v1beta3",
|
|
916
899
|
className: styles.link
|
|
917
900
|
}, /* @__PURE__ */ React.createElement(WarningIcon, null))));
|
|
918
901
|
};
|
|
919
902
|
const TemplateCard = ({ template, deprecated }) => {
|
|
920
903
|
var _a;
|
|
921
904
|
const backstageTheme = useTheme();
|
|
922
|
-
const
|
|
905
|
+
const templateRoute = useRouteRef(selectedTemplateRouteRef);
|
|
923
906
|
const templateProps = getTemplateCardProps(template);
|
|
924
907
|
const ownedByRelations = getEntityRelations(template, RELATION_OWNED_BY);
|
|
925
908
|
const themeId = backstageTheme.getPageTheme({ themeId: templateProps.type }) ? templateProps.type : "other";
|
|
926
909
|
const theme = backstageTheme.getPageTheme({ themeId });
|
|
927
910
|
const classes = useStyles$2({ backgroundImage: theme.backgroundImage });
|
|
928
|
-
const href =
|
|
929
|
-
templateName: templateProps.name
|
|
930
|
-
});
|
|
911
|
+
const href = templateRoute({ templateName: templateProps.name });
|
|
931
912
|
const scmIntegrationsApi = useApi(scmIntegrationsApiRef);
|
|
932
913
|
const sourceLocation = getEntitySourceLocation(template, scmIntegrationsApi);
|
|
933
914
|
return /* @__PURE__ */ React.createElement(Card, null, /* @__PURE__ */ React.createElement(CardMedia, {
|
|
934
915
|
className: classes.cardHeader
|
|
935
|
-
}, /* @__PURE__ */ React.createElement(
|
|
916
|
+
}, /* @__PURE__ */ React.createElement(FavoriteEntity, {
|
|
917
|
+
className: classes.starButton,
|
|
936
918
|
entity: template
|
|
937
919
|
}), deprecated && /* @__PURE__ */ React.createElement(DeprecationWarning, null), /* @__PURE__ */ React.createElement(ItemCardHeader, {
|
|
938
920
|
title: templateProps.title,
|
|
@@ -976,14 +958,26 @@ const TemplateList = ({
|
|
|
976
958
|
TemplateCardComponent,
|
|
977
959
|
group
|
|
978
960
|
}) => {
|
|
979
|
-
const { loading, error, entities } =
|
|
961
|
+
const { loading, error, entities } = useEntityList();
|
|
980
962
|
const Card = TemplateCardComponent || TemplateCard;
|
|
981
963
|
const maybeFilteredEntities = group ? entities.filter((e) => group.filter(e)) : entities;
|
|
982
|
-
const
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
964
|
+
const titleComponent = (() => {
|
|
965
|
+
if (group == null ? void 0 : group.titleComponent) {
|
|
966
|
+
console.warn("DEPRECATED: group.titleComponent is now deprecated. Use group.title instead, it can be a string or a react component");
|
|
967
|
+
return group == null ? void 0 : group.titleComponent;
|
|
968
|
+
}
|
|
969
|
+
if (group && group.title) {
|
|
970
|
+
if (typeof group.title === "string") {
|
|
971
|
+
return /* @__PURE__ */ React.createElement(ContentHeader, {
|
|
972
|
+
title: group.title
|
|
973
|
+
});
|
|
974
|
+
}
|
|
975
|
+
return group.title;
|
|
976
|
+
}
|
|
977
|
+
return /* @__PURE__ */ React.createElement(ContentHeader, {
|
|
978
|
+
title: "Other Templates"
|
|
979
|
+
});
|
|
980
|
+
})();
|
|
987
981
|
if (group && maybeFilteredEntities.length === 0) {
|
|
988
982
|
return null;
|
|
989
983
|
}
|
|
@@ -993,9 +987,10 @@ const TemplateList = ({
|
|
|
993
987
|
variant: "body2"
|
|
994
988
|
}, "No templates found that match your filter. Learn more about", " ", /* @__PURE__ */ React.createElement(Link$1, {
|
|
995
989
|
to: "https://backstage.io/docs/features/software-templates/adding-templates"
|
|
996
|
-
}, "adding templates"), "."), /* @__PURE__ */ React.createElement(Content, null,
|
|
990
|
+
}, "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, {
|
|
997
991
|
key: stringifyEntityRef(template),
|
|
998
|
-
template
|
|
992
|
+
template,
|
|
993
|
+
deprecated: template.apiVersion === "backstage.io/v1beta2"
|
|
999
994
|
})))));
|
|
1000
995
|
};
|
|
1001
996
|
|
|
@@ -1223,7 +1218,7 @@ const TaskPageLinks = ({ output }) => {
|
|
|
1223
1218
|
pb: 3
|
|
1224
1219
|
}, links.filter(({ url, entityRef }) => url || entityRef).map(({ url, entityRef, title, icon }) => {
|
|
1225
1220
|
if (entityRef) {
|
|
1226
|
-
const entityName =
|
|
1221
|
+
const entityName = parseEntityRef(entityRef);
|
|
1227
1222
|
const target = entityRoute(entityName);
|
|
1228
1223
|
return { title, icon, url: target };
|
|
1229
1224
|
}
|
|
@@ -1357,11 +1352,16 @@ const TaskStatusStepper = memo(({
|
|
|
1357
1352
|
})))));
|
|
1358
1353
|
})));
|
|
1359
1354
|
});
|
|
1360
|
-
const hasLinks = ({
|
|
1355
|
+
const hasLinks = ({
|
|
1356
|
+
entityRef,
|
|
1357
|
+
remoteUrl,
|
|
1358
|
+
links = []
|
|
1359
|
+
}) => !!(entityRef || remoteUrl || links.length > 0);
|
|
1361
1360
|
const TaskPage = ({ loadingText }) => {
|
|
1362
1361
|
const classes = useStyles();
|
|
1363
1362
|
const navigate = useNavigate();
|
|
1364
|
-
const
|
|
1363
|
+
const rootPath = useRouteRef(rootRouteRef);
|
|
1364
|
+
const templateRoute = useRouteRef(selectedTemplateRouteRef);
|
|
1365
1365
|
const [userSelectedStepId, setUserSelectedStepId] = useState(void 0);
|
|
1366
1366
|
const [lastActiveStepId, setLastActiveStepId] = useState(void 0);
|
|
1367
1367
|
const { taskId } = useParams();
|
|
@@ -1400,16 +1400,16 @@ const TaskPage = ({ loadingText }) => {
|
|
|
1400
1400
|
const taskNotFound = taskStream.completed === true && taskStream.loading === false && !taskStream.task;
|
|
1401
1401
|
const { output } = taskStream;
|
|
1402
1402
|
const handleStartOver = () => {
|
|
1403
|
-
var _a, _b;
|
|
1404
|
-
if (!taskStream.task || !((_b = (_a = taskStream.task) == null ? void 0 : _a.spec.
|
|
1405
|
-
navigate(
|
|
1403
|
+
var _a, _b, _c;
|
|
1404
|
+
if (!taskStream.task || !((_b = (_a = taskStream.task) == null ? void 0 : _a.spec.templateInfo) == null ? void 0 : _b.entityRef)) {
|
|
1405
|
+
navigate(rootPath());
|
|
1406
|
+
return;
|
|
1406
1407
|
}
|
|
1407
1408
|
const formData = taskStream.task.spec.apiVersion === "backstage.io/v1beta2" ? taskStream.task.spec.values : taskStream.task.spec.parameters;
|
|
1408
|
-
|
|
1409
|
+
const { name } = parseEntityRef((_c = taskStream.task.spec.templateInfo) == null ? void 0 : _c.entityRef);
|
|
1410
|
+
navigate(`${templateRoute({ templateName: name })}?${qs.stringify({
|
|
1409
1411
|
formData: JSON.stringify(formData)
|
|
1410
|
-
})}
|
|
1411
|
-
templateName: taskStream.task.spec.metadata.name
|
|
1412
|
-
}));
|
|
1412
|
+
})}`);
|
|
1413
1413
|
};
|
|
1414
1414
|
return /* @__PURE__ */ React.createElement(Page, {
|
|
1415
1415
|
themeId: "home"
|
|
@@ -1451,5 +1451,5 @@ const TaskPage = ({ loadingText }) => {
|
|
|
1451
1451
|
})))))));
|
|
1452
1452
|
};
|
|
1453
1453
|
|
|
1454
|
-
export { EntityPicker as E, FIELD_EXTENSION_WRAPPER_KEY as F, OwnerPicker as O, RepoUrlPicker as R, SecretsContext as S, TemplateTypePicker as T, EntityNamePicker as a, EntityTagsPicker as b, OwnedEntityPicker as c, registerComponentRouteRef as d, entityNamePickerValidation as e, TemplateList as f,
|
|
1455
|
-
//# sourceMappingURL=index-
|
|
1454
|
+
export { EntityPicker as E, FIELD_EXTENSION_WRAPPER_KEY as F, OwnerPicker as O, RepoUrlPicker as R, SecretsContext as S, TemplateTypePicker as T, EntityNamePicker as a, EntityTagsPicker as b, OwnedEntityPicker as c, registerComponentRouteRef as d, entityNamePickerValidation as e, TemplateList as f, scaffolderTaskRouteRef as g, rootRouteRef as h, FIELD_EXTENSION_KEY as i, SecretsContextProvider as j, TaskPage as k, ScaffolderClient as l, createScaffolderFieldExtension as m, ScaffolderFieldExtensions as n, EntityPickerFieldExtension as o, EntityNamePickerFieldExtension as p, EntityTagsPickerFieldExtension as q, repoPickerValidation as r, scaffolderApiRef as s, OwnerPickerFieldExtension as t, OwnedEntityPickerFieldExtension as u, RepoUrlPickerFieldExtension as v, ScaffolderPage as w, scaffolderPlugin as x, useTemplateSecrets as y };
|
|
1455
|
+
//# sourceMappingURL=index-da137e20.esm.js.map
|