@backstage/plugin-scaffolder 0.13.0 → 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 +33 -0
- package/dist/esm/{Router-8ca04a51.esm.js → Router-ba25f61c.esm.js} +23 -17
- package/dist/esm/Router-ba25f61c.esm.js.map +1 -0
- package/dist/esm/{index-7ce19edf.esm.js → index-da137e20.esm.js} +64 -68
- package/dist/esm/index-da137e20.esm.js.map +1 -0
- package/dist/index.d.ts +91 -84
- package/dist/index.esm.js +2 -4
- package/dist/index.esm.js.map +1 -1
- package/package.json +17 -17
- package/dist/esm/Router-8ca04a51.esm.js.map +0 -1
- package/dist/esm/index-7ce19edf.esm.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
# @backstage/plugin-scaffolder
|
|
2
2
|
|
|
3
|
+
## 0.14.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 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.
|
|
8
|
+
- 86da51cec5: **BREAKING**: Removing the exports of the raw components that back the `CustomFieldExtensions`.
|
|
9
|
+
|
|
10
|
+
### Patch Changes
|
|
11
|
+
|
|
12
|
+
- f41a293231: - **DEPRECATION**: Deprecated `formatEntityRefTitle` in favor of the new `humanizeEntityRef` method instead. Please migrate to using the new method instead.
|
|
13
|
+
- 55361f3f7b: Added some deprecations as follows:
|
|
14
|
+
|
|
15
|
+
- **DEPRECATED**: `TemplateCardComponent` and `TaskPageComponent` props have been deprecated, and moved to a `components` prop instead. You can pass them in through there instead.
|
|
16
|
+
- **DEPRECATED**: `TemplateList` and `TemplateListProps` has been deprecated. Please use the `TemplateCard` to create your own list component instead.
|
|
17
|
+
- **DEPRECATED**: `setSecret` has been deprecated in favour of `setSecrets` when calling `useTemplateSecrets`
|
|
18
|
+
|
|
19
|
+
Other notable changes:
|
|
20
|
+
|
|
21
|
+
- `scaffolderApi.scaffold()` `values` type has been narrowed from `Record<string, any>` to `Record<string, JsonValue>` instead.
|
|
22
|
+
- Moved all navigation internally over to using `routeRefs` and `subRouteRefs`
|
|
23
|
+
|
|
24
|
+
- Updated dependencies
|
|
25
|
+
- @backstage/catalog-model@0.12.0
|
|
26
|
+
- @backstage/catalog-client@0.8.0
|
|
27
|
+
- @backstage/core-components@0.9.0
|
|
28
|
+
- @backstage/plugin-catalog-react@0.8.0
|
|
29
|
+
- @backstage/plugin-catalog-common@0.2.0
|
|
30
|
+
- @backstage/integration@0.8.0
|
|
31
|
+
- @backstage/core-plugin-api@0.8.0
|
|
32
|
+
- @backstage/plugin-scaffolder-common@0.2.3
|
|
33
|
+
- @backstage/integration-react@0.1.24
|
|
34
|
+
- @backstage/plugin-permission-react@0.3.3
|
|
35
|
+
|
|
3
36
|
## 0.13.0
|
|
4
37
|
|
|
5
38
|
### Minor Changes
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import React, { useState, useContext, useCallback } from 'react';
|
|
2
|
-
import { useNavigate, Navigate,
|
|
2
|
+
import { useNavigate, Navigate, useOutlet, Routes, Route } from 'react-router';
|
|
3
3
|
import { Page, Header, Lifecycle, Content, ContentHeader, CreateButton, SupportButton, MarkdownContent, StructuredMetadataTable, InfoCard, Progress, ErrorPage } from '@backstage/core-components';
|
|
4
4
|
import { useRouteRef, useApi, errorApiRef, featureFlagsApiRef, useApiHolder, useElementFilter } from '@backstage/core-plugin-api';
|
|
5
5
|
import { EntityListProvider, EntitySearchBar, EntityKindPicker, UserListPicker, EntityTagPicker } from '@backstage/plugin-catalog-react';
|
|
6
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,
|
|
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 scaffolderTaskRouteRef, h as rootRouteRef, F as FIELD_EXTENSION_WRAPPER_KEY, i as FIELD_EXTENSION_KEY, j as SecretsContextProvider, k as TaskPage } from './index-da137e20.esm.js';
|
|
8
8
|
import { catalogEntityCreatePermission } from '@backstage/plugin-catalog-common';
|
|
9
9
|
import { usePermission } from '@backstage/plugin-permission-react';
|
|
10
10
|
import qs from 'qs';
|
|
@@ -26,8 +26,6 @@ import '@material-ui/core/FormHelperText';
|
|
|
26
26
|
import '@material-ui/core/Input';
|
|
27
27
|
import '@material-ui/core/InputLabel';
|
|
28
28
|
import 'react-use/lib/useDebounce';
|
|
29
|
-
import '@material-ui/icons/Star';
|
|
30
|
-
import '@material-ui/icons/StarBorder';
|
|
31
29
|
import '@material-ui/icons/Warning';
|
|
32
30
|
import 'lodash/capitalize';
|
|
33
31
|
import '@material-ui/icons/CheckBox';
|
|
@@ -423,7 +421,8 @@ const TemplatePage = ({
|
|
|
423
421
|
const scaffolderApi = useApi(scaffolderApiRef);
|
|
424
422
|
const { templateName } = useParams();
|
|
425
423
|
const navigate = useNavigate();
|
|
426
|
-
const
|
|
424
|
+
const scaffolderTaskRoute = useRouteRef(scaffolderTaskRouteRef);
|
|
425
|
+
const rootRoute = useRouteRef(rootRouteRef);
|
|
427
426
|
const { schema, loading, error } = useTemplateParameterSchema(templateName);
|
|
428
427
|
const [formState, setFormState] = useState(() => {
|
|
429
428
|
var _a;
|
|
@@ -452,18 +451,18 @@ const TemplatePage = ({
|
|
|
452
451
|
const formParams = qs.stringify({ formData: formState }, { addQueryPrefix: true });
|
|
453
452
|
const newUrl = `${window.location.pathname}${formParams}`;
|
|
454
453
|
(_a = window.history) == null ? void 0 : _a.replaceState(null, document.title, newUrl);
|
|
455
|
-
navigate(
|
|
454
|
+
navigate(scaffolderTaskRoute({ taskId }));
|
|
456
455
|
};
|
|
457
456
|
if (error) {
|
|
458
457
|
errorApi.post(new Error(`Failed to load template, ${error}`));
|
|
459
458
|
return /* @__PURE__ */ React.createElement(Navigate, {
|
|
460
|
-
to:
|
|
459
|
+
to: rootRoute()
|
|
461
460
|
});
|
|
462
461
|
}
|
|
463
462
|
if (!loading && !schema) {
|
|
464
463
|
errorApi.post(new Error("Template was not found."));
|
|
465
464
|
return /* @__PURE__ */ React.createElement(Navigate, {
|
|
466
|
-
to:
|
|
465
|
+
to: rootRoute()
|
|
467
466
|
});
|
|
468
467
|
}
|
|
469
468
|
const customFieldComponents = Object.fromEntries(customFieldExtensions.map(({ name, component }) => [name, component]));
|
|
@@ -605,13 +604,20 @@ const ActionsPage = () => {
|
|
|
605
604
|
}), /* @__PURE__ */ React.createElement(Content, null, items));
|
|
606
605
|
};
|
|
607
606
|
|
|
608
|
-
const Router = ({
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
607
|
+
const Router = (props) => {
|
|
608
|
+
var _a;
|
|
609
|
+
const {
|
|
610
|
+
TemplateCardComponent: legacyTemplateCardComponent,
|
|
611
|
+
TaskPageComponent: legacyTaskPageComponent,
|
|
612
|
+
groups,
|
|
613
|
+
components = {}
|
|
614
|
+
} = props;
|
|
615
|
+
if (legacyTemplateCardComponent || legacyTaskPageComponent) {
|
|
616
|
+
console.warn("DEPRECATION: 'TemplateCardComponent' and 'TaskPageComponent' are deprecated when calling the 'ScaffolderPage'. Use 'components' prop to pass these component overrides instead.");
|
|
617
|
+
}
|
|
618
|
+
const { TemplateCardComponent, TaskPageComponent } = components;
|
|
613
619
|
const outlet = useOutlet();
|
|
614
|
-
const TaskPageElement = TaskPageComponent
|
|
620
|
+
const TaskPageElement = (_a = TaskPageComponent != null ? TaskPageComponent : legacyTaskPageComponent) != null ? _a : TaskPage;
|
|
615
621
|
const customFieldExtensions = useElementFilter(outlet, (elements) => elements.selectByComponentData({
|
|
616
622
|
key: FIELD_EXTENSION_WRAPPER_KEY
|
|
617
623
|
}).findComponentData({
|
|
@@ -624,8 +630,8 @@ const Router = ({
|
|
|
624
630
|
return /* @__PURE__ */ React.createElement(Routes, null, /* @__PURE__ */ React.createElement(Route, {
|
|
625
631
|
path: "/",
|
|
626
632
|
element: /* @__PURE__ */ React.createElement(ScaffolderPage, {
|
|
627
|
-
|
|
628
|
-
|
|
633
|
+
groups,
|
|
634
|
+
TemplateCardComponent: TemplateCardComponent != null ? TemplateCardComponent : legacyTemplateCardComponent
|
|
629
635
|
})
|
|
630
636
|
}), /* @__PURE__ */ React.createElement(Route, {
|
|
631
637
|
path: "/templates/:templateName",
|
|
@@ -642,4 +648,4 @@ const Router = ({
|
|
|
642
648
|
};
|
|
643
649
|
|
|
644
650
|
export { Router };
|
|
645
|
-
//# sourceMappingURL=Router-
|
|
651
|
+
//# sourceMappingURL=Router-ba25f61c.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Router-ba25f61c.esm.js","sources":["../../src/extensions/default.ts","../../src/components/ScaffolderPage/ScaffolderPage.tsx","../../src/components/MultistepJsonForm/schema.ts","../../src/components/MultistepJsonForm/FieldOverrides/DescriptionField.tsx","../../src/components/MultistepJsonForm/MultistepJsonForm.tsx","../../src/components/TemplatePage/TemplatePage.tsx","../../src/components/ActionsPage/ActionsPage.tsx","../../src/components/Router.tsx"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { EntityPicker } from '../components/fields/EntityPicker/EntityPicker';\nimport { EntityNamePicker } from '../components/fields/EntityNamePicker/EntityNamePicker';\nimport { entityNamePickerValidation } from '../components/fields/EntityNamePicker/validation';\nimport { EntityTagsPicker } from '../components/fields/EntityTagsPicker/EntityTagsPicker';\nimport { OwnerPicker } from '../components/fields/OwnerPicker/OwnerPicker';\nimport { RepoUrlPicker } from '../components/fields/RepoUrlPicker/RepoUrlPicker';\nimport { repoPickerValidation } from '../components/fields/RepoUrlPicker/validation';\nimport { OwnedEntityPicker } from '../components/fields/OwnedEntityPicker/OwnedEntityPicker';\n\nexport const DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS = [\n {\n component: EntityPicker,\n name: 'EntityPicker',\n },\n {\n component: EntityNamePicker,\n name: 'EntityNamePicker',\n validation: entityNamePickerValidation,\n },\n {\n component: EntityTagsPicker,\n name: 'EntityTagsPicker',\n },\n {\n component: RepoUrlPicker,\n name: 'RepoUrlPicker',\n validation: repoPickerValidation,\n },\n {\n component: OwnerPicker,\n name: 'OwnerPicker',\n },\n {\n component: OwnedEntityPicker,\n name: 'OwnedEntityPicker',\n },\n];\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n Content,\n ContentHeader,\n CreateButton,\n Header,\n Lifecycle,\n Page,\n SupportButton,\n} from '@backstage/core-components';\nimport { Entity } from '@backstage/catalog-model';\nimport { TemplateEntityV1beta2 } from '@backstage/plugin-scaffolder-common';\nimport { useRouteRef } from '@backstage/core-plugin-api';\nimport {\n EntityKindPicker,\n EntityListProvider,\n EntitySearchBar,\n EntityTagPicker,\n UserListPicker,\n} from '@backstage/plugin-catalog-react';\nimport { makeStyles } from '@material-ui/core';\nimport React, { ComponentType } from 'react';\nimport { registerComponentRouteRef } from '../../routes';\nimport { TemplateList } from '../TemplateList';\nimport { TemplateTypePicker } from '../TemplateTypePicker';\nimport { catalogEntityCreatePermission } from '@backstage/plugin-catalog-common';\nimport { usePermission } from '@backstage/plugin-permission-react';\n\nconst useStyles = makeStyles(theme => ({\n contentWrapper: {\n display: 'grid',\n gridTemplateAreas: \"'filters' 'grid'\",\n gridTemplateColumns: '250px 1fr',\n gridColumnGap: theme.spacing(2),\n },\n}));\n\nexport type ScaffolderPageProps = {\n TemplateCardComponent?:\n | ComponentType<{ template: TemplateEntityV1beta2 }>\n | undefined;\n groups?: Array<{\n title?: React.ReactNode;\n /** @deprcated use title instead as it accepts a string and react component */\n titleComponent?: React.ReactNode;\n filter: (entity: Entity) => boolean;\n }>;\n};\n\nexport const ScaffolderPageContents = ({\n TemplateCardComponent,\n groups,\n}: ScaffolderPageProps) => {\n const styles = useStyles();\n const registerComponentLink = useRouteRef(registerComponentRouteRef);\n const otherTemplatesGroup = {\n title: groups ? 'Other Templates' : 'Templates',\n filter: (entity: Entity) => {\n const filtered = (groups ?? []).map(group => group.filter(entity));\n return !filtered.some(result => result === true);\n },\n };\n\n const { allowed } = usePermission(catalogEntityCreatePermission);\n\n return (\n <Page themeId=\"home\">\n <Header\n pageTitleOverride=\"Create a New Component\"\n title={\n <>\n Create a New Component <Lifecycle shorthand />\n </>\n }\n subtitle=\"Create new software components using standard templates\"\n />\n <Content>\n <ContentHeader title=\"Available Templates\">\n {allowed && (\n <CreateButton\n title=\"Register Existing Component\"\n to={registerComponentLink && registerComponentLink()}\n />\n )}\n <SupportButton>\n Create new software components using standard templates. Different\n templates create different kinds of components (services, websites,\n documentation, ...).\n </SupportButton>\n </ContentHeader>\n\n <div className={styles.contentWrapper}>\n <div>\n <EntitySearchBar />\n <EntityKindPicker initialFilter=\"template\" hidden />\n <UserListPicker\n initialFilter=\"all\"\n availableFilters={['all', 'starred']}\n />\n <TemplateTypePicker />\n <EntityTagPicker />\n </div>\n <div>\n {groups &&\n groups.map((group, index) => (\n <TemplateList\n key={index}\n TemplateCardComponent={TemplateCardComponent}\n group={group}\n />\n ))}\n <TemplateList\n key=\"other\"\n TemplateCardComponent={TemplateCardComponent}\n group={otherTemplatesGroup}\n />\n </div>\n </div>\n </Content>\n </Page>\n );\n};\n\nexport const ScaffolderPage = ({\n TemplateCardComponent,\n groups,\n}: ScaffolderPageProps) => (\n <EntityListProvider>\n <ScaffolderPageContents\n TemplateCardComponent={TemplateCardComponent}\n groups={groups}\n />\n </EntityListProvider>\n);\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { JsonObject } from '@backstage/types';\nimport { FormProps } from '@rjsf/core';\n\nfunction isObject(value: unknown): value is JsonObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction extractUiSchema(schema: JsonObject, uiSchema: JsonObject) {\n if (!isObject(schema)) {\n return;\n }\n\n const { properties, items, anyOf, oneOf, allOf, dependencies } = schema;\n\n for (const propName in schema) {\n if (!schema.hasOwnProperty(propName)) {\n continue;\n }\n\n if (propName.startsWith('ui:')) {\n uiSchema[propName] = schema[propName];\n delete schema[propName];\n }\n }\n\n if (isObject(properties)) {\n for (const propName in properties) {\n if (!properties.hasOwnProperty(propName)) {\n continue;\n }\n\n const schemaNode = properties[propName];\n if (!isObject(schemaNode)) {\n continue;\n }\n const innerUiSchema = {};\n uiSchema[propName] = innerUiSchema;\n extractUiSchema(schemaNode, innerUiSchema);\n }\n }\n\n if (isObject(items)) {\n const innerUiSchema = {};\n uiSchema.items = innerUiSchema;\n extractUiSchema(items, innerUiSchema);\n }\n\n if (Array.isArray(anyOf)) {\n for (const schemaNode of anyOf) {\n if (!isObject(schemaNode)) {\n continue;\n }\n extractUiSchema(schemaNode, uiSchema);\n }\n }\n\n if (Array.isArray(oneOf)) {\n for (const schemaNode of oneOf) {\n if (!isObject(schemaNode)) {\n continue;\n }\n extractUiSchema(schemaNode, uiSchema);\n }\n }\n\n if (Array.isArray(allOf)) {\n for (const schemaNode of allOf) {\n if (!isObject(schemaNode)) {\n continue;\n }\n extractUiSchema(schemaNode, uiSchema);\n }\n }\n\n if (isObject(dependencies)) {\n for (const depName of Object.keys(dependencies)) {\n const schemaNode = dependencies[depName];\n if (!isObject(schemaNode)) {\n continue;\n }\n extractUiSchema(schemaNode, uiSchema);\n }\n }\n}\n\nexport function transformSchemaToProps(inputSchema: JsonObject): {\n schema: FormProps<any>['schema'];\n uiSchema: FormProps<any>['uiSchema'];\n} {\n inputSchema.type = inputSchema.type || 'object';\n const schema = JSON.parse(JSON.stringify(inputSchema));\n delete schema.title; // Rendered separately\n const uiSchema = {};\n extractUiSchema(schema, uiSchema);\n return { schema, uiSchema };\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport { MarkdownContent } from '@backstage/core-components';\nimport { FieldProps } from '@rjsf/core';\n\nexport const DescriptionField = ({ description }: FieldProps) =>\n description && <MarkdownContent content={description} linkTarget=\"_blank\" />;\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { JsonObject } from '@backstage/types';\nimport {\n Box,\n Button,\n Paper,\n Step as StepUI,\n StepContent,\n StepLabel,\n Stepper,\n Typography,\n} from '@material-ui/core';\nimport {\n errorApiRef,\n useApi,\n featureFlagsApiRef,\n} from '@backstage/core-plugin-api';\nimport { FormProps, IChangeEvent, UiSchema, withTheme } from '@rjsf/core';\nimport { Theme as MuiTheme } from '@rjsf/material-ui';\nimport React, { useState } from 'react';\nimport { transformSchemaToProps } from './schema';\nimport { Content, StructuredMetadataTable } from '@backstage/core-components';\nimport cloneDeep from 'lodash/cloneDeep';\nimport * as fieldOverrides from './FieldOverrides';\n\nconst Form = withTheme(MuiTheme);\ntype Step = {\n schema: JsonObject;\n title: string;\n} & Partial<Omit<FormProps<any>, 'schema'>>;\n\ntype Props = {\n /**\n * Steps for the form, each contains title and form schema\n */\n steps: Step[];\n formData: Record<string, any>;\n onChange: (e: IChangeEvent) => void;\n onReset: () => void;\n onFinish: () => Promise<void>;\n widgets?: FormProps<any>['widgets'];\n fields?: FormProps<any>['fields'];\n};\n\nexport function getUiSchemasFromSteps(steps: Step[]): UiSchema[] {\n const uiSchemas: Array<UiSchema> = [];\n steps.forEach(step => {\n const schemaProps = step.schema.properties as JsonObject;\n for (const key in schemaProps) {\n if (schemaProps.hasOwnProperty(key)) {\n const uiSchema = schemaProps[key] as UiSchema;\n uiSchema.name = key;\n uiSchemas.push(uiSchema);\n }\n }\n });\n return uiSchemas;\n}\n\nexport function getReviewData(formData: Record<string, any>, steps: Step[]) {\n const uiSchemas = getUiSchemasFromSteps(steps);\n const reviewData: Record<string, any> = {};\n for (const key in formData) {\n if (formData.hasOwnProperty(key)) {\n const uiSchema = uiSchemas.find(us => us.name === key);\n\n if (!uiSchema) {\n reviewData[key] = formData[key];\n continue;\n }\n\n if (uiSchema['ui:widget'] === 'password') {\n reviewData[key] = '******';\n continue;\n }\n\n if (!uiSchema['ui:backstage'] || !uiSchema['ui:backstage'].review) {\n reviewData[key] = formData[key];\n continue;\n }\n\n const review = uiSchema['ui:backstage'].review as JsonObject;\n if (!review.show) {\n continue;\n }\n\n if (review.mask) {\n reviewData[key] = review.mask;\n continue;\n }\n reviewData[key] = formData[key];\n }\n }\n\n return reviewData;\n}\n\nexport const MultistepJsonForm = (props: Props) => {\n const { formData, onChange, onReset, onFinish, fields, widgets } = props;\n const [activeStep, setActiveStep] = useState(0);\n const [disableButtons, setDisableButtons] = useState(false);\n const errorApi = useApi(errorApiRef);\n const featureFlagApi = useApi(featureFlagsApiRef);\n const featureFlagKey = 'backstage:featureFlag';\n const filterOutProperties = (step: Step): Step => {\n const filteredStep = cloneDeep(step);\n const removedPropertyKeys: Array<string> = [];\n if (filteredStep.schema.properties) {\n filteredStep.schema.properties = Object.fromEntries(\n Object.entries(filteredStep.schema.properties).filter(\n ([key, value]) => {\n if (value[featureFlagKey]) {\n if (featureFlagApi.isActive(value[featureFlagKey])) {\n return true;\n }\n removedPropertyKeys.push(key);\n return false;\n }\n return true;\n },\n ),\n );\n\n // remove the feature flag property key from required if they are not active\n filteredStep.schema.required = Array.isArray(filteredStep.schema.required)\n ? filteredStep.schema.required?.filter(\n r => !removedPropertyKeys.includes(r as string),\n )\n : filteredStep.schema.required;\n }\n return filteredStep;\n };\n\n const steps = props.steps\n .filter(step => {\n const featureFlag = step.schema[featureFlagKey];\n return (\n typeof featureFlag !== 'string' || featureFlagApi.isActive(featureFlag)\n );\n })\n .map(filterOutProperties);\n\n const handleReset = () => {\n setActiveStep(0);\n onReset();\n };\n const handleNext = () => {\n setActiveStep(Math.min(activeStep + 1, steps.length));\n };\n const handleBack = () => setActiveStep(Math.max(activeStep - 1, 0));\n const handleCreate = async () => {\n setDisableButtons(true);\n try {\n await onFinish();\n } catch (err) {\n setDisableButtons(false);\n errorApi.post(err);\n }\n };\n\n return (\n <>\n <Stepper activeStep={activeStep} orientation=\"vertical\">\n {steps.map(({ title, schema, ...formProps }, index) => {\n return (\n <StepUI key={title}>\n <StepLabel\n aria-label={`Step ${index + 1} ${title}`}\n aria-disabled=\"false\"\n tabIndex={0}\n >\n <Typography variant=\"h6\" component=\"h3\">\n {title}\n </Typography>\n </StepLabel>\n <StepContent key={title}>\n <Form\n showErrorList={false}\n fields={{ ...fieldOverrides, ...fields }}\n widgets={widgets}\n noHtml5Validate\n formData={formData}\n onChange={onChange}\n onSubmit={e => {\n if (e.errors.length === 0) handleNext();\n }}\n {...formProps}\n {...transformSchemaToProps(schema)}\n >\n <Button disabled={activeStep === 0} onClick={handleBack}>\n Back\n </Button>\n <Button variant=\"contained\" color=\"primary\" type=\"submit\">\n Next step\n </Button>\n </Form>\n </StepContent>\n </StepUI>\n );\n })}\n </Stepper>\n {activeStep === steps.length && (\n <Content>\n <Paper square elevation={0}>\n <Typography variant=\"h6\">Review and create</Typography>\n <StructuredMetadataTable\n dense\n metadata={getReviewData(formData, steps)}\n />\n <Box mb={4} />\n <Button onClick={handleBack} disabled={disableButtons}>\n Back\n </Button>\n <Button onClick={handleReset} disabled={disableButtons}>\n Reset\n </Button>\n <Button\n variant=\"contained\"\n color=\"primary\"\n onClick={handleCreate}\n disabled={disableButtons}\n >\n Create\n </Button>\n </Paper>\n </Content>\n )}\n </>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { JsonObject, JsonValue } from '@backstage/types';\nimport { LinearProgress } from '@material-ui/core';\nimport { FormValidation, IChangeEvent } from '@rjsf/core';\nimport qs from 'qs';\nimport React, { useCallback, useContext, useState } from 'react';\nimport { Navigate, useNavigate } from 'react-router';\nimport { useParams } from 'react-router-dom';\nimport useAsync from 'react-use/lib/useAsync';\nimport { scaffolderApiRef } from '../../api';\nimport { CustomFieldValidator, FieldExtensionOptions } from '../../extensions';\nimport { SecretsContext } from '../secrets/SecretsContext';\nimport { rootRouteRef, scaffolderTaskRouteRef } from '../../routes';\nimport { MultistepJsonForm } from '../MultistepJsonForm';\n\nimport {\n Content,\n Header,\n InfoCard,\n Lifecycle,\n Page,\n} from '@backstage/core-components';\nimport {\n ApiHolder,\n errorApiRef,\n useApi,\n useApiHolder,\n useRouteRef,\n} from '@backstage/core-plugin-api';\nimport { stringifyEntityRef } from '@backstage/catalog-model';\n\nconst useTemplateParameterSchema = (templateRef: string) => {\n const scaffolderApi = useApi(scaffolderApiRef);\n const { value, loading, error } = useAsync(\n () => scaffolderApi.getTemplateParameterSchema(templateRef),\n [scaffolderApi, templateRef],\n );\n return { schema: value, loading, error };\n};\n\nfunction isObject(obj: unknown): obj is JsonObject {\n return typeof obj === 'object' && obj !== null && !Array.isArray(obj);\n}\n\nexport const createValidator = (\n rootSchema: JsonObject,\n validators: Record<string, undefined | CustomFieldValidator<unknown>>,\n context: {\n apiHolder: ApiHolder;\n },\n) => {\n function validate(\n schema: JsonObject,\n formData: JsonObject,\n errors: FormValidation,\n ) {\n const schemaProps = schema.properties;\n if (!isObject(schemaProps)) {\n return;\n }\n\n for (const [key, propData] of Object.entries(formData)) {\n const propValidation = errors[key];\n\n if (isObject(propData)) {\n const propSchemaProps = schemaProps[key];\n if (isObject(propSchemaProps)) {\n validate(\n propSchemaProps,\n propData as JsonObject,\n propValidation as FormValidation,\n );\n }\n } else {\n const propSchema = schemaProps[key];\n const fieldName =\n isObject(propSchema) && (propSchema['ui:field'] as string);\n if (fieldName && typeof validators[fieldName] === 'function') {\n validators[fieldName]!(\n propData as JsonValue,\n propValidation,\n context,\n );\n }\n }\n }\n }\n\n return (formData: JsonObject, errors: FormValidation) => {\n validate(rootSchema, formData, errors);\n return errors;\n };\n};\n\nexport const TemplatePage = ({\n customFieldExtensions = [],\n}: {\n customFieldExtensions?: FieldExtensionOptions<any, any>[];\n}) => {\n const apiHolder = useApiHolder();\n const secretsContext = useContext(SecretsContext);\n const errorApi = useApi(errorApiRef);\n const scaffolderApi = useApi(scaffolderApiRef);\n const { templateName } = useParams();\n const navigate = useNavigate();\n const scaffolderTaskRoute = useRouteRef(scaffolderTaskRouteRef);\n const rootRoute = useRouteRef(rootRouteRef);\n const { schema, loading, error } = useTemplateParameterSchema(templateName);\n const [formState, setFormState] = useState<Record<string, any>>(() => {\n const query = qs.parse(window.location.search, {\n ignoreQueryPrefix: true,\n });\n\n try {\n return JSON.parse(query.formData as string);\n } catch (e) {\n return query.formData ?? {};\n }\n });\n const handleFormReset = () => setFormState({});\n const handleChange = useCallback(\n (e: IChangeEvent) => setFormState(e.formData),\n [setFormState],\n );\n\n const handleCreate = async () => {\n const { taskId } = await scaffolderApi.scaffold({\n templateRef: stringifyEntityRef({\n name: templateName,\n kind: 'template',\n namespace: 'default',\n }),\n values: formState,\n secrets: secretsContext?.secrets,\n });\n\n const formParams = qs.stringify(\n { formData: formState },\n { addQueryPrefix: true },\n );\n const newUrl = `${window.location.pathname}${formParams}`;\n // We use direct history manipulation since useSearchParams and\n // useNavigate in react-router-dom cause unnecessary extra rerenders.\n // Also make sure to replace the state rather than pushing to avoid\n // extra back/forward slots.\n window.history?.replaceState(null, document.title, newUrl);\n\n navigate(scaffolderTaskRoute({ taskId }));\n };\n\n if (error) {\n errorApi.post(new Error(`Failed to load template, ${error}`));\n return <Navigate to={rootRoute()} />;\n }\n if (!loading && !schema) {\n errorApi.post(new Error('Template was not found.'));\n return <Navigate to={rootRoute()} />;\n }\n\n const customFieldComponents = Object.fromEntries(\n customFieldExtensions.map(({ name, component }) => [name, component]),\n );\n\n const customFieldValidators = Object.fromEntries(\n customFieldExtensions.map(({ name, validation }) => [name, validation]),\n );\n\n return (\n <Page themeId=\"home\">\n <Header\n pageTitleOverride=\"Create a New Component\"\n title={\n <>\n Create a New Component <Lifecycle shorthand />\n </>\n }\n subtitle=\"Create new software components using standard templates\"\n />\n <Content>\n {loading && <LinearProgress data-testid=\"loading-progress\" />}\n {schema && (\n <InfoCard\n title={schema.title}\n noPadding\n titleTypographyProps={{ component: 'h2' }}\n >\n <MultistepJsonForm\n formData={formState}\n fields={customFieldComponents}\n onChange={handleChange}\n onReset={handleFormReset}\n onFinish={handleCreate}\n steps={schema.steps.map(step => {\n return {\n ...step,\n validate: createValidator(\n step.schema,\n customFieldValidators,\n { apiHolder },\n ),\n };\n })}\n />\n </InfoCard>\n )}\n </Content>\n </Page>\n );\n};\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React from 'react';\nimport useAsync from 'react-use/lib/useAsync';\nimport { scaffolderApiRef } from '../../api';\nimport {\n Typography,\n Paper,\n Table,\n TableBody,\n Box,\n TableCell,\n TableContainer,\n TableHead,\n TableRow,\n makeStyles,\n} from '@material-ui/core';\nimport { JSONSchema7, JSONSchema7Definition } from 'json-schema';\nimport classNames from 'classnames';\n\nimport { useApi } from '@backstage/core-plugin-api';\nimport {\n Progress,\n Content,\n Header,\n Page,\n ErrorPage,\n} from '@backstage/core-components';\n\nconst useStyles = makeStyles(theme => ({\n code: {\n fontFamily: 'Menlo, monospace',\n padding: theme.spacing(1),\n backgroundColor:\n theme.palette.type === 'dark'\n ? theme.palette.grey[700]\n : theme.palette.grey[300],\n display: 'inline-block',\n borderRadius: 5,\n border: `1px solid ${theme.palette.grey[500]}`,\n position: 'relative',\n },\n\n codeRequired: {\n '&::after': {\n position: 'absolute',\n content: '\"*\"',\n top: 0,\n right: theme.spacing(0.5),\n fontWeight: 'bolder',\n color: theme.palette.error.light,\n },\n },\n}));\n\nexport const ActionsPage = () => {\n const api = useApi(scaffolderApiRef);\n const classes = useStyles();\n const { loading, value, error } = useAsync(async () => {\n return api.listActions();\n });\n\n if (loading) {\n return <Progress />;\n }\n\n if (error) {\n return (\n <ErrorPage\n statusMessage=\"Failed to load installed actions\"\n status=\"500\"\n />\n );\n }\n\n const formatRows = (input: JSONSchema7) => {\n const properties = input.properties;\n if (!properties) {\n return undefined;\n }\n\n return Object.entries(properties).map(entry => {\n const [key] = entry;\n const props = entry[1] as unknown as JSONSchema7;\n const codeClassname = classNames(classes.code, {\n [classes.codeRequired]: input.required?.includes(key),\n });\n\n return (\n <TableRow key={key}>\n <TableCell>\n <div className={codeClassname}>{key}</div>\n </TableCell>\n <TableCell>{props.title}</TableCell>\n <TableCell>{props.description}</TableCell>\n <TableCell>\n <span className={classes.code}>{props.type}</span>\n </TableCell>\n </TableRow>\n );\n });\n };\n\n const renderTable = (input: JSONSchema7) => {\n if (!input.properties) {\n return undefined;\n }\n return (\n <TableContainer component={Paper}>\n <Table size=\"small\">\n <TableHead>\n <TableRow>\n <TableCell>Name</TableCell>\n <TableCell>Title</TableCell>\n <TableCell>Description</TableCell>\n <TableCell>Type</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>{formatRows(input)}</TableBody>\n </Table>\n </TableContainer>\n );\n };\n\n const renderTables = (name: string, input?: JSONSchema7Definition[]) => {\n if (!input) {\n return undefined;\n }\n\n return (\n <>\n <Typography variant=\"h6\">{name}</Typography>\n {input.map((i, index) => (\n <div key={index}>{renderTable(i as unknown as JSONSchema7)}</div>\n ))}\n </>\n );\n };\n\n const items = value?.map(action => {\n if (action.id.startsWith('legacy:')) {\n return undefined;\n }\n\n const oneOf = renderTables('oneOf', action.schema?.input?.oneOf);\n return (\n <Box pb={4} key={action.id}>\n <Typography variant=\"h4\" className={classes.code}>\n {action.id}\n </Typography>\n <Typography>{action.description}</Typography>\n {action.schema?.input && (\n <Box pb={2}>\n <Typography variant=\"h5\">Input</Typography>\n {renderTable(action.schema.input)}\n {oneOf}\n </Box>\n )}\n {action.schema?.output && (\n <Box pb={2}>\n <Typography variant=\"h5\">Output</Typography>\n {renderTable(action.schema.output)}\n </Box>\n )}\n </Box>\n );\n });\n\n return (\n <Page themeId=\"home\">\n <Header\n pageTitleOverride=\"Create a New Component\"\n title=\"Installed actions\"\n subtitle=\"This is the collection of all installed actions\"\n />\n <Content>{items}</Content>\n </Page>\n );\n};\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, { ComponentType } from 'react';\nimport { Routes, Route, useOutlet } from 'react-router';\nimport { Entity } from '@backstage/catalog-model';\nimport { TemplateEntityV1beta2 } from '@backstage/plugin-scaffolder-common';\nimport { ScaffolderPage } from './ScaffolderPage';\nimport { TemplatePage } from './TemplatePage';\nimport { TaskPage } from './TaskPage';\nimport { ActionsPage } from './ActionsPage';\nimport { SecretsContextProvider } from './secrets/SecretsContext';\n\nimport {\n FieldExtensionOptions,\n FIELD_EXTENSION_WRAPPER_KEY,\n FIELD_EXTENSION_KEY,\n DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS,\n} from '../extensions';\nimport { useElementFilter } from '@backstage/core-plugin-api';\n\nexport type RouterProps = {\n /** @deprecated use components.TemplateCardComponent instead */\n TemplateCardComponent?:\n | ComponentType<{ template: TemplateEntityV1beta2 }>\n | undefined;\n /** @deprecated use component.TaskPageComponent instead */\n TaskPageComponent?: ComponentType<{}>;\n\n components?: {\n TemplateCardComponent?:\n | ComponentType<{ template: TemplateEntityV1beta2 }>\n | undefined;\n TaskPageComponent?: ComponentType<{}>;\n };\n groups?: Array<{\n title?: string;\n titleComponent?: React.ReactNode;\n filter: (entity: Entity) => boolean;\n }>;\n};\n\nexport const Router = (props: RouterProps) => {\n const {\n TemplateCardComponent: legacyTemplateCardComponent,\n TaskPageComponent: legacyTaskPageComponent,\n groups,\n components = {},\n } = props;\n\n if (legacyTemplateCardComponent || legacyTaskPageComponent) {\n // eslint-disable-next-line no-console\n console.warn(\n \"DEPRECATION: 'TemplateCardComponent' and 'TaskPageComponent' are deprecated when calling the 'ScaffolderPage'. Use 'components' prop to pass these component overrides instead.\",\n );\n }\n\n const { TemplateCardComponent, TaskPageComponent } = components;\n\n const outlet = useOutlet();\n const TaskPageElement =\n TaskPageComponent ?? legacyTaskPageComponent ?? TaskPage;\n\n const customFieldExtensions = useElementFilter(outlet, elements =>\n elements\n .selectByComponentData({\n key: FIELD_EXTENSION_WRAPPER_KEY,\n })\n .findComponentData<FieldExtensionOptions>({\n key: FIELD_EXTENSION_KEY,\n }),\n );\n\n const fieldExtensions = [\n ...customFieldExtensions,\n ...DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS.filter(\n ({ name }) =>\n !customFieldExtensions.some(\n customFieldExtension => customFieldExtension.name === name,\n ),\n ),\n ];\n\n return (\n <Routes>\n <Route\n path=\"/\"\n element={\n <ScaffolderPage\n groups={groups}\n TemplateCardComponent={\n TemplateCardComponent ?? legacyTemplateCardComponent\n }\n />\n }\n />\n <Route\n path=\"/templates/:templateName\"\n element={\n <SecretsContextProvider>\n <TemplatePage customFieldExtensions={fieldExtensions} />\n </SecretsContextProvider>\n }\n />\n <Route path=\"/tasks/:taskId\" element={<TaskPageElement />} />\n <Route path=\"/actions\" element={<ActionsPage />} />\n </Routes>\n );\n};\n"],"names":["useStyles","isObject","MuiTheme","StepUI"],"mappings":"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"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { parseEntityRef, KubernetesValidatorFunctions, makeValidator, RELATION_OWNED_BY, stringifyEntityRef } from '@backstage/catalog-model';
|
|
2
|
-
import { createApiRef, useApi, attachComponentData, createExternalRouteRef, createRouteRef, createPlugin, createApiFactory, discoveryApiRef, fetchApiRef, createRoutableExtension, useRouteRef, alertApiRef, useApp } from '@backstage/core-plugin-api';
|
|
2
|
+
import { createApiRef, useApi, attachComponentData, createExternalRouteRef, createRouteRef, createSubRouteRef, createPlugin, createApiFactory, discoveryApiRef, fetchApiRef, createRoutableExtension, useRouteRef, alertApiRef, useApp } from '@backstage/core-plugin-api';
|
|
3
3
|
import { ResponseError } from '@backstage/errors';
|
|
4
4
|
import qs from 'qs';
|
|
5
5
|
import ObservableImpl from 'zen-observable';
|
|
6
|
-
import { catalogApiRef,
|
|
7
|
-
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';
|
|
8
8
|
import FormControl from '@material-ui/core/FormControl';
|
|
9
9
|
import Autocomplete from '@material-ui/lab/Autocomplete';
|
|
10
10
|
import React, { useCallback, useEffect, useState, createContext, useContext, useMemo, memo } from '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';
|
|
@@ -205,7 +203,7 @@ const EntityPicker = (props) => {
|
|
|
205
203
|
const defaultKind = (_b = uiSchema["ui:options"]) == null ? void 0 : _b.defaultKind;
|
|
206
204
|
const catalogApi = useApi(catalogApiRef);
|
|
207
205
|
const { value: entities, loading } = useAsync(() => catalogApi.getEntities(allowedKinds ? { filter: { kind: allowedKinds } } : void 0));
|
|
208
|
-
const entityRefs = entities == null ? void 0 : entities.items.map((e) =>
|
|
206
|
+
const entityRefs = entities == null ? void 0 : entities.items.map((e) => humanizeEntityRef(e, { defaultKind }));
|
|
209
207
|
const onSelect = useCallback((_, value) => {
|
|
210
208
|
onChange(value || "");
|
|
211
209
|
}, [onChange]);
|
|
@@ -587,11 +585,11 @@ const useTemplateSecrets = () => {
|
|
|
587
585
|
if (!value) {
|
|
588
586
|
throw new Error("useTemplateSecrets must be used within a SecretsContextProvider");
|
|
589
587
|
}
|
|
590
|
-
const { setSecrets } = value;
|
|
591
|
-
const
|
|
592
|
-
|
|
593
|
-
}, [
|
|
594
|
-
return { setSecret };
|
|
588
|
+
const { setSecrets: updateSecrets } = value;
|
|
589
|
+
const setSecrets = useCallback((input) => {
|
|
590
|
+
updateSecrets((currentSecrets) => ({ ...currentSecrets, ...input }));
|
|
591
|
+
}, [updateSecrets]);
|
|
592
|
+
return { setSecret: setSecrets, setSecrets };
|
|
595
593
|
};
|
|
596
594
|
|
|
597
595
|
const RepoUrlPicker = (props) => {
|
|
@@ -600,7 +598,7 @@ const RepoUrlPicker = (props) => {
|
|
|
600
598
|
const [state, setState] = useState(parseRepoPickerUrl(formData));
|
|
601
599
|
const integrationApi = useApi(scmIntegrationsApiRef);
|
|
602
600
|
const scmAuthApi = useApi(scmAuthApiRef);
|
|
603
|
-
const {
|
|
601
|
+
const { setSecrets } = useTemplateSecrets();
|
|
604
602
|
const allowedHosts = useMemo(() => {
|
|
605
603
|
var _a2, _b2;
|
|
606
604
|
return (_b2 = (_a2 = uiSchema == null ? void 0 : uiSchema["ui:options"]) == null ? void 0 : _a2.allowedHosts) != null ? _b2 : [];
|
|
@@ -638,7 +636,7 @@ const RepoUrlPicker = (props) => {
|
|
|
638
636
|
customScopes: requestUserCredentials.additionalScopes
|
|
639
637
|
}
|
|
640
638
|
});
|
|
641
|
-
|
|
639
|
+
setSecrets({ [requestUserCredentials.secretsKey]: token });
|
|
642
640
|
}, 500, [state, uiSchema]);
|
|
643
641
|
const hostType = (_b = state.host && ((_a = integrationApi.byHost(state.host)) == null ? void 0 : _a.type)) != null ? _b : null;
|
|
644
642
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(RepoUrlPickerHost, {
|
|
@@ -710,7 +708,7 @@ const OwnedEntityPicker = (props) => {
|
|
|
710
708
|
const allowedKinds = (_a = uiSchema["ui:options"]) == null ? void 0 : _a.allowedKinds;
|
|
711
709
|
const defaultKind = (_b = uiSchema["ui:options"]) == null ? void 0 : _b.defaultKind;
|
|
712
710
|
const { ownedEntities, loading } = useOwnedEntities(allowedKinds);
|
|
713
|
-
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);
|
|
714
712
|
const onSelect = (_, value) => {
|
|
715
713
|
onChange(value || "");
|
|
716
714
|
};
|
|
@@ -759,6 +757,21 @@ const registerComponentRouteRef = createExternalRouteRef({
|
|
|
759
757
|
const rootRouteRef = createRouteRef({
|
|
760
758
|
id: "scaffolder"
|
|
761
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
|
+
});
|
|
762
775
|
|
|
763
776
|
const scaffolderPlugin = createPlugin({
|
|
764
777
|
id: "scaffolder",
|
|
@@ -804,7 +817,7 @@ const OwnerPickerFieldExtension = scaffolderPlugin.provide(createScaffolderField
|
|
|
804
817
|
}));
|
|
805
818
|
const ScaffolderPage = scaffolderPlugin.provide(createRoutableExtension({
|
|
806
819
|
name: "ScaffolderPage",
|
|
807
|
-
component: () => import('./Router-
|
|
820
|
+
component: () => import('./Router-ba25f61c.esm.js').then((m) => m.Router),
|
|
808
821
|
mountPoint: rootRouteRef
|
|
809
822
|
}));
|
|
810
823
|
const OwnedEntityPickerFieldExtension = scaffolderPlugin.provide(createScaffolderFieldExtension({
|
|
@@ -816,39 +829,6 @@ const EntityTagsPickerFieldExtension = scaffolderPlugin.provide(createScaffolder
|
|
|
816
829
|
name: "EntityTagsPicker"
|
|
817
830
|
}));
|
|
818
831
|
|
|
819
|
-
const YellowStar = withStyles({
|
|
820
|
-
root: {
|
|
821
|
-
color: "#f3ba37"
|
|
822
|
-
}
|
|
823
|
-
})(Star);
|
|
824
|
-
const WhiteBorderStar = withStyles({
|
|
825
|
-
root: {
|
|
826
|
-
color: "#ffffff"
|
|
827
|
-
}
|
|
828
|
-
})(StarBorder);
|
|
829
|
-
const useStyles$3 = makeStyles((theme) => ({
|
|
830
|
-
starButton: {
|
|
831
|
-
position: "absolute",
|
|
832
|
-
top: theme.spacing(0.5),
|
|
833
|
-
right: theme.spacing(0.5),
|
|
834
|
-
padding: "0.25rem"
|
|
835
|
-
}
|
|
836
|
-
}));
|
|
837
|
-
const favouriteTemplateTooltip = (isStarred) => isStarred ? "Remove from favorites" : "Add to favorites";
|
|
838
|
-
const favouriteTemplateIcon = (isStarred) => isStarred ? /* @__PURE__ */ React.createElement(YellowStar, null) : /* @__PURE__ */ React.createElement(WhiteBorderStar, null);
|
|
839
|
-
const FavouriteTemplate = (props) => {
|
|
840
|
-
const classes = useStyles$3();
|
|
841
|
-
const { toggleStarredEntity, isStarredEntity } = useStarredEntity(props.entity);
|
|
842
|
-
return /* @__PURE__ */ React.createElement(IconButton, {
|
|
843
|
-
color: "inherit",
|
|
844
|
-
className: classes.starButton,
|
|
845
|
-
...props,
|
|
846
|
-
onClick: () => toggleStarredEntity()
|
|
847
|
-
}, /* @__PURE__ */ React.createElement(Tooltip, {
|
|
848
|
-
title: favouriteTemplateTooltip(isStarredEntity)
|
|
849
|
-
}, favouriteTemplateIcon(isStarredEntity)));
|
|
850
|
-
};
|
|
851
|
-
|
|
852
832
|
const useStyles$2 = makeStyles((theme) => ({
|
|
853
833
|
cardHeader: {
|
|
854
834
|
position: "relative"
|
|
@@ -875,6 +855,12 @@ const useStyles$2 = makeStyles((theme) => ({
|
|
|
875
855
|
},
|
|
876
856
|
leftButton: {
|
|
877
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"
|
|
878
864
|
}
|
|
879
865
|
}));
|
|
880
866
|
const useDeprecationStyles = makeStyles((theme) => ({
|
|
@@ -916,20 +902,19 @@ const DeprecationWarning = () => {
|
|
|
916
902
|
const TemplateCard = ({ template, deprecated }) => {
|
|
917
903
|
var _a;
|
|
918
904
|
const backstageTheme = useTheme();
|
|
919
|
-
const
|
|
905
|
+
const templateRoute = useRouteRef(selectedTemplateRouteRef);
|
|
920
906
|
const templateProps = getTemplateCardProps(template);
|
|
921
907
|
const ownedByRelations = getEntityRelations(template, RELATION_OWNED_BY);
|
|
922
908
|
const themeId = backstageTheme.getPageTheme({ themeId: templateProps.type }) ? templateProps.type : "other";
|
|
923
909
|
const theme = backstageTheme.getPageTheme({ themeId });
|
|
924
910
|
const classes = useStyles$2({ backgroundImage: theme.backgroundImage });
|
|
925
|
-
const href =
|
|
926
|
-
templateName: templateProps.name
|
|
927
|
-
});
|
|
911
|
+
const href = templateRoute({ templateName: templateProps.name });
|
|
928
912
|
const scmIntegrationsApi = useApi(scmIntegrationsApiRef);
|
|
929
913
|
const sourceLocation = getEntitySourceLocation(template, scmIntegrationsApi);
|
|
930
914
|
return /* @__PURE__ */ React.createElement(Card, null, /* @__PURE__ */ React.createElement(CardMedia, {
|
|
931
915
|
className: classes.cardHeader
|
|
932
|
-
}, /* @__PURE__ */ React.createElement(
|
|
916
|
+
}, /* @__PURE__ */ React.createElement(FavoriteEntity, {
|
|
917
|
+
className: classes.starButton,
|
|
933
918
|
entity: template
|
|
934
919
|
}), deprecated && /* @__PURE__ */ React.createElement(DeprecationWarning, null), /* @__PURE__ */ React.createElement(ItemCardHeader, {
|
|
935
920
|
title: templateProps.title,
|
|
@@ -976,11 +961,23 @@ const TemplateList = ({
|
|
|
976
961
|
const { loading, error, entities } = useEntityList();
|
|
977
962
|
const Card = TemplateCardComponent || TemplateCard;
|
|
978
963
|
const maybeFilteredEntities = group ? entities.filter((e) => group.filter(e)) : entities;
|
|
979
|
-
const
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
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
|
+
})();
|
|
984
981
|
if (group && maybeFilteredEntities.length === 0) {
|
|
985
982
|
return null;
|
|
986
983
|
}
|
|
@@ -990,7 +987,7 @@ const TemplateList = ({
|
|
|
990
987
|
variant: "body2"
|
|
991
988
|
}, "No templates found that match your filter. Learn more about", " ", /* @__PURE__ */ React.createElement(Link$1, {
|
|
992
989
|
to: "https://backstage.io/docs/features/software-templates/adding-templates"
|
|
993
|
-
}, "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, {
|
|
994
991
|
key: stringifyEntityRef(template),
|
|
995
992
|
template,
|
|
996
993
|
deprecated: template.apiVersion === "backstage.io/v1beta2"
|
|
@@ -1363,7 +1360,8 @@ const hasLinks = ({
|
|
|
1363
1360
|
const TaskPage = ({ loadingText }) => {
|
|
1364
1361
|
const classes = useStyles();
|
|
1365
1362
|
const navigate = useNavigate();
|
|
1366
|
-
const
|
|
1363
|
+
const rootPath = useRouteRef(rootRouteRef);
|
|
1364
|
+
const templateRoute = useRouteRef(selectedTemplateRouteRef);
|
|
1367
1365
|
const [userSelectedStepId, setUserSelectedStepId] = useState(void 0);
|
|
1368
1366
|
const [lastActiveStepId, setLastActiveStepId] = useState(void 0);
|
|
1369
1367
|
const { taskId } = useParams();
|
|
@@ -1404,16 +1402,14 @@ const TaskPage = ({ loadingText }) => {
|
|
|
1404
1402
|
const handleStartOver = () => {
|
|
1405
1403
|
var _a, _b, _c;
|
|
1406
1404
|
if (!taskStream.task || !((_b = (_a = taskStream.task) == null ? void 0 : _a.spec.templateInfo) == null ? void 0 : _b.entityRef)) {
|
|
1407
|
-
navigate(
|
|
1405
|
+
navigate(rootPath());
|
|
1408
1406
|
return;
|
|
1409
1407
|
}
|
|
1410
1408
|
const formData = taskStream.task.spec.apiVersion === "backstage.io/v1beta2" ? taskStream.task.spec.values : taskStream.task.spec.parameters;
|
|
1411
1409
|
const { name } = parseEntityRef((_c = taskStream.task.spec.templateInfo) == null ? void 0 : _c.entityRef);
|
|
1412
|
-
navigate(
|
|
1410
|
+
navigate(`${templateRoute({ templateName: name })}?${qs.stringify({
|
|
1413
1411
|
formData: JSON.stringify(formData)
|
|
1414
|
-
})}
|
|
1415
|
-
templateName: name
|
|
1416
|
-
}));
|
|
1412
|
+
})}`);
|
|
1417
1413
|
};
|
|
1418
1414
|
return /* @__PURE__ */ React.createElement(Page, {
|
|
1419
1415
|
themeId: "home"
|
|
@@ -1455,5 +1451,5 @@ const TaskPage = ({ loadingText }) => {
|
|
|
1455
1451
|
})))))));
|
|
1456
1452
|
};
|
|
1457
1453
|
|
|
1458
|
-
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,
|
|
1459
|
-
//# 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
|