@backstage/plugin-notifications 0.5.16-next.1 → 0.5.16-next.2

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 (50) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/alpha.d.ts +2 -1
  3. package/dist/alpha.esm.js +1 -1
  4. package/dist/alpha.esm.js.map +1 -1
  5. package/dist/components/NotificationsFilters/NotificationsFilters.esm.js +88 -103
  6. package/dist/components/NotificationsFilters/NotificationsFilters.esm.js.map +1 -1
  7. package/dist/components/NotificationsPage/NotificationsPage.esm.js +7 -8
  8. package/dist/components/NotificationsPage/NotificationsPage.esm.js.map +1 -1
  9. package/dist/components/NotificationsSideBarItem/NotificationsSideBarItem.esm.js +65 -58
  10. package/dist/components/NotificationsSideBarItem/NotificationsSideBarItem.esm.js.map +1 -1
  11. package/dist/components/NotificationsSideBarItem/NotificationsSideBarItem.module.css.esm.js +8 -0
  12. package/dist/components/NotificationsSideBarItem/NotificationsSideBarItem.module.css.esm.js.map +1 -0
  13. package/dist/components/NotificationsTable/BulkActions.esm.js +48 -32
  14. package/dist/components/NotificationsTable/BulkActions.esm.js.map +1 -1
  15. package/dist/components/NotificationsTable/NotificationDescription.esm.js +8 -11
  16. package/dist/components/NotificationsTable/NotificationDescription.esm.js.map +1 -1
  17. package/dist/components/NotificationsTable/NotificationIcon.esm.js +4 -3
  18. package/dist/components/NotificationsTable/NotificationIcon.esm.js.map +1 -1
  19. package/dist/components/NotificationsTable/NotificationsTable.esm.js +90 -114
  20. package/dist/components/NotificationsTable/NotificationsTable.esm.js.map +1 -1
  21. package/dist/components/NotificationsTable/NotificationsTable.module.css.esm.js +8 -0
  22. package/dist/components/NotificationsTable/NotificationsTable.module.css.esm.js.map +1 -0
  23. package/dist/components/NotificationsTable/SelectAll.esm.js +18 -33
  24. package/dist/components/NotificationsTable/SelectAll.esm.js.map +1 -1
  25. package/dist/components/NotificationsTable/SelectAll.module.css.esm.js +8 -0
  26. package/dist/components/NotificationsTable/SelectAll.module.css.esm.js.map +1 -0
  27. package/dist/components/NotificationsTable/SeverityIcon.esm.js +37 -25
  28. package/dist/components/NotificationsTable/SeverityIcon.esm.js.map +1 -1
  29. package/dist/components/NotificationsTable/SeverityIcon.module.css.esm.js +8 -0
  30. package/dist/components/NotificationsTable/SeverityIcon.module.css.esm.js.map +1 -0
  31. package/dist/components/UserNotificationSettingsCard/NoBorderTableCell.esm.js +6 -7
  32. package/dist/components/UserNotificationSettingsCard/NoBorderTableCell.esm.js.map +1 -1
  33. package/dist/components/UserNotificationSettingsCard/NoBorderTableCell.module.css.esm.js +8 -0
  34. package/dist/components/UserNotificationSettingsCard/NoBorderTableCell.module.css.esm.js.map +1 -0
  35. package/dist/components/UserNotificationSettingsCard/OriginRow.esm.js +35 -43
  36. package/dist/components/UserNotificationSettingsCard/OriginRow.esm.js.map +1 -1
  37. package/dist/components/UserNotificationSettingsCard/TopicRow.esm.js +22 -33
  38. package/dist/components/UserNotificationSettingsCard/TopicRow.esm.js.map +1 -1
  39. package/dist/components/UserNotificationSettingsCard/UserNotificationSettingsPanel.esm.js +20 -20
  40. package/dist/components/UserNotificationSettingsCard/UserNotificationSettingsPanel.esm.js.map +1 -1
  41. package/dist/components/UserNotificationSettingsCard/UserNotificationSettingsPanel.module.css.esm.js +8 -0
  42. package/dist/components/UserNotificationSettingsCard/UserNotificationSettingsPanel.module.css.esm.js.map +1 -0
  43. package/dist/index.d.ts +2 -1
  44. package/dist/node_modules_dist/style-inject/dist/style-inject.es.esm.js +29 -0
  45. package/dist/node_modules_dist/style-inject/dist/style-inject.es.esm.js.map +1 -0
  46. package/dist/{package.json.esm.js → plugins/notifications/package.json.esm.js} +1 -4
  47. package/dist/{package.json.esm.js.map → plugins/notifications/package.json.esm.js.map} +1 -1
  48. package/dist/translation.esm.js +3 -2
  49. package/dist/translation.esm.js.map +1 -1
  50. package/package.json +12 -15
@@ -1,49 +1,46 @@
1
- import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
- import { useMemo, useState, useCallback, useEffect } from 'react';
1
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
+ import { forwardRef, useMemo, useState, useCallback, useEffect } from 'react';
3
3
  import { useNotificationsApi } from '../../hooks/useNotificationsApi.esm.js';
4
4
  import { useWebNotifications } from '../../hooks/useWebNotifications.esm.js';
5
5
  import { useTitleCounter } from '../../hooks/useTitleCounter.esm.js';
6
- import { SidebarItem, Link } from '@backstage/core-components';
7
- import NotificationsIcon from '@material-ui/icons/Notifications';
8
- import { useApi, alertApiRef, useRouteRef } from '@backstage/core-plugin-api';
6
+ import { SidebarItem } from '@backstage/core-components';
7
+ import { useApi, useRouteRef } from '@backstage/core-plugin-api';
8
+ import { toastApiRef } from '@backstage/frontend-plugin-api';
9
9
  import { rootRouteRef } from '../../routes.esm.js';
10
10
  import { useSignal } from '@backstage/plugin-signals-react';
11
11
  import { notificationsApiRef } from '../../api/NotificationsApi.esm.js';
12
12
  import '@backstage/errors';
13
13
  import { MaterialDesignContent, SnackbarProvider, closeSnackbar, enqueueSnackbar } from 'notistack';
14
14
  import { SeverityIcon } from '../NotificationsTable/SeverityIcon.esm.js';
15
- import OpenInNew from '@material-ui/icons/OpenInNew';
16
- import MarkAsReadIcon from '@material-ui/icons/CheckCircle';
17
- import IconButton from '@material-ui/core/IconButton';
18
- import Chip from '@material-ui/core/Chip';
19
- import { styled } from '@material-ui/core/styles';
15
+ import { TagGroup, Tag, Flex, ButtonIcon } from '@backstage/ui';
16
+ import { RiNotification2Line, RiExternalLinkLine, RiCheckboxCircleLine } from '@remixicon/react';
17
+ import styles from './NotificationsSideBarItem.module.css.esm.js';
20
18
 
21
- const StyledMaterialDesignContent = styled(MaterialDesignContent)(
22
- ({ theme }) => ({
23
- "&.notistack-MuiContent-low": {
24
- backgroundColor: theme.palette.background.default,
25
- color: theme.palette.text.primary
26
- },
27
- "&.notistack-MuiContent-normal": {
28
- backgroundColor: theme.palette.background.default,
29
- color: theme.palette.text.primary
30
- },
31
- "&.notistack-MuiContent-high": {
32
- backgroundColor: theme.palette.background.default,
33
- color: theme.palette.text.primary
34
- },
35
- "&.notistack-MuiContent-critical": {
36
- backgroundColor: theme.palette.background.default,
37
- color: theme.palette.text.primary
19
+ const NotificationsIcon = (props) => {
20
+ let size = 24;
21
+ if (props.fontSize === "large") {
22
+ size = 32;
23
+ } else if (props.fontSize === "small") {
24
+ size = 16;
25
+ }
26
+ return /* @__PURE__ */ jsx(RiNotification2Line, { size });
27
+ };
28
+ const StyledMaterialDesignContent = forwardRef(
29
+ (props, ref) => /* @__PURE__ */ jsx(
30
+ MaterialDesignContent,
31
+ {
32
+ ...props,
33
+ ref,
34
+ className: [props.className, styles.snackbarContent].filter(Boolean).join(" ")
38
35
  }
39
- })
36
+ )
40
37
  );
41
38
  const NotificationsSidebarItem = (props) => {
42
39
  const {
43
40
  webNotificationsEnabled = false,
44
41
  titleCounterEnabled = true,
45
42
  snackbarEnabled = true,
46
- snackbarAutoHideDuration = 1e4,
43
+ snackbarAutoHideDuration = 15e3,
47
44
  icon = NotificationsIcon,
48
45
  text = "Notifications",
49
46
  ...restProps
@@ -52,7 +49,7 @@ const NotificationsSidebarItem = (props) => {
52
49
  titleCounterEnabled: true,
53
50
  snackbarProps: {
54
51
  enabled: true,
55
- autoHideDuration: 1e4
52
+ autoHideDuration: 15e3
56
53
  }
57
54
  };
58
55
  const snackbarProps = useMemo(
@@ -66,7 +63,7 @@ const NotificationsSidebarItem = (props) => {
66
63
  (api) => api.getStatus()
67
64
  );
68
65
  const notificationsApi = useApi(notificationsApiRef);
69
- const alertApi = useApi(alertApiRef);
66
+ const toastApi = useApi(toastApiRef);
70
67
  const [unreadCount, setUnreadCount] = useState(0);
71
68
  const notificationsRoute = useRouteRef(rootRouteRef)();
72
69
  const { lastSignal } = useSignal("notifications");
@@ -77,52 +74,56 @@ const NotificationsSidebarItem = (props) => {
77
74
  const { setNotificationCount } = useTitleCounter();
78
75
  const getSnackbarProperties = useCallback(
79
76
  (notification) => {
80
- const action = (snackBarId) => /* @__PURE__ */ jsxs(Fragment, { children: [
77
+ const action = (snackBarId) => /* @__PURE__ */ jsxs(Flex, { gap: "1", children: [
81
78
  /* @__PURE__ */ jsx(
82
- IconButton,
79
+ ButtonIcon,
83
80
  {
84
- component: Link,
85
- to: notification.payload.link ?? notificationsRoute,
86
- onClick: () => {
81
+ "aria-label": "open notification",
82
+ icon: /* @__PURE__ */ jsx(RiExternalLinkLine, { size: 16 }),
83
+ variant: "secondary",
84
+ onPress: () => {
85
+ const link = notification.payload.link ?? notificationsRoute;
86
+ window.open(link, "_blank", "noopener,noreferrer");
87
87
  if (notification.payload.link) {
88
88
  notificationsApi.updateNotifications({
89
89
  ids: [notification.id],
90
90
  read: true
91
91
  }).catch(() => {
92
- alertApi.post({
93
- message: "Failed to mark notification as read",
94
- severity: "error"
92
+ toastApi.post({
93
+ title: "Failed to mark notification as read",
94
+ status: "danger"
95
95
  });
96
96
  });
97
97
  }
98
98
  closeSnackbar(snackBarId);
99
- },
100
- children: /* @__PURE__ */ jsx(OpenInNew, { fontSize: "small" })
99
+ }
101
100
  }
102
101
  ),
103
102
  /* @__PURE__ */ jsx(
104
- IconButton,
103
+ ButtonIcon,
105
104
  {
106
- onClick: () => {
105
+ "aria-label": "mark as read",
106
+ icon: /* @__PURE__ */ jsx(RiCheckboxCircleLine, { size: 16 }),
107
+ variant: "secondary",
108
+ onPress: () => {
107
109
  notificationsApi.updateNotifications({
108
110
  ids: [notification.id],
109
111
  read: true
110
112
  }).then(() => {
111
113
  closeSnackbar(snackBarId);
112
114
  }).catch(() => {
113
- alertApi.post({
114
- message: "Failed to mark notification as read",
115
- severity: "error"
115
+ toastApi.post({
116
+ title: "Failed to mark notification as read",
117
+ status: "danger"
116
118
  });
117
119
  });
118
- },
119
- children: /* @__PURE__ */ jsx(MarkAsReadIcon, { fontSize: "small" })
120
+ }
120
121
  }
121
122
  )
122
123
  ] });
123
124
  return { action };
124
125
  },
125
- [notificationsRoute, notificationsApi, alertApi]
126
+ [notificationsRoute, notificationsApi, toastApi]
126
127
  );
127
128
  useEffect(() => {
128
129
  if (refresh) {
@@ -163,9 +164,9 @@ const NotificationsSidebarItem = (props) => {
163
164
  });
164
165
  }
165
166
  }).catch(() => {
166
- alertApi.post({
167
- message: "Failed to fetch notification",
168
- severity: "error"
167
+ toastApi.post({
168
+ title: "Failed to fetch notification",
169
+ status: "danger"
169
170
  });
170
171
  });
171
172
  };
@@ -178,7 +179,7 @@ const NotificationsSidebarItem = (props) => {
178
179
  sendWebNotification,
179
180
  webNotificationsEnabled,
180
181
  notificationsApi,
181
- alertApi,
182
+ toastApi,
182
183
  getSnackbarProperties,
183
184
  snackbarProps
184
185
  ]);
@@ -209,10 +210,16 @@ const NotificationsSidebarItem = (props) => {
209
210
  SnackbarProvider,
210
211
  {
211
212
  iconVariant: {
212
- normal: snackbarProps?.iconVariant?.normal ?? /* @__PURE__ */ jsx(SeverityIcon, { severity: "normal" }),
213
- critical: snackbarProps?.iconVariant?.critical ?? /* @__PURE__ */ jsx(SeverityIcon, { severity: "critical" }),
214
- high: snackbarProps?.iconVariant?.high ?? /* @__PURE__ */ jsx(SeverityIcon, { severity: "high" }),
215
- low: snackbarProps?.iconVariant?.low ?? /* @__PURE__ */ jsx(SeverityIcon, { severity: "low" })
213
+ normal: snackbarProps?.iconVariant?.normal ?? /* @__PURE__ */ jsx(SeverityIcon, { severity: "normal", className: styles.snackbarIcon }),
214
+ critical: snackbarProps?.iconVariant?.critical ?? /* @__PURE__ */ jsx(
215
+ SeverityIcon,
216
+ {
217
+ severity: "critical",
218
+ className: styles.snackbarIcon
219
+ }
220
+ ),
221
+ high: snackbarProps?.iconVariant?.high ?? /* @__PURE__ */ jsx(SeverityIcon, { severity: "high", className: styles.snackbarIcon }),
222
+ low: snackbarProps?.iconVariant?.low ?? /* @__PURE__ */ jsx(SeverityIcon, { severity: "low", className: styles.snackbarIcon })
216
223
  },
217
224
  dense: snackbarProps?.dense,
218
225
  maxSnack: snackbarProps?.maxSnack,
@@ -232,7 +239,7 @@ const NotificationsSidebarItem = (props) => {
232
239
  text,
233
240
  icon,
234
241
  ...restProps,
235
- children: count && /* @__PURE__ */ jsx(Chip, { size: "small", label: count > 99 ? "99+" : count })
242
+ children: count && /* @__PURE__ */ jsx(TagGroup, { "aria-label": "Unread notifications", children: /* @__PURE__ */ jsx(Tag, { size: "small", children: count > 99 ? "99+" : count }) })
236
243
  }
237
244
  )
238
245
  ] });
@@ -1 +1 @@
1
- {"version":3,"file":"NotificationsSideBarItem.esm.js","sources":["../../../src/components/NotificationsSideBarItem/NotificationsSideBarItem.tsx"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport { useNotificationsApi } from '../../hooks';\nimport { Link, SidebarItem } from '@backstage/core-components';\nimport NotificationsIcon from '@material-ui/icons/Notifications';\nimport {\n alertApiRef,\n IconComponent,\n useApi,\n useRouteRef,\n} from '@backstage/core-plugin-api';\nimport { rootRouteRef } from '../../routes';\nimport { useSignal } from '@backstage/plugin-signals-react';\nimport {\n Notification,\n NotificationSeverity,\n NotificationSignal,\n} from '@backstage/plugin-notifications-common';\nimport { useWebNotifications } from '../../hooks/useWebNotifications';\nimport { useTitleCounter } from '../../hooks/useTitleCounter';\nimport { notificationsApiRef } from '../../api';\nimport {\n closeSnackbar,\n enqueueSnackbar,\n MaterialDesignContent,\n OptionsWithExtraProps,\n SnackbarKey,\n SnackbarProvider,\n VariantType,\n} from 'notistack';\nimport { SeverityIcon } from '../NotificationsTable/SeverityIcon';\nimport OpenInNew from '@material-ui/icons/OpenInNew';\nimport MarkAsReadIcon from '@material-ui/icons/CheckCircle';\nimport IconButton from '@material-ui/core/IconButton';\nimport Chip from '@material-ui/core/Chip';\nimport { styled } from '@material-ui/core/styles';\n\nconst StyledMaterialDesignContent = styled(MaterialDesignContent)(\n ({ theme }) => ({\n '&.notistack-MuiContent-low': {\n backgroundColor: theme.palette.background.default,\n color: theme.palette.text.primary,\n },\n '&.notistack-MuiContent-normal': {\n backgroundColor: theme.palette.background.default,\n color: theme.palette.text.primary,\n },\n '&.notistack-MuiContent-high': {\n backgroundColor: theme.palette.background.default,\n color: theme.palette.text.primary,\n },\n '&.notistack-MuiContent-critical': {\n backgroundColor: theme.palette.background.default,\n color: theme.palette.text.primary,\n },\n }),\n);\n\ndeclare module 'notistack' {\n interface VariantOverrides {\n // Custom variants for the snackbar\n low: true;\n normal: true;\n high: true;\n critical: true;\n }\n}\n\n/**\n * @public\n */\nexport type NotificationSnackbarProperties = {\n enabled?: boolean;\n autoHideDuration?: number | null;\n anchorOrigin?: {\n vertical: 'top' | 'bottom';\n horizontal: 'left' | 'center' | 'right';\n };\n dense?: boolean;\n maxSnack?: number;\n snackStyle?: React.CSSProperties;\n iconVariant?: Partial<Record<NotificationSeverity, React.ReactNode>>;\n Components?: {\n [key in NotificationSeverity]: React.JSXElementConstructor<any>;\n };\n};\n\n/**\n * Props passed to the custom renderItem function\n * @public\n */\nexport type NotificationsRenderItemProps = {\n /** Current unread notification count */\n unreadCount: number;\n /** Route path to the notifications page */\n to: string;\n /** Click handler that requests web notification permission */\n onClick: () => void;\n};\n\n/**\n * @public\n */\nexport type NotificationsSideBarItemProps = {\n webNotificationsEnabled?: boolean;\n titleCounterEnabled?: boolean;\n /**\n * @deprecated Use `snackbarProps` instead.\n */\n snackbarEnabled?: boolean;\n /**\n * @deprecated Use `snackbarProps` instead.\n */\n snackbarAutoHideDuration?: number | null;\n snackbarProps?: NotificationSnackbarProperties;\n className?: string;\n icon?: IconComponent;\n text?: string;\n disableHighlight?: boolean;\n noTrack?: boolean;\n /**\n * Optional render function to provide custom UI instead of the default SidebarItem.\n */\n renderItem?: (props: NotificationsRenderItemProps) => React.ReactNode;\n};\n\n/** @public */\nexport const NotificationsSidebarItem = (\n props?: NotificationsSideBarItemProps,\n) => {\n const {\n webNotificationsEnabled = false,\n titleCounterEnabled = true,\n snackbarEnabled = true,\n snackbarAutoHideDuration = 10000,\n icon = NotificationsIcon,\n text = 'Notifications',\n ...restProps\n } = props ?? {\n webNotificationsEnabled: false,\n titleCounterEnabled: true,\n snackbarProps: {\n enabled: true,\n autoHideDuration: 10000,\n },\n };\n\n const snackbarProps = useMemo(\n () =>\n props?.snackbarProps ?? {\n enabled: snackbarEnabled,\n autoHideDuration: snackbarAutoHideDuration,\n },\n [props?.snackbarProps, snackbarAutoHideDuration, snackbarEnabled],\n );\n\n const { loading, error, value, retry } = useNotificationsApi(api =>\n api.getStatus(),\n );\n const notificationsApi = useApi(notificationsApiRef);\n const alertApi = useApi(alertApiRef);\n const [unreadCount, setUnreadCount] = useState(0);\n const notificationsRoute = useRouteRef(rootRouteRef)();\n // TODO: Do we want to add long polling in case signals are not available\n const { lastSignal } = useSignal<NotificationSignal>('notifications');\n const { sendWebNotification, requestUserPermission } = useWebNotifications(\n webNotificationsEnabled,\n );\n const [refresh, setRefresh] = useState(false);\n const { setNotificationCount } = useTitleCounter();\n\n const getSnackbarProperties = useCallback(\n (notification: Notification) => {\n const action = (snackBarId: SnackbarKey) => (\n <>\n <IconButton\n component={Link}\n to={notification.payload.link ?? notificationsRoute}\n onClick={() => {\n if (notification.payload.link) {\n notificationsApi\n .updateNotifications({\n ids: [notification.id],\n read: true,\n })\n .catch(() => {\n alertApi.post({\n message: 'Failed to mark notification as read',\n severity: 'error',\n });\n });\n }\n closeSnackbar(snackBarId);\n }}\n >\n <OpenInNew fontSize=\"small\" />\n </IconButton>\n <IconButton\n onClick={() => {\n notificationsApi\n .updateNotifications({\n ids: [notification.id],\n read: true,\n })\n .then(() => {\n closeSnackbar(snackBarId);\n })\n .catch(() => {\n alertApi.post({\n message: 'Failed to mark notification as read',\n severity: 'error',\n });\n });\n }}\n >\n <MarkAsReadIcon fontSize=\"small\" />\n </IconButton>\n </>\n );\n\n return { action };\n },\n [notificationsRoute, notificationsApi, alertApi],\n );\n\n useEffect(() => {\n if (refresh) {\n retry();\n setRefresh(false);\n }\n }, [refresh, retry]);\n\n useEffect(() => {\n const handleNotificationSignal = (signal: NotificationSignal) => {\n if (\n (!webNotificationsEnabled && !snackbarProps.enabled) ||\n signal.action !== 'new_notification'\n ) {\n return;\n }\n notificationsApi\n .getNotification(signal.notification_id)\n .then(notification => {\n if (!notification) {\n return;\n }\n if (webNotificationsEnabled) {\n sendWebNotification({\n id: notification.id,\n title: notification.payload.title,\n description: notification.payload.description ?? '',\n link: notification.payload.link,\n });\n }\n if (snackbarProps.enabled) {\n const { action } = getSnackbarProperties(notification);\n const snackBarText =\n notification.payload.title.length > 50\n ? `${notification.payload.title.substring(0, 50)}...`\n : notification.payload.title;\n enqueueSnackbar(snackBarText, {\n key: notification.id,\n style: snackbarProps.snackStyle,\n variant: notification.payload.severity,\n anchorOrigin: snackbarProps.anchorOrigin ?? {\n vertical: 'bottom',\n horizontal: 'right',\n },\n action,\n autoHideDuration: snackbarProps.autoHideDuration,\n } as OptionsWithExtraProps<VariantType>);\n }\n })\n .catch(() => {\n alertApi.post({\n message: 'Failed to fetch notification',\n severity: 'error',\n });\n });\n };\n\n if (lastSignal && lastSignal.action) {\n handleNotificationSignal(lastSignal);\n setRefresh(true);\n }\n }, [\n lastSignal,\n sendWebNotification,\n webNotificationsEnabled,\n notificationsApi,\n alertApi,\n getSnackbarProperties,\n snackbarProps,\n ]);\n\n useEffect(() => {\n if (!loading && !error && value) {\n setUnreadCount(value.unread);\n }\n }, [loading, error, value]);\n\n useEffect(() => {\n if (titleCounterEnabled) {\n setNotificationCount(unreadCount);\n }\n }, [titleCounterEnabled, unreadCount, setNotificationCount]);\n\n const count = !error && !!unreadCount ? unreadCount : undefined;\n\n const handleClick = useCallback(() => {\n requestUserPermission();\n }, [requestUserPermission]);\n\n // Props to pass to custom renderItem function\n const renderItemProps: NotificationsRenderItemProps = useMemo(\n () => ({\n unreadCount,\n to: notificationsRoute,\n onClick: handleClick,\n }),\n [unreadCount, notificationsRoute, handleClick],\n );\n\n return (\n <>\n {snackbarEnabled && (\n <SnackbarProvider\n iconVariant={{\n normal: snackbarProps?.iconVariant?.normal ?? (\n <SeverityIcon severity=\"normal\" />\n ),\n critical: snackbarProps?.iconVariant?.critical ?? (\n <SeverityIcon severity=\"critical\" />\n ),\n high: snackbarProps?.iconVariant?.high ?? (\n <SeverityIcon severity=\"high\" />\n ),\n low: snackbarProps?.iconVariant?.low ?? (\n <SeverityIcon severity=\"low\" />\n ),\n }}\n dense={snackbarProps?.dense}\n maxSnack={snackbarProps?.maxSnack}\n Components={{\n normal:\n snackbarProps?.Components?.normal ?? StyledMaterialDesignContent,\n critical:\n snackbarProps?.Components?.critical ??\n StyledMaterialDesignContent,\n high:\n snackbarProps?.Components?.high ?? StyledMaterialDesignContent,\n low: snackbarProps?.Components?.low ?? StyledMaterialDesignContent,\n }}\n />\n )}\n {props?.renderItem ? (\n props.renderItem(renderItemProps)\n ) : (\n <SidebarItem\n to={notificationsRoute}\n onClick={handleClick}\n text={text}\n icon={icon}\n {...restProps}\n >\n {count && <Chip size=\"small\" label={count > 99 ? '99+' : count} />}\n </SidebarItem>\n )}\n </>\n );\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"NotificationsSideBarItem.esm.js","sources":["../../../src/components/NotificationsSideBarItem/NotificationsSideBarItem.tsx"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { forwardRef, useCallback, useEffect, useMemo, useState } from 'react';\nimport { useNotificationsApi } from '../../hooks';\nimport { SidebarItem } from '@backstage/core-components';\nimport { IconComponent, useApi, useRouteRef } from '@backstage/core-plugin-api';\nimport { toastApiRef } from '@backstage/frontend-plugin-api';\nimport { rootRouteRef } from '../../routes';\nimport { useSignal } from '@backstage/plugin-signals-react';\nimport {\n Notification,\n NotificationSeverity,\n NotificationSignal,\n} from '@backstage/plugin-notifications-common';\nimport { useWebNotifications } from '../../hooks/useWebNotifications';\nimport { useTitleCounter } from '../../hooks/useTitleCounter';\nimport { notificationsApiRef } from '../../api';\nimport {\n closeSnackbar,\n enqueueSnackbar,\n MaterialDesignContent,\n OptionsWithExtraProps,\n SnackbarKey,\n SnackbarProvider,\n VariantType,\n} from 'notistack';\nimport { SeverityIcon } from '../NotificationsTable/SeverityIcon';\nimport { ButtonIcon, Flex, Tag, TagGroup } from '@backstage/ui';\nimport {\n RiExternalLinkLine,\n RiCheckboxCircleLine,\n RiNotification2Line,\n} from '@remixicon/react';\nimport styles from './NotificationsSideBarItem.module.css';\n\nconst NotificationsIcon: IconComponent = props => {\n let size = 24;\n if (props.fontSize === 'large') {\n size = 32;\n } else if (props.fontSize === 'small') {\n size = 16;\n }\n return <RiNotification2Line size={size} />;\n};\n\nconst StyledMaterialDesignContent = forwardRef<HTMLDivElement, any>(\n (props: any, ref: React.Ref<HTMLDivElement>) => (\n <MaterialDesignContent\n {...props}\n ref={ref}\n className={[props.className, styles.snackbarContent]\n .filter(Boolean)\n .join(' ')}\n />\n ),\n);\n\ndeclare module 'notistack' {\n interface VariantOverrides {\n // Custom variants for the snackbar\n low: true;\n normal: true;\n high: true;\n critical: true;\n }\n}\n\n/**\n * @public\n */\nexport type NotificationSnackbarProperties = {\n enabled?: boolean;\n autoHideDuration?: number | null;\n anchorOrigin?: {\n vertical: 'top' | 'bottom';\n horizontal: 'left' | 'center' | 'right';\n };\n dense?: boolean;\n maxSnack?: number;\n snackStyle?: React.CSSProperties;\n iconVariant?: Partial<Record<NotificationSeverity, React.ReactNode>>;\n Components?: {\n [key in NotificationSeverity]: React.JSXElementConstructor<any>;\n };\n};\n\n/**\n * Props passed to the custom renderItem function\n * @public\n */\nexport type NotificationsRenderItemProps = {\n /** Current unread notification count */\n unreadCount: number;\n /** Route path to the notifications page */\n to: string;\n /** Click handler that requests web notification permission */\n onClick: () => void;\n};\n\n/**\n * @public\n */\nexport type NotificationsSideBarItemProps = {\n webNotificationsEnabled?: boolean;\n titleCounterEnabled?: boolean;\n /**\n * @deprecated Use `snackbarProps` instead.\n */\n snackbarEnabled?: boolean;\n /**\n * @deprecated Use `snackbarProps` instead.\n */\n snackbarAutoHideDuration?: number | null;\n snackbarProps?: NotificationSnackbarProperties;\n className?: string;\n icon?: IconComponent;\n text?: string;\n disableHighlight?: boolean;\n noTrack?: boolean;\n /**\n * Optional render function to provide custom UI instead of the default SidebarItem.\n */\n renderItem?: (props: NotificationsRenderItemProps) => React.ReactNode;\n};\n\n/** @public */\nexport const NotificationsSidebarItem = (\n props?: NotificationsSideBarItemProps,\n) => {\n const {\n webNotificationsEnabled = false,\n titleCounterEnabled = true,\n snackbarEnabled = true,\n snackbarAutoHideDuration = 15000,\n icon = NotificationsIcon,\n text = 'Notifications',\n ...restProps\n } = props ?? {\n webNotificationsEnabled: false,\n titleCounterEnabled: true,\n snackbarProps: {\n enabled: true,\n autoHideDuration: 15000,\n },\n };\n\n const snackbarProps = useMemo(\n () =>\n props?.snackbarProps ?? {\n enabled: snackbarEnabled,\n autoHideDuration: snackbarAutoHideDuration,\n },\n [props?.snackbarProps, snackbarAutoHideDuration, snackbarEnabled],\n );\n\n const { loading, error, value, retry } = useNotificationsApi(api =>\n api.getStatus(),\n );\n const notificationsApi = useApi(notificationsApiRef);\n const toastApi = useApi(toastApiRef);\n const [unreadCount, setUnreadCount] = useState(0);\n const notificationsRoute = useRouteRef(rootRouteRef)();\n // TODO: Do we want to add long polling in case signals are not available\n const { lastSignal } = useSignal<NotificationSignal>('notifications');\n const { sendWebNotification, requestUserPermission } = useWebNotifications(\n webNotificationsEnabled,\n );\n const [refresh, setRefresh] = useState(false);\n const { setNotificationCount } = useTitleCounter();\n\n const getSnackbarProperties = useCallback(\n (notification: Notification) => {\n const action = (snackBarId: SnackbarKey) => (\n <Flex gap=\"1\">\n <ButtonIcon\n aria-label=\"open notification\"\n icon={<RiExternalLinkLine size={16} />}\n variant=\"secondary\"\n onPress={() => {\n const link = notification.payload.link ?? notificationsRoute;\n window.open(link, '_blank', 'noopener,noreferrer');\n if (notification.payload.link) {\n notificationsApi\n .updateNotifications({\n ids: [notification.id],\n read: true,\n })\n .catch(() => {\n toastApi.post({\n title: 'Failed to mark notification as read',\n status: 'danger',\n });\n });\n }\n closeSnackbar(snackBarId);\n }}\n />\n <ButtonIcon\n aria-label=\"mark as read\"\n icon={<RiCheckboxCircleLine size={16} />}\n variant=\"secondary\"\n onPress={() => {\n notificationsApi\n .updateNotifications({\n ids: [notification.id],\n read: true,\n })\n .then(() => {\n closeSnackbar(snackBarId);\n })\n .catch(() => {\n toastApi.post({\n title: 'Failed to mark notification as read',\n status: 'danger',\n });\n });\n }}\n />\n </Flex>\n );\n\n return { action };\n },\n [notificationsRoute, notificationsApi, toastApi],\n );\n\n useEffect(() => {\n if (refresh) {\n retry();\n setRefresh(false);\n }\n }, [refresh, retry]);\n\n useEffect(() => {\n const handleNotificationSignal = (signal: NotificationSignal) => {\n if (\n (!webNotificationsEnabled && !snackbarProps.enabled) ||\n signal.action !== 'new_notification'\n ) {\n return;\n }\n notificationsApi\n .getNotification(signal.notification_id)\n .then(notification => {\n if (!notification) {\n return;\n }\n if (webNotificationsEnabled) {\n sendWebNotification({\n id: notification.id,\n title: notification.payload.title,\n description: notification.payload.description ?? '',\n link: notification.payload.link,\n });\n }\n if (snackbarProps.enabled) {\n const { action } = getSnackbarProperties(notification);\n const snackBarText =\n notification.payload.title.length > 50\n ? `${notification.payload.title.substring(0, 50)}...`\n : notification.payload.title;\n enqueueSnackbar(snackBarText, {\n key: notification.id,\n style: snackbarProps.snackStyle,\n variant: notification.payload.severity,\n anchorOrigin: snackbarProps.anchorOrigin ?? {\n vertical: 'bottom',\n horizontal: 'right',\n },\n action,\n autoHideDuration: snackbarProps.autoHideDuration,\n } as OptionsWithExtraProps<VariantType>);\n }\n })\n .catch(() => {\n toastApi.post({\n title: 'Failed to fetch notification',\n status: 'danger',\n });\n });\n };\n\n if (lastSignal && lastSignal.action) {\n handleNotificationSignal(lastSignal);\n setRefresh(true);\n }\n }, [\n lastSignal,\n sendWebNotification,\n webNotificationsEnabled,\n notificationsApi,\n toastApi,\n getSnackbarProperties,\n snackbarProps,\n ]);\n\n useEffect(() => {\n if (!loading && !error && value) {\n setUnreadCount(value.unread);\n }\n }, [loading, error, value]);\n\n useEffect(() => {\n if (titleCounterEnabled) {\n setNotificationCount(unreadCount);\n }\n }, [titleCounterEnabled, unreadCount, setNotificationCount]);\n\n const count = !error && !!unreadCount ? unreadCount : undefined;\n\n const handleClick = useCallback(() => {\n requestUserPermission();\n }, [requestUserPermission]);\n\n // Props to pass to custom renderItem function\n const renderItemProps: NotificationsRenderItemProps = useMemo(\n () => ({\n unreadCount,\n to: notificationsRoute,\n onClick: handleClick,\n }),\n [unreadCount, notificationsRoute, handleClick],\n );\n\n return (\n <>\n {snackbarEnabled && (\n <SnackbarProvider\n iconVariant={{\n normal: snackbarProps?.iconVariant?.normal ?? (\n <SeverityIcon severity=\"normal\" className={styles.snackbarIcon} />\n ),\n critical: snackbarProps?.iconVariant?.critical ?? (\n <SeverityIcon\n severity=\"critical\"\n className={styles.snackbarIcon}\n />\n ),\n high: snackbarProps?.iconVariant?.high ?? (\n <SeverityIcon severity=\"high\" className={styles.snackbarIcon} />\n ),\n low: snackbarProps?.iconVariant?.low ?? (\n <SeverityIcon severity=\"low\" className={styles.snackbarIcon} />\n ),\n }}\n dense={snackbarProps?.dense}\n maxSnack={snackbarProps?.maxSnack}\n Components={{\n normal:\n snackbarProps?.Components?.normal ?? StyledMaterialDesignContent,\n critical:\n snackbarProps?.Components?.critical ??\n StyledMaterialDesignContent,\n high:\n snackbarProps?.Components?.high ?? StyledMaterialDesignContent,\n low: snackbarProps?.Components?.low ?? StyledMaterialDesignContent,\n }}\n />\n )}\n {props?.renderItem ? (\n props.renderItem(renderItemProps)\n ) : (\n <SidebarItem\n to={notificationsRoute}\n onClick={handleClick}\n text={text}\n icon={icon}\n {...restProps}\n >\n {count && (\n <TagGroup aria-label=\"Unread notifications\">\n <Tag size=\"small\">{count > 99 ? '99+' : count}</Tag>\n </TagGroup>\n )}\n </SidebarItem>\n )}\n </>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import styleInject from '../../node_modules_dist/style-inject/dist/style-inject.es.esm.js';
2
+
3
+ var css_248z = "/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n@layer components {\n .NotificationsSideBarItem_snackbarContent__7e80c9a4a0 {\n background-color: var(--bui-bg-app);\n color: var(--bui-fg-primary);\n }\n\n .NotificationsSideBarItem_snackbarIcon__7e80c9a4a0 {\n margin-right: var(--bui-space-2);\n }\n}\n";
4
+ var styles = {"snackbarContent":"NotificationsSideBarItem_snackbarContent__7e80c9a4a0","snackbarIcon":"NotificationsSideBarItem_snackbarIcon__7e80c9a4a0"};
5
+ styleInject(css_248z);
6
+
7
+ export { styles as default };
8
+ //# sourceMappingURL=NotificationsSideBarItem.module.css.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NotificationsSideBarItem.module.css.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;"}
@@ -1,12 +1,6 @@
1
1
  import { jsxs, jsx } from 'react/jsx-runtime';
2
- import Grid from '@material-ui/core/Grid';
3
- import IconButton from '@material-ui/core/IconButton';
4
- import Tooltip from '@material-ui/core/Tooltip';
5
- import MarkAsUnreadIcon from '@material-ui/icons/Markunread';
6
- import MarkAsReadIcon from '@material-ui/icons/CheckCircle';
7
- import MarkAsUnsavedIcon from '@material-ui/icons/LabelOff';
8
- import MarkAsSavedIcon from '@material-ui/icons/Label';
9
- import MarkAllReadIcon from '@material-ui/icons/DoneAll';
2
+ import { Flex, TooltipTrigger, ButtonIcon, Tooltip } from '@backstage/ui';
3
+ import { RiCheckDoubleLine, RiBookmark3Line, RiBookmarkLine, RiMailLine, RiCheckboxCircleLine } from '@remixicon/react';
10
4
  import { useTranslationRef } from '@backstage/core-plugin-api/alpha';
11
5
  import { notificationsTranslationRef } from '../../translation.esm.js';
12
6
 
@@ -30,32 +24,54 @@ const BulkActions = ({
30
24
  (notification) => !!notification.saved
31
25
  );
32
26
  const markAsReadText = isOneRead ? t("table.bulkActions.returnSelectedAmongUnread") : t("table.bulkActions.markSelectedAsRead");
33
- const IconComponent = isOneRead ? MarkAsUnreadIcon : MarkAsReadIcon;
27
+ const ReadIcon = isOneRead ? RiMailLine : RiCheckboxCircleLine;
34
28
  const markAsSavedText = isOneSaved ? t("table.bulkActions.undoSaveForSelected") : t("table.bulkActions.saveSelectedForLater");
35
- const SavedIconComponent = isOneSaved ? MarkAsUnsavedIcon : MarkAsSavedIcon;
29
+ const SavedIcon = isOneSaved ? RiBookmark3Line : RiBookmarkLine;
36
30
  const markAllReadText = t("table.bulkActions.markAllRead");
37
- return /* @__PURE__ */ jsxs(Grid, { container: true, wrap: "nowrap", children: [
38
- /* @__PURE__ */ jsx(Grid, { item: true, xs: 3, children: onMarkAllRead ? /* @__PURE__ */ jsx(Tooltip, { title: markAllReadText, children: /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(IconButton, { disabled: !isUnread, onClick: onMarkAllRead, children: /* @__PURE__ */ jsx(MarkAllReadIcon, { "aria-label": markAllReadText }) }) }) }) : /* @__PURE__ */ jsx("div", {}) }),
39
- /* @__PURE__ */ jsx(Grid, { item: true, xs: 3, children: /* @__PURE__ */ jsx(Tooltip, { title: markAsSavedText, children: /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
40
- IconButton,
41
- {
42
- disabled: isDisabled,
43
- onClick: () => {
44
- onSwitchSavedStatus([...selectedNotifications], !isOneSaved);
45
- },
46
- children: /* @__PURE__ */ jsx(SavedIconComponent, { "aria-label": markAsSavedText })
47
- }
48
- ) }) }) }),
49
- /* @__PURE__ */ jsx(Grid, { item: true, xs: 3, children: /* @__PURE__ */ jsx(Tooltip, { title: markAsReadText, children: /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
50
- IconButton,
51
- {
52
- disabled: isDisabled,
53
- onClick: () => {
54
- onSwitchReadStatus([...selectedNotifications], !isOneRead);
55
- },
56
- children: /* @__PURE__ */ jsx(IconComponent, { "aria-label": markAsReadText })
57
- }
58
- ) }) }) })
31
+ return /* @__PURE__ */ jsxs(Flex, { gap: "1", children: [
32
+ onMarkAllRead ? /* @__PURE__ */ jsxs(TooltipTrigger, { children: [
33
+ /* @__PURE__ */ jsx(
34
+ ButtonIcon,
35
+ {
36
+ "aria-label": markAllReadText,
37
+ isDisabled: !isUnread,
38
+ onPress: onMarkAllRead,
39
+ icon: /* @__PURE__ */ jsx(RiCheckDoubleLine, { size: 16 }),
40
+ variant: "secondary"
41
+ }
42
+ ),
43
+ /* @__PURE__ */ jsx(Tooltip, { children: markAllReadText })
44
+ ] }) : /* @__PURE__ */ jsx("div", {}),
45
+ /* @__PURE__ */ jsxs(TooltipTrigger, { children: [
46
+ /* @__PURE__ */ jsx(
47
+ ButtonIcon,
48
+ {
49
+ "aria-label": markAsSavedText,
50
+ isDisabled,
51
+ onPress: () => {
52
+ onSwitchSavedStatus([...selectedNotifications], !isOneSaved);
53
+ },
54
+ icon: /* @__PURE__ */ jsx(SavedIcon, { size: 16 }),
55
+ variant: "secondary"
56
+ }
57
+ ),
58
+ /* @__PURE__ */ jsx(Tooltip, { children: markAsSavedText })
59
+ ] }),
60
+ /* @__PURE__ */ jsxs(TooltipTrigger, { children: [
61
+ /* @__PURE__ */ jsx(
62
+ ButtonIcon,
63
+ {
64
+ "aria-label": markAsReadText,
65
+ isDisabled,
66
+ onPress: () => {
67
+ onSwitchReadStatus([...selectedNotifications], !isOneRead);
68
+ },
69
+ icon: /* @__PURE__ */ jsx(ReadIcon, { size: 16 }),
70
+ variant: "secondary"
71
+ }
72
+ ),
73
+ /* @__PURE__ */ jsx(Tooltip, { children: markAsReadText })
74
+ ] })
59
75
  ] });
60
76
  };
61
77
 
@@ -1 +1 @@
1
- {"version":3,"file":"BulkActions.esm.js","sources":["../../../src/components/NotificationsTable/BulkActions.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 { Notification } from '@backstage/plugin-notifications-common';\nimport Grid from '@material-ui/core/Grid';\nimport IconButton from '@material-ui/core/IconButton';\nimport Tooltip from '@material-ui/core/Tooltip';\nimport MarkAsUnreadIcon from '@material-ui/icons/Markunread' /* TODO: use Drafts and MarkAsUnread once we have mui 5 icons */;\nimport MarkAsReadIcon from '@material-ui/icons/CheckCircle';\nimport MarkAsUnsavedIcon from '@material-ui/icons/LabelOff' /* TODO: use BookmarkRemove and BookmarkAdd once we have mui 5 icons */;\nimport MarkAsSavedIcon from '@material-ui/icons/Label';\nimport MarkAllReadIcon from '@material-ui/icons/DoneAll';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport { notificationsTranslationRef } from '../../translation';\n\nexport const BulkActions = ({\n selectedNotifications,\n notifications,\n isUnread,\n onSwitchReadStatus,\n onSwitchSavedStatus,\n onMarkAllRead,\n}: {\n selectedNotifications: Set<Notification['id']>;\n notifications: Notification[];\n isUnread?: boolean;\n onSwitchReadStatus: (ids: Notification['id'][], newStatus: boolean) => void;\n onSwitchSavedStatus: (ids: Notification['id'][], newStatus: boolean) => void;\n onMarkAllRead?: () => void;\n}) => {\n const { t } = useTranslationRef(notificationsTranslationRef);\n const isDisabled = selectedNotifications.size === 0;\n const bulkNotifications = notifications.filter(notification =>\n selectedNotifications.has(notification.id),\n );\n\n const isOneRead = !!bulkNotifications.find(\n (notification: Notification) => !!notification.read,\n );\n const isOneSaved = !!bulkNotifications.find(\n (notification: Notification) => !!notification.saved,\n );\n\n const markAsReadText = isOneRead\n ? t('table.bulkActions.returnSelectedAmongUnread')\n : t('table.bulkActions.markSelectedAsRead');\n const IconComponent = isOneRead ? MarkAsUnreadIcon : MarkAsReadIcon;\n\n const markAsSavedText = isOneSaved\n ? t('table.bulkActions.undoSaveForSelected')\n : t('table.bulkActions.saveSelectedForLater');\n const SavedIconComponent = isOneSaved ? MarkAsUnsavedIcon : MarkAsSavedIcon;\n const markAllReadText = t('table.bulkActions.markAllRead');\n\n return (\n <Grid container wrap=\"nowrap\">\n <Grid item xs={3}>\n {onMarkAllRead ? (\n <Tooltip title={markAllReadText}>\n <div>\n {/* The <div> here is a workaround for the Tooltip which does not work for a \"disabled\" child */}\n <IconButton disabled={!isUnread} onClick={onMarkAllRead}>\n <MarkAllReadIcon aria-label={markAllReadText} />\n </IconButton>\n </div>\n </Tooltip>\n ) : (\n <div />\n )}\n </Grid>\n\n <Grid item xs={3}>\n <Tooltip title={markAsSavedText}>\n <div>\n {/* The <div> here is a workaround for the Tooltip which does not work for a \"disabled\" child */}\n <IconButton\n disabled={isDisabled}\n onClick={() => {\n onSwitchSavedStatus([...selectedNotifications], !isOneSaved);\n }}\n >\n <SavedIconComponent aria-label={markAsSavedText} />\n </IconButton>\n </div>\n </Tooltip>\n </Grid>\n\n <Grid item xs={3}>\n <Tooltip title={markAsReadText}>\n <div>\n <IconButton\n disabled={isDisabled}\n onClick={() => {\n onSwitchReadStatus([...selectedNotifications], !isOneRead);\n }}\n >\n <IconComponent aria-label={markAsReadText} />\n </IconButton>\n </div>\n </Tooltip>\n </Grid>\n </Grid>\n );\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"BulkActions.esm.js","sources":["../../../src/components/NotificationsTable/BulkActions.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 { Notification } from '@backstage/plugin-notifications-common';\nimport { ButtonIcon, Flex, Tooltip, TooltipTrigger } from '@backstage/ui';\nimport {\n RiCheckDoubleLine,\n RiBookmarkLine,\n RiBookmark3Line,\n RiCheckboxCircleLine,\n RiMailLine,\n} from '@remixicon/react';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport { notificationsTranslationRef } from '../../translation';\n\nexport const BulkActions = ({\n selectedNotifications,\n notifications,\n isUnread,\n onSwitchReadStatus,\n onSwitchSavedStatus,\n onMarkAllRead,\n}: {\n selectedNotifications: Set<Notification['id']>;\n notifications: Notification[];\n isUnread?: boolean;\n onSwitchReadStatus: (ids: Notification['id'][], newStatus: boolean) => void;\n onSwitchSavedStatus: (ids: Notification['id'][], newStatus: boolean) => void;\n onMarkAllRead?: () => void;\n}) => {\n const { t } = useTranslationRef(notificationsTranslationRef);\n const isDisabled = selectedNotifications.size === 0;\n const bulkNotifications = notifications.filter(notification =>\n selectedNotifications.has(notification.id),\n );\n\n const isOneRead = !!bulkNotifications.find(\n (notification: Notification) => !!notification.read,\n );\n const isOneSaved = !!bulkNotifications.find(\n (notification: Notification) => !!notification.saved,\n );\n\n const markAsReadText = isOneRead\n ? t('table.bulkActions.returnSelectedAmongUnread')\n : t('table.bulkActions.markSelectedAsRead');\n const ReadIcon = isOneRead ? RiMailLine : RiCheckboxCircleLine;\n\n const markAsSavedText = isOneSaved\n ? t('table.bulkActions.undoSaveForSelected')\n : t('table.bulkActions.saveSelectedForLater');\n const SavedIcon = isOneSaved ? RiBookmark3Line : RiBookmarkLine;\n const markAllReadText = t('table.bulkActions.markAllRead');\n\n return (\n <Flex gap=\"1\">\n {onMarkAllRead ? (\n <TooltipTrigger>\n <ButtonIcon\n aria-label={markAllReadText}\n isDisabled={!isUnread}\n onPress={onMarkAllRead}\n icon={<RiCheckDoubleLine size={16} />}\n variant=\"secondary\"\n />\n <Tooltip>{markAllReadText}</Tooltip>\n </TooltipTrigger>\n ) : (\n <div />\n )}\n\n <TooltipTrigger>\n <ButtonIcon\n aria-label={markAsSavedText}\n isDisabled={isDisabled}\n onPress={() => {\n onSwitchSavedStatus([...selectedNotifications], !isOneSaved);\n }}\n icon={<SavedIcon size={16} />}\n variant=\"secondary\"\n />\n <Tooltip>{markAsSavedText}</Tooltip>\n </TooltipTrigger>\n\n <TooltipTrigger>\n <ButtonIcon\n aria-label={markAsReadText}\n isDisabled={isDisabled}\n onPress={() => {\n onSwitchReadStatus([...selectedNotifications], !isOneRead);\n }}\n icon={<ReadIcon size={16} />}\n variant=\"secondary\"\n />\n <Tooltip>{markAsReadText}</Tooltip>\n </TooltipTrigger>\n </Flex>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -1,6 +1,5 @@
1
1
  import { jsx, jsxs } from 'react/jsx-runtime';
2
- import Typography from '@material-ui/core/Typography';
3
- import Button from '@material-ui/core/Button';
2
+ import { Text, Button } from '@backstage/ui';
4
3
  import { useState } from 'react';
5
4
 
6
5
  const MAX_LENGTH = 100;
@@ -9,18 +8,17 @@ const NotificationDescription = (props) => {
9
8
  const [shown, setShown] = useState(false);
10
9
  const isLong = description.length > MAX_LENGTH;
11
10
  if (!isLong) {
12
- return /* @__PURE__ */ jsx(Typography, { variant: "body2", children: description });
11
+ return /* @__PURE__ */ jsx(Text, { variant: "body-small", children: description });
13
12
  }
14
13
  if (shown) {
15
- return /* @__PURE__ */ jsxs(Typography, { variant: "body2", children: [
14
+ return /* @__PURE__ */ jsxs(Text, { variant: "body-small", children: [
16
15
  description,
17
16
  " ",
18
17
  /* @__PURE__ */ jsx(
19
18
  Button,
20
19
  {
21
- variant: "text",
22
- size: "small",
23
- onClick: () => {
20
+ variant: "tertiary",
21
+ onPress: () => {
24
22
  setShown(false);
25
23
  },
26
24
  children: "Show less"
@@ -28,16 +26,15 @@ const NotificationDescription = (props) => {
28
26
  )
29
27
  ] });
30
28
  }
31
- return /* @__PURE__ */ jsxs(Typography, { variant: "body2", children: [
29
+ return /* @__PURE__ */ jsxs(Text, { variant: "body-small", children: [
32
30
  description.substring(0, MAX_LENGTH),
33
31
  "...",
34
32
  " ",
35
33
  /* @__PURE__ */ jsx(
36
34
  Button,
37
35
  {
38
- variant: "text",
39
- size: "small",
40
- onClick: () => {
36
+ variant: "tertiary",
37
+ onPress: () => {
41
38
  setShown(true);
42
39
  },
43
40
  children: "Show more"
@@ -1 +1 @@
1
- {"version":3,"file":"NotificationDescription.esm.js","sources":["../../../src/components/NotificationsTable/NotificationDescription.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 Typography from '@material-ui/core/Typography';\nimport Button from '@material-ui/core/Button';\nimport { useState } from 'react';\n\nconst MAX_LENGTH = 100;\n\nexport const NotificationDescription = (props: { description: string }) => {\n const { description } = props;\n const [shown, setShown] = useState(false);\n const isLong = description.length > MAX_LENGTH;\n\n if (!isLong) {\n return <Typography variant=\"body2\">{description}</Typography>;\n }\n\n if (shown) {\n return (\n <Typography variant=\"body2\">\n {description}{' '}\n <Button\n variant=\"text\"\n size=\"small\"\n onClick={() => {\n setShown(false);\n }}\n >\n Show less\n </Button>\n </Typography>\n );\n }\n return (\n <Typography variant=\"body2\">\n {description.substring(0, MAX_LENGTH)}...{' '}\n <Button\n variant=\"text\"\n size=\"small\"\n onClick={() => {\n setShown(true);\n }}\n >\n Show more\n </Button>\n </Typography>\n );\n};\n"],"names":[],"mappings":";;;;;AAmBA,MAAM,UAAA,GAAa,GAAA;AAEZ,MAAM,uBAAA,GAA0B,CAAC,KAAA,KAAmC;AACzE,EAAA,MAAM,EAAE,aAAY,GAAI,KAAA;AACxB,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAS,KAAK,CAAA;AACxC,EAAA,MAAM,MAAA,GAAS,YAAY,MAAA,GAAS,UAAA;AAEpC,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,uBAAO,GAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,OAAA,EAAS,QAAA,EAAA,WAAA,EAAY,CAAA;AAAA,EAClD;AAEA,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,uBACE,IAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,OAAA,EACjB,QAAA,EAAA;AAAA,MAAA,WAAA;AAAA,MAAa,GAAA;AAAA,sBACd,GAAA;AAAA,QAAC,MAAA;AAAA,QAAA;AAAA,UACC,OAAA,EAAQ,MAAA;AAAA,UACR,IAAA,EAAK,OAAA;AAAA,UACL,SAAS,MAAM;AACb,YAAA,QAAA,CAAS,KAAK,CAAA;AAAA,UAChB,CAAA;AAAA,UACD,QAAA,EAAA;AAAA;AAAA;AAED,KAAA,EACF,CAAA;AAAA,EAEJ;AACA,EAAA,uBACE,IAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,OAAA,EACjB,QAAA,EAAA;AAAA,IAAA,WAAA,CAAY,SAAA,CAAU,GAAG,UAAU,CAAA;AAAA,IAAE,KAAA;AAAA,IAAI,GAAA;AAAA,oBAC1C,GAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,OAAA,EAAQ,MAAA;AAAA,QACR,IAAA,EAAK,OAAA;AAAA,QACL,SAAS,MAAM;AACb,UAAA,QAAA,CAAS,IAAI,CAAA;AAAA,QACf,CAAA;AAAA,QACD,QAAA,EAAA;AAAA;AAAA;AAED,GAAA,EACF,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"NotificationDescription.esm.js","sources":["../../../src/components/NotificationsTable/NotificationDescription.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 { Text, Button } from '@backstage/ui';\nimport { useState } from 'react';\n\nconst MAX_LENGTH = 100;\n\nexport const NotificationDescription = (props: { description: string }) => {\n const { description } = props;\n const [shown, setShown] = useState(false);\n const isLong = description.length > MAX_LENGTH;\n\n if (!isLong) {\n return <Text variant=\"body-small\">{description}</Text>;\n }\n\n if (shown) {\n return (\n <Text variant=\"body-small\">\n {description}{' '}\n <Button\n variant=\"tertiary\"\n onPress={() => {\n setShown(false);\n }}\n >\n Show less\n </Button>\n </Text>\n );\n }\n return (\n <Text variant=\"body-small\">\n {description.substring(0, MAX_LENGTH)}...{' '}\n <Button\n variant=\"tertiary\"\n onPress={() => {\n setShown(true);\n }}\n >\n Show more\n </Button>\n </Text>\n );\n};\n"],"names":[],"mappings":";;;;AAkBA,MAAM,UAAA,GAAa,GAAA;AAEZ,MAAM,uBAAA,GAA0B,CAAC,KAAA,KAAmC;AACzE,EAAA,MAAM,EAAE,aAAY,GAAI,KAAA;AACxB,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAS,KAAK,CAAA;AACxC,EAAA,MAAM,MAAA,GAAS,YAAY,MAAA,GAAS,UAAA;AAEpC,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,uBAAO,GAAA,CAAC,IAAA,EAAA,EAAK,OAAA,EAAQ,YAAA,EAAc,QAAA,EAAA,WAAA,EAAY,CAAA;AAAA,EACjD;AAEA,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,uBACE,IAAA,CAAC,IAAA,EAAA,EAAK,OAAA,EAAQ,YAAA,EACX,QAAA,EAAA;AAAA,MAAA,WAAA;AAAA,MAAa,GAAA;AAAA,sBACd,GAAA;AAAA,QAAC,MAAA;AAAA,QAAA;AAAA,UACC,OAAA,EAAQ,UAAA;AAAA,UACR,SAAS,MAAM;AACb,YAAA,QAAA,CAAS,KAAK,CAAA;AAAA,UAChB,CAAA;AAAA,UACD,QAAA,EAAA;AAAA;AAAA;AAED,KAAA,EACF,CAAA;AAAA,EAEJ;AACA,EAAA,uBACE,IAAA,CAAC,IAAA,EAAA,EAAK,OAAA,EAAQ,YAAA,EACX,QAAA,EAAA;AAAA,IAAA,WAAA,CAAY,SAAA,CAAU,GAAG,UAAU,CAAA;AAAA,IAAE,KAAA;AAAA,IAAI,GAAA;AAAA,oBAC1C,GAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,OAAA,EAAQ,UAAA;AAAA,QACR,SAAS,MAAM;AACb,UAAA,QAAA,CAAS,IAAI,CAAA;AAAA,QACf,CAAA;AAAA,QACD,QAAA,EAAA;AAAA;AAAA;AAED,GAAA,EACF,CAAA;AAEJ;;;;"}
@@ -1,5 +1,4 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
- import SvgIcon from '@material-ui/core/SvgIcon';
3
2
  import { useApp } from '@backstage/core-plugin-api';
4
3
  import { SeverityIcon } from './SeverityIcon.esm.js';
5
4
 
@@ -8,8 +7,10 @@ const NotificationIcon = ({
8
7
  }) => {
9
8
  const app = useApp();
10
9
  if (notification.payload.icon) {
11
- const Icon = app.getSystemIcon(notification.payload.icon) ?? SvgIcon;
12
- return /* @__PURE__ */ jsx(Icon, {});
10
+ const Icon = app.getSystemIcon(notification.payload.icon);
11
+ if (Icon) {
12
+ return /* @__PURE__ */ jsx(Icon, {});
13
+ }
13
14
  }
14
15
  return /* @__PURE__ */ jsx(SeverityIcon, { severity: notification.payload.severity });
15
16
  };
@@ -1 +1 @@
1
- {"version":3,"file":"NotificationIcon.esm.js","sources":["../../../src/components/NotificationsTable/NotificationIcon.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 { Notification } from '@backstage/plugin-notifications-common';\nimport SvgIcon from '@material-ui/core/SvgIcon';\nimport { useApp } from '@backstage/core-plugin-api';\nimport { SeverityIcon } from './SeverityIcon';\n\nexport const NotificationIcon = ({\n notification,\n}: {\n notification: Notification;\n}) => {\n const app = useApp();\n\n if (notification.payload.icon) {\n const Icon = app.getSystemIcon(notification.payload.icon) ?? SvgIcon;\n return <Icon />;\n }\n return <SeverityIcon severity={notification.payload.severity} />;\n};\n"],"names":[],"mappings":";;;;;AAoBO,MAAM,mBAAmB,CAAC;AAAA,EAC/B;AACF,CAAA,KAEM;AACJ,EAAA,MAAM,MAAM,MAAA,EAAO;AAEnB,EAAA,IAAI,YAAA,CAAa,QAAQ,IAAA,EAAM;AAC7B,IAAA,MAAM,OAAO,GAAA,CAAI,aAAA,CAAc,YAAA,CAAa,OAAA,CAAQ,IAAI,CAAA,IAAK,OAAA;AAC7D,IAAA,2BAAQ,IAAA,EAAA,EAAK,CAAA;AAAA,EACf;AACA,EAAA,uBAAO,GAAA,CAAC,YAAA,EAAA,EAAa,QAAA,EAAU,YAAA,CAAa,QAAQ,QAAA,EAAU,CAAA;AAChE;;;;"}
1
+ {"version":3,"file":"NotificationIcon.esm.js","sources":["../../../src/components/NotificationsTable/NotificationIcon.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 { Notification } from '@backstage/plugin-notifications-common';\nimport { useApp } from '@backstage/core-plugin-api';\nimport { SeverityIcon } from './SeverityIcon';\n\nexport const NotificationIcon = ({\n notification,\n}: {\n notification: Notification;\n}) => {\n const app = useApp();\n\n if (notification.payload.icon) {\n const Icon = app.getSystemIcon(notification.payload.icon);\n if (Icon) {\n return <Icon />;\n }\n }\n return <SeverityIcon severity={notification.payload.severity} />;\n};\n"],"names":[],"mappings":";;;;AAmBO,MAAM,mBAAmB,CAAC;AAAA,EAC/B;AACF,CAAA,KAEM;AACJ,EAAA,MAAM,MAAM,MAAA,EAAO;AAEnB,EAAA,IAAI,YAAA,CAAa,QAAQ,IAAA,EAAM;AAC7B,IAAA,MAAM,IAAA,GAAO,GAAA,CAAI,aAAA,CAAc,YAAA,CAAa,QAAQ,IAAI,CAAA;AACxD,IAAA,IAAI,IAAA,EAAM;AACR,MAAA,2BAAQ,IAAA,EAAA,EAAK,CAAA;AAAA,IACf;AAAA,EACF;AACA,EAAA,uBAAO,GAAA,CAAC,YAAA,EAAA,EAAa,QAAA,EAAU,YAAA,CAAa,QAAQ,QAAA,EAAU,CAAA;AAChE;;;;"}