@backstage/plugin-scaffolder 1.4.0-next.2 → 1.4.1-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 +81 -6
- package/alpha/package.json +1 -1
- package/dist/esm/{Router-fbba0f54.esm.js → Router-18ba5123.esm.js} +293 -177
- package/dist/esm/Router-18ba5123.esm.js.map +1 -0
- package/dist/esm/{default-a258a462.esm.js → default-a659a7f3.esm.js} +2 -2
- package/dist/esm/{default-a258a462.esm.js.map → default-a659a7f3.esm.js.map} +1 -1
- package/dist/esm/{index-a2c4b694.esm.js → index-53f13d8f.esm.js} +397 -274
- package/dist/esm/index-53f13d8f.esm.js.map +1 -0
- package/dist/esm/{index-a72ba1c5.esm.js → index-5a329900.esm.js} +36 -21
- package/dist/esm/{index-a72ba1c5.esm.js.map → index-5a329900.esm.js.map} +1 -1
- package/dist/index.alpha.d.ts +2 -1
- package/dist/index.beta.d.ts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.esm.js +1 -1
- package/package.json +23 -23
- package/dist/esm/Router-fbba0f54.esm.js.map +0 -1
- package/dist/esm/index-a2c4b694.esm.js.map +0 -1
|
@@ -3,7 +3,7 @@ import { useNavigate, Navigate, useOutlet, Routes, Route, useParams as useParams
|
|
|
3
3
|
import { ItemCardHeader, MarkdownContent, Button, ContentHeader, Progress, WarningPanel, Link as Link$1, Content, ItemCardGrid, Page, Header, CreateButton, SupportButton, StructuredMetadataTable, InfoCard, ErrorPage, ErrorPanel, LogViewer, StatusError, StatusOK, StatusPending, Lifecycle, EmptyState, Table as Table$1 } from '@backstage/core-components';
|
|
4
4
|
import { useRouteRef, useApi, errorApiRef, featureFlagsApiRef, useApiHolder, alertApiRef, useElementFilter } from '@backstage/core-plugin-api';
|
|
5
5
|
import { getEntityRelations, getEntitySourceLocation, FavoriteEntity, EntityRefLinks, useEntityList, EntityListProvider, CatalogFilterLayout, EntitySearchBar, EntityKindPicker, UserListPicker, EntityTagPicker, catalogApiRef, humanizeEntityRef, EntityRefLink } from '@backstage/plugin-catalog-react';
|
|
6
|
-
import { s as selectedTemplateRouteRef, e as editRouteRef, a as actionsRouteRef, b as scaffolderListTaskRouteRef, r as registerComponentRouteRef, T as TemplateTypePicker, S as SecretsContext, c as scaffolderApiRef, d as scaffolderTaskRouteRef, f as rootRouteRef, g as TaskStatusStepper, h as TaskPageLinks, F as FIELD_EXTENSION_WRAPPER_KEY, i as FIELD_EXTENSION_KEY, l as legacySelectedTemplateRouteRef, j as SecretsContextProvider, k as TaskPage } from './index-
|
|
6
|
+
import { s as selectedTemplateRouteRef, e as editRouteRef, a as actionsRouteRef, b as scaffolderListTaskRouteRef, r as registerComponentRouteRef, T as TemplateTypePicker, S as SecretsContext, c as scaffolderApiRef, d as scaffolderTaskRouteRef, f as rootRouteRef, g as TaskStatusStepper, h as TaskPageLinks, F as FIELD_EXTENSION_WRAPPER_KEY, i as FIELD_EXTENSION_KEY, l as legacySelectedTemplateRouteRef, j as SecretsContextProvider, k as TaskPage } from './index-53f13d8f.esm.js';
|
|
7
7
|
import { RELATION_OWNED_BY, parseEntityRef, stringifyEntityRef } from '@backstage/catalog-model';
|
|
8
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, Divider as Divider$1, FormControl, InputLabel, Select, MenuItem as MenuItem$1, List as List$2, ListItemIcon as ListItemIcon$1, ListItemText as ListItemText$1 } from '@material-ui/core';
|
|
9
9
|
import { scmIntegrationsApiRef, ScmIntegrationIcon } from '@backstage/integration-react';
|
|
@@ -66,7 +66,7 @@ import SettingsIcon from '@material-ui/icons/Settings';
|
|
|
66
66
|
import AllIcon from '@material-ui/icons/FontDownload';
|
|
67
67
|
import { DateTime, Interval } from 'luxon';
|
|
68
68
|
import humanizeDuration from 'humanize-duration';
|
|
69
|
-
import { D as DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS } from './default-
|
|
69
|
+
import { D as DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS } from './default-a659a7f3.esm.js';
|
|
70
70
|
import '@backstage/errors';
|
|
71
71
|
import 'zen-observable';
|
|
72
72
|
import '@material-ui/core/FormControl';
|
|
@@ -164,7 +164,10 @@ const TemplateCard = ({ template, deprecated }) => {
|
|
|
164
164
|
const backstageTheme = useTheme();
|
|
165
165
|
const templateRoute = useRouteRef(selectedTemplateRouteRef);
|
|
166
166
|
const templateProps = getTemplateCardProps(template);
|
|
167
|
-
const ownedByRelations = getEntityRelations(
|
|
167
|
+
const ownedByRelations = getEntityRelations(
|
|
168
|
+
template,
|
|
169
|
+
RELATION_OWNED_BY
|
|
170
|
+
);
|
|
168
171
|
const themeId = backstageTheme.getPageTheme({ themeId: templateProps.type }) ? templateProps.type : "other";
|
|
169
172
|
const theme = backstageTheme.getPageTheme({ themeId });
|
|
170
173
|
const classes = useStyles$e({ backgroundImage: theme.backgroundImage });
|
|
@@ -359,10 +362,12 @@ const ScaffolderPageContents = ({
|
|
|
359
362
|
};
|
|
360
363
|
const ScaffolderPage = ({
|
|
361
364
|
TemplateCardComponent,
|
|
362
|
-
groups
|
|
365
|
+
groups,
|
|
366
|
+
contextMenu
|
|
363
367
|
}) => /* @__PURE__ */ React.createElement(EntityListProvider, null, /* @__PURE__ */ React.createElement(ScaffolderPageContents, {
|
|
364
368
|
TemplateCardComponent,
|
|
365
|
-
groups
|
|
369
|
+
groups,
|
|
370
|
+
contextMenu
|
|
366
371
|
}));
|
|
367
372
|
|
|
368
373
|
function isObject$1(value) {
|
|
@@ -520,17 +525,23 @@ const MultistepJsonForm = (props) => {
|
|
|
520
525
|
const filteredStep = cloneDeep(step);
|
|
521
526
|
const removedPropertyKeys = [];
|
|
522
527
|
if (filteredStep.schema.properties) {
|
|
523
|
-
filteredStep.schema.properties = Object.fromEntries(
|
|
524
|
-
|
|
525
|
-
|
|
528
|
+
filteredStep.schema.properties = Object.fromEntries(
|
|
529
|
+
Object.entries(filteredStep.schema.properties).filter(
|
|
530
|
+
([key, value]) => {
|
|
531
|
+
if (value[featureFlagKey]) {
|
|
532
|
+
if (featureFlagApi.isActive(value[featureFlagKey])) {
|
|
533
|
+
return true;
|
|
534
|
+
}
|
|
535
|
+
removedPropertyKeys.push(key);
|
|
536
|
+
return false;
|
|
537
|
+
}
|
|
526
538
|
return true;
|
|
527
539
|
}
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
filteredStep.schema.required = Array.isArray(filteredStep.schema.required) ? (_a = filteredStep.schema.required) == null ? void 0 : _a.filter((r) => !removedPropertyKeys.includes(r)) : filteredStep.schema.required;
|
|
540
|
+
)
|
|
541
|
+
);
|
|
542
|
+
filteredStep.schema.required = Array.isArray(filteredStep.schema.required) ? (_a = filteredStep.schema.required) == null ? void 0 : _a.filter(
|
|
543
|
+
(r) => !removedPropertyKeys.includes(r)
|
|
544
|
+
) : filteredStep.schema.required;
|
|
534
545
|
}
|
|
535
546
|
return filteredStep;
|
|
536
547
|
};
|
|
@@ -636,13 +647,21 @@ const createValidator = (rootSchema, validators, context) => {
|
|
|
636
647
|
if (isObject(propData)) {
|
|
637
648
|
const propSchemaProps = schemaProps[key];
|
|
638
649
|
if (isObject(propSchemaProps)) {
|
|
639
|
-
validate(
|
|
650
|
+
validate(
|
|
651
|
+
propSchemaProps,
|
|
652
|
+
propData,
|
|
653
|
+
propValidation
|
|
654
|
+
);
|
|
640
655
|
}
|
|
641
656
|
} else {
|
|
642
657
|
const propSchema = schemaProps[key];
|
|
643
658
|
const fieldName = isObject(propSchema) && propSchema["ui:field"];
|
|
644
659
|
if (fieldName && typeof validators[fieldName] === "function") {
|
|
645
|
-
validators[fieldName](
|
|
660
|
+
validators[fieldName](
|
|
661
|
+
propData,
|
|
662
|
+
propValidation,
|
|
663
|
+
context
|
|
664
|
+
);
|
|
646
665
|
}
|
|
647
666
|
}
|
|
648
667
|
}
|
|
@@ -661,7 +680,10 @@ const createValidator = (rootSchema, validators, context) => {
|
|
|
661
680
|
|
|
662
681
|
const useTemplateParameterSchema = (templateRef) => {
|
|
663
682
|
const scaffolderApi = useApi(scaffolderApiRef);
|
|
664
|
-
const { value, loading, error } = useAsync(
|
|
683
|
+
const { value, loading, error } = useAsync(
|
|
684
|
+
() => scaffolderApi.getTemplateParameterSchema(templateRef),
|
|
685
|
+
[scaffolderApi, templateRef]
|
|
686
|
+
);
|
|
665
687
|
return { schema: value, loading, error };
|
|
666
688
|
};
|
|
667
689
|
const TemplatePage = ({
|
|
@@ -693,7 +715,10 @@ const TemplatePage = ({
|
|
|
693
715
|
}
|
|
694
716
|
});
|
|
695
717
|
const handleFormReset = () => setFormState({});
|
|
696
|
-
const handleChange = useCallback(
|
|
718
|
+
const handleChange = useCallback(
|
|
719
|
+
(e) => setFormState(e.formData),
|
|
720
|
+
[setFormState]
|
|
721
|
+
);
|
|
697
722
|
const handleCreate = async () => {
|
|
698
723
|
var _a;
|
|
699
724
|
const { taskId } = await scaffolderApi.scaffold({
|
|
@@ -701,7 +726,10 @@ const TemplatePage = ({
|
|
|
701
726
|
values: formState,
|
|
702
727
|
secrets: secretsContext == null ? void 0 : secretsContext.secrets
|
|
703
728
|
});
|
|
704
|
-
const formParams = qs.stringify(
|
|
729
|
+
const formParams = qs.stringify(
|
|
730
|
+
{ formData: formState },
|
|
731
|
+
{ addQueryPrefix: true }
|
|
732
|
+
);
|
|
705
733
|
const newUrl = `${window.location.pathname}${formParams}`;
|
|
706
734
|
(_a = window.history) == null ? void 0 : _a.replaceState(null, document.title, newUrl);
|
|
707
735
|
navigate(scaffolderTaskRoute({ taskId }));
|
|
@@ -718,8 +746,12 @@ const TemplatePage = ({
|
|
|
718
746
|
to: rootRoute()
|
|
719
747
|
});
|
|
720
748
|
}
|
|
721
|
-
const customFieldComponents = Object.fromEntries(
|
|
722
|
-
|
|
749
|
+
const customFieldComponents = Object.fromEntries(
|
|
750
|
+
customFieldExtensions.map(({ name, component }) => [name, component])
|
|
751
|
+
);
|
|
752
|
+
const customFieldValidators = Object.fromEntries(
|
|
753
|
+
customFieldExtensions.map(({ name, validation }) => [name, validation])
|
|
754
|
+
);
|
|
723
755
|
return /* @__PURE__ */ React.createElement(Page, {
|
|
724
756
|
themeId: "home"
|
|
725
757
|
}, /* @__PURE__ */ React.createElement(Header, {
|
|
@@ -741,7 +773,11 @@ const TemplatePage = ({
|
|
|
741
773
|
steps: schema.steps.map((step) => {
|
|
742
774
|
return {
|
|
743
775
|
...step,
|
|
744
|
-
validate: createValidator(
|
|
776
|
+
validate: createValidator(
|
|
777
|
+
step.schema,
|
|
778
|
+
customFieldValidators,
|
|
779
|
+
{ apiHolder }
|
|
780
|
+
)
|
|
745
781
|
};
|
|
746
782
|
})
|
|
747
783
|
}))));
|
|
@@ -1090,11 +1126,16 @@ class DirectoryEditorManager {
|
|
|
1090
1126
|
var _a;
|
|
1091
1127
|
const selectedPath = (_a = __privateGet(this, _selectedFile)) == null ? void 0 : _a.path;
|
|
1092
1128
|
const files = await __privateGet(this, _access2).listFiles();
|
|
1093
|
-
const fileManagers = await Promise.all(
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1129
|
+
const fileManagers = await Promise.all(
|
|
1130
|
+
files.map(async (file) => {
|
|
1131
|
+
const manager = new DirectoryEditorFileManager(
|
|
1132
|
+
file,
|
|
1133
|
+
__privateGet(this, _signalUpdate2)
|
|
1134
|
+
);
|
|
1135
|
+
await manager.reload();
|
|
1136
|
+
return manager;
|
|
1137
|
+
})
|
|
1138
|
+
);
|
|
1098
1139
|
__privateGet(this, _files).length = 0;
|
|
1099
1140
|
__privateGet(this, _files).push(...fileManagers);
|
|
1100
1141
|
this.setSelectedFile(selectedPath);
|
|
@@ -1112,7 +1153,9 @@ _listeners = new WeakMap();
|
|
|
1112
1153
|
_files = new WeakMap();
|
|
1113
1154
|
_selectedFile = new WeakMap();
|
|
1114
1155
|
_signalUpdate2 = new WeakMap();
|
|
1115
|
-
const DirectoryEditorContext = createContext(
|
|
1156
|
+
const DirectoryEditorContext = createContext(
|
|
1157
|
+
void 0
|
|
1158
|
+
);
|
|
1116
1159
|
function useDirectoryEditor() {
|
|
1117
1160
|
const value = useContext(DirectoryEditorContext);
|
|
1118
1161
|
const rerender = useRerender();
|
|
@@ -1124,15 +1167,17 @@ function useDirectoryEditor() {
|
|
|
1124
1167
|
}
|
|
1125
1168
|
function DirectoryEditorProvider(props) {
|
|
1126
1169
|
const { directory } = props;
|
|
1127
|
-
const [{ result, error }, { execute }] = useAsync$1(
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1170
|
+
const [{ result, error }, { execute }] = useAsync$1(
|
|
1171
|
+
async (dir) => {
|
|
1172
|
+
const manager = new DirectoryEditorManager(dir);
|
|
1173
|
+
await manager.reload();
|
|
1174
|
+
const firstYaml = manager.files.find((file) => file.path.match(/\.ya?ml$/));
|
|
1175
|
+
if (firstYaml) {
|
|
1176
|
+
manager.setSelectedFile(firstYaml.path);
|
|
1177
|
+
}
|
|
1178
|
+
return manager;
|
|
1133
1179
|
}
|
|
1134
|
-
|
|
1135
|
-
});
|
|
1180
|
+
);
|
|
1136
1181
|
useEffect(() => {
|
|
1137
1182
|
execute(directory);
|
|
1138
1183
|
}, [execute, directory]);
|
|
@@ -1162,7 +1207,9 @@ function base64EncodeContent(content) {
|
|
|
1162
1207
|
const buffer = decoder.encode(content);
|
|
1163
1208
|
const chunks = new Array();
|
|
1164
1209
|
for (let offset = 0; offset < buffer.length; offset += CHUNK_SIZE) {
|
|
1165
|
-
chunks.push(
|
|
1210
|
+
chunks.push(
|
|
1211
|
+
String.fromCharCode(...buffer.slice(offset, offset + CHUNK_SIZE))
|
|
1212
|
+
);
|
|
1166
1213
|
}
|
|
1167
1214
|
return btoa(chunks.join(""));
|
|
1168
1215
|
}
|
|
@@ -1201,38 +1248,44 @@ function DryRunProvider(props) {
|
|
|
1201
1248
|
};
|
|
1202
1249
|
});
|
|
1203
1250
|
}, []);
|
|
1204
|
-
const execute = useCallback(
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
setState((prevState) => {
|
|
1223
|
-
var _a;
|
|
1224
|
-
return {
|
|
1225
|
-
results: [...prevState.results, result],
|
|
1226
|
-
selectedResult: (_a = prevState.selectedResult) != null ? _a : result
|
|
1251
|
+
const execute = useCallback(
|
|
1252
|
+
async (options) => {
|
|
1253
|
+
if (!scaffolderApi.dryRun) {
|
|
1254
|
+
throw new Error("Scaffolder API does not support dry-run");
|
|
1255
|
+
}
|
|
1256
|
+
const parsed = yaml.parse(options.templateContent);
|
|
1257
|
+
const response = await scaffolderApi.dryRun({
|
|
1258
|
+
template: parsed,
|
|
1259
|
+
values: options.values,
|
|
1260
|
+
secrets: {},
|
|
1261
|
+
directoryContents: options.files.map((file) => ({
|
|
1262
|
+
path: file.path,
|
|
1263
|
+
base64Content: base64EncodeContent(file.content)
|
|
1264
|
+
}))
|
|
1265
|
+
});
|
|
1266
|
+
const result = {
|
|
1267
|
+
...response,
|
|
1268
|
+
id: idRef.current++
|
|
1227
1269
|
};
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1270
|
+
setState((prevState) => {
|
|
1271
|
+
var _a;
|
|
1272
|
+
return {
|
|
1273
|
+
results: [...prevState.results, result],
|
|
1274
|
+
selectedResult: (_a = prevState.selectedResult) != null ? _a : result
|
|
1275
|
+
};
|
|
1276
|
+
});
|
|
1277
|
+
},
|
|
1278
|
+
[scaffolderApi]
|
|
1279
|
+
);
|
|
1280
|
+
const dryRun = useMemo(
|
|
1281
|
+
() => ({
|
|
1282
|
+
...state,
|
|
1283
|
+
selectResult,
|
|
1284
|
+
deleteResult,
|
|
1285
|
+
execute
|
|
1286
|
+
}),
|
|
1287
|
+
[state, selectResult, deleteResult, execute]
|
|
1288
|
+
);
|
|
1236
1289
|
return /* @__PURE__ */ React.createElement(DryRunContext.Provider, {
|
|
1237
1290
|
value: dryRun
|
|
1238
1291
|
}, props.children);
|
|
@@ -1322,7 +1375,9 @@ function parseFileEntires(paths) {
|
|
|
1322
1375
|
path: entryPath,
|
|
1323
1376
|
children: []
|
|
1324
1377
|
};
|
|
1325
|
-
const firstFileIndex = current.children.findIndex(
|
|
1378
|
+
const firstFileIndex = current.children.findIndex(
|
|
1379
|
+
(child) => child.type === "file"
|
|
1380
|
+
);
|
|
1326
1381
|
current.children.splice(firstFileIndex, 0, newEntry);
|
|
1327
1382
|
current = newEntry;
|
|
1328
1383
|
} else {
|
|
@@ -1354,7 +1409,10 @@ function FileTreeItem({ entry }) {
|
|
|
1354
1409
|
}
|
|
1355
1410
|
function FileBrowser(props) {
|
|
1356
1411
|
const classes = useStyles$9();
|
|
1357
|
-
const fileTree = useMemo(
|
|
1412
|
+
const fileTree = useMemo(
|
|
1413
|
+
() => parseFileEntires(props.filePaths),
|
|
1414
|
+
[props.filePaths]
|
|
1415
|
+
);
|
|
1358
1416
|
return /* @__PURE__ */ React.createElement(TreeView, {
|
|
1359
1417
|
selected: props.selected,
|
|
1360
1418
|
className: classes.root,
|
|
@@ -1432,7 +1490,9 @@ function FilesContent() {
|
|
|
1432
1490
|
const classes = useStyles$7();
|
|
1433
1491
|
const { selectedResult } = useDryRun();
|
|
1434
1492
|
const [selectedPath, setSelectedPath] = useState("");
|
|
1435
|
-
const selectedFile = selectedResult == null ? void 0 : selectedResult.directoryContents.find(
|
|
1493
|
+
const selectedFile = selectedResult == null ? void 0 : selectedResult.directoryContents.find(
|
|
1494
|
+
(f) => f.path === selectedPath
|
|
1495
|
+
);
|
|
1436
1496
|
useEffect(() => {
|
|
1437
1497
|
if (selectedResult) {
|
|
1438
1498
|
const [firstFile] = selectedResult.directoryContents;
|
|
@@ -1471,7 +1531,9 @@ function LogContent() {
|
|
|
1471
1531
|
}
|
|
1472
1532
|
return (_a2 = selectedResult.steps.map((step) => {
|
|
1473
1533
|
var _a3, _b2;
|
|
1474
|
-
const stepLog = selectedResult.log.filter(
|
|
1534
|
+
const stepLog = selectedResult.log.filter(
|
|
1535
|
+
(l) => l.body.stepId === step.id
|
|
1536
|
+
);
|
|
1475
1537
|
return {
|
|
1476
1538
|
id: step.id,
|
|
1477
1539
|
name: step.name,
|
|
@@ -1514,7 +1576,9 @@ function OutputContent() {
|
|
|
1514
1576
|
}
|
|
1515
1577
|
function DryRunResultsView() {
|
|
1516
1578
|
const classes = useStyles$7();
|
|
1517
|
-
const [selectedTab, setSelectedTab] = useState(
|
|
1579
|
+
const [selectedTab, setSelectedTab] = useState(
|
|
1580
|
+
"files"
|
|
1581
|
+
);
|
|
1518
1582
|
return /* @__PURE__ */ React.createElement("div", {
|
|
1519
1583
|
className: classes.root
|
|
1520
1584
|
}, /* @__PURE__ */ React.createElement(Tabs, {
|
|
@@ -1614,7 +1678,9 @@ function TemplateEditorBrowser(props) {
|
|
|
1614
1678
|
return;
|
|
1615
1679
|
}
|
|
1616
1680
|
if (changedFiles.length > 0) {
|
|
1617
|
-
const accepted = window.confirm(
|
|
1681
|
+
const accepted = window.confirm(
|
|
1682
|
+
"Are you sure? Unsaved changes will be lost"
|
|
1683
|
+
);
|
|
1618
1684
|
if (!accepted) {
|
|
1619
1685
|
return;
|
|
1620
1686
|
}
|
|
@@ -1702,49 +1768,61 @@ function TemplateEditorForm(props) {
|
|
|
1702
1768
|
const apiHolder = useApiHolder();
|
|
1703
1769
|
const [steps, setSteps] = useState();
|
|
1704
1770
|
const fields = useMemo(() => {
|
|
1705
|
-
return Object.fromEntries(
|
|
1771
|
+
return Object.fromEntries(
|
|
1772
|
+
fieldExtensions.map(({ name, component }) => [name, component])
|
|
1773
|
+
);
|
|
1706
1774
|
}, [fieldExtensions]);
|
|
1707
|
-
useDebounce(
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
return;
|
|
1712
|
-
}
|
|
1713
|
-
const parsed = yaml.parse(content);
|
|
1714
|
-
if (!isJsonObject(parsed)) {
|
|
1715
|
-
setSteps(void 0);
|
|
1716
|
-
return;
|
|
1717
|
-
}
|
|
1718
|
-
let rootObj = parsed;
|
|
1719
|
-
if (!contentIsSpec) {
|
|
1720
|
-
const isTemplate = String(parsed.kind).toLocaleLowerCase("en-US") === "template";
|
|
1721
|
-
if (!isTemplate) {
|
|
1775
|
+
useDebounce(
|
|
1776
|
+
() => {
|
|
1777
|
+
try {
|
|
1778
|
+
if (!content) {
|
|
1722
1779
|
setSteps(void 0);
|
|
1723
1780
|
return;
|
|
1724
1781
|
}
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
setErrorText("Template parameters must be an array");
|
|
1730
|
-
setSteps(void 0);
|
|
1731
|
-
return;
|
|
1732
|
-
}
|
|
1733
|
-
const fieldValidators = Object.fromEntries(fieldExtensions.map(({ name, validation }) => [name, validation]));
|
|
1734
|
-
setErrorText();
|
|
1735
|
-
setSteps(parameters.flatMap((param) => isJsonObject(param) ? [
|
|
1736
|
-
{
|
|
1737
|
-
title: String(param.title),
|
|
1738
|
-
schema: param,
|
|
1739
|
-
validate: createValidator(param, fieldValidators, {
|
|
1740
|
-
apiHolder
|
|
1741
|
-
})
|
|
1782
|
+
const parsed = yaml.parse(content);
|
|
1783
|
+
if (!isJsonObject(parsed)) {
|
|
1784
|
+
setSteps(void 0);
|
|
1785
|
+
return;
|
|
1742
1786
|
}
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1787
|
+
let rootObj = parsed;
|
|
1788
|
+
if (!contentIsSpec) {
|
|
1789
|
+
const isTemplate = String(parsed.kind).toLocaleLowerCase("en-US") === "template";
|
|
1790
|
+
if (!isTemplate) {
|
|
1791
|
+
setSteps(void 0);
|
|
1792
|
+
return;
|
|
1793
|
+
}
|
|
1794
|
+
rootObj = isJsonObject(parsed.spec) ? parsed.spec : {};
|
|
1795
|
+
}
|
|
1796
|
+
const { parameters } = rootObj;
|
|
1797
|
+
if (!Array.isArray(parameters)) {
|
|
1798
|
+
setErrorText("Template parameters must be an array");
|
|
1799
|
+
setSteps(void 0);
|
|
1800
|
+
return;
|
|
1801
|
+
}
|
|
1802
|
+
const fieldValidators = Object.fromEntries(
|
|
1803
|
+
fieldExtensions.map(({ name, validation }) => [name, validation])
|
|
1804
|
+
);
|
|
1805
|
+
setErrorText();
|
|
1806
|
+
setSteps(
|
|
1807
|
+
parameters.flatMap(
|
|
1808
|
+
(param) => isJsonObject(param) ? [
|
|
1809
|
+
{
|
|
1810
|
+
title: String(param.title),
|
|
1811
|
+
schema: param,
|
|
1812
|
+
validate: createValidator(param, fieldValidators, {
|
|
1813
|
+
apiHolder
|
|
1814
|
+
})
|
|
1815
|
+
}
|
|
1816
|
+
] : []
|
|
1817
|
+
)
|
|
1818
|
+
);
|
|
1819
|
+
} catch (e) {
|
|
1820
|
+
setErrorText(e.message);
|
|
1821
|
+
}
|
|
1822
|
+
},
|
|
1823
|
+
250,
|
|
1824
|
+
[contentIsSpec, content, apiHolder]
|
|
1825
|
+
);
|
|
1748
1826
|
if (!steps) {
|
|
1749
1827
|
return null;
|
|
1750
1828
|
}
|
|
@@ -1838,12 +1916,15 @@ function TemplateEditorTextArea(props) {
|
|
|
1838
1916
|
dom.textContent = errorText;
|
|
1839
1917
|
return showPanel.of(() => ({ dom, bottom: true }));
|
|
1840
1918
|
}, [classes, errorText]);
|
|
1841
|
-
useKeyboardEvent(
|
|
1842
|
-
e.
|
|
1843
|
-
|
|
1844
|
-
|
|
1919
|
+
useKeyboardEvent(
|
|
1920
|
+
(e) => e.key === "s" && (e.ctrlKey || e.metaKey),
|
|
1921
|
+
(e) => {
|
|
1922
|
+
e.preventDefault();
|
|
1923
|
+
if (props.onSave) {
|
|
1924
|
+
props.onSave();
|
|
1925
|
+
}
|
|
1845
1926
|
}
|
|
1846
|
-
|
|
1927
|
+
);
|
|
1847
1928
|
return /* @__PURE__ */ React.createElement("div", {
|
|
1848
1929
|
className: classes.container
|
|
1849
1930
|
}, /* @__PURE__ */ React.createElement(CodeMirror, {
|
|
@@ -2022,31 +2103,43 @@ const TemplateFormPreviewer = ({
|
|
|
2022
2103
|
const [templateOptions, setTemplateOptions] = useState([]);
|
|
2023
2104
|
const [templateYaml, setTemplateYaml] = useState(defaultPreviewTemplate);
|
|
2024
2105
|
const [formState, setFormState] = useState({});
|
|
2025
|
-
const { loading } = useAsync(
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2106
|
+
const { loading } = useAsync(
|
|
2107
|
+
() => catalogApi.getEntities({
|
|
2108
|
+
filter: { kind: "template" },
|
|
2109
|
+
fields: [
|
|
2110
|
+
"kind",
|
|
2111
|
+
"metadata.namespace",
|
|
2112
|
+
"metadata.name",
|
|
2113
|
+
"metadata.title",
|
|
2114
|
+
"spec.parameters",
|
|
2115
|
+
"spec.steps",
|
|
2116
|
+
"spec.output"
|
|
2117
|
+
]
|
|
2118
|
+
}).then(
|
|
2119
|
+
({ items }) => setTemplateOptions(
|
|
2120
|
+
items.map((template) => {
|
|
2121
|
+
var _a;
|
|
2122
|
+
return {
|
|
2123
|
+
label: (_a = template.metadata.title) != null ? _a : humanizeEntityRef(template, { defaultKind: "template" }),
|
|
2124
|
+
value: template
|
|
2125
|
+
};
|
|
2126
|
+
})
|
|
2127
|
+
)
|
|
2128
|
+
).catch(
|
|
2129
|
+
(e) => alertApi.post({
|
|
2130
|
+
message: `Error loading exisiting templates: ${e.message}`,
|
|
2131
|
+
severity: "error"
|
|
2132
|
+
})
|
|
2133
|
+
),
|
|
2134
|
+
[catalogApi]
|
|
2135
|
+
);
|
|
2136
|
+
const handleSelectChange = useCallback(
|
|
2137
|
+
(selected) => {
|
|
2138
|
+
setSelectedTemplate(selected);
|
|
2139
|
+
setTemplateYaml(yaml.stringify(selected.spec));
|
|
2140
|
+
},
|
|
2141
|
+
[setTemplateYaml]
|
|
2142
|
+
);
|
|
2050
2143
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, loading && /* @__PURE__ */ React.createElement(LinearProgress, null), /* @__PURE__ */ React.createElement("main", {
|
|
2051
2144
|
className: classes.root
|
|
2052
2145
|
}, /* @__PURE__ */ React.createElement("div", {
|
|
@@ -2121,31 +2214,34 @@ function TemplateEditorPage(props) {
|
|
|
2121
2214
|
}), content);
|
|
2122
2215
|
}
|
|
2123
2216
|
|
|
2124
|
-
const useStyles = makeStyles(
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2217
|
+
const useStyles = makeStyles(
|
|
2218
|
+
(theme) => ({
|
|
2219
|
+
root: {
|
|
2220
|
+
backgroundColor: "rgba(0, 0, 0, .11)",
|
|
2221
|
+
boxShadow: "none",
|
|
2222
|
+
margin: theme.spacing(1, 0, 1, 0)
|
|
2223
|
+
},
|
|
2224
|
+
title: {
|
|
2225
|
+
margin: theme.spacing(1, 0, 0, 1),
|
|
2226
|
+
textTransform: "uppercase",
|
|
2227
|
+
fontSize: 12,
|
|
2228
|
+
fontWeight: "bold"
|
|
2229
|
+
},
|
|
2230
|
+
listIcon: {
|
|
2231
|
+
minWidth: 30,
|
|
2232
|
+
color: theme.palette.text.primary
|
|
2233
|
+
},
|
|
2234
|
+
menuItem: {
|
|
2235
|
+
minHeight: theme.spacing(6)
|
|
2236
|
+
},
|
|
2237
|
+
groupWrapper: {
|
|
2238
|
+
margin: theme.spacing(1, 1, 2, 1)
|
|
2239
|
+
}
|
|
2240
|
+
}),
|
|
2241
|
+
{
|
|
2242
|
+
name: "ScaffolderReactOwnerListPicker"
|
|
2145
2243
|
}
|
|
2146
|
-
|
|
2147
|
-
name: "ScaffolderReactOwnerListPicker"
|
|
2148
|
-
});
|
|
2244
|
+
);
|
|
2149
2245
|
function getFilterGroups() {
|
|
2150
2246
|
return [
|
|
2151
2247
|
{
|
|
@@ -2207,7 +2303,10 @@ const CreatedAtColumn = ({ createdAt }) => {
|
|
|
2207
2303
|
const OwnerEntityColumn = ({ entityRef }) => {
|
|
2208
2304
|
var _a, _b, _c;
|
|
2209
2305
|
const catalogApi = useApi(catalogApiRef);
|
|
2210
|
-
const { value, loading, error } = useAsync(
|
|
2306
|
+
const { value, loading, error } = useAsync(
|
|
2307
|
+
() => catalogApi.getEntityByRef(entityRef || ""),
|
|
2308
|
+
[catalogApi, entityRef]
|
|
2309
|
+
);
|
|
2211
2310
|
if (!entityRef) {
|
|
2212
2311
|
return /* @__PURE__ */ React.createElement("p", null, "Unknown");
|
|
2213
2312
|
}
|
|
@@ -2234,7 +2333,10 @@ const TaskStatusColumn = ({ status }) => {
|
|
|
2234
2333
|
|
|
2235
2334
|
const TemplateTitleColumn = ({ entityRef }) => {
|
|
2236
2335
|
const scaffolder = useApi(scaffolderApiRef);
|
|
2237
|
-
const { value, loading, error } = useAsync(
|
|
2336
|
+
const { value, loading, error } = useAsync(
|
|
2337
|
+
() => scaffolder.getTemplateParameterSchema(entityRef || ""),
|
|
2338
|
+
[scaffolder, entityRef]
|
|
2339
|
+
);
|
|
2238
2340
|
if (loading || error || !entityRef) {
|
|
2239
2341
|
return null;
|
|
2240
2342
|
}
|
|
@@ -2255,7 +2357,9 @@ const ListTaskPageContent = (props) => {
|
|
|
2255
2357
|
if (scaffolderApi.listTasks) {
|
|
2256
2358
|
return (_a2 = scaffolderApi.listTasks) == null ? void 0 : _a2.call(scaffolderApi, { filterByOwnership: ownerFilter });
|
|
2257
2359
|
}
|
|
2258
|
-
console.warn(
|
|
2360
|
+
console.warn(
|
|
2361
|
+
"listTasks is not implemented in the scaffolderApi, please make sure to implement this method."
|
|
2362
|
+
);
|
|
2259
2363
|
return Promise.resolve({ tasks: [] });
|
|
2260
2364
|
}, [scaffolderApi, ownerFilter]);
|
|
2261
2365
|
if (loading) {
|
|
@@ -2340,19 +2444,31 @@ const Router = (props) => {
|
|
|
2340
2444
|
const { TemplateCardComponent, TaskPageComponent } = components;
|
|
2341
2445
|
const outlet = useOutlet();
|
|
2342
2446
|
const TaskPageElement = TaskPageComponent != null ? TaskPageComponent : TaskPage;
|
|
2343
|
-
const customFieldExtensions = useElementFilter(
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2447
|
+
const customFieldExtensions = useElementFilter(
|
|
2448
|
+
outlet,
|
|
2449
|
+
(elements) => elements.selectByComponentData({
|
|
2450
|
+
key: FIELD_EXTENSION_WRAPPER_KEY
|
|
2451
|
+
}).findComponentData({
|
|
2452
|
+
key: FIELD_EXTENSION_KEY
|
|
2453
|
+
})
|
|
2454
|
+
);
|
|
2348
2455
|
const fieldExtensions = [
|
|
2349
2456
|
...customFieldExtensions,
|
|
2350
|
-
...DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS.filter(
|
|
2457
|
+
...DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS.filter(
|
|
2458
|
+
({ name }) => !customFieldExtensions.some(
|
|
2459
|
+
(customFieldExtension) => customFieldExtension.name === name
|
|
2460
|
+
)
|
|
2461
|
+
)
|
|
2351
2462
|
];
|
|
2352
2463
|
const RedirectingComponent = () => {
|
|
2353
2464
|
const { templateName } = useParams$1();
|
|
2354
2465
|
const newLink = useRouteRef(selectedTemplateRouteRef);
|
|
2355
|
-
useEffect(
|
|
2466
|
+
useEffect(
|
|
2467
|
+
() => console.warn(
|
|
2468
|
+
"The route /template/:templateName is deprecated, please use the new /template/:namespace/:templateName route instead"
|
|
2469
|
+
),
|
|
2470
|
+
[]
|
|
2471
|
+
);
|
|
2356
2472
|
return /* @__PURE__ */ React.createElement(Navigate, {
|
|
2357
2473
|
to: newLink({ namespace: "default", templateName })
|
|
2358
2474
|
});
|
|
@@ -2394,4 +2510,4 @@ const Router = (props) => {
|
|
|
2394
2510
|
};
|
|
2395
2511
|
|
|
2396
2512
|
export { Router };
|
|
2397
|
-
//# sourceMappingURL=Router-
|
|
2513
|
+
//# sourceMappingURL=Router-18ba5123.esm.js.map
|