@backstage-community/plugin-announcements 0.15.0 → 0.16.1

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 (37) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +17 -0
  3. package/dist/alpha/banner.esm.js +25 -0
  4. package/dist/alpha/banner.esm.js.map +1 -0
  5. package/dist/alpha.d.ts +33 -1
  6. package/dist/alpha.esm.js +3 -1
  7. package/dist/alpha.esm.js.map +1 -1
  8. package/dist/components/Admin/AnnouncementsContent/AnnouncementsContent.esm.js +1 -1
  9. package/dist/components/Admin/AnnouncementsContent/AnnouncementsContent.esm.js.map +1 -1
  10. package/dist/components/Admin/CategoriesContent/CategoriesContent.esm.js +1 -1
  11. package/dist/components/Admin/CategoriesContent/CategoriesContent.esm.js.map +1 -1
  12. package/dist/components/Admin/TagsContent/TagsContent.esm.js +1 -1
  13. package/dist/components/Admin/TagsContent/TagsContent.esm.js.map +1 -1
  14. package/dist/components/AnnouncementPage/AnnouncementPage.esm.js +16 -16
  15. package/dist/components/AnnouncementPage/AnnouncementPage.esm.js.map +1 -1
  16. package/dist/components/AnnouncementsPage/AnnouncementsPage.esm.js +1 -3
  17. package/dist/components/AnnouncementsPage/AnnouncementsPage.esm.js.map +1 -1
  18. package/dist/components/CategoriesPage/CategoriesPage.esm.js +11 -3
  19. package/dist/components/CategoriesPage/CategoriesPage.esm.js.map +1 -1
  20. package/dist/components/CreateAnnouncementPage/CreateAnnouncementPage.esm.js +5 -1
  21. package/dist/components/CreateAnnouncementPage/CreateAnnouncementPage.esm.js.map +1 -1
  22. package/dist/components/NewAnnouncementBanner/NewAnnouncementBanner.esm.js +24 -5
  23. package/dist/components/NewAnnouncementBanner/NewAnnouncementBanner.esm.js.map +1 -1
  24. package/dist/components/NewCategoryDialog/NewCategoryDialog.esm.js +7 -3
  25. package/dist/components/NewCategoryDialog/NewCategoryDialog.esm.js.map +1 -1
  26. package/dist/components/NewTagDialog/NewTagDialog.esm.js +71 -0
  27. package/dist/components/NewTagDialog/NewTagDialog.esm.js.map +1 -0
  28. package/dist/components/Router.esm.js +10 -2
  29. package/dist/components/Router.esm.js.map +1 -1
  30. package/dist/components/TagsPage/TagsPage.esm.js +122 -0
  31. package/dist/components/TagsPage/TagsPage.esm.js.map +1 -0
  32. package/dist/components/utils/truncateUtils.esm.js +6 -0
  33. package/dist/components/utils/truncateUtils.esm.js.map +1 -0
  34. package/dist/index.d.ts +4 -0
  35. package/dist/plugin.esm.js +4 -3
  36. package/dist/plugin.esm.js.map +1 -1
  37. package/package.json +3 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,34 @@
1
1
  # @backstage-community/plugin-announcements
2
2
 
3
+ ## 0.16.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 9987329: The success message shown when an announcement is created is now transient
8
+ - ffb26dc: Fixed routing issue where some links were incorrectly redirecting to `/announcements/admin` instead of `/announcements`. Changed `<AnnouncementsAdminPortal />` from a routable extension to a component extension to resolve the mount point conflict with the main `<AnnouncementsPage />`.
9
+ - f39d97f: Added announcement banner as app root element for the new frontend system.
10
+
11
+ ## 0.16.0
12
+
13
+ ### Minor Changes
14
+
15
+ - 1c076d9: - Centered text for empty tables in:
16
+ - Announcements
17
+ - Category
18
+ - Tags
19
+ - Properly mounted in the frontend the `/tags` path
20
+ - Updated `CategoriesPage` and `TagsPage` in order to display the `ContextMenu`
21
+ - Added titleLength prop in order to truncate title on `AnnouncementDetails`
22
+ - Fixed insert of Categories from `CategoriesPage` and clean up on dialog
23
+ - Added in the `NewAnnouncementBanner` a `cardOptions={{titleLength,excerptLength }}` props, this would allow to truncate text. Default is 50.
24
+ - Now in the `NewAnnouncementBanner` when the title get clicked, the alert is dismissed as user navigate to alert details
25
+
26
+ ### Patch Changes
27
+
28
+ - Updated dependencies [95470f7]
29
+ - @backstage-community/plugin-announcements-common@0.12.1
30
+ - @backstage-community/plugin-announcements-react@0.14.1
31
+
3
32
  ## 0.15.0
4
33
 
5
34
  ### Minor Changes
package/README.md CHANGED
@@ -140,6 +140,23 @@ It is possible to specify the text for the "New announcement" button rendered on
140
140
  }
141
141
  ```
142
142
 
143
+ ### Overriding the NewAnnouncementBanner
144
+
145
+ It is possible to specify the length of the title for announcements rendered on the `NewAnnouncementBanner`. You can do this by passing a `cardOptions` prop to the `NewAnnouncementBanner` component. The `cardOptions` prop accepts an object with the following properties:
146
+
147
+ ```ts
148
+ {
149
+ titleLength: number; // defaults to 50
150
+ excerptLength: number; // defaults to 50
151
+ }
152
+ ```
153
+
154
+ Example
155
+
156
+ ```tsx
157
+ <NewAnnouncementBanner cardOptions={{ titleLength: 10 }} />
158
+ ```
159
+
143
160
  ### Markdown rendering
144
161
 
145
162
  The plugin supports two different markdown rendering options:
@@ -0,0 +1,25 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { AppRootElementBlueprint } from '@backstage/frontend-plugin-api';
3
+ import { NewAnnouncementBanner } from '../components/NewAnnouncementBanner/NewAnnouncementBanner.esm.js';
4
+
5
+ const announcementsBanner = AppRootElementBlueprint.makeWithOverrides({
6
+ name: "banner",
7
+ config: {
8
+ schema: {
9
+ variant: (z) => z.enum(["block", "floating"]).default("floating"),
10
+ max: (z) => z.number().optional(),
11
+ category: (z) => z.string().optional(),
12
+ active: (z) => z.boolean().optional(),
13
+ current: (z) => z.boolean().optional(),
14
+ tags: (z) => z.array(z.string()).optional()
15
+ }
16
+ },
17
+ factory: (originalFactory, { config }) => {
18
+ return originalFactory({
19
+ element: /* @__PURE__ */ jsx(NewAnnouncementBanner, { ...config })
20
+ });
21
+ }
22
+ });
23
+
24
+ export { announcementsBanner };
25
+ //# sourceMappingURL=banner.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"banner.esm.js","sources":["../../src/alpha/banner.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 */\n\nimport { AppRootElementBlueprint } from '@backstage/frontend-plugin-api';\nimport { NewAnnouncementBanner } from '../components/NewAnnouncementBanner';\n\n/**\n * @alpha\n */\nexport const announcementsBanner = AppRootElementBlueprint.makeWithOverrides({\n name: 'banner',\n config: {\n schema: {\n variant: z => z.enum(['block', 'floating']).default('floating'),\n max: z => z.number().optional(),\n category: z => z.string().optional(),\n active: z => z.boolean().optional(),\n current: z => z.boolean().optional(),\n tags: z => z.array(z.string()).optional(),\n },\n },\n factory: (originalFactory, { config }) => {\n return originalFactory({\n element: <NewAnnouncementBanner {...config} />,\n });\n },\n});\n"],"names":[],"mappings":";;;;AAsBa,MAAA,mBAAA,GAAsB,wBAAwB,iBAAkB,CAAA;AAAA,EAC3E,IAAM,EAAA,QAAA;AAAA,EACN,MAAQ,EAAA;AAAA,IACN,MAAQ,EAAA;AAAA,MACN,OAAA,EAAS,CAAK,CAAA,KAAA,CAAA,CAAE,IAAK,CAAA,CAAC,SAAS,UAAU,CAAC,CAAE,CAAA,OAAA,CAAQ,UAAU,CAAA;AAAA,MAC9D,GAAK,EAAA,CAAA,CAAA,KAAK,CAAE,CAAA,MAAA,GAAS,QAAS,EAAA;AAAA,MAC9B,QAAU,EAAA,CAAA,CAAA,KAAK,CAAE,CAAA,MAAA,GAAS,QAAS,EAAA;AAAA,MACnC,MAAQ,EAAA,CAAA,CAAA,KAAK,CAAE,CAAA,OAAA,GAAU,QAAS,EAAA;AAAA,MAClC,OAAS,EAAA,CAAA,CAAA,KAAK,CAAE,CAAA,OAAA,GAAU,QAAS,EAAA;AAAA,MACnC,IAAA,EAAM,OAAK,CAAE,CAAA,KAAA,CAAM,EAAE,MAAO,EAAC,EAAE,QAAS;AAAA;AAC1C,GACF;AAAA,EACA,OAAS,EAAA,CAAC,eAAiB,EAAA,EAAE,QAAa,KAAA;AACxC,IAAA,OAAO,eAAgB,CAAA;AAAA,MACrB,OAAS,kBAAA,GAAA,CAAC,qBAAuB,EAAA,EAAA,GAAG,MAAQ,EAAA;AAAA,KAC7C,CAAA;AAAA;AAEL,CAAC;;;;"}
package/dist/alpha.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  /// <reference types="react" />
2
2
  import * as _backstage_plugin_search_react_alpha from '@backstage/plugin-search-react/alpha';
3
3
  import * as _backstage_catalog_model from '@backstage/catalog-model';
4
- import * as react from 'react';
5
4
  import * as _backstage_plugin_catalog_react_alpha from '@backstage/plugin-catalog-react/alpha';
5
+ import * as react from 'react';
6
6
  import * as _backstage_core_plugin_api from '@backstage/core-plugin-api';
7
7
  import * as _backstage_frontend_plugin_api from '@backstage/frontend-plugin-api';
8
8
 
@@ -23,6 +23,38 @@ declare const _default: _backstage_frontend_plugin_api.OverridableFrontendPlugin
23
23
  [x: string]: unknown;
24
24
  }>(params: _backstage_core_plugin_api.ApiFactory<TApi, TImpl, TDeps>) => _backstage_frontend_plugin_api.ExtensionBlueprintParams<_backstage_core_plugin_api.AnyApiFactory>;
25
25
  }>;
26
+ "app-root-element:announcements/banner": _backstage_frontend_plugin_api.ExtensionDefinition<{
27
+ config: {
28
+ variant: "block" | "floating";
29
+ max: number | undefined;
30
+ category: string | undefined;
31
+ active: boolean | undefined;
32
+ current: boolean | undefined;
33
+ tags: string[] | undefined;
34
+ };
35
+ configInput: {
36
+ variant?: "block" | "floating" | undefined;
37
+ max?: number | undefined;
38
+ active?: boolean | undefined;
39
+ current?: boolean | undefined;
40
+ tags?: string[] | undefined;
41
+ category?: string | undefined;
42
+ };
43
+ output: _backstage_frontend_plugin_api.ExtensionDataRef<react.JSX.Element, "core.reactElement", {}>;
44
+ inputs: {
45
+ [x: string]: _backstage_frontend_plugin_api.ExtensionInput<_backstage_frontend_plugin_api.ExtensionDataRef<unknown, string, {
46
+ optional?: true | undefined;
47
+ }>, {
48
+ optional: boolean;
49
+ singleton: boolean;
50
+ }>;
51
+ };
52
+ kind: "app-root-element";
53
+ name: "banner";
54
+ params: {
55
+ element: JSX.Element;
56
+ };
57
+ }>;
26
58
  "entity-card:announcements/announcements": _backstage_frontend_plugin_api.ExtensionDefinition<{
27
59
  kind: "entity-card";
28
60
  name: "announcements";
package/dist/alpha.esm.js CHANGED
@@ -6,6 +6,7 @@ import { announcementsNavItem } from './alpha/navItems.esm.js';
6
6
  import { announcementsPage } from './alpha/pages.esm.js';
7
7
  import { announcementsSearchResultListItem, announcementsSearchFilterResultType } from './alpha/search.esm.js';
8
8
  import { rootRouteRef } from './routes.esm.js';
9
+ import { announcementsBanner } from './alpha/banner.esm.js';
9
10
 
10
11
  var alpha = createFrontendPlugin({
11
12
  pluginId: "announcements",
@@ -18,7 +19,8 @@ var alpha = createFrontendPlugin({
18
19
  announcementsPage,
19
20
  announcementsNavItem,
20
21
  announcementsSearchResultListItem,
21
- announcementsSearchFilterResultType
22
+ announcementsSearchFilterResultType,
23
+ announcementsBanner
22
24
  ]
23
25
  });
24
26
 
@@ -1 +1 @@
1
- {"version":3,"file":"alpha.esm.js","sources":["../src/alpha.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 { convertLegacyRouteRefs } from '@backstage/core-compat-api';\nimport { createFrontendPlugin } from '@backstage/frontend-plugin-api';\nimport { announcementsApiExtension } from './alpha/apis';\nimport { entityAnnouncementsCard } from './alpha/entityCards';\nimport { announcementsNavItem } from './alpha/navItems';\nimport { announcementsPage } from './alpha/pages';\nimport {\n announcementsSearchFilterResultType,\n announcementsSearchResultListItem,\n} from './alpha/search';\nimport { rootRouteRef } from './routes';\n\n/**\n * @alpha\n */\nexport default createFrontendPlugin({\n pluginId: 'announcements',\n routes: convertLegacyRouteRefs({\n root: rootRouteRef,\n }),\n extensions: [\n announcementsApiExtension,\n entityAnnouncementsCard,\n announcementsPage,\n announcementsNavItem,\n announcementsSearchResultListItem,\n announcementsSearchFilterResultType,\n ],\n});\n"],"names":[],"mappings":";;;;;;;;;AA8BA,YAAe,oBAAqB,CAAA;AAAA,EAClC,QAAU,EAAA,eAAA;AAAA,EACV,QAAQ,sBAAuB,CAAA;AAAA,IAC7B,IAAM,EAAA;AAAA,GACP,CAAA;AAAA,EACD,UAAY,EAAA;AAAA,IACV,yBAAA;AAAA,IACA,uBAAA;AAAA,IACA,iBAAA;AAAA,IACA,oBAAA;AAAA,IACA,iCAAA;AAAA,IACA;AAAA;AAEJ,CAAC,CAAA;;;;"}
1
+ {"version":3,"file":"alpha.esm.js","sources":["../src/alpha.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 { convertLegacyRouteRefs } from '@backstage/core-compat-api';\nimport { createFrontendPlugin } from '@backstage/frontend-plugin-api';\nimport { announcementsApiExtension } from './alpha/apis';\nimport { entityAnnouncementsCard } from './alpha/entityCards';\nimport { announcementsNavItem } from './alpha/navItems';\nimport { announcementsPage } from './alpha/pages';\nimport {\n announcementsSearchFilterResultType,\n announcementsSearchResultListItem,\n} from './alpha/search';\nimport { rootRouteRef } from './routes';\nimport { announcementsBanner } from './alpha/banner';\n\n/**\n * @alpha\n */\nexport default createFrontendPlugin({\n pluginId: 'announcements',\n routes: convertLegacyRouteRefs({\n root: rootRouteRef,\n }),\n extensions: [\n announcementsApiExtension,\n entityAnnouncementsCard,\n announcementsPage,\n announcementsNavItem,\n announcementsSearchResultListItem,\n announcementsSearchFilterResultType,\n announcementsBanner,\n ],\n});\n"],"names":[],"mappings":";;;;;;;;;;AA+BA,YAAe,oBAAqB,CAAA;AAAA,EAClC,QAAU,EAAA,eAAA;AAAA,EACV,QAAQ,sBAAuB,CAAA;AAAA,IAC7B,IAAM,EAAA;AAAA,GACP,CAAA;AAAA,EACD,UAAY,EAAA;AAAA,IACV,yBAAA;AAAA,IACA,uBAAA;AAAA,IACA,iBAAA;AAAA,IACA,oBAAA;AAAA,IACA,iCAAA;AAAA,IACA,mCAAA;AAAA,IACA;AAAA;AAEJ,CAAC,CAAA;;;;"}
@@ -231,7 +231,7 @@ const AnnouncementsContent = ({
231
231
  options: { pageSize: 20, search: true },
232
232
  columns,
233
233
  data: announcements?.results ?? [],
234
- emptyContent: /* @__PURE__ */ jsx(Typography, { style: { padding: 2 }, children: t("admin.announcementsContent.noAnnouncementsFound") })
234
+ emptyContent: /* @__PURE__ */ jsx(Typography, { style: { padding: 2, textAlign: "center" }, children: t("admin.announcementsContent.noAnnouncementsFound") })
235
235
  }
236
236
  ),
237
237
  /* @__PURE__ */ jsx(
@@ -1 +1 @@
1
- {"version":3,"file":"AnnouncementsContent.esm.js","sources":["../../../../src/components/Admin/AnnouncementsContent/AnnouncementsContent.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 StatusOK,\n StatusPending,\n} from '@backstage/core-components';\nimport { alertApiRef, useApi } from '@backstage/core-plugin-api';\nimport {\n announcementsApiRef,\n CreateAnnouncementRequest,\n useAnnouncementsTranslation,\n useCategories,\n} from '@backstage-community/plugin-announcements-react';\nimport {\n Announcement,\n announcementCreatePermission,\n announcementDeletePermission,\n announcementUpdatePermission,\n Category,\n} from '@backstage-community/plugin-announcements-common';\nimport useAsyncRetry from 'react-use/esm/useAsyncRetry';\nimport { useDeleteAnnouncementDialogState } from '../../AnnouncementsPage/useDeleteAnnouncementDialogState';\nimport { DeleteAnnouncementDialog } from '../../AnnouncementsPage/DeleteAnnouncementDialog';\nimport { useNavigate } from 'react-router-dom';\nimport { AnnouncementForm } from '../../AnnouncementForm';\nimport slugify from 'slugify';\nimport {\n RequirePermission,\n usePermission,\n} from '@backstage/plugin-permission-react';\nimport { Box, Button, Grid, IconButton, Typography } from '@material-ui/core';\nimport DeleteIcon from '@material-ui/icons/Delete';\nimport EditIcon from '@material-ui/icons/Edit';\nimport PreviewIcon from '@material-ui/icons/Visibility';\nimport { DateTime } from 'luxon';\n\ntype AnnouncementsContentProps = {\n defaultInactive?: boolean;\n};\n\nexport const AnnouncementsContent = ({\n defaultInactive,\n}: AnnouncementsContentProps) => {\n const alertApi = useApi(alertApiRef);\n const announcementsApi = useApi(announcementsApiRef);\n const navigate = useNavigate();\n const { categories } = useCategories();\n const { t } = useAnnouncementsTranslation();\n\n const { loading: loadingCreatePermission, allowed: canCreateAnnouncement } =\n usePermission({\n permission: announcementCreatePermission,\n });\n\n const { loading: loadingUpdatePermission, allowed: canUpdateAnnouncement } =\n usePermission({\n permission: announcementUpdatePermission,\n });\n\n const { loading: loadingDeletePermission, allowed: canDeleteAnnouncement } =\n usePermission({\n permission: announcementDeletePermission,\n });\n\n const [showCreateAnnouncementForm, setShowCreateAnnouncementForm] =\n useState(false);\n\n const {\n loading,\n error,\n value: announcements,\n retry,\n } = useAsyncRetry(async () => await announcementsApi.announcements({}));\n\n const {\n isOpen: isDeleteDialogOpen,\n open: openDeleteDialog,\n close: closeDeleteDialog,\n announcement: announcementToDelete,\n } = useDeleteAnnouncementDialogState();\n\n const onCreateButtonClick = () => {\n setShowCreateAnnouncementForm(!showCreateAnnouncementForm);\n };\n\n const onTitleClick = (announcement: Announcement) => {\n navigate(`/announcements/view/${announcement.id}`);\n };\n\n const onEdit = (announcement: Announcement) => {\n navigate(`/announcements/edit/${announcement.id}`);\n };\n\n const onCancelDelete = () => {\n closeDeleteDialog();\n };\n const onConfirmDelete = async () => {\n closeDeleteDialog();\n\n try {\n await announcementsApi.deleteAnnouncementByID(announcementToDelete!.id);\n\n alertApi.post({ message: 'Announcement deleted.', severity: 'success' });\n } catch (err) {\n alertApi.post({ message: (err as Error).message, severity: 'error' });\n }\n\n retry();\n };\n\n const onSubmit = async (request: CreateAnnouncementRequest) => {\n const { category } = request;\n\n const slugs = categories.map((c: Category) => c.slug);\n let alertMsg = t('admin.announcementsContent.alertMessage') as string;\n\n try {\n if (category) {\n const categorySlug = slugify(category, {\n lower: true,\n });\n if (slugs.indexOf(categorySlug) === -1) {\n alertMsg = alertMsg.replace('.', '');\n alertMsg = `${alertMsg} ${t(\n 'admin.announcementsContent.alertMessageWithNewCategory',\n )} ${category}.`;\n\n await announcementsApi.createCategory({\n title: category,\n });\n }\n }\n\n await announcementsApi.createAnnouncement({\n ...request,\n category: request.category?.toLocaleLowerCase('en-US'),\n });\n alertApi.post({ message: alertMsg, severity: 'success' });\n\n setShowCreateAnnouncementForm(false);\n retry();\n } catch (err) {\n alertApi.post({ message: (err as Error).message, severity: 'error' });\n }\n };\n\n if (loading) {\n return <Progress />;\n }\n if (error) {\n return <ErrorPanel error={error} />;\n }\n\n const columns: TableColumn<Announcement>[] = [\n {\n title: (\n <Typography>{t('admin.announcementsContent.table.title')}</Typography>\n ),\n sorting: true,\n field: 'title',\n render: rowData => rowData.title,\n },\n {\n title: (\n <Typography>{t('admin.announcementsContent.table.body')}</Typography>\n ),\n sorting: true,\n field: 'body',\n render: rowData => rowData.body,\n },\n {\n title: (\n <Typography>\n {t('admin.announcementsContent.table.publisher')}\n </Typography>\n ),\n sorting: true,\n field: 'publisher',\n render: rowData => rowData.publisher,\n },\n {\n title: (\n <Typography>\n {t('admin.announcementsContent.table.onBehalfOf')}\n </Typography>\n ),\n sorting: true,\n field: 'on_behalf_of',\n render: rowData => rowData.on_behalf_of,\n },\n\n {\n title: (\n <Typography>\n {t('admin.announcementsContent.table.category')}\n </Typography>\n ),\n sorting: true,\n field: 'category',\n render: rowData => rowData.category?.title ?? '',\n },\n {\n title: (\n <Typography>{t('admin.announcementsContent.table.tags')}</Typography>\n ),\n sorting: true,\n field: 'tags',\n render: rowData => rowData.tags?.map(tag => tag.title).join(', ') || '',\n },\n {\n title: (\n <Typography>{t('admin.announcementsContent.table.status')}</Typography>\n ),\n sorting: true,\n field: 'active',\n render: rowData =>\n rowData.active ? (\n <StatusOK>{t('admin.announcementsContent.table.active')}</StatusOK>\n ) : (\n <StatusPending>\n {t('admin.announcementsContent.table.inactive')}\n </StatusPending>\n ),\n },\n {\n title: (\n <Typography>\n {t('admin.announcementsContent.table.created_at')}\n </Typography>\n ),\n sorting: true,\n field: 'created_at',\n type: 'date',\n render: rowData =>\n DateTime.fromISO(rowData.created_at).toFormat('M/d/yyyy'),\n },\n {\n title: (\n <Typography>\n {t('admin.announcementsContent.table.start_at')}\n </Typography>\n ),\n sorting: true,\n field: 'start_at',\n type: 'date',\n render: rowData =>\n DateTime.fromISO(rowData.start_at).toFormat('M/d/yyyy'),\n },\n {\n title: (\n <Typography>\n {t('admin.announcementsContent.table.until_date')}\n </Typography>\n ),\n sorting: true,\n field: 'until_date',\n type: 'date',\n render: rowData =>\n rowData?.until_date\n ? DateTime.fromISO(rowData.until_date).toFormat('M/d/yyyy')\n : '-',\n },\n {\n title: (\n <Typography>{t('admin.announcementsContent.table.actions')}</Typography>\n ),\n render: rowData => {\n return (\n <Box display=\"flex\" flexDirection=\"row\">\n <IconButton\n aria-label=\"preview\"\n onClick={() => onTitleClick(rowData)}\n size=\"small\"\n >\n <PreviewIcon fontSize=\"small\" data-testid=\"preview\" />\n </IconButton>\n\n <IconButton\n aria-label=\"edit\"\n disabled={loadingUpdatePermission || !canUpdateAnnouncement}\n onClick={() => onEdit(rowData)}\n size=\"small\"\n >\n <EditIcon fontSize=\"small\" data-testid=\"edit-icon\" />\n </IconButton>\n\n <IconButton\n aria-label=\"delete\"\n disabled={loadingDeletePermission || !canDeleteAnnouncement}\n onClick={() => openDeleteDialog(rowData)}\n size=\"small\"\n >\n <DeleteIcon fontSize=\"small\" data-testid=\"delete-icon\" />\n </IconButton>\n </Box>\n );\n },\n },\n ];\n\n return (\n <RequirePermission permission={announcementCreatePermission}>\n <Grid container>\n <Grid item xs={12}>\n <Button\n disabled={loadingCreatePermission || !canCreateAnnouncement}\n variant=\"contained\"\n onClick={() => onCreateButtonClick()}\n >\n {showCreateAnnouncementForm\n ? t('admin.announcementsContent.cancelButton')\n : t('admin.announcementsContent.createButton')}\n </Button>\n </Grid>\n\n {showCreateAnnouncementForm && (\n <Grid item xs={12}>\n <AnnouncementForm\n initialData={{ active: !defaultInactive } as Announcement}\n onSubmit={onSubmit}\n />\n </Grid>\n )}\n\n <Grid item xs={12}>\n <Table\n title={t('admin.announcementsContent.announcements')}\n options={{ pageSize: 20, search: true }}\n columns={columns}\n data={announcements?.results ?? []}\n emptyContent={\n <Typography style={{ padding: 2 }}>\n {t('admin.announcementsContent.noAnnouncementsFound')}\n </Typography>\n }\n />\n\n <DeleteAnnouncementDialog\n open={isDeleteDialogOpen}\n onCancel={onCancelDelete}\n onConfirm={onConfirmDelete}\n />\n </Grid>\n </Grid>\n </RequirePermission>\n );\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AnnouncementsContent.esm.js","sources":["../../../../src/components/Admin/AnnouncementsContent/AnnouncementsContent.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 StatusOK,\n StatusPending,\n} from '@backstage/core-components';\nimport { alertApiRef, useApi } from '@backstage/core-plugin-api';\nimport {\n announcementsApiRef,\n CreateAnnouncementRequest,\n useAnnouncementsTranslation,\n useCategories,\n} from '@backstage-community/plugin-announcements-react';\nimport {\n Announcement,\n announcementCreatePermission,\n announcementDeletePermission,\n announcementUpdatePermission,\n Category,\n} from '@backstage-community/plugin-announcements-common';\nimport useAsyncRetry from 'react-use/esm/useAsyncRetry';\nimport { useDeleteAnnouncementDialogState } from '../../AnnouncementsPage/useDeleteAnnouncementDialogState';\nimport { DeleteAnnouncementDialog } from '../../AnnouncementsPage/DeleteAnnouncementDialog';\nimport { useNavigate } from 'react-router-dom';\nimport { AnnouncementForm } from '../../AnnouncementForm';\nimport slugify from 'slugify';\nimport {\n RequirePermission,\n usePermission,\n} from '@backstage/plugin-permission-react';\nimport { Box, Button, Grid, IconButton, Typography } from '@material-ui/core';\nimport DeleteIcon from '@material-ui/icons/Delete';\nimport EditIcon from '@material-ui/icons/Edit';\nimport PreviewIcon from '@material-ui/icons/Visibility';\nimport { DateTime } from 'luxon';\n\ntype AnnouncementsContentProps = {\n defaultInactive?: boolean;\n};\n\nexport const AnnouncementsContent = ({\n defaultInactive,\n}: AnnouncementsContentProps) => {\n const alertApi = useApi(alertApiRef);\n const announcementsApi = useApi(announcementsApiRef);\n const navigate = useNavigate();\n const { categories } = useCategories();\n const { t } = useAnnouncementsTranslation();\n\n const { loading: loadingCreatePermission, allowed: canCreateAnnouncement } =\n usePermission({\n permission: announcementCreatePermission,\n });\n\n const { loading: loadingUpdatePermission, allowed: canUpdateAnnouncement } =\n usePermission({\n permission: announcementUpdatePermission,\n });\n\n const { loading: loadingDeletePermission, allowed: canDeleteAnnouncement } =\n usePermission({\n permission: announcementDeletePermission,\n });\n\n const [showCreateAnnouncementForm, setShowCreateAnnouncementForm] =\n useState(false);\n\n const {\n loading,\n error,\n value: announcements,\n retry,\n } = useAsyncRetry(async () => await announcementsApi.announcements({}));\n\n const {\n isOpen: isDeleteDialogOpen,\n open: openDeleteDialog,\n close: closeDeleteDialog,\n announcement: announcementToDelete,\n } = useDeleteAnnouncementDialogState();\n\n const onCreateButtonClick = () => {\n setShowCreateAnnouncementForm(!showCreateAnnouncementForm);\n };\n\n const onTitleClick = (announcement: Announcement) => {\n navigate(`/announcements/view/${announcement.id}`);\n };\n\n const onEdit = (announcement: Announcement) => {\n navigate(`/announcements/edit/${announcement.id}`);\n };\n\n const onCancelDelete = () => {\n closeDeleteDialog();\n };\n const onConfirmDelete = async () => {\n closeDeleteDialog();\n\n try {\n await announcementsApi.deleteAnnouncementByID(announcementToDelete!.id);\n\n alertApi.post({ message: 'Announcement deleted.', severity: 'success' });\n } catch (err) {\n alertApi.post({ message: (err as Error).message, severity: 'error' });\n }\n\n retry();\n };\n\n const onSubmit = async (request: CreateAnnouncementRequest) => {\n const { category } = request;\n\n const slugs = categories.map((c: Category) => c.slug);\n let alertMsg = t('admin.announcementsContent.alertMessage') as string;\n\n try {\n if (category) {\n const categorySlug = slugify(category, {\n lower: true,\n });\n if (slugs.indexOf(categorySlug) === -1) {\n alertMsg = alertMsg.replace('.', '');\n alertMsg = `${alertMsg} ${t(\n 'admin.announcementsContent.alertMessageWithNewCategory',\n )} ${category}.`;\n\n await announcementsApi.createCategory({\n title: category,\n });\n }\n }\n\n await announcementsApi.createAnnouncement({\n ...request,\n category: request.category?.toLocaleLowerCase('en-US'),\n });\n alertApi.post({ message: alertMsg, severity: 'success' });\n\n setShowCreateAnnouncementForm(false);\n retry();\n } catch (err) {\n alertApi.post({ message: (err as Error).message, severity: 'error' });\n }\n };\n\n if (loading) {\n return <Progress />;\n }\n if (error) {\n return <ErrorPanel error={error} />;\n }\n\n const columns: TableColumn<Announcement>[] = [\n {\n title: (\n <Typography>{t('admin.announcementsContent.table.title')}</Typography>\n ),\n sorting: true,\n field: 'title',\n render: rowData => rowData.title,\n },\n {\n title: (\n <Typography>{t('admin.announcementsContent.table.body')}</Typography>\n ),\n sorting: true,\n field: 'body',\n render: rowData => rowData.body,\n },\n {\n title: (\n <Typography>\n {t('admin.announcementsContent.table.publisher')}\n </Typography>\n ),\n sorting: true,\n field: 'publisher',\n render: rowData => rowData.publisher,\n },\n {\n title: (\n <Typography>\n {t('admin.announcementsContent.table.onBehalfOf')}\n </Typography>\n ),\n sorting: true,\n field: 'on_behalf_of',\n render: rowData => rowData.on_behalf_of,\n },\n\n {\n title: (\n <Typography>\n {t('admin.announcementsContent.table.category')}\n </Typography>\n ),\n sorting: true,\n field: 'category',\n render: rowData => rowData.category?.title ?? '',\n },\n {\n title: (\n <Typography>{t('admin.announcementsContent.table.tags')}</Typography>\n ),\n sorting: true,\n field: 'tags',\n render: rowData => rowData.tags?.map(tag => tag.title).join(', ') || '',\n },\n {\n title: (\n <Typography>{t('admin.announcementsContent.table.status')}</Typography>\n ),\n sorting: true,\n field: 'active',\n render: rowData =>\n rowData.active ? (\n <StatusOK>{t('admin.announcementsContent.table.active')}</StatusOK>\n ) : (\n <StatusPending>\n {t('admin.announcementsContent.table.inactive')}\n </StatusPending>\n ),\n },\n {\n title: (\n <Typography>\n {t('admin.announcementsContent.table.created_at')}\n </Typography>\n ),\n sorting: true,\n field: 'created_at',\n type: 'date',\n render: rowData =>\n DateTime.fromISO(rowData.created_at).toFormat('M/d/yyyy'),\n },\n {\n title: (\n <Typography>\n {t('admin.announcementsContent.table.start_at')}\n </Typography>\n ),\n sorting: true,\n field: 'start_at',\n type: 'date',\n render: rowData =>\n DateTime.fromISO(rowData.start_at).toFormat('M/d/yyyy'),\n },\n {\n title: (\n <Typography>\n {t('admin.announcementsContent.table.until_date')}\n </Typography>\n ),\n sorting: true,\n field: 'until_date',\n type: 'date',\n render: rowData =>\n rowData?.until_date\n ? DateTime.fromISO(rowData.until_date).toFormat('M/d/yyyy')\n : '-',\n },\n {\n title: (\n <Typography>{t('admin.announcementsContent.table.actions')}</Typography>\n ),\n render: rowData => {\n return (\n <Box display=\"flex\" flexDirection=\"row\">\n <IconButton\n aria-label=\"preview\"\n onClick={() => onTitleClick(rowData)}\n size=\"small\"\n >\n <PreviewIcon fontSize=\"small\" data-testid=\"preview\" />\n </IconButton>\n\n <IconButton\n aria-label=\"edit\"\n disabled={loadingUpdatePermission || !canUpdateAnnouncement}\n onClick={() => onEdit(rowData)}\n size=\"small\"\n >\n <EditIcon fontSize=\"small\" data-testid=\"edit-icon\" />\n </IconButton>\n\n <IconButton\n aria-label=\"delete\"\n disabled={loadingDeletePermission || !canDeleteAnnouncement}\n onClick={() => openDeleteDialog(rowData)}\n size=\"small\"\n >\n <DeleteIcon fontSize=\"small\" data-testid=\"delete-icon\" />\n </IconButton>\n </Box>\n );\n },\n },\n ];\n\n return (\n <RequirePermission permission={announcementCreatePermission}>\n <Grid container>\n <Grid item xs={12}>\n <Button\n disabled={loadingCreatePermission || !canCreateAnnouncement}\n variant=\"contained\"\n onClick={() => onCreateButtonClick()}\n >\n {showCreateAnnouncementForm\n ? t('admin.announcementsContent.cancelButton')\n : t('admin.announcementsContent.createButton')}\n </Button>\n </Grid>\n\n {showCreateAnnouncementForm && (\n <Grid item xs={12}>\n <AnnouncementForm\n initialData={{ active: !defaultInactive } as Announcement}\n onSubmit={onSubmit}\n />\n </Grid>\n )}\n\n <Grid item xs={12}>\n <Table\n title={t('admin.announcementsContent.announcements')}\n options={{ pageSize: 20, search: true }}\n columns={columns}\n data={announcements?.results ?? []}\n emptyContent={\n <Typography style={{ padding: 2, textAlign: 'center' }}>\n {t('admin.announcementsContent.noAnnouncementsFound')}\n </Typography>\n }\n />\n\n <DeleteAnnouncementDialog\n open={isDeleteDialogOpen}\n onCancel={onCancelDelete}\n onConfirm={onConfirmDelete}\n />\n </Grid>\n </Grid>\n </RequirePermission>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -118,7 +118,7 @@ const CategoriesContent = () => {
118
118
  options: { pageSize: 20, search: true },
119
119
  columns,
120
120
  data: categories ?? [],
121
- emptyContent: /* @__PURE__ */ jsx(Typography, { style: { padding: 2 }, children: t("admin.categoriesContent.table.noCategoriesFound") })
121
+ emptyContent: /* @__PURE__ */ jsx(Typography, { style: { padding: 2, textAlign: "center" }, children: t("admin.categoriesContent.table.noCategoriesFound") })
122
122
  }
123
123
  ) }),
124
124
  /* @__PURE__ */ jsx(
@@ -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 { CategoriesForm } from '../../CategoriesForm';\nimport { useApi, alertApiRef } from '@backstage/core-plugin-api';\nimport {\n RequirePermission,\n usePermission,\n} from '@backstage/plugin-permission-react';\nimport { useDeleteCategoryDialogState } from '../../CategoriesPage/useDeleteCategoryDialogState';\nimport { ResponseError } from '@backstage/errors';\nimport { DeleteCategoryDialog } from '../../CategoriesPage/DeleteCategoryDialog';\nimport { Button, Grid, IconButton, Typography } from '@material-ui/core';\nimport DeleteIcon from '@material-ui/icons/Delete';\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 }}>\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} from '@backstage-community/plugin-announcements-react';\nimport {\n announcementCreatePermission,\n announcementDeletePermission,\n Category,\n} from '@backstage-community/plugin-announcements-common';\nimport { CategoriesForm } from '../../CategoriesForm';\nimport { useApi, alertApiRef } from '@backstage/core-plugin-api';\nimport {\n RequirePermission,\n usePermission,\n} from '@backstage/plugin-permission-react';\nimport { useDeleteCategoryDialogState } from '../../CategoriesPage/useDeleteCategoryDialogState';\nimport { ResponseError } from '@backstage/errors';\nimport { DeleteCategoryDialog } from '../../CategoriesPage/DeleteCategoryDialog';\nimport { Button, Grid, IconButton, Typography } from '@material-ui/core';\nimport DeleteIcon from '@material-ui/icons/Delete';\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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"}
@@ -128,7 +128,7 @@ const TagsContent = () => {
128
128
  options: { pageSize: 20, search: true },
129
129
  columns,
130
130
  data: tags ?? [],
131
- emptyContent: /* @__PURE__ */ jsx(Typography, { style: { padding: 2 }, children: t("admin.tagsContent.table.noTagsFound") })
131
+ emptyContent: /* @__PURE__ */ jsx(Typography, { style: { padding: 2, textAlign: "center" }, children: t("admin.tagsContent.table.noTagsFound") })
132
132
  }
133
133
  ) }),
134
134
  /* @__PURE__ */ jsx(
@@ -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 { TagsForm } from '../../TagsForm';\nimport { useApi, alertApiRef } from '@backstage/core-plugin-api';\nimport {\n RequirePermission,\n usePermission,\n} from '@backstage/plugin-permission-react';\nimport { useDeleteTagDialogState } from '../../TagsPage/useDeleteTagDialogState';\nimport { ResponseError } from '@backstage/errors';\nimport { DeleteTagDialog } from '../../TagsPage/DeleteTagDialog';\nimport { Button, Grid, IconButton, Typography } from '@material-ui/core';\nimport DeleteIcon from '@material-ui/icons/Delete';\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 }}>\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} from '@backstage-community/plugin-announcements-react';\nimport {\n announcementCreatePermission,\n announcementDeletePermission,\n Tag,\n} from '@backstage-community/plugin-announcements-common';\nimport { TagsForm } from '../../TagsForm';\nimport { useApi, alertApiRef } from '@backstage/core-plugin-api';\nimport {\n RequirePermission,\n usePermission,\n} from '@backstage/plugin-permission-react';\nimport { useDeleteTagDialogState } from '../../TagsPage/useDeleteTagDialogState';\nimport { ResponseError } from '@backstage/errors';\nimport { DeleteTagDialog } from '../../TagsPage/DeleteTagDialog';\nimport { Button, Grid, IconButton, Typography } from '@material-ui/core';\nimport DeleteIcon from '@material-ui/icons/Delete';\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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"}
@@ -6,13 +6,16 @@ import { useApi, useRouteRefParams, useRouteRef } from '@backstage/core-plugin-a
6
6
  import { EntityRefLink } from '@backstage/plugin-catalog-react';
7
7
  import { announcementViewRouteRef, rootRouteRef } from '../../routes.esm.js';
8
8
  import { announcementsApiRef } from '@backstage-community/plugin-announcements-react';
9
- import { Grid, Typography } from '@material-ui/core';
9
+ import { MAX_TITLE_LENGTH } from '@backstage-community/plugin-announcements-common';
10
+ import { Grid, Typography, Tooltip } from '@material-ui/core';
10
11
  import { Alert } from '@material-ui/lab';
11
12
  import { MarkdownRenderer } from '../MarkdownRenderer/MarkdownRenderer.esm.js';
13
+ import { truncate } from '../utils/truncateUtils.esm.js';
12
14
 
13
15
  const AnnouncementDetails = ({
14
16
  announcement,
15
- markdownRenderer
17
+ markdownRenderer,
18
+ titleLength
16
19
  }) => {
17
20
  const announcementsLink = useRouteRef(rootRouteRef);
18
21
  const deepLink = {
@@ -32,21 +35,17 @@ const AnnouncementDetails = ({
32
35
  ", ",
33
36
  DateTime.fromISO(announcement.created_at).toRelative()
34
37
  ] });
35
- return /* @__PURE__ */ jsx(
36
- InfoCard,
38
+ const maxLength = titleLength ?? MAX_TITLE_LENGTH;
39
+ const title = truncate(announcement.title, maxLength);
40
+ const isTruncated = announcement.title.length > maxLength;
41
+ const titleElement = isTruncated ? /* @__PURE__ */ jsx(Tooltip, { title: announcement.title, arrow: true, children: /* @__PURE__ */ jsx(Typography, { component: "span", children: title }) }) : title;
42
+ return /* @__PURE__ */ jsx(InfoCard, { title: titleElement, subheader: subHeader, deepLink, children: /* @__PURE__ */ jsx(
43
+ MarkdownRenderer,
37
44
  {
38
- title: announcement.title,
39
- subheader: subHeader,
40
- deepLink,
41
- children: /* @__PURE__ */ jsx(
42
- MarkdownRenderer,
43
- {
44
- content: announcement.body,
45
- rendererType: markdownRenderer
46
- }
47
- )
45
+ content: announcement.body,
46
+ rendererType: markdownRenderer
48
47
  }
49
- );
48
+ ) });
50
49
  };
51
50
  const AnnouncementPage = (props) => {
52
51
  const announcementsApi = useApi(announcementsApiRef);
@@ -67,7 +66,8 @@ const AnnouncementPage = (props) => {
67
66
  AnnouncementDetails,
68
67
  {
69
68
  announcement: value,
70
- markdownRenderer: props.markdownRenderer
69
+ markdownRenderer: props.markdownRenderer,
70
+ titleLength: props.titleLength
71
71
  }
72
72
  );
73
73
  const lastSeen = announcementsApi.lastSeenDate();
@@ -1 +1 @@
1
- {"version":3,"file":"AnnouncementPage.esm.js","sources":["../../../src/components/AnnouncementPage/AnnouncementPage.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 { ReactNode } from 'react';\nimport useAsync from 'react-use/lib/useAsync';\nimport { DateTime } from 'luxon';\nimport {\n Progress,\n Page,\n Header,\n Content,\n InfoCard,\n} from '@backstage/core-components';\nimport {\n useApi,\n useRouteRef,\n useRouteRefParams,\n} from '@backstage/core-plugin-api';\nimport { EntityRefLink } from '@backstage/plugin-catalog-react';\nimport { announcementViewRouteRef, rootRouteRef } from '../../routes';\nimport { announcementsApiRef } from '@backstage-community/plugin-announcements-react';\nimport { Announcement } from '@backstage-community/plugin-announcements-common';\nimport { Grid, Typography } from '@material-ui/core';\nimport { Alert } from '@material-ui/lab';\nimport {\n MarkdownRenderer,\n MarkdownRendererTypeProps,\n} from '../MarkdownRenderer';\n\nconst AnnouncementDetails = ({\n announcement,\n markdownRenderer,\n}: {\n announcement: Announcement;\n markdownRenderer?: MarkdownRendererTypeProps;\n}) => {\n const announcementsLink = useRouteRef(rootRouteRef);\n const deepLink = {\n link: announcementsLink(),\n title: 'Back to announcements',\n };\n const subHeader = (\n <Typography>\n By{' '}\n <EntityRefLink\n entityRef={announcement.on_behalf_of || announcement.publisher}\n hideIcon\n />\n , {DateTime.fromISO(announcement.created_at).toRelative()}\n </Typography>\n );\n\n return (\n <InfoCard\n title={announcement.title}\n subheader={subHeader}\n deepLink={deepLink}\n >\n <MarkdownRenderer\n content={announcement.body}\n rendererType={markdownRenderer}\n />\n </InfoCard>\n );\n};\n\ntype AnnouncementPageProps = {\n themeId: string;\n title: string;\n subtitle?: ReactNode;\n markdownRenderer?: MarkdownRendererTypeProps;\n};\n\nexport const AnnouncementPage = (props: AnnouncementPageProps) => {\n const announcementsApi = useApi(announcementsApiRef);\n const { id } = useRouteRefParams(announcementViewRouteRef);\n const { value, loading, error } = useAsync(\n async () => announcementsApi.announcementByID(id),\n [id],\n );\n\n let title = props.title;\n let content: ReactNode;\n\n if (loading) {\n content = <Progress />;\n } else if (error) {\n content = <Alert severity=\"error\">{error.message}</Alert>;\n } else {\n title = `${value!.title} – ${title}`;\n content = (\n <AnnouncementDetails\n announcement={value!}\n markdownRenderer={props.markdownRenderer}\n />\n );\n\n const lastSeen = announcementsApi.lastSeenDate();\n const announcementCreatedAt = DateTime.fromISO(value!.created_at);\n\n if (announcementCreatedAt > lastSeen) {\n announcementsApi.markLastSeenDate(announcementCreatedAt);\n }\n }\n\n return (\n <Page themeId={props.themeId}>\n <Header title={title} subtitle={props.subtitle} />\n\n <Content>\n <Grid container justifyContent=\"center\" alignItems=\"center\">\n <Grid item sm={6}>\n {content}\n </Grid>\n </Grid>\n </Content>\n </Page>\n );\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AnnouncementPage.esm.js","sources":["../../../src/components/AnnouncementPage/AnnouncementPage.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 { ReactNode } from 'react';\nimport useAsync from 'react-use/lib/useAsync';\nimport { DateTime } from 'luxon';\nimport {\n Progress,\n Page,\n Header,\n Content,\n InfoCard,\n} from '@backstage/core-components';\nimport {\n useApi,\n useRouteRef,\n useRouteRefParams,\n} from '@backstage/core-plugin-api';\nimport { EntityRefLink } from '@backstage/plugin-catalog-react';\nimport { announcementViewRouteRef, rootRouteRef } from '../../routes';\nimport { announcementsApiRef } from '@backstage-community/plugin-announcements-react';\nimport {\n Announcement,\n MAX_TITLE_LENGTH,\n} from '@backstage-community/plugin-announcements-common';\nimport { Grid, Tooltip, Typography } from '@material-ui/core';\nimport { Alert } from '@material-ui/lab';\nimport {\n MarkdownRenderer,\n MarkdownRendererTypeProps,\n} from '../MarkdownRenderer';\nimport { truncate } from '../utils/truncateUtils';\n\nconst AnnouncementDetails = ({\n announcement,\n markdownRenderer,\n titleLength,\n}: {\n announcement: Announcement;\n markdownRenderer?: MarkdownRendererTypeProps;\n titleLength?: number;\n}) => {\n const announcementsLink = useRouteRef(rootRouteRef);\n const deepLink = {\n link: announcementsLink(),\n title: 'Back to announcements',\n };\n const subHeader = (\n <Typography>\n By{' '}\n <EntityRefLink\n entityRef={announcement.on_behalf_of || announcement.publisher}\n hideIcon\n />\n , {DateTime.fromISO(announcement.created_at).toRelative()}\n </Typography>\n );\n\n const maxLength = titleLength ?? MAX_TITLE_LENGTH;\n const title = truncate(announcement.title, maxLength);\n const isTruncated = announcement.title.length > maxLength;\n\n const titleElement = isTruncated ? (\n <Tooltip title={announcement.title} arrow>\n <Typography component=\"span\">{title}</Typography>\n </Tooltip>\n ) : (\n title\n );\n return (\n <InfoCard title={titleElement} subheader={subHeader} deepLink={deepLink}>\n <MarkdownRenderer\n content={announcement.body}\n rendererType={markdownRenderer}\n />\n </InfoCard>\n );\n};\n\ntype AnnouncementPageProps = {\n themeId: string;\n title: string;\n subtitle?: ReactNode;\n markdownRenderer?: MarkdownRendererTypeProps;\n titleLength?: number;\n};\n\nexport const AnnouncementPage = (props: AnnouncementPageProps) => {\n const announcementsApi = useApi(announcementsApiRef);\n const { id } = useRouteRefParams(announcementViewRouteRef);\n const { value, loading, error } = useAsync(\n async () => announcementsApi.announcementByID(id),\n [id],\n );\n\n let title = props.title;\n let content: ReactNode;\n\n if (loading) {\n content = <Progress />;\n } else if (error) {\n content = <Alert severity=\"error\">{error.message}</Alert>;\n } else {\n title = `${value!.title} – ${title}`;\n content = (\n <AnnouncementDetails\n announcement={value!}\n markdownRenderer={props.markdownRenderer}\n titleLength={props.titleLength}\n />\n );\n\n const lastSeen = announcementsApi.lastSeenDate();\n const announcementCreatedAt = DateTime.fromISO(value!.created_at);\n\n if (announcementCreatedAt > lastSeen) {\n announcementsApi.markLastSeenDate(announcementCreatedAt);\n }\n }\n\n return (\n <Page themeId={props.themeId}>\n <Header title={title} subtitle={props.subtitle} />\n\n <Content>\n <Grid container justifyContent=\"center\" alignItems=\"center\">\n <Grid item sm={6}>\n {content}\n </Grid>\n </Grid>\n </Content>\n </Page>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;AA6CA,MAAM,sBAAsB,CAAC;AAAA,EAC3B,YAAA;AAAA,EACA,gBAAA;AAAA,EACA;AACF,CAIM,KAAA;AACJ,EAAM,MAAA,iBAAA,GAAoB,YAAY,YAAY,CAAA;AAClD,EAAA,MAAM,QAAW,GAAA;AAAA,IACf,MAAM,iBAAkB,EAAA;AAAA,IACxB,KAAO,EAAA;AAAA,GACT;AACA,EAAM,MAAA,SAAA,wBACH,UAAW,EAAA,EAAA,QAAA,EAAA;AAAA,IAAA,IAAA;AAAA,IACP,GAAA;AAAA,oBACH,GAAA;AAAA,MAAC,aAAA;AAAA,MAAA;AAAA,QACC,SAAA,EAAW,YAAa,CAAA,YAAA,IAAgB,YAAa,CAAA,SAAA;AAAA,QACrD,QAAQ,EAAA;AAAA;AAAA,KACV;AAAA,IAAE,IAAA;AAAA,IACC,QAAS,CAAA,OAAA,CAAQ,YAAa,CAAA,UAAU,EAAE,UAAW;AAAA,GAC1D,EAAA,CAAA;AAGF,EAAA,MAAM,YAAY,WAAe,IAAA,gBAAA;AACjC,EAAA,MAAM,KAAQ,GAAA,QAAA,CAAS,YAAa,CAAA,KAAA,EAAO,SAAS,CAAA;AACpD,EAAM,MAAA,WAAA,GAAc,YAAa,CAAA,KAAA,CAAM,MAAS,GAAA,SAAA;AAEhD,EAAA,MAAM,YAAe,GAAA,WAAA,mBAClB,GAAA,CAAA,OAAA,EAAA,EAAQ,OAAO,YAAa,CAAA,KAAA,EAAO,KAAK,EAAA,IAAA,EACvC,8BAAC,UAAW,EAAA,EAAA,SAAA,EAAU,MAAQ,EAAA,QAAA,EAAA,KAAA,EAAM,GACtC,CAEA,GAAA,KAAA;AAEF,EAAA,2BACG,QAAS,EAAA,EAAA,KAAA,EAAO,YAAc,EAAA,SAAA,EAAW,WAAW,QACnD,EAAA,QAAA,kBAAA,GAAA;AAAA,IAAC,gBAAA;AAAA,IAAA;AAAA,MACC,SAAS,YAAa,CAAA,IAAA;AAAA,MACtB,YAAc,EAAA;AAAA;AAAA,GAElB,EAAA,CAAA;AAEJ,CAAA;AAUa,MAAA,gBAAA,GAAmB,CAAC,KAAiC,KAAA;AAChE,EAAM,MAAA,gBAAA,GAAmB,OAAO,mBAAmB,CAAA;AACnD,EAAA,MAAM,EAAE,EAAA,EAAO,GAAA,iBAAA,CAAkB,wBAAwB,CAAA;AACzD,EAAA,MAAM,EAAE,KAAA,EAAO,OAAS,EAAA,KAAA,EAAU,GAAA,QAAA;AAAA,IAChC,YAAY,gBAAiB,CAAA,gBAAA,CAAiB,EAAE,CAAA;AAAA,IAChD,CAAC,EAAE;AAAA,GACL;AAEA,EAAA,IAAI,QAAQ,KAAM,CAAA,KAAA;AAClB,EAAI,IAAA,OAAA;AAEJ,EAAA,IAAI,OAAS,EAAA;AACX,IAAA,OAAA,uBAAW,QAAS,EAAA,EAAA,CAAA;AAAA,aACX,KAAO,EAAA;AAChB,IAAA,OAAA,mBAAW,GAAA,CAAA,KAAA,EAAA,EAAM,QAAS,EAAA,OAAA,EAAS,gBAAM,OAAQ,EAAA,CAAA;AAAA,GAC5C,MAAA;AACL,IAAA,KAAA,GAAQ,CAAG,EAAA,KAAA,CAAO,KAAK,CAAA,QAAA,EAAM,KAAK,CAAA,CAAA;AAClC,IACE,OAAA,mBAAA,GAAA;AAAA,MAAC,mBAAA;AAAA,MAAA;AAAA,QACC,YAAc,EAAA,KAAA;AAAA,QACd,kBAAkB,KAAM,CAAA,gBAAA;AAAA,QACxB,aAAa,KAAM,CAAA;AAAA;AAAA,KACrB;AAGF,IAAM,MAAA,QAAA,GAAW,iBAAiB,YAAa,EAAA;AAC/C,IAAA,MAAM,qBAAwB,GAAA,QAAA,CAAS,OAAQ,CAAA,KAAA,CAAO,UAAU,CAAA;AAEhE,IAAA,IAAI,wBAAwB,QAAU,EAAA;AACpC,MAAA,gBAAA,CAAiB,iBAAiB,qBAAqB,CAAA;AAAA;AACzD;AAGF,EAAA,uBACG,IAAA,CAAA,IAAA,EAAA,EAAK,OAAS,EAAA,KAAA,CAAM,OACnB,EAAA,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,MAAO,EAAA,EAAA,KAAA,EAAc,QAAU,EAAA,KAAA,CAAM,QAAU,EAAA,CAAA;AAAA,wBAE/C,OACC,EAAA,EAAA,QAAA,kBAAA,GAAA,CAAC,QAAK,SAAS,EAAA,IAAA,EAAC,gBAAe,QAAS,EAAA,UAAA,EAAW,QACjD,EAAA,QAAA,kBAAA,GAAA,CAAC,QAAK,IAAI,EAAA,IAAA,EAAC,IAAI,CACZ,EAAA,QAAA,EAAA,OAAA,EACH,GACF,CACF,EAAA;AAAA,GACF,EAAA,CAAA;AAEJ;;;;"}
@@ -18,6 +18,7 @@ import { useAnnouncementsTranslation, announcementsApiRef, useAnnouncements } fr
18
18
  import { makeStyles, Tooltip, Typography, Box, Chip, Card, CardHeader, CardContent, IconButton, Menu, MenuItem, ListItemIcon } from '@material-ui/core';
19
19
  import { Alert, Pagination } from '@material-ui/lab';
20
20
  import { formatAnnouncementStartTime } from '../utils/announcementDateUtils.esm.js';
21
+ import { truncate } from '../utils/truncateUtils.esm.js';
21
22
 
22
23
  const useStyles = makeStyles((theme) => {
23
24
  return {
@@ -31,9 +32,6 @@ const useStyles = makeStyles((theme) => {
31
32
  }
32
33
  };
33
34
  });
34
- const truncate = (text, length) => {
35
- return text.length > length ? `${text.substring(0, length)}...` : text;
36
- };
37
35
  const AnnouncementCard = ({
38
36
  announcement,
39
37
  onDelete,