@backstage/plugin-scaffolder 1.32.1-next.1 → 1.33.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,53 @@
1
1
  # @backstage/plugin-scaffolder
2
2
 
3
+ ## 1.33.0
4
+
5
+ ### Minor Changes
6
+
7
+ - c1ce316: BREAKING `/alpha`: Converted `scaffolder.task.read` and `scaffolder.task.cancel` into Resource Permissions.
8
+
9
+ BREAKING `/alpha`: Added a new scaffolder rule `isTaskOwner` for `scaffolder.task.read` and `scaffolder.task.cancel` to allow for conditional permission policies such as restricting access to tasks and task events based on task creators.
10
+
11
+ BREAKING `/alpha`: Retrying a task now requires both `scaffolder.task.read` and `scaffolder.task.create` permissions, replacing the previous requirement of `scaffolder.task.read` and `scaffolder.task.cancel`.
12
+
13
+ ### Patch Changes
14
+
15
+ - 289e4a1: Filter MultiEntityPicker options based on rendered option value
16
+ - Updated dependencies
17
+ - @backstage/plugin-catalog-react@1.19.1
18
+ - @backstage/catalog-model@1.7.5
19
+ - @backstage/plugin-scaffolder-react@1.18.0
20
+ - @backstage/catalog-client@1.10.2
21
+ - @backstage/core-components@0.17.4
22
+ - @backstage/core-plugin-api@1.10.9
23
+ - @backstage/integration@1.17.1
24
+ - @backstage/integration-react@1.2.9
25
+ - @backstage/plugin-scaffolder-common@1.6.0
26
+ - @backstage/core-compat-api@0.4.4
27
+ - @backstage/frontend-plugin-api@0.10.4
28
+ - @backstage/plugin-catalog-common@1.1.5
29
+ - @backstage/plugin-permission-react@0.4.36
30
+
31
+ ## 1.33.0-next.2
32
+
33
+ ### Minor Changes
34
+
35
+ - c1ce316: BREAKING `/alpha`: Converted `scaffolder.task.read` and `scaffolder.task.cancel` into Resource Permissions.
36
+
37
+ BREAKING `/alpha`: Added a new scaffolder rule `isTaskOwner` for `scaffolder.task.read` and `scaffolder.task.cancel` to allow for conditional permission policies such as restricting access to tasks and task events based on task creators.
38
+
39
+ BREAKING `/alpha`: Retrying a task now requires both `scaffolder.task.read` and `scaffolder.task.create` permissions, replacing the previous requirement of `scaffolder.task.read` and `scaffolder.task.cancel`.
40
+
41
+ ### Patch Changes
42
+
43
+ - Updated dependencies
44
+ - @backstage/plugin-scaffolder-react@1.18.0-next.2
45
+ - @backstage/core-components@0.17.4-next.2
46
+ - @backstage/plugin-scaffolder-common@1.6.0-next.1
47
+ - @backstage/core-compat-api@0.4.4-next.1
48
+ - @backstage/core-plugin-api@1.10.9-next.0
49
+ - @backstage/plugin-catalog-react@1.19.1-next.1
50
+
3
51
  ## 1.32.1-next.1
4
52
 
5
53
  ### Patch Changes
@@ -1,4 +1,4 @@
1
- import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
2
  import { Page, Header, Content, Progress, ErrorPanel, EmptyState, Table, Link } from '@backstage/core-components';
3
3
  import { useRouteRef, useApi } from '@backstage/core-plugin-api';
4
4
  import { CatalogFilterLayout } from '@backstage/plugin-catalog-react';
@@ -41,16 +41,25 @@ const ListTaskPageContent = (props) => {
41
41
  return /* @__PURE__ */ jsx(Progress, {});
42
42
  }
43
43
  if (error) {
44
- return /* @__PURE__ */ jsxs(Fragment, { children: [
45
- /* @__PURE__ */ jsx(ErrorPanel, { error }),
46
- /* @__PURE__ */ jsx(
47
- EmptyState,
44
+ return /* @__PURE__ */ jsxs(CatalogFilterLayout, { children: [
45
+ /* @__PURE__ */ jsx(CatalogFilterLayout.Filters, { children: /* @__PURE__ */ jsx(
46
+ OwnerListPicker,
48
47
  {
49
- missing: "info",
50
- title: t("listTaskPage.content.emptyState.title"),
51
- description: t("listTaskPage.content.emptyState.description")
48
+ filter: ownerFilter,
49
+ onSelectOwner: (id) => setOwnerFilter(id)
52
50
  }
53
- )
51
+ ) }),
52
+ /* @__PURE__ */ jsxs(CatalogFilterLayout.Content, { children: [
53
+ /* @__PURE__ */ jsx(ErrorPanel, { error }),
54
+ /* @__PURE__ */ jsx(
55
+ EmptyState,
56
+ {
57
+ missing: "info",
58
+ title: t("listTaskPage.content.emptyState.title"),
59
+ description: t("listTaskPage.content.emptyState.description")
60
+ }
61
+ )
62
+ ] })
54
63
  ] });
55
64
  }
56
65
  return /* @__PURE__ */ jsxs(CatalogFilterLayout, { children: [
@@ -1 +1 @@
1
- {"version":3,"file":"ListTasksPage.esm.js","sources":["../../../src/components/ListTasksPage/ListTasksPage.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 {\n Content,\n EmptyState,\n ErrorPanel,\n Header,\n Link,\n Page,\n Progress,\n Table,\n} from '@backstage/core-components';\nimport { useApi, useRouteRef } from '@backstage/core-plugin-api';\nimport { CatalogFilterLayout } from '@backstage/plugin-catalog-react';\nimport useAsync from 'react-use/esm/useAsync';\nimport { useState } from 'react';\nimport {\n scaffolderApiRef,\n ScaffolderTask,\n} from '@backstage/plugin-scaffolder-react';\nimport { OwnerListPicker } from './OwnerListPicker';\nimport {\n CreatedAtColumn,\n OwnerEntityColumn,\n TaskStatusColumn,\n TemplateTitleColumn,\n} from './columns';\nimport {\n actionsRouteRef,\n editRouteRef,\n rootRouteRef,\n templatingExtensionsRouteRef,\n} from '../../routes';\nimport { ScaffolderPageContextMenu } from '@backstage/plugin-scaffolder-react/alpha';\nimport { useNavigate } from 'react-router-dom';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport { scaffolderTranslationRef } from '../../translation';\n\nexport interface MyTaskPageProps {\n initiallySelectedFilter?: 'owned' | 'all';\n contextMenu?: {\n editor?: boolean;\n actions?: boolean;\n create?: boolean;\n };\n}\n\nconst ListTaskPageContent = (props: MyTaskPageProps) => {\n const { initiallySelectedFilter = 'owned' } = props;\n const { t } = useTranslationRef(scaffolderTranslationRef);\n const [limit, setLimit] = useState(5);\n const [page, setPage] = useState(0);\n\n const scaffolderApi = useApi(scaffolderApiRef);\n const rootLink = useRouteRef(rootRouteRef);\n\n const [ownerFilter, setOwnerFilter] = useState(initiallySelectedFilter);\n const { value, loading, error } = useAsync(() => {\n if (scaffolderApi.listTasks) {\n return scaffolderApi.listTasks?.({\n filterByOwnership: ownerFilter,\n limit,\n offset: page * limit,\n });\n }\n\n // eslint-disable-next-line no-console\n console.warn(\n 'listTasks is not implemented in the scaffolderApi, please make sure to implement this method.',\n );\n\n return Promise.resolve({ tasks: [], totalTasks: 0 });\n }, [scaffolderApi, ownerFilter, limit, page]);\n\n if (loading) {\n return <Progress />;\n }\n\n if (error) {\n return (\n <>\n <ErrorPanel error={error} />\n <EmptyState\n missing=\"info\"\n title={t('listTaskPage.content.emptyState.title')}\n description={t('listTaskPage.content.emptyState.description')}\n />\n </>\n );\n }\n\n return (\n <CatalogFilterLayout>\n <CatalogFilterLayout.Filters>\n <OwnerListPicker\n filter={ownerFilter}\n onSelectOwner={id => setOwnerFilter(id)}\n />\n </CatalogFilterLayout.Filters>\n <CatalogFilterLayout.Content>\n <Table<ScaffolderTask>\n onRowsPerPageChange={pageSize => {\n setPage(0);\n setLimit(pageSize);\n }}\n onPageChange={newPage => setPage(newPage)}\n options={{ pageSize: limit, emptyRowsWhenPaging: false }}\n data={value?.tasks ?? []}\n page={page}\n totalCount={value?.totalTasks ?? 0}\n title={t('listTaskPage.content.tableTitle')}\n columns={[\n {\n title: t('listTaskPage.content.tableCell.taskID'),\n field: 'id',\n render: row => (\n <Link to={`${rootLink()}/tasks/${row.id}`}>{row.id}</Link>\n ),\n },\n {\n title: t('listTaskPage.content.tableCell.template'),\n field: 'spec.templateInfo.entity.metadata.title',\n render: row => (\n <TemplateTitleColumn\n entityRef={row.spec.templateInfo?.entityRef}\n />\n ),\n },\n {\n title: t('listTaskPage.content.tableCell.created'),\n field: 'createdAt',\n render: row => <CreatedAtColumn createdAt={row.createdAt} />,\n },\n {\n title: t('listTaskPage.content.tableCell.owner'),\n field: 'createdBy',\n render: row => (\n <OwnerEntityColumn entityRef={row.spec?.user?.ref} />\n ),\n },\n {\n title: t('listTaskPage.content.tableCell.status'),\n field: 'status',\n render: row => <TaskStatusColumn status={row.status} />,\n },\n ]}\n />\n </CatalogFilterLayout.Content>\n </CatalogFilterLayout>\n );\n};\n\nexport const ListTasksPage = (props: MyTaskPageProps) => {\n const navigate = useNavigate();\n const editorLink = useRouteRef(editRouteRef);\n const actionsLink = useRouteRef(actionsRouteRef);\n const createLink = useRouteRef(rootRouteRef);\n const { t } = useTranslationRef(scaffolderTranslationRef);\n const templatingExtensionsLink = useRouteRef(templatingExtensionsRouteRef);\n\n const scaffolderPageContextMenuProps = {\n onEditorClicked:\n props?.contextMenu?.editor !== false\n ? () => navigate(editorLink())\n : undefined,\n onActionsClicked:\n props?.contextMenu?.actions !== false\n ? () => navigate(actionsLink())\n : undefined,\n onTasksClicked: undefined,\n onCreateClicked:\n props?.contextMenu?.create !== false\n ? () => navigate(createLink())\n : undefined,\n onTemplatingExtensionsClicked: () => navigate(templatingExtensionsLink()),\n };\n return (\n <Page themeId=\"home\">\n <Header\n pageTitleOverride={t('listTaskPage.pageTitle')}\n title={t('listTaskPage.title')}\n subtitle={t('listTaskPage.subtitle')}\n >\n <ScaffolderPageContextMenu {...scaffolderPageContextMenuProps} />\n </Header>\n <Content>\n <ListTaskPageContent {...props} />\n </Content>\n </Page>\n );\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ListTasksPage.esm.js","sources":["../../../src/components/ListTasksPage/ListTasksPage.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 {\n Content,\n EmptyState,\n ErrorPanel,\n Header,\n Link,\n Page,\n Progress,\n Table,\n} from '@backstage/core-components';\nimport { useApi, useRouteRef } from '@backstage/core-plugin-api';\nimport { CatalogFilterLayout } from '@backstage/plugin-catalog-react';\nimport useAsync from 'react-use/esm/useAsync';\nimport { useState } from 'react';\nimport {\n scaffolderApiRef,\n ScaffolderTask,\n} from '@backstage/plugin-scaffolder-react';\nimport { OwnerListPicker } from './OwnerListPicker';\nimport {\n CreatedAtColumn,\n OwnerEntityColumn,\n TaskStatusColumn,\n TemplateTitleColumn,\n} from './columns';\nimport {\n actionsRouteRef,\n editRouteRef,\n rootRouteRef,\n templatingExtensionsRouteRef,\n} from '../../routes';\nimport { ScaffolderPageContextMenu } from '@backstage/plugin-scaffolder-react/alpha';\nimport { useNavigate } from 'react-router-dom';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport { scaffolderTranslationRef } from '../../translation';\n\nexport interface MyTaskPageProps {\n initiallySelectedFilter?: 'owned' | 'all';\n contextMenu?: {\n editor?: boolean;\n actions?: boolean;\n create?: boolean;\n };\n}\n\nconst ListTaskPageContent = (props: MyTaskPageProps) => {\n const { initiallySelectedFilter = 'owned' } = props;\n const { t } = useTranslationRef(scaffolderTranslationRef);\n const [limit, setLimit] = useState(5);\n const [page, setPage] = useState(0);\n\n const scaffolderApi = useApi(scaffolderApiRef);\n const rootLink = useRouteRef(rootRouteRef);\n\n const [ownerFilter, setOwnerFilter] = useState(initiallySelectedFilter);\n const { value, loading, error } = useAsync(() => {\n if (scaffolderApi.listTasks) {\n return scaffolderApi.listTasks?.({\n filterByOwnership: ownerFilter,\n limit,\n offset: page * limit,\n });\n }\n\n // eslint-disable-next-line no-console\n console.warn(\n 'listTasks is not implemented in the scaffolderApi, please make sure to implement this method.',\n );\n\n return Promise.resolve({ tasks: [], totalTasks: 0 });\n }, [scaffolderApi, ownerFilter, limit, page]);\n\n if (loading) {\n return <Progress />;\n }\n\n if (error) {\n return (\n <CatalogFilterLayout>\n <CatalogFilterLayout.Filters>\n <OwnerListPicker\n filter={ownerFilter}\n onSelectOwner={id => setOwnerFilter(id)}\n />\n </CatalogFilterLayout.Filters>\n <CatalogFilterLayout.Content>\n <ErrorPanel error={error} />\n <EmptyState\n missing=\"info\"\n title={t('listTaskPage.content.emptyState.title')}\n description={t('listTaskPage.content.emptyState.description')}\n />\n </CatalogFilterLayout.Content>\n </CatalogFilterLayout>\n );\n }\n\n return (\n <CatalogFilterLayout>\n <CatalogFilterLayout.Filters>\n <OwnerListPicker\n filter={ownerFilter}\n onSelectOwner={id => setOwnerFilter(id)}\n />\n </CatalogFilterLayout.Filters>\n <CatalogFilterLayout.Content>\n <Table<ScaffolderTask>\n onRowsPerPageChange={pageSize => {\n setPage(0);\n setLimit(pageSize);\n }}\n onPageChange={newPage => setPage(newPage)}\n options={{ pageSize: limit, emptyRowsWhenPaging: false }}\n data={value?.tasks ?? []}\n page={page}\n totalCount={value?.totalTasks ?? 0}\n title={t('listTaskPage.content.tableTitle')}\n columns={[\n {\n title: t('listTaskPage.content.tableCell.taskID'),\n field: 'id',\n render: row => (\n <Link to={`${rootLink()}/tasks/${row.id}`}>{row.id}</Link>\n ),\n },\n {\n title: t('listTaskPage.content.tableCell.template'),\n field: 'spec.templateInfo.entity.metadata.title',\n render: row => (\n <TemplateTitleColumn\n entityRef={row.spec.templateInfo?.entityRef}\n />\n ),\n },\n {\n title: t('listTaskPage.content.tableCell.created'),\n field: 'createdAt',\n render: row => <CreatedAtColumn createdAt={row.createdAt} />,\n },\n {\n title: t('listTaskPage.content.tableCell.owner'),\n field: 'createdBy',\n render: row => (\n <OwnerEntityColumn entityRef={row.spec?.user?.ref} />\n ),\n },\n {\n title: t('listTaskPage.content.tableCell.status'),\n field: 'status',\n render: row => <TaskStatusColumn status={row.status} />,\n },\n ]}\n />\n </CatalogFilterLayout.Content>\n </CatalogFilterLayout>\n );\n};\n\nexport const ListTasksPage = (props: MyTaskPageProps) => {\n const navigate = useNavigate();\n const editorLink = useRouteRef(editRouteRef);\n const actionsLink = useRouteRef(actionsRouteRef);\n const createLink = useRouteRef(rootRouteRef);\n const { t } = useTranslationRef(scaffolderTranslationRef);\n const templatingExtensionsLink = useRouteRef(templatingExtensionsRouteRef);\n\n const scaffolderPageContextMenuProps = {\n onEditorClicked:\n props?.contextMenu?.editor !== false\n ? () => navigate(editorLink())\n : undefined,\n onActionsClicked:\n props?.contextMenu?.actions !== false\n ? () => navigate(actionsLink())\n : undefined,\n onTasksClicked: undefined,\n onCreateClicked:\n props?.contextMenu?.create !== false\n ? () => navigate(createLink())\n : undefined,\n onTemplatingExtensionsClicked: () => navigate(templatingExtensionsLink()),\n };\n return (\n <Page themeId=\"home\">\n <Header\n pageTitleOverride={t('listTaskPage.pageTitle')}\n title={t('listTaskPage.title')}\n subtitle={t('listTaskPage.subtitle')}\n >\n <ScaffolderPageContextMenu {...scaffolderPageContextMenuProps} />\n </Header>\n <Content>\n <ListTaskPageContent {...props} />\n </Content>\n </Page>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -33,7 +33,8 @@ const ContextMenu = (props) => {
33
33
  onRetry,
34
34
  onStartOver,
35
35
  onToggleLogs,
36
- onToggleButtonBar
36
+ onToggleButtonBar,
37
+ taskId
37
38
  } = props;
38
39
  const { getPageTheme } = useTheme();
39
40
  const pageTheme = getPageTheme({ themeId: "website" });
@@ -41,7 +42,8 @@ const ContextMenu = (props) => {
41
42
  const [anchorEl, setAnchorEl] = useState();
42
43
  const { t } = useTranslationRef(scaffolderTranslationRef);
43
44
  const { allowed: canReadTask } = usePermission({
44
- permission: taskReadPermission
45
+ permission: taskReadPermission,
46
+ resourceRef: taskId
45
47
  });
46
48
  const { allowed: canCreateTask } = usePermission({
47
49
  permission: taskCreatePermission
@@ -1 +1 @@
1
- {"version":3,"file":"ContextMenu.esm.js","sources":["../../../src/components/OngoingTask/ContextMenu.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 */\n\nimport IconButton from '@material-ui/core/IconButton';\nimport ListItemIcon from '@material-ui/core/ListItemIcon';\nimport ListItemText from '@material-ui/core/ListItemText';\nimport MenuItem from '@material-ui/core/MenuItem';\nimport MenuList from '@material-ui/core/MenuList';\nimport Popover from '@material-ui/core/Popover';\nimport { makeStyles, Theme, useTheme } from '@material-ui/core/styles';\nimport Cancel from '@material-ui/icons/Cancel';\nimport Repeat from '@material-ui/icons/Repeat';\nimport Replay from '@material-ui/icons/Replay';\nimport Toc from '@material-ui/icons/Toc';\nimport ControlPointIcon from '@material-ui/icons/ControlPoint';\nimport MoreVert from '@material-ui/icons/MoreVert';\nimport { SyntheticEvent, useState } from 'react';\nimport { usePermission } from '@backstage/plugin-permission-react';\nimport {\n taskReadPermission,\n taskCreatePermission,\n} from '@backstage/plugin-scaffolder-common/alpha';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport { scaffolderTranslationRef } from '../../translation';\n\ntype ContextMenuProps = {\n cancelEnabled?: boolean;\n canRetry: boolean;\n isRetryableTask: boolean;\n logsVisible?: boolean;\n buttonBarVisible?: boolean;\n onRetry?: () => void;\n onStartOver?: () => void;\n onToggleLogs?: (state: boolean) => void;\n onToggleButtonBar?: (state: boolean) => void;\n isCancelButtonDisabled: boolean;\n onCancel: () => void;\n};\n\nconst useStyles = makeStyles<Theme, { fontColor: string }>(() => ({\n button: {\n color: ({ fontColor }) => fontColor,\n },\n}));\n\nexport const ContextMenu = (props: ContextMenuProps) => {\n const {\n cancelEnabled,\n canRetry,\n isRetryableTask,\n logsVisible,\n buttonBarVisible,\n onRetry,\n onStartOver,\n onToggleLogs,\n onToggleButtonBar,\n } = props;\n const { getPageTheme } = useTheme();\n const pageTheme = getPageTheme({ themeId: 'website' });\n const classes = useStyles({ fontColor: pageTheme.fontColor });\n const [anchorEl, setAnchorEl] = useState<HTMLButtonElement>();\n const { t } = useTranslationRef(scaffolderTranslationRef);\n\n const { allowed: canReadTask } = usePermission({\n permission: taskReadPermission,\n });\n\n const { allowed: canCreateTask } = usePermission({\n permission: taskCreatePermission,\n });\n\n // Start Over endpoint requires user to have both read (to grab parameters) and create (to create new task) permissions\n const canStartOver = canReadTask && canCreateTask;\n\n return (\n <>\n <IconButton\n aria-label=\"more\"\n aria-controls=\"long-menu\"\n aria-haspopup=\"true\"\n onClick={(event: SyntheticEvent<HTMLButtonElement>) => {\n setAnchorEl(event.currentTarget);\n }}\n data-testid=\"menu-button\"\n className={classes.button}\n >\n <MoreVert />\n </IconButton>\n <Popover\n open={Boolean(anchorEl)}\n onClose={() => setAnchorEl(undefined)}\n anchorEl={anchorEl}\n anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}\n transformOrigin={{ vertical: 'top', horizontal: 'right' }}\n >\n <MenuList>\n <MenuItem onClick={() => onToggleLogs?.(!logsVisible)}>\n <ListItemIcon>\n <Toc fontSize=\"small\" />\n </ListItemIcon>\n <ListItemText\n primary={\n logsVisible\n ? t('ongoingTask.contextMenu.hideLogs')\n : t('ongoingTask.contextMenu.showLogs')\n }\n />\n </MenuItem>\n <MenuItem onClick={() => onToggleButtonBar?.(!buttonBarVisible)}>\n <ListItemIcon>\n <ControlPointIcon fontSize=\"small\" />\n </ListItemIcon>\n <ListItemText\n primary={\n buttonBarVisible\n ? t('ongoingTask.contextMenu.hideButtonBar')\n : t('ongoingTask.contextMenu.showButtonBar')\n }\n />\n </MenuItem>\n <MenuItem\n onClick={onStartOver}\n disabled={cancelEnabled || !canStartOver}\n data-testid=\"start-over-task\"\n >\n <ListItemIcon>\n <Repeat fontSize=\"small\" />\n </ListItemIcon>\n <ListItemText primary={t('ongoingTask.contextMenu.startOver')} />\n </MenuItem>\n {isRetryableTask && (\n <MenuItem\n onClick={onRetry}\n disabled={cancelEnabled || !canRetry}\n data-testid=\"retry-task\"\n >\n <ListItemIcon>\n <Replay fontSize=\"small\" />\n </ListItemIcon>\n <ListItemText primary={t('ongoingTask.contextMenu.retry')} />\n </MenuItem>\n )}\n <MenuItem\n onClick={props.onCancel}\n disabled={props.isCancelButtonDisabled}\n data-testid=\"cancel-task\"\n >\n <ListItemIcon>\n <Cancel fontSize=\"small\" />\n </ListItemIcon>\n <ListItemText primary={t('ongoingTask.contextMenu.cancel')} />\n </MenuItem>\n </MenuList>\n </Popover>\n </>\n );\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ContextMenu.esm.js","sources":["../../../src/components/OngoingTask/ContextMenu.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 */\n\nimport IconButton from '@material-ui/core/IconButton';\nimport ListItemIcon from '@material-ui/core/ListItemIcon';\nimport ListItemText from '@material-ui/core/ListItemText';\nimport MenuItem from '@material-ui/core/MenuItem';\nimport MenuList from '@material-ui/core/MenuList';\nimport Popover from '@material-ui/core/Popover';\nimport { makeStyles, Theme, useTheme } from '@material-ui/core/styles';\nimport Cancel from '@material-ui/icons/Cancel';\nimport Repeat from '@material-ui/icons/Repeat';\nimport Replay from '@material-ui/icons/Replay';\nimport Toc from '@material-ui/icons/Toc';\nimport ControlPointIcon from '@material-ui/icons/ControlPoint';\nimport MoreVert from '@material-ui/icons/MoreVert';\nimport { SyntheticEvent, useState } from 'react';\nimport { usePermission } from '@backstage/plugin-permission-react';\nimport {\n taskReadPermission,\n taskCreatePermission,\n} from '@backstage/plugin-scaffolder-common/alpha';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport { scaffolderTranslationRef } from '../../translation';\n\ntype ContextMenuProps = {\n cancelEnabled?: boolean;\n canRetry: boolean;\n isRetryableTask: boolean;\n logsVisible?: boolean;\n buttonBarVisible?: boolean;\n onRetry?: () => void;\n onStartOver?: () => void;\n onToggleLogs?: (state: boolean) => void;\n onToggleButtonBar?: (state: boolean) => void;\n taskId?: string;\n isCancelButtonDisabled: boolean;\n onCancel: () => void;\n};\n\nconst useStyles = makeStyles<Theme, { fontColor: string }>(() => ({\n button: {\n color: ({ fontColor }) => fontColor,\n },\n}));\n\nexport const ContextMenu = (props: ContextMenuProps) => {\n const {\n cancelEnabled,\n canRetry,\n isRetryableTask,\n logsVisible,\n buttonBarVisible,\n onRetry,\n onStartOver,\n onToggleLogs,\n onToggleButtonBar,\n taskId,\n } = props;\n const { getPageTheme } = useTheme();\n const pageTheme = getPageTheme({ themeId: 'website' });\n const classes = useStyles({ fontColor: pageTheme.fontColor });\n const [anchorEl, setAnchorEl] = useState<HTMLButtonElement>();\n const { t } = useTranslationRef(scaffolderTranslationRef);\n\n const { allowed: canReadTask } = usePermission({\n permission: taskReadPermission,\n resourceRef: taskId,\n });\n\n const { allowed: canCreateTask } = usePermission({\n permission: taskCreatePermission,\n });\n\n // Start Over endpoint requires user to have both read (to grab parameters) and create (to create new task) permissions\n const canStartOver = canReadTask && canCreateTask;\n\n return (\n <>\n <IconButton\n aria-label=\"more\"\n aria-controls=\"long-menu\"\n aria-haspopup=\"true\"\n onClick={(event: SyntheticEvent<HTMLButtonElement>) => {\n setAnchorEl(event.currentTarget);\n }}\n data-testid=\"menu-button\"\n className={classes.button}\n >\n <MoreVert />\n </IconButton>\n <Popover\n open={Boolean(anchorEl)}\n onClose={() => setAnchorEl(undefined)}\n anchorEl={anchorEl}\n anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}\n transformOrigin={{ vertical: 'top', horizontal: 'right' }}\n >\n <MenuList>\n <MenuItem onClick={() => onToggleLogs?.(!logsVisible)}>\n <ListItemIcon>\n <Toc fontSize=\"small\" />\n </ListItemIcon>\n <ListItemText\n primary={\n logsVisible\n ? t('ongoingTask.contextMenu.hideLogs')\n : t('ongoingTask.contextMenu.showLogs')\n }\n />\n </MenuItem>\n <MenuItem onClick={() => onToggleButtonBar?.(!buttonBarVisible)}>\n <ListItemIcon>\n <ControlPointIcon fontSize=\"small\" />\n </ListItemIcon>\n <ListItemText\n primary={\n buttonBarVisible\n ? t('ongoingTask.contextMenu.hideButtonBar')\n : t('ongoingTask.contextMenu.showButtonBar')\n }\n />\n </MenuItem>\n <MenuItem\n onClick={onStartOver}\n disabled={cancelEnabled || !canStartOver}\n data-testid=\"start-over-task\"\n >\n <ListItemIcon>\n <Repeat fontSize=\"small\" />\n </ListItemIcon>\n <ListItemText primary={t('ongoingTask.contextMenu.startOver')} />\n </MenuItem>\n {isRetryableTask && (\n <MenuItem\n onClick={onRetry}\n disabled={cancelEnabled || !canRetry}\n data-testid=\"retry-task\"\n >\n <ListItemIcon>\n <Replay fontSize=\"small\" />\n </ListItemIcon>\n <ListItemText primary={t('ongoingTask.contextMenu.retry')} />\n </MenuItem>\n )}\n <MenuItem\n onClick={props.onCancel}\n disabled={props.isCancelButtonDisabled}\n data-testid=\"cancel-task\"\n >\n <ListItemIcon>\n <Cancel fontSize=\"small\" />\n </ListItemIcon>\n <ListItemText primary={t('ongoingTask.contextMenu.cancel')} />\n </MenuItem>\n </MenuList>\n </Popover>\n </>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -80,10 +80,12 @@ function OngoingTaskContent(props) {
80
80
  const [logsVisible, setLogVisibleState] = useState(false);
81
81
  const [buttonBarVisible, setButtonBarVisibleState] = useState(true);
82
82
  const { allowed: canCancelTask } = usePermission({
83
- permission: taskCancelPermission
83
+ permission: taskCancelPermission,
84
+ resourceRef: taskId
84
85
  });
85
86
  const { allowed: canReadTask } = usePermission({
86
- permission: taskReadPermission
87
+ permission: taskReadPermission,
88
+ resourceRef: taskId
87
89
  });
88
90
  const { allowed: canCreateTask } = usePermission({
89
91
  permission: taskCreatePermission
@@ -180,6 +182,7 @@ function OngoingTaskContent(props) {
180
182
  onRetry: triggerRetry,
181
183
  onToggleLogs: setLogVisibleState,
182
184
  onToggleButtonBar: setButtonBarVisibleState,
185
+ taskId,
183
186
  onCancel: triggerCancel,
184
187
  isCancelButtonDisabled
185
188
  }
@@ -1 +1 @@
1
- {"version":3,"file":"OngoingTask.esm.js","sources":["../../../src/components/OngoingTask/OngoingTask.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 {\n ComponentType,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from 'react';\nimport { Content, ErrorPanel, Header, Page } from '@backstage/core-components';\nimport { useNavigate, useParams } from 'react-router-dom';\nimport Box from '@material-ui/core/Box';\nimport Button from '@material-ui/core/Button';\nimport Paper from '@material-ui/core/Paper';\nimport { makeStyles } from '@material-ui/core/styles';\nimport {\n scaffolderApiRef,\n ScaffolderTaskOutput,\n useTaskEventStream,\n} from '@backstage/plugin-scaffolder-react';\nimport { selectedTemplateRouteRef } from '../../routes';\nimport {\n AnalyticsContext,\n useAnalytics,\n useApi,\n useRouteRef,\n} from '@backstage/core-plugin-api';\nimport qs from 'qs';\nimport { ContextMenu } from './ContextMenu';\nimport {\n DefaultTemplateOutputs,\n TaskLogStream,\n TaskSteps,\n} from '@backstage/plugin-scaffolder-react/alpha';\nimport { useAsync } from '@react-hookz/web';\nimport { usePermission } from '@backstage/plugin-permission-react';\nimport {\n taskCancelPermission,\n taskCreatePermission,\n taskReadPermission,\n} from '@backstage/plugin-scaffolder-common/alpha';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport { scaffolderTranslationRef } from '../../translation';\nimport { entityPresentationApiRef } from '@backstage/plugin-catalog-react';\nimport { default as reactUseAsync } from 'react-use/esm/useAsync';\nimport { stringifyEntityRef } from '@backstage/catalog-model';\n\nconst useStyles = makeStyles(theme => ({\n contentWrapper: {\n display: 'flex',\n flexDirection: 'column',\n },\n buttonBar: {\n display: 'flex',\n flexDirection: 'row',\n justifyContent: 'right',\n },\n cancelButton: {\n marginRight: theme.spacing(1),\n },\n retryButton: {\n marginRight: theme.spacing(1),\n },\n logsVisibilityButton: {\n marginRight: theme.spacing(1),\n },\n}));\n\n/**\n * @public\n */\nexport const OngoingTask = (props: {\n TemplateOutputsComponent?: ComponentType<{\n output?: ScaffolderTaskOutput;\n }>;\n}) => {\n // todo(blam): check that task Id actually exists, and that it's valid. otherwise redirect to something more useful.\n const { taskId } = useParams();\n const taskStream = useTaskEventStream(taskId!);\n const { namespace, name } =\n taskStream.task?.spec.templateInfo?.entity?.metadata ?? {};\n\n return (\n <AnalyticsContext\n attributes={{\n entityRef:\n name &&\n stringifyEntityRef({\n kind: 'template',\n namespace,\n name,\n }),\n taskId,\n }}\n >\n <Page themeId=\"website\">\n <OngoingTaskContent {...props} />\n </Page>\n </AnalyticsContext>\n );\n};\n\nfunction OngoingTaskContent(props: {\n TemplateOutputsComponent?: ComponentType<{\n output?: ScaffolderTaskOutput;\n }>;\n}) {\n const { taskId } = useParams();\n const templateRouteRef = useRouteRef(selectedTemplateRouteRef);\n const navigate = useNavigate();\n const analytics = useAnalytics();\n const scaffolderApi = useApi(scaffolderApiRef);\n const entityPresentationApi = useApi(entityPresentationApiRef);\n const taskStream = useTaskEventStream(taskId!);\n const classes = useStyles();\n const steps = useMemo(\n () =>\n taskStream.task?.spec.steps.map(step => ({\n ...step,\n ...taskStream?.steps?.[step.id],\n })) ?? [],\n [taskStream],\n );\n const { t } = useTranslationRef(scaffolderTranslationRef);\n\n const [logsVisible, setLogVisibleState] = useState(false);\n const [buttonBarVisible, setButtonBarVisibleState] = useState(true);\n\n // Used dummy string value for `resourceRef` since `allowed` field will always return `false` if `resourceRef` is `undefined`\n const { allowed: canCancelTask } = usePermission({\n permission: taskCancelPermission,\n });\n\n const { allowed: canReadTask } = usePermission({\n permission: taskReadPermission,\n });\n\n const { allowed: canCreateTask } = usePermission({\n permission: taskCreatePermission,\n });\n\n // Start Over endpoint requires user to have both read (to grab parameters) and create (to create new task) permissions\n const canStartOver = canReadTask && canCreateTask;\n\n useEffect(() => {\n if (taskStream.error) {\n setLogVisibleState(true);\n }\n }, [taskStream.error]);\n\n useEffect(() => {\n if (taskStream.completed && !taskStream.error) {\n setLogVisibleState(true);\n setButtonBarVisibleState(false);\n }\n }, [taskStream.error, taskStream.completed]);\n\n const { value: presentation } = reactUseAsync(async () => {\n const templateEntityRef = taskStream.task?.spec.templateInfo?.entityRef;\n if (!templateEntityRef) {\n return undefined;\n }\n return entityPresentationApi.forEntity(templateEntityRef).promise;\n }, [entityPresentationApi, taskStream.task?.spec.templateInfo?.entityRef]);\n\n const activeStep = useMemo(() => {\n for (let i = steps.length - 1; i >= 0; i--) {\n if (steps[i].status !== 'open') {\n return i;\n }\n }\n\n return 0;\n }, [steps]);\n\n const isRetryableTask =\n taskStream.task?.spec.EXPERIMENTAL_recovery?.EXPERIMENTAL_strategy ===\n 'startOver';\n\n const canRetry = canReadTask && canCreateTask && isRetryableTask;\n\n const startOver = useCallback(() => {\n const { namespace, name } =\n taskStream.task?.spec.templateInfo?.entity?.metadata ?? {};\n\n const formData = taskStream.task?.spec.parameters ?? {};\n\n if (!namespace || !name) {\n return;\n }\n\n analytics.captureEvent('click', `Task has been started over`);\n\n navigate({\n pathname: templateRouteRef({\n namespace,\n templateName: name,\n }),\n search: `?${qs.stringify({ formData: JSON.stringify(formData) })}`,\n });\n }, [\n analytics,\n navigate,\n taskStream.task?.spec.parameters,\n taskStream.task?.spec.templateInfo?.entity?.metadata,\n templateRouteRef,\n ]);\n\n const [, { execute: triggerRetry }] = useAsync(async () => {\n if (taskId) {\n analytics.captureEvent('retried', 'Template has been retried');\n await scaffolderApi.retry?.(taskId);\n }\n });\n\n const [{ status: cancelStatus }, { execute: triggerCancel }] = useAsync(\n async () => {\n if (taskId) {\n analytics.captureEvent('cancelled', 'Template has been cancelled');\n await scaffolderApi.cancelTask(taskId);\n }\n },\n );\n\n const Outputs = props.TemplateOutputsComponent ?? DefaultTemplateOutputs;\n\n const cancelEnabled = !(taskStream.cancelled || taskStream.completed);\n const isCancelButtonDisabled =\n !cancelEnabled || cancelStatus !== 'not-executed' || !canCancelTask;\n\n return (\n <>\n <Header\n pageTitleOverride={\n presentation\n ? t('ongoingTask.pageTitle.hasTemplateName', {\n templateName: presentation.primaryTitle,\n })\n : t('ongoingTask.pageTitle.noTemplateName')\n }\n title={\n <div>\n {t('ongoingTask.title')}{' '}\n <code>{presentation ? presentation.primaryTitle : ''}</code>\n </div>\n }\n subtitle={t('ongoingTask.subtitle', { taskId: taskId as string })}\n >\n <ContextMenu\n cancelEnabled={cancelEnabled}\n canRetry={canRetry}\n isRetryableTask={isRetryableTask}\n logsVisible={logsVisible}\n buttonBarVisible={buttonBarVisible}\n onStartOver={startOver}\n onRetry={triggerRetry}\n onToggleLogs={setLogVisibleState}\n onToggleButtonBar={setButtonBarVisibleState}\n onCancel={triggerCancel}\n isCancelButtonDisabled={isCancelButtonDisabled}\n />\n </Header>\n <Content className={classes.contentWrapper}>\n {taskStream.error ? (\n <Box paddingBottom={2}>\n <ErrorPanel\n error={taskStream.error}\n titleFormat=\"markdown\"\n title={taskStream.error.message}\n />\n </Box>\n ) : null}\n\n <Box paddingBottom={2}>\n <TaskSteps\n steps={steps}\n activeStep={activeStep}\n isComplete={taskStream.completed}\n isError={Boolean(taskStream.error)}\n />\n </Box>\n\n <Outputs output={taskStream.output} />\n\n {buttonBarVisible ? (\n <Box paddingBottom={2}>\n <Paper>\n <Box padding={2}>\n <div className={classes.buttonBar}>\n <Button\n className={classes.cancelButton}\n disabled={\n !cancelEnabled ||\n (cancelStatus !== 'not-executed' && !isRetryableTask) ||\n !canCancelTask\n }\n onClick={triggerCancel}\n data-testid=\"cancel-button\"\n >\n {t('ongoingTask.cancelButtonTitle')}\n </Button>\n {isRetryableTask && (\n <Button\n className={classes.retryButton}\n disabled={cancelEnabled || !canRetry}\n onClick={triggerRetry}\n data-testid=\"retry-button\"\n >\n {t('ongoingTask.retryButtonTitle')}\n </Button>\n )}\n <Button\n className={classes.logsVisibilityButton}\n color=\"primary\"\n variant=\"outlined\"\n onClick={() => setLogVisibleState(!logsVisible)}\n >\n {logsVisible\n ? t('ongoingTask.hideLogsButtonTitle')\n : t('ongoingTask.showLogsButtonTitle')}\n </Button>\n <Button\n variant=\"contained\"\n color=\"primary\"\n disabled={cancelEnabled || !canStartOver}\n onClick={startOver}\n data-testid=\"start-over-button\"\n >\n {t('ongoingTask.startOverButtonTitle')}\n </Button>\n </div>\n </Box>\n </Paper>\n </Box>\n ) : null}\n\n {logsVisible ? (\n <Paper style={{ height: '100%' }}>\n <Box padding={2} height=\"100%\">\n <TaskLogStream logs={taskStream.stepLogs} />\n </Box>\n </Paper>\n ) : null}\n </Content>\n </>\n );\n}\n"],"names":["reactUseAsync","useAsync"],"mappings":"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"}
1
+ {"version":3,"file":"OngoingTask.esm.js","sources":["../../../src/components/OngoingTask/OngoingTask.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 {\n ComponentType,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from 'react';\nimport { Content, ErrorPanel, Header, Page } from '@backstage/core-components';\nimport { useNavigate, useParams } from 'react-router-dom';\nimport Box from '@material-ui/core/Box';\nimport Button from '@material-ui/core/Button';\nimport Paper from '@material-ui/core/Paper';\nimport { makeStyles } from '@material-ui/core/styles';\nimport {\n scaffolderApiRef,\n ScaffolderTaskOutput,\n useTaskEventStream,\n} from '@backstage/plugin-scaffolder-react';\nimport { selectedTemplateRouteRef } from '../../routes';\nimport {\n AnalyticsContext,\n useAnalytics,\n useApi,\n useRouteRef,\n} from '@backstage/core-plugin-api';\nimport qs from 'qs';\nimport { ContextMenu } from './ContextMenu';\nimport {\n DefaultTemplateOutputs,\n TaskLogStream,\n TaskSteps,\n} from '@backstage/plugin-scaffolder-react/alpha';\nimport { useAsync } from '@react-hookz/web';\nimport { usePermission } from '@backstage/plugin-permission-react';\nimport {\n taskCancelPermission,\n taskCreatePermission,\n taskReadPermission,\n} from '@backstage/plugin-scaffolder-common/alpha';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport { scaffolderTranslationRef } from '../../translation';\nimport { entityPresentationApiRef } from '@backstage/plugin-catalog-react';\nimport { default as reactUseAsync } from 'react-use/esm/useAsync';\nimport { stringifyEntityRef } from '@backstage/catalog-model';\n\nconst useStyles = makeStyles(theme => ({\n contentWrapper: {\n display: 'flex',\n flexDirection: 'column',\n },\n buttonBar: {\n display: 'flex',\n flexDirection: 'row',\n justifyContent: 'right',\n },\n cancelButton: {\n marginRight: theme.spacing(1),\n },\n retryButton: {\n marginRight: theme.spacing(1),\n },\n logsVisibilityButton: {\n marginRight: theme.spacing(1),\n },\n}));\n\n/**\n * @public\n */\nexport const OngoingTask = (props: {\n TemplateOutputsComponent?: ComponentType<{\n output?: ScaffolderTaskOutput;\n }>;\n}) => {\n // todo(blam): check that task Id actually exists, and that it's valid. otherwise redirect to something more useful.\n const { taskId } = useParams();\n const taskStream = useTaskEventStream(taskId!);\n const { namespace, name } =\n taskStream.task?.spec.templateInfo?.entity?.metadata ?? {};\n\n return (\n <AnalyticsContext\n attributes={{\n entityRef:\n name &&\n stringifyEntityRef({\n kind: 'template',\n namespace,\n name,\n }),\n taskId,\n }}\n >\n <Page themeId=\"website\">\n <OngoingTaskContent {...props} />\n </Page>\n </AnalyticsContext>\n );\n};\n\nfunction OngoingTaskContent(props: {\n TemplateOutputsComponent?: ComponentType<{\n output?: ScaffolderTaskOutput;\n }>;\n}) {\n const { taskId } = useParams();\n const templateRouteRef = useRouteRef(selectedTemplateRouteRef);\n const navigate = useNavigate();\n const analytics = useAnalytics();\n const scaffolderApi = useApi(scaffolderApiRef);\n const entityPresentationApi = useApi(entityPresentationApiRef);\n const taskStream = useTaskEventStream(taskId!);\n const classes = useStyles();\n const steps = useMemo(\n () =>\n taskStream.task?.spec.steps.map(step => ({\n ...step,\n ...taskStream?.steps?.[step.id],\n })) ?? [],\n [taskStream],\n );\n const { t } = useTranslationRef(scaffolderTranslationRef);\n\n const [logsVisible, setLogVisibleState] = useState(false);\n const [buttonBarVisible, setButtonBarVisibleState] = useState(true);\n\n const { allowed: canCancelTask } = usePermission({\n permission: taskCancelPermission,\n resourceRef: taskId,\n });\n\n const { allowed: canReadTask } = usePermission({\n permission: taskReadPermission,\n resourceRef: taskId,\n });\n\n const { allowed: canCreateTask } = usePermission({\n permission: taskCreatePermission,\n });\n\n // Start Over endpoint requires user to have both read (to grab parameters) and create (to create new task) permissions\n const canStartOver = canReadTask && canCreateTask;\n\n useEffect(() => {\n if (taskStream.error) {\n setLogVisibleState(true);\n }\n }, [taskStream.error]);\n\n useEffect(() => {\n if (taskStream.completed && !taskStream.error) {\n setLogVisibleState(true);\n setButtonBarVisibleState(false);\n }\n }, [taskStream.error, taskStream.completed]);\n\n const { value: presentation } = reactUseAsync(async () => {\n const templateEntityRef = taskStream.task?.spec.templateInfo?.entityRef;\n if (!templateEntityRef) {\n return undefined;\n }\n return entityPresentationApi.forEntity(templateEntityRef).promise;\n }, [entityPresentationApi, taskStream.task?.spec.templateInfo?.entityRef]);\n\n const activeStep = useMemo(() => {\n for (let i = steps.length - 1; i >= 0; i--) {\n if (steps[i].status !== 'open') {\n return i;\n }\n }\n\n return 0;\n }, [steps]);\n\n const isRetryableTask =\n taskStream.task?.spec.EXPERIMENTAL_recovery?.EXPERIMENTAL_strategy ===\n 'startOver';\n\n const canRetry = canReadTask && canCreateTask && isRetryableTask;\n\n const startOver = useCallback(() => {\n const { namespace, name } =\n taskStream.task?.spec.templateInfo?.entity?.metadata ?? {};\n\n const formData = taskStream.task?.spec.parameters ?? {};\n\n if (!namespace || !name) {\n return;\n }\n\n analytics.captureEvent('click', `Task has been started over`);\n\n navigate({\n pathname: templateRouteRef({\n namespace,\n templateName: name,\n }),\n search: `?${qs.stringify({ formData: JSON.stringify(formData) })}`,\n });\n }, [\n analytics,\n navigate,\n taskStream.task?.spec.parameters,\n taskStream.task?.spec.templateInfo?.entity?.metadata,\n templateRouteRef,\n ]);\n\n const [, { execute: triggerRetry }] = useAsync(async () => {\n if (taskId) {\n analytics.captureEvent('retried', 'Template has been retried');\n await scaffolderApi.retry?.(taskId);\n }\n });\n\n const [{ status: cancelStatus }, { execute: triggerCancel }] = useAsync(\n async () => {\n if (taskId) {\n analytics.captureEvent('cancelled', 'Template has been cancelled');\n await scaffolderApi.cancelTask(taskId);\n }\n },\n );\n\n const Outputs = props.TemplateOutputsComponent ?? DefaultTemplateOutputs;\n\n const cancelEnabled = !(taskStream.cancelled || taskStream.completed);\n const isCancelButtonDisabled =\n !cancelEnabled || cancelStatus !== 'not-executed' || !canCancelTask;\n\n return (\n <>\n <Header\n pageTitleOverride={\n presentation\n ? t('ongoingTask.pageTitle.hasTemplateName', {\n templateName: presentation.primaryTitle,\n })\n : t('ongoingTask.pageTitle.noTemplateName')\n }\n title={\n <div>\n {t('ongoingTask.title')}{' '}\n <code>{presentation ? presentation.primaryTitle : ''}</code>\n </div>\n }\n subtitle={t('ongoingTask.subtitle', { taskId: taskId as string })}\n >\n <ContextMenu\n cancelEnabled={cancelEnabled}\n canRetry={canRetry}\n isRetryableTask={isRetryableTask}\n logsVisible={logsVisible}\n buttonBarVisible={buttonBarVisible}\n onStartOver={startOver}\n onRetry={triggerRetry}\n onToggleLogs={setLogVisibleState}\n onToggleButtonBar={setButtonBarVisibleState}\n taskId={taskId}\n onCancel={triggerCancel}\n isCancelButtonDisabled={isCancelButtonDisabled}\n />\n </Header>\n <Content className={classes.contentWrapper}>\n {taskStream.error ? (\n <Box paddingBottom={2}>\n <ErrorPanel\n error={taskStream.error}\n titleFormat=\"markdown\"\n title={taskStream.error.message}\n />\n </Box>\n ) : null}\n\n <Box paddingBottom={2}>\n <TaskSteps\n steps={steps}\n activeStep={activeStep}\n isComplete={taskStream.completed}\n isError={Boolean(taskStream.error)}\n />\n </Box>\n\n <Outputs output={taskStream.output} />\n\n {buttonBarVisible ? (\n <Box paddingBottom={2}>\n <Paper>\n <Box padding={2}>\n <div className={classes.buttonBar}>\n <Button\n className={classes.cancelButton}\n disabled={\n !cancelEnabled ||\n (cancelStatus !== 'not-executed' && !isRetryableTask) ||\n !canCancelTask\n }\n onClick={triggerCancel}\n data-testid=\"cancel-button\"\n >\n {t('ongoingTask.cancelButtonTitle')}\n </Button>\n {isRetryableTask && (\n <Button\n className={classes.retryButton}\n disabled={cancelEnabled || !canRetry}\n onClick={triggerRetry}\n data-testid=\"retry-button\"\n >\n {t('ongoingTask.retryButtonTitle')}\n </Button>\n )}\n <Button\n className={classes.logsVisibilityButton}\n color=\"primary\"\n variant=\"outlined\"\n onClick={() => setLogVisibleState(!logsVisible)}\n >\n {logsVisible\n ? t('ongoingTask.hideLogsButtonTitle')\n : t('ongoingTask.showLogsButtonTitle')}\n </Button>\n <Button\n variant=\"contained\"\n color=\"primary\"\n disabled={cancelEnabled || !canStartOver}\n onClick={startOver}\n data-testid=\"start-over-button\"\n >\n {t('ongoingTask.startOverButtonTitle')}\n </Button>\n </div>\n </Box>\n </Paper>\n </Box>\n ) : null}\n\n {logsVisible ? (\n <Paper style={{ height: '100%' }}>\n <Box padding={2} height=\"100%\">\n <TaskLogStream logs={taskStream.stepLogs} />\n </Box>\n </Paper>\n ) : null}\n </Content>\n </>\n );\n}\n"],"names":["reactUseAsync","useAsync"],"mappings":"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"}
@@ -13,7 +13,7 @@ import { TemplateFormPage } from '../../alpha/components/TemplateEditorPage/Temp
13
13
  import { TemplateIntroPage } from '../../alpha/components/TemplateEditorPage/TemplateIntroPage.esm.js';
14
14
  import { CustomFieldsPage } from '../../alpha/components/TemplateEditorPage/CustomFieldsPage.esm.js';
15
15
  import { RequirePermission } from '@backstage/plugin-permission-react';
16
- import { taskReadPermission, templateManagementPermission } from '@backstage/plugin-scaffolder-common/alpha';
16
+ import { templateManagementPermission } from '@backstage/plugin-scaffolder-common/alpha';
17
17
  import { useApp } from '@backstage/core-plugin-api';
18
18
  import { useAsync, useMountEffect } from '@react-hookz/web';
19
19
  import { TemplatingExtensionsPage } from '../TemplatingExtensionsPage/TemplatingExtensionsPage.esm.js';
@@ -83,12 +83,12 @@ const InternalRouter = (props) => {
83
83
  Route,
84
84
  {
85
85
  path: scaffolderTaskRouteRef.path,
86
- element: /* @__PURE__ */ jsx(RequirePermission, { permission: taskReadPermission, children: /* @__PURE__ */ jsx(
86
+ element: /* @__PURE__ */ jsx(
87
87
  TaskPageComponent,
88
88
  {
89
89
  TemplateOutputsComponent
90
90
  }
91
- ) })
91
+ )
92
92
  }
93
93
  ),
94
94
  /* @__PURE__ */ jsx(
@@ -130,7 +130,7 @@ const InternalRouter = (props) => {
130
130
  Route,
131
131
  {
132
132
  path: scaffolderListTaskRouteRef.path,
133
- element: /* @__PURE__ */ jsx(RequirePermission, { permission: taskReadPermission, children: /* @__PURE__ */ jsx(ListTasksPage, { contextMenu: props.contextMenu }) })
133
+ element: /* @__PURE__ */ jsx(ListTasksPage, { contextMenu: props.contextMenu })
134
134
  }
135
135
  ),
136
136
  /* @__PURE__ */ jsx(
@@ -1 +1 @@
1
- {"version":3,"file":"Router.esm.js","sources":["../../../src/components/Router/Router.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 { ComponentType, PropsWithChildren } from 'react';\nimport { Routes, Route, useOutlet } from 'react-router-dom';\n\nimport {\n FieldExtensionOptions,\n FormProps,\n ReviewStepProps,\n TemplateGroupFilter,\n} from '@backstage/plugin-scaffolder-react';\nimport {\n ScaffolderTaskOutput,\n SecretsContextProvider,\n useCustomFieldExtensions,\n useCustomLayouts,\n} from '@backstage/plugin-scaffolder-react';\n\nimport { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common';\nimport { DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS } from '../../extensions/default';\n\nimport {\n actionsRouteRef,\n editorRouteRef,\n customFieldsRouteRef,\n editRouteRef,\n scaffolderListTaskRouteRef,\n scaffolderTaskRouteRef,\n selectedTemplateRouteRef,\n templateFormRouteRef,\n templatingExtensionsRouteRef,\n} from '../../routes';\n\nimport { ActionsPage } from '../../components/ActionsPage';\nimport { ListTasksPage } from '../../components/ListTasksPage';\n\nimport {\n TemplateListPageProps,\n TemplateWizardPageProps,\n} from '@backstage/plugin-scaffolder/alpha';\nimport { TemplateListPage, TemplateWizardPage } from '../../alpha/components';\nimport { OngoingTask } from '../OngoingTask';\nimport {\n TemplateFormPage,\n TemplateIntroPage,\n TemplateEditorPage,\n CustomFieldsPage,\n} from '../../alpha/components/TemplateEditorPage';\nimport { RequirePermission } from '@backstage/plugin-permission-react';\nimport {\n taskReadPermission,\n templateManagementPermission,\n} from '@backstage/plugin-scaffolder-common/alpha';\nimport { useApp } from '@backstage/core-plugin-api';\nimport { FormField, OpaqueFormField } from '@internal/scaffolder';\nimport { useAsync, useMountEffect } from '@react-hookz/web';\nimport { TemplatingExtensionsPage } from '../TemplatingExtensionsPage';\n\n/**\n * The Props for the Scaffolder Router\n *\n * @public\n */\nexport type RouterProps = {\n components?: {\n ReviewStepComponent?: ComponentType<ReviewStepProps>;\n TemplateCardComponent?: ComponentType<{\n template: TemplateEntityV1beta3;\n }>;\n TaskPageComponent?: ComponentType<PropsWithChildren<{}>>;\n EXPERIMENTAL_TemplateOutputsComponent?: ComponentType<{\n output?: ScaffolderTaskOutput;\n }>;\n EXPERIMENTAL_TemplateListPageComponent?: ComponentType<TemplateListPageProps>;\n EXPERIMENTAL_TemplateWizardPageComponent?: ComponentType<TemplateWizardPageProps>;\n };\n groups?: TemplateGroupFilter[];\n templateFilter?: (entity: TemplateEntityV1beta3) => boolean;\n headerOptions?: {\n pageTitleOverride?: string;\n title?: string;\n subtitle?: string;\n };\n defaultPreviewTemplate?: string;\n formProps?: FormProps;\n contextMenu?: {\n /** Whether to show a link to the template editor */\n editor?: boolean;\n /** Whether to show a link to the actions documentation */\n actions?: boolean;\n /** Whether to show a link to the tasks page */\n tasks?: boolean;\n /** Whether to show a link to the create page (on /create subroutes) */\n create?: boolean;\n };\n};\n\n/**\n * Internal router with additional props that aren't available in the public API\n * for the old frontend system.\n *\n * @internal\n */\nexport const InternalRouter = (\n props: PropsWithChildren<\n RouterProps & { formFieldLoaders?: Array<() => Promise<FormField>> }\n >,\n) => {\n const {\n components: {\n TemplateCardComponent,\n TaskPageComponent = OngoingTask,\n ReviewStepComponent,\n EXPERIMENTAL_TemplateOutputsComponent: TemplateOutputsComponent,\n EXPERIMENTAL_TemplateListPageComponent:\n TemplateListPageComponent = TemplateListPage,\n EXPERIMENTAL_TemplateWizardPageComponent:\n TemplateWizardPageComponent = TemplateWizardPage,\n } = {},\n } = props;\n const outlet = useOutlet() || props.children;\n const customFieldExtensions = useCustomFieldExtensions(outlet);\n const loadedFieldExtensions = useFormFieldLoaders(props.formFieldLoaders);\n\n const app = useApp();\n const { NotFoundErrorPage } = app.getComponents();\n\n const fieldExtensions = [\n ...customFieldExtensions,\n ...loadedFieldExtensions,\n ...DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS.filter(\n ({ name }) =>\n !customFieldExtensions.some(\n customFieldExtension => customFieldExtension.name === name,\n ),\n ),\n ] as FieldExtensionOptions[];\n\n const customLayouts = useCustomLayouts(outlet);\n\n return (\n <Routes>\n <Route\n path=\"/\"\n element={\n <TemplateListPageComponent\n TemplateCardComponent={TemplateCardComponent}\n contextMenu={props.contextMenu}\n groups={props.groups}\n templateFilter={props.templateFilter}\n headerOptions={props.headerOptions}\n />\n }\n />\n <Route\n path={selectedTemplateRouteRef.path}\n element={\n <SecretsContextProvider>\n <TemplateWizardPageComponent\n headerOptions={props.headerOptions}\n customFieldExtensions={fieldExtensions}\n layouts={customLayouts}\n components={{ ReviewStepComponent }}\n formProps={props.formProps}\n />\n </SecretsContextProvider>\n }\n />\n <Route\n path={scaffolderTaskRouteRef.path}\n element={\n <RequirePermission permission={taskReadPermission}>\n <TaskPageComponent\n TemplateOutputsComponent={TemplateOutputsComponent}\n />\n </RequirePermission>\n }\n />\n <Route\n path={editRouteRef.path}\n element={\n <RequirePermission permission={templateManagementPermission}>\n <SecretsContextProvider>\n <TemplateIntroPage />\n </SecretsContextProvider>\n </RequirePermission>\n }\n />\n <Route\n path={customFieldsRouteRef.path}\n element={\n <RequirePermission permission={templateManagementPermission}>\n <SecretsContextProvider>\n <CustomFieldsPage fieldExtensions={fieldExtensions} />\n </SecretsContextProvider>\n </RequirePermission>\n }\n />\n <Route\n path={templateFormRouteRef.path}\n element={\n <RequirePermission permission={templateManagementPermission}>\n <SecretsContextProvider>\n <TemplateFormPage\n layouts={customLayouts}\n formProps={props.formProps}\n fieldExtensions={fieldExtensions}\n />\n </SecretsContextProvider>\n </RequirePermission>\n }\n />\n\n <Route\n path={actionsRouteRef.path}\n element={<ActionsPage contextMenu={props.contextMenu} />}\n />\n <Route\n path={scaffolderListTaskRouteRef.path}\n element={\n <RequirePermission permission={taskReadPermission}>\n <ListTasksPage contextMenu={props.contextMenu} />\n </RequirePermission>\n }\n />\n <Route\n path={editorRouteRef.path}\n element={\n <RequirePermission permission={templateManagementPermission}>\n <SecretsContextProvider>\n <TemplateEditorPage\n layouts={customLayouts}\n formProps={props.formProps}\n fieldExtensions={fieldExtensions}\n />\n </SecretsContextProvider>\n </RequirePermission>\n }\n />\n <Route\n path={templatingExtensionsRouteRef.path}\n element={<TemplatingExtensionsPage />}\n />\n <Route path=\"*\" element={<NotFoundErrorPage />} />\n </Routes>\n );\n};\n\n/**\n * The Scaffolder Router\n *\n * @public\n */\nexport const Router = (props: PropsWithChildren<RouterProps>) => {\n return <InternalRouter {...props} />;\n};\n\nfunction useFormFieldLoaders(\n formFieldLoaders?: Array<() => Promise<FormField>>,\n) {\n const [{ result: loadedFieldExtensions }, { execute }] =\n useAsync(async () => {\n const loaded = await Promise.all(\n (formFieldLoaders ?? []).map(loader => loader()),\n );\n return loaded.map(f => OpaqueFormField.toInternal(f));\n }, []);\n useMountEffect(execute);\n return loadedFieldExtensions;\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Router.esm.js","sources":["../../../src/components/Router/Router.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 { ComponentType, PropsWithChildren } from 'react';\nimport { Routes, Route, useOutlet } from 'react-router-dom';\n\nimport {\n FieldExtensionOptions,\n FormProps,\n ReviewStepProps,\n TemplateGroupFilter,\n} from '@backstage/plugin-scaffolder-react';\nimport {\n ScaffolderTaskOutput,\n SecretsContextProvider,\n useCustomFieldExtensions,\n useCustomLayouts,\n} from '@backstage/plugin-scaffolder-react';\n\nimport { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common';\nimport { DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS } from '../../extensions/default';\n\nimport {\n actionsRouteRef,\n editorRouteRef,\n customFieldsRouteRef,\n editRouteRef,\n scaffolderListTaskRouteRef,\n scaffolderTaskRouteRef,\n selectedTemplateRouteRef,\n templateFormRouteRef,\n templatingExtensionsRouteRef,\n} from '../../routes';\n\nimport { ActionsPage } from '../../components/ActionsPage';\nimport { ListTasksPage } from '../../components/ListTasksPage';\n\nimport {\n TemplateListPageProps,\n TemplateWizardPageProps,\n} from '@backstage/plugin-scaffolder/alpha';\nimport { TemplateListPage, TemplateWizardPage } from '../../alpha/components';\nimport { OngoingTask } from '../OngoingTask';\nimport {\n TemplateFormPage,\n TemplateIntroPage,\n TemplateEditorPage,\n CustomFieldsPage,\n} from '../../alpha/components/TemplateEditorPage';\nimport { RequirePermission } from '@backstage/plugin-permission-react';\nimport { templateManagementPermission } from '@backstage/plugin-scaffolder-common/alpha';\nimport { useApp } from '@backstage/core-plugin-api';\nimport { FormField, OpaqueFormField } from '@internal/scaffolder';\nimport { useAsync, useMountEffect } from '@react-hookz/web';\nimport { TemplatingExtensionsPage } from '../TemplatingExtensionsPage';\n\n/**\n * The Props for the Scaffolder Router\n *\n * @public\n */\nexport type RouterProps = {\n components?: {\n ReviewStepComponent?: ComponentType<ReviewStepProps>;\n TemplateCardComponent?: ComponentType<{\n template: TemplateEntityV1beta3;\n }>;\n TaskPageComponent?: ComponentType<PropsWithChildren<{}>>;\n EXPERIMENTAL_TemplateOutputsComponent?: ComponentType<{\n output?: ScaffolderTaskOutput;\n }>;\n EXPERIMENTAL_TemplateListPageComponent?: ComponentType<TemplateListPageProps>;\n EXPERIMENTAL_TemplateWizardPageComponent?: ComponentType<TemplateWizardPageProps>;\n };\n groups?: TemplateGroupFilter[];\n templateFilter?: (entity: TemplateEntityV1beta3) => boolean;\n headerOptions?: {\n pageTitleOverride?: string;\n title?: string;\n subtitle?: string;\n };\n defaultPreviewTemplate?: string;\n formProps?: FormProps;\n contextMenu?: {\n /** Whether to show a link to the template editor */\n editor?: boolean;\n /** Whether to show a link to the actions documentation */\n actions?: boolean;\n /** Whether to show a link to the tasks page */\n tasks?: boolean;\n /** Whether to show a link to the create page (on /create subroutes) */\n create?: boolean;\n };\n};\n\n/**\n * Internal router with additional props that aren't available in the public API\n * for the old frontend system.\n *\n * @internal\n */\nexport const InternalRouter = (\n props: PropsWithChildren<\n RouterProps & { formFieldLoaders?: Array<() => Promise<FormField>> }\n >,\n) => {\n const {\n components: {\n TemplateCardComponent,\n TaskPageComponent = OngoingTask,\n ReviewStepComponent,\n EXPERIMENTAL_TemplateOutputsComponent: TemplateOutputsComponent,\n EXPERIMENTAL_TemplateListPageComponent:\n TemplateListPageComponent = TemplateListPage,\n EXPERIMENTAL_TemplateWizardPageComponent:\n TemplateWizardPageComponent = TemplateWizardPage,\n } = {},\n } = props;\n const outlet = useOutlet() || props.children;\n const customFieldExtensions = useCustomFieldExtensions(outlet);\n const loadedFieldExtensions = useFormFieldLoaders(props.formFieldLoaders);\n\n const app = useApp();\n const { NotFoundErrorPage } = app.getComponents();\n\n const fieldExtensions = [\n ...customFieldExtensions,\n ...loadedFieldExtensions,\n ...DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS.filter(\n ({ name }) =>\n !customFieldExtensions.some(\n customFieldExtension => customFieldExtension.name === name,\n ),\n ),\n ] as FieldExtensionOptions[];\n\n const customLayouts = useCustomLayouts(outlet);\n\n return (\n <Routes>\n <Route\n path=\"/\"\n element={\n <TemplateListPageComponent\n TemplateCardComponent={TemplateCardComponent}\n contextMenu={props.contextMenu}\n groups={props.groups}\n templateFilter={props.templateFilter}\n headerOptions={props.headerOptions}\n />\n }\n />\n <Route\n path={selectedTemplateRouteRef.path}\n element={\n <SecretsContextProvider>\n <TemplateWizardPageComponent\n headerOptions={props.headerOptions}\n customFieldExtensions={fieldExtensions}\n layouts={customLayouts}\n components={{ ReviewStepComponent }}\n formProps={props.formProps}\n />\n </SecretsContextProvider>\n }\n />\n <Route\n path={scaffolderTaskRouteRef.path}\n element={\n <TaskPageComponent\n TemplateOutputsComponent={TemplateOutputsComponent}\n />\n }\n />\n <Route\n path={editRouteRef.path}\n element={\n <RequirePermission permission={templateManagementPermission}>\n <SecretsContextProvider>\n <TemplateIntroPage />\n </SecretsContextProvider>\n </RequirePermission>\n }\n />\n <Route\n path={customFieldsRouteRef.path}\n element={\n <RequirePermission permission={templateManagementPermission}>\n <SecretsContextProvider>\n <CustomFieldsPage fieldExtensions={fieldExtensions} />\n </SecretsContextProvider>\n </RequirePermission>\n }\n />\n <Route\n path={templateFormRouteRef.path}\n element={\n <RequirePermission permission={templateManagementPermission}>\n <SecretsContextProvider>\n <TemplateFormPage\n layouts={customLayouts}\n formProps={props.formProps}\n fieldExtensions={fieldExtensions}\n />\n </SecretsContextProvider>\n </RequirePermission>\n }\n />\n\n <Route\n path={actionsRouteRef.path}\n element={<ActionsPage contextMenu={props.contextMenu} />}\n />\n <Route\n path={scaffolderListTaskRouteRef.path}\n element={<ListTasksPage contextMenu={props.contextMenu} />}\n />\n <Route\n path={editorRouteRef.path}\n element={\n <RequirePermission permission={templateManagementPermission}>\n <SecretsContextProvider>\n <TemplateEditorPage\n layouts={customLayouts}\n formProps={props.formProps}\n fieldExtensions={fieldExtensions}\n />\n </SecretsContextProvider>\n </RequirePermission>\n }\n />\n <Route\n path={templatingExtensionsRouteRef.path}\n element={<TemplatingExtensionsPage />}\n />\n <Route path=\"*\" element={<NotFoundErrorPage />} />\n </Routes>\n );\n};\n\n/**\n * The Scaffolder Router\n *\n * @public\n */\nexport const Router = (props: PropsWithChildren<RouterProps>) => {\n return <InternalRouter {...props} />;\n};\n\nfunction useFormFieldLoaders(\n formFieldLoaders?: Array<() => Promise<FormField>>,\n) {\n const [{ result: loadedFieldExtensions }, { execute }] =\n useAsync(async () => {\n const loaded = await Promise.all(\n (formFieldLoaders ?? []).map(loader => loader()),\n );\n return loaded.map(f => OpaqueFormField.toInternal(f));\n }, []);\n useMountEffect(execute);\n return loadedFieldExtensions;\n}\n"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  var name = "@backstage/plugin-scaffolder";
2
- var version = "1.32.1-next.1";
2
+ var version = "1.33.0";
3
3
  var description = "The Backstage plugin that helps you create new things";
4
4
  var backstage = {
5
5
  role: "frontend-plugin",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/plugin-scaffolder",
3
- "version": "1.32.1-next.1",
3
+ "version": "1.33.0",
4
4
  "description": "The Backstage plugin that helps you create new things",
5
5
  "backstage": {
6
6
  "role": "frontend-plugin",
@@ -70,21 +70,21 @@
70
70
  "test": "backstage-cli package test"
71
71
  },
72
72
  "dependencies": {
73
- "@backstage/catalog-client": "1.10.2-next.0",
74
- "@backstage/catalog-model": "1.7.5-next.0",
75
- "@backstage/core-compat-api": "0.4.4-next.1",
76
- "@backstage/core-components": "0.17.4-next.1",
77
- "@backstage/core-plugin-api": "1.10.9-next.0",
78
- "@backstage/errors": "1.2.7",
79
- "@backstage/frontend-plugin-api": "0.10.4-next.1",
80
- "@backstage/integration": "1.17.1-next.1",
81
- "@backstage/integration-react": "1.2.9-next.1",
82
- "@backstage/plugin-catalog-common": "1.1.5-next.0",
83
- "@backstage/plugin-catalog-react": "1.19.1-next.1",
84
- "@backstage/plugin-permission-react": "0.4.36-next.0",
85
- "@backstage/plugin-scaffolder-common": "1.5.12-next.0",
86
- "@backstage/plugin-scaffolder-react": "1.17.1-next.1",
87
- "@backstage/types": "1.2.1",
73
+ "@backstage/catalog-client": "^1.10.2",
74
+ "@backstage/catalog-model": "^1.7.5",
75
+ "@backstage/core-compat-api": "^0.4.4",
76
+ "@backstage/core-components": "^0.17.4",
77
+ "@backstage/core-plugin-api": "^1.10.9",
78
+ "@backstage/errors": "^1.2.7",
79
+ "@backstage/frontend-plugin-api": "^0.10.4",
80
+ "@backstage/integration": "^1.17.1",
81
+ "@backstage/integration-react": "^1.2.9",
82
+ "@backstage/plugin-catalog-common": "^1.1.5",
83
+ "@backstage/plugin-catalog-react": "^1.19.1",
84
+ "@backstage/plugin-permission-react": "^0.4.36",
85
+ "@backstage/plugin-scaffolder-common": "^1.6.0",
86
+ "@backstage/plugin-scaffolder-react": "^1.18.0",
87
+ "@backstage/types": "^1.2.1",
88
88
  "@codemirror/language": "^6.0.0",
89
89
  "@codemirror/legacy-modes": "^6.1.0",
90
90
  "@codemirror/view": "^6.0.0",
@@ -117,12 +117,12 @@
117
117
  "zod-to-json-schema": "^3.20.4"
118
118
  },
119
119
  "devDependencies": {
120
- "@backstage/cli": "0.33.1-next.1",
121
- "@backstage/core-app-api": "1.17.2-next.0",
122
- "@backstage/dev-utils": "1.1.12-next.1",
123
- "@backstage/plugin-catalog": "1.31.1-next.1",
124
- "@backstage/plugin-permission-common": "0.9.1-next.0",
125
- "@backstage/test-utils": "1.7.10-next.1",
120
+ "@backstage/cli": "^0.33.1",
121
+ "@backstage/core-app-api": "^1.18.0",
122
+ "@backstage/dev-utils": "^1.1.12",
123
+ "@backstage/plugin-catalog": "^1.31.1",
124
+ "@backstage/plugin-permission-common": "^0.9.1",
125
+ "@backstage/test-utils": "^1.7.10",
126
126
  "@testing-library/dom": "^10.0.0",
127
127
  "@testing-library/jest-dom": "^6.0.0",
128
128
  "@testing-library/react": "^16.0.0",