@backstage/plugin-scaffolder-react 1.8.4-next.1 → 1.8.5-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.
Files changed (94) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/alpha/package.json +1 -1
  3. package/dist/alpha.esm.js +19 -1451
  4. package/dist/alpha.esm.js.map +1 -1
  5. package/dist/api/ref.esm.js +12 -0
  6. package/dist/api/ref.esm.js.map +1 -0
  7. package/dist/extensions/index.esm.js +25 -0
  8. package/dist/extensions/index.esm.js.map +1 -0
  9. package/dist/extensions/keys.esm.js +5 -0
  10. package/dist/extensions/keys.esm.js.map +1 -0
  11. package/dist/hooks/useCustomFieldExtensions.esm.js +16 -0
  12. package/dist/hooks/useCustomFieldExtensions.esm.js.map +1 -0
  13. package/dist/hooks/useCustomLayouts.esm.js +16 -0
  14. package/dist/hooks/useCustomLayouts.esm.js.map +1 -0
  15. package/dist/hooks/useEventStream.esm.js +167 -0
  16. package/dist/hooks/useEventStream.esm.js.map +1 -0
  17. package/dist/index.esm.js +7 -228
  18. package/dist/index.esm.js.map +1 -1
  19. package/dist/layouts/createScaffolderLayout.esm.js +17 -0
  20. package/dist/layouts/createScaffolderLayout.esm.js.map +1 -0
  21. package/dist/layouts/keys.esm.js +5 -0
  22. package/dist/layouts/keys.esm.js.map +1 -0
  23. package/dist/next/components/Form/DescriptionFieldTemplate.esm.js +37 -0
  24. package/dist/next/components/Form/DescriptionFieldTemplate.esm.js.map +1 -0
  25. package/dist/next/components/Form/FieldTemplate.esm.js +65 -0
  26. package/dist/next/components/Form/FieldTemplate.esm.js.map +1 -0
  27. package/dist/next/components/Form/Form.esm.js +44 -0
  28. package/dist/next/components/Form/Form.esm.js.map +1 -0
  29. package/dist/next/components/ReviewState/ReviewState.esm.js +43 -0
  30. package/dist/next/components/ReviewState/ReviewState.esm.js.map +1 -0
  31. package/dist/next/components/ScaffolderField/ScaffolderField.esm.js +52 -0
  32. package/dist/next/components/ScaffolderField/ScaffolderField.esm.js.map +1 -0
  33. package/dist/next/components/ScaffolderPageContextMenu/ScaffolderPageContextMenu.esm.js +63 -0
  34. package/dist/next/components/ScaffolderPageContextMenu/ScaffolderPageContextMenu.esm.js.map +1 -0
  35. package/dist/next/components/Stepper/ErrorListTemplate/errorListTemplate.esm.js +32 -0
  36. package/dist/next/components/Stepper/ErrorListTemplate/errorListTemplate.esm.js.map +1 -0
  37. package/dist/next/components/Stepper/FieldOverrides/DescriptionField.esm.js +7 -0
  38. package/dist/next/components/Stepper/FieldOverrides/DescriptionField.esm.js.map +1 -0
  39. package/dist/next/components/Stepper/FieldOverrides/index.esm.js +2 -0
  40. package/dist/next/components/Stepper/FieldOverrides/index.esm.js.map +1 -0
  41. package/dist/next/components/Stepper/Stepper.esm.js +203 -0
  42. package/dist/next/components/Stepper/Stepper.esm.js.map +1 -0
  43. package/dist/next/components/Stepper/createAsyncValidators.esm.js +80 -0
  44. package/dist/next/components/Stepper/createAsyncValidators.esm.js.map +1 -0
  45. package/dist/next/components/Stepper/utils.esm.js +27 -0
  46. package/dist/next/components/Stepper/utils.esm.js.map +1 -0
  47. package/dist/next/components/TaskLogStream/TaskLogStream.esm.js +23 -0
  48. package/dist/next/components/TaskLogStream/TaskLogStream.esm.js.map +1 -0
  49. package/dist/next/components/TaskSteps/StepIcon.esm.js +52 -0
  50. package/dist/next/components/TaskSteps/StepIcon.esm.js.map +1 -0
  51. package/dist/next/components/TaskSteps/StepTime.esm.js +36 -0
  52. package/dist/next/components/TaskSteps/StepTime.esm.js.map +1 -0
  53. package/dist/next/components/TaskSteps/TaskBorder.esm.js +29 -0
  54. package/dist/next/components/TaskSteps/TaskBorder.esm.js.map +1 -0
  55. package/dist/next/components/TaskSteps/TaskSteps.esm.js +54 -0
  56. package/dist/next/components/TaskSteps/TaskSteps.esm.js.map +1 -0
  57. package/dist/next/components/TemplateCard/CardHeader.esm.js +41 -0
  58. package/dist/next/components/TemplateCard/CardHeader.esm.js.map +1 -0
  59. package/dist/next/components/TemplateCard/CardLink.esm.js +17 -0
  60. package/dist/next/components/TemplateCard/CardLink.esm.js.map +1 -0
  61. package/dist/next/components/TemplateCard/TemplateCard.esm.js +114 -0
  62. package/dist/next/components/TemplateCard/TemplateCard.esm.js.map +1 -0
  63. package/dist/next/components/TemplateCategoryPicker/TemplateCategoryPicker.esm.js +80 -0
  64. package/dist/next/components/TemplateCategoryPicker/TemplateCategoryPicker.esm.js.map +1 -0
  65. package/dist/next/components/TemplateGroup/TemplateGroup.esm.js +30 -0
  66. package/dist/next/components/TemplateGroup/TemplateGroup.esm.js.map +1 -0
  67. package/dist/next/components/TemplateGroups/TemplateGroups.esm.js +52 -0
  68. package/dist/next/components/TemplateGroups/TemplateGroups.esm.js.map +1 -0
  69. package/dist/next/components/TemplateOutputs/DefaultTemplateOutputs.esm.js +51 -0
  70. package/dist/next/components/TemplateOutputs/DefaultTemplateOutputs.esm.js.map +1 -0
  71. package/dist/next/components/TemplateOutputs/LinkOutputs.esm.js +40 -0
  72. package/dist/next/components/TemplateOutputs/LinkOutputs.esm.js.map +1 -0
  73. package/dist/next/components/TemplateOutputs/TextOutputs.esm.js +39 -0
  74. package/dist/next/components/TemplateOutputs/TextOutputs.esm.js.map +1 -0
  75. package/dist/next/components/Workflow/Workflow.esm.js +83 -0
  76. package/dist/next/components/Workflow/Workflow.esm.js.map +1 -0
  77. package/dist/next/hooks/useFilteredSchemaProperties.esm.js +44 -0
  78. package/dist/next/hooks/useFilteredSchemaProperties.esm.js.map +1 -0
  79. package/dist/next/hooks/useFormDataFromQuery.esm.js +21 -0
  80. package/dist/next/hooks/useFormDataFromQuery.esm.js.map +1 -0
  81. package/dist/next/hooks/useTemplateParameterSchema.esm.js +19 -0
  82. package/dist/next/hooks/useTemplateParameterSchema.esm.js.map +1 -0
  83. package/dist/next/hooks/useTemplateSchema.esm.js +46 -0
  84. package/dist/next/hooks/useTemplateSchema.esm.js.map +1 -0
  85. package/dist/next/hooks/useTemplateTimeSaved.esm.js +25 -0
  86. package/dist/next/hooks/useTemplateTimeSaved.esm.js.map +1 -0
  87. package/dist/next/hooks/useTransformSchemaToProps.esm.js +24 -0
  88. package/dist/next/hooks/useTransformSchemaToProps.esm.js.map +1 -0
  89. package/dist/next/lib/schema.esm.js +108 -0
  90. package/dist/next/lib/schema.esm.js.map +1 -0
  91. package/dist/{esm/ref-NRtFlQHB.esm.js → secrets/SecretsContext.esm.js} +3 -11
  92. package/dist/secrets/SecretsContext.esm.js.map +1 -0
  93. package/package.json +20 -20
  94. package/dist/esm/ref-NRtFlQHB.esm.js.map +0 -1
@@ -0,0 +1,30 @@
1
+ import React from 'react';
2
+ import { Content, ItemCardGrid, ContentHeader } from '@backstage/core-components';
3
+ import { stringifyEntityRef } from '@backstage/catalog-model';
4
+ import { TemplateCard } from '../TemplateCard/TemplateCard.esm.js';
5
+
6
+ const TemplateGroup = (props) => {
7
+ const {
8
+ templates,
9
+ title,
10
+ components: { CardComponent } = {},
11
+ onSelected
12
+ } = props;
13
+ const titleComponent = typeof title === "string" ? /* @__PURE__ */ React.createElement(ContentHeader, { title }) : title;
14
+ if (templates.length === 0) {
15
+ return null;
16
+ }
17
+ const Card = CardComponent || TemplateCard;
18
+ return /* @__PURE__ */ React.createElement(Content, null, titleComponent, /* @__PURE__ */ React.createElement(ItemCardGrid, null, templates.map(({ template, additionalLinks }) => /* @__PURE__ */ React.createElement(
19
+ Card,
20
+ {
21
+ key: stringifyEntityRef(template),
22
+ additionalLinks,
23
+ template,
24
+ onSelected
25
+ }
26
+ ))));
27
+ };
28
+
29
+ export { TemplateGroup };
30
+ //# sourceMappingURL=TemplateGroup.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TemplateGroup.esm.js","sources":["../../../../src/next/components/TemplateGroup/TemplateGroup.tsx"],"sourcesContent":["/*\n * Copyright 2022 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 { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common';\nimport React from 'react';\nimport {\n Content,\n ContentHeader,\n ItemCardGrid,\n} from '@backstage/core-components';\nimport { stringifyEntityRef } from '@backstage/catalog-model';\nimport { TemplateCardProps, TemplateCard } from '../TemplateCard';\nimport { IconComponent } from '@backstage/core-plugin-api';\n\n/**\n * The props for the {@link TemplateGroup} component.\n * @alpha\n */\nexport interface TemplateGroupProps {\n templates: {\n template: TemplateEntityV1beta3;\n additionalLinks?: {\n icon: IconComponent;\n text: string;\n url: string;\n }[];\n }[];\n onSelected: (template: TemplateEntityV1beta3) => void;\n title: React.ReactNode;\n components?: {\n CardComponent?: React.ComponentType<TemplateCardProps>;\n };\n}\n\n/**\n * The `TemplateGroup` component is used to display a group of templates with a title.\n * @alpha\n */\nexport const TemplateGroup = (props: TemplateGroupProps) => {\n const {\n templates,\n title,\n components: { CardComponent } = {},\n onSelected,\n } = props;\n const titleComponent =\n typeof title === 'string' ? <ContentHeader title={title} /> : title;\n\n if (templates.length === 0) {\n return null;\n }\n\n const Card = CardComponent || TemplateCard;\n\n return (\n <Content>\n {titleComponent}\n <ItemCardGrid>\n {templates.map(({ template, additionalLinks }) => (\n <Card\n key={stringifyEntityRef(template)}\n additionalLinks={additionalLinks}\n template={template}\n onSelected={onSelected}\n />\n ))}\n </ItemCardGrid>\n </Content>\n );\n};\n"],"names":[],"mappings":";;;;;AAkDa,MAAA,aAAA,GAAgB,CAAC,KAA8B,KAAA;AAC1D,EAAM,MAAA;AAAA,IACJ,SAAA;AAAA,IACA,KAAA;AAAA,IACA,UAAY,EAAA,EAAE,aAAc,EAAA,GAAI,EAAC;AAAA,IACjC,UAAA;AAAA,GACE,GAAA,KAAA,CAAA;AACJ,EAAA,MAAM,iBACJ,OAAO,KAAA,KAAU,2BAAY,KAAA,CAAA,aAAA,CAAA,aAAA,EAAA,EAAc,OAAc,CAAK,GAAA,KAAA,CAAA;AAEhE,EAAI,IAAA,SAAA,CAAU,WAAW,CAAG,EAAA;AAC1B,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAEA,EAAA,MAAM,OAAO,aAAiB,IAAA,YAAA,CAAA;AAE9B,EACE,uBAAA,KAAA,CAAA,aAAA,CAAC,OACE,EAAA,IAAA,EAAA,cAAA,kBACA,KAAA,CAAA,aAAA,CAAA,YAAA,EAAA,IAAA,EACE,SAAU,CAAA,GAAA,CAAI,CAAC,EAAE,QAAU,EAAA,eAAA,EAC1B,qBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,IAAA;AAAA,IAAA;AAAA,MACC,GAAA,EAAK,mBAAmB,QAAQ,CAAA;AAAA,MAChC,eAAA;AAAA,MACA,QAAA;AAAA,MACA,UAAA;AAAA,KAAA;AAAA,GAEH,CACH,CACF,CAAA,CAAA;AAEJ;;;;"}
@@ -0,0 +1,52 @@
1
+ import React, { useCallback } from 'react';
2
+ import { useEntityList } from '@backstage/plugin-catalog-react';
3
+ import { isTemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common';
4
+ import { Progress, Link } from '@backstage/core-components';
5
+ import Typography from '@material-ui/core/Typography';
6
+ import { useApi, errorApiRef } from '@backstage/core-plugin-api';
7
+ import { TemplateGroup } from '../TemplateGroup/TemplateGroup.esm.js';
8
+
9
+ const TemplateGroups = (props) => {
10
+ const { loading, error, entities } = useEntityList();
11
+ const { groups, templateFilter, TemplateCardComponent, onTemplateSelected } = props;
12
+ const errorApi = useApi(errorApiRef);
13
+ const onSelected = useCallback(
14
+ (template) => {
15
+ onTemplateSelected == null ? void 0 : onTemplateSelected(template);
16
+ },
17
+ [onTemplateSelected]
18
+ );
19
+ if (loading) {
20
+ return /* @__PURE__ */ React.createElement(Progress, null);
21
+ }
22
+ if (error) {
23
+ errorApi.post(error);
24
+ return null;
25
+ }
26
+ if (!entities || !entities.length) {
27
+ return /* @__PURE__ */ React.createElement(Typography, { variant: "body2" }, "No templates found that match your filter. Learn more about", " ", /* @__PURE__ */ React.createElement(Link, { to: "https://backstage.io/docs/features/software-templates/adding-templates" }, "adding templates"), ".");
28
+ }
29
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, groups.map(({ title, filter }, index) => {
30
+ const templates = entities.filter(isTemplateEntityV1beta3).filter((e) => templateFilter ? templateFilter(e) : true).filter(filter).map((template) => {
31
+ var _a, _b;
32
+ const additionalLinks = (_b = (_a = props.additionalLinksForEntity) == null ? void 0 : _a.call(props, template)) != null ? _b : [];
33
+ return {
34
+ template,
35
+ additionalLinks
36
+ };
37
+ });
38
+ return /* @__PURE__ */ React.createElement(
39
+ TemplateGroup,
40
+ {
41
+ key: index,
42
+ templates,
43
+ title,
44
+ components: { CardComponent: TemplateCardComponent },
45
+ onSelected
46
+ }
47
+ );
48
+ }));
49
+ };
50
+
51
+ export { TemplateGroups };
52
+ //# sourceMappingURL=TemplateGroups.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TemplateGroups.esm.js","sources":["../../../../src/next/components/TemplateGroups/TemplateGroups.tsx"],"sourcesContent":["/*\n * Copyright 2022 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, { useCallback } from 'react';\n\nimport { useEntityList } from '@backstage/plugin-catalog-react';\nimport {\n isTemplateEntityV1beta3,\n TemplateEntityV1beta3,\n} from '@backstage/plugin-scaffolder-common';\nimport { Progress, Link } from '@backstage/core-components';\nimport Typography from '@material-ui/core/Typography';\nimport { errorApiRef, IconComponent, useApi } from '@backstage/core-plugin-api';\nimport { TemplateGroupFilter } from '@backstage/plugin-scaffolder-react';\nimport { TemplateGroup } from '../TemplateGroup/TemplateGroup';\n\n/**\n * @alpha\n */\nexport interface TemplateGroupsProps {\n groups: TemplateGroupFilter[];\n templateFilter?: (entity: TemplateEntityV1beta3) => boolean;\n TemplateCardComponent?: React.ComponentType<{\n template: TemplateEntityV1beta3;\n }>;\n onTemplateSelected?: (template: TemplateEntityV1beta3) => void;\n additionalLinksForEntity?: (template: TemplateEntityV1beta3) => {\n icon: IconComponent;\n text: string;\n url: string;\n }[];\n}\n\n/**\n * @alpha\n */\nexport const TemplateGroups = (props: TemplateGroupsProps) => {\n const { loading, error, entities } = useEntityList();\n const { groups, templateFilter, TemplateCardComponent, onTemplateSelected } =\n props;\n const errorApi = useApi(errorApiRef);\n const onSelected = useCallback(\n (template: TemplateEntityV1beta3) => {\n onTemplateSelected?.(template);\n },\n [onTemplateSelected],\n );\n\n if (loading) {\n return <Progress />;\n }\n\n if (error) {\n errorApi.post(error);\n return null;\n }\n\n if (!entities || !entities.length) {\n return (\n <Typography variant=\"body2\">\n No templates found that match your filter. Learn more about{' '}\n <Link to=\"https://backstage.io/docs/features/software-templates/adding-templates\">\n adding templates\n </Link>\n .\n </Typography>\n );\n }\n\n return (\n <>\n {groups.map(({ title, filter }, index) => {\n const templates = entities\n .filter(isTemplateEntityV1beta3)\n .filter(e => (templateFilter ? templateFilter(e) : true))\n .filter(filter)\n .map(template => {\n const additionalLinks =\n props.additionalLinksForEntity?.(template) ?? [];\n\n return {\n template,\n additionalLinks,\n };\n });\n\n return (\n <TemplateGroup\n key={index}\n templates={templates}\n title={title}\n components={{ CardComponent: TemplateCardComponent }}\n onSelected={onSelected}\n />\n );\n })}\n </>\n );\n};\n"],"names":[],"mappings":";;;;;;;;AAgDa,MAAA,cAAA,GAAiB,CAAC,KAA+B,KAAA;AAC5D,EAAA,MAAM,EAAE,OAAA,EAAS,KAAO,EAAA,QAAA,KAAa,aAAc,EAAA,CAAA;AACnD,EAAA,MAAM,EAAE,MAAA,EAAQ,cAAgB,EAAA,qBAAA,EAAuB,oBACrD,GAAA,KAAA,CAAA;AACF,EAAM,MAAA,QAAA,GAAW,OAAO,WAAW,CAAA,CAAA;AACnC,EAAA,MAAM,UAAa,GAAA,WAAA;AAAA,IACjB,CAAC,QAAoC,KAAA;AACnC,MAAqB,kBAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,kBAAA,CAAA,QAAA,CAAA,CAAA;AAAA,KACvB;AAAA,IACA,CAAC,kBAAkB,CAAA;AAAA,GACrB,CAAA;AAEA,EAAA,IAAI,OAAS,EAAA;AACX,IAAA,2CAAQ,QAAS,EAAA,IAAA,CAAA,CAAA;AAAA,GACnB;AAEA,EAAA,IAAI,KAAO,EAAA;AACT,IAAA,QAAA,CAAS,KAAK,KAAK,CAAA,CAAA;AACnB,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAEA,EAAA,IAAI,CAAC,QAAA,IAAY,CAAC,QAAA,CAAS,MAAQ,EAAA;AACjC,IAAA,uBACG,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,OAAQ,EAAA,OAAA,EAAA,EAAQ,6DACkC,EAAA,GAAA,kBAC3D,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,EAAK,EAAG,EAAA,wEAAA,EAAA,EAAyE,kBAElF,CAAA,EAAO,GAET,CAAA,CAAA;AAAA,GAEJ;AAEA,EACE,uBAAA,KAAA,CAAA,aAAA,CAAA,KAAA,CAAA,QAAA,EAAA,IAAA,EACG,OAAO,GAAI,CAAA,CAAC,EAAE,KAAO,EAAA,MAAA,IAAU,KAAU,KAAA;AACxC,IAAA,MAAM,YAAY,QACf,CAAA,MAAA,CAAO,uBAAuB,CAAA,CAC9B,OAAO,CAAM,CAAA,KAAA,cAAA,GAAiB,cAAe,CAAA,CAAC,IAAI,IAAK,CAAA,CACvD,OAAO,MAAM,CAAA,CACb,IAAI,CAAY,QAAA,KAAA;AAxF3B,MAAA,IAAA,EAAA,EAAA,EAAA,CAAA;AAyFY,MAAA,MAAM,mBACJ,EAAM,GAAA,CAAA,EAAA,GAAA,KAAA,CAAA,wBAAA,KAAN,IAAiC,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,IAAA,CAAA,KAAA,EAAA,QAAA,CAAA,KAAjC,YAA8C,EAAC,CAAA;AAEjD,MAAO,OAAA;AAAA,QACL,QAAA;AAAA,QACA,eAAA;AAAA,OACF,CAAA;AAAA,KACD,CAAA,CAAA;AAEH,IACE,uBAAA,KAAA,CAAA,aAAA;AAAA,MAAC,aAAA;AAAA,MAAA;AAAA,QACC,GAAK,EAAA,KAAA;AAAA,QACL,SAAA;AAAA,QACA,KAAA;AAAA,QACA,UAAA,EAAY,EAAE,aAAA,EAAe,qBAAsB,EAAA;AAAA,QACnD,UAAA;AAAA,OAAA;AAAA,KACF,CAAA;AAAA,GAEH,CACH,CAAA,CAAA;AAEJ;;;;"}
@@ -0,0 +1,51 @@
1
+ import { InfoCard, MarkdownContent } from '@backstage/core-components';
2
+ import Box from '@material-ui/core/Box';
3
+ import Paper from '@material-ui/core/Paper';
4
+ import React, { useState, useEffect, useMemo } from 'react';
5
+ import { LinkOutputs } from './LinkOutputs.esm.js';
6
+ import { TextOutputs } from './TextOutputs.esm.js';
7
+
8
+ const DefaultTemplateOutputs = (props) => {
9
+ var _a, _b;
10
+ const { output } = props;
11
+ const [textOutputIndex, setTextOutputIndex] = useState(
12
+ void 0
13
+ );
14
+ useEffect(() => {
15
+ if (textOutputIndex === void 0 && (output == null ? void 0 : output.text)) {
16
+ const defaultIndex = output.text.findIndex(
17
+ (t) => t.default
18
+ );
19
+ setTextOutputIndex(defaultIndex >= 0 ? defaultIndex : 0);
20
+ }
21
+ }, [textOutputIndex, output]);
22
+ const textOutput = useMemo(
23
+ () => {
24
+ var _a2;
25
+ return textOutputIndex !== void 0 ? (_a2 = output == null ? void 0 : output.text) == null ? void 0 : _a2[textOutputIndex] : null;
26
+ },
27
+ [output, textOutputIndex]
28
+ );
29
+ if (!output) {
30
+ return null;
31
+ }
32
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Box, { paddingBottom: 2 }, /* @__PURE__ */ React.createElement(Paper, null, /* @__PURE__ */ React.createElement(Box, { padding: 2, justifyContent: "center", display: "flex", gridGap: 16 }, /* @__PURE__ */ React.createElement(
33
+ TextOutputs,
34
+ {
35
+ output,
36
+ index: textOutputIndex,
37
+ setIndex: setTextOutputIndex
38
+ }
39
+ ), /* @__PURE__ */ React.createElement(LinkOutputs, { output })))), textOutput ? /* @__PURE__ */ React.createElement(Box, { paddingBottom: 2 }, /* @__PURE__ */ React.createElement(
40
+ InfoCard,
41
+ {
42
+ title: (_a = textOutput.title) != null ? _a : "Text Output",
43
+ noPadding: true,
44
+ titleTypographyProps: { component: "h2" }
45
+ },
46
+ /* @__PURE__ */ React.createElement(Box, { padding: 2, height: "100%" }, /* @__PURE__ */ React.createElement(MarkdownContent, { content: (_b = textOutput.content) != null ? _b : "" }))
47
+ )) : null);
48
+ };
49
+
50
+ export { DefaultTemplateOutputs };
51
+ //# sourceMappingURL=DefaultTemplateOutputs.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DefaultTemplateOutputs.esm.js","sources":["../../../../src/next/components/TemplateOutputs/DefaultTemplateOutputs.tsx"],"sourcesContent":["/*\n * Copyright 2023 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 { InfoCard, MarkdownContent } from '@backstage/core-components';\nimport {\n ScaffolderOutputText,\n ScaffolderTaskOutput,\n} from '@backstage/plugin-scaffolder-react';\nimport Box from '@material-ui/core/Box';\nimport Paper from '@material-ui/core/Paper';\nimport React, { useEffect, useMemo, useState } from 'react';\nimport { LinkOutputs } from './LinkOutputs';\nimport { TextOutputs } from './TextOutputs';\n\n/**\n * The DefaultOutputs renderer for the scaffolder task output\n *\n * @alpha\n */\nexport const DefaultTemplateOutputs = (props: {\n output?: ScaffolderTaskOutput;\n}) => {\n const { output } = props;\n const [textOutputIndex, setTextOutputIndex] = useState<number | undefined>(\n undefined,\n );\n\n useEffect(() => {\n if (textOutputIndex === undefined && output?.text) {\n const defaultIndex = output.text.findIndex(\n (t: ScaffolderOutputText) => t.default,\n );\n setTextOutputIndex(defaultIndex >= 0 ? defaultIndex : 0);\n }\n }, [textOutputIndex, output]);\n\n const textOutput = useMemo(\n () =>\n textOutputIndex !== undefined ? output?.text?.[textOutputIndex] : null,\n [output, textOutputIndex],\n );\n\n if (!output) {\n return null;\n }\n\n return (\n <>\n <Box paddingBottom={2}>\n <Paper>\n <Box padding={2} justifyContent=\"center\" display=\"flex\" gridGap={16}>\n <TextOutputs\n output={output}\n index={textOutputIndex}\n setIndex={setTextOutputIndex}\n />\n <LinkOutputs output={output} />\n </Box>\n </Paper>\n </Box>\n {textOutput ? (\n <Box paddingBottom={2}>\n <InfoCard\n title={textOutput.title ?? 'Text Output'}\n noPadding\n titleTypographyProps={{ component: 'h2' }}\n >\n <Box padding={2} height=\"100%\">\n <MarkdownContent content={textOutput.content ?? ''} />\n </Box>\n </InfoCard>\n </Box>\n ) : null}\n </>\n );\n};\n"],"names":["_a"],"mappings":";;;;;;;AA+Ba,MAAA,sBAAA,GAAyB,CAAC,KAEjC,KAAA;AAjCN,EAAA,IAAA,EAAA,EAAA,EAAA,CAAA;AAkCE,EAAM,MAAA,EAAE,QAAW,GAAA,KAAA,CAAA;AACnB,EAAM,MAAA,CAAC,eAAiB,EAAA,kBAAkB,CAAI,GAAA,QAAA;AAAA,IAC5C,KAAA,CAAA;AAAA,GACF,CAAA;AAEA,EAAA,SAAA,CAAU,MAAM;AACd,IAAI,IAAA,eAAA,KAAoB,KAAa,CAAA,KAAA,MAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,MAAA,CAAQ,IAAM,CAAA,EAAA;AACjD,MAAM,MAAA,YAAA,GAAe,OAAO,IAAK,CAAA,SAAA;AAAA,QAC/B,CAAC,MAA4B,CAAE,CAAA,OAAA;AAAA,OACjC,CAAA;AACA,MAAmB,kBAAA,CAAA,YAAA,IAAgB,CAAI,GAAA,YAAA,GAAe,CAAC,CAAA,CAAA;AAAA,KACzD;AAAA,GACC,EAAA,CAAC,eAAiB,EAAA,MAAM,CAAC,CAAA,CAAA;AAE5B,EAAA,MAAM,UAAa,GAAA,OAAA;AAAA,IACjB,MAAG;AAjDP,MAAAA,IAAAA,GAAAA,CAAAA;AAkDM,MAAA,OAAA,eAAA,KAAoB,UAAYA,GAAA,GAAA,MAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,MAAA,CAAQ,IAAR,KAAA,IAAA,GAAA,KAAA,CAAA,GAAAA,IAAe,eAAmB,CAAA,GAAA,IAAA,CAAA;AAAA,KAAA;AAAA,IACpE,CAAC,QAAQ,eAAe,CAAA;AAAA,GAC1B,CAAA;AAEA,EAAA,IAAI,CAAC,MAAQ,EAAA;AACX,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAEA,EAAA,iFAEK,KAAA,CAAA,aAAA,CAAA,GAAA,EAAA,EAAI,aAAe,EAAA,CAAA,EAAA,sCACjB,KACC,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,GAAI,EAAA,EAAA,OAAA,EAAS,GAAG,cAAe,EAAA,QAAA,EAAS,OAAQ,EAAA,MAAA,EAAO,SAAS,EAC/D,EAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,WAAA;AAAA,IAAA;AAAA,MACC,MAAA;AAAA,MACA,KAAO,EAAA,eAAA;AAAA,MACP,QAAU,EAAA,kBAAA;AAAA,KAAA;AAAA,GAEZ,kBAAA,KAAA,CAAA,aAAA,CAAC,WAAY,EAAA,EAAA,MAAA,EAAgB,CAC/B,CACF,CACF,CAAA,EACC,UACC,mBAAA,KAAA,CAAA,aAAA,CAAC,GAAI,EAAA,EAAA,aAAA,EAAe,CAClB,EAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAA,CAAO,EAAW,GAAA,UAAA,CAAA,KAAA,KAAX,IAAoB,GAAA,EAAA,GAAA,aAAA;AAAA,MAC3B,SAAS,EAAA,IAAA;AAAA,MACT,oBAAA,EAAsB,EAAE,SAAA,EAAW,IAAK,EAAA;AAAA,KAAA;AAAA,oBAEvC,KAAA,CAAA,aAAA,CAAA,GAAA,EAAA,EAAI,OAAS,EAAA,CAAA,EAAG,MAAO,EAAA,MAAA,EAAA,kBACrB,KAAA,CAAA,aAAA,CAAA,eAAA,EAAA,EAAgB,OAAS,EAAA,CAAA,EAAA,GAAA,UAAA,CAAW,OAAX,KAAA,IAAA,GAAA,EAAA,GAAsB,IAAI,CACtD,CAAA;AAAA,GAEJ,IACE,IACN,CAAA,CAAA;AAEJ;;;;"}
@@ -0,0 +1,40 @@
1
+ import { useApp, useRouteRef } from '@backstage/core-plugin-api';
2
+ import { entityRouteRef } from '@backstage/plugin-catalog-react';
3
+ import Button from '@material-ui/core/Button';
4
+ import { makeStyles } from '@material-ui/core/styles';
5
+ import React from 'react';
6
+ import LinkIcon from '@material-ui/icons/Link';
7
+ import { parseEntityRef } from '@backstage/catalog-model';
8
+ import { Link } from '@backstage/core-components';
9
+
10
+ const useStyles = makeStyles({
11
+ root: {
12
+ "&:hover": {
13
+ textDecoration: "none"
14
+ }
15
+ }
16
+ });
17
+ const LinkOutputs = (props) => {
18
+ const { links = [] } = props.output;
19
+ const classes = useStyles();
20
+ const app = useApp();
21
+ const entityRoute = useRouteRef(entityRouteRef);
22
+ const iconResolver = (key) => {
23
+ var _a;
24
+ return (_a = app.getSystemIcon(key)) != null ? _a : LinkIcon;
25
+ };
26
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, links.filter(({ url, entityRef }) => url || entityRef).map(({ url, entityRef, title, icon }) => {
27
+ if (entityRef) {
28
+ const entityName = parseEntityRef(entityRef);
29
+ const target = entityRoute(entityName);
30
+ return { title, icon, url: target };
31
+ }
32
+ return { title, icon, url };
33
+ }).map(({ url, title, icon }, i) => {
34
+ const Icon = iconResolver(icon);
35
+ return /* @__PURE__ */ React.createElement(Link, { to: url, key: i, classes: { root: classes.root } }, /* @__PURE__ */ React.createElement(Button, { startIcon: /* @__PURE__ */ React.createElement(Icon, null), component: "div", color: "primary" }, title));
36
+ }));
37
+ };
38
+
39
+ export { LinkOutputs };
40
+ //# sourceMappingURL=LinkOutputs.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LinkOutputs.esm.js","sources":["../../../../src/next/components/TemplateOutputs/LinkOutputs.tsx"],"sourcesContent":["/*\n * Copyright 2023 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 { IconComponent, useApp, useRouteRef } from '@backstage/core-plugin-api';\nimport { entityRouteRef } from '@backstage/plugin-catalog-react';\nimport Button from '@material-ui/core/Button';\nimport { makeStyles } from '@material-ui/core/styles';\nimport React from 'react';\nimport LinkIcon from '@material-ui/icons/Link';\nimport { parseEntityRef } from '@backstage/catalog-model';\nimport { Link } from '@backstage/core-components';\nimport { ScaffolderTaskOutput } from '../../../api';\n\nconst useStyles = makeStyles({\n root: {\n '&:hover': {\n textDecoration: 'none',\n },\n },\n});\n\nexport const LinkOutputs = (props: { output: ScaffolderTaskOutput }) => {\n const { links = [] } = props.output;\n const classes = useStyles();\n const app = useApp();\n const entityRoute = useRouteRef(entityRouteRef);\n\n const iconResolver = (key?: string): IconComponent =>\n app.getSystemIcon(key!) ?? LinkIcon;\n\n return (\n <>\n {links\n .filter(({ url, entityRef }) => url || entityRef)\n .map(({ url, entityRef, title, icon }) => {\n if (entityRef) {\n const entityName = parseEntityRef(entityRef);\n const target = entityRoute(entityName);\n return { title, icon, url: target };\n }\n return { title, icon, url: url! };\n })\n .map(({ url, title, icon }, i) => {\n const Icon = iconResolver(icon);\n return (\n <Link to={url} key={i} classes={{ root: classes.root }}>\n <Button startIcon={<Icon />} component=\"div\" color=\"primary\">\n {title}\n </Button>\n </Link>\n );\n })}\n </>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;AAyBA,MAAM,YAAY,UAAW,CAAA;AAAA,EAC3B,IAAM,EAAA;AAAA,IACJ,SAAW,EAAA;AAAA,MACT,cAAgB,EAAA,MAAA;AAAA,KAClB;AAAA,GACF;AACF,CAAC,CAAA,CAAA;AAEY,MAAA,WAAA,GAAc,CAAC,KAA4C,KAAA;AACtE,EAAA,MAAM,EAAE,KAAA,GAAQ,EAAC,KAAM,KAAM,CAAA,MAAA,CAAA;AAC7B,EAAA,MAAM,UAAU,SAAU,EAAA,CAAA;AAC1B,EAAA,MAAM,MAAM,MAAO,EAAA,CAAA;AACnB,EAAM,MAAA,WAAA,GAAc,YAAY,cAAc,CAAA,CAAA;AAE9C,EAAM,MAAA,YAAA,GAAe,CAAC,GAA6B,KAAA;AAvCrD,IAAA,IAAA,EAAA,CAAA;AAwCI,IAAI,OAAA,CAAA,EAAA,GAAA,GAAA,CAAA,aAAA,CAAc,GAAI,CAAA,KAAtB,IAA2B,GAAA,EAAA,GAAA,QAAA,CAAA;AAAA,GAAA,CAAA;AAE7B,EAAA,iEAEK,KACE,CAAA,MAAA,CAAO,CAAC,EAAE,GAAA,EAAK,WAAgB,KAAA,GAAA,IAAO,SAAS,CAAA,CAC/C,IAAI,CAAC,EAAE,KAAK,SAAW,EAAA,KAAA,EAAO,MAAW,KAAA;AACxC,IAAA,IAAI,SAAW,EAAA;AACb,MAAM,MAAA,UAAA,GAAa,eAAe,SAAS,CAAA,CAAA;AAC3C,MAAM,MAAA,MAAA,GAAS,YAAY,UAAU,CAAA,CAAA;AACrC,MAAA,OAAO,EAAE,KAAA,EAAO,IAAM,EAAA,GAAA,EAAK,MAAO,EAAA,CAAA;AAAA,KACpC;AACA,IAAO,OAAA,EAAE,KAAO,EAAA,IAAA,EAAM,GAAU,EAAA,CAAA;AAAA,GACjC,EACA,GAAI,CAAA,CAAC,EAAE,GAAK,EAAA,KAAA,EAAO,IAAK,EAAA,EAAG,CAAM,KAAA;AAChC,IAAM,MAAA,IAAA,GAAO,aAAa,IAAI,CAAA,CAAA;AAC9B,IACE,uBAAA,KAAA,CAAA,aAAA,CAAC,QAAK,EAAI,EAAA,GAAA,EAAK,KAAK,CAAG,EAAA,OAAA,EAAS,EAAE,IAAA,EAAM,OAAQ,CAAA,IAAA,sBAC7C,KAAA,CAAA,aAAA,CAAA,MAAA,EAAA,EAAO,SAAW,kBAAA,KAAA,CAAA,aAAA,CAAC,IAAK,EAAA,IAAA,CAAA,EAAI,WAAU,KAAM,EAAA,KAAA,EAAM,SAChD,EAAA,EAAA,KACH,CACF,CAAA,CAAA;AAAA,GAEH,CACL,CAAA,CAAA;AAEJ;;;;"}
@@ -0,0 +1,39 @@
1
+ import { useApp } from '@backstage/core-plugin-api';
2
+ import Button from '@material-ui/core/Button';
3
+ import DescriptionIcon from '@material-ui/icons/Description';
4
+ import React from 'react';
5
+
6
+ const TextOutputs = (props) => {
7
+ const {
8
+ output: { text = [] },
9
+ index,
10
+ setIndex
11
+ } = props;
12
+ const app = useApp();
13
+ const iconResolver = (key) => {
14
+ var _a;
15
+ return (_a = app.getSystemIcon(key)) != null ? _a : DescriptionIcon;
16
+ };
17
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, text.filter(({ content }) => content !== void 0).map(({ title, icon }, i) => {
18
+ const Icon = iconResolver(icon);
19
+ return /* @__PURE__ */ React.createElement(
20
+ Button,
21
+ {
22
+ key: i,
23
+ startIcon: /* @__PURE__ */ React.createElement(Icon, null),
24
+ component: "div",
25
+ color: "primary",
26
+ onClick: () => {
27
+ if (index !== i) {
28
+ setIndex == null ? void 0 : setIndex(i);
29
+ }
30
+ },
31
+ variant: index === i ? "outlined" : void 0
32
+ },
33
+ title
34
+ );
35
+ }));
36
+ };
37
+
38
+ export { TextOutputs };
39
+ //# sourceMappingURL=TextOutputs.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TextOutputs.esm.js","sources":["../../../../src/next/components/TemplateOutputs/TextOutputs.tsx"],"sourcesContent":["/*\n * Copyright 2023 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 { IconComponent, useApp } from '@backstage/core-plugin-api';\nimport Button from '@material-ui/core/Button';\nimport DescriptionIcon from '@material-ui/icons/Description';\nimport React from 'react';\nimport { ScaffolderTaskOutput } from '../../../api';\n\nexport const TextOutputs = (props: {\n output: ScaffolderTaskOutput;\n index?: number;\n setIndex?: (index: number | undefined) => void;\n}) => {\n const {\n output: { text = [] },\n index,\n setIndex,\n } = props;\n\n const app = useApp();\n\n const iconResolver = (key?: string): IconComponent =>\n app.getSystemIcon(key!) ?? DescriptionIcon;\n\n return (\n <>\n {text\n .filter(({ content }) => content !== undefined)\n .map(({ title, icon }, i) => {\n const Icon = iconResolver(icon);\n return (\n <Button\n key={i}\n startIcon={<Icon />}\n component=\"div\"\n color=\"primary\"\n onClick={() => {\n if (index !== i) {\n setIndex?.(i);\n }\n }}\n variant={index === i ? 'outlined' : undefined}\n >\n {title}\n </Button>\n );\n })}\n </>\n );\n};\n"],"names":[],"mappings":";;;;;AAqBa,MAAA,WAAA,GAAc,CAAC,KAItB,KAAA;AACJ,EAAM,MAAA;AAAA,IACJ,MAAQ,EAAA,EAAE,IAAO,GAAA,EAAG,EAAA;AAAA,IACpB,KAAA;AAAA,IACA,QAAA;AAAA,GACE,GAAA,KAAA,CAAA;AAEJ,EAAA,MAAM,MAAM,MAAO,EAAA,CAAA;AAEnB,EAAM,MAAA,YAAA,GAAe,CAAC,GAA6B,KAAA;AAlCrD,IAAA,IAAA,EAAA,CAAA;AAmCI,IAAI,OAAA,CAAA,EAAA,GAAA,GAAA,CAAA,aAAA,CAAc,GAAI,CAAA,KAAtB,IAA2B,GAAA,EAAA,GAAA,eAAA,CAAA;AAAA,GAAA,CAAA;AAE7B,EAAA,iEAEK,IACE,CAAA,MAAA,CAAO,CAAC,EAAE,SAAc,KAAA,OAAA,KAAY,KAAS,CAAA,CAAA,CAC7C,IAAI,CAAC,EAAE,KAAO,EAAA,IAAA,IAAQ,CAAM,KAAA;AAC3B,IAAM,MAAA,IAAA,GAAO,aAAa,IAAI,CAAA,CAAA;AAC9B,IACE,uBAAA,KAAA,CAAA,aAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,GAAK,EAAA,CAAA;AAAA,QACL,SAAA,sCAAY,IAAK,EAAA,IAAA,CAAA;AAAA,QACjB,SAAU,EAAA,KAAA;AAAA,QACV,KAAM,EAAA,SAAA;AAAA,QACN,SAAS,MAAM;AACb,UAAA,IAAI,UAAU,CAAG,EAAA;AACf,YAAW,QAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,QAAA,CAAA,CAAA,CAAA,CAAA;AAAA,WACb;AAAA,SACF;AAAA,QACA,OAAA,EAAS,KAAU,KAAA,CAAA,GAAI,UAAa,GAAA,KAAA,CAAA;AAAA,OAAA;AAAA,MAEnC,KAAA;AAAA,KACH,CAAA;AAAA,GAEH,CACL,CAAA,CAAA;AAEJ;;;;"}
@@ -0,0 +1,83 @@
1
+ import React, { useCallback, useEffect } from 'react';
2
+ import { Content, Progress, InfoCard, MarkdownContent } from '@backstage/core-components';
3
+ import { stringifyEntityRef } from '@backstage/catalog-model';
4
+ import { makeStyles } from '@material-ui/core/styles';
5
+ import { useAnalytics, useApi, errorApiRef } from '@backstage/core-plugin-api';
6
+ import { useTemplateParameterSchema } from '../../hooks/useTemplateParameterSchema.esm.js';
7
+ import { Stepper } from '../Stepper/Stepper.esm.js';
8
+ import { SecretsContextProvider } from '../../../secrets/SecretsContext.esm.js';
9
+ import { useFilteredSchemaProperties } from '../../hooks/useFilteredSchemaProperties.esm.js';
10
+ import { useTemplateTimeSavedMinutes } from '../../hooks/useTemplateTimeSaved.esm.js';
11
+
12
+ const useStyles = makeStyles({
13
+ markdown: {
14
+ /** to make the styles for React Markdown not leak into the description */
15
+ "& :first-child": {
16
+ marginTop: 0
17
+ },
18
+ "& :last-child": {
19
+ marginBottom: 0
20
+ }
21
+ }
22
+ });
23
+ const Workflow = (workflowProps) => {
24
+ var _a;
25
+ const { title, description, namespace, templateName, onCreate, ...props } = workflowProps;
26
+ const analytics = useAnalytics();
27
+ const styles = useStyles();
28
+ const templateRef = stringifyEntityRef({
29
+ kind: "Template",
30
+ namespace,
31
+ name: templateName
32
+ });
33
+ const errorApi = useApi(errorApiRef);
34
+ const { loading, manifest, error } = useTemplateParameterSchema(templateRef);
35
+ const sortedManifest = useFilteredSchemaProperties(manifest);
36
+ const minutesSaved = useTemplateTimeSavedMinutes(templateRef);
37
+ const workflowOnCreate = useCallback(
38
+ async (formState) => {
39
+ var _a2;
40
+ onCreate(formState);
41
+ const name = typeof formState.name === "string" ? formState.name : void 0;
42
+ analytics.captureEvent("create", (_a2 = name != null ? name : templateName) != null ? _a2 : "unknown", {
43
+ value: minutesSaved
44
+ });
45
+ },
46
+ [onCreate, analytics, templateName, minutesSaved]
47
+ );
48
+ useEffect(() => {
49
+ if (error) {
50
+ errorApi.post(new Error(`Failed to load template, ${error}`));
51
+ }
52
+ }, [error, errorApi]);
53
+ if (error) {
54
+ return props.onError(error);
55
+ }
56
+ return /* @__PURE__ */ React.createElement(Content, null, loading && /* @__PURE__ */ React.createElement(Progress, null), sortedManifest && /* @__PURE__ */ React.createElement(
57
+ InfoCard,
58
+ {
59
+ title: title != null ? title : sortedManifest.title,
60
+ subheader: /* @__PURE__ */ React.createElement(
61
+ MarkdownContent,
62
+ {
63
+ className: styles.markdown,
64
+ content: (_a = description != null ? description : sortedManifest.description) != null ? _a : "No description"
65
+ }
66
+ ),
67
+ noPadding: true,
68
+ titleTypographyProps: { component: "h2" }
69
+ },
70
+ /* @__PURE__ */ React.createElement(
71
+ Stepper,
72
+ {
73
+ manifest: sortedManifest,
74
+ onCreate: workflowOnCreate,
75
+ ...props
76
+ }
77
+ )
78
+ ));
79
+ };
80
+ const EmbeddableWorkflow = (props) => /* @__PURE__ */ React.createElement(SecretsContextProvider, null, /* @__PURE__ */ React.createElement(Workflow, { ...props }));
81
+
82
+ export { EmbeddableWorkflow, Workflow };
83
+ //# sourceMappingURL=Workflow.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Workflow.esm.js","sources":["../../../../src/next/components/Workflow/Workflow.tsx"],"sourcesContent":["/*\n * Copyright 2022 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, { useCallback, useEffect } from 'react';\nimport {\n Content,\n InfoCard,\n MarkdownContent,\n Progress,\n} from '@backstage/core-components';\nimport { stringifyEntityRef } from '@backstage/catalog-model';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { errorApiRef, useAnalytics, useApi } from '@backstage/core-plugin-api';\nimport { useTemplateParameterSchema } from '../../hooks/useTemplateParameterSchema';\nimport { Stepper, type StepperProps } from '../Stepper/Stepper';\nimport { SecretsContextProvider } from '../../../secrets/SecretsContext';\nimport { useFilteredSchemaProperties } from '../../hooks/useFilteredSchemaProperties';\nimport { ReviewStepProps } from '@backstage/plugin-scaffolder-react';\nimport { useTemplateTimeSavedMinutes } from '../../hooks/useTemplateTimeSaved';\nimport { JsonValue } from '@backstage/types';\n\nconst useStyles = makeStyles({\n markdown: {\n /** to make the styles for React Markdown not leak into the description */\n '& :first-child': {\n marginTop: 0,\n },\n '& :last-child': {\n marginBottom: 0,\n },\n },\n});\n\n/**\n * @alpha\n */\nexport type WorkflowProps = {\n title?: string;\n description?: string;\n namespace: string;\n templateName: string;\n components?: {\n ReviewStepComponent?: React.ComponentType<ReviewStepProps>;\n };\n onError(error: Error | undefined): JSX.Element | null;\n} & Pick<\n StepperProps,\n | 'extensions'\n | 'formProps'\n | 'components'\n | 'onCreate'\n | 'initialState'\n | 'layouts'\n>;\n\n/**\n * @alpha\n */\nexport const Workflow = (workflowProps: WorkflowProps): JSX.Element | null => {\n const { title, description, namespace, templateName, onCreate, ...props } =\n workflowProps;\n\n const analytics = useAnalytics();\n const styles = useStyles();\n const templateRef = stringifyEntityRef({\n kind: 'Template',\n namespace: namespace,\n name: templateName,\n });\n\n const errorApi = useApi(errorApiRef);\n\n const { loading, manifest, error } = useTemplateParameterSchema(templateRef);\n\n const sortedManifest = useFilteredSchemaProperties(manifest);\n\n const minutesSaved = useTemplateTimeSavedMinutes(templateRef);\n\n const workflowOnCreate = useCallback(\n async (formState: Record<string, JsonValue>) => {\n onCreate(formState);\n\n const name =\n typeof formState.name === 'string' ? formState.name : undefined;\n analytics.captureEvent('create', name ?? templateName ?? 'unknown', {\n value: minutesSaved,\n });\n },\n [onCreate, analytics, templateName, minutesSaved],\n );\n\n useEffect(() => {\n if (error) {\n errorApi.post(new Error(`Failed to load template, ${error}`));\n }\n }, [error, errorApi]);\n\n if (error) {\n return props.onError(error);\n }\n\n return (\n <Content>\n {loading && <Progress />}\n {sortedManifest && (\n <InfoCard\n title={title ?? sortedManifest.title}\n subheader={\n <MarkdownContent\n className={styles.markdown}\n content={\n description ?? sortedManifest.description ?? 'No description'\n }\n />\n }\n noPadding\n titleTypographyProps={{ component: 'h2' }}\n >\n <Stepper\n manifest={sortedManifest}\n onCreate={workflowOnCreate}\n {...props}\n />\n </InfoCard>\n )}\n </Content>\n );\n};\n\n/**\n * @alpha\n */\nexport const EmbeddableWorkflow = (props: WorkflowProps) => (\n <SecretsContextProvider>\n <Workflow {...props} />\n </SecretsContextProvider>\n);\n"],"names":["_a"],"mappings":";;;;;;;;;;;AAkCA,MAAM,YAAY,UAAW,CAAA;AAAA,EAC3B,QAAU,EAAA;AAAA;AAAA,IAER,gBAAkB,EAAA;AAAA,MAChB,SAAW,EAAA,CAAA;AAAA,KACb;AAAA,IACA,eAAiB,EAAA;AAAA,MACf,YAAc,EAAA,CAAA;AAAA,KAChB;AAAA,GACF;AACF,CAAC,CAAA,CAAA;AA2BY,MAAA,QAAA,GAAW,CAAC,aAAqD,KAAA;AAvE9E,EAAA,IAAA,EAAA,CAAA;AAwEE,EAAM,MAAA,EAAE,OAAO,WAAa,EAAA,SAAA,EAAW,cAAc,QAAU,EAAA,GAAG,OAChE,GAAA,aAAA,CAAA;AAEF,EAAA,MAAM,YAAY,YAAa,EAAA,CAAA;AAC/B,EAAA,MAAM,SAAS,SAAU,EAAA,CAAA;AACzB,EAAA,MAAM,cAAc,kBAAmB,CAAA;AAAA,IACrC,IAAM,EAAA,UAAA;AAAA,IACN,SAAA;AAAA,IACA,IAAM,EAAA,YAAA;AAAA,GACP,CAAA,CAAA;AAED,EAAM,MAAA,QAAA,GAAW,OAAO,WAAW,CAAA,CAAA;AAEnC,EAAA,MAAM,EAAE,OAAS,EAAA,QAAA,EAAU,KAAM,EAAA,GAAI,2BAA2B,WAAW,CAAA,CAAA;AAE3E,EAAM,MAAA,cAAA,GAAiB,4BAA4B,QAAQ,CAAA,CAAA;AAE3D,EAAM,MAAA,YAAA,GAAe,4BAA4B,WAAW,CAAA,CAAA;AAE5D,EAAA,MAAM,gBAAmB,GAAA,WAAA;AAAA,IACvB,OAAO,SAAyC,KAAA;AA5FpD,MAAAA,IAAAA,GAAAA,CAAAA;AA6FM,MAAA,QAAA,CAAS,SAAS,CAAA,CAAA;AAElB,MAAA,MAAM,OACJ,OAAO,SAAA,CAAU,IAAS,KAAA,QAAA,GAAW,UAAU,IAAO,GAAA,KAAA,CAAA,CAAA;AACxD,MAAA,SAAA,CAAU,aAAa,QAAUA,EAAAA,CAAAA,GAAAA,GAAA,sBAAQ,YAAR,KAAA,IAAA,GAAAA,MAAwB,SAAW,EAAA;AAAA,QAClE,KAAO,EAAA,YAAA;AAAA,OACR,CAAA,CAAA;AAAA,KACH;AAAA,IACA,CAAC,QAAA,EAAU,SAAW,EAAA,YAAA,EAAc,YAAY,CAAA;AAAA,GAClD,CAAA;AAEA,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,KAAO,EAAA;AACT,MAAA,QAAA,CAAS,KAAK,IAAI,KAAA,CAAM,CAA4B,yBAAA,EAAA,KAAK,EAAE,CAAC,CAAA,CAAA;AAAA,KAC9D;AAAA,GACC,EAAA,CAAC,KAAO,EAAA,QAAQ,CAAC,CAAA,CAAA;AAEpB,EAAA,IAAI,KAAO,EAAA;AACT,IAAO,OAAA,KAAA,CAAM,QAAQ,KAAK,CAAA,CAAA;AAAA,GAC5B;AAEA,EAAA,2CACG,OACE,EAAA,IAAA,EAAA,OAAA,oBAAY,KAAA,CAAA,aAAA,CAAA,QAAA,EAAA,IAAS,GACrB,cACC,oBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAO,wBAAS,cAAe,CAAA,KAAA;AAAA,MAC/B,SACE,kBAAA,KAAA,CAAA,aAAA;AAAA,QAAC,eAAA;AAAA,QAAA;AAAA,UACC,WAAW,MAAO,CAAA,QAAA;AAAA,UAClB,OACE,EAAA,CAAA,EAAA,GAAA,WAAA,IAAA,IAAA,GAAA,WAAA,GAAe,cAAe,CAAA,WAAA,KAA9B,IAA6C,GAAA,EAAA,GAAA,gBAAA;AAAA,SAAA;AAAA,OAEjD;AAAA,MAEF,SAAS,EAAA,IAAA;AAAA,MACT,oBAAA,EAAsB,EAAE,SAAA,EAAW,IAAK,EAAA;AAAA,KAAA;AAAA,oBAExC,KAAA,CAAA,aAAA;AAAA,MAAC,OAAA;AAAA,MAAA;AAAA,QACC,QAAU,EAAA,cAAA;AAAA,QACV,QAAU,EAAA,gBAAA;AAAA,QACT,GAAG,KAAA;AAAA,OAAA;AAAA,KACN;AAAA,GAGN,CAAA,CAAA;AAEJ,EAAA;AAKa,MAAA,kBAAA,GAAqB,CAAC,KACjC,qBAAA,KAAA,CAAA,aAAA,CAAC,8CACE,KAAA,CAAA,aAAA,CAAA,QAAA,EAAA,EAAU,GAAG,KAAA,EAAO,CACvB;;;;"}
@@ -0,0 +1,44 @@
1
+ import cloneDeep from 'lodash/cloneDeep';
2
+ import { useApi, featureFlagsApiRef } from '@backstage/core-plugin-api';
3
+
4
+ const useFilteredSchemaProperties = (manifest) => {
5
+ const featureFlagKey = "backstage:featureFlag";
6
+ const featureFlagApi = useApi(featureFlagsApiRef);
7
+ if (!manifest) {
8
+ return void 0;
9
+ }
10
+ const filteredSteps = manifest == null ? void 0 : manifest.steps.filter((step) => {
11
+ const featureFlag = step.schema[featureFlagKey];
12
+ return typeof featureFlag !== "string" || featureFlagApi.isActive(featureFlag);
13
+ }).map((step) => {
14
+ var _a;
15
+ const filteredStep = cloneDeep(step);
16
+ const removedPropertyKeys = [];
17
+ if (filteredStep.schema.properties) {
18
+ filteredStep.schema.properties = Object.fromEntries(
19
+ Object.entries(filteredStep.schema.properties).filter(
20
+ ([key, value]) => {
21
+ if (value[featureFlagKey]) {
22
+ if (featureFlagApi.isActive(value[featureFlagKey])) {
23
+ return true;
24
+ }
25
+ removedPropertyKeys.push(key);
26
+ return false;
27
+ }
28
+ return true;
29
+ }
30
+ )
31
+ );
32
+ filteredStep.schema.required = Array.isArray(
33
+ filteredStep.schema.required
34
+ ) ? (_a = filteredStep.schema.required) == null ? void 0 : _a.filter(
35
+ (r) => !removedPropertyKeys.includes(r)
36
+ ) : filteredStep.schema.required;
37
+ }
38
+ return filteredStep;
39
+ });
40
+ return { ...manifest, steps: filteredSteps };
41
+ };
42
+
43
+ export { useFilteredSchemaProperties };
44
+ //# sourceMappingURL=useFilteredSchemaProperties.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useFilteredSchemaProperties.esm.js","sources":["../../../src/next/hooks/useFilteredSchemaProperties.ts"],"sourcesContent":["/*\n * Copyright 2023 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 cloneDeep from 'lodash/cloneDeep';\nimport { useApi, featureFlagsApiRef } from '@backstage/core-plugin-api';\nimport { TemplateParameterSchema } from '@backstage/plugin-scaffolder-react';\n\n/**\n * Returns manifest of software templates with steps without a featureFlag tag.\n * @alpha\n */\n\nexport const useFilteredSchemaProperties = (\n manifest: TemplateParameterSchema | undefined,\n): TemplateParameterSchema | undefined => {\n const featureFlagKey = 'backstage:featureFlag';\n const featureFlagApi = useApi(featureFlagsApiRef);\n\n if (!manifest) {\n return undefined;\n }\n\n const filteredSteps = manifest?.steps\n .filter(step => {\n const featureFlag = step.schema[featureFlagKey];\n return (\n typeof featureFlag !== 'string' || featureFlagApi.isActive(featureFlag)\n );\n })\n .map(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\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(\n filteredStep.schema.required,\n )\n ? filteredStep.schema.required?.filter(\n r => !removedPropertyKeys.includes(r as string),\n )\n : filteredStep.schema.required;\n }\n\n return filteredStep;\n });\n\n return { ...manifest, steps: filteredSteps };\n};\n"],"names":[],"mappings":";;;AAwBa,MAAA,2BAAA,GAA8B,CACzC,QACwC,KAAA;AACxC,EAAA,MAAM,cAAiB,GAAA,uBAAA,CAAA;AACvB,EAAM,MAAA,cAAA,GAAiB,OAAO,kBAAkB,CAAA,CAAA;AAEhD,EAAA,IAAI,CAAC,QAAU,EAAA;AACb,IAAO,OAAA,KAAA,CAAA,CAAA;AAAA,GACT;AAEA,EAAA,MAAM,aAAgB,GAAA,QAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,QAAA,CAAU,KAC7B,CAAA,MAAA,CAAO,CAAQ,IAAA,KAAA;AACd,IAAM,MAAA,WAAA,GAAc,IAAK,CAAA,MAAA,CAAO,cAAc,CAAA,CAAA;AAC9C,IAAA,OACE,OAAO,WAAA,KAAgB,QAAY,IAAA,cAAA,CAAe,SAAS,WAAW,CAAA,CAAA;AAAA,GAE1E,CAAA,CACC,IAAI,CAAQ,IAAA,KAAA;AAzCjB,IAAA,IAAA,EAAA,CAAA;AA0CM,IAAM,MAAA,YAAA,GAAe,UAAU,IAAI,CAAA,CAAA;AACnC,IAAA,MAAM,sBAAqC,EAAC,CAAA;AAC5C,IAAI,IAAA,YAAA,CAAa,OAAO,UAAY,EAAA;AAClC,MAAa,YAAA,CAAA,MAAA,CAAO,aAAa,MAAO,CAAA,WAAA;AAAA,QACtC,MAAO,CAAA,OAAA,CAAQ,YAAa,CAAA,MAAA,CAAO,UAAU,CAAE,CAAA,MAAA;AAAA,UAC7C,CAAC,CAAC,GAAK,EAAA,KAAK,CAAM,KAAA;AAChB,YAAI,IAAA,KAAA,CAAM,cAAc,CAAG,EAAA;AACzB,cAAA,IAAI,cAAe,CAAA,QAAA,CAAS,KAAM,CAAA,cAAc,CAAC,CAAG,EAAA;AAClD,gBAAO,OAAA,IAAA,CAAA;AAAA,eACT;AAEA,cAAA,mBAAA,CAAoB,KAAK,GAAG,CAAA,CAAA;AAC5B,cAAO,OAAA,KAAA,CAAA;AAAA,aACT;AACA,YAAO,OAAA,IAAA,CAAA;AAAA,WACT;AAAA,SACF;AAAA,OACF,CAAA;AAGA,MAAa,YAAA,CAAA,MAAA,CAAO,WAAW,KAAM,CAAA,OAAA;AAAA,QACnC,aAAa,MAAO,CAAA,QAAA;AAAA,OAElB,GAAA,CAAA,EAAA,GAAA,YAAA,CAAa,MAAO,CAAA,QAAA,KAApB,IAA8B,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,MAAA;AAAA,QAC5B,CAAK,CAAA,KAAA,CAAC,mBAAoB,CAAA,QAAA,CAAS,CAAW,CAAA;AAAA,OAAA,GAEhD,aAAa,MAAO,CAAA,QAAA,CAAA;AAAA,KAC1B;AAEA,IAAO,OAAA,YAAA,CAAA;AAAA,GACT,CAAA,CAAA;AAEF,EAAA,OAAO,EAAE,GAAG,QAAU,EAAA,KAAA,EAAO,aAAc,EAAA,CAAA;AAC7C;;;;"}
@@ -0,0 +1,21 @@
1
+ import qs from 'qs';
2
+ import { useState } from 'react';
3
+
4
+ const useFormDataFromQuery = (initialState) => {
5
+ return useState(() => {
6
+ if (initialState) {
7
+ return initialState;
8
+ }
9
+ const query = qs.parse(window.location.search, {
10
+ ignoreQueryPrefix: true
11
+ });
12
+ try {
13
+ return JSON.parse(query.formData);
14
+ } catch (e) {
15
+ return {};
16
+ }
17
+ });
18
+ };
19
+
20
+ export { useFormDataFromQuery };
21
+ //# sourceMappingURL=useFormDataFromQuery.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useFormDataFromQuery.esm.js","sources":["../../../src/next/hooks/useFormDataFromQuery.ts"],"sourcesContent":["/*\n * Copyright 2022 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 { JsonValue } from '@backstage/types';\nimport qs from 'qs';\nimport { useState } from 'react';\n\n/**\n * This hook is used to get the formData from the query string.\n * @alpha\n */\nexport const useFormDataFromQuery = (\n initialState?: Record<string, JsonValue>,\n) => {\n return useState<Record<string, any>>(() => {\n if (initialState) {\n return initialState;\n }\n\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 {};\n }\n });\n};\n"],"names":[],"mappings":";;;AAwBa,MAAA,oBAAA,GAAuB,CAClC,YACG,KAAA;AACH,EAAA,OAAO,SAA8B,MAAM;AACzC,IAAA,IAAI,YAAc,EAAA;AAChB,MAAO,OAAA,YAAA,CAAA;AAAA,KACT;AAEA,IAAA,MAAM,KAAQ,GAAA,EAAA,CAAG,KAAM,CAAA,MAAA,CAAO,SAAS,MAAQ,EAAA;AAAA,MAC7C,iBAAmB,EAAA,IAAA;AAAA,KACpB,CAAA,CAAA;AAED,IAAI,IAAA;AACF,MAAO,OAAA,IAAA,CAAK,KAAM,CAAA,KAAA,CAAM,QAAkB,CAAA,CAAA;AAAA,aACnC,CAAG,EAAA;AACV,MAAA,OAAO,EAAC,CAAA;AAAA,KACV;AAAA,GACD,CAAA,CAAA;AACH;;;;"}
@@ -0,0 +1,19 @@
1
+ import useAsync from 'react-use/esm/useAsync';
2
+ import { scaffolderApiRef } from '../../api/ref.esm.js';
3
+ import { useApi } from '@backstage/core-plugin-api';
4
+
5
+ const useTemplateParameterSchema = (templateRef) => {
6
+ const scaffolderApi = useApi(scaffolderApiRef);
7
+ const { value, loading, error } = useAsync(
8
+ () => scaffolderApi.getTemplateParameterSchema(templateRef),
9
+ [scaffolderApi, templateRef]
10
+ );
11
+ return {
12
+ manifest: value,
13
+ loading,
14
+ error
15
+ };
16
+ };
17
+
18
+ export { useTemplateParameterSchema };
19
+ //# sourceMappingURL=useTemplateParameterSchema.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTemplateParameterSchema.esm.js","sources":["../../../src/next/hooks/useTemplateParameterSchema.ts"],"sourcesContent":["/*\n * Copyright 2023 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 useAsync from 'react-use/esm/useAsync';\nimport { scaffolderApiRef } from '../../api/ref';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { TemplateParameterSchema } from '@backstage/plugin-scaffolder-react';\n\n/**\n * @alpha\n */\nexport const useTemplateParameterSchema = (templateRef: string) => {\n const scaffolderApi = useApi(scaffolderApiRef);\n const { value, loading, error } = useAsync(\n () => scaffolderApi.getTemplateParameterSchema(templateRef),\n [scaffolderApi, templateRef],\n );\n\n return {\n manifest: value as TemplateParameterSchema | undefined,\n loading,\n error,\n };\n};\n"],"names":[],"mappings":";;;;AAwBa,MAAA,0BAAA,GAA6B,CAAC,WAAwB,KAAA;AACjE,EAAM,MAAA,aAAA,GAAgB,OAAO,gBAAgB,CAAA,CAAA;AAC7C,EAAA,MAAM,EAAE,KAAA,EAAO,OAAS,EAAA,KAAA,EAAU,GAAA,QAAA;AAAA,IAChC,MAAM,aAAc,CAAA,0BAAA,CAA2B,WAAW,CAAA;AAAA,IAC1D,CAAC,eAAe,WAAW,CAAA;AAAA,GAC7B,CAAA;AAEA,EAAO,OAAA;AAAA,IACL,QAAU,EAAA,KAAA;AAAA,IACV,OAAA;AAAA,IACA,KAAA;AAAA,GACF,CAAA;AACF;;;;"}
@@ -0,0 +1,46 @@
1
+ import { useApi, featureFlagsApiRef } from '@backstage/core-plugin-api';
2
+ import { extractSchemaFromStep } from '../lib/schema.esm.js';
3
+
4
+ const useTemplateSchema = (manifest) => {
5
+ const featureFlags = useApi(featureFlagsApiRef);
6
+ const steps = manifest.steps.map(({ title, description, schema }) => ({
7
+ title,
8
+ description,
9
+ mergedSchema: schema,
10
+ ...extractSchemaFromStep(schema)
11
+ }));
12
+ const returningSteps = steps.filter((step) => {
13
+ var _a;
14
+ const stepFeatureFlag = (_a = step.uiSchema["ui:backstage"]) == null ? void 0 : _a.featureFlag;
15
+ return stepFeatureFlag ? featureFlags.isActive(stepFeatureFlag) : true;
16
+ }).map((step) => {
17
+ var _a, _b, _c, _d;
18
+ const strippedSchema = {
19
+ ...step,
20
+ schema: {
21
+ ...step.schema,
22
+ // Title is rendered at the top of the page, so let's ignore this from jsonschemaform
23
+ title: void 0
24
+ }
25
+ };
26
+ if (((_a = step.schema) == null ? void 0 : _a.properties) || !((_b = step.schema) == null ? void 0 : _b.dependencies)) {
27
+ strippedSchema.schema.properties = Object.fromEntries(
28
+ Object.entries((_d = (_c = step.schema) == null ? void 0 : _c.properties) != null ? _d : {}).filter(
29
+ ([key]) => {
30
+ var _a2, _b2;
31
+ const stepFeatureFlag = (_b2 = (_a2 = step.uiSchema[key]) == null ? void 0 : _a2["ui:backstage"]) == null ? void 0 : _b2.featureFlag;
32
+ return stepFeatureFlag ? featureFlags.isActive(stepFeatureFlag) : true;
33
+ }
34
+ )
35
+ );
36
+ }
37
+ return strippedSchema;
38
+ });
39
+ return {
40
+ presentation: manifest.presentation,
41
+ steps: returningSteps
42
+ };
43
+ };
44
+
45
+ export { useTemplateSchema };
46
+ //# sourceMappingURL=useTemplateSchema.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTemplateSchema.esm.js","sources":["../../../src/next/hooks/useTemplateSchema.ts"],"sourcesContent":["/*\n * Copyright 2022 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 { featureFlagsApiRef, useApi } from '@backstage/core-plugin-api';\nimport { TemplatePresentationV1beta3 } from '@backstage/plugin-scaffolder-common';\nimport { JsonObject } from '@backstage/types';\nimport { UiSchema } from '@rjsf/utils';\nimport { TemplateParameterSchema } from '@backstage/plugin-scaffolder-react';\nimport { extractSchemaFromStep } from '../lib';\n\n/**\n * This is the parsed template schema that is returned from the {@link useTemplateSchema} hook.\n * @alpha\n */\nexport interface ParsedTemplateSchema {\n uiSchema: UiSchema;\n mergedSchema: JsonObject;\n schema: JsonObject;\n title: string;\n description?: string;\n}\n\n/**\n * This hook will parse the template schema and return the steps with the\n * parsed schema and uiSchema. Filtering out any steps or properties that\n * are not enabled with feature flags.\n * @alpha\n */\nexport const useTemplateSchema = (\n manifest: TemplateParameterSchema,\n): {\n steps: ParsedTemplateSchema[];\n presentation?: TemplatePresentationV1beta3;\n} => {\n const featureFlags = useApi(featureFlagsApiRef);\n const steps = manifest.steps.map(({ title, description, schema }) => ({\n title,\n description,\n mergedSchema: schema,\n ...extractSchemaFromStep(schema),\n }));\n\n const returningSteps = steps\n // Filter out steps that are not enabled with the feature flags\n .filter(step => {\n const stepFeatureFlag = step.uiSchema['ui:backstage']?.featureFlag;\n return stepFeatureFlag ? featureFlags.isActive(stepFeatureFlag) : true;\n })\n // Then filter out the properties that are not enabled with feature flag\n .map(step => {\n const strippedSchema = {\n ...step,\n schema: {\n ...step.schema,\n // Title is rendered at the top of the page, so let's ignore this from jsonschemaform\n title: undefined,\n },\n } as ParsedTemplateSchema;\n\n if (step.schema?.properties || !step.schema?.dependencies) {\n strippedSchema.schema.properties = Object.fromEntries(\n Object.entries((step.schema?.properties ?? {}) as JsonObject).filter(\n ([key]) => {\n const stepFeatureFlag =\n step.uiSchema[key]?.['ui:backstage']?.featureFlag;\n return stepFeatureFlag\n ? featureFlags.isActive(stepFeatureFlag)\n : true;\n },\n ),\n );\n }\n\n return strippedSchema;\n });\n\n return {\n presentation: manifest.presentation,\n steps: returningSteps,\n };\n};\n"],"names":["_a","_b"],"mappings":";;;AAwCa,MAAA,iBAAA,GAAoB,CAC/B,QAIG,KAAA;AACH,EAAM,MAAA,YAAA,GAAe,OAAO,kBAAkB,CAAA,CAAA;AAC9C,EAAM,MAAA,KAAA,GAAQ,SAAS,KAAM,CAAA,GAAA,CAAI,CAAC,EAAE,KAAA,EAAO,WAAa,EAAA,MAAA,EAAc,MAAA;AAAA,IACpE,KAAA;AAAA,IACA,WAAA;AAAA,IACA,YAAc,EAAA,MAAA;AAAA,IACd,GAAG,sBAAsB,MAAM,CAAA;AAAA,GAC/B,CAAA,CAAA,CAAA;AAEF,EAAM,MAAA,cAAA,GAAiB,KAEpB,CAAA,MAAA,CAAO,CAAQ,IAAA,KAAA;AAxDpB,IAAA,IAAA,EAAA,CAAA;AAyDM,IAAA,MAAM,eAAkB,GAAA,CAAA,EAAA,GAAA,IAAA,CAAK,QAAS,CAAA,cAAc,MAA5B,IAA+B,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,WAAA,CAAA;AACvD,IAAA,OAAO,eAAkB,GAAA,YAAA,CAAa,QAAS,CAAA,eAAe,CAAI,GAAA,IAAA,CAAA;AAAA,GACnE,CAEA,CAAA,GAAA,CAAI,CAAQ,IAAA,KAAA;AA7DjB,IAAA,IAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,CAAA;AA8DM,IAAA,MAAM,cAAiB,GAAA;AAAA,MACrB,GAAG,IAAA;AAAA,MACH,MAAQ,EAAA;AAAA,QACN,GAAG,IAAK,CAAA,MAAA;AAAA;AAAA,QAER,KAAO,EAAA,KAAA,CAAA;AAAA,OACT;AAAA,KACF,CAAA;AAEA,IAAI,IAAA,CAAA,CAAA,EAAA,GAAA,IAAA,CAAK,WAAL,IAAa,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,UAAA,KAAc,GAAC,EAAK,GAAA,IAAA,CAAA,MAAA,KAAL,mBAAa,YAAc,CAAA,EAAA;AACzD,MAAe,cAAA,CAAA,MAAA,CAAO,aAAa,MAAO,CAAA,WAAA;AAAA,QACxC,MAAA,CAAO,SAAS,EAAK,GAAA,CAAA,EAAA,GAAA,IAAA,CAAA,MAAA,KAAL,mBAAa,UAAb,KAAA,IAAA,GAAA,EAAA,GAA2B,EAAiB,CAAE,CAAA,MAAA;AAAA,UAC5D,CAAC,CAAC,GAAG,CAAM,KAAA;AA1EvB,YAAA,IAAAA,GAAAC,EAAAA,GAAAA,CAAAA;AA2Ec,YAAM,MAAA,eAAA,GAAA,CACJA,GAAAD,GAAAA,CAAAA,GAAAA,GAAA,IAAK,CAAA,QAAA,CAAS,GAAG,CAAA,KAAjB,IAAAA,GAAAA,KAAAA,CAAAA,GAAAA,GAAAA,CAAqB,cAArB,CAAA,KAAA,IAAA,GAAA,KAAA,CAAA,GAAAC,GAAsC,CAAA,WAAA,CAAA;AACxC,YAAA,OAAO,eACH,GAAA,YAAA,CAAa,QAAS,CAAA,eAAe,CACrC,GAAA,IAAA,CAAA;AAAA,WACN;AAAA,SACF;AAAA,OACF,CAAA;AAAA,KACF;AAEA,IAAO,OAAA,cAAA,CAAA;AAAA,GACR,CAAA,CAAA;AAEH,EAAO,OAAA;AAAA,IACL,cAAc,QAAS,CAAA,YAAA;AAAA,IACvB,KAAO,EAAA,cAAA;AAAA,GACT,CAAA;AACF;;;;"}
@@ -0,0 +1,25 @@
1
+ import { useApi } from '@backstage/core-plugin-api';
2
+ import { catalogApiRef } from '@backstage/plugin-catalog-react';
3
+ import { Duration } from 'luxon';
4
+ import useAsync from 'react-use/lib/useAsync';
5
+
6
+ const useTemplateTimeSavedMinutes = (templateRef) => {
7
+ const catalogApi = useApi(catalogApiRef);
8
+ const { value: timeSavedMinutes } = useAsync(async () => {
9
+ var _a;
10
+ const entity = await catalogApi.getEntityByRef(templateRef);
11
+ const timeSaved = (_a = entity == null ? void 0 : entity.metadata.annotations) == null ? void 0 : _a["backstage.io/time-saved"];
12
+ if (!entity || !timeSaved) {
13
+ return void 0;
14
+ }
15
+ const durationMs = Duration.fromISO(timeSaved).as("minutes");
16
+ if (Number.isNaN(durationMs)) {
17
+ return void 0;
18
+ }
19
+ return durationMs;
20
+ }, [catalogApi, templateRef]);
21
+ return timeSavedMinutes;
22
+ };
23
+
24
+ export { useTemplateTimeSavedMinutes };
25
+ //# sourceMappingURL=useTemplateTimeSaved.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTemplateTimeSaved.esm.js","sources":["../../../src/next/hooks/useTemplateTimeSaved.ts"],"sourcesContent":["/*\n * Copyright 2024 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 { useApi } from '@backstage/core-plugin-api';\nimport { catalogApiRef } from '@backstage/plugin-catalog-react';\nimport { Duration } from 'luxon';\nimport useAsync from 'react-use/lib/useAsync';\n\n/**\n * Returns the backstage.io/time-saved annotation (as a number of minutes) for\n * a given template entity ref.\n */\nexport const useTemplateTimeSavedMinutes = (templateRef: string) => {\n const catalogApi = useApi(catalogApiRef);\n\n const { value: timeSavedMinutes } = useAsync(async () => {\n const entity = await catalogApi.getEntityByRef(templateRef);\n const timeSaved = entity?.metadata.annotations?.['backstage.io/time-saved'];\n\n // This is not a valid template or the template has no time-saved value.\n if (!entity || !timeSaved) {\n return undefined;\n }\n\n const durationMs = Duration.fromISO(timeSaved).as('minutes');\n\n // The time-saved annotation has an invalid value. Ignore.\n if (Number.isNaN(durationMs)) {\n return undefined;\n }\n\n return durationMs;\n }, [catalogApi, templateRef]);\n\n return timeSavedMinutes;\n};\n"],"names":[],"mappings":";;;;;AAyBa,MAAA,2BAAA,GAA8B,CAAC,WAAwB,KAAA;AAClE,EAAM,MAAA,UAAA,GAAa,OAAO,aAAa,CAAA,CAAA;AAEvC,EAAA,MAAM,EAAE,KAAA,EAAO,gBAAiB,EAAA,GAAI,SAAS,YAAY;AA5B3D,IAAA,IAAA,EAAA,CAAA;AA6BI,IAAA,MAAM,MAAS,GAAA,MAAM,UAAW,CAAA,cAAA,CAAe,WAAW,CAAA,CAAA;AAC1D,IAAA,MAAM,SAAY,GAAA,CAAA,EAAA,GAAA,MAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,MAAA,CAAQ,QAAS,CAAA,WAAA,KAAjB,IAA+B,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,yBAAA,CAAA,CAAA;AAGjD,IAAI,IAAA,CAAC,MAAU,IAAA,CAAC,SAAW,EAAA;AACzB,MAAO,OAAA,KAAA,CAAA,CAAA;AAAA,KACT;AAEA,IAAA,MAAM,aAAa,QAAS,CAAA,OAAA,CAAQ,SAAS,CAAA,CAAE,GAAG,SAAS,CAAA,CAAA;AAG3D,IAAI,IAAA,MAAA,CAAO,KAAM,CAAA,UAAU,CAAG,EAAA;AAC5B,MAAO,OAAA,KAAA,CAAA,CAAA;AAAA,KACT;AAEA,IAAO,OAAA,UAAA,CAAA;AAAA,GACN,EAAA,CAAC,UAAY,EAAA,WAAW,CAAC,CAAA,CAAA;AAE5B,EAAO,OAAA,gBAAA,CAAA;AACT;;;;"}
@@ -0,0 +1,24 @@
1
+ const useTransformSchemaToProps = (step, options = {}) => {
2
+ var _a;
3
+ const { layouts = [] } = options;
4
+ const objectFieldTemplate = step == null ? void 0 : step.uiSchema["ui:ObjectFieldTemplate"];
5
+ if (typeof objectFieldTemplate !== "string") {
6
+ return step;
7
+ }
8
+ const Layout = (_a = layouts.find(
9
+ (layout) => layout.name === objectFieldTemplate
10
+ )) == null ? void 0 : _a.component;
11
+ if (!Layout) {
12
+ return step;
13
+ }
14
+ return {
15
+ ...step,
16
+ uiSchema: {
17
+ ...step.uiSchema,
18
+ ["ui:ObjectFieldTemplate"]: Layout
19
+ }
20
+ };
21
+ };
22
+
23
+ export { useTransformSchemaToProps };
24
+ //# sourceMappingURL=useTransformSchemaToProps.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTransformSchemaToProps.esm.js","sources":["../../../src/next/hooks/useTransformSchemaToProps.ts"],"sourcesContent":["/*\n * Copyright 2023 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 { LayoutOptions } from '../../layouts';\nimport { type ParsedTemplateSchema } from './useTemplateSchema';\n\ninterface Options {\n layouts?: LayoutOptions[];\n}\n\nexport const useTransformSchemaToProps = (\n step: ParsedTemplateSchema,\n options: Options = {},\n): ParsedTemplateSchema => {\n const { layouts = [] } = options;\n const objectFieldTemplate = step?.uiSchema['ui:ObjectFieldTemplate'] as\n | string\n | undefined;\n\n if (typeof objectFieldTemplate !== 'string') {\n return step;\n }\n\n const Layout = layouts.find(\n layout => layout.name === objectFieldTemplate,\n )?.component;\n\n if (!Layout) {\n return step;\n }\n\n return {\n ...step,\n uiSchema: {\n ...step.uiSchema,\n ['ui:ObjectFieldTemplate']: Layout,\n },\n };\n};\n"],"names":[],"mappings":"AAsBO,MAAM,yBAA4B,GAAA,CACvC,IACA,EAAA,OAAA,GAAmB,EACM,KAAA;AAzB3B,EAAA,IAAA,EAAA,CAAA;AA0BE,EAAA,MAAM,EAAE,OAAA,GAAU,EAAC,EAAM,GAAA,OAAA,CAAA;AACzB,EAAM,MAAA,mBAAA,GAAsB,6BAAM,QAAS,CAAA,wBAAA,CAAA,CAAA;AAI3C,EAAI,IAAA,OAAO,wBAAwB,QAAU,EAAA;AAC3C,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAEA,EAAA,MAAM,UAAS,EAAQ,GAAA,OAAA,CAAA,IAAA;AAAA,IACrB,CAAA,MAAA,KAAU,OAAO,IAAS,KAAA,mBAAA;AAAA,QADb,IAEZ,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,SAAA,CAAA;AAEH,EAAA,IAAI,CAAC,MAAQ,EAAA;AACX,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAEA,EAAO,OAAA;AAAA,IACL,GAAG,IAAA;AAAA,IACH,QAAU,EAAA;AAAA,MACR,GAAG,IAAK,CAAA,QAAA;AAAA,MACR,CAAC,wBAAwB,GAAG,MAAA;AAAA,KAC9B;AAAA,GACF,CAAA;AACF;;;;"}