@backstage/plugin-scaffolder-react 1.16.1-next.2 → 1.17.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 CHANGED
@@ -1,5 +1,26 @@
1
1
  # @backstage/plugin-scaffolder-react
2
2
 
3
+ ## 1.17.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 6c972fe: Added information about the `entityRef` and `taskId` to the analytics events whenever is possible.
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies
12
+ - @backstage/core-components@0.17.3
13
+ - @backstage/catalog-client@1.10.1
14
+ - @backstage/core-plugin-api@1.10.8
15
+ - @backstage/frontend-plugin-api@0.10.3
16
+ - @backstage/plugin-catalog-react@1.19.0
17
+ - @backstage/catalog-model@1.7.4
18
+ - @backstage/theme@0.6.6
19
+ - @backstage/types@1.2.1
20
+ - @backstage/version-bridge@1.0.11
21
+ - @backstage/plugin-permission-react@0.4.35
22
+ - @backstage/plugin-scaffolder-common@1.5.11
23
+
3
24
  ## 1.16.1-next.2
4
25
 
5
26
  ### Patch Changes
@@ -2,6 +2,7 @@ import { jsxs, jsx } from 'react/jsx-runtime';
2
2
  import { Content, ItemCardGrid, ContentHeader } from '@backstage/core-components';
3
3
  import { stringifyEntityRef } from '@backstage/catalog-model';
4
4
  import { TemplateCard } from '../TemplateCard/TemplateCard.esm.js';
5
+ import { AnalyticsContext } from '@backstage/core-plugin-api';
5
6
 
6
7
  const TemplateGroup = (props) => {
7
8
  const {
@@ -18,11 +19,19 @@ const TemplateGroup = (props) => {
18
19
  return /* @__PURE__ */ jsxs(Content, { children: [
19
20
  titleComponent,
20
21
  /* @__PURE__ */ jsx(ItemCardGrid, { children: templates.map(({ template, additionalLinks }) => /* @__PURE__ */ jsx(
21
- Card,
22
+ AnalyticsContext,
22
23
  {
23
- additionalLinks,
24
- template,
25
- onSelected
24
+ attributes: {
25
+ entityRef: stringifyEntityRef(template)
26
+ },
27
+ children: /* @__PURE__ */ jsx(
28
+ Card,
29
+ {
30
+ additionalLinks,
31
+ template,
32
+ onSelected
33
+ }
34
+ )
26
35
  },
27
36
  stringifyEntityRef(template)
28
37
  )) })
@@ -1 +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 { ReactNode, ComponentType } 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: ReactNode;\n components?: {\n CardComponent?: 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;AAAA,GACE,GAAA,KAAA;AACJ,EAAA,MAAM,iBACJ,OAAO,KAAA,KAAU,2BAAY,GAAA,CAAA,aAAA,EAAA,EAAc,OAAc,CAAK,GAAA,KAAA;AAEhE,EAAI,IAAA,SAAA,CAAU,WAAW,CAAG,EAAA;AAC1B,IAAO,OAAA,IAAA;AAAA;AAGT,EAAA,MAAM,OAAO,aAAiB,IAAA,YAAA;AAE9B,EAAA,4BACG,OACE,EAAA,EAAA,QAAA,EAAA;AAAA,IAAA,cAAA;AAAA,oBACD,GAAA,CAAC,gBACE,QAAU,EAAA,SAAA,CAAA,GAAA,CAAI,CAAC,EAAE,QAAA,EAAU,iBAC1B,qBAAA,GAAA;AAAA,MAAC,IAAA;AAAA,MAAA;AAAA,QAEC,eAAA;AAAA,QACA,QAAA;AAAA,QACA;AAAA,OAAA;AAAA,MAHK,mBAAmB,QAAQ;AAAA,KAKnC,CACH,EAAA;AAAA,GACF,EAAA,CAAA;AAEJ;;;;"}
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 { ReactNode, ComponentType } 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 { AnalyticsContext, 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: ReactNode;\n components?: {\n CardComponent?: 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 <AnalyticsContext\n attributes={{\n entityRef: stringifyEntityRef(template),\n }}\n key={stringifyEntityRef(template)}\n >\n <Card\n additionalLinks={additionalLinks}\n template={template}\n onSelected={onSelected}\n />\n </AnalyticsContext>\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;AAAA,GACE,GAAA,KAAA;AACJ,EAAA,MAAM,iBACJ,OAAO,KAAA,KAAU,2BAAY,GAAA,CAAA,aAAA,EAAA,EAAc,OAAc,CAAK,GAAA,KAAA;AAEhE,EAAI,IAAA,SAAA,CAAU,WAAW,CAAG,EAAA;AAC1B,IAAO,OAAA,IAAA;AAAA;AAGT,EAAA,MAAM,OAAO,aAAiB,IAAA,YAAA;AAE9B,EAAA,4BACG,OACE,EAAA,EAAA,QAAA,EAAA;AAAA,IAAA,cAAA;AAAA,oBACD,GAAA,CAAC,gBACE,QAAU,EAAA,SAAA,CAAA,GAAA,CAAI,CAAC,EAAE,QAAA,EAAU,iBAC1B,qBAAA,GAAA;AAAA,MAAC,gBAAA;AAAA,MAAA;AAAA,QACC,UAAY,EAAA;AAAA,UACV,SAAA,EAAW,mBAAmB,QAAQ;AAAA,SACxC;AAAA,QAGA,QAAA,kBAAA,GAAA;AAAA,UAAC,IAAA;AAAA,UAAA;AAAA,YACC,eAAA;AAAA,YACA,QAAA;AAAA,YACA;AAAA;AAAA;AACF,OAAA;AAAA,MANK,mBAAmB,QAAQ;AAAA,KAQnC,CACH,EAAA;AAAA,GACF,EAAA,CAAA;AAEJ;;;;"}
@@ -4,7 +4,7 @@ import { useApi, errorApiRef } from '@backstage/core-plugin-api';
4
4
  import { useEntityList } from '@backstage/plugin-catalog-react';
5
5
  import { isTemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common';
6
6
  import Typography from '@material-ui/core/Typography';
7
- import { useCallback } from 'react';
7
+ import { useCallback, useEffect } from 'react';
8
8
  import { TemplateGroup } from '../TemplateGroup/TemplateGroup.esm.js';
9
9
 
10
10
  const TemplateGroups = (props) => {
@@ -17,11 +17,15 @@ const TemplateGroups = (props) => {
17
17
  },
18
18
  [onTemplateSelected]
19
19
  );
20
+ useEffect(() => {
21
+ if (error) {
22
+ errorApi.post(error);
23
+ }
24
+ }, [error, errorApi]);
20
25
  if (loading) {
21
26
  return /* @__PURE__ */ jsx(Progress, {});
22
27
  }
23
28
  if (error) {
24
- errorApi.post(error);
25
29
  return null;
26
30
  }
27
31
  if (!entities || !entities.length) {
@@ -1 +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 { Link, Progress } from '@backstage/core-components';\nimport { errorApiRef, IconComponent, useApi } from '@backstage/core-plugin-api';\nimport { useEntityList } from '@backstage/plugin-catalog-react';\nimport {\n isTemplateEntityV1beta3,\n TemplateEntityV1beta3,\n} from '@backstage/plugin-scaffolder-common';\nimport { TemplateGroupFilter } from '@backstage/plugin-scaffolder-react';\nimport Typography from '@material-ui/core/Typography';\nimport { ComponentType, useCallback } from 'react';\n\nimport { TemplateGroup } from '../TemplateGroup/TemplateGroup';\n\n/**\n * @alpha\n */\nexport interface TemplateGroupsProps {\n groups: TemplateGroupFilter[];\n templateFilter?: (entity: TemplateEntityV1beta3) => boolean;\n TemplateCardComponent?: 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;AACnD,EAAA,MAAM,EAAE,MAAA,EAAQ,cAAgB,EAAA,qBAAA,EAAuB,oBACrD,GAAA,KAAA;AACF,EAAM,MAAA,QAAA,GAAW,OAAO,WAAW,CAAA;AACnC,EAAA,MAAM,UAAa,GAAA,WAAA;AAAA,IACjB,CAAC,QAAoC,KAAA;AACnC,MAAA,kBAAA,GAAqB,QAAQ,CAAA;AAAA,KAC/B;AAAA,IACA,CAAC,kBAAkB;AAAA,GACrB;AAEA,EAAA,IAAI,OAAS,EAAA;AACX,IAAA,2BAAQ,QAAS,EAAA,EAAA,CAAA;AAAA;AAGnB,EAAA,IAAI,KAAO,EAAA;AACT,IAAA,QAAA,CAAS,KAAK,KAAK,CAAA;AACnB,IAAO,OAAA,IAAA;AAAA;AAGT,EAAA,IAAI,CAAC,QAAA,IAAY,CAAC,QAAA,CAAS,MAAQ,EAAA;AACjC,IACE,uBAAA,IAAA,CAAC,UAAW,EAAA,EAAA,OAAA,EAAQ,OAAQ,EAAA,QAAA,EAAA;AAAA,MAAA,6DAAA;AAAA,MACkC,GAAA;AAAA,sBAC3D,GAAA,CAAA,IAAA,EAAA,EAAK,EAAG,EAAA,wEAAA,EAAyE,QAElF,EAAA,kBAAA,EAAA,CAAA;AAAA,MAAO;AAAA,KAET,EAAA,CAAA;AAAA;AAIJ,EACE,uBAAA,GAAA,CAAA,QAAA,EAAA,EACG,iBAAO,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;AACf,MAAA,MAAM,eACJ,GAAA,KAAA,CAAM,wBAA2B,GAAA,QAAQ,KAAK,EAAC;AAEjD,MAAO,OAAA;AAAA,QACL,QAAA;AAAA,QACA;AAAA,OACF;AAAA,KACD,CAAA;AAEH,IACE,uBAAA,GAAA;AAAA,MAAC,aAAA;AAAA,MAAA;AAAA,QAEC,SAAA;AAAA,QACA,KAAA;AAAA,QACA,UAAA,EAAY,EAAE,aAAA,EAAe,qBAAsB,EAAA;AAAA,QACnD;AAAA,OAAA;AAAA,MAJK;AAAA,KAKP;AAAA,GAEH,CACH,EAAA,CAAA;AAEJ;;;;"}
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 { Link, Progress } from '@backstage/core-components';\nimport { errorApiRef, IconComponent, useApi } from '@backstage/core-plugin-api';\nimport { useEntityList } from '@backstage/plugin-catalog-react';\nimport {\n isTemplateEntityV1beta3,\n TemplateEntityV1beta3,\n} from '@backstage/plugin-scaffolder-common';\nimport { TemplateGroupFilter } from '@backstage/plugin-scaffolder-react';\nimport Typography from '@material-ui/core/Typography';\nimport { ComponentType, useCallback, useEffect } from 'react';\n\nimport { TemplateGroup } from '../TemplateGroup/TemplateGroup';\n\n/**\n * @alpha\n */\nexport interface TemplateGroupsProps {\n groups: TemplateGroupFilter[];\n templateFilter?: (entity: TemplateEntityV1beta3) => boolean;\n TemplateCardComponent?: 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 useEffect(() => {\n if (error) {\n errorApi.post(error);\n }\n }, [error, errorApi]);\n\n if (loading) {\n return <Progress />;\n }\n\n if (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;AACnD,EAAA,MAAM,EAAE,MAAA,EAAQ,cAAgB,EAAA,qBAAA,EAAuB,oBACrD,GAAA,KAAA;AACF,EAAM,MAAA,QAAA,GAAW,OAAO,WAAW,CAAA;AACnC,EAAA,MAAM,UAAa,GAAA,WAAA;AAAA,IACjB,CAAC,QAAoC,KAAA;AACnC,MAAA,kBAAA,GAAqB,QAAQ,CAAA;AAAA,KAC/B;AAAA,IACA,CAAC,kBAAkB;AAAA,GACrB;AAEA,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,KAAO,EAAA;AACT,MAAA,QAAA,CAAS,KAAK,KAAK,CAAA;AAAA;AACrB,GACC,EAAA,CAAC,KAAO,EAAA,QAAQ,CAAC,CAAA;AAEpB,EAAA,IAAI,OAAS,EAAA;AACX,IAAA,2BAAQ,QAAS,EAAA,EAAA,CAAA;AAAA;AAGnB,EAAA,IAAI,KAAO,EAAA;AACT,IAAO,OAAA,IAAA;AAAA;AAGT,EAAA,IAAI,CAAC,QAAA,IAAY,CAAC,QAAA,CAAS,MAAQ,EAAA;AACjC,IACE,uBAAA,IAAA,CAAC,UAAW,EAAA,EAAA,OAAA,EAAQ,OAAQ,EAAA,QAAA,EAAA;AAAA,MAAA,6DAAA;AAAA,MACkC,GAAA;AAAA,sBAC3D,GAAA,CAAA,IAAA,EAAA,EAAK,EAAG,EAAA,wEAAA,EAAyE,QAElF,EAAA,kBAAA,EAAA,CAAA;AAAA,MAAO;AAAA,KAET,EAAA,CAAA;AAAA;AAIJ,EACE,uBAAA,GAAA,CAAA,QAAA,EAAA,EACG,iBAAO,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;AACf,MAAA,MAAM,eACJ,GAAA,KAAA,CAAM,wBAA2B,GAAA,QAAQ,KAAK,EAAC;AAEjD,MAAO,OAAA;AAAA,QACL,QAAA;AAAA,QACA;AAAA,OACF;AAAA,KACD,CAAA;AAEH,IACE,uBAAA,GAAA;AAAA,MAAC,aAAA;AAAA,MAAA;AAAA,QAEC,SAAA;AAAA,QACA,KAAA;AAAA,QACA,UAAA,EAAY,EAAE,aAAA,EAAe,qBAAsB,EAAA;AAAA,QACnD;AAAA,OAAA;AAAA,MAJK;AAAA,KAKP;AAAA,GAEH,CACH,EAAA,CAAA;AAEJ;;;;"}
@@ -40,12 +40,14 @@ const Workflow = (workflowProps) => {
40
40
  const workflowOnCreate = useCallback(
41
41
  async (formState) => {
42
42
  await onCreate(formState);
43
- const name = typeof formState.name === "string" ? formState.name : void 0;
44
- analytics.captureEvent("create", name ?? templateName ?? "unknown", {
45
- value: minutesSaved
43
+ analytics.captureEvent("create", "Task has been created", {
44
+ value: minutesSaved,
45
+ attributes: {
46
+ templateSteps: sortedManifest?.steps?.length ?? 0
47
+ }
46
48
  });
47
49
  },
48
- [onCreate, analytics, templateName, minutesSaved]
50
+ [onCreate, analytics, minutesSaved, sortedManifest]
49
51
  );
50
52
  useEffect(() => {
51
53
  if (error) {
@@ -1 +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 { stringifyEntityRef } from '@backstage/catalog-model';\nimport {\n Content,\n InfoCard,\n MarkdownContent,\n Progress,\n} from '@backstage/core-components';\nimport { errorApiRef, useAnalytics, useApi } from '@backstage/core-plugin-api';\nimport { useTranslationRef } from '@backstage/frontend-plugin-api';\nimport { ReviewStepProps } from '@backstage/plugin-scaffolder-react';\nimport { JsonValue } from '@backstage/types';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { ComponentType, useCallback, useEffect } from 'react';\n\nimport { SecretsContextProvider } from '../../../secrets/SecretsContext';\nimport { scaffolderReactTranslationRef } from '../../../translation';\nimport { useFilteredSchemaProperties } from '../../hooks/useFilteredSchemaProperties';\nimport { useTemplateParameterSchema } from '../../hooks/useTemplateParameterSchema';\nimport { useTemplateTimeSavedMinutes } from '../../hooks/useTemplateTimeSaved';\nimport { Stepper, type StepperProps } from '../Stepper/Stepper';\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?: 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 { t } = useTranslationRef(scaffolderReactTranslationRef);\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 await 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 linkTarget=\"_blank\"\n content={\n description ??\n sortedManifest.description ??\n t('workflow.noDescription')\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":[],"mappings":"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"}
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 { stringifyEntityRef } from '@backstage/catalog-model';\nimport {\n Content,\n InfoCard,\n MarkdownContent,\n Progress,\n} from '@backstage/core-components';\nimport { errorApiRef, useAnalytics, useApi } from '@backstage/core-plugin-api';\nimport { useTranslationRef } from '@backstage/frontend-plugin-api';\nimport { ReviewStepProps } from '@backstage/plugin-scaffolder-react';\nimport { JsonValue } from '@backstage/types';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { ComponentType, useCallback, useEffect } from 'react';\n\nimport { SecretsContextProvider } from '../../../secrets/SecretsContext';\nimport { scaffolderReactTranslationRef } from '../../../translation';\nimport { useFilteredSchemaProperties } from '../../hooks/useFilteredSchemaProperties';\nimport { useTemplateParameterSchema } from '../../hooks/useTemplateParameterSchema';\nimport { useTemplateTimeSavedMinutes } from '../../hooks/useTemplateTimeSaved';\nimport { Stepper, type StepperProps } from '../Stepper/Stepper';\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?: 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 { t } = useTranslationRef(scaffolderReactTranslationRef);\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 await onCreate(formState);\n\n analytics.captureEvent('create', 'Task has been created', {\n value: minutesSaved,\n attributes: {\n templateSteps: sortedManifest?.steps?.length ?? 0,\n },\n });\n },\n [onCreate, analytics, minutesSaved, sortedManifest],\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 linkTarget=\"_blank\"\n content={\n description ??\n sortedManifest.description ??\n t('workflow.noDescription')\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":[],"mappings":"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"}
@@ -1,42 +1,45 @@
1
1
  import cloneDeep from 'lodash/cloneDeep';
2
2
  import { useApi, featureFlagsApiRef } from '@backstage/core-plugin-api';
3
+ import { useMemo } from 'react';
3
4
 
4
5
  const useFilteredSchemaProperties = (manifest) => {
5
6
  const featureFlagKey = "backstage:featureFlag";
6
7
  const featureFlagApi = useApi(featureFlagsApiRef);
7
- if (!manifest) {
8
- return void 0;
9
- }
10
- const filteredSteps = manifest?.steps.filter((step) => {
11
- const featureFlag = step.schema[featureFlagKey];
12
- return typeof featureFlag !== "string" || featureFlagApi.isActive(featureFlag);
13
- }).map((step) => {
14
- const filteredStep = cloneDeep(step);
15
- const removedPropertyKeys = [];
16
- if (filteredStep.schema.properties) {
17
- filteredStep.schema.properties = Object.fromEntries(
18
- Object.entries(filteredStep.schema.properties).filter(
19
- ([key, value]) => {
20
- if (value[featureFlagKey]) {
21
- if (featureFlagApi.isActive(value[featureFlagKey])) {
22
- return true;
8
+ return useMemo(() => {
9
+ if (!manifest) {
10
+ return void 0;
11
+ }
12
+ const filteredSteps = manifest?.steps.filter((step) => {
13
+ const featureFlag = step.schema[featureFlagKey];
14
+ return typeof featureFlag !== "string" || featureFlagApi.isActive(featureFlag);
15
+ }).map((step) => {
16
+ const filteredStep = cloneDeep(step);
17
+ const removedPropertyKeys = [];
18
+ if (filteredStep.schema.properties) {
19
+ filteredStep.schema.properties = Object.fromEntries(
20
+ Object.entries(filteredStep.schema.properties).filter(
21
+ ([key, value]) => {
22
+ if (value[featureFlagKey]) {
23
+ if (featureFlagApi.isActive(value[featureFlagKey])) {
24
+ return true;
25
+ }
26
+ removedPropertyKeys.push(key);
27
+ return false;
23
28
  }
24
- removedPropertyKeys.push(key);
25
- return false;
29
+ return true;
26
30
  }
27
- return true;
28
- }
29
- )
30
- );
31
- filteredStep.schema.required = Array.isArray(
32
- filteredStep.schema.required
33
- ) ? filteredStep.schema.required?.filter(
34
- (r) => !removedPropertyKeys.includes(r)
35
- ) : filteredStep.schema.required;
36
- }
37
- return filteredStep;
38
- });
39
- return { ...manifest, steps: filteredSteps };
31
+ )
32
+ );
33
+ filteredStep.schema.required = Array.isArray(
34
+ filteredStep.schema.required
35
+ ) ? filteredStep.schema.required?.filter(
36
+ (r) => !removedPropertyKeys.includes(r)
37
+ ) : filteredStep.schema.required;
38
+ }
39
+ return filteredStep;
40
+ });
41
+ return { ...manifest, steps: filteredSteps };
42
+ }, [manifest, featureFlagApi]);
40
43
  };
41
44
 
42
45
  export { useFilteredSchemaProperties };
@@ -1 +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;AACvB,EAAM,MAAA,cAAA,GAAiB,OAAO,kBAAkB,CAAA;AAEhD,EAAA,IAAI,CAAC,QAAU,EAAA;AACb,IAAO,OAAA,KAAA,CAAA;AAAA;AAGT,EAAA,MAAM,aAAgB,GAAA,QAAA,EAAU,KAC7B,CAAA,MAAA,CAAO,CAAQ,IAAA,KAAA;AACd,IAAM,MAAA,WAAA,GAAc,IAAK,CAAA,MAAA,CAAO,cAAc,CAAA;AAC9C,IAAA,OACE,OAAO,WAAA,KAAgB,QAAY,IAAA,cAAA,CAAe,SAAS,WAAW,CAAA;AAAA,GAEzE,CACA,CAAA,GAAA,CAAI,CAAQ,IAAA,KAAA;AACX,IAAM,MAAA,YAAA,GAAe,UAAU,IAAI,CAAA;AACnC,IAAA,MAAM,sBAAqC,EAAC;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;AAAA;AAGT,cAAA,mBAAA,CAAoB,KAAK,GAAG,CAAA;AAC5B,cAAO,OAAA,KAAA;AAAA;AAET,YAAO,OAAA,IAAA;AAAA;AACT;AACF,OACF;AAGA,MAAa,YAAA,CAAA,MAAA,CAAO,WAAW,KAAM,CAAA,OAAA;AAAA,QACnC,aAAa,MAAO,CAAA;AAAA,OACtB,GACI,YAAa,CAAA,MAAA,CAAO,QAAU,EAAA,MAAA;AAAA,QAC5B,CAAK,CAAA,KAAA,CAAC,mBAAoB,CAAA,QAAA,CAAS,CAAW;AAAA,OAChD,GACA,aAAa,MAAO,CAAA,QAAA;AAAA;AAG1B,IAAO,OAAA,YAAA;AAAA,GACR,CAAA;AAEH,EAAA,OAAO,EAAE,GAAG,QAAU,EAAA,KAAA,EAAO,aAAc,EAAA;AAC7C;;;;"}
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';\nimport { useMemo } from '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 return useMemo(() => {\n if (!manifest) {\n return undefined;\n }\n const filteredSteps = manifest?.steps\n .filter(step => {\n const featureFlag = step.schema[featureFlagKey];\n return (\n typeof featureFlag !== 'string' ||\n 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 }, [manifest, featureFlagApi]);\n};\n"],"names":[],"mappings":";;;;AAyBa,MAAA,2BAAA,GAA8B,CACzC,QACwC,KAAA;AACxC,EAAA,MAAM,cAAiB,GAAA,uBAAA;AACvB,EAAM,MAAA,cAAA,GAAiB,OAAO,kBAAkB,CAAA;AAEhD,EAAA,OAAO,QAAQ,MAAM;AACnB,IAAA,IAAI,CAAC,QAAU,EAAA;AACb,MAAO,OAAA,KAAA,CAAA;AAAA;AAET,IAAA,MAAM,aAAgB,GAAA,QAAA,EAAU,KAC7B,CAAA,MAAA,CAAO,CAAQ,IAAA,KAAA;AACd,MAAM,MAAA,WAAA,GAAc,IAAK,CAAA,MAAA,CAAO,cAAc,CAAA;AAC9C,MAAA,OACE,OAAO,WAAA,KAAgB,QACvB,IAAA,cAAA,CAAe,SAAS,WAAW,CAAA;AAAA,KAEtC,CACA,CAAA,GAAA,CAAI,CAAQ,IAAA,KAAA;AACX,MAAM,MAAA,YAAA,GAAe,UAAU,IAAI,CAAA;AACnC,MAAA,MAAM,sBAAqC,EAAC;AAC5C,MAAI,IAAA,YAAA,CAAa,OAAO,UAAY,EAAA;AAClC,QAAa,YAAA,CAAA,MAAA,CAAO,aAAa,MAAO,CAAA,WAAA;AAAA,UACtC,MAAO,CAAA,OAAA,CAAQ,YAAa,CAAA,MAAA,CAAO,UAAU,CAAE,CAAA,MAAA;AAAA,YAC7C,CAAC,CAAC,GAAK,EAAA,KAAK,CAAM,KAAA;AAChB,cAAI,IAAA,KAAA,CAAM,cAAc,CAAG,EAAA;AACzB,gBAAA,IAAI,cAAe,CAAA,QAAA,CAAS,KAAM,CAAA,cAAc,CAAC,CAAG,EAAA;AAClD,kBAAO,OAAA,IAAA;AAAA;AAGT,gBAAA,mBAAA,CAAoB,KAAK,GAAG,CAAA;AAC5B,gBAAO,OAAA,KAAA;AAAA;AAET,cAAO,OAAA,IAAA;AAAA;AACT;AACF,SACF;AAGA,QAAa,YAAA,CAAA,MAAA,CAAO,WAAW,KAAM,CAAA,OAAA;AAAA,UACnC,aAAa,MAAO,CAAA;AAAA,SACtB,GACI,YAAa,CAAA,MAAA,CAAO,QAAU,EAAA,MAAA;AAAA,UAC5B,CAAK,CAAA,KAAA,CAAC,mBAAoB,CAAA,QAAA,CAAS,CAAW;AAAA,SAChD,GACA,aAAa,MAAO,CAAA,QAAA;AAAA;AAG1B,MAAO,OAAA,YAAA;AAAA,KACR,CAAA;AAEH,IAAA,OAAO,EAAE,GAAG,QAAU,EAAA,KAAA,EAAO,aAAc,EAAA;AAAA,GAC1C,EAAA,CAAC,QAAU,EAAA,cAAc,CAAC,CAAA;AAC/B;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/plugin-scaffolder-react",
3
- "version": "1.16.1-next.2",
3
+ "version": "1.17.0",
4
4
  "description": "A frontend library that helps other Backstage plugins interact with the Scaffolder",
5
5
  "backstage": {
6
6
  "role": "web-library",
@@ -66,17 +66,17 @@
66
66
  "test": "backstage-cli package test"
67
67
  },
68
68
  "dependencies": {
69
- "@backstage/catalog-client": "1.10.1-next.0",
70
- "@backstage/catalog-model": "1.7.4",
71
- "@backstage/core-components": "0.17.3-next.0",
72
- "@backstage/core-plugin-api": "1.10.7",
73
- "@backstage/frontend-plugin-api": "0.10.3-next.1",
74
- "@backstage/plugin-catalog-react": "1.19.0-next.2",
75
- "@backstage/plugin-permission-react": "0.4.34",
76
- "@backstage/plugin-scaffolder-common": "1.5.11",
77
- "@backstage/theme": "0.6.6",
78
- "@backstage/types": "1.2.1",
79
- "@backstage/version-bridge": "1.0.11",
69
+ "@backstage/catalog-client": "^1.10.1",
70
+ "@backstage/catalog-model": "^1.7.4",
71
+ "@backstage/core-components": "^0.17.3",
72
+ "@backstage/core-plugin-api": "^1.10.8",
73
+ "@backstage/frontend-plugin-api": "^0.10.3",
74
+ "@backstage/plugin-catalog-react": "^1.19.0",
75
+ "@backstage/plugin-permission-react": "^0.4.35",
76
+ "@backstage/plugin-scaffolder-common": "^1.5.11",
77
+ "@backstage/theme": "^0.6.6",
78
+ "@backstage/types": "^1.2.1",
79
+ "@backstage/version-bridge": "^1.0.11",
80
80
  "@material-ui/core": "^4.12.2",
81
81
  "@material-ui/icons": "^4.9.1",
82
82
  "@material-ui/lab": "4.0.0-alpha.61",
@@ -104,12 +104,12 @@
104
104
  "zod-to-json-schema": "^3.20.4"
105
105
  },
106
106
  "devDependencies": {
107
- "@backstage/cli": "0.33.0-next.1",
108
- "@backstage/core-app-api": "1.17.0",
109
- "@backstage/plugin-catalog": "1.31.0-next.2",
110
- "@backstage/plugin-catalog-common": "1.1.4",
111
- "@backstage/plugin-permission-common": "0.9.0",
112
- "@backstage/test-utils": "1.7.8",
107
+ "@backstage/cli": "^0.33.0",
108
+ "@backstage/core-app-api": "^1.17.1",
109
+ "@backstage/plugin-catalog": "^1.31.0",
110
+ "@backstage/plugin-catalog-common": "^1.1.4",
111
+ "@backstage/plugin-permission-common": "^0.9.0",
112
+ "@backstage/test-utils": "^1.7.9",
113
113
  "@testing-library/dom": "^10.0.0",
114
114
  "@testing-library/jest-dom": "^6.0.0",
115
115
  "@testing-library/react": "^16.0.0",