@backstage/plugin-notifications 0.5.4-next.1 → 0.5.4-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.
- package/CHANGELOG.md +19 -0
- package/dist/alpha.d.ts +2 -2
- package/dist/alpha.esm.js +2 -2
- package/dist/alpha.esm.js.map +1 -1
- package/dist/components/NotificationsFilters/NotificationsFilters.esm.js +82 -53
- package/dist/components/NotificationsFilters/NotificationsFilters.esm.js.map +1 -1
- package/dist/components/NotificationsPage/NotificationsPage.esm.js +54 -52
- package/dist/components/NotificationsPage/NotificationsPage.esm.js.map +1 -1
- package/dist/components/NotificationsSideBarItem/NotificationsSideBarItem.esm.js +68 -61
- package/dist/components/NotificationsSideBarItem/NotificationsSideBarItem.esm.js.map +1 -1
- package/dist/components/NotificationsTable/BulkActions.esm.js +22 -18
- package/dist/components/NotificationsTable/BulkActions.esm.js.map +1 -1
- package/dist/components/NotificationsTable/NotificationIcon.esm.js +3 -3
- package/dist/components/NotificationsTable/NotificationIcon.esm.js.map +1 -1
- package/dist/components/NotificationsTable/NotificationsTable.esm.js +71 -46
- package/dist/components/NotificationsTable/NotificationsTable.esm.js.map +1 -1
- package/dist/components/NotificationsTable/SelectAll.esm.js +3 -3
- package/dist/components/NotificationsTable/SelectAll.esm.js.map +1 -1
- package/dist/components/NotificationsTable/SeverityIcon.esm.js +5 -5
- package/dist/components/NotificationsTable/SeverityIcon.esm.js.map +1 -1
- package/dist/components/UserNotificationSettingsCard/UserNotificationSettingsCard.esm.js +15 -10
- package/dist/components/UserNotificationSettingsCard/UserNotificationSettingsCard.esm.js.map +1 -1
- package/dist/components/UserNotificationSettingsCard/UserNotificationSettingsPanel.esm.js +33 -24
- package/dist/components/UserNotificationSettingsCard/UserNotificationSettingsPanel.esm.js.map +1 -1
- package/dist/index.d.ts +5 -6
- package/package.json +15 -15
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useState, useCallback, useEffect } from 'react';
|
|
2
3
|
import { useNotificationsApi } from '../../hooks/useNotificationsApi.esm.js';
|
|
3
4
|
import { useWebNotifications } from '../../hooks/useWebNotifications.esm.js';
|
|
4
5
|
import { useTitleCounter } from '../../hooks/useTitleCounter.esm.js';
|
|
@@ -57,56 +58,59 @@ const NotificationsSidebarItem = (props) => {
|
|
|
57
58
|
);
|
|
58
59
|
const notificationsApi = useApi(notificationsApiRef);
|
|
59
60
|
const alertApi = useApi(alertApiRef);
|
|
60
|
-
const [unreadCount, setUnreadCount] =
|
|
61
|
+
const [unreadCount, setUnreadCount] = useState(0);
|
|
61
62
|
const notificationsRoute = useRouteRef(rootRouteRef)();
|
|
62
63
|
const { lastSignal } = useSignal("notifications");
|
|
63
64
|
const { sendWebNotification, requestUserPermission } = useWebNotifications(
|
|
64
65
|
webNotificationsEnabled
|
|
65
66
|
);
|
|
66
|
-
const [refresh, setRefresh] =
|
|
67
|
+
const [refresh, setRefresh] = useState(false);
|
|
67
68
|
const { setNotificationCount } = useTitleCounter();
|
|
68
69
|
const getSnackbarProperties = useCallback(
|
|
69
70
|
(notification) => {
|
|
70
|
-
const action = (snackBarId) => /* @__PURE__ */
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
71
|
+
const action = (snackBarId) => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
72
|
+
/* @__PURE__ */ jsx(
|
|
73
|
+
IconButton,
|
|
74
|
+
{
|
|
75
|
+
component: Link,
|
|
76
|
+
to: notification.payload.link ?? notificationsRoute,
|
|
77
|
+
onClick: () => {
|
|
78
|
+
if (notification.payload.link) {
|
|
79
|
+
notificationsApi.updateNotifications({
|
|
80
|
+
ids: [notification.id],
|
|
81
|
+
read: true
|
|
82
|
+
}).catch(() => {
|
|
83
|
+
alertApi.post({
|
|
84
|
+
message: "Failed to mark notification as read",
|
|
85
|
+
severity: "error"
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
closeSnackbar(snackBarId);
|
|
90
|
+
},
|
|
91
|
+
children: /* @__PURE__ */ jsx(OpenInNew, { fontSize: "small" })
|
|
92
|
+
}
|
|
93
|
+
),
|
|
94
|
+
/* @__PURE__ */ jsx(
|
|
95
|
+
IconButton,
|
|
96
|
+
{
|
|
97
|
+
onClick: () => {
|
|
77
98
|
notificationsApi.updateNotifications({
|
|
78
99
|
ids: [notification.id],
|
|
79
100
|
read: true
|
|
101
|
+
}).then(() => {
|
|
102
|
+
closeSnackbar(snackBarId);
|
|
80
103
|
}).catch(() => {
|
|
81
104
|
alertApi.post({
|
|
82
105
|
message: "Failed to mark notification as read",
|
|
83
106
|
severity: "error"
|
|
84
107
|
});
|
|
85
108
|
});
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
}
|
|
89
|
-
},
|
|
90
|
-
/* @__PURE__ */ React.createElement(OpenInNew, { fontSize: "small" })
|
|
91
|
-
), /* @__PURE__ */ React.createElement(
|
|
92
|
-
IconButton,
|
|
93
|
-
{
|
|
94
|
-
onClick: () => {
|
|
95
|
-
notificationsApi.updateNotifications({
|
|
96
|
-
ids: [notification.id],
|
|
97
|
-
read: true
|
|
98
|
-
}).then(() => {
|
|
99
|
-
closeSnackbar(snackBarId);
|
|
100
|
-
}).catch(() => {
|
|
101
|
-
alertApi.post({
|
|
102
|
-
message: "Failed to mark notification as read",
|
|
103
|
-
severity: "error"
|
|
104
|
-
});
|
|
105
|
-
});
|
|
109
|
+
},
|
|
110
|
+
children: /* @__PURE__ */ jsx(MarkAsReadIcon, { fontSize: "small" })
|
|
106
111
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
));
|
|
112
|
+
)
|
|
113
|
+
] });
|
|
110
114
|
return { action };
|
|
111
115
|
},
|
|
112
116
|
[notificationsRoute, notificationsApi, alertApi]
|
|
@@ -177,35 +181,38 @@ const NotificationsSidebarItem = (props) => {
|
|
|
177
181
|
}
|
|
178
182
|
}, [titleCounterEnabled, unreadCount, setNotificationCount]);
|
|
179
183
|
const count = !error && !!unreadCount ? unreadCount : void 0;
|
|
180
|
-
return /* @__PURE__ */
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
184
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
185
|
+
snackbarEnabled && /* @__PURE__ */ jsx(
|
|
186
|
+
SnackbarProvider,
|
|
187
|
+
{
|
|
188
|
+
iconVariant: {
|
|
189
|
+
normal: /* @__PURE__ */ jsx(SeverityIcon, { severity: "normal" }),
|
|
190
|
+
critical: /* @__PURE__ */ jsx(SeverityIcon, { severity: "critical" }),
|
|
191
|
+
high: /* @__PURE__ */ jsx(SeverityIcon, { severity: "high" }),
|
|
192
|
+
low: /* @__PURE__ */ jsx(SeverityIcon, { severity: "low" })
|
|
193
|
+
},
|
|
194
|
+
Components: {
|
|
195
|
+
normal: StyledMaterialDesignContent,
|
|
196
|
+
critical: StyledMaterialDesignContent,
|
|
197
|
+
high: StyledMaterialDesignContent,
|
|
198
|
+
low: StyledMaterialDesignContent
|
|
199
|
+
}
|
|
194
200
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
201
|
+
),
|
|
202
|
+
/* @__PURE__ */ jsx(
|
|
203
|
+
SidebarItem,
|
|
204
|
+
{
|
|
205
|
+
to: notificationsRoute,
|
|
206
|
+
onClick: () => {
|
|
207
|
+
requestUserPermission();
|
|
208
|
+
},
|
|
209
|
+
text,
|
|
210
|
+
icon,
|
|
211
|
+
...restProps,
|
|
212
|
+
children: count && /* @__PURE__ */ jsx(Chip, { size: "small", label: count > 99 ? "99+" : count })
|
|
213
|
+
}
|
|
214
|
+
)
|
|
215
|
+
] });
|
|
209
216
|
};
|
|
210
217
|
|
|
211
218
|
export { NotificationsSidebarItem };
|
|
@@ -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 React, { useCallback, useEffect } 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 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/** @public */\nexport const NotificationsSidebarItem = (props?: {\n webNotificationsEnabled?: boolean;\n titleCounterEnabled?: boolean;\n snackbarEnabled?: boolean;\n snackbarAutoHideDuration?: number | null;\n className?: string;\n icon?: IconComponent;\n text?: string;\n disableHighlight?: boolean;\n noTrack?: boolean;\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 snackbarEnabled: true,\n snackbarAutoHideDuration: 10000,\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] = React.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] = React.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 && !snackbarEnabled) ||\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 (snackbarEnabled) {\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 variant: notification.payload.severity,\n anchorOrigin: { vertical: 'bottom', horizontal: 'right' },\n action,\n autoHideDuration: snackbarAutoHideDuration,\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 snackbarEnabled,\n snackbarAutoHideDuration,\n notificationsApi,\n alertApi,\n getSnackbarProperties,\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 return (\n <>\n {snackbarEnabled && (\n <SnackbarProvider\n iconVariant={{\n normal: <SeverityIcon severity=\"normal\" />,\n critical: <SeverityIcon severity=\"critical\" />,\n high: <SeverityIcon severity=\"high\" />,\n low: <SeverityIcon severity=\"low\" />,\n }}\n Components={{\n normal: StyledMaterialDesignContent,\n critical: StyledMaterialDesignContent,\n high: StyledMaterialDesignContent,\n low: StyledMaterialDesignContent,\n }}\n />\n )}\n <SidebarItem\n to={notificationsRoute}\n onClick={() => {\n requestUserPermission();\n }}\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"],"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 { useState, useCallback, useEffect } 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 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/** @public */\nexport const NotificationsSidebarItem = (props?: {\n webNotificationsEnabled?: boolean;\n titleCounterEnabled?: boolean;\n snackbarEnabled?: boolean;\n snackbarAutoHideDuration?: number | null;\n className?: string;\n icon?: IconComponent;\n text?: string;\n disableHighlight?: boolean;\n noTrack?: boolean;\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 snackbarEnabled: true,\n snackbarAutoHideDuration: 10000,\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 && !snackbarEnabled) ||\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 (snackbarEnabled) {\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 variant: notification.payload.severity,\n anchorOrigin: { vertical: 'bottom', horizontal: 'right' },\n action,\n autoHideDuration: snackbarAutoHideDuration,\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 snackbarEnabled,\n snackbarAutoHideDuration,\n notificationsApi,\n alertApi,\n getSnackbarProperties,\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 return (\n <>\n {snackbarEnabled && (\n <SnackbarProvider\n iconVariant={{\n normal: <SeverityIcon severity=\"normal\" />,\n critical: <SeverityIcon severity=\"critical\" />,\n high: <SeverityIcon severity=\"high\" />,\n low: <SeverityIcon severity=\"low\" />,\n }}\n Components={{\n normal: StyledMaterialDesignContent,\n critical: StyledMaterialDesignContent,\n high: StyledMaterialDesignContent,\n low: StyledMaterialDesignContent,\n }}\n />\n )}\n <SidebarItem\n to={notificationsRoute}\n onClick={() => {\n requestUserPermission();\n }}\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"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
2
|
import Grid from '@material-ui/core/Grid';
|
|
3
3
|
import IconButton from '@material-ui/core/IconButton';
|
|
4
4
|
import Tooltip from '@material-ui/core/Tooltip';
|
|
@@ -30,25 +30,29 @@ const BulkActions = ({
|
|
|
30
30
|
const IconComponent = isOneRead ? MarkAsUnreadIcon : MarkAsReadIcon;
|
|
31
31
|
const markAsSavedText = isOneSaved ? "Undo save for selected" : "Save selected for later";
|
|
32
32
|
const SavedIconComponent = isOneSaved ? MarkAsUnsavedIcon : MarkAsSavedIcon;
|
|
33
|
-
return /* @__PURE__ */
|
|
34
|
-
IconButton,
|
|
35
|
-
{
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
return /* @__PURE__ */ jsxs(Grid, { container: true, wrap: "nowrap", children: [
|
|
34
|
+
/* @__PURE__ */ jsx(Grid, { item: true, xs: 3, children: onMarkAllRead ? /* @__PURE__ */ jsx(Tooltip, { title: "Mark all read", children: /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(IconButton, { disabled: !isUnread, onClick: onMarkAllRead, children: /* @__PURE__ */ jsx(MarkAllReadIcon, { "aria-label": markAsSavedText }) }) }) }) : /* @__PURE__ */ jsx("div", {}) }),
|
|
35
|
+
/* @__PURE__ */ jsx(Grid, { item: true, xs: 3, children: /* @__PURE__ */ jsx(Tooltip, { title: markAsSavedText, children: /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
|
|
36
|
+
IconButton,
|
|
37
|
+
{
|
|
38
|
+
disabled: isDisabled,
|
|
39
|
+
onClick: () => {
|
|
40
|
+
onSwitchSavedStatus([...selectedNotifications], !isOneSaved);
|
|
41
|
+
},
|
|
42
|
+
children: /* @__PURE__ */ jsx(SavedIconComponent, { "aria-label": markAsSavedText })
|
|
39
43
|
}
|
|
40
|
-
},
|
|
41
|
-
/* @__PURE__ */
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
) }) }) }),
|
|
45
|
+
/* @__PURE__ */ jsx(Grid, { item: true, xs: 3, children: /* @__PURE__ */ jsx(Tooltip, { title: markAsReadText, children: /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
|
|
46
|
+
IconButton,
|
|
47
|
+
{
|
|
48
|
+
disabled: isDisabled,
|
|
49
|
+
onClick: () => {
|
|
50
|
+
onSwitchReadStatus([...selectedNotifications], !isOneRead);
|
|
51
|
+
},
|
|
52
|
+
children: /* @__PURE__ */ jsx(IconComponent, { "aria-label": markAsReadText })
|
|
48
53
|
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
)))));
|
|
54
|
+
) }) }) })
|
|
55
|
+
] });
|
|
52
56
|
};
|
|
53
57
|
|
|
54
58
|
export { BulkActions };
|
|
@@ -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
|
|
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';\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 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 ? 'Return selected among unread'\n : 'Mark selected as read';\n const IconComponent = isOneRead ? MarkAsUnreadIcon : MarkAsReadIcon;\n\n const markAsSavedText = isOneSaved\n ? 'Undo save for selected'\n : 'Save selected for later';\n const SavedIconComponent = isOneSaved ? MarkAsUnsavedIcon : MarkAsSavedIcon;\n\n return (\n <Grid container wrap=\"nowrap\">\n <Grid item xs={3}>\n {onMarkAllRead ? (\n <Tooltip title=\"Mark all read\">\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={markAsSavedText} />\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,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
2
|
import SvgIcon from '@material-ui/core/SvgIcon';
|
|
3
3
|
import { useApp } from '@backstage/core-plugin-api';
|
|
4
4
|
import { SeverityIcon } from './SeverityIcon.esm.js';
|
|
@@ -9,9 +9,9 @@ const NotificationIcon = ({
|
|
|
9
9
|
const app = useApp();
|
|
10
10
|
if (notification.payload.icon) {
|
|
11
11
|
const Icon = app.getSystemIcon(notification.payload.icon) ?? SvgIcon;
|
|
12
|
-
return /* @__PURE__ */
|
|
12
|
+
return /* @__PURE__ */ jsx(Icon, {});
|
|
13
13
|
}
|
|
14
|
-
return /* @__PURE__ */
|
|
14
|
+
return /* @__PURE__ */ jsx(SeverityIcon, { severity: notification.payload.severity });
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
export { NotificationIcon };
|
|
@@ -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
|
|
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,CAEM,KAAA;AACJ,EAAA,MAAM,MAAM,MAAO,EAAA;AAEnB,EAAI,IAAA,YAAA,CAAa,QAAQ,IAAM,EAAA;AAC7B,IAAA,MAAM,OAAO,GAAI,CAAA,aAAA,CAAc,YAAa,CAAA,OAAA,CAAQ,IAAI,CAAK,IAAA,OAAA;AAC7D,IAAA,2BAAQ,IAAK,EAAA,EAAA,CAAA;AAAA;AAEf,EAAA,uBAAQ,GAAA,CAAA,YAAA,EAAA,EAAa,QAAU,EAAA,YAAA,CAAa,QAAQ,QAAU,EAAA,CAAA;AAChE;;;;"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useState, useCallback, useMemo, useEffect } from 'react';
|
|
2
3
|
import throttle from 'lodash/throttle';
|
|
3
4
|
import RelativeTime from 'react-relative-time';
|
|
4
5
|
import Box from '@material-ui/core/Box';
|
|
@@ -52,10 +53,10 @@ const NotificationsTable = ({
|
|
|
52
53
|
const notificationsApi = useApi(notificationsApiRef);
|
|
53
54
|
const alertApi = useApi(alertApiRef);
|
|
54
55
|
const confirm = useConfirm();
|
|
55
|
-
const [selectedNotifications, setSelectedNotifications] =
|
|
56
|
+
const [selectedNotifications, setSelectedNotifications] = useState(
|
|
56
57
|
/* @__PURE__ */ new Set()
|
|
57
58
|
);
|
|
58
|
-
const onNotificationsSelectChange =
|
|
59
|
+
const onNotificationsSelectChange = useCallback(
|
|
59
60
|
(ids, checked) => {
|
|
60
61
|
let newSelect;
|
|
61
62
|
if (checked) {
|
|
@@ -68,7 +69,7 @@ const NotificationsTable = ({
|
|
|
68
69
|
},
|
|
69
70
|
[selectedNotifications, setSelectedNotifications]
|
|
70
71
|
);
|
|
71
|
-
const onSwitchReadStatus =
|
|
72
|
+
const onSwitchReadStatus = useCallback(
|
|
72
73
|
(ids, newStatus) => {
|
|
73
74
|
notificationsApi.updateNotifications({
|
|
74
75
|
ids,
|
|
@@ -77,7 +78,7 @@ const NotificationsTable = ({
|
|
|
77
78
|
},
|
|
78
79
|
[notificationsApi, onUpdate]
|
|
79
80
|
);
|
|
80
|
-
const onSwitchSavedStatus =
|
|
81
|
+
const onSwitchSavedStatus = useCallback(
|
|
81
82
|
(ids, newStatus) => {
|
|
82
83
|
notificationsApi.updateNotifications({
|
|
83
84
|
ids,
|
|
@@ -86,10 +87,16 @@ const NotificationsTable = ({
|
|
|
86
87
|
},
|
|
87
88
|
[notificationsApi, onUpdate]
|
|
88
89
|
);
|
|
89
|
-
const onMarkAllRead =
|
|
90
|
+
const onMarkAllRead = useCallback(() => {
|
|
90
91
|
confirm({
|
|
91
92
|
title: "Are you sure?",
|
|
92
|
-
description: /* @__PURE__ */
|
|
93
|
+
description: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
94
|
+
"Mark ",
|
|
95
|
+
/* @__PURE__ */ jsx("b", { children: "all" }),
|
|
96
|
+
" notifications as ",
|
|
97
|
+
/* @__PURE__ */ jsx("b", { children: "read" }),
|
|
98
|
+
"."
|
|
99
|
+
] }),
|
|
93
100
|
confirmationText: "Mark All"
|
|
94
101
|
}).then(async () => {
|
|
95
102
|
const ids = (await notificationsApi.getNotifications({ read: false })).notifications?.map((notification) => notification.id);
|
|
@@ -106,11 +113,11 @@ const NotificationsTable = ({
|
|
|
106
113
|
}
|
|
107
114
|
});
|
|
108
115
|
}, [alertApi, confirm, notificationsApi, onUpdate]);
|
|
109
|
-
const throttledContainsTextHandler =
|
|
116
|
+
const throttledContainsTextHandler = useMemo(
|
|
110
117
|
() => throttle(setContainsText, ThrottleDelayMs),
|
|
111
118
|
[setContainsText]
|
|
112
119
|
);
|
|
113
|
-
|
|
120
|
+
useEffect(() => {
|
|
114
121
|
const allShownIds = new Set(notifications.map((n) => n.id));
|
|
115
122
|
const intersect = [...selectedNotifications].filter(
|
|
116
123
|
(id) => allShownIds.has(id)
|
|
@@ -119,13 +126,13 @@ const NotificationsTable = ({
|
|
|
119
126
|
setSelectedNotifications(new Set(intersect));
|
|
120
127
|
}
|
|
121
128
|
}, [notifications, selectedNotifications]);
|
|
122
|
-
const compactColumns =
|
|
129
|
+
const compactColumns = useMemo(() => {
|
|
123
130
|
const showToolbar = notifications.length > 0;
|
|
124
131
|
return [
|
|
125
132
|
{
|
|
126
133
|
/* selection column */
|
|
127
134
|
width: "1rem",
|
|
128
|
-
title: showToolbar ? /* @__PURE__ */
|
|
135
|
+
title: showToolbar ? /* @__PURE__ */ jsx(
|
|
129
136
|
SelectAll,
|
|
130
137
|
{
|
|
131
138
|
count: selectedNotifications.size,
|
|
@@ -136,7 +143,7 @@ const NotificationsTable = ({
|
|
|
136
143
|
)
|
|
137
144
|
}
|
|
138
145
|
) : void 0,
|
|
139
|
-
render: (notification) => /* @__PURE__ */
|
|
146
|
+
render: (notification) => /* @__PURE__ */ jsx(
|
|
140
147
|
Checkbox,
|
|
141
148
|
{
|
|
142
149
|
color: "primary",
|
|
@@ -149,44 +156,62 @@ const NotificationsTable = ({
|
|
|
149
156
|
/* compact-data column */
|
|
150
157
|
customFilterAndSearch: () => true,
|
|
151
158
|
render: (notification) => {
|
|
152
|
-
return /* @__PURE__ */
|
|
153
|
-
|
|
154
|
-
{
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
+
return /* @__PURE__ */ jsxs(Grid, { container: true, children: [
|
|
160
|
+
/* @__PURE__ */ jsx(Grid, { item: true, className: classes.severityItem, children: /* @__PURE__ */ jsx(NotificationIcon, { notification }) }),
|
|
161
|
+
/* @__PURE__ */ jsx(Grid, { item: true, xs: 11, children: /* @__PURE__ */ jsxs(Box, { children: [
|
|
162
|
+
/* @__PURE__ */ jsx(Typography, { variant: "subtitle1", children: notification.payload.link ? /* @__PURE__ */ jsx(
|
|
163
|
+
Link,
|
|
164
|
+
{
|
|
165
|
+
to: notification.payload.link,
|
|
166
|
+
onClick: () => {
|
|
167
|
+
if (markAsReadOnLinkOpen && !notification.read) {
|
|
168
|
+
onSwitchReadStatus([notification.id], true);
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
children: notification.payload.title
|
|
159
172
|
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
173
|
+
) : notification.payload.title }),
|
|
174
|
+
notification.payload.description ? /* @__PURE__ */ jsx(Typography, { variant: "body2", className: classes.description, children: notification.payload.description }) : null,
|
|
175
|
+
/* @__PURE__ */ jsxs(Typography, { variant: "caption", children: [
|
|
176
|
+
!notification.user && /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(BroadcastIcon, { className: classes.broadcastIcon }) }),
|
|
177
|
+
notification.origin && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
178
|
+
/* @__PURE__ */ jsx(
|
|
179
|
+
Typography,
|
|
180
|
+
{
|
|
181
|
+
variant: "inherit",
|
|
182
|
+
className: classes.notificationInfoRow,
|
|
183
|
+
children: notification.origin
|
|
184
|
+
}
|
|
185
|
+
),
|
|
186
|
+
"\u2022"
|
|
187
|
+
] }),
|
|
188
|
+
notification.payload.topic && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
189
|
+
/* @__PURE__ */ jsx(
|
|
190
|
+
Typography,
|
|
191
|
+
{
|
|
192
|
+
variant: "inherit",
|
|
193
|
+
className: classes.notificationInfoRow,
|
|
194
|
+
children: notification.payload.topic
|
|
195
|
+
}
|
|
196
|
+
),
|
|
197
|
+
"\u2022"
|
|
198
|
+
] }),
|
|
199
|
+
notification.created && /* @__PURE__ */ jsx(
|
|
200
|
+
RelativeTime,
|
|
201
|
+
{
|
|
202
|
+
value: notification.created,
|
|
203
|
+
className: classes.notificationInfoRow
|
|
204
|
+
}
|
|
205
|
+
)
|
|
206
|
+
] })
|
|
207
|
+
] }) })
|
|
208
|
+
] });
|
|
184
209
|
}
|
|
185
210
|
},
|
|
186
211
|
{
|
|
187
212
|
/* actions column */
|
|
188
213
|
width: "1rem",
|
|
189
|
-
title: showToolbar ? /* @__PURE__ */
|
|
214
|
+
title: showToolbar ? /* @__PURE__ */ jsx(
|
|
190
215
|
BulkActions,
|
|
191
216
|
{
|
|
192
217
|
notifications,
|
|
@@ -197,7 +222,7 @@ const NotificationsTable = ({
|
|
|
197
222
|
onMarkAllRead
|
|
198
223
|
}
|
|
199
224
|
) : void 0,
|
|
200
|
-
render: (notification) => /* @__PURE__ */
|
|
225
|
+
render: (notification) => /* @__PURE__ */ jsx(
|
|
201
226
|
BulkActions,
|
|
202
227
|
{
|
|
203
228
|
notifications: [notification],
|
|
@@ -222,7 +247,7 @@ const NotificationsTable = ({
|
|
|
222
247
|
classes.notificationInfoRow,
|
|
223
248
|
markAsReadOnLinkOpen
|
|
224
249
|
]);
|
|
225
|
-
return /* @__PURE__ */
|
|
250
|
+
return /* @__PURE__ */ jsx(
|
|
226
251
|
Table,
|
|
227
252
|
{
|
|
228
253
|
isLoading,
|