@backstage-community/plugin-announcements 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/dist/alpha/Router.esm.js +74 -0
  3. package/dist/alpha/Router.esm.js.map +1 -0
  4. package/dist/alpha/components/admin/AnnouncementsAdminPage.esm.js +43 -0
  5. package/dist/alpha/components/admin/AnnouncementsAdminPage.esm.js.map +1 -0
  6. package/dist/alpha/navItems.esm.js +1 -1
  7. package/dist/alpha/navItems.esm.js.map +1 -1
  8. package/dist/alpha/pages.esm.js +1 -1
  9. package/dist/alpha/pages.esm.js.map +1 -1
  10. package/dist/alpha.d.ts +5 -13
  11. package/dist/alpha.esm.js +1 -1
  12. package/dist/alpha.esm.js.map +1 -1
  13. package/dist/components/Admin/AnnouncementsContent/AnnouncementsContent.esm.js +14 -22
  14. package/dist/components/Admin/AnnouncementsContent/AnnouncementsContent.esm.js.map +1 -1
  15. package/dist/components/Admin/CategoriesContent/CategoriesContent.esm.js +26 -19
  16. package/dist/components/Admin/CategoriesContent/CategoriesContent.esm.js.map +1 -1
  17. package/dist/components/Admin/TagsContent/TagsContent.esm.js +31 -19
  18. package/dist/components/Admin/TagsContent/TagsContent.esm.js.map +1 -1
  19. package/dist/components/Admin/shared/DeleteDialog/DeleteDialog.esm.js +30 -0
  20. package/dist/components/Admin/shared/DeleteDialog/DeleteDialog.esm.js.map +1 -0
  21. package/dist/components/Admin/{TagsContent/useDeleteTagDialogState.esm.js → shared/DeleteDialog/useDeleteDialogState.esm.js} +7 -7
  22. package/dist/components/Admin/shared/DeleteDialog/useDeleteDialogState.esm.js.map +1 -0
  23. package/dist/components/Admin/shared/TitleForm/TitleForm.esm.js +71 -0
  24. package/dist/components/Admin/shared/TitleForm/TitleForm.esm.js.map +1 -0
  25. package/dist/components/AnnouncementsCard/AnnouncementsCard.esm.js +3 -8
  26. package/dist/components/AnnouncementsCard/AnnouncementsCard.esm.js.map +1 -1
  27. package/dist/components/AnnouncementsPage/AnnouncementsPage.esm.js +3 -5
  28. package/dist/components/AnnouncementsPage/AnnouncementsPage.esm.js.map +1 -1
  29. package/dist/index.d.ts +14 -6
  30. package/dist/plugin.esm.js.map +1 -1
  31. package/dist/routes.esm.js +14 -4
  32. package/dist/routes.esm.js.map +1 -1
  33. package/package.json +19 -18
  34. package/dist/components/Admin/AnnouncementsContent/DeleteAnnouncementDialog.esm.js +0 -31
  35. package/dist/components/Admin/AnnouncementsContent/DeleteAnnouncementDialog.esm.js.map +0 -1
  36. package/dist/components/Admin/AnnouncementsContent/useDeleteAnnouncementDialogState.esm.js +0 -29
  37. package/dist/components/Admin/AnnouncementsContent/useDeleteAnnouncementDialogState.esm.js.map +0 -1
  38. package/dist/components/Admin/CategoriesContent/CategoriesForm.esm.js +0 -75
  39. package/dist/components/Admin/CategoriesContent/CategoriesForm.esm.js.map +0 -1
  40. package/dist/components/Admin/CategoriesContent/DeleteCategoryDialog.esm.js +0 -16
  41. package/dist/components/Admin/CategoriesContent/DeleteCategoryDialog.esm.js.map +0 -1
  42. package/dist/components/Admin/CategoriesContent/useDeleteCategoryDialogState.esm.js +0 -29
  43. package/dist/components/Admin/CategoriesContent/useDeleteCategoryDialogState.esm.js.map +0 -1
  44. package/dist/components/Admin/TagsContent/DeleteTagDialog.esm.js +0 -16
  45. package/dist/components/Admin/TagsContent/DeleteTagDialog.esm.js.map +0 -1
  46. package/dist/components/Admin/TagsContent/TagsForm.esm.js +0 -85
  47. package/dist/components/Admin/TagsContent/TagsForm.esm.js.map +0 -1
  48. package/dist/components/Admin/TagsContent/useDeleteTagDialogState.esm.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"CategoriesContent.esm.js","sources":["../../../../src/components/Admin/CategoriesContent/CategoriesContent.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useState } from 'react';\nimport {\n ErrorPanel,\n Progress,\n Table,\n TableColumn,\n} from '@backstage/core-components';\nimport {\n CreateCategoryRequest,\n announcementsApiRef,\n useAnnouncementsTranslation,\n useCategories,\n} from '@backstage-community/plugin-announcements-react';\nimport {\n announcementCreatePermission,\n announcementDeletePermission,\n Category,\n} from '@backstage-community/plugin-announcements-common';\nimport { useApi, alertApiRef } from '@backstage/core-plugin-api';\nimport {\n RequirePermission,\n usePermission,\n} from '@backstage/plugin-permission-react';\nimport { ResponseError } from '@backstage/errors';\nimport { Button, Grid, IconButton, Typography } from '@material-ui/core';\nimport DeleteIcon from '@material-ui/icons/Delete';\n\nimport { CategoriesForm } from './CategoriesForm';\nimport { useDeleteCategoryDialogState } from './useDeleteCategoryDialogState';\nimport { DeleteCategoryDialog } from './DeleteCategoryDialog';\n\nexport const CategoriesContent = () => {\n const [showNewCategoryForm, setShowNewCategoryForm] = useState(false);\n const { categories, loading, error, retry: refresh } = useCategories();\n const announcementsApi = useApi(announcementsApiRef);\n const alertApi = useApi(alertApiRef);\n const { t } = useAnnouncementsTranslation();\n\n const {\n isOpen: isDeleteDialogOpen,\n open: openDeleteDialog,\n close: closeDeleteDialog,\n category: categoryToDelete,\n } = useDeleteCategoryDialogState();\n\n const { loading: loadingCreatePermission, allowed: canCreateCategory } =\n usePermission({\n permission: announcementCreatePermission,\n });\n\n const { loading: loadingDeletePermission, allowed: canDeleteAnnouncement } =\n usePermission({\n permission: announcementDeletePermission,\n });\n\n const onSubmit = async (request: CreateCategoryRequest) => {\n const { title } = request;\n\n try {\n await announcementsApi.createCategory({\n title,\n });\n\n alertApi.post({\n message: `${title} ${t('admin.categoriesContent.createdMessage')}`,\n severity: 'success',\n });\n\n refresh();\n } catch (err) {\n alertApi.post({ message: (err as Error).message, severity: 'error' });\n }\n };\n\n const onCreateButtonClick = () => {\n setShowNewCategoryForm(!showNewCategoryForm);\n };\n\n const onCancelDelete = () => {\n closeDeleteDialog();\n };\n\n const onConfirmDelete = async () => {\n closeDeleteDialog();\n\n try {\n await announcementsApi.deleteCategory(categoryToDelete!.slug);\n\n alertApi.post({\n message: t('admin.categoriesContent.table.categoryDeleted'),\n severity: 'success',\n });\n } catch (err) {\n alertApi.post({\n message: (err as ResponseError).body.error.message,\n severity: 'error',\n });\n }\n\n refresh();\n };\n\n if (loading) {\n return <Progress />;\n }\n if (error) {\n return <ErrorPanel error={error} />;\n }\n\n const columns: TableColumn<Category>[] = [\n {\n title: (\n <Typography>{t('admin.categoriesContent.table.title')}</Typography>\n ),\n sorting: true,\n field: 'title',\n render: rowData => rowData.title,\n },\n {\n title: <Typography>{t('admin.categoriesContent.table.slug')}</Typography>,\n sorting: true,\n field: 'slug',\n render: rowData => rowData.slug,\n },\n {\n title: (\n <Typography>{t('admin.categoriesContent.table.actions')}</Typography>\n ),\n render: rowData => {\n return (\n <IconButton\n aria-label=\"delete\"\n disabled={loadingDeletePermission || !canDeleteAnnouncement}\n onClick={() => openDeleteDialog(rowData)}\n >\n <DeleteIcon fontSize=\"small\" data-testid=\"delete-icon\" />\n </IconButton>\n );\n },\n },\n ];\n\n return (\n <RequirePermission permission={announcementCreatePermission}>\n <Grid container>\n <Grid item xs={12}>\n <Button\n disabled={loadingCreatePermission || !canCreateCategory}\n variant=\"contained\"\n onClick={() => onCreateButtonClick()}\n >\n {showNewCategoryForm\n ? t('admin.categoriesContent.cancelButton')\n : t('admin.categoriesContent.createButton')}\n </Button>\n </Grid>\n\n {showNewCategoryForm && (\n <Grid item xs={12}>\n <CategoriesForm initialData={{} as Category} onSubmit={onSubmit} />\n </Grid>\n )}\n\n <Grid item xs={12}>\n <Table\n title=\"Categories\"\n options={{ pageSize: 20, search: true }}\n columns={columns}\n data={categories ?? []}\n emptyContent={\n <Typography style={{ padding: 2, textAlign: 'center' }}>\n {t('admin.categoriesContent.table.noCategoriesFound')}\n </Typography>\n }\n />\n </Grid>\n\n <DeleteCategoryDialog\n open={isDeleteDialogOpen}\n onCancel={onCancelDelete}\n onConfirm={onConfirmDelete}\n />\n </Grid>\n </RequirePermission>\n );\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"CategoriesContent.esm.js","sources":["../../../../src/components/Admin/CategoriesContent/CategoriesContent.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useState } from 'react';\nimport {\n ErrorPanel,\n Progress,\n Table,\n TableColumn,\n} from '@backstage/core-components';\nimport {\n CreateCategoryRequest,\n announcementsApiRef,\n useAnnouncementsTranslation,\n useCategories,\n useAnnouncementsPermissions,\n} from '@backstage-community/plugin-announcements-react';\nimport {\n announcementCreatePermission,\n Category,\n} from '@backstage-community/plugin-announcements-common';\nimport { useApi, alertApiRef } from '@backstage/core-plugin-api';\nimport { RequirePermission } from '@backstage/plugin-permission-react';\nimport { ResponseError } from '@backstage/errors';\nimport { Button, Grid, IconButton, Typography } from '@material-ui/core';\nimport DeleteIcon from '@material-ui/icons/Delete';\n\nimport { useDeleteDialogState, DeleteDialog, TitleForm } from '../shared';\n\nexport const CategoriesContent = () => {\n const [showNewCategoryForm, setShowNewCategoryForm] = useState(false);\n const { categories, loading, error, retry: refresh } = useCategories();\n const announcementsApi = useApi(announcementsApiRef);\n const alertApi = useApi(alertApiRef);\n const { t } = useAnnouncementsTranslation();\n\n const {\n isOpen: isDeleteDialogOpen,\n open: openDeleteDialog,\n close: closeDeleteDialog,\n item: categoryToDelete,\n } = useDeleteDialogState<Category>();\n\n const permissions = useAnnouncementsPermissions();\n\n const translationKeys = {\n new: t('categoriesForm.newCategory'),\n edit: t('categoriesForm.editCategory'),\n titleLabel: t('categoriesForm.titleLabel'),\n submit: t('categoriesForm.submit'),\n };\n\n const onSubmit = async (request: CreateCategoryRequest) => {\n const { title } = request;\n\n try {\n await announcementsApi.createCategory({\n title,\n });\n\n alertApi.post({\n message: `${title} ${t('admin.categoriesContent.createdMessage')}`,\n severity: 'success',\n });\n\n refresh();\n } catch (err) {\n alertApi.post({ message: (err as Error).message, severity: 'error' });\n }\n };\n\n const onCreateButtonClick = () => {\n setShowNewCategoryForm(!showNewCategoryForm);\n };\n\n const onCancelDelete = () => {\n closeDeleteDialog();\n };\n\n const onConfirmDelete = async () => {\n closeDeleteDialog();\n\n try {\n await announcementsApi.deleteCategory(categoryToDelete!.slug);\n\n alertApi.post({\n message: t('admin.categoriesContent.table.categoryDeleted'),\n severity: 'success',\n });\n } catch (err) {\n alertApi.post({\n message: (err as ResponseError).body.error.message,\n severity: 'error',\n });\n }\n\n refresh();\n };\n\n if (loading) {\n return <Progress />;\n }\n if (error) {\n return <ErrorPanel error={error} />;\n }\n\n const columns: TableColumn<Category>[] = [\n {\n title: (\n <Typography>{t('admin.categoriesContent.table.title')}</Typography>\n ),\n sorting: true,\n field: 'title',\n render: rowData => rowData.title,\n },\n {\n title: <Typography>{t('admin.categoriesContent.table.slug')}</Typography>,\n sorting: true,\n field: 'slug',\n render: rowData => rowData.slug,\n },\n {\n title: (\n <Typography>{t('admin.categoriesContent.table.actions')}</Typography>\n ),\n render: rowData => {\n return (\n <IconButton\n aria-label=\"delete\"\n disabled={permissions.delete.loading || !permissions.delete.allowed}\n onClick={() => openDeleteDialog(rowData)}\n >\n <DeleteIcon fontSize=\"small\" data-testid=\"delete-icon\" />\n </IconButton>\n );\n },\n },\n ];\n\n return (\n <RequirePermission permission={announcementCreatePermission}>\n <Grid container>\n <Grid item xs={12}>\n <Button\n disabled={permissions.create.loading || !permissions.create.allowed}\n variant=\"contained\"\n onClick={() => onCreateButtonClick()}\n >\n {showNewCategoryForm\n ? t('admin.categoriesContent.cancelButton')\n : t('admin.categoriesContent.createButton')}\n </Button>\n </Grid>\n\n {showNewCategoryForm && (\n <Grid item xs={12}>\n <TitleForm<Category>\n translationKeys={translationKeys}\n onSubmit={onSubmit}\n />\n </Grid>\n )}\n\n <Grid item xs={12}>\n <Table\n title=\"Categories\"\n options={{ pageSize: 20, search: true }}\n columns={columns}\n data={categories ?? []}\n emptyContent={\n <Typography style={{ padding: 2, textAlign: 'center' }}>\n {t('admin.categoriesContent.table.noCategoriesFound')}\n </Typography>\n }\n />\n </Grid>\n\n <DeleteDialog\n isOpen={isDeleteDialogOpen}\n onCancel={onCancelDelete}\n onConfirm={onConfirmDelete}\n />\n </Grid>\n </RequirePermission>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -1,15 +1,15 @@
1
1
  import { jsx, jsxs } from 'react/jsx-runtime';
2
2
  import { useState } from 'react';
3
3
  import { Progress, ErrorPanel, Table } from '@backstage/core-components';
4
- import { useTags, announcementsApiRef, useAnnouncementsTranslation } from '@backstage-community/plugin-announcements-react';
5
- import { announcementCreatePermission, announcementDeletePermission } from '@backstage-community/plugin-announcements-common';
4
+ import { useTags, announcementsApiRef, useAnnouncementsTranslation, useAnnouncementsPermissions } from '@backstage-community/plugin-announcements-react';
5
+ import { announcementCreatePermission } from '@backstage-community/plugin-announcements-common';
6
6
  import { useApi, alertApiRef } from '@backstage/core-plugin-api';
7
- import { usePermission, RequirePermission } from '@backstage/plugin-permission-react';
7
+ import { RequirePermission } from '@backstage/plugin-permission-react';
8
8
  import { Typography, IconButton, Grid, Button } from '@material-ui/core';
9
9
  import DeleteIcon from '@material-ui/icons/Delete';
10
- import { useDeleteTagDialogState } from './useDeleteTagDialogState.esm.js';
11
- import { DeleteTagDialog } from './DeleteTagDialog.esm.js';
12
- import { TagsForm } from './TagsForm.esm.js';
10
+ import { useDeleteDialogState } from '../shared/DeleteDialog/useDeleteDialogState.esm.js';
11
+ import { DeleteDialog } from '../shared/DeleteDialog/DeleteDialog.esm.js';
12
+ import { TitleForm } from '../shared/TitleForm/TitleForm.esm.js';
13
13
 
14
14
  const TagsContent = () => {
15
15
  const [showNewTagForm, setShowNewTagForm] = useState(false);
@@ -21,14 +21,15 @@ const TagsContent = () => {
21
21
  isOpen: isDeleteDialogOpen,
22
22
  open: openDeleteDialog,
23
23
  close: closeDeleteDialog,
24
- tag: tagToDelete
25
- } = useDeleteTagDialogState();
26
- const { loading: loadingCreatePermission, allowed: canCreateTag } = usePermission({
27
- permission: announcementCreatePermission
28
- });
29
- const { loading: loadingDeletePermission, allowed: canDeleteAnnouncement } = usePermission({
30
- permission: announcementDeletePermission
31
- });
24
+ item: tagToDelete
25
+ } = useDeleteDialogState();
26
+ const permissions = useAnnouncementsPermissions();
27
+ const translationKeys = {
28
+ new: t("tagsForm.newTag"),
29
+ edit: t("tagsForm.editTag"),
30
+ titleLabel: t("tagsForm.titleLabel"),
31
+ submit: t("tagsForm.submit")
32
+ };
32
33
  const onSubmit = async (request) => {
33
34
  const { title } = request;
34
35
  try {
@@ -102,7 +103,7 @@ const TagsContent = () => {
102
103
  IconButton,
103
104
  {
104
105
  "aria-label": "delete",
105
- disabled: loadingDeletePermission || !canDeleteAnnouncement,
106
+ disabled: permissions.delete.loading || !permissions.delete.allowed,
106
107
  onClick: () => openDeleteDialog(rowData),
107
108
  children: /* @__PURE__ */ jsx(DeleteIcon, { fontSize: "small", "data-testid": "delete-icon" })
108
109
  }
@@ -114,13 +115,24 @@ const TagsContent = () => {
114
115
  /* @__PURE__ */ jsx(Grid, { item: true, xs: 12, children: /* @__PURE__ */ jsx(
115
116
  Button,
116
117
  {
117
- disabled: loadingCreatePermission || !canCreateTag,
118
+ disabled: permissions.create.loading || !permissions.create.allowed,
118
119
  variant: "contained",
119
120
  onClick: () => onCreateButtonClick(),
120
121
  children: showNewTagForm ? t("admin.tagsContent.cancelButton") : t("admin.tagsContent.createButton")
121
122
  }
122
123
  ) }),
123
- showNewTagForm && /* @__PURE__ */ jsx(Grid, { item: true, xs: 12, children: /* @__PURE__ */ jsx(TagsForm, { initialData: {}, onSubmit }) }),
124
+ showNewTagForm && /* @__PURE__ */ jsx(Grid, { item: true, xs: 12, children: /* @__PURE__ */ jsx(
125
+ TitleForm,
126
+ {
127
+ translationKeys,
128
+ onSubmit,
129
+ testIds: {
130
+ form: "tag-form",
131
+ input: "tag-title-input",
132
+ button: "tag-submit-button"
133
+ }
134
+ }
135
+ ) }),
124
136
  /* @__PURE__ */ jsx(Grid, { item: true, xs: 12, children: /* @__PURE__ */ jsx(
125
137
  Table,
126
138
  {
@@ -132,9 +144,9 @@ const TagsContent = () => {
132
144
  }
133
145
  ) }),
134
146
  /* @__PURE__ */ jsx(
135
- DeleteTagDialog,
147
+ DeleteDialog,
136
148
  {
137
- open: isDeleteDialogOpen,
149
+ isOpen: isDeleteDialogOpen,
138
150
  onCancel: onCancelDelete,
139
151
  onConfirm: onConfirmDelete
140
152
  }
@@ -1 +1 @@
1
- {"version":3,"file":"TagsContent.esm.js","sources":["../../../../src/components/Admin/TagsContent/TagsContent.tsx"],"sourcesContent":["/*\n * Copyright 2025 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 { useState } from 'react';\nimport {\n ErrorPanel,\n Progress,\n Table,\n TableColumn,\n} from '@backstage/core-components';\nimport {\n CreateTagRequest,\n announcementsApiRef,\n useAnnouncementsTranslation,\n useTags,\n} from '@backstage-community/plugin-announcements-react';\nimport {\n announcementCreatePermission,\n announcementDeletePermission,\n Tag,\n} from '@backstage-community/plugin-announcements-common';\nimport { useApi, alertApiRef } from '@backstage/core-plugin-api';\nimport {\n RequirePermission,\n usePermission,\n} from '@backstage/plugin-permission-react';\nimport { ResponseError } from '@backstage/errors';\nimport { Button, Grid, IconButton, Typography } from '@material-ui/core';\nimport DeleteIcon from '@material-ui/icons/Delete';\n\nimport { useDeleteTagDialogState } from './useDeleteTagDialogState';\nimport { DeleteTagDialog } from './DeleteTagDialog';\nimport { TagsForm } from './TagsForm';\n\nexport const TagsContent = () => {\n const [showNewTagForm, setShowNewTagForm] = useState(false);\n const { tags, loading, error, retry: refresh } = useTags();\n const announcementsApi = useApi(announcementsApiRef);\n const alertApi = useApi(alertApiRef);\n const { t } = useAnnouncementsTranslation();\n\n const {\n isOpen: isDeleteDialogOpen,\n open: openDeleteDialog,\n close: closeDeleteDialog,\n tag: tagToDelete,\n } = useDeleteTagDialogState();\n\n const { loading: loadingCreatePermission, allowed: canCreateTag } =\n usePermission({\n permission: announcementCreatePermission,\n });\n\n const { loading: loadingDeletePermission, allowed: canDeleteAnnouncement } =\n usePermission({\n permission: announcementDeletePermission,\n });\n\n const onSubmit = async (request: CreateTagRequest) => {\n const { title } = request;\n\n try {\n await announcementsApi.createTag({\n title,\n });\n\n alertApi.post({\n message: `${title} ${t('admin.tagsContent.createdMessage')}`,\n severity: 'success',\n });\n\n refresh();\n } catch (err: any) {\n if (err.response?.status === 409) {\n alertApi.post({\n message: t('admin.tagsContent.errors.alreadyExists'),\n severity: 'error',\n });\n } else {\n alertApi.post({\n message: (err as Error).message,\n severity: 'error',\n });\n }\n }\n };\n\n const onCreateButtonClick = () => {\n setShowNewTagForm(!showNewTagForm);\n };\n\n const onCancelDelete = () => {\n closeDeleteDialog();\n };\n\n const onConfirmDelete = async () => {\n closeDeleteDialog();\n\n try {\n await announcementsApi.deleteTag(tagToDelete!.slug);\n\n alertApi.post({\n message: t('admin.tagsContent.table.tagDeleted'),\n severity: 'success',\n });\n } catch (err) {\n alertApi.post({\n message: (err as ResponseError).body.error.message,\n severity: 'error',\n });\n }\n\n refresh();\n };\n\n if (loading) {\n return <Progress />;\n }\n if (error) {\n return <ErrorPanel error={error} />;\n }\n\n const columns: TableColumn<Tag>[] = [\n {\n title: <Typography>{t('admin.tagsContent.table.title')}</Typography>,\n sorting: true,\n field: 'title',\n render: rowData => rowData.title,\n },\n {\n title: <Typography>{t('admin.tagsContent.table.slug')}</Typography>,\n sorting: true,\n field: 'slug',\n render: rowData => rowData.slug,\n },\n {\n title: <Typography>{t('admin.tagsContent.table.actions')}</Typography>,\n render: rowData => {\n return (\n <IconButton\n aria-label=\"delete\"\n disabled={loadingDeletePermission || !canDeleteAnnouncement}\n onClick={() => openDeleteDialog(rowData)}\n >\n <DeleteIcon fontSize=\"small\" data-testid=\"delete-icon\" />\n </IconButton>\n );\n },\n },\n ];\n\n return (\n <RequirePermission permission={announcementCreatePermission}>\n <Grid container>\n <Grid item xs={12}>\n <Button\n disabled={loadingCreatePermission || !canCreateTag}\n variant=\"contained\"\n onClick={() => onCreateButtonClick()}\n >\n {showNewTagForm\n ? t('admin.tagsContent.cancelButton')\n : t('admin.tagsContent.createButton')}\n </Button>\n </Grid>\n\n {showNewTagForm && (\n <Grid item xs={12}>\n <TagsForm initialData={{} as Tag} onSubmit={onSubmit} />\n </Grid>\n )}\n\n <Grid item xs={12}>\n <Table\n title=\"Tags\"\n options={{ pageSize: 20, search: true }}\n columns={columns}\n data={tags ?? []}\n emptyContent={\n <Typography style={{ padding: 2, textAlign: 'center' }}>\n {t('admin.tagsContent.table.noTagsFound')}\n </Typography>\n }\n />\n </Grid>\n\n <DeleteTagDialog\n open={isDeleteDialogOpen}\n onCancel={onCancelDelete}\n onConfirm={onConfirmDelete}\n />\n </Grid>\n </RequirePermission>\n );\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TagsContent.esm.js","sources":["../../../../src/components/Admin/TagsContent/TagsContent.tsx"],"sourcesContent":["/*\n * Copyright 2025 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 { useState } from 'react';\nimport {\n ErrorPanel,\n Progress,\n Table,\n TableColumn,\n} from '@backstage/core-components';\nimport {\n CreateTagRequest,\n announcementsApiRef,\n useAnnouncementsTranslation,\n useTags,\n useAnnouncementsPermissions,\n} from '@backstage-community/plugin-announcements-react';\nimport {\n announcementCreatePermission,\n Tag,\n} from '@backstage-community/plugin-announcements-common';\nimport { useApi, alertApiRef } from '@backstage/core-plugin-api';\nimport { RequirePermission } from '@backstage/plugin-permission-react';\nimport { ResponseError } from '@backstage/errors';\nimport { Button, Grid, IconButton, Typography } from '@material-ui/core';\nimport DeleteIcon from '@material-ui/icons/Delete';\n\nimport { useDeleteDialogState, DeleteDialog, TitleForm } from '../shared';\n\nexport const TagsContent = () => {\n const [showNewTagForm, setShowNewTagForm] = useState(false);\n const { tags, loading, error, retry: refresh } = useTags();\n const announcementsApi = useApi(announcementsApiRef);\n const alertApi = useApi(alertApiRef);\n const { t } = useAnnouncementsTranslation();\n\n const {\n isOpen: isDeleteDialogOpen,\n open: openDeleteDialog,\n close: closeDeleteDialog,\n item: tagToDelete,\n } = useDeleteDialogState<Tag>();\n\n const permissions = useAnnouncementsPermissions();\n\n const translationKeys = {\n new: t('tagsForm.newTag'),\n edit: t('tagsForm.editTag'),\n titleLabel: t('tagsForm.titleLabel'),\n submit: t('tagsForm.submit'),\n };\n\n const onSubmit = async (request: CreateTagRequest) => {\n const { title } = request;\n\n try {\n await announcementsApi.createTag({\n title,\n });\n\n alertApi.post({\n message: `${title} ${t('admin.tagsContent.createdMessage')}`,\n severity: 'success',\n });\n\n refresh();\n } catch (err: any) {\n if (err.response?.status === 409) {\n alertApi.post({\n message: t('admin.tagsContent.errors.alreadyExists'),\n severity: 'error',\n });\n } else {\n alertApi.post({\n message: (err as Error).message,\n severity: 'error',\n });\n }\n }\n };\n\n const onCreateButtonClick = () => {\n setShowNewTagForm(!showNewTagForm);\n };\n\n const onCancelDelete = () => {\n closeDeleteDialog();\n };\n\n const onConfirmDelete = async () => {\n closeDeleteDialog();\n\n try {\n await announcementsApi.deleteTag(tagToDelete!.slug);\n\n alertApi.post({\n message: t('admin.tagsContent.table.tagDeleted'),\n severity: 'success',\n });\n } catch (err) {\n alertApi.post({\n message: (err as ResponseError).body.error.message,\n severity: 'error',\n });\n }\n\n refresh();\n };\n\n if (loading) {\n return <Progress />;\n }\n if (error) {\n return <ErrorPanel error={error} />;\n }\n\n const columns: TableColumn<Tag>[] = [\n {\n title: <Typography>{t('admin.tagsContent.table.title')}</Typography>,\n sorting: true,\n field: 'title',\n render: rowData => rowData.title,\n },\n {\n title: <Typography>{t('admin.tagsContent.table.slug')}</Typography>,\n sorting: true,\n field: 'slug',\n render: rowData => rowData.slug,\n },\n {\n title: <Typography>{t('admin.tagsContent.table.actions')}</Typography>,\n render: rowData => {\n return (\n <IconButton\n aria-label=\"delete\"\n disabled={permissions.delete.loading || !permissions.delete.allowed}\n onClick={() => openDeleteDialog(rowData)}\n >\n <DeleteIcon fontSize=\"small\" data-testid=\"delete-icon\" />\n </IconButton>\n );\n },\n },\n ];\n\n return (\n <RequirePermission permission={announcementCreatePermission}>\n <Grid container>\n <Grid item xs={12}>\n <Button\n disabled={permissions.create.loading || !permissions.create.allowed}\n variant=\"contained\"\n onClick={() => onCreateButtonClick()}\n >\n {showNewTagForm\n ? t('admin.tagsContent.cancelButton')\n : t('admin.tagsContent.createButton')}\n </Button>\n </Grid>\n\n {showNewTagForm && (\n <Grid item xs={12}>\n <TitleForm<Tag>\n translationKeys={translationKeys}\n onSubmit={onSubmit}\n testIds={{\n form: 'tag-form',\n input: 'tag-title-input',\n button: 'tag-submit-button',\n }}\n />\n </Grid>\n )}\n\n <Grid item xs={12}>\n <Table\n title=\"Tags\"\n options={{ pageSize: 20, search: true }}\n columns={columns}\n data={tags ?? []}\n emptyContent={\n <Typography style={{ padding: 2, textAlign: 'center' }}>\n {t('admin.tagsContent.table.noTagsFound')}\n </Typography>\n }\n />\n </Grid>\n\n <DeleteDialog\n isOpen={isDeleteDialogOpen}\n onCancel={onCancelDelete}\n onConfirm={onConfirmDelete}\n />\n </Grid>\n </RequirePermission>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { Dialog, DialogTitle, DialogActions, Button } from '@material-ui/core';
3
+ import { useAnnouncementsTranslation, useAnnouncementsPermissions } from '@backstage-community/plugin-announcements-react';
4
+
5
+ const DeleteDialog = (props) => {
6
+ const { isOpen, onConfirm, onCancel } = props;
7
+ const { t } = useAnnouncementsTranslation();
8
+ const permissions = useAnnouncementsPermissions();
9
+ const dialogTitle = t("confirmDeleteDialog.title");
10
+ const cancelText = t("confirmDeleteDialog.cancel");
11
+ const deleteText = t("confirmDeleteDialog.delete");
12
+ return /* @__PURE__ */ jsxs(Dialog, { open: isOpen, onClose: onCancel, children: [
13
+ /* @__PURE__ */ jsx(DialogTitle, { children: dialogTitle }),
14
+ /* @__PURE__ */ jsxs(DialogActions, { children: [
15
+ /* @__PURE__ */ jsx(Button, { onClick: onCancel, children: cancelText }),
16
+ /* @__PURE__ */ jsx(
17
+ Button,
18
+ {
19
+ disabled: permissions.delete.loading || !permissions.delete.allowed,
20
+ onClick: onConfirm,
21
+ color: "secondary",
22
+ children: deleteText
23
+ }
24
+ )
25
+ ] })
26
+ ] });
27
+ };
28
+
29
+ export { DeleteDialog };
30
+ //# sourceMappingURL=DeleteDialog.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DeleteDialog.esm.js","sources":["../../../../../src/components/Admin/shared/DeleteDialog/DeleteDialog.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { Button, Dialog, DialogActions, DialogTitle } from '@material-ui/core';\nimport {\n useAnnouncementsTranslation,\n useAnnouncementsPermissions,\n} from '@backstage-community/plugin-announcements-react';\n\ntype DeleteDialogProps = {\n isOpen: boolean;\n onConfirm: () => void;\n onCancel: () => void;\n};\n\nexport const DeleteDialog = (props: DeleteDialogProps) => {\n const { isOpen, onConfirm, onCancel } = props;\n\n const { t } = useAnnouncementsTranslation();\n const permissions = useAnnouncementsPermissions();\n\n const dialogTitle = t('confirmDeleteDialog.title');\n const cancelText = t('confirmDeleteDialog.cancel');\n const deleteText = t('confirmDeleteDialog.delete');\n\n return (\n <Dialog open={isOpen} onClose={onCancel}>\n <DialogTitle>{dialogTitle}</DialogTitle>\n <DialogActions>\n <Button onClick={onCancel}>{cancelText}</Button>\n\n <Button\n disabled={permissions.delete.loading || !permissions.delete.allowed}\n onClick={onConfirm}\n color=\"secondary\"\n >\n {deleteText}\n </Button>\n </DialogActions>\n </Dialog>\n );\n};\n"],"names":[],"mappings":";;;;AA2Ba,MAAA,YAAA,GAAe,CAAC,KAA6B,KAAA;AACxD,EAAA,MAAM,EAAE,MAAA,EAAQ,SAAW,EAAA,QAAA,EAAa,GAAA,KAAA;AAExC,EAAM,MAAA,EAAE,CAAE,EAAA,GAAI,2BAA4B,EAAA;AAC1C,EAAA,MAAM,cAAc,2BAA4B,EAAA;AAEhD,EAAM,MAAA,WAAA,GAAc,EAAE,2BAA2B,CAAA;AACjD,EAAM,MAAA,UAAA,GAAa,EAAE,4BAA4B,CAAA;AACjD,EAAM,MAAA,UAAA,GAAa,EAAE,4BAA4B,CAAA;AAEjD,EAAA,uBACG,IAAA,CAAA,MAAA,EAAA,EAAO,IAAM,EAAA,MAAA,EAAQ,SAAS,QAC7B,EAAA,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,eAAa,QAAY,EAAA,WAAA,EAAA,CAAA;AAAA,yBACzB,aACC,EAAA,EAAA,QAAA,EAAA;AAAA,sBAAC,GAAA,CAAA,MAAA,EAAA,EAAO,OAAS,EAAA,QAAA,EAAW,QAAW,EAAA,UAAA,EAAA,CAAA;AAAA,sBAEvC,GAAA;AAAA,QAAC,MAAA;AAAA,QAAA;AAAA,UACC,UAAU,WAAY,CAAA,MAAA,CAAO,OAAW,IAAA,CAAC,YAAY,MAAO,CAAA,OAAA;AAAA,UAC5D,OAAS,EAAA,SAAA;AAAA,UACT,KAAM,EAAA,WAAA;AAAA,UAEL,QAAA,EAAA;AAAA;AAAA;AACH,KACF,EAAA;AAAA,GACF,EAAA,CAAA;AAEJ;;;;"}
@@ -1,12 +1,12 @@
1
1
  import { useState, useCallback } from 'react';
2
2
 
3
- function useDeleteTagDialogState() {
3
+ function useDeleteDialogState() {
4
4
  const [state, setState] = useState({ open: false });
5
5
  const setOpen = useCallback(
6
- (t) => {
6
+ (item) => {
7
7
  setState({
8
8
  open: true,
9
- tag: t
9
+ item
10
10
  });
11
11
  },
12
12
  [setState]
@@ -14,16 +14,16 @@ function useDeleteTagDialogState() {
14
14
  const setClosed = useCallback(() => {
15
15
  setState({
16
16
  open: false,
17
- tag: void 0
17
+ item: void 0
18
18
  });
19
19
  }, [setState]);
20
20
  return {
21
21
  open: setOpen,
22
22
  close: setClosed,
23
- tag: state.tag,
23
+ item: state.item,
24
24
  isOpen: state.open
25
25
  };
26
26
  }
27
27
 
28
- export { useDeleteTagDialogState };
29
- //# sourceMappingURL=useDeleteTagDialogState.esm.js.map
28
+ export { useDeleteDialogState };
29
+ //# sourceMappingURL=useDeleteDialogState.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDeleteDialogState.esm.js","sources":["../../../../../src/components/Admin/shared/DeleteDialog/useDeleteDialogState.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useCallback, useState } from 'react';\n\ntype DeleteDialogState<T> = {\n open: (item: T) => void;\n close: () => void;\n isOpen: boolean;\n item?: T;\n};\n\nexport function useDeleteDialogState<T>(): DeleteDialogState<T> {\n const [state, setState] = useState<{\n open: boolean;\n item?: T;\n }>({ open: false });\n\n const setOpen = useCallback(\n (item: T) => {\n setState({\n open: true,\n item,\n });\n },\n [setState],\n );\n\n const setClosed = useCallback(() => {\n setState({\n open: false,\n item: undefined,\n });\n }, [setState]);\n\n return {\n open: setOpen,\n close: setClosed,\n item: state.item,\n isOpen: state.open,\n };\n}\n"],"names":[],"mappings":";;AAwBO,SAAS,oBAAgD,GAAA;AAC9D,EAAM,MAAA,CAAC,OAAO,QAAQ,CAAA,GAAI,SAGvB,EAAE,IAAA,EAAM,OAAO,CAAA;AAElB,EAAA,MAAM,OAAU,GAAA,WAAA;AAAA,IACd,CAAC,IAAY,KAAA;AACX,MAAS,QAAA,CAAA;AAAA,QACP,IAAM,EAAA,IAAA;AAAA,QACN;AAAA,OACD,CAAA;AAAA,KACH;AAAA,IACA,CAAC,QAAQ;AAAA,GACX;AAEA,EAAM,MAAA,SAAA,GAAY,YAAY,MAAM;AAClC,IAAS,QAAA,CAAA;AAAA,MACP,IAAM,EAAA,KAAA;AAAA,MACN,IAAM,EAAA,KAAA;AAAA,KACP,CAAA;AAAA,GACH,EAAG,CAAC,QAAQ,CAAC,CAAA;AAEb,EAAO,OAAA;AAAA,IACL,IAAM,EAAA,OAAA;AAAA,IACN,KAAO,EAAA,SAAA;AAAA,IACP,MAAM,KAAM,CAAA,IAAA;AAAA,IACZ,QAAQ,KAAM,CAAA;AAAA,GAChB;AACF;;;;"}
@@ -0,0 +1,71 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { useState, useMemo } from 'react';
3
+ import { InfoCard } from '@backstage/core-components';
4
+ import { useAnnouncementsPermissions } from '@backstage-community/plugin-announcements-react';
5
+ import { Box, TextField, Button } from '@material-ui/core';
6
+
7
+ const TitleForm = (props) => {
8
+ const { initialData, translationKeys, onSubmit, testIds } = props;
9
+ const [form, setForm] = useState(initialData ?? { title: "" });
10
+ const [loading, setLoading] = useState(false);
11
+ const permissions = useAnnouncementsPermissions();
12
+ const handleChange = (event) => {
13
+ setForm((prev) => ({
14
+ ...prev,
15
+ title: event.target.value
16
+ }));
17
+ };
18
+ const handleSubmit = async (event) => {
19
+ setLoading(true);
20
+ event.preventDefault();
21
+ try {
22
+ await onSubmit(form);
23
+ } finally {
24
+ setLoading(false);
25
+ }
26
+ };
27
+ const isDisabled = useMemo(() => {
28
+ return loading || !form?.title || permissions.create.loading || !permissions.create.allowed;
29
+ }, [
30
+ loading,
31
+ form?.title,
32
+ permissions.create.loading,
33
+ permissions.create.allowed
34
+ ]);
35
+ return /* @__PURE__ */ jsx(
36
+ InfoCard,
37
+ {
38
+ title: initialData?.title ? translationKeys.edit : translationKeys.new,
39
+ children: /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, "data-testid": testIds?.form ?? "title-form", children: [
40
+ /* @__PURE__ */ jsx(Box, { py: 2, children: /* @__PURE__ */ jsx(
41
+ TextField,
42
+ {
43
+ id: "title",
44
+ "data-testid": testIds?.input ?? "title-input",
45
+ type: "text",
46
+ label: translationKeys.titleLabel,
47
+ value: form.title,
48
+ onChange: handleChange,
49
+ variant: "outlined",
50
+ fullWidth: true,
51
+ required: true
52
+ }
53
+ ) }),
54
+ /* @__PURE__ */ jsx(
55
+ Button,
56
+ {
57
+ variant: "contained",
58
+ color: "primary",
59
+ type: "submit",
60
+ "data-testid": testIds?.button ?? "title-submit-button",
61
+ disabled: isDisabled,
62
+ children: translationKeys.submit
63
+ }
64
+ )
65
+ ] })
66
+ }
67
+ );
68
+ };
69
+
70
+ export { TitleForm };
71
+ //# sourceMappingURL=TitleForm.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TitleForm.esm.js","sources":["../../../../../src/components/Admin/shared/TitleForm/TitleForm.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { ChangeEvent, FormEvent, useMemo, useState } from 'react';\nimport { InfoCard } from '@backstage/core-components';\nimport { useAnnouncementsPermissions } from '@backstage-community/plugin-announcements-react';\nimport { Box, Button, TextField } from '@material-ui/core';\n\ntype TitleFormTranslationKeys = {\n new: string;\n edit: string;\n titleLabel: string;\n submit: string;\n};\n\ntype TitleFormTestIds = {\n form?: string;\n input?: string;\n button?: string;\n};\n\nexport type TitleFormRequest = {\n title: string;\n};\n\nexport type TitleFormProps<T extends TitleFormRequest> = {\n initialData?: T;\n translationKeys: TitleFormTranslationKeys;\n onSubmit: (data: T) => Promise<void>;\n testIds?: TitleFormTestIds;\n};\n\nexport const TitleForm = <T extends TitleFormRequest>(\n props: TitleFormProps<T>,\n) => {\n const { initialData, translationKeys, onSubmit, testIds } = props;\n\n const [form, setForm] = useState<T>(initialData ?? ({ title: '' } as T));\n const [loading, setLoading] = useState(false);\n const permissions = useAnnouncementsPermissions();\n\n const handleChange = (event: ChangeEvent<HTMLInputElement>) => {\n setForm(prev => ({\n ...prev,\n title: event.target.value,\n }));\n };\n\n const handleSubmit = async (event: FormEvent<HTMLFormElement>) => {\n setLoading(true);\n event.preventDefault();\n\n try {\n await onSubmit(form);\n } finally {\n // will still handle setting loading to false even if onSubmit fails\n setLoading(false);\n }\n };\n\n const isDisabled = useMemo(() => {\n return (\n loading ||\n !form?.title ||\n permissions.create.loading ||\n !permissions.create.allowed\n );\n }, [\n loading,\n form?.title,\n permissions.create.loading,\n permissions.create.allowed,\n ]);\n\n return (\n <InfoCard\n title={initialData?.title ? translationKeys.edit : translationKeys.new}\n >\n <form onSubmit={handleSubmit} data-testid={testIds?.form ?? 'title-form'}>\n <Box py={2}>\n <TextField\n id=\"title\"\n data-testid={testIds?.input ?? 'title-input'}\n type=\"text\"\n label={translationKeys.titleLabel}\n value={form.title}\n onChange={handleChange}\n variant=\"outlined\"\n fullWidth\n required\n />\n </Box>\n\n <Button\n variant=\"contained\"\n color=\"primary\"\n type=\"submit\"\n data-testid={testIds?.button ?? 'title-submit-button'}\n disabled={isDisabled}\n >\n {translationKeys.submit}\n </Button>\n </form>\n </InfoCard>\n );\n};\n"],"names":[],"mappings":";;;;;;AA4Ca,MAAA,SAAA,GAAY,CACvB,KACG,KAAA;AACH,EAAA,MAAM,EAAE,WAAA,EAAa,eAAiB,EAAA,QAAA,EAAU,SAAY,GAAA,KAAA;AAE5D,EAAM,MAAA,CAAC,MAAM,OAAO,CAAA,GAAI,SAAY,WAAgB,IAAA,EAAE,KAAO,EAAA,EAAA,EAAU,CAAA;AACvE,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAS,KAAK,CAAA;AAC5C,EAAA,MAAM,cAAc,2BAA4B,EAAA;AAEhD,EAAM,MAAA,YAAA,GAAe,CAAC,KAAyC,KAAA;AAC7D,IAAA,OAAA,CAAQ,CAAS,IAAA,MAAA;AAAA,MACf,GAAG,IAAA;AAAA,MACH,KAAA,EAAO,MAAM,MAAO,CAAA;AAAA,KACpB,CAAA,CAAA;AAAA,GACJ;AAEA,EAAM,MAAA,YAAA,GAAe,OAAO,KAAsC,KAAA;AAChE,IAAA,UAAA,CAAW,IAAI,CAAA;AACf,IAAA,KAAA,CAAM,cAAe,EAAA;AAErB,IAAI,IAAA;AACF,MAAA,MAAM,SAAS,IAAI,CAAA;AAAA,KACnB,SAAA;AAEA,MAAA,UAAA,CAAW,KAAK,CAAA;AAAA;AAClB,GACF;AAEA,EAAM,MAAA,UAAA,GAAa,QAAQ,MAAM;AAC/B,IACE,OAAA,OAAA,IACA,CAAC,IAAM,EAAA,KAAA,IACP,YAAY,MAAO,CAAA,OAAA,IACnB,CAAC,WAAA,CAAY,MAAO,CAAA,OAAA;AAAA,GAErB,EAAA;AAAA,IACD,OAAA;AAAA,IACA,IAAM,EAAA,KAAA;AAAA,IACN,YAAY,MAAO,CAAA,OAAA;AAAA,IACnB,YAAY,MAAO,CAAA;AAAA,GACpB,CAAA;AAED,EACE,uBAAA,GAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,KAAO,EAAA,WAAA,EAAa,KAAQ,GAAA,eAAA,CAAgB,OAAO,eAAgB,CAAA,GAAA;AAAA,MAEnE,+BAAC,MAAK,EAAA,EAAA,QAAA,EAAU,cAAc,aAAa,EAAA,OAAA,EAAS,QAAQ,YAC1D,EAAA,QAAA,EAAA;AAAA,wBAAC,GAAA,CAAA,GAAA,EAAA,EAAI,IAAI,CACP,EAAA,QAAA,kBAAA,GAAA;AAAA,UAAC,SAAA;AAAA,UAAA;AAAA,YACC,EAAG,EAAA,OAAA;AAAA,YACH,aAAA,EAAa,SAAS,KAAS,IAAA,aAAA;AAAA,YAC/B,IAAK,EAAA,MAAA;AAAA,YACL,OAAO,eAAgB,CAAA,UAAA;AAAA,YACvB,OAAO,IAAK,CAAA,KAAA;AAAA,YACZ,QAAU,EAAA,YAAA;AAAA,YACV,OAAQ,EAAA,UAAA;AAAA,YACR,SAAS,EAAA,IAAA;AAAA,YACT,QAAQ,EAAA;AAAA;AAAA,SAEZ,EAAA,CAAA;AAAA,wBAEA,GAAA;AAAA,UAAC,MAAA;AAAA,UAAA;AAAA,YACC,OAAQ,EAAA,WAAA;AAAA,YACR,KAAM,EAAA,SAAA;AAAA,YACN,IAAK,EAAA,QAAA;AAAA,YACL,aAAA,EAAa,SAAS,MAAU,IAAA,qBAAA;AAAA,YAChC,QAAU,EAAA,UAAA;AAAA,YAET,QAAgB,EAAA,eAAA,CAAA;AAAA;AAAA;AACnB,OACF,EAAA;AAAA;AAAA,GACF;AAEJ;;;;"}
@@ -1,12 +1,10 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
2
  import { DateTime } from 'luxon';
3
- import { usePermission } from '@backstage/plugin-permission-react';
4
3
  import { Progress, InfoCard, Link } from '@backstage/core-components';
5
4
  import { useApi, useRouteRef, useAnalytics } from '@backstage/core-plugin-api';
6
- import { announcementEntityPermissions } from '@backstage-community/plugin-announcements-common';
7
5
  import { rootRouteRef, announcementViewRouteRef, announcementAdminRouteRef } from '../../routes.esm.js';
8
6
  import { formatAnnouncementStartTime } from '../utils/announcementDateUtils.esm.js';
9
- import { announcementsApiRef, useAnnouncementsTranslation, useAnnouncements } from '@backstage-community/plugin-announcements-react';
7
+ import { announcementsApiRef, useAnnouncementsTranslation, useAnnouncements, useAnnouncementsPermissions } from '@backstage-community/plugin-announcements-react';
10
8
  import { makeStyles, List, ListItem, ListItemIcon, ListItemText, Box, Typography, Chip } from '@material-ui/core';
11
9
  import { Alert } from '@material-ui/lab';
12
10
  import NewReleasesIcon from '@material-ui/icons/NewReleases';
@@ -47,10 +45,7 @@ const AnnouncementsCard = ({
47
45
  order,
48
46
  current
49
47
  });
50
- const { announcementCreatePermission } = announcementEntityPermissions;
51
- const { loading: loadingPermission, allowed: canAdd } = usePermission({
52
- permission: announcementCreatePermission
53
- });
48
+ const permissions = useAnnouncementsPermissions();
54
49
  if (loading) {
55
50
  return /* @__PURE__ */ jsx(Progress, {});
56
51
  } else if (error) {
@@ -137,7 +132,7 @@ const AnnouncementsCard = ({
137
132
  ),
138
133
  " "
139
134
  ] }, announcement.id)),
140
- announcements.count === 0 && !loadingPermission && canAdd && /* @__PURE__ */ jsx(ListItem, { children: /* @__PURE__ */ jsxs(ListItemText, { children: [
135
+ announcements.count === 0 && !permissions.create.loading && permissions.create.allowed && /* @__PURE__ */ jsx(ListItem, { children: /* @__PURE__ */ jsxs(ListItemText, { children: [
141
136
  `${t("announcementsCard.noAnnouncements")} `,
142
137
  /* @__PURE__ */ jsx(Link, { to: announcementAdminLink(), variant: "inherit", children: t("announcementsCard.addOne") }),
143
138
  "?"
@@ -1 +1 @@
1
- {"version":3,"file":"AnnouncementsCard.esm.js","sources":["../../../src/components/AnnouncementsCard/AnnouncementsCard.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { DateTime } from 'luxon';\nimport { usePermission } from '@backstage/plugin-permission-react';\nimport {\n InfoCard,\n InfoCardVariants,\n Link,\n Progress,\n} from '@backstage/core-components';\nimport { useApi, useRouteRef, useAnalytics } from '@backstage/core-plugin-api';\nimport { announcementEntityPermissions } from '@backstage-community/plugin-announcements-common';\nimport {\n announcementAdminRouteRef,\n announcementViewRouteRef,\n rootRouteRef,\n} from '../../routes';\nimport { formatAnnouncementStartTime } from '../utils/announcementDateUtils';\nimport {\n announcementsApiRef,\n useAnnouncements,\n useAnnouncementsTranslation,\n} from '@backstage-community/plugin-announcements-react';\nimport {\n makeStyles,\n List,\n ListItem,\n ListItemIcon,\n ListItemText,\n Typography,\n Box,\n Chip,\n} from '@material-ui/core';\nimport { Alert } from '@material-ui/lab';\nimport NewReleasesIcon from '@material-ui/icons/NewReleases';\n\nconst useStyles = makeStyles({\n newAnnouncementIcon: {\n minWidth: '36px',\n },\n chipStyle: {\n marginRight: 4,\n marginBottom: 4,\n },\n});\n\ntype AnnouncementsCardOpts = {\n title?: string;\n max?: number;\n category?: string;\n active?: boolean;\n variant?: InfoCardVariants;\n sortBy?: 'created_at' | 'start_at';\n order?: 'asc' | 'desc';\n current?: boolean;\n hideStartAt?: boolean;\n};\n\nexport const AnnouncementsCard = ({\n title,\n max,\n category,\n active,\n variant = 'gridItem',\n sortBy,\n order,\n current,\n hideStartAt,\n}: AnnouncementsCardOpts) => {\n const classes = useStyles();\n const announcementsApi = useApi(announcementsApiRef);\n const announcementsLink = useRouteRef(rootRouteRef);\n const viewAnnouncementLink = useRouteRef(announcementViewRouteRef);\n const announcementAdminLink = useRouteRef(announcementAdminRouteRef);\n const lastSeen = announcementsApi.lastSeenDate();\n const analytics = useAnalytics();\n const { t } = useAnnouncementsTranslation();\n\n const { announcements, loading, error } = useAnnouncements({\n max: max || 5,\n category,\n active,\n sortBy,\n order,\n current,\n });\n\n const { announcementCreatePermission } = announcementEntityPermissions;\n const { loading: loadingPermission, allowed: canAdd } = usePermission({\n permission: announcementCreatePermission,\n });\n\n if (loading) {\n return <Progress />;\n } else if (error) {\n return <Alert severity=\"error\">{error.message}</Alert>;\n }\n\n const deepLink = {\n link: announcementsLink(),\n title: t('announcementsCard.seeAll'),\n };\n\n return (\n <InfoCard\n title={title || t('announcementsCard.announcements')}\n variant={variant}\n deepLink={deepLink}\n >\n <List dense>\n {announcements.results.map(announcement => (\n <ListItem key={announcement.id}>\n <ListItemIcon\n className={classes.newAnnouncementIcon}\n style={{\n visibility:\n lastSeen < DateTime.fromISO(announcement.created_at)\n ? 'visible'\n : 'hidden',\n }}\n title={t('announcementsCard.new')}\n >\n <NewReleasesIcon />\n </ListItemIcon>\n <ListItemText\n primary={\n <Link\n to={viewAnnouncementLink({ id: announcement.id })}\n variant=\"inherit\"\n onClick={() =>\n analytics.captureEvent('click', announcement.title, {\n attributes: {\n announcementId: announcement.id,\n location: 'AnnouncementsCard',\n },\n })\n }\n >\n {announcement.title}\n </Link>\n }\n secondary={\n <Box>\n <Typography variant=\"body2\" color=\"textSecondary\">\n {DateTime.fromISO(announcement.created_at).toRelative()}\n {announcement.category && (\n <>\n {` ${t('announcementsCard.in')} `}\n <Link\n to={`${announcementsLink()}?category=${\n announcement.category.slug\n }`}\n variant=\"inherit\"\n >\n {announcement.category.title}\n </Link>\n </>\n )}\n </Typography>\n <Typography variant=\"body2\" color=\"textSecondary\">\n {announcement.excerpt}\n {announcement.tags && announcement.tags.length > 0 && (\n <Box mt={1}>\n {announcement.tags.map(tag => (\n <Chip\n key={tag.slug}\n size=\"small\"\n label={tag.title}\n component={Link}\n to={`${announcementsLink()}?tags=${tag.slug}`}\n clickable\n className={classes.chipStyle}\n />\n ))}\n </Box>\n )}\n </Typography>\n {!hideStartAt && (\n <Typography variant=\"caption\" color=\"textSecondary\">\n {formatAnnouncementStartTime(\n announcement.start_at,\n t('announcementsCard.occurred'),\n t('announcementsCard.scheduled'),\n t('announcementsCard.today'),\n )}\n </Typography>\n )}\n </Box>\n }\n />{' '}\n </ListItem>\n ))}\n {announcements.count === 0 && !loadingPermission && canAdd && (\n <ListItem>\n <ListItemText>\n {`${t('announcementsCard.noAnnouncements')} `}\n <Link to={announcementAdminLink()} variant=\"inherit\">\n {t('announcementsCard.addOne')}\n </Link>\n ?\n </ListItemText>\n </ListItem>\n )}\n </List>\n </InfoCard>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;AAiDA,MAAM,YAAY,UAAW,CAAA;AAAA,EAC3B,mBAAqB,EAAA;AAAA,IACnB,QAAU,EAAA;AAAA,GACZ;AAAA,EACA,SAAW,EAAA;AAAA,IACT,WAAa,EAAA,CAAA;AAAA,IACb,YAAc,EAAA;AAAA;AAElB,CAAC,CAAA;AAcM,MAAM,oBAAoB,CAAC;AAAA,EAChC,KAAA;AAAA,EACA,GAAA;AAAA,EACA,QAAA;AAAA,EACA,MAAA;AAAA,EACA,OAAU,GAAA,UAAA;AAAA,EACV,MAAA;AAAA,EACA,KAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF,CAA6B,KAAA;AAC3B,EAAA,MAAM,UAAU,SAAU,EAAA;AAC1B,EAAM,MAAA,gBAAA,GAAmB,OAAO,mBAAmB,CAAA;AACnD,EAAM,MAAA,iBAAA,GAAoB,YAAY,YAAY,CAAA;AAClD,EAAM,MAAA,oBAAA,GAAuB,YAAY,wBAAwB,CAAA;AACjE,EAAM,MAAA,qBAAA,GAAwB,YAAY,yBAAyB,CAAA;AACnE,EAAM,MAAA,QAAA,GAAW,iBAAiB,YAAa,EAAA;AAC/C,EAAA,MAAM,YAAY,YAAa,EAAA;AAC/B,EAAM,MAAA,EAAE,CAAE,EAAA,GAAI,2BAA4B,EAAA;AAE1C,EAAA,MAAM,EAAE,aAAA,EAAe,OAAS,EAAA,KAAA,KAAU,gBAAiB,CAAA;AAAA,IACzD,KAAK,GAAO,IAAA,CAAA;AAAA,IACZ,QAAA;AAAA,IACA,MAAA;AAAA,IACA,MAAA;AAAA,IACA,KAAA;AAAA,IACA;AAAA,GACD,CAAA;AAED,EAAM,MAAA,EAAE,8BAAiC,GAAA,6BAAA;AACzC,EAAA,MAAM,EAAE,OAAS,EAAA,iBAAA,EAAmB,OAAS,EAAA,MAAA,KAAW,aAAc,CAAA;AAAA,IACpE,UAAY,EAAA;AAAA,GACb,CAAA;AAED,EAAA,IAAI,OAAS,EAAA;AACX,IAAA,2BAAQ,QAAS,EAAA,EAAA,CAAA;AAAA,aACR,KAAO,EAAA;AAChB,IAAA,uBAAQ,GAAA,CAAA,KAAA,EAAA,EAAM,QAAS,EAAA,OAAA,EAAS,gBAAM,OAAQ,EAAA,CAAA;AAAA;AAGhD,EAAA,MAAM,QAAW,GAAA;AAAA,IACf,MAAM,iBAAkB,EAAA;AAAA,IACxB,KAAA,EAAO,EAAE,0BAA0B;AAAA,GACrC;AAEA,EACE,uBAAA,GAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAO,KAAS,IAAA,CAAA,CAAE,iCAAiC,CAAA;AAAA,MACnD,OAAA;AAAA,MACA,QAAA;AAAA,MAEA,QAAA,kBAAA,IAAA,CAAC,IAAK,EAAA,EAAA,KAAA,EAAK,IACR,EAAA,QAAA,EAAA;AAAA,QAAA,aAAA,CAAc,OAAQ,CAAA,GAAA,CAAI,CACzB,YAAA,qBAAA,IAAA,CAAC,QACC,EAAA,EAAA,QAAA,EAAA;AAAA,0BAAA,GAAA;AAAA,YAAC,YAAA;AAAA,YAAA;AAAA,cACC,WAAW,OAAQ,CAAA,mBAAA;AAAA,cACnB,KAAO,EAAA;AAAA,gBACL,YACE,QAAW,GAAA,QAAA,CAAS,QAAQ,YAAa,CAAA,UAAU,IAC/C,SACA,GAAA;AAAA,eACR;AAAA,cACA,KAAA,EAAO,EAAE,uBAAuB,CAAA;AAAA,cAEhC,8BAAC,eAAgB,EAAA,EAAA;AAAA;AAAA,WACnB;AAAA,0BACA,GAAA;AAAA,YAAC,YAAA;AAAA,YAAA;AAAA,cACC,OACE,kBAAA,GAAA;AAAA,gBAAC,IAAA;AAAA,gBAAA;AAAA,kBACC,IAAI,oBAAqB,CAAA,EAAE,EAAI,EAAA,YAAA,CAAa,IAAI,CAAA;AAAA,kBAChD,OAAQ,EAAA,SAAA;AAAA,kBACR,SAAS,MACP,SAAA,CAAU,YAAa,CAAA,OAAA,EAAS,aAAa,KAAO,EAAA;AAAA,oBAClD,UAAY,EAAA;AAAA,sBACV,gBAAgB,YAAa,CAAA,EAAA;AAAA,sBAC7B,QAAU,EAAA;AAAA;AACZ,mBACD,CAAA;AAAA,kBAGF,QAAa,EAAA,YAAA,CAAA;AAAA;AAAA,eAChB;AAAA,cAEF,SAAA,uBACG,GACC,EAAA,EAAA,QAAA,EAAA;AAAA,gCAAA,IAAA,CAAC,UAAW,EAAA,EAAA,OAAA,EAAQ,OAAQ,EAAA,KAAA,EAAM,eAC/B,EAAA,QAAA,EAAA;AAAA,kBAAA,QAAA,CAAS,OAAQ,CAAA,YAAA,CAAa,UAAU,CAAA,CAAE,UAAW,EAAA;AAAA,kBACrD,YAAA,CAAa,4BAET,IAAA,CAAA,QAAA,EAAA,EAAA,QAAA,EAAA;AAAA,oBAAI,CAAA,CAAA,EAAA,CAAA,CAAE,sBAAsB,CAAC,CAAA,CAAA,CAAA;AAAA,oCAC9B,GAAA;AAAA,sBAAC,IAAA;AAAA,sBAAA;AAAA,wBACC,IAAI,CAAG,EAAA,iBAAA,EAAmB,CACxB,UAAA,EAAA,YAAA,CAAa,SAAS,IACxB,CAAA,CAAA;AAAA,wBACA,OAAQ,EAAA,SAAA;AAAA,wBAEP,uBAAa,QAAS,CAAA;AAAA;AAAA;AACzB,mBACF,EAAA;AAAA,iBAEJ,EAAA,CAAA;AAAA,gCACC,IAAA,CAAA,UAAA,EAAA,EAAW,OAAQ,EAAA,OAAA,EAAQ,OAAM,eAC/B,EAAA,QAAA,EAAA;AAAA,kBAAa,YAAA,CAAA,OAAA;AAAA,kBACb,YAAa,CAAA,IAAA,IAAQ,YAAa,CAAA,IAAA,CAAK,MAAS,GAAA,CAAA,oBAC9C,GAAA,CAAA,GAAA,EAAA,EAAI,EAAI,EAAA,CAAA,EACN,QAAa,EAAA,YAAA,CAAA,IAAA,CAAK,IAAI,CACrB,GAAA,qBAAA,GAAA;AAAA,oBAAC,IAAA;AAAA,oBAAA;AAAA,sBAEC,IAAK,EAAA,OAAA;AAAA,sBACL,OAAO,GAAI,CAAA,KAAA;AAAA,sBACX,SAAW,EAAA,IAAA;AAAA,sBACX,IAAI,CAAG,EAAA,iBAAA,EAAmB,CAAA,MAAA,EAAS,IAAI,IAAI,CAAA,CAAA;AAAA,sBAC3C,SAAS,EAAA,IAAA;AAAA,sBACT,WAAW,OAAQ,CAAA;AAAA,qBAAA;AAAA,oBANd,GAAI,CAAA;AAAA,mBAQZ,CACH,EAAA;AAAA,iBAEJ,EAAA,CAAA;AAAA,gBACC,CAAC,WACA,oBAAA,GAAA,CAAC,cAAW,OAAQ,EAAA,SAAA,EAAU,OAAM,eACjC,EAAA,QAAA,EAAA,2BAAA;AAAA,kBACC,YAAa,CAAA,QAAA;AAAA,kBACb,EAAE,4BAA4B,CAAA;AAAA,kBAC9B,EAAE,6BAA6B,CAAA;AAAA,kBAC/B,EAAE,yBAAyB;AAAA,iBAE/B,EAAA;AAAA,eAEJ,EAAA;AAAA;AAAA,WAEJ;AAAA,UAAG;AAAA,SA9EU,EAAA,EAAA,YAAA,CAAa,EA+E5B,CACD,CAAA;AAAA,QACA,aAAA,CAAc,UAAU,CAAK,IAAA,CAAC,qBAAqB,MAClD,oBAAA,GAAA,CAAC,QACC,EAAA,EAAA,QAAA,kBAAA,IAAA,CAAC,YACE,EAAA,EAAA,QAAA,EAAA;AAAA,UAAG,CAAA,EAAA,CAAA,CAAE,mCAAmC,CAAC,CAAA,CAAA,CAAA;AAAA,0BAC1C,GAAA,CAAC,QAAK,EAAI,EAAA,qBAAA,IAAyB,OAAQ,EAAA,SAAA,EACxC,QAAE,EAAA,CAAA,CAAA,0BAA0B,CAC/B,EAAA,CAAA;AAAA,UAAO;AAAA,SAAA,EAET,CACF,EAAA;AAAA,OAEJ,EAAA;AAAA;AAAA,GACF;AAEJ;;;;"}
1
+ {"version":3,"file":"AnnouncementsCard.esm.js","sources":["../../../src/components/AnnouncementsCard/AnnouncementsCard.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { DateTime } from 'luxon';\nimport {\n InfoCard,\n InfoCardVariants,\n Link,\n Progress,\n} from '@backstage/core-components';\nimport { useApi, useRouteRef, useAnalytics } from '@backstage/core-plugin-api';\nimport {\n announcementAdminRouteRef,\n announcementViewRouteRef,\n rootRouteRef,\n} from '../../routes';\nimport { formatAnnouncementStartTime } from '../utils/announcementDateUtils';\nimport {\n announcementsApiRef,\n useAnnouncements,\n useAnnouncementsTranslation,\n useAnnouncementsPermissions,\n} from '@backstage-community/plugin-announcements-react';\nimport {\n makeStyles,\n List,\n ListItem,\n ListItemIcon,\n ListItemText,\n Typography,\n Box,\n Chip,\n} from '@material-ui/core';\nimport { Alert } from '@material-ui/lab';\nimport NewReleasesIcon from '@material-ui/icons/NewReleases';\n\nconst useStyles = makeStyles({\n newAnnouncementIcon: {\n minWidth: '36px',\n },\n chipStyle: {\n marginRight: 4,\n marginBottom: 4,\n },\n});\n\ntype AnnouncementsCardOpts = {\n title?: string;\n max?: number;\n category?: string;\n active?: boolean;\n variant?: InfoCardVariants;\n sortBy?: 'created_at' | 'start_at';\n order?: 'asc' | 'desc';\n current?: boolean;\n hideStartAt?: boolean;\n};\n\nexport const AnnouncementsCard = ({\n title,\n max,\n category,\n active,\n variant = 'gridItem',\n sortBy,\n order,\n current,\n hideStartAt,\n}: AnnouncementsCardOpts) => {\n const classes = useStyles();\n const announcementsApi = useApi(announcementsApiRef);\n const announcementsLink = useRouteRef(rootRouteRef);\n const viewAnnouncementLink = useRouteRef(announcementViewRouteRef);\n const announcementAdminLink = useRouteRef(announcementAdminRouteRef);\n const lastSeen = announcementsApi.lastSeenDate();\n const analytics = useAnalytics();\n const { t } = useAnnouncementsTranslation();\n\n const { announcements, loading, error } = useAnnouncements({\n max: max || 5,\n category,\n active,\n sortBy,\n order,\n current,\n });\n\n const permissions = useAnnouncementsPermissions();\n\n if (loading) {\n return <Progress />;\n } else if (error) {\n return <Alert severity=\"error\">{error.message}</Alert>;\n }\n\n const deepLink = {\n link: announcementsLink(),\n title: t('announcementsCard.seeAll'),\n };\n\n return (\n <InfoCard\n title={title || t('announcementsCard.announcements')}\n variant={variant}\n deepLink={deepLink}\n >\n <List dense>\n {announcements.results.map(announcement => (\n <ListItem key={announcement.id}>\n <ListItemIcon\n className={classes.newAnnouncementIcon}\n style={{\n visibility:\n lastSeen < DateTime.fromISO(announcement.created_at)\n ? 'visible'\n : 'hidden',\n }}\n title={t('announcementsCard.new')}\n >\n <NewReleasesIcon />\n </ListItemIcon>\n <ListItemText\n primary={\n <Link\n to={viewAnnouncementLink({ id: announcement.id })}\n variant=\"inherit\"\n onClick={() =>\n analytics.captureEvent('click', announcement.title, {\n attributes: {\n announcementId: announcement.id,\n location: 'AnnouncementsCard',\n },\n })\n }\n >\n {announcement.title}\n </Link>\n }\n secondary={\n <Box>\n <Typography variant=\"body2\" color=\"textSecondary\">\n {DateTime.fromISO(announcement.created_at).toRelative()}\n {announcement.category && (\n <>\n {` ${t('announcementsCard.in')} `}\n <Link\n to={`${announcementsLink()}?category=${\n announcement.category.slug\n }`}\n variant=\"inherit\"\n >\n {announcement.category.title}\n </Link>\n </>\n )}\n </Typography>\n <Typography variant=\"body2\" color=\"textSecondary\">\n {announcement.excerpt}\n {announcement.tags && announcement.tags.length > 0 && (\n <Box mt={1}>\n {announcement.tags.map(tag => (\n <Chip\n key={tag.slug}\n size=\"small\"\n label={tag.title}\n component={Link}\n to={`${announcementsLink()}?tags=${tag.slug}`}\n clickable\n className={classes.chipStyle}\n />\n ))}\n </Box>\n )}\n </Typography>\n {!hideStartAt && (\n <Typography variant=\"caption\" color=\"textSecondary\">\n {formatAnnouncementStartTime(\n announcement.start_at,\n t('announcementsCard.occurred'),\n t('announcementsCard.scheduled'),\n t('announcementsCard.today'),\n )}\n </Typography>\n )}\n </Box>\n }\n />{' '}\n </ListItem>\n ))}\n {announcements.count === 0 &&\n !permissions.create.loading &&\n permissions.create.allowed && (\n <ListItem>\n <ListItemText>\n {`${t('announcementsCard.noAnnouncements')} `}\n <Link to={announcementAdminLink()} variant=\"inherit\">\n {t('announcementsCard.addOne')}\n </Link>\n ?\n </ListItemText>\n </ListItem>\n )}\n </List>\n </InfoCard>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -1,13 +1,11 @@
1
1
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
2
  import { useState, useMemo } from 'react';
3
3
  import { useLocation } from 'react-router-dom';
4
- import { usePermission } from '@backstage/plugin-permission-react';
5
- import { announcementCreatePermission } from '@backstage-community/plugin-announcements-common';
6
4
  import { DateTime } from 'luxon';
7
5
  import { Page, Header, Content, Progress, ItemCardGrid, Link } from '@backstage/core-components';
8
6
  import { useRouteRef } from '@backstage/core-plugin-api';
9
7
  import { EntityRefLink } from '@backstage/plugin-catalog-react';
10
- import { useAnnouncements, useAnnouncementsTranslation } from '@backstage-community/plugin-announcements-react';
8
+ import { useAnnouncementsPermissions, useAnnouncements, useAnnouncementsTranslation } from '@backstage-community/plugin-announcements-react';
11
9
  import { makeStyles, Tooltip, Typography, Box, Chip, Card, CardHeader, CardContent } from '@material-ui/core';
12
10
  import { Alert, Pagination } from '@material-ui/lab';
13
11
  import { rootRouteRef, announcementViewRouteRef } from '../../routes.esm.js';
@@ -163,7 +161,7 @@ const AnnouncementsGrid = ({
163
161
  const AnnouncementsPage = (props) => {
164
162
  const location = useLocation();
165
163
  const queryParams = new URLSearchParams(location.search);
166
- const { loading: loadingCreatePermission, allowed: canCreate } = usePermission({ permission: announcementCreatePermission });
164
+ const permissions = useAnnouncementsPermissions();
167
165
  const {
168
166
  hideContextMenu,
169
167
  hideInactive,
@@ -178,7 +176,7 @@ const AnnouncementsPage = (props) => {
178
176
  order
179
177
  } = props;
180
178
  return /* @__PURE__ */ jsxs(Page, { themeId, children: [
181
- /* @__PURE__ */ jsx(Header, { title, subtitle, children: !hideContextMenu && !loadingCreatePermission && canCreate && /* @__PURE__ */ jsx(ContextMenu, {}) }),
179
+ /* @__PURE__ */ jsx(Header, { title, subtitle, children: !hideContextMenu && !permissions.create.loading && permissions.create.allowed && /* @__PURE__ */ jsx(ContextMenu, {}) }),
182
180
  /* @__PURE__ */ jsx(Content, { children: /* @__PURE__ */ jsx(
183
181
  AnnouncementsGrid,
184
182
  {
@@ -1 +1 @@
1
- {"version":3,"file":"AnnouncementsPage.esm.js","sources":["../../../src/components/AnnouncementsPage/AnnouncementsPage.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useState, ReactNode, useMemo } from 'react';\nimport { useLocation } from 'react-router-dom';\nimport { usePermission } from '@backstage/plugin-permission-react';\nimport {\n announcementCreatePermission,\n Announcement,\n} from '@backstage-community/plugin-announcements-common';\nimport { DateTime } from 'luxon';\nimport {\n Page,\n Header,\n Content,\n Link,\n ItemCardGrid,\n Progress,\n} from '@backstage/core-components';\nimport { useRouteRef } from '@backstage/core-plugin-api';\nimport { EntityRefLink } from '@backstage/plugin-catalog-react';\nimport {\n useAnnouncements,\n useAnnouncementsTranslation,\n} from '@backstage-community/plugin-announcements-react';\nimport {\n Box,\n Card,\n CardContent,\n CardHeader,\n Chip,\n makeStyles,\n Tooltip,\n Typography,\n} from '@material-ui/core';\nimport { Alert, Pagination } from '@material-ui/lab';\n\nimport { announcementViewRouteRef, rootRouteRef } from '../../routes';\nimport { ContextMenu } from './ContextMenu';\nimport { formatAnnouncementStartTime } from '../utils/announcementDateUtils';\nimport { MarkdownRendererTypeProps } from '../MarkdownRenderer/MarkdownRenderer';\nimport { truncate } from '../utils/truncateUtils';\n\nconst useStyles = makeStyles(theme => {\n return {\n cardHeader: {\n color: theme?.palette?.text?.primary || '#000',\n },\n pagination: {\n display: 'flex',\n justifyContent: 'center',\n marginTop: theme?.spacing?.(4) || 32,\n },\n };\n});\n\nconst AnnouncementCard = ({\n announcement,\n options: { titleLength = 50 },\n hideStartAt,\n}: {\n announcement: Announcement;\n options: AnnouncementCardProps;\n hideStartAt?: boolean;\n}) => {\n const classes = useStyles();\n const announcementsLink = useRouteRef(rootRouteRef);\n const viewAnnouncementLink = useRouteRef(announcementViewRouteRef);\n const { t } = useAnnouncementsTranslation();\n\n const title = (\n <Tooltip\n title={announcement.title}\n disableFocusListener\n data-testid=\"announcement-card-title-tooltip\"\n >\n <Link\n className={classes.cardHeader}\n to={viewAnnouncementLink({ id: announcement.id })}\n >\n {truncate(announcement.title, titleLength)}\n </Link>\n </Tooltip>\n );\n const subTitle = (\n <>\n <Typography variant=\"body2\" color=\"textSecondary\" component=\"span\">\n {t('announcementsPage.card.by')}{' '}\n <EntityRefLink\n entityRef={announcement.on_behalf_of || announcement.publisher}\n hideIcon\n />\n {announcement.category && (\n <>\n {' '}\n {t('announcementsPage.card.in')}{' '}\n <Link\n to={`${announcementsLink()}?category=${\n announcement.category.slug\n }`}\n >\n {announcement.category.title}\n </Link>\n </>\n )}\n , {DateTime.fromISO(announcement.created_at).toRelative()}\n </Typography>\n <Box>\n {!hideStartAt && (\n <Typography variant=\"caption\" color=\"textSecondary\">\n {formatAnnouncementStartTime(\n announcement.start_at,\n t('announcementsCard.occurred'),\n t('announcementsCard.scheduled'),\n t('announcementsCard.today'),\n )}\n </Typography>\n )}\n </Box>\n {announcement.tags && announcement.tags.length > 0 && (\n <Typography variant=\"body2\" color=\"textSecondary\">\n <Box mt={1}>\n {announcement.tags.map(tag => (\n <Chip\n key={tag.slug}\n size=\"small\"\n label={tag.title}\n component={Link}\n to={`${announcementsLink()}?tags=${tag.slug}`}\n clickable\n style={{ marginRight: 4, marginBottom: 4 }}\n />\n ))}\n </Box>\n </Typography>\n )}\n </>\n );\n\n return (\n <Card>\n <CardHeader title={title} subheader={subTitle} />\n <CardContent>{announcement.excerpt}</CardContent>\n </Card>\n );\n};\n\nconst AnnouncementsGrid = ({\n maxPerPage,\n category,\n tags,\n cardTitleLength,\n active,\n sortBy,\n order,\n hideStartAt,\n}: {\n maxPerPage: number;\n category?: string;\n tags?: string[];\n cardTitleLength?: number;\n active?: boolean;\n sortBy?: 'created_at' | 'start_at';\n order?: 'asc' | 'desc';\n hideStartAt?: boolean;\n}) => {\n const classes = useStyles();\n const location = useLocation();\n const queryParams = new URLSearchParams(location.search);\n\n const [page, setPage] = useState(1);\n const handleChange = (_event: any, value: number) => {\n setPage(value);\n };\n\n const tagsParam = queryParams.get('tags');\n const tagsFromUrl = useMemo(() => {\n return tagsParam ? tagsParam.split(',') : undefined;\n }, [tagsParam]);\n\n const { announcements, loading, error } = useAnnouncements(\n {\n max: maxPerPage,\n page: page,\n category,\n tags: tags || tagsFromUrl,\n active,\n sortBy,\n order,\n },\n { dependencies: [maxPerPage, page, category, tagsFromUrl] },\n );\n\n if (loading) {\n return <Progress />;\n } else if (error) {\n return <Alert severity=\"error\">{error.message}</Alert>;\n }\n\n return (\n <>\n <ItemCardGrid>\n {announcements.results.map(announcement => (\n <AnnouncementCard\n key={announcement.id}\n announcement={announcement}\n options={{ titleLength: cardTitleLength }}\n hideStartAt={hideStartAt}\n />\n ))}\n </ItemCardGrid>\n\n {announcements && announcements.count !== 0 && (\n <div className={classes.pagination}>\n <Pagination\n count={Math.ceil(announcements.count / maxPerPage)}\n page={page}\n onChange={handleChange}\n />\n </div>\n )}\n </>\n );\n};\n\ntype AnnouncementCardProps = {\n titleLength?: number;\n};\n\ntype AnnouncementCreateButtonProps = {\n name?: string;\n};\n\nexport type AnnouncementsPageProps = {\n themeId: string;\n title: string;\n subtitle?: ReactNode;\n maxPerPage?: number;\n category?: string;\n tags?: string[];\n buttonOptions?: AnnouncementCreateButtonProps;\n cardOptions?: AnnouncementCardProps;\n hideContextMenu?: boolean;\n hideInactive?: boolean;\n hideStartAt?: boolean;\n markdownRenderer?: MarkdownRendererTypeProps;\n sortby?: 'created_at' | 'start_at';\n order?: 'asc' | 'desc';\n};\n\nexport const AnnouncementsPage = (props: AnnouncementsPageProps) => {\n const location = useLocation();\n const queryParams = new URLSearchParams(location.search);\n const { loading: loadingCreatePermission, allowed: canCreate } =\n usePermission({ permission: announcementCreatePermission });\n\n const {\n hideContextMenu,\n hideInactive,\n hideStartAt,\n themeId,\n title,\n subtitle,\n maxPerPage,\n category,\n cardOptions,\n sortby,\n order,\n } = props;\n\n return (\n <Page themeId={themeId}>\n <Header title={title} subtitle={subtitle}>\n {!hideContextMenu && !loadingCreatePermission && canCreate && (\n <ContextMenu />\n )}\n </Header>\n\n <Content>\n <AnnouncementsGrid\n maxPerPage={maxPerPage ?? 10}\n category={category ?? queryParams.get('category') ?? undefined}\n tags={props.tags}\n cardTitleLength={cardOptions?.titleLength}\n active={!!hideInactive}\n sortBy={sortby ?? 'created_at'}\n order={order ?? 'desc'}\n hideStartAt={hideStartAt}\n />\n </Content>\n </Page>\n );\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AnnouncementsPage.esm.js","sources":["../../../src/components/AnnouncementsPage/AnnouncementsPage.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useState, ReactNode, useMemo } from 'react';\nimport { useLocation } from 'react-router-dom';\nimport { Announcement } from '@backstage-community/plugin-announcements-common';\nimport { DateTime } from 'luxon';\nimport {\n Page,\n Header,\n Content,\n Link,\n ItemCardGrid,\n Progress,\n} from '@backstage/core-components';\nimport { useRouteRef } from '@backstage/core-plugin-api';\nimport { EntityRefLink } from '@backstage/plugin-catalog-react';\nimport {\n useAnnouncements,\n useAnnouncementsTranslation,\n useAnnouncementsPermissions,\n} from '@backstage-community/plugin-announcements-react';\nimport {\n Box,\n Card,\n CardContent,\n CardHeader,\n Chip,\n makeStyles,\n Tooltip,\n Typography,\n} from '@material-ui/core';\nimport { Alert, Pagination } from '@material-ui/lab';\n\nimport { announcementViewRouteRef, rootRouteRef } from '../../routes';\nimport { ContextMenu } from './ContextMenu';\nimport { formatAnnouncementStartTime } from '../utils/announcementDateUtils';\nimport { MarkdownRendererTypeProps } from '../MarkdownRenderer/MarkdownRenderer';\nimport { truncate } from '../utils/truncateUtils';\n\nconst useStyles = makeStyles(theme => {\n return {\n cardHeader: {\n color: theme?.palette?.text?.primary || '#000',\n },\n pagination: {\n display: 'flex',\n justifyContent: 'center',\n marginTop: theme?.spacing?.(4) || 32,\n },\n };\n});\n\nconst AnnouncementCard = ({\n announcement,\n options: { titleLength = 50 },\n hideStartAt,\n}: {\n announcement: Announcement;\n options: AnnouncementCardProps;\n hideStartAt?: boolean;\n}) => {\n const classes = useStyles();\n const announcementsLink = useRouteRef(rootRouteRef);\n const viewAnnouncementLink = useRouteRef(announcementViewRouteRef);\n const { t } = useAnnouncementsTranslation();\n\n const title = (\n <Tooltip\n title={announcement.title}\n disableFocusListener\n data-testid=\"announcement-card-title-tooltip\"\n >\n <Link\n className={classes.cardHeader}\n to={viewAnnouncementLink({ id: announcement.id })}\n >\n {truncate(announcement.title, titleLength)}\n </Link>\n </Tooltip>\n );\n const subTitle = (\n <>\n <Typography variant=\"body2\" color=\"textSecondary\" component=\"span\">\n {t('announcementsPage.card.by')}{' '}\n <EntityRefLink\n entityRef={announcement.on_behalf_of || announcement.publisher}\n hideIcon\n />\n {announcement.category && (\n <>\n {' '}\n {t('announcementsPage.card.in')}{' '}\n <Link\n to={`${announcementsLink()}?category=${\n announcement.category.slug\n }`}\n >\n {announcement.category.title}\n </Link>\n </>\n )}\n , {DateTime.fromISO(announcement.created_at).toRelative()}\n </Typography>\n <Box>\n {!hideStartAt && (\n <Typography variant=\"caption\" color=\"textSecondary\">\n {formatAnnouncementStartTime(\n announcement.start_at,\n t('announcementsCard.occurred'),\n t('announcementsCard.scheduled'),\n t('announcementsCard.today'),\n )}\n </Typography>\n )}\n </Box>\n {announcement.tags && announcement.tags.length > 0 && (\n <Typography variant=\"body2\" color=\"textSecondary\">\n <Box mt={1}>\n {announcement.tags.map(tag => (\n <Chip\n key={tag.slug}\n size=\"small\"\n label={tag.title}\n component={Link}\n to={`${announcementsLink()}?tags=${tag.slug}`}\n clickable\n style={{ marginRight: 4, marginBottom: 4 }}\n />\n ))}\n </Box>\n </Typography>\n )}\n </>\n );\n\n return (\n <Card>\n <CardHeader title={title} subheader={subTitle} />\n <CardContent>{announcement.excerpt}</CardContent>\n </Card>\n );\n};\n\nconst AnnouncementsGrid = ({\n maxPerPage,\n category,\n tags,\n cardTitleLength,\n active,\n sortBy,\n order,\n hideStartAt,\n}: {\n maxPerPage: number;\n category?: string;\n tags?: string[];\n cardTitleLength?: number;\n active?: boolean;\n sortBy?: 'created_at' | 'start_at';\n order?: 'asc' | 'desc';\n hideStartAt?: boolean;\n}) => {\n const classes = useStyles();\n const location = useLocation();\n const queryParams = new URLSearchParams(location.search);\n\n const [page, setPage] = useState(1);\n const handleChange = (_event: any, value: number) => {\n setPage(value);\n };\n\n const tagsParam = queryParams.get('tags');\n const tagsFromUrl = useMemo(() => {\n return tagsParam ? tagsParam.split(',') : undefined;\n }, [tagsParam]);\n\n const { announcements, loading, error } = useAnnouncements(\n {\n max: maxPerPage,\n page: page,\n category,\n tags: tags || tagsFromUrl,\n active,\n sortBy,\n order,\n },\n { dependencies: [maxPerPage, page, category, tagsFromUrl] },\n );\n\n if (loading) {\n return <Progress />;\n } else if (error) {\n return <Alert severity=\"error\">{error.message}</Alert>;\n }\n\n return (\n <>\n <ItemCardGrid>\n {announcements.results.map(announcement => (\n <AnnouncementCard\n key={announcement.id}\n announcement={announcement}\n options={{ titleLength: cardTitleLength }}\n hideStartAt={hideStartAt}\n />\n ))}\n </ItemCardGrid>\n\n {announcements && announcements.count !== 0 && (\n <div className={classes.pagination}>\n <Pagination\n count={Math.ceil(announcements.count / maxPerPage)}\n page={page}\n onChange={handleChange}\n />\n </div>\n )}\n </>\n );\n};\n\ntype AnnouncementCardProps = {\n titleLength?: number;\n};\n\ntype AnnouncementCreateButtonProps = {\n name?: string;\n};\n\nexport type AnnouncementsPageProps = {\n themeId: string;\n title: string;\n subtitle?: ReactNode;\n maxPerPage?: number;\n category?: string;\n tags?: string[];\n buttonOptions?: AnnouncementCreateButtonProps;\n cardOptions?: AnnouncementCardProps;\n hideContextMenu?: boolean;\n hideInactive?: boolean;\n hideStartAt?: boolean;\n markdownRenderer?: MarkdownRendererTypeProps;\n sortby?: 'created_at' | 'start_at';\n order?: 'asc' | 'desc';\n};\n\nexport const AnnouncementsPage = (props: AnnouncementsPageProps) => {\n const location = useLocation();\n const queryParams = new URLSearchParams(location.search);\n const permissions = useAnnouncementsPermissions();\n\n const {\n hideContextMenu,\n hideInactive,\n hideStartAt,\n themeId,\n title,\n subtitle,\n maxPerPage,\n category,\n cardOptions,\n sortby,\n order,\n } = props;\n\n return (\n <Page themeId={themeId}>\n <Header title={title} subtitle={subtitle}>\n {!hideContextMenu &&\n !permissions.create.loading &&\n permissions.create.allowed && <ContextMenu />}\n </Header>\n\n <Content>\n <AnnouncementsGrid\n maxPerPage={maxPerPage ?? 10}\n category={category ?? queryParams.get('category') ?? undefined}\n tags={props.tags}\n cardTitleLength={cardOptions?.titleLength}\n active={!!hideInactive}\n sortBy={sortby ?? 'created_at'}\n order={order ?? 'desc'}\n hideStartAt={hideStartAt}\n />\n </Content>\n </Page>\n );\n};\n"],"names":[],"mappings":"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"}