@backstage/plugin-scaffolder 0.11.12 → 0.11.16
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 +72 -0
- package/dist/esm/{Router-5919d585.esm.js → Router-a8e778fd.esm.js} +124 -74
- package/dist/esm/Router-a8e778fd.esm.js.map +1 -0
- package/dist/esm/{index-9d7df4e7.esm.js → index-f378943f.esm.js} +228 -78
- package/dist/esm/index-f378943f.esm.js.map +1 -0
- package/dist/index.d.ts +34 -19
- package/dist/index.esm.js +5 -6
- package/dist/index.esm.js.map +1 -1
- package/package.json +19 -17
- package/dist/esm/Router-5919d585.esm.js.map +0 -1
- package/dist/esm/index-9d7df4e7.esm.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,77 @@
|
|
|
1
1
|
# @backstage/plugin-scaffolder
|
|
2
2
|
|
|
3
|
+
## 0.11.16
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 9c25894892: Implement a `EntityTagsPicker` field extension
|
|
8
|
+
- 7d4b4e937c: Uptake changes to the GitHub Credentials Provider interface.
|
|
9
|
+
- d078377f67: Support navigating back to pre-filled templates to update inputs of scaffolder tasks for resubmission
|
|
10
|
+
- Updated dependencies
|
|
11
|
+
- @backstage/plugin-catalog-react@0.6.9
|
|
12
|
+
- @backstage/plugin-scaffolder-common@0.1.2
|
|
13
|
+
- @backstage/integration@0.7.0
|
|
14
|
+
- @backstage/integration-react@0.1.17
|
|
15
|
+
|
|
16
|
+
## 0.11.15
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- c5eb756760: Fix a small browser console warning
|
|
21
|
+
- ff5ff57883: EntityPicker can require an existing entity be selected by disallowing arbitrary values
|
|
22
|
+
- 0f645a7947: Added OwnedEntityPicker field which displays Owned Entities in options
|
|
23
|
+
- b646a73fe0: In @backstage/plugin-scaffolder - When user will have one option available in hostUrl or owner - autoselect and select component should be readonly.
|
|
24
|
+
|
|
25
|
+
in @backstage/core-components - Select component has extended API with few more props: native : boolean, disabled: boolean. native - if set to true - Select component will use native browser select picker (not rendered by Material UI lib ).
|
|
26
|
+
disabled - if set to true - action on component will not be possible.
|
|
27
|
+
|
|
28
|
+
- 7a4bd2ceac: Prefer using `Link` from `@backstage/core-components` rather than material-UI.
|
|
29
|
+
- 4c269c7c23: Add DescriptionField override to support Markdown
|
|
30
|
+
- Updated dependencies
|
|
31
|
+
- @backstage/core-plugin-api@0.4.0
|
|
32
|
+
- @backstage/plugin-catalog-react@0.6.8
|
|
33
|
+
- @backstage/core-components@0.8.2
|
|
34
|
+
- @backstage/catalog-client@0.5.3
|
|
35
|
+
- @backstage/integration-react@0.1.16
|
|
36
|
+
|
|
37
|
+
## 0.11.14
|
|
38
|
+
|
|
39
|
+
### Patch Changes
|
|
40
|
+
|
|
41
|
+
- 6845cce533: Can specify allowedOwners to the RepoUrlPicker picker in a template definition
|
|
42
|
+
- cd450844f6: Moved React dependencies to `peerDependencies` and allow both React v16 and v17 to be used.
|
|
43
|
+
- 2edcf7738f: Fix bug with setting owner in RepoUrlPicker causing validation failure
|
|
44
|
+
- b291c3176e: Switch to using `LogViewer` component from `@backstage/core-components` to display scaffolder logs.
|
|
45
|
+
- Updated dependencies
|
|
46
|
+
- @backstage/core-components@0.8.0
|
|
47
|
+
- @backstage/core-plugin-api@0.3.0
|
|
48
|
+
- @backstage/integration-react@0.1.15
|
|
49
|
+
- @backstage/plugin-catalog-react@0.6.5
|
|
50
|
+
|
|
51
|
+
## 0.11.13
|
|
52
|
+
|
|
53
|
+
### Patch Changes
|
|
54
|
+
|
|
55
|
+
- ed5bef529e: Add group filtering to the scaffolder page so that individuals can surface specific templates to end users ahead of others, or group templates together. This can be accomplished by passing in a `groups` prop to the `ScaffolderPage`
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
<ScaffolderPage
|
|
59
|
+
groups={[
|
|
60
|
+
{
|
|
61
|
+
title: "Recommended",
|
|
62
|
+
filter: entity =>
|
|
63
|
+
entity?.metadata?.tags?.includes('recommended') ?? false,
|
|
64
|
+
},
|
|
65
|
+
]}
|
|
66
|
+
/>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
- Updated dependencies
|
|
70
|
+
- @backstage/integration@0.6.10
|
|
71
|
+
- @backstage/core-components@0.7.6
|
|
72
|
+
- @backstage/theme@0.2.14
|
|
73
|
+
- @backstage/core-plugin-api@0.2.2
|
|
74
|
+
|
|
3
75
|
## 0.11.12
|
|
4
76
|
|
|
5
77
|
### Patch Changes
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import React, { useState, useCallback, useEffect, memo,
|
|
1
|
+
import React, { useState, useCallback, useEffect, memo, useMemo } from 'react';
|
|
2
2
|
import { useNavigate, Navigate, generatePath, useParams as useParams$1, useOutlet, Routes, Route } from 'react-router';
|
|
3
|
-
import { Page, Header, Lifecycle, Content, ContentHeader, CreateButton, SupportButton, StructuredMetadataTable, InfoCard, Link,
|
|
3
|
+
import { Page, Header, Lifecycle, Content, ContentHeader, CreateButton, SupportButton, MarkdownContent, StructuredMetadataTable, InfoCard, Link, ErrorPage, LogViewer, Progress } from '@backstage/core-components';
|
|
4
4
|
import { useRouteRef, useApi, errorApiRef, useApiHolder, useApp, useElementFilter } from '@backstage/core-plugin-api';
|
|
5
5
|
import { EntityListProvider, EntitySearchBar, EntityKindPicker, UserListPicker, EntityTagPicker, entityRouteRef } from '@backstage/plugin-catalog-react';
|
|
6
6
|
import { makeStyles, Stepper, Step, StepLabel, Typography, StepContent, Button, Paper, Box, LinearProgress, Grid, StepButton, CircularProgress, TableContainer, Table, TableHead, TableRow, TableCell, TableBody } from '@material-ui/core';
|
|
7
|
-
import { E as EntityPicker, a as EntityNamePicker, e as entityNamePickerValidation, R as RepoUrlPicker, r as repoPickerValidation, O as OwnerPicker,
|
|
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 scaffolderApiRef, g as rootRouteRef, F as FIELD_EXTENSION_WRAPPER_KEY, h as FIELD_EXTENSION_KEY } from './index-f378943f.esm.js';
|
|
8
|
+
import qs from 'qs';
|
|
8
9
|
import { useParams } from 'react-router-dom';
|
|
9
10
|
import { useAsync, useInterval } from 'react-use';
|
|
10
11
|
import { withTheme } from '@rjsf/core';
|
|
@@ -24,15 +25,14 @@ import { useImmerReducer } from 'use-immer';
|
|
|
24
25
|
import { parseEntityName } from '@backstage/catalog-model';
|
|
25
26
|
import LanguageIcon from '@material-ui/icons/Language';
|
|
26
27
|
import '@backstage/errors';
|
|
27
|
-
import 'qs';
|
|
28
28
|
import 'zen-observable';
|
|
29
29
|
import '@material-ui/core/FormControl';
|
|
30
30
|
import '@material-ui/lab/Autocomplete';
|
|
31
|
+
import '@material-ui/lab';
|
|
31
32
|
import '@backstage/integration-react';
|
|
32
|
-
import '@material-ui/core/Select';
|
|
33
|
-
import '@material-ui/core/InputLabel';
|
|
34
|
-
import '@material-ui/core/Input';
|
|
35
33
|
import '@material-ui/core/FormHelperText';
|
|
34
|
+
import '@material-ui/core/Input';
|
|
35
|
+
import '@material-ui/core/InputLabel';
|
|
36
36
|
import '@material-ui/icons/Star';
|
|
37
37
|
import '@material-ui/icons/StarBorder';
|
|
38
38
|
import '@material-ui/icons/Warning';
|
|
@@ -40,7 +40,6 @@ import 'lodash/capitalize';
|
|
|
40
40
|
import '@material-ui/icons/CheckBox';
|
|
41
41
|
import '@material-ui/icons/CheckBoxOutlineBlank';
|
|
42
42
|
import '@material-ui/icons/ExpandMore';
|
|
43
|
-
import '@material-ui/lab';
|
|
44
43
|
|
|
45
44
|
const DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS = [
|
|
46
45
|
{
|
|
@@ -52,6 +51,10 @@ const DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS = [
|
|
|
52
51
|
name: "EntityNamePicker",
|
|
53
52
|
validation: entityNamePickerValidation
|
|
54
53
|
},
|
|
54
|
+
{
|
|
55
|
+
component: EntityTagsPicker,
|
|
56
|
+
name: "EntityTagsPicker"
|
|
57
|
+
},
|
|
55
58
|
{
|
|
56
59
|
component: RepoUrlPicker,
|
|
57
60
|
name: "RepoUrlPicker",
|
|
@@ -60,6 +63,10 @@ const DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS = [
|
|
|
60
63
|
{
|
|
61
64
|
component: OwnerPicker,
|
|
62
65
|
name: "OwnerPicker"
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
component: OwnedEntityPicker,
|
|
69
|
+
name: "OwnedEntityPicker"
|
|
63
70
|
}
|
|
64
71
|
];
|
|
65
72
|
|
|
@@ -72,10 +79,18 @@ const useStyles$3 = makeStyles((theme) => ({
|
|
|
72
79
|
}
|
|
73
80
|
}));
|
|
74
81
|
const ScaffolderPageContents = ({
|
|
75
|
-
TemplateCardComponent
|
|
82
|
+
TemplateCardComponent,
|
|
83
|
+
groups
|
|
76
84
|
}) => {
|
|
77
85
|
const styles = useStyles$3();
|
|
78
86
|
const registerComponentLink = useRouteRef(registerComponentRouteRef);
|
|
87
|
+
const otherTemplatesGroup = {
|
|
88
|
+
title: groups ? "Other Templates" : "Templates",
|
|
89
|
+
filter: (entity) => {
|
|
90
|
+
const filtered = (groups != null ? groups : []).map((group) => group.filter(entity));
|
|
91
|
+
return !filtered.some((result) => result === true);
|
|
92
|
+
}
|
|
93
|
+
};
|
|
79
94
|
return /* @__PURE__ */ React.createElement(Page, {
|
|
80
95
|
themeId: "home"
|
|
81
96
|
}, /* @__PURE__ */ React.createElement(Header, {
|
|
@@ -97,14 +112,22 @@ const ScaffolderPageContents = ({
|
|
|
97
112
|
}), /* @__PURE__ */ React.createElement(UserListPicker, {
|
|
98
113
|
initialFilter: "all",
|
|
99
114
|
availableFilters: ["all", "starred"]
|
|
100
|
-
}), /* @__PURE__ */ React.createElement(TemplateTypePicker, null), /* @__PURE__ */ React.createElement(EntityTagPicker, null)), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement(TemplateList, {
|
|
101
|
-
|
|
115
|
+
}), /* @__PURE__ */ React.createElement(TemplateTypePicker, null), /* @__PURE__ */ React.createElement(EntityTagPicker, null)), /* @__PURE__ */ React.createElement("div", null, groups && groups.map((group, index) => /* @__PURE__ */ React.createElement(TemplateList, {
|
|
116
|
+
key: index,
|
|
117
|
+
TemplateCardComponent,
|
|
118
|
+
group
|
|
119
|
+
})), /* @__PURE__ */ React.createElement(TemplateList, {
|
|
120
|
+
key: "other",
|
|
121
|
+
TemplateCardComponent,
|
|
122
|
+
group: otherTemplatesGroup
|
|
102
123
|
})))));
|
|
103
124
|
};
|
|
104
125
|
const ScaffolderPage = ({
|
|
105
|
-
TemplateCardComponent
|
|
126
|
+
TemplateCardComponent,
|
|
127
|
+
groups
|
|
106
128
|
}) => /* @__PURE__ */ React.createElement(EntityListProvider, null, /* @__PURE__ */ React.createElement(ScaffolderPageContents, {
|
|
107
|
-
TemplateCardComponent
|
|
129
|
+
TemplateCardComponent,
|
|
130
|
+
groups
|
|
108
131
|
}));
|
|
109
132
|
|
|
110
133
|
function isObject$1(value) {
|
|
@@ -114,7 +137,7 @@ function extractUiSchema(schema, uiSchema) {
|
|
|
114
137
|
if (!isObject$1(schema)) {
|
|
115
138
|
return;
|
|
116
139
|
}
|
|
117
|
-
const {properties, items, anyOf, oneOf, allOf, dependencies} = schema;
|
|
140
|
+
const { properties, items, anyOf, oneOf, allOf, dependencies } = schema;
|
|
118
141
|
for (const propName in schema) {
|
|
119
142
|
if (!schema.hasOwnProperty(propName)) {
|
|
120
143
|
continue;
|
|
@@ -183,9 +206,18 @@ function transformSchemaToProps(inputSchema) {
|
|
|
183
206
|
delete schema.title;
|
|
184
207
|
const uiSchema = {};
|
|
185
208
|
extractUiSchema(schema, uiSchema);
|
|
186
|
-
return {schema, uiSchema};
|
|
209
|
+
return { schema, uiSchema };
|
|
187
210
|
}
|
|
188
211
|
|
|
212
|
+
const DescriptionField = ({ description }) => description && /* @__PURE__ */ React.createElement(MarkdownContent, {
|
|
213
|
+
content: description
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
var fieldOverrides = /*#__PURE__*/Object.freeze({
|
|
217
|
+
__proto__: null,
|
|
218
|
+
DescriptionField: DescriptionField
|
|
219
|
+
});
|
|
220
|
+
|
|
189
221
|
const Form = withTheme(Theme);
|
|
190
222
|
function getUiSchemasFromSteps(steps) {
|
|
191
223
|
const uiSchemas = [];
|
|
@@ -264,7 +296,7 @@ const MultistepJsonForm = ({
|
|
|
264
296
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Stepper, {
|
|
265
297
|
activeStep,
|
|
266
298
|
orientation: "vertical"
|
|
267
|
-
}, steps.map(({title, schema, ...formProps}, index) => {
|
|
299
|
+
}, steps.map(({ title, schema, ...formProps }, index) => {
|
|
268
300
|
return /* @__PURE__ */ React.createElement(Step, {
|
|
269
301
|
key: title
|
|
270
302
|
}, /* @__PURE__ */ React.createElement(StepLabel, {
|
|
@@ -278,7 +310,7 @@ const MultistepJsonForm = ({
|
|
|
278
310
|
key: title
|
|
279
311
|
}, /* @__PURE__ */ React.createElement(Form, {
|
|
280
312
|
showErrorList: false,
|
|
281
|
-
fields,
|
|
313
|
+
fields: { ...fieldOverrides, ...fields },
|
|
282
314
|
widgets,
|
|
283
315
|
noHtml5Validate: true,
|
|
284
316
|
formData,
|
|
@@ -323,12 +355,12 @@ const MultistepJsonForm = ({
|
|
|
323
355
|
|
|
324
356
|
const useTemplateParameterSchema = (templateName) => {
|
|
325
357
|
const scaffolderApi = useApi(scaffolderApiRef);
|
|
326
|
-
const {value, loading, error} = useAsync(() => scaffolderApi.getTemplateParameterSchema({
|
|
358
|
+
const { value, loading, error } = useAsync(() => scaffolderApi.getTemplateParameterSchema({
|
|
327
359
|
name: templateName,
|
|
328
360
|
kind: "template",
|
|
329
361
|
namespace: "default"
|
|
330
362
|
}), [scaffolderApi, templateName]);
|
|
331
|
-
return {schema: value, loading, error};
|
|
363
|
+
return { schema: value, loading, error };
|
|
332
364
|
};
|
|
333
365
|
function isObject(obj) {
|
|
334
366
|
return typeof obj === "object" && obj !== null && !Array.isArray(obj);
|
|
@@ -366,16 +398,26 @@ const TemplatePage = ({
|
|
|
366
398
|
const apiHolder = useApiHolder();
|
|
367
399
|
const errorApi = useApi(errorApiRef);
|
|
368
400
|
const scaffolderApi = useApi(scaffolderApiRef);
|
|
369
|
-
const {templateName} = useParams();
|
|
401
|
+
const { templateName } = useParams();
|
|
370
402
|
const navigate = useNavigate();
|
|
371
403
|
const rootLink = useRouteRef(rootRouteRef);
|
|
372
|
-
const {schema, loading, error} = useTemplateParameterSchema(templateName);
|
|
373
|
-
const [formState, setFormState] = useState({
|
|
404
|
+
const { schema, loading, error } = useTemplateParameterSchema(templateName);
|
|
405
|
+
const [formState, setFormState] = useState(() => {
|
|
406
|
+
var _a;
|
|
407
|
+
const query = qs.parse(window.location.search, {
|
|
408
|
+
ignoreQueryPrefix: true
|
|
409
|
+
});
|
|
410
|
+
return (_a = query.formData) != null ? _a : {};
|
|
411
|
+
});
|
|
374
412
|
const handleFormReset = () => setFormState({});
|
|
375
413
|
const handleChange = useCallback((e) => setFormState(e.formData), [setFormState]);
|
|
376
414
|
const handleCreate = async () => {
|
|
415
|
+
var _a;
|
|
377
416
|
const id = await scaffolderApi.scaffold(templateName, formState);
|
|
378
|
-
|
|
417
|
+
const formParams = qs.stringify({ formData: formState }, { addQueryPrefix: true });
|
|
418
|
+
const newUrl = `${window.location.pathname}${formParams}`;
|
|
419
|
+
(_a = window.history) == null ? void 0 : _a.replaceState(null, document.title, newUrl);
|
|
420
|
+
navigate(generatePath(`${rootLink()}/tasks/:taskId`, { taskId: id }));
|
|
379
421
|
};
|
|
380
422
|
if (error) {
|
|
381
423
|
errorApi.post(new Error(`Failed to load template, ${error}`));
|
|
@@ -389,8 +431,8 @@ const TemplatePage = ({
|
|
|
389
431
|
to: rootLink()
|
|
390
432
|
});
|
|
391
433
|
}
|
|
392
|
-
const customFieldComponents = Object.fromEntries(customFieldExtensions.map(({name, component}) => [name, component]));
|
|
393
|
-
const customFieldValidators = Object.fromEntries(customFieldExtensions.map(({name, validation}) => [name, validation]));
|
|
434
|
+
const customFieldComponents = Object.fromEntries(customFieldExtensions.map(({ name, component }) => [name, component]));
|
|
435
|
+
const customFieldValidators = Object.fromEntries(customFieldExtensions.map(({ name, validation }) => [name, validation]));
|
|
394
436
|
return /* @__PURE__ */ React.createElement(Page, {
|
|
395
437
|
themeId: "home"
|
|
396
438
|
}, /* @__PURE__ */ React.createElement(Header, {
|
|
@@ -404,7 +446,7 @@ const TemplatePage = ({
|
|
|
404
446
|
}), schema && /* @__PURE__ */ React.createElement(InfoCard, {
|
|
405
447
|
title: schema.title,
|
|
406
448
|
noPadding: true,
|
|
407
|
-
titleTypographyProps: {component: "h2"}
|
|
449
|
+
titleTypographyProps: { component: "h2" }
|
|
408
450
|
}, /* @__PURE__ */ React.createElement(MultistepJsonForm, {
|
|
409
451
|
formData: formState,
|
|
410
452
|
fields: customFieldComponents,
|
|
@@ -414,7 +456,7 @@ const TemplatePage = ({
|
|
|
414
456
|
steps: schema.steps.map((step) => {
|
|
415
457
|
return {
|
|
416
458
|
...step,
|
|
417
|
-
validate: createValidator(step.schema, customFieldValidators, {apiHolder})
|
|
459
|
+
validate: createValidator(step.schema, customFieldValidators, { apiHolder })
|
|
418
460
|
};
|
|
419
461
|
})
|
|
420
462
|
}))));
|
|
@@ -425,7 +467,7 @@ function reducer(draft, action) {
|
|
|
425
467
|
switch (action.type) {
|
|
426
468
|
case "INIT": {
|
|
427
469
|
draft.steps = action.data.spec.steps.reduce((current, next) => {
|
|
428
|
-
current[next.id] = {status: "open", id: next.id};
|
|
470
|
+
current[next.id] = { status: "open", id: next.id };
|
|
429
471
|
return current;
|
|
430
472
|
}, {});
|
|
431
473
|
draft.stepLogs = action.data.spec.steps.reduce((current, next) => {
|
|
@@ -491,13 +533,13 @@ const useTaskEventStream = (taskId) => {
|
|
|
491
533
|
if (didCancel) {
|
|
492
534
|
return;
|
|
493
535
|
}
|
|
494
|
-
dispatch({type: "INIT", data: task});
|
|
495
|
-
const observable = scaffolderApi.streamLogs({taskId});
|
|
536
|
+
dispatch({ type: "INIT", data: task });
|
|
537
|
+
const observable = scaffolderApi.streamLogs({ taskId });
|
|
496
538
|
const collectedLogEvents = new Array();
|
|
497
539
|
function emitLogs() {
|
|
498
540
|
if (collectedLogEvents.length) {
|
|
499
541
|
const logs = collectedLogEvents.splice(0, collectedLogEvents.length);
|
|
500
|
-
dispatch({type: "LOGS", data: logs});
|
|
542
|
+
dispatch({ type: "LOGS", data: logs });
|
|
501
543
|
}
|
|
502
544
|
}
|
|
503
545
|
logPusher = setInterval(emitLogs, 500);
|
|
@@ -508,7 +550,7 @@ const useTaskEventStream = (taskId) => {
|
|
|
508
550
|
return collectedLogEvents.push(event);
|
|
509
551
|
case "completion":
|
|
510
552
|
emitLogs();
|
|
511
|
-
dispatch({type: "COMPLETED", data: event});
|
|
553
|
+
dispatch({ type: "COMPLETED", data: event });
|
|
512
554
|
return void 0;
|
|
513
555
|
default:
|
|
514
556
|
throw new Error(`Unhandled event type ${event.type} in observer`);
|
|
@@ -516,12 +558,12 @@ const useTaskEventStream = (taskId) => {
|
|
|
516
558
|
},
|
|
517
559
|
error: (error) => {
|
|
518
560
|
emitLogs();
|
|
519
|
-
dispatch({type: "ERROR", data: error});
|
|
561
|
+
dispatch({ type: "ERROR", data: error });
|
|
520
562
|
}
|
|
521
563
|
});
|
|
522
564
|
}, (error) => {
|
|
523
565
|
if (!didCancel) {
|
|
524
|
-
dispatch({type: "ERROR", data: error});
|
|
566
|
+
dispatch({ type: "ERROR", data: error });
|
|
525
567
|
}
|
|
526
568
|
});
|
|
527
569
|
return () => {
|
|
@@ -548,7 +590,7 @@ const useStyles$2 = makeStyles({
|
|
|
548
590
|
}
|
|
549
591
|
});
|
|
550
592
|
const IconLink = (props) => {
|
|
551
|
-
const {href, text, Icon, ...linkProps} = props;
|
|
593
|
+
const { href, text, Icon, ...linkProps } = props;
|
|
552
594
|
const classes = useStyles$2();
|
|
553
595
|
return /* @__PURE__ */ React.createElement(Grid, {
|
|
554
596
|
container: true,
|
|
@@ -567,9 +609,9 @@ const IconLink = (props) => {
|
|
|
567
609
|
}, text || href)));
|
|
568
610
|
};
|
|
569
611
|
|
|
570
|
-
const TaskPageLinks = ({output}) => {
|
|
571
|
-
const {entityRef: entityRefOutput, remoteUrl} = output;
|
|
572
|
-
let {links = []} = output;
|
|
612
|
+
const TaskPageLinks = ({ output }) => {
|
|
613
|
+
const { entityRef: entityRefOutput, remoteUrl } = output;
|
|
614
|
+
let { links = [] } = output;
|
|
573
615
|
const app = useApp();
|
|
574
616
|
const entityRoute = useRouteRef(entityRouteRef);
|
|
575
617
|
const iconResolver = (key) => {
|
|
@@ -577,7 +619,7 @@ const TaskPageLinks = ({output}) => {
|
|
|
577
619
|
return key ? (_a = app.getSystemIcon(key)) != null ? _a : LanguageIcon : LanguageIcon;
|
|
578
620
|
};
|
|
579
621
|
if (remoteUrl) {
|
|
580
|
-
links = [{url: remoteUrl, title: "Repo"}, ...links];
|
|
622
|
+
links = [{ url: remoteUrl, title: "Repo" }, ...links];
|
|
581
623
|
}
|
|
582
624
|
if (entityRefOutput) {
|
|
583
625
|
links = [
|
|
@@ -592,14 +634,14 @@ const TaskPageLinks = ({output}) => {
|
|
|
592
634
|
return /* @__PURE__ */ React.createElement(Box, {
|
|
593
635
|
px: 3,
|
|
594
636
|
pb: 3
|
|
595
|
-
}, links.filter(({url, entityRef}) => url || entityRef).map(({url, entityRef, title, icon}) => {
|
|
637
|
+
}, links.filter(({ url, entityRef }) => url || entityRef).map(({ url, entityRef, title, icon }) => {
|
|
596
638
|
if (entityRef) {
|
|
597
639
|
const entityName = parseEntityName(entityRef);
|
|
598
640
|
const target = entityRoute(entityName);
|
|
599
|
-
return {title, icon, url: target};
|
|
641
|
+
return { title, icon, url: target };
|
|
600
642
|
}
|
|
601
|
-
return {title, icon, url};
|
|
602
|
-
}).map(({url, title, icon}, i) => /* @__PURE__ */ React.createElement(IconLink, {
|
|
643
|
+
return { title, icon, url };
|
|
644
|
+
}).map(({ url, title, icon }, i) => /* @__PURE__ */ React.createElement(IconLink, {
|
|
603
645
|
key: `output-link-${i}`,
|
|
604
646
|
href: url,
|
|
605
647
|
text: title != null ? title : url,
|
|
@@ -608,15 +650,14 @@ const TaskPageLinks = ({output}) => {
|
|
|
608
650
|
})));
|
|
609
651
|
};
|
|
610
652
|
|
|
611
|
-
const LazyLog = React.lazy(() => import('react-lazylog/build/LazyLog'));
|
|
612
653
|
const humanizeDuration = require("humanize-duration");
|
|
613
654
|
const useStyles$1 = makeStyles$1((theme) => createStyles({
|
|
614
655
|
root: {
|
|
615
656
|
width: "100%"
|
|
616
657
|
},
|
|
617
658
|
button: {
|
|
618
|
-
|
|
619
|
-
|
|
659
|
+
marginBottom: theme.spacing(2),
|
|
660
|
+
marginLeft: theme.spacing(2)
|
|
620
661
|
},
|
|
621
662
|
actionsContainer: {
|
|
622
663
|
marginBottom: theme.spacing(2)
|
|
@@ -634,7 +675,7 @@ const useStyles$1 = makeStyles$1((theme) => createStyles({
|
|
|
634
675
|
width: "100%"
|
|
635
676
|
}
|
|
636
677
|
}));
|
|
637
|
-
const StepTimeTicker = ({step}) => {
|
|
678
|
+
const StepTimeTicker = ({ step }) => {
|
|
638
679
|
const [time, setTime] = useState("");
|
|
639
680
|
useInterval(() => {
|
|
640
681
|
if (!step.startedAt) {
|
|
@@ -644,7 +685,7 @@ const StepTimeTicker = ({step}) => {
|
|
|
644
685
|
const end = step.endedAt ? DateTime.fromISO(step.endedAt) : DateTime.local();
|
|
645
686
|
const startedAt = DateTime.fromISO(step.startedAt);
|
|
646
687
|
const formatted = Interval.fromDateTimes(startedAt, end).toDuration().valueOf();
|
|
647
|
-
setTime(humanizeDuration(formatted, {round: true}));
|
|
688
|
+
setTime(humanizeDuration(formatted, { round: true }));
|
|
648
689
|
}, 1e3);
|
|
649
690
|
return /* @__PURE__ */ React.createElement(Typography$1, {
|
|
650
691
|
variant: "caption"
|
|
@@ -666,7 +707,7 @@ const useStepIconStyles = makeStyles$1((theme) => createStyles({
|
|
|
666
707
|
}));
|
|
667
708
|
function TaskStepIconComponent(props) {
|
|
668
709
|
const classes = useStepIconStyles();
|
|
669
|
-
const {active, completed, error} = props;
|
|
710
|
+
const { active, completed, error } = props;
|
|
670
711
|
const getMiddle = () => {
|
|
671
712
|
if (active) {
|
|
672
713
|
return /* @__PURE__ */ React.createElement(CircularProgress, {
|
|
@@ -729,24 +770,14 @@ const TaskStatusStepper = memo(({
|
|
|
729
770
|
})))));
|
|
730
771
|
})));
|
|
731
772
|
});
|
|
732
|
-
const
|
|
733
|
-
return /* @__PURE__ */ React.createElement(Suspense, {
|
|
734
|
-
fallback: /* @__PURE__ */ React.createElement(Progress, null)
|
|
735
|
-
}, /* @__PURE__ */ React.createElement("div", {
|
|
736
|
-
style: {height: "80vh"}
|
|
737
|
-
}, /* @__PURE__ */ React.createElement(LazyLog, {
|
|
738
|
-
text: log,
|
|
739
|
-
extraLines: 1,
|
|
740
|
-
follow: true,
|
|
741
|
-
selectableLines: true,
|
|
742
|
-
enableSearch: true
|
|
743
|
-
})));
|
|
744
|
-
});
|
|
745
|
-
const hasLinks = ({entityRef, remoteUrl, links = []}) => !!(entityRef || remoteUrl || links.length > 0);
|
|
773
|
+
const hasLinks = ({ entityRef, remoteUrl, links = [] }) => !!(entityRef || remoteUrl || links.length > 0);
|
|
746
774
|
const TaskPage = () => {
|
|
775
|
+
const classes = useStyles$1();
|
|
776
|
+
const navigate = useNavigate();
|
|
777
|
+
const rootLink = useRouteRef(rootRouteRef);
|
|
747
778
|
const [userSelectedStepId, setUserSelectedStepId] = useState(void 0);
|
|
748
779
|
const [lastActiveStepId, setLastActiveStepId] = useState(void 0);
|
|
749
|
-
const {taskId} = useParams$1();
|
|
780
|
+
const { taskId } = useParams$1();
|
|
750
781
|
const taskStream = useTaskEventStream(taskId);
|
|
751
782
|
const completed = taskStream.completed;
|
|
752
783
|
const steps = useMemo(() => {
|
|
@@ -780,7 +811,17 @@ const TaskPage = () => {
|
|
|
780
811
|
return log.join("\n");
|
|
781
812
|
}, [taskStream.stepLogs, currentStepId]);
|
|
782
813
|
const taskNotFound = taskStream.completed === true && taskStream.loading === false && !taskStream.task;
|
|
783
|
-
const {output} = taskStream;
|
|
814
|
+
const { output } = taskStream;
|
|
815
|
+
const handleStartOver = () => {
|
|
816
|
+
var _a, _b;
|
|
817
|
+
if (!taskStream.task || !((_b = (_a = taskStream.task) == null ? void 0 : _a.spec.metadata) == null ? void 0 : _b.name)) {
|
|
818
|
+
navigate(generatePath(rootLink()));
|
|
819
|
+
}
|
|
820
|
+
const formData = taskStream.task.spec.apiVersion === "backstage.io/v1beta2" ? taskStream.task.spec.values : taskStream.task.spec.parameters;
|
|
821
|
+
navigate(generatePath(`${rootLink()}/templates/:templateName?${qs.stringify({ formData })}`, {
|
|
822
|
+
templateName: taskStream.task.spec.metadata.name
|
|
823
|
+
}));
|
|
824
|
+
};
|
|
784
825
|
return /* @__PURE__ */ React.createElement(Page, {
|
|
785
826
|
themeId: "home"
|
|
786
827
|
}, /* @__PURE__ */ React.createElement(Header, {
|
|
@@ -805,12 +846,20 @@ const TaskPage = () => {
|
|
|
805
846
|
onUserStepChange: setUserSelectedStepId
|
|
806
847
|
}), output && hasLinks(output) && /* @__PURE__ */ React.createElement(TaskPageLinks, {
|
|
807
848
|
output
|
|
808
|
-
})
|
|
849
|
+
}), /* @__PURE__ */ React.createElement(Button, {
|
|
850
|
+
className: classes.button,
|
|
851
|
+
onClick: handleStartOver,
|
|
852
|
+
disabled: !completed,
|
|
853
|
+
variant: "contained",
|
|
854
|
+
color: "primary"
|
|
855
|
+
}, "Start Over"))), /* @__PURE__ */ React.createElement(Grid$1, {
|
|
809
856
|
item: true,
|
|
810
857
|
xs: 9
|
|
811
|
-
}, /* @__PURE__ */ React.createElement(
|
|
812
|
-
|
|
813
|
-
}
|
|
858
|
+
}, /* @__PURE__ */ React.createElement("div", {
|
|
859
|
+
style: { height: "80vh" }
|
|
860
|
+
}, /* @__PURE__ */ React.createElement(LogViewer, {
|
|
861
|
+
text: logAsString
|
|
862
|
+
})))))));
|
|
814
863
|
};
|
|
815
864
|
|
|
816
865
|
const useStyles = makeStyles((theme) => ({
|
|
@@ -837,7 +886,7 @@ const useStyles = makeStyles((theme) => ({
|
|
|
837
886
|
const ActionsPage = () => {
|
|
838
887
|
const api = useApi(scaffolderApiRef);
|
|
839
888
|
const classes = useStyles();
|
|
840
|
-
const {loading, value, error} = useAsync(async () => {
|
|
889
|
+
const { loading, value, error } = useAsync(async () => {
|
|
841
890
|
return api.listActions();
|
|
842
891
|
});
|
|
843
892
|
if (loading) {
|
|
@@ -921,7 +970,7 @@ const ActionsPage = () => {
|
|
|
921
970
|
}), /* @__PURE__ */ React.createElement(Content, null, items));
|
|
922
971
|
};
|
|
923
972
|
|
|
924
|
-
const Router = ({TemplateCardComponent}) => {
|
|
973
|
+
const Router = ({ TemplateCardComponent, groups }) => {
|
|
925
974
|
const outlet = useOutlet();
|
|
926
975
|
const customFieldExtensions = useElementFilter(outlet, (elements) => elements.selectByComponentData({
|
|
927
976
|
key: FIELD_EXTENSION_WRAPPER_KEY
|
|
@@ -930,12 +979,13 @@ const Router = ({TemplateCardComponent}) => {
|
|
|
930
979
|
}));
|
|
931
980
|
const fieldExtensions = [
|
|
932
981
|
...customFieldExtensions,
|
|
933
|
-
...DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS.filter(({name}) => !customFieldExtensions.some((customFieldExtension) => customFieldExtension.name === name))
|
|
982
|
+
...DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS.filter(({ name }) => !customFieldExtensions.some((customFieldExtension) => customFieldExtension.name === name))
|
|
934
983
|
];
|
|
935
984
|
return /* @__PURE__ */ React.createElement(Routes, null, /* @__PURE__ */ React.createElement(Route, {
|
|
936
985
|
path: "/",
|
|
937
986
|
element: /* @__PURE__ */ React.createElement(ScaffolderPage, {
|
|
938
|
-
TemplateCardComponent
|
|
987
|
+
TemplateCardComponent,
|
|
988
|
+
groups
|
|
939
989
|
})
|
|
940
990
|
}), /* @__PURE__ */ React.createElement(Route, {
|
|
941
991
|
path: "/templates/:templateName",
|
|
@@ -952,4 +1002,4 @@ const Router = ({TemplateCardComponent}) => {
|
|
|
952
1002
|
};
|
|
953
1003
|
|
|
954
1004
|
export { Router };
|
|
955
|
-
//# sourceMappingURL=Router-
|
|
1005
|
+
//# sourceMappingURL=Router-a8e778fd.esm.js.map
|