@backstage/plugin-notifications 0.0.1-next.1 → 0.1.0-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +34 -0
- package/dist/esm/index-3798ac09.esm.js +134 -0
- package/dist/esm/index-3798ac09.esm.js.map +1 -0
- package/dist/index.d.ts +14 -8
- package/dist/index.esm.js +123 -222
- package/dist/index.esm.js.map +1 -1
- package/package.json +12 -11
- package/dist/esm/index-9074aad8.esm.js +0 -89
- package/dist/esm/index-9074aad8.esm.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,39 @@
|
|
|
1
1
|
# @backstage/plugin-notifications
|
|
2
2
|
|
|
3
|
+
## 0.1.0-next.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 758f2a4: The Notifications frontend has been redesigned towards list view with condensed row details. The 'done' attribute has been removed to keep the Notifications aligned with the idea of a messaging system instead of a task manager.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- 5d9c5ba: The Notifications can be newly filtered based on the Created Date.
|
|
12
|
+
- Updated dependencies
|
|
13
|
+
- @backstage/errors@1.2.4-next.0
|
|
14
|
+
- @backstage/theme@0.5.2-next.0
|
|
15
|
+
- @backstage/core-components@0.14.1-next.0
|
|
16
|
+
- @backstage/plugin-notifications-common@0.0.2-next.0
|
|
17
|
+
- @backstage/core-plugin-api@1.9.1-next.0
|
|
18
|
+
- @backstage/types@1.1.1
|
|
19
|
+
- @backstage/plugin-signals-react@0.0.2-next.0
|
|
20
|
+
|
|
21
|
+
## 0.0.1
|
|
22
|
+
|
|
23
|
+
### Patch Changes
|
|
24
|
+
|
|
25
|
+
- 9873c44: Add support for signal type in notifications
|
|
26
|
+
- 8472188: Added or fixed the `repository` field in `package.json`.
|
|
27
|
+
- fb8fc24: Initial notifications system for backstage
|
|
28
|
+
- Updated dependencies
|
|
29
|
+
- @backstage/core-components@0.14.0
|
|
30
|
+
- @backstage/plugin-signals-react@0.0.1
|
|
31
|
+
- @backstage/plugin-notifications-common@0.0.1
|
|
32
|
+
- @backstage/theme@0.5.1
|
|
33
|
+
- @backstage/core-plugin-api@1.9.0
|
|
34
|
+
- @backstage/errors@1.2.3
|
|
35
|
+
- @backstage/types@1.1.1
|
|
36
|
+
|
|
3
37
|
## 0.0.1-next.1
|
|
4
38
|
|
|
5
39
|
### Patch Changes
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import React, { useEffect } from 'react';
|
|
2
|
+
import { ResponseErrorPanel, PageWithHeader, Content } from '@backstage/core-components';
|
|
3
|
+
import { Grid, Typography, Divider, FormControl, InputLabel, Select, MenuItem } from '@material-ui/core';
|
|
4
|
+
import { useSignal } from '@backstage/plugin-signals-react';
|
|
5
|
+
import { useNotificationsApi, NotificationsTable } from '../index.esm.js';
|
|
6
|
+
import '@backstage/core-plugin-api';
|
|
7
|
+
import '@backstage/errors';
|
|
8
|
+
import 'react-use/lib/useAsyncRetry';
|
|
9
|
+
import '@material-ui/icons/Notifications';
|
|
10
|
+
import 'lodash/throttle';
|
|
11
|
+
import '@material-ui/icons/Markunread';
|
|
12
|
+
import '@material-ui/icons/CheckCircle';
|
|
13
|
+
import 'react-relative-time';
|
|
14
|
+
|
|
15
|
+
const CreatedAfterOptions = {
|
|
16
|
+
last24h: {
|
|
17
|
+
label: "Last 24h",
|
|
18
|
+
getDate: () => new Date(Date.now() - 24 * 3600 * 1e3)
|
|
19
|
+
},
|
|
20
|
+
lastWeek: {
|
|
21
|
+
label: "Last week",
|
|
22
|
+
getDate: () => new Date(Date.now() - 7 * 24 * 3600 * 1e3)
|
|
23
|
+
},
|
|
24
|
+
all: {
|
|
25
|
+
label: "Any time",
|
|
26
|
+
getDate: () => /* @__PURE__ */ new Date(0)
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
const NotificationsFilters = ({
|
|
30
|
+
// sorting,
|
|
31
|
+
// setSorting,
|
|
32
|
+
unreadOnly,
|
|
33
|
+
onUnreadOnlyChanged,
|
|
34
|
+
createdAfter,
|
|
35
|
+
onCreatedAfterChanged
|
|
36
|
+
}) => {
|
|
37
|
+
const handleOnCreatedAfterChanged = (event) => {
|
|
38
|
+
onCreatedAfterChanged(event.target.value);
|
|
39
|
+
};
|
|
40
|
+
const handleOnUnreadOnlyChanged = (event) => {
|
|
41
|
+
let value = void 0;
|
|
42
|
+
if (event.target.value === "unread")
|
|
43
|
+
value = true;
|
|
44
|
+
if (event.target.value === "read")
|
|
45
|
+
value = false;
|
|
46
|
+
onUnreadOnlyChanged(value);
|
|
47
|
+
};
|
|
48
|
+
let unreadOnlyValue = "all";
|
|
49
|
+
if (unreadOnly)
|
|
50
|
+
unreadOnlyValue = "unread";
|
|
51
|
+
if (unreadOnly === false)
|
|
52
|
+
unreadOnlyValue = "read";
|
|
53
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Grid, { container: true }, /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React.createElement(Typography, { variant: "h6" }, "Filters"), /* @__PURE__ */ React.createElement(Divider, { variant: "fullWidth" })), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React.createElement(FormControl, { fullWidth: true, variant: "outlined", size: "small" }, /* @__PURE__ */ React.createElement(InputLabel, { id: "notifications-filter-view" }, "View"), /* @__PURE__ */ React.createElement(
|
|
54
|
+
Select,
|
|
55
|
+
{
|
|
56
|
+
labelId: "notifications-filter-view",
|
|
57
|
+
label: "View",
|
|
58
|
+
value: unreadOnlyValue,
|
|
59
|
+
onChange: handleOnUnreadOnlyChanged
|
|
60
|
+
},
|
|
61
|
+
/* @__PURE__ */ React.createElement(MenuItem, { value: "unread" }, "New only"),
|
|
62
|
+
/* @__PURE__ */ React.createElement(MenuItem, { value: "read" }, "Marked as read"),
|
|
63
|
+
/* @__PURE__ */ React.createElement(MenuItem, { value: "all" }, "All")
|
|
64
|
+
))), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React.createElement(FormControl, { fullWidth: true, variant: "outlined", size: "small" }, /* @__PURE__ */ React.createElement(InputLabel, { id: "notifications-filter-view" }, "Created after"), /* @__PURE__ */ React.createElement(
|
|
65
|
+
Select,
|
|
66
|
+
{
|
|
67
|
+
label: "Created after",
|
|
68
|
+
placeholder: "Notifications since",
|
|
69
|
+
value: createdAfter,
|
|
70
|
+
onChange: handleOnCreatedAfterChanged
|
|
71
|
+
},
|
|
72
|
+
Object.keys(CreatedAfterOptions).map((key) => /* @__PURE__ */ React.createElement(MenuItem, { value: key, key }, CreatedAfterOptions[key].label))
|
|
73
|
+
)))));
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const NotificationsPage = () => {
|
|
77
|
+
const [refresh, setRefresh] = React.useState(false);
|
|
78
|
+
const { lastSignal } = useSignal("notifications");
|
|
79
|
+
const [unreadOnly, setUnreadOnly] = React.useState(true);
|
|
80
|
+
const [containsText, setContainsText] = React.useState();
|
|
81
|
+
const [createdAfter, setCreatedAfter] = React.useState("lastWeek");
|
|
82
|
+
const { error, value, retry, loading } = useNotificationsApi(
|
|
83
|
+
// TODO: add pagination and other filters
|
|
84
|
+
(api) => {
|
|
85
|
+
const options = { search: containsText };
|
|
86
|
+
if (unreadOnly !== void 0) {
|
|
87
|
+
options.read = !unreadOnly;
|
|
88
|
+
}
|
|
89
|
+
const createdAfterDate = CreatedAfterOptions[createdAfter].getDate();
|
|
90
|
+
if (createdAfterDate.valueOf() > 0) {
|
|
91
|
+
options.createdAfter = createdAfterDate;
|
|
92
|
+
}
|
|
93
|
+
return api.getNotifications(options);
|
|
94
|
+
},
|
|
95
|
+
[containsText, unreadOnly, createdAfter]
|
|
96
|
+
);
|
|
97
|
+
useEffect(() => {
|
|
98
|
+
if (refresh) {
|
|
99
|
+
retry();
|
|
100
|
+
setRefresh(false);
|
|
101
|
+
}
|
|
102
|
+
}, [refresh, setRefresh, retry]);
|
|
103
|
+
useEffect(() => {
|
|
104
|
+
if (lastSignal && lastSignal.action) {
|
|
105
|
+
setRefresh(true);
|
|
106
|
+
}
|
|
107
|
+
}, [lastSignal]);
|
|
108
|
+
const onUpdate = () => {
|
|
109
|
+
setRefresh(true);
|
|
110
|
+
};
|
|
111
|
+
if (error) {
|
|
112
|
+
return /* @__PURE__ */ React.createElement(ResponseErrorPanel, { error });
|
|
113
|
+
}
|
|
114
|
+
return /* @__PURE__ */ React.createElement(PageWithHeader, { title: "Notifications", themeId: "tool" }, /* @__PURE__ */ React.createElement(Content, null, /* @__PURE__ */ React.createElement(Grid, { container: true }, /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 2 }, /* @__PURE__ */ React.createElement(
|
|
115
|
+
NotificationsFilters,
|
|
116
|
+
{
|
|
117
|
+
unreadOnly,
|
|
118
|
+
onUnreadOnlyChanged: setUnreadOnly,
|
|
119
|
+
createdAfter,
|
|
120
|
+
onCreatedAfterChanged: setCreatedAfter
|
|
121
|
+
}
|
|
122
|
+
)), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 10 }, /* @__PURE__ */ React.createElement(
|
|
123
|
+
NotificationsTable,
|
|
124
|
+
{
|
|
125
|
+
isLoading: loading,
|
|
126
|
+
notifications: value,
|
|
127
|
+
onUpdate,
|
|
128
|
+
setContainsText
|
|
129
|
+
}
|
|
130
|
+
)))));
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
export { NotificationsPage };
|
|
134
|
+
//# sourceMappingURL=index-3798ac09.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-3798ac09.esm.js","sources":["../../src/components/NotificationsFilters/NotificationsFilters.tsx","../../src/components/NotificationsPage/NotificationsPage.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 React from 'react';\n\nimport {\n Divider,\n FormControl,\n Grid,\n InputLabel,\n MenuItem,\n Select,\n Typography,\n} from '@material-ui/core';\n\nexport type NotificationsFiltersProps = {\n unreadOnly?: boolean;\n onUnreadOnlyChanged: (checked: boolean | undefined) => void;\n createdAfter?: string;\n onCreatedAfterChanged: (value: string) => void;\n\n // sorting?: {\n // orderBy: GetNotificationsOrderByEnum;\n // orderByDirec: GetNotificationsOrderByDirecEnum;\n // };\n // setSorting: ({\n // orderBy,\n // orderByDirec,\n // }: {\n // orderBy: GetNotificationsOrderByEnum;\n // orderByDirec: GetNotificationsOrderByDirecEnum;\n // }) => void;\n};\n\nexport const CreatedAfterOptions: {\n [key: string]: { label: string; getDate: () => Date };\n} = {\n last24h: {\n label: 'Last 24h',\n getDate: () => new Date(Date.now() - 24 * 3600 * 1000),\n },\n lastWeek: {\n label: 'Last week',\n getDate: () => new Date(Date.now() - 7 * 24 * 3600 * 1000),\n },\n all: {\n label: 'Any time',\n getDate: () => new Date(0),\n },\n};\n\n// export const SortByOptions: {\n// [key: string]: {\n// label: string;\n// orderBy: GetNotificationsOrderByEnum;\n// orderByDirec: GetNotificationsOrderByDirecEnum;\n// };\n// } = {\n// newest: {\n// label: 'Newest on top',\n// orderBy: GetNotificationsOrderByEnum.Created,\n// orderByDirec: GetNotificationsOrderByDirecEnum.Asc,\n// },\n// oldest: {\n// label: 'Oldest on top',\n// orderBy: GetNotificationsOrderByEnum.Created,\n// orderByDirec: GetNotificationsOrderByDirecEnum.Desc,\n// },\n// topic: {\n// label: 'Topic',\n// orderBy: GetNotificationsOrderByEnum.Topic,\n// orderByDirec: GetNotificationsOrderByDirecEnum.Asc,\n// },\n// origin: {\n// label: 'Origin',\n// orderBy: GetNotificationsOrderByEnum.Origin,\n// orderByDirec: GetNotificationsOrderByDirecEnum.Asc,\n// },\n// };\n\n// TODO: Implement sorting on server (to work with pagination)\n// const getSortBy = (sorting: NotificationsFiltersProps['sorting']): string => {\n// if (\n// sorting?.orderBy === GetNotificationsOrderByEnum.Created &&\n// sorting.orderByDirec === GetNotificationsOrderByDirecEnum.Desc\n// ) {\n// return 'oldest';\n// }\n// if (sorting?.orderBy === GetNotificationsOrderByEnum.Topic) {\n// return 'topic';\n// }\n// if (sorting?.orderBy === GetNotificationsOrderByEnum.Origin) {\n// return 'origin';\n// }\n\n// return 'newest';\n// };\n\nexport const NotificationsFilters = ({\n // sorting,\n // setSorting,\n unreadOnly,\n onUnreadOnlyChanged,\n createdAfter,\n onCreatedAfterChanged,\n}: NotificationsFiltersProps) => {\n // const sortBy = getSortBy(sorting);\n\n const handleOnCreatedAfterChanged = (\n event: React.ChangeEvent<{ name?: string; value: unknown }>,\n ) => {\n onCreatedAfterChanged(event.target.value as string);\n };\n\n const handleOnUnreadOnlyChanged = (\n event: React.ChangeEvent<{ name?: string; value: unknown }>,\n ) => {\n let value = undefined;\n if (event.target.value === 'unread') value = true;\n if (event.target.value === 'read') value = false;\n onUnreadOnlyChanged(value);\n };\n\n // const handleOnSortByChanged = (\n // event: React.ChangeEvent<{ name?: string; value: unknown }>,\n // ) => {\n // const idx = (event.target.value as string) || 'newest';\n // const option = SortByOptions[idx];\n // setSorting({\n // orderBy: option.orderBy,\n // orderByDirec: option.orderByDirec,\n // });\n // };\n\n let unreadOnlyValue = 'all';\n if (unreadOnly) unreadOnlyValue = 'unread';\n if (unreadOnly === false) unreadOnlyValue = 'read';\n\n return (\n <>\n <Grid container>\n <Grid item xs={12}>\n <Typography variant=\"h6\">Filters</Typography>\n <Divider variant=\"fullWidth\" />\n </Grid>\n <Grid item xs={12}>\n <FormControl fullWidth variant=\"outlined\" size=\"small\">\n <InputLabel id=\"notifications-filter-view\">View</InputLabel>\n <Select\n labelId=\"notifications-filter-view\"\n label=\"View\"\n value={unreadOnlyValue}\n onChange={handleOnUnreadOnlyChanged}\n >\n <MenuItem value=\"unread\">New only</MenuItem>\n <MenuItem value=\"read\">Marked as read</MenuItem>\n <MenuItem value=\"all\">All</MenuItem>\n </Select>\n </FormControl>\n </Grid>\n <Grid item xs={12}>\n <FormControl fullWidth variant=\"outlined\" size=\"small\">\n <InputLabel id=\"notifications-filter-view\">\n Created after\n </InputLabel>\n\n <Select\n label=\"Created after\"\n placeholder=\"Notifications since\"\n value={createdAfter}\n onChange={handleOnCreatedAfterChanged}\n >\n {Object.keys(CreatedAfterOptions).map((key: string) => (\n <MenuItem value={key} key={key}>\n {CreatedAfterOptions[key].label}\n </MenuItem>\n ))}\n </Select>\n </FormControl>\n </Grid>\n\n {/*\n <Grid item xs={12}>\n <FormControl fullWidth variant=\"outlined\" size=\"small\">\n <InputLabel id=\"notifications-filter-sort\">Sort by</InputLabel>\n\n <Select\n label=\"Sort by\"\n placeholder=\"Field to sort by\"\n value={sortBy}\n onChange={handleOnSortByChanged}\n >\n {Object.keys(SortByOptions).map((key: string) => (\n <MenuItem value={key} key={key}>\n {SortByOptions[key].label}\n </MenuItem>\n ))}\n </Select>\n </FormControl>\n </Grid> */}\n </Grid>\n </>\n );\n};\n","/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, { useEffect } from 'react';\nimport {\n Content,\n PageWithHeader,\n ResponseErrorPanel,\n} from '@backstage/core-components';\nimport { Grid } from '@material-ui/core';\nimport { useSignal } from '@backstage/plugin-signals-react';\n\nimport { NotificationsTable } from '../NotificationsTable';\nimport { useNotificationsApi } from '../../hooks';\nimport {\n CreatedAfterOptions,\n NotificationsFilters,\n} from '../NotificationsFilters';\nimport { GetNotificationsOptions } from '../../api';\n\nexport const NotificationsPage = () => {\n const [refresh, setRefresh] = React.useState(false);\n const { lastSignal } = useSignal('notifications');\n const [unreadOnly, setUnreadOnly] = React.useState<boolean | undefined>(true);\n const [containsText, setContainsText] = React.useState<string>();\n const [createdAfter, setCreatedAfter] = React.useState<string>('lastWeek');\n\n const { error, value, retry, loading } = useNotificationsApi(\n // TODO: add pagination and other filters\n api => {\n const options: GetNotificationsOptions = { search: containsText };\n if (unreadOnly !== undefined) {\n options.read = !unreadOnly;\n }\n\n const createdAfterDate = CreatedAfterOptions[createdAfter].getDate();\n if (createdAfterDate.valueOf() > 0) {\n options.createdAfter = createdAfterDate;\n }\n\n return api.getNotifications(options);\n },\n [containsText, unreadOnly, createdAfter],\n );\n\n useEffect(() => {\n if (refresh) {\n retry();\n setRefresh(false);\n }\n }, [refresh, setRefresh, retry]);\n\n useEffect(() => {\n if (lastSignal && lastSignal.action) {\n setRefresh(true);\n }\n }, [lastSignal]);\n\n const onUpdate = () => {\n setRefresh(true);\n };\n\n if (error) {\n return <ResponseErrorPanel error={error} />;\n }\n\n return (\n <PageWithHeader title=\"Notifications\" themeId=\"tool\">\n <Content>\n <Grid container>\n <Grid item xs={2}>\n <NotificationsFilters\n unreadOnly={unreadOnly}\n onUnreadOnlyChanged={setUnreadOnly}\n createdAfter={createdAfter}\n onCreatedAfterChanged={setCreatedAfter}\n // setSorting={setSorting}\n // sorting={sorting}\n />\n </Grid>\n <Grid item xs={10}>\n <NotificationsTable\n isLoading={loading}\n notifications={value}\n onUpdate={onUpdate}\n setContainsText={setContainsText}\n />\n </Grid>\n </Grid>\n </Content>\n </PageWithHeader>\n );\n};\n"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import * as React from 'react';
|
|
|
3
3
|
import React__default from 'react';
|
|
4
4
|
import * as _backstage_core_plugin_api from '@backstage/core-plugin-api';
|
|
5
5
|
import { DiscoveryApi, FetchApi } from '@backstage/core-plugin-api';
|
|
6
|
-
import {
|
|
6
|
+
import { Notification as Notification$1, NotificationStatus } from '@backstage/plugin-notifications-common';
|
|
7
7
|
|
|
8
8
|
/** @public */
|
|
9
9
|
declare const notificationsPlugin: _backstage_core_plugin_api.BackstagePlugin<{
|
|
@@ -16,21 +16,22 @@ declare const NotificationsPage: () => React.JSX.Element;
|
|
|
16
16
|
declare const notificationsApiRef: _backstage_core_plugin_api.ApiRef<NotificationsApi>;
|
|
17
17
|
/** @public */
|
|
18
18
|
type GetNotificationsOptions = {
|
|
19
|
-
type?: NotificationType;
|
|
20
19
|
offset?: number;
|
|
21
20
|
limit?: number;
|
|
22
21
|
search?: string;
|
|
22
|
+
read?: boolean;
|
|
23
|
+
createdAfter?: Date;
|
|
23
24
|
};
|
|
24
25
|
/** @public */
|
|
25
26
|
type UpdateNotificationsOptions = {
|
|
26
27
|
ids: string[];
|
|
27
|
-
done?: boolean;
|
|
28
28
|
read?: boolean;
|
|
29
29
|
saved?: boolean;
|
|
30
30
|
};
|
|
31
31
|
/** @public */
|
|
32
32
|
interface NotificationsApi {
|
|
33
33
|
getNotifications(options?: GetNotificationsOptions): Promise<Notification$1[]>;
|
|
34
|
+
getNotification(id: string): Promise<Notification$1>;
|
|
34
35
|
getStatus(): Promise<NotificationStatus>;
|
|
35
36
|
updateNotifications(options: UpdateNotificationsOptions): Promise<Notification$1[]>;
|
|
36
37
|
}
|
|
@@ -44,6 +45,7 @@ declare class NotificationsClient implements NotificationsApi {
|
|
|
44
45
|
fetchApi: FetchApi;
|
|
45
46
|
});
|
|
46
47
|
getNotifications(options?: GetNotificationsOptions): Promise<Notification$1[]>;
|
|
48
|
+
getNotification(id: string): Promise<Notification$1>;
|
|
47
49
|
getStatus(): Promise<NotificationStatus>;
|
|
48
50
|
updateNotifications(options: UpdateNotificationsOptions): Promise<Notification$1[]>;
|
|
49
51
|
private request;
|
|
@@ -77,6 +79,7 @@ declare function useWebNotifications(): {
|
|
|
77
79
|
sendWebNotification: (options: {
|
|
78
80
|
title: string;
|
|
79
81
|
description: string;
|
|
82
|
+
link?: string;
|
|
80
83
|
}) => Notification | null;
|
|
81
84
|
};
|
|
82
85
|
|
|
@@ -92,10 +95,13 @@ declare const NotificationsSidebarItem: (props?: {
|
|
|
92
95
|
}) => React__default.JSX.Element;
|
|
93
96
|
|
|
94
97
|
/** @public */
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
type: NotificationType;
|
|
98
|
+
type NotificationsTableProps = {
|
|
99
|
+
isLoading?: boolean;
|
|
98
100
|
notifications?: Notification$1[];
|
|
99
|
-
|
|
101
|
+
onUpdate: () => void;
|
|
102
|
+
setContainsText: (search: string) => void;
|
|
103
|
+
};
|
|
104
|
+
/** @public */
|
|
105
|
+
declare const NotificationsTable: ({ isLoading, notifications, onUpdate, setContainsText, }: NotificationsTableProps) => React__default.JSX.Element;
|
|
100
106
|
|
|
101
|
-
export { GetNotificationsOptions, NotificationsApi, NotificationsClient, NotificationsPage, NotificationsSidebarItem, NotificationsTable, UpdateNotificationsOptions, notificationsApiRef, notificationsPlugin, useNotificationsApi, useTitleCounter, useWebNotifications };
|
|
107
|
+
export { GetNotificationsOptions, NotificationsApi, NotificationsClient, NotificationsPage, NotificationsSidebarItem, NotificationsTable, NotificationsTableProps, UpdateNotificationsOptions, notificationsApiRef, notificationsPlugin, useNotificationsApi, useTitleCounter, useWebNotifications };
|
package/dist/index.esm.js
CHANGED
|
@@ -1,19 +1,15 @@
|
|
|
1
1
|
import { createRouteRef, createApiRef, createPlugin, createApiFactory, discoveryApiRef, fetchApiRef, createRoutableExtension, useApi, useRouteRef } from '@backstage/core-plugin-api';
|
|
2
2
|
import { ResponseError } from '@backstage/errors';
|
|
3
3
|
import useAsyncRetry from 'react-use/lib/useAsyncRetry';
|
|
4
|
-
import React, { useState, useEffect, useCallback } from 'react';
|
|
5
|
-
import { SidebarItem } from '@backstage/core-components';
|
|
4
|
+
import React, { useState, useEffect, useCallback, useMemo } from 'react';
|
|
5
|
+
import { SidebarItem, Link, Table } from '@backstage/core-components';
|
|
6
6
|
import NotificationsIcon from '@material-ui/icons/Notifications';
|
|
7
7
|
import { useSignal } from '@backstage/plugin-signals-react';
|
|
8
|
-
import
|
|
9
|
-
import {
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import Bookmark from '@material-ui/icons/Bookmark';
|
|
13
|
-
import Inbox from '@material-ui/icons/Inbox';
|
|
14
|
-
import CloseIcon from '@material-ui/icons/Close';
|
|
8
|
+
import throttle from 'lodash/throttle';
|
|
9
|
+
import { Box, Typography, Tooltip, IconButton } from '@material-ui/core';
|
|
10
|
+
import MarkAsUnreadIcon from '@material-ui/icons/Markunread';
|
|
11
|
+
import MarkAsReadIcon from '@material-ui/icons/CheckCircle';
|
|
15
12
|
import RelativeTime from 'react-relative-time';
|
|
16
|
-
import ArrowForwardIcon from '@material-ui/icons/ArrowForward';
|
|
17
13
|
|
|
18
14
|
const rootRouteRef = createRouteRef({
|
|
19
15
|
id: "notifications"
|
|
@@ -38,9 +34,6 @@ class NotificationsClient {
|
|
|
38
34
|
}
|
|
39
35
|
async getNotifications(options) {
|
|
40
36
|
const queryString = new URLSearchParams();
|
|
41
|
-
if (options == null ? void 0 : options.type) {
|
|
42
|
-
queryString.append("type", options.type);
|
|
43
|
-
}
|
|
44
37
|
if ((options == null ? void 0 : options.limit) !== void 0) {
|
|
45
38
|
queryString.append("limit", options.limit.toString(10));
|
|
46
39
|
}
|
|
@@ -50,9 +43,18 @@ class NotificationsClient {
|
|
|
50
43
|
if (options == null ? void 0 : options.search) {
|
|
51
44
|
queryString.append("search", options.search);
|
|
52
45
|
}
|
|
46
|
+
if ((options == null ? void 0 : options.read) !== void 0) {
|
|
47
|
+
queryString.append("read", options.read ? "true" : "false");
|
|
48
|
+
}
|
|
49
|
+
if ((options == null ? void 0 : options.createdAfter) !== void 0) {
|
|
50
|
+
queryString.append("created_after", options.createdAfter.toISOString());
|
|
51
|
+
}
|
|
53
52
|
const urlSegment = `?${queryString}`;
|
|
54
53
|
return await this.request(urlSegment);
|
|
55
54
|
}
|
|
55
|
+
async getNotification(id) {
|
|
56
|
+
return await this.request(`${id}`);
|
|
57
|
+
}
|
|
56
58
|
async getStatus() {
|
|
57
59
|
return await this.request("status");
|
|
58
60
|
}
|
|
@@ -90,7 +92,7 @@ const notificationsPlugin = createPlugin({
|
|
|
90
92
|
const NotificationsPage = notificationsPlugin.provide(
|
|
91
93
|
createRoutableExtension({
|
|
92
94
|
name: "NotificationsPage",
|
|
93
|
-
component: () => import('./esm/index-
|
|
95
|
+
component: () => import('./esm/index-3798ac09.esm.js').then((m) => m.NotificationsPage),
|
|
94
96
|
mountPoint: rootRouteRef
|
|
95
97
|
})
|
|
96
98
|
);
|
|
@@ -126,6 +128,13 @@ function useWebNotifications() {
|
|
|
126
128
|
const notification = new Notification(options.title, {
|
|
127
129
|
body: options.description
|
|
128
130
|
});
|
|
131
|
+
notification.onclick = (event) => {
|
|
132
|
+
event.preventDefault();
|
|
133
|
+
notification.close();
|
|
134
|
+
if (options.link) {
|
|
135
|
+
window.open(options.link, "_blank");
|
|
136
|
+
}
|
|
137
|
+
};
|
|
129
138
|
return notification;
|
|
130
139
|
},
|
|
131
140
|
[webNotificationPermission]
|
|
@@ -174,6 +183,7 @@ const NotificationsSidebarItem = (props) => {
|
|
|
174
183
|
const { loading, error, value, retry } = useNotificationsApi(
|
|
175
184
|
(api) => api.getStatus()
|
|
176
185
|
);
|
|
186
|
+
const notificationsApi = useApi(notificationsApiRef);
|
|
177
187
|
const [unreadCount, setUnreadCount] = React.useState(0);
|
|
178
188
|
const notificationsRoute = useRouteRef(rootRouteRef);
|
|
179
189
|
const { lastSignal } = useSignal("notifications");
|
|
@@ -188,30 +198,31 @@ const NotificationsSidebarItem = (props) => {
|
|
|
188
198
|
}, [refresh, retry]);
|
|
189
199
|
useEffect(() => {
|
|
190
200
|
const handleWebNotification = (signal) => {
|
|
191
|
-
if (!webNotificationsEnabled ||
|
|
201
|
+
if (!webNotificationsEnabled || signal.action !== "new_notification") {
|
|
192
202
|
return;
|
|
193
203
|
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
204
|
+
notificationsApi.getNotification(signal.notification_id).then((notification) => {
|
|
205
|
+
var _a;
|
|
206
|
+
if (!notification) {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
sendWebNotification({
|
|
210
|
+
title: notification.payload.title,
|
|
211
|
+
description: (_a = notification.payload.description) != null ? _a : "",
|
|
212
|
+
link: notification.payload.link
|
|
213
|
+
});
|
|
201
214
|
});
|
|
202
|
-
if (notification) {
|
|
203
|
-
notification.onclick = (event) => {
|
|
204
|
-
event.preventDefault();
|
|
205
|
-
notification.close();
|
|
206
|
-
window.open(notificationData.link, "_blank");
|
|
207
|
-
};
|
|
208
|
-
}
|
|
209
215
|
};
|
|
210
216
|
if (lastSignal && lastSignal.action) {
|
|
211
217
|
handleWebNotification(lastSignal);
|
|
212
218
|
setRefresh(true);
|
|
213
219
|
}
|
|
214
|
-
}, [
|
|
220
|
+
}, [
|
|
221
|
+
lastSignal,
|
|
222
|
+
sendWebNotification,
|
|
223
|
+
webNotificationsEnabled,
|
|
224
|
+
notificationsApi
|
|
225
|
+
]);
|
|
215
226
|
useEffect(() => {
|
|
216
227
|
if (!loading && !error && value) {
|
|
217
228
|
setUnreadCount(value.unread);
|
|
@@ -231,204 +242,94 @@ const NotificationsSidebarItem = (props) => {
|
|
|
231
242
|
);
|
|
232
243
|
};
|
|
233
244
|
|
|
234
|
-
const
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
},
|
|
249
|
-
"& .showOnHover": {
|
|
250
|
-
display: "none"
|
|
245
|
+
const ThrottleDelayMs = 1e3;
|
|
246
|
+
const NotificationsTable = ({
|
|
247
|
+
isLoading,
|
|
248
|
+
notifications = [],
|
|
249
|
+
onUpdate,
|
|
250
|
+
setContainsText
|
|
251
|
+
}) => {
|
|
252
|
+
const notificationsApi = useApi(notificationsApiRef);
|
|
253
|
+
const onSwitchReadStatus = React.useCallback(
|
|
254
|
+
(notification) => {
|
|
255
|
+
notificationsApi.updateNotifications({
|
|
256
|
+
ids: [notification.id],
|
|
257
|
+
read: !notification.read
|
|
258
|
+
}).then(() => onUpdate());
|
|
251
259
|
},
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
260
|
+
[notificationsApi, onUpdate]
|
|
261
|
+
);
|
|
262
|
+
const throttledContainsTextHandler = useMemo(
|
|
263
|
+
() => throttle(setContainsText, ThrottleDelayMs),
|
|
264
|
+
[setContainsText]
|
|
265
|
+
);
|
|
266
|
+
const compactColumns = React.useMemo(
|
|
267
|
+
() => [
|
|
268
|
+
{
|
|
269
|
+
customFilterAndSearch: () => true,
|
|
270
|
+
render: (notification) => {
|
|
271
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Typography, { variant: "subtitle2" }, notification.payload.link ? /* @__PURE__ */ React.createElement(Link, { to: notification.payload.link }, notification.payload.title) : notification.payload.title), /* @__PURE__ */ React.createElement(Typography, { variant: "body2" }, notification.payload.description), /* @__PURE__ */ React.createElement(Typography, { variant: "caption" }, notification.origin && /* @__PURE__ */ React.createElement(React.Fragment, null, notification.origin, "\xA0\u2022\xA0"), notification.payload.topic && /* @__PURE__ */ React.createElement(React.Fragment, null, notification.payload.topic, "\xA0\u2022\xA0"), notification.created && /* @__PURE__ */ React.createElement(RelativeTime, { value: notification.created }))));
|
|
272
|
+
}
|
|
255
273
|
},
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
Checkbox,
|
|
294
|
-
{
|
|
295
|
-
size: "small",
|
|
296
|
-
style: { paddingLeft: 0 },
|
|
297
|
-
checked: isAllSelected(),
|
|
298
|
-
onClick: () => {
|
|
299
|
-
if (isAllSelected()) {
|
|
300
|
-
setSelected([]);
|
|
301
|
-
} else {
|
|
302
|
-
setSelected(
|
|
303
|
-
notifications ? notifications.map((n) => n.id) : []
|
|
304
|
-
);
|
|
274
|
+
// {
|
|
275
|
+
// // TODO: additional action links
|
|
276
|
+
// width: '25%',
|
|
277
|
+
// render: (notification: Notification) => {
|
|
278
|
+
// return (
|
|
279
|
+
// notification.payload.link && (
|
|
280
|
+
// <Grid container>
|
|
281
|
+
// {/* TODO: render additionalLinks of different titles */}
|
|
282
|
+
// <Grid item>
|
|
283
|
+
// <Link
|
|
284
|
+
// key={notification.payload.link}
|
|
285
|
+
// to={notification.payload.link}
|
|
286
|
+
// >
|
|
287
|
+
// More info
|
|
288
|
+
// </Link>
|
|
289
|
+
// </Grid>
|
|
290
|
+
// </Grid>
|
|
291
|
+
// )
|
|
292
|
+
// );
|
|
293
|
+
// },
|
|
294
|
+
// },
|
|
295
|
+
{
|
|
296
|
+
// TODO: action for saving notifications
|
|
297
|
+
// actions
|
|
298
|
+
width: "1rem",
|
|
299
|
+
render: (notification) => {
|
|
300
|
+
const markAsReadText = !!notification.read ? "Return among unread" : "Mark as read";
|
|
301
|
+
const IconComponent = !!notification.read ? MarkAsUnreadIcon : MarkAsReadIcon;
|
|
302
|
+
return /* @__PURE__ */ React.createElement(Tooltip, { title: markAsReadText }, /* @__PURE__ */ React.createElement(
|
|
303
|
+
IconButton,
|
|
304
|
+
{
|
|
305
|
+
onClick: () => {
|
|
306
|
+
onSwitchReadStatus(notification);
|
|
307
|
+
}
|
|
308
|
+
},
|
|
309
|
+
/* @__PURE__ */ React.createElement(IconComponent, { "aria-label": markAsReadText })
|
|
310
|
+
));
|
|
305
311
|
}
|
|
306
312
|
}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
onClick: () => {
|
|
313
|
-
notificationsApi.updateNotifications({ ids: selected, done: false }).then(() => props.onUpdate());
|
|
314
|
-
setSelected([]);
|
|
315
|
-
}
|
|
316
|
-
},
|
|
317
|
-
"Move to inbox"
|
|
318
|
-
), type === "undone" && selected.length > 0 && /* @__PURE__ */ React.createElement(
|
|
319
|
-
Button,
|
|
313
|
+
],
|
|
314
|
+
[onSwitchReadStatus]
|
|
315
|
+
);
|
|
316
|
+
return /* @__PURE__ */ React.createElement(
|
|
317
|
+
Table,
|
|
320
318
|
{
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
return /* @__PURE__ */ React.createElement(
|
|
330
|
-
TableRow,
|
|
331
|
-
{
|
|
332
|
-
key: notification.id,
|
|
333
|
-
className: `${styles.notificationRow} ${!notification.read ? "unread" : ""}`,
|
|
334
|
-
hover: true
|
|
319
|
+
isLoading,
|
|
320
|
+
options: {
|
|
321
|
+
search: true,
|
|
322
|
+
// TODO: add pagination
|
|
323
|
+
// paging: true,
|
|
324
|
+
// pageSize,
|
|
325
|
+
header: false,
|
|
326
|
+
sorting: false
|
|
335
327
|
},
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
},
|
|
342
|
-
/* @__PURE__ */ React.createElement(
|
|
343
|
-
Checkbox,
|
|
344
|
-
{
|
|
345
|
-
className: styles.checkBox,
|
|
346
|
-
size: "small",
|
|
347
|
-
checked: isChecked(notification.id),
|
|
348
|
-
onClick: () => onCheckBoxClick(notification.id)
|
|
349
|
-
}
|
|
350
|
-
)
|
|
351
|
-
),
|
|
352
|
-
/* @__PURE__ */ React.createElement(
|
|
353
|
-
TableCell,
|
|
354
|
-
{
|
|
355
|
-
onClick: () => notificationsApi.updateNotifications({ ids: [notification.id], read: true }).then(() => navigate(notification.payload.link)),
|
|
356
|
-
style: { paddingLeft: 0 }
|
|
357
|
-
},
|
|
358
|
-
/* @__PURE__ */ React.createElement(Typography, { variant: "subtitle2" }, notification.payload.title),
|
|
359
|
-
/* @__PURE__ */ React.createElement(Typography, { variant: "body2" }, notification.payload.description)
|
|
360
|
-
),
|
|
361
|
-
/* @__PURE__ */ React.createElement(TableCell, { style: { textAlign: "right" } }, /* @__PURE__ */ React.createElement(Box, { className: "hideOnHover" }, /* @__PURE__ */ React.createElement(RelativeTime, { value: notification.created })), /* @__PURE__ */ React.createElement(Box, { className: "showOnHover" }, /* @__PURE__ */ React.createElement(Tooltip, { title: notification.payload.link }, /* @__PURE__ */ React.createElement(
|
|
362
|
-
IconButton,
|
|
363
|
-
{
|
|
364
|
-
className: styles.actionButton,
|
|
365
|
-
onClick: () => notificationsApi.updateNotifications({
|
|
366
|
-
ids: [notification.id],
|
|
367
|
-
read: true
|
|
368
|
-
}).then(() => navigate(notification.payload.link))
|
|
369
|
-
},
|
|
370
|
-
/* @__PURE__ */ React.createElement(ArrowForwardIcon, null)
|
|
371
|
-
)), /* @__PURE__ */ React.createElement(
|
|
372
|
-
Tooltip,
|
|
373
|
-
{
|
|
374
|
-
title: notification.read ? "Move to inbox" : "Mark as done"
|
|
375
|
-
},
|
|
376
|
-
/* @__PURE__ */ React.createElement(
|
|
377
|
-
IconButton,
|
|
378
|
-
{
|
|
379
|
-
className: styles.actionButton,
|
|
380
|
-
onClick: () => {
|
|
381
|
-
if (notification.read) {
|
|
382
|
-
notificationsApi.updateNotifications({
|
|
383
|
-
ids: [notification.id],
|
|
384
|
-
done: false
|
|
385
|
-
}).then(() => {
|
|
386
|
-
props.onUpdate();
|
|
387
|
-
});
|
|
388
|
-
} else {
|
|
389
|
-
notificationsApi.updateNotifications({
|
|
390
|
-
ids: [notification.id],
|
|
391
|
-
done: true
|
|
392
|
-
}).then(() => {
|
|
393
|
-
props.onUpdate();
|
|
394
|
-
});
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
},
|
|
398
|
-
notification.read ? /* @__PURE__ */ React.createElement(Inbox, { fontSize: "small" }) : /* @__PURE__ */ React.createElement(Check, { fontSize: "small" })
|
|
399
|
-
)
|
|
400
|
-
), /* @__PURE__ */ React.createElement(
|
|
401
|
-
Tooltip,
|
|
402
|
-
{
|
|
403
|
-
title: notification.saved ? "Remove from saved" : "Save"
|
|
404
|
-
},
|
|
405
|
-
/* @__PURE__ */ React.createElement(
|
|
406
|
-
IconButton,
|
|
407
|
-
{
|
|
408
|
-
className: styles.actionButton,
|
|
409
|
-
onClick: () => {
|
|
410
|
-
if (notification.saved) {
|
|
411
|
-
notificationsApi.updateNotifications({
|
|
412
|
-
ids: [notification.id],
|
|
413
|
-
saved: false
|
|
414
|
-
}).then(() => {
|
|
415
|
-
props.onUpdate();
|
|
416
|
-
});
|
|
417
|
-
} else {
|
|
418
|
-
notificationsApi.updateNotifications({
|
|
419
|
-
ids: [notification.id],
|
|
420
|
-
saved: true
|
|
421
|
-
}).then(() => {
|
|
422
|
-
props.onUpdate();
|
|
423
|
-
});
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
},
|
|
427
|
-
notification.saved ? /* @__PURE__ */ React.createElement(CloseIcon, { fontSize: "small" }) : /* @__PURE__ */ React.createElement(Bookmark, { fontSize: "small" })
|
|
428
|
-
)
|
|
429
|
-
)))
|
|
430
|
-
);
|
|
431
|
-
})));
|
|
328
|
+
onSearchChange: throttledContainsTextHandler,
|
|
329
|
+
data: notifications,
|
|
330
|
+
columns: compactColumns
|
|
331
|
+
}
|
|
332
|
+
);
|
|
432
333
|
};
|
|
433
334
|
|
|
434
335
|
export { NotificationsClient, NotificationsPage, NotificationsSidebarItem, NotificationsTable, notificationsApiRef, notificationsPlugin, useNotificationsApi, useTitleCounter, useWebNotifications };
|
package/dist/index.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":["../src/routes.ts","../src/api/NotificationsApi.ts","../src/api/NotificationsClient.ts","../src/plugin.ts","../src/hooks/useNotificationsApi.ts","../src/hooks/useWebNotifications.ts","../src/hooks/useTitleCounter.ts","../src/components/NotificationsSideBarItem/NotificationsSideBarItem.tsx","../src/components/NotificationsTable/NotificationsTable.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 { createRouteRef } from '@backstage/core-plugin-api';\n\nexport const rootRouteRef = createRouteRef({\n id: 'notifications',\n});\n","/*\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 { createApiRef } from '@backstage/core-plugin-api';\nimport {\n Notification,\n NotificationStatus,\n NotificationType,\n} from '@backstage/plugin-notifications-common';\n\n/** @public */\nexport const notificationsApiRef = createApiRef<NotificationsApi>({\n id: 'plugin.notifications.service',\n});\n\n/** @public */\nexport type GetNotificationsOptions = {\n type?: NotificationType;\n offset?: number;\n limit?: number;\n search?: string;\n};\n\n/** @public */\nexport type UpdateNotificationsOptions = {\n ids: string[];\n done?: boolean;\n read?: boolean;\n saved?: boolean;\n};\n\n/** @public */\nexport interface NotificationsApi {\n getNotifications(options?: GetNotificationsOptions): Promise<Notification[]>;\n\n getStatus(): Promise<NotificationStatus>;\n\n updateNotifications(\n options: UpdateNotificationsOptions,\n ): Promise<Notification[]>;\n}\n","/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n GetNotificationsOptions,\n NotificationsApi,\n UpdateNotificationsOptions,\n} from './NotificationsApi';\nimport { DiscoveryApi, FetchApi } from '@backstage/core-plugin-api';\nimport { ResponseError } from '@backstage/errors';\nimport {\n Notification,\n NotificationStatus,\n} from '@backstage/plugin-notifications-common';\n\n/** @public */\nexport class NotificationsClient implements NotificationsApi {\n private readonly discoveryApi: DiscoveryApi;\n private readonly fetchApi: FetchApi;\n\n public constructor(options: {\n discoveryApi: DiscoveryApi;\n fetchApi: FetchApi;\n }) {\n this.discoveryApi = options.discoveryApi;\n this.fetchApi = options.fetchApi;\n }\n\n async getNotifications(\n options?: GetNotificationsOptions,\n ): Promise<Notification[]> {\n const queryString = new URLSearchParams();\n if (options?.type) {\n queryString.append('type', options.type);\n }\n if (options?.limit !== undefined) {\n queryString.append('limit', options.limit.toString(10));\n }\n if (options?.offset !== undefined) {\n queryString.append('offset', options.offset.toString(10));\n }\n if (options?.search) {\n queryString.append('search', options.search);\n }\n\n const urlSegment = `?${queryString}`;\n\n return await this.request<Notification[]>(urlSegment);\n }\n\n async getStatus(): Promise<NotificationStatus> {\n return await this.request<NotificationStatus>('status');\n }\n\n async updateNotifications(\n options: UpdateNotificationsOptions,\n ): Promise<Notification[]> {\n return await this.request<Notification[]>('update', {\n method: 'POST',\n body: JSON.stringify(options),\n headers: { 'Content-Type': 'application/json' },\n });\n }\n\n private async request<T>(path: string, init?: any): Promise<T> {\n const baseUrl = `${await this.discoveryApi.getBaseUrl('notifications')}/`;\n const url = new URL(path, baseUrl);\n\n const response = await this.fetchApi.fetch(url.toString(), init);\n\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n return response.json() as Promise<T>;\n }\n}\n","/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n createApiFactory,\n createPlugin,\n createRoutableExtension,\n discoveryApiRef,\n fetchApiRef,\n} from '@backstage/core-plugin-api';\n\nimport { rootRouteRef } from './routes';\nimport { notificationsApiRef } from './api/NotificationsApi';\nimport { NotificationsClient } from './api';\n\n/** @public */\nexport const notificationsPlugin = createPlugin({\n id: 'notifications',\n routes: {\n root: rootRouteRef,\n },\n apis: [\n createApiFactory({\n api: notificationsApiRef,\n deps: { discoveryApi: discoveryApiRef, fetchApi: fetchApiRef },\n factory: ({ discoveryApi, fetchApi }) =>\n new NotificationsClient({ discoveryApi, fetchApi }),\n }),\n ],\n});\n\n/** @public */\nexport const NotificationsPage = notificationsPlugin.provide(\n createRoutableExtension({\n name: 'NotificationsPage',\n component: () =>\n import('./components/NotificationsPage').then(m => m.NotificationsPage),\n mountPoint: rootRouteRef,\n }),\n);\n","/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { NotificationsApi, notificationsApiRef } from '../api';\nimport { useApi } from '@backstage/core-plugin-api';\nimport useAsyncRetry from 'react-use/lib/useAsyncRetry';\n\n/** @public */\nexport function useNotificationsApi<T>(\n f: (api: NotificationsApi) => Promise<T>,\n deps: any[] = [],\n) {\n const notificationsApi = useApi(notificationsApiRef);\n\n return useAsyncRetry(async () => {\n return await f(notificationsApi);\n }, deps);\n}\n","/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useCallback, useEffect, useState } from 'react';\n\n/** @public */\nexport function useWebNotifications() {\n const [webNotificationPermission, setWebNotificationPermission] =\n useState('default');\n const [webNotifications, setWebNotifications] = useState<Notification[]>([]);\n\n useEffect(() => {\n if ('Notification' in window && webNotificationPermission === 'default') {\n window.Notification.requestPermission().then(permission => {\n setWebNotificationPermission(permission);\n });\n }\n }, [webNotificationPermission]);\n\n document.addEventListener('visibilitychange', () => {\n if (document.visibilityState === 'visible') {\n webNotifications.forEach(n => n.close());\n setWebNotifications([]);\n }\n });\n\n const sendWebNotification = useCallback(\n (options: { title: string; description: string }) => {\n if (webNotificationPermission !== 'granted') {\n return null;\n }\n\n const notification = new Notification(options.title, {\n body: options.description,\n });\n return notification;\n },\n [webNotificationPermission],\n );\n\n return { sendWebNotification };\n}\n","/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useCallback, useEffect, useState } from 'react';\n\n/** @public */\nexport function useTitleCounter() {\n const [title, setTitle] = useState(document.title);\n const [count, setCount] = useState(0);\n\n const getPrefix = (value: number) => {\n return value === 0 ? '' : `(${value}) `;\n };\n\n const cleanTitle = (currentTitle: string) => {\n return currentTitle.replace(/^\\(\\d+\\)\\s/, '');\n };\n\n useEffect(() => {\n document.title = title;\n }, [title]);\n\n useEffect(() => {\n const baseTitle = cleanTitle(title);\n setTitle(`${getPrefix(count)}${baseTitle}`);\n return () => {\n document.title = cleanTitle(title);\n };\n }, [title, count]);\n\n const titleElement = document.querySelector('title');\n if (titleElement) {\n new MutationObserver(() => {\n setTitle(document.title);\n }).observe(titleElement, {\n subtree: true,\n characterData: true,\n childList: true,\n });\n }\n\n const setNotificationCount = useCallback(\n (newCount: number) => setCount(newCount),\n [],\n );\n\n return { setNotificationCount };\n}\n","/*\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, { useEffect } from 'react';\nimport { useNotificationsApi } from '../../hooks';\nimport { SidebarItem } from '@backstage/core-components';\nimport NotificationsIcon from '@material-ui/icons/Notifications';\nimport { useRouteRef } from '@backstage/core-plugin-api';\nimport { rootRouteRef } from '../../routes';\nimport { useSignal } from '@backstage/plugin-signals-react';\nimport { useWebNotifications } from '../../hooks/useWebNotifications';\nimport { useTitleCounter } from '../../hooks/useTitleCounter';\nimport { JsonObject } from '@backstage/types';\n\n/** @public */\nexport const NotificationsSidebarItem = (props?: {\n webNotificationsEnabled?: boolean;\n titleCounterEnabled?: boolean;\n}) => {\n const { webNotificationsEnabled = false, titleCounterEnabled = true } =\n props ?? { webNotificationsEnabled: false, titleCounterEnabled: true };\n\n const { loading, error, value, retry } = useNotificationsApi(api =>\n api.getStatus(),\n );\n const [unreadCount, setUnreadCount] = React.useState(0);\n const notificationsRoute = useRouteRef(rootRouteRef);\n // TODO: Add signal type support to `useSignal` to make it a bit easier to use\n // TODO: Do we want to add long polling in case signals are not available\n const { lastSignal } = useSignal('notifications');\n const { sendWebNotification } = useWebNotifications();\n const [refresh, setRefresh] = React.useState(false);\n const { setNotificationCount } = useTitleCounter();\n\n useEffect(() => {\n if (refresh) {\n retry();\n setRefresh(false);\n }\n }, [refresh, retry]);\n\n useEffect(() => {\n const handleWebNotification = (signal: JsonObject) => {\n if (!webNotificationsEnabled || !('notification' in signal)) {\n return;\n }\n\n const notificationData = signal.notification as JsonObject;\n\n if (\n !notificationData ||\n !('title' in notificationData) ||\n !('description' in notificationData) ||\n !('title' in notificationData)\n ) {\n return;\n }\n const notification = sendWebNotification({\n title: notificationData.title as string,\n description: notificationData.description as string,\n });\n if (notification) {\n notification.onclick = event => {\n event.preventDefault();\n notification.close();\n window.open(notificationData.link as string, '_blank');\n };\n }\n };\n\n if (lastSignal && lastSignal.action) {\n handleWebNotification(lastSignal);\n setRefresh(true);\n }\n }, [lastSignal, sendWebNotification, webNotificationsEnabled]);\n\n useEffect(() => {\n if (!loading && !error && value) {\n setUnreadCount(value.unread);\n if (titleCounterEnabled) {\n setNotificationCount(value.unread);\n }\n }\n }, [loading, error, value, titleCounterEnabled, setNotificationCount]);\n\n // TODO: Figure out if the count can be added to hasNotifications\n return (\n <SidebarItem\n icon={NotificationsIcon}\n to={notificationsRoute()}\n text=\"Notifications\"\n hasNotifications={!error && !!unreadCount}\n />\n );\n};\n","/*\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, { useEffect, useState } from 'react';\nimport {\n Box,\n Button,\n IconButton,\n makeStyles,\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableRow,\n Tooltip,\n Typography,\n} from '@material-ui/core';\nimport {\n Notification,\n NotificationType,\n} from '@backstage/plugin-notifications-common';\nimport { useNavigate } from 'react-router-dom';\nimport Checkbox from '@material-ui/core/Checkbox';\nimport Check from '@material-ui/icons/Check';\nimport Bookmark from '@material-ui/icons/Bookmark';\nimport { notificationsApiRef } from '../../api';\nimport { useApi } from '@backstage/core-plugin-api';\nimport Inbox from '@material-ui/icons/Inbox';\nimport CloseIcon from '@material-ui/icons/Close';\n// @ts-ignore\nimport RelativeTime from 'react-relative-time';\nimport ArrowForwardIcon from '@material-ui/icons/ArrowForward';\n\nconst useStyles = makeStyles(theme => ({\n table: {\n border: `1px solid ${theme.palette.divider}`,\n },\n header: {\n borderBottom: `1px solid ${theme.palette.divider}`,\n },\n\n notificationRow: {\n cursor: 'pointer',\n '&.unread': {\n border: '1px solid rgba(255, 255, 255, .3)',\n },\n '& .hideOnHover': {\n display: 'initial',\n },\n '& .showOnHover': {\n display: 'none',\n },\n '&:hover': {\n '& .hideOnHover': {\n display: 'none',\n },\n '& .showOnHover': {\n display: 'initial',\n },\n },\n },\n actionButton: {\n padding: '9px',\n },\n checkBox: {\n padding: '0 10px 10px 0',\n },\n}));\n\n/** @public */\nexport const NotificationsTable = (props: {\n onUpdate: () => void;\n type: NotificationType;\n notifications?: Notification[];\n}) => {\n const { notifications, type } = props;\n const navigate = useNavigate();\n const styles = useStyles();\n const [selected, setSelected] = useState<string[]>([]);\n const notificationsApi = useApi(notificationsApiRef);\n\n const onCheckBoxClick = (id: string) => {\n const index = selected.indexOf(id);\n if (index !== -1) {\n setSelected(selected.filter(s => s !== id));\n } else {\n setSelected([...selected, id]);\n }\n };\n\n useEffect(() => {\n setSelected([]);\n }, [type]);\n\n const isChecked = (id: string) => {\n return selected.indexOf(id) !== -1;\n };\n\n const isAllSelected = () => {\n return (\n selected.length === notifications?.length && notifications.length > 0\n );\n };\n\n return (\n <Table size=\"small\" className={styles.table}>\n <TableHead>\n <TableRow>\n <TableCell colSpan={3}>\n {type !== 'saved' && !notifications?.length && 'No notifications'}\n {type !== 'saved' && !!notifications?.length && (\n <Checkbox\n size=\"small\"\n style={{ paddingLeft: 0 }}\n checked={isAllSelected()}\n onClick={() => {\n if (isAllSelected()) {\n setSelected([]);\n } else {\n setSelected(\n notifications ? notifications.map(n => n.id) : [],\n );\n }\n }}\n />\n )}\n {type === 'saved' &&\n `${notifications?.length ?? 0} saved notifications`}\n {selected.length === 0 &&\n !!notifications?.length &&\n type !== 'saved' &&\n 'Select all'}\n {selected.length > 0 && `${selected.length} selected`}\n {type === 'done' && selected.length > 0 && (\n <Button\n startIcon={<Inbox fontSize=\"small\" />}\n onClick={() => {\n notificationsApi\n .updateNotifications({ ids: selected, done: false })\n .then(() => props.onUpdate());\n setSelected([]);\n }}\n >\n Move to inbox\n </Button>\n )}\n\n {type === 'undone' && selected.length > 0 && (\n <Button\n startIcon={<Check fontSize=\"small\" />}\n onClick={() => {\n notificationsApi\n .updateNotifications({ ids: selected, done: true })\n .then(() => props.onUpdate());\n setSelected([]);\n }}\n >\n Mark as done\n </Button>\n )}\n </TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {props.notifications?.map(notification => {\n return (\n <TableRow\n key={notification.id}\n className={`${styles.notificationRow} ${\n !notification.read ? 'unread' : ''\n }`}\n hover\n >\n <TableCell\n width=\"60px\"\n style={{ verticalAlign: 'center', paddingRight: '0px' }}\n >\n <Checkbox\n className={styles.checkBox}\n size=\"small\"\n checked={isChecked(notification.id)}\n onClick={() => onCheckBoxClick(notification.id)}\n />\n </TableCell>\n <TableCell\n onClick={() =>\n notificationsApi\n .updateNotifications({ ids: [notification.id], read: true })\n .then(() => navigate(notification.payload.link))\n }\n style={{ paddingLeft: 0 }}\n >\n <Typography variant=\"subtitle2\">\n {notification.payload.title}\n </Typography>\n <Typography variant=\"body2\">\n {notification.payload.description}\n </Typography>\n </TableCell>\n <TableCell style={{ textAlign: 'right' }}>\n <Box className=\"hideOnHover\">\n <RelativeTime value={notification.created} />\n </Box>\n <Box className=\"showOnHover\">\n <Tooltip title={notification.payload.link}>\n <IconButton\n className={styles.actionButton}\n onClick={() =>\n notificationsApi\n .updateNotifications({\n ids: [notification.id],\n read: true,\n })\n .then(() => navigate(notification.payload.link))\n }\n >\n <ArrowForwardIcon />\n </IconButton>\n </Tooltip>\n <Tooltip\n title={notification.read ? 'Move to inbox' : 'Mark as done'}\n >\n <IconButton\n className={styles.actionButton}\n onClick={() => {\n if (notification.read) {\n notificationsApi\n .updateNotifications({\n ids: [notification.id],\n done: false,\n })\n .then(() => {\n props.onUpdate();\n });\n } else {\n notificationsApi\n .updateNotifications({\n ids: [notification.id],\n done: true,\n })\n .then(() => {\n props.onUpdate();\n });\n }\n }}\n >\n {notification.read ? (\n <Inbox fontSize=\"small\" />\n ) : (\n <Check fontSize=\"small\" />\n )}\n </IconButton>\n </Tooltip>\n <Tooltip\n title={notification.saved ? 'Remove from saved' : 'Save'}\n >\n <IconButton\n className={styles.actionButton}\n onClick={() => {\n if (notification.saved) {\n notificationsApi\n .updateNotifications({\n ids: [notification.id],\n saved: false,\n })\n .then(() => {\n props.onUpdate();\n });\n } else {\n notificationsApi\n .updateNotifications({\n ids: [notification.id],\n saved: true,\n })\n .then(() => {\n props.onUpdate();\n });\n }\n }}\n >\n {notification.saved ? (\n <CloseIcon fontSize=\"small\" />\n ) : (\n <Bookmark fontSize=\"small\" />\n )}\n </IconButton>\n </Tooltip>\n </Box>\n </TableCell>\n </TableRow>\n );\n })}\n </TableBody>\n </Table>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../src/routes.ts","../src/api/NotificationsApi.ts","../src/api/NotificationsClient.ts","../src/plugin.ts","../src/hooks/useNotificationsApi.ts","../src/hooks/useWebNotifications.ts","../src/hooks/useTitleCounter.ts","../src/components/NotificationsSideBarItem/NotificationsSideBarItem.tsx","../src/components/NotificationsTable/NotificationsTable.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 { createRouteRef } from '@backstage/core-plugin-api';\n\nexport const rootRouteRef = createRouteRef({\n id: 'notifications',\n});\n","/*\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 { createApiRef } from '@backstage/core-plugin-api';\nimport {\n Notification,\n NotificationStatus,\n} from '@backstage/plugin-notifications-common';\n\n/** @public */\nexport const notificationsApiRef = createApiRef<NotificationsApi>({\n id: 'plugin.notifications.service',\n});\n\n/** @public */\nexport type GetNotificationsOptions = {\n offset?: number;\n limit?: number;\n search?: string;\n read?: boolean;\n createdAfter?: Date;\n};\n\n/** @public */\nexport type UpdateNotificationsOptions = {\n ids: string[];\n read?: boolean;\n saved?: boolean;\n};\n\n/** @public */\nexport interface NotificationsApi {\n getNotifications(options?: GetNotificationsOptions): Promise<Notification[]>;\n\n getNotification(id: string): Promise<Notification>;\n\n getStatus(): Promise<NotificationStatus>;\n\n updateNotifications(\n options: UpdateNotificationsOptions,\n ): Promise<Notification[]>;\n}\n","/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n GetNotificationsOptions,\n NotificationsApi,\n UpdateNotificationsOptions,\n} from './NotificationsApi';\nimport { DiscoveryApi, FetchApi } from '@backstage/core-plugin-api';\nimport { ResponseError } from '@backstage/errors';\nimport {\n Notification,\n NotificationStatus,\n} from '@backstage/plugin-notifications-common';\n\n/** @public */\nexport class NotificationsClient implements NotificationsApi {\n private readonly discoveryApi: DiscoveryApi;\n private readonly fetchApi: FetchApi;\n\n public constructor(options: {\n discoveryApi: DiscoveryApi;\n fetchApi: FetchApi;\n }) {\n this.discoveryApi = options.discoveryApi;\n this.fetchApi = options.fetchApi;\n }\n\n async getNotifications(\n options?: GetNotificationsOptions,\n ): Promise<Notification[]> {\n const queryString = new URLSearchParams();\n if (options?.limit !== undefined) {\n queryString.append('limit', options.limit.toString(10));\n }\n if (options?.offset !== undefined) {\n queryString.append('offset', options.offset.toString(10));\n }\n if (options?.search) {\n queryString.append('search', options.search);\n }\n if (options?.read !== undefined) {\n queryString.append('read', options.read ? 'true' : 'false');\n }\n if (options?.createdAfter !== undefined) {\n queryString.append('created_after', options.createdAfter.toISOString());\n }\n const urlSegment = `?${queryString}`;\n\n return await this.request<Notification[]>(urlSegment);\n }\n\n async getNotification(id: string): Promise<Notification> {\n return await this.request<Notification>(`${id}`);\n }\n\n async getStatus(): Promise<NotificationStatus> {\n return await this.request<NotificationStatus>('status');\n }\n\n async updateNotifications(\n options: UpdateNotificationsOptions,\n ): Promise<Notification[]> {\n return await this.request<Notification[]>('update', {\n method: 'POST',\n body: JSON.stringify(options),\n headers: { 'Content-Type': 'application/json' },\n });\n }\n\n private async request<T>(path: string, init?: any): Promise<T> {\n const baseUrl = `${await this.discoveryApi.getBaseUrl('notifications')}/`;\n const url = new URL(path, baseUrl);\n\n const response = await this.fetchApi.fetch(url.toString(), init);\n\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n return response.json() as Promise<T>;\n }\n}\n","/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n createApiFactory,\n createPlugin,\n createRoutableExtension,\n discoveryApiRef,\n fetchApiRef,\n} from '@backstage/core-plugin-api';\n\nimport { rootRouteRef } from './routes';\nimport { notificationsApiRef } from './api/NotificationsApi';\nimport { NotificationsClient } from './api';\n\n/** @public */\nexport const notificationsPlugin = createPlugin({\n id: 'notifications',\n routes: {\n root: rootRouteRef,\n },\n apis: [\n createApiFactory({\n api: notificationsApiRef,\n deps: { discoveryApi: discoveryApiRef, fetchApi: fetchApiRef },\n factory: ({ discoveryApi, fetchApi }) =>\n new NotificationsClient({ discoveryApi, fetchApi }),\n }),\n ],\n});\n\n/** @public */\nexport const NotificationsPage = notificationsPlugin.provide(\n createRoutableExtension({\n name: 'NotificationsPage',\n component: () =>\n import('./components/NotificationsPage').then(m => m.NotificationsPage),\n mountPoint: rootRouteRef,\n }),\n);\n","/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { NotificationsApi, notificationsApiRef } from '../api';\nimport { useApi } from '@backstage/core-plugin-api';\nimport useAsyncRetry from 'react-use/lib/useAsyncRetry';\n\n/** @public */\nexport function useNotificationsApi<T>(\n f: (api: NotificationsApi) => Promise<T>,\n deps: any[] = [],\n) {\n const notificationsApi = useApi(notificationsApiRef);\n\n return useAsyncRetry(async () => {\n return await f(notificationsApi);\n }, deps);\n}\n","/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useCallback, useEffect, useState } from 'react';\n\n/** @public */\nexport function useWebNotifications() {\n const [webNotificationPermission, setWebNotificationPermission] =\n useState('default');\n const [webNotifications, setWebNotifications] = useState<Notification[]>([]);\n\n useEffect(() => {\n if ('Notification' in window && webNotificationPermission === 'default') {\n window.Notification.requestPermission().then(permission => {\n setWebNotificationPermission(permission);\n });\n }\n }, [webNotificationPermission]);\n\n document.addEventListener('visibilitychange', () => {\n if (document.visibilityState === 'visible') {\n webNotifications.forEach(n => n.close());\n setWebNotifications([]);\n }\n });\n\n const sendWebNotification = useCallback(\n (options: { title: string; description: string; link?: string }) => {\n if (webNotificationPermission !== 'granted') {\n return null;\n }\n\n const notification = new Notification(options.title, {\n body: options.description,\n });\n\n notification.onclick = event => {\n event.preventDefault();\n notification.close();\n if (options.link) {\n window.open(options.link, '_blank');\n }\n };\n\n return notification;\n },\n [webNotificationPermission],\n );\n\n return { sendWebNotification };\n}\n","/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useCallback, useEffect, useState } from 'react';\n\n/** @public */\nexport function useTitleCounter() {\n const [title, setTitle] = useState(document.title);\n const [count, setCount] = useState(0);\n\n const getPrefix = (value: number) => {\n return value === 0 ? '' : `(${value}) `;\n };\n\n const cleanTitle = (currentTitle: string) => {\n return currentTitle.replace(/^\\(\\d+\\)\\s/, '');\n };\n\n useEffect(() => {\n document.title = title;\n }, [title]);\n\n useEffect(() => {\n const baseTitle = cleanTitle(title);\n setTitle(`${getPrefix(count)}${baseTitle}`);\n return () => {\n document.title = cleanTitle(title);\n };\n }, [title, count]);\n\n const titleElement = document.querySelector('title');\n if (titleElement) {\n new MutationObserver(() => {\n setTitle(document.title);\n }).observe(titleElement, {\n subtree: true,\n characterData: true,\n childList: true,\n });\n }\n\n const setNotificationCount = useCallback(\n (newCount: number) => setCount(newCount),\n [],\n );\n\n return { setNotificationCount };\n}\n","/*\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, { useEffect } from 'react';\nimport { useNotificationsApi } from '../../hooks';\nimport { SidebarItem } from '@backstage/core-components';\nimport NotificationsIcon from '@material-ui/icons/Notifications';\nimport { useApi, useRouteRef } from '@backstage/core-plugin-api';\nimport { rootRouteRef } from '../../routes';\nimport { useSignal } from '@backstage/plugin-signals-react';\nimport { NotificationSignal } from '@backstage/plugin-notifications-common';\nimport { useWebNotifications } from '../../hooks/useWebNotifications';\nimport { useTitleCounter } from '../../hooks/useTitleCounter';\nimport { notificationsApiRef } from '../../api';\n\n/** @public */\nexport const NotificationsSidebarItem = (props?: {\n webNotificationsEnabled?: boolean;\n titleCounterEnabled?: boolean;\n}) => {\n const { webNotificationsEnabled = false, titleCounterEnabled = true } =\n props ?? { webNotificationsEnabled: false, titleCounterEnabled: true };\n\n const { loading, error, value, retry } = useNotificationsApi(api =>\n api.getStatus(),\n );\n const notificationsApi = useApi(notificationsApiRef);\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 } = useWebNotifications();\n const [refresh, setRefresh] = React.useState(false);\n const { setNotificationCount } = useTitleCounter();\n\n useEffect(() => {\n if (refresh) {\n retry();\n setRefresh(false);\n }\n }, [refresh, retry]);\n\n useEffect(() => {\n const handleWebNotification = (signal: NotificationSignal) => {\n if (!webNotificationsEnabled || signal.action !== 'new_notification') {\n return;\n }\n\n notificationsApi\n .getNotification(signal.notification_id)\n .then(notification => {\n if (!notification) {\n return;\n }\n sendWebNotification({\n title: notification.payload.title,\n description: notification.payload.description ?? '',\n link: notification.payload.link,\n });\n });\n };\n\n if (lastSignal && lastSignal.action) {\n handleWebNotification(lastSignal);\n setRefresh(true);\n }\n }, [\n lastSignal,\n sendWebNotification,\n webNotificationsEnabled,\n notificationsApi,\n ]);\n\n useEffect(() => {\n if (!loading && !error && value) {\n setUnreadCount(value.unread);\n if (titleCounterEnabled) {\n setNotificationCount(value.unread);\n }\n }\n }, [loading, error, value, titleCounterEnabled, setNotificationCount]);\n\n // TODO: Figure out if the count can be added to hasNotifications\n return (\n <SidebarItem\n icon={NotificationsIcon}\n to={notificationsRoute()}\n text=\"Notifications\"\n hasNotifications={!error && !!unreadCount}\n />\n );\n};\n","/*\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, { useMemo } from 'react';\nimport throttle from 'lodash/throttle';\nimport { Box, IconButton, Tooltip, Typography } from '@material-ui/core';\nimport { Notification } from '@backstage/plugin-notifications-common';\nimport { notificationsApiRef } from '../../api';\nimport { useApi } from '@backstage/core-plugin-api';\nimport MarkAsUnreadIcon from '@material-ui/icons/Markunread';\nimport MarkAsReadIcon from '@material-ui/icons/CheckCircle';\n\n// @ts-ignore\nimport RelativeTime from 'react-relative-time';\nimport { Link, Table, TableColumn } from '@backstage/core-components';\n\nconst ThrottleDelayMs = 1000;\n\n/** @public */\nexport type NotificationsTableProps = {\n isLoading?: boolean;\n notifications?: Notification[];\n onUpdate: () => void;\n setContainsText: (search: string) => void;\n};\n\n/** @public */\nexport const NotificationsTable = ({\n isLoading,\n notifications = [],\n onUpdate,\n setContainsText,\n}: NotificationsTableProps) => {\n const notificationsApi = useApi(notificationsApiRef);\n\n const onSwitchReadStatus = React.useCallback(\n (notification: Notification) => {\n notificationsApi\n .updateNotifications({\n ids: [notification.id],\n read: !notification.read,\n })\n .then(() => onUpdate());\n },\n [notificationsApi, onUpdate],\n );\n\n const throttledContainsTextHandler = useMemo(\n () => throttle(setContainsText, ThrottleDelayMs),\n [setContainsText],\n );\n\n const compactColumns = React.useMemo(\n (): TableColumn<Notification>[] => [\n {\n customFilterAndSearch: () =>\n true /* Keep it on backend due to pagination. If recent flickering is an issue, implement search here as well. */,\n render: (notification: Notification) => {\n // Compact content\n return (\n <>\n <Box>\n <Typography variant=\"subtitle2\">\n {notification.payload.link ? (\n <Link to={notification.payload.link}>\n {notification.payload.title}\n </Link>\n ) : (\n notification.payload.title\n )}\n </Typography>\n <Typography variant=\"body2\">\n {notification.payload.description}\n </Typography>\n <Typography variant=\"caption\">\n {notification.origin && (\n <>{notification.origin} • </>\n )}\n {notification.payload.topic && (\n <>{notification.payload.topic} • </>\n )}\n {notification.created && (\n <RelativeTime value={notification.created} />\n )}\n </Typography>\n </Box>\n </>\n );\n },\n },\n // {\n // // TODO: additional action links\n // width: '25%',\n // render: (notification: Notification) => {\n // return (\n // notification.payload.link && (\n // <Grid container>\n // {/* TODO: render additionalLinks of different titles */}\n // <Grid item>\n // <Link\n // key={notification.payload.link}\n // to={notification.payload.link}\n // >\n // More info\n // </Link>\n // </Grid>\n // </Grid>\n // )\n // );\n // },\n // },\n {\n // TODO: action for saving notifications\n // actions\n width: '1rem',\n render: (notification: Notification) => {\n const markAsReadText = !!notification.read\n ? 'Return among unread'\n : 'Mark as read';\n const IconComponent = !!notification.read\n ? MarkAsUnreadIcon\n : MarkAsReadIcon;\n\n return (\n <Tooltip title={markAsReadText}>\n <IconButton\n onClick={() => {\n onSwitchReadStatus(notification);\n }}\n >\n <IconComponent aria-label={markAsReadText} />\n </IconButton>\n </Tooltip>\n );\n },\n },\n ],\n [onSwitchReadStatus],\n );\n\n // TODO: render \"Saved notifications\" as \"Pinned\"\n return (\n <Table<Notification>\n isLoading={isLoading}\n options={{\n search: true,\n // TODO: add pagination\n // paging: true,\n // pageSize,\n header: false,\n sorting: false,\n }}\n // onPageChange={setPageNumber}\n // onRowsPerPageChange={setPageSize}\n // page={offset}\n // totalCount={value?.totalCount}\n onSearchChange={throttledContainsTextHandler}\n data={notifications}\n columns={compactColumns}\n />\n );\n};\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/plugin-notifications",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0-next.0",
|
|
4
4
|
"main": "dist/index.esm.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -28,17 +28,18 @@
|
|
|
28
28
|
"postpack": "backstage-cli package postpack"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@backstage/core-components": "^0.14.
|
|
32
|
-
"@backstage/core-plugin-api": "^1.9.
|
|
33
|
-
"@backstage/errors": "^1.2.
|
|
34
|
-
"@backstage/plugin-notifications-common": "^0.0.
|
|
35
|
-
"@backstage/plugin-signals-react": "^0.0.
|
|
36
|
-
"@backstage/theme": "^0.5.
|
|
31
|
+
"@backstage/core-components": "^0.14.1-next.0",
|
|
32
|
+
"@backstage/core-plugin-api": "^1.9.1-next.0",
|
|
33
|
+
"@backstage/errors": "^1.2.4-next.0",
|
|
34
|
+
"@backstage/plugin-notifications-common": "^0.0.2-next.0",
|
|
35
|
+
"@backstage/plugin-signals-react": "^0.0.2-next.0",
|
|
36
|
+
"@backstage/theme": "^0.5.2-next.0",
|
|
37
37
|
"@backstage/types": "^1.1.1",
|
|
38
38
|
"@material-ui/core": "^4.9.13",
|
|
39
39
|
"@material-ui/icons": "^4.9.1",
|
|
40
40
|
"@material-ui/lab": "^4.0.0-alpha.61",
|
|
41
41
|
"@types/react": "^16.13.1 || ^17.0.0",
|
|
42
|
+
"lodash": "^4.17.21",
|
|
42
43
|
"react-relative-time": "^0.0.9",
|
|
43
44
|
"react-use": "^17.2.4"
|
|
44
45
|
},
|
|
@@ -47,10 +48,10 @@
|
|
|
47
48
|
"react-router-dom": "6.0.0-beta.0 || ^6.3.0"
|
|
48
49
|
},
|
|
49
50
|
"devDependencies": {
|
|
50
|
-
"@backstage/cli": "^0.25.
|
|
51
|
-
"@backstage/core-app-api": "^1.12.
|
|
52
|
-
"@backstage/dev-utils": "^1.0.
|
|
53
|
-
"@backstage/test-utils": "^1.5.
|
|
51
|
+
"@backstage/cli": "^0.25.3-next.0",
|
|
52
|
+
"@backstage/core-app-api": "^1.12.1-next.0",
|
|
53
|
+
"@backstage/dev-utils": "^1.0.28-next.0",
|
|
54
|
+
"@backstage/test-utils": "^1.5.1-next.0",
|
|
54
55
|
"@testing-library/jest-dom": "^6.0.0",
|
|
55
56
|
"@testing-library/react": "^14.0.0",
|
|
56
57
|
"@testing-library/user-event": "^14.0.0",
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import React, { useState, useEffect } from 'react';
|
|
2
|
-
import { ErrorPanel, PageWithHeader, Content } from '@backstage/core-components';
|
|
3
|
-
import { useNotificationsApi, NotificationsTable } from '../index.esm.js';
|
|
4
|
-
import { makeStyles, Grid, Button } from '@material-ui/core';
|
|
5
|
-
import Bookmark from '@material-ui/icons/Bookmark';
|
|
6
|
-
import Check from '@material-ui/icons/Check';
|
|
7
|
-
import Inbox from '@material-ui/icons/Inbox';
|
|
8
|
-
import { useSignal } from '@backstage/plugin-signals-react';
|
|
9
|
-
import '@backstage/core-plugin-api';
|
|
10
|
-
import '@backstage/errors';
|
|
11
|
-
import 'react-use/lib/useAsyncRetry';
|
|
12
|
-
import '@material-ui/icons/Notifications';
|
|
13
|
-
import 'react-router-dom';
|
|
14
|
-
import '@material-ui/core/Checkbox';
|
|
15
|
-
import '@material-ui/icons/Close';
|
|
16
|
-
import 'react-relative-time';
|
|
17
|
-
import '@material-ui/icons/ArrowForward';
|
|
18
|
-
|
|
19
|
-
const useStyles = makeStyles((_theme) => ({
|
|
20
|
-
filterButton: {
|
|
21
|
-
width: "100%",
|
|
22
|
-
justifyContent: "start"
|
|
23
|
-
}
|
|
24
|
-
}));
|
|
25
|
-
const NotificationsPage = () => {
|
|
26
|
-
const [type, setType] = useState("undone");
|
|
27
|
-
const [refresh, setRefresh] = React.useState(false);
|
|
28
|
-
const { error, value, retry } = useNotificationsApi(
|
|
29
|
-
(api) => api.getNotifications({ type }),
|
|
30
|
-
[type]
|
|
31
|
-
);
|
|
32
|
-
useEffect(() => {
|
|
33
|
-
if (refresh) {
|
|
34
|
-
retry();
|
|
35
|
-
setRefresh(false);
|
|
36
|
-
}
|
|
37
|
-
}, [refresh, setRefresh, retry]);
|
|
38
|
-
const { lastSignal } = useSignal("notifications");
|
|
39
|
-
useEffect(() => {
|
|
40
|
-
if (lastSignal && lastSignal.action) {
|
|
41
|
-
setRefresh(true);
|
|
42
|
-
}
|
|
43
|
-
}, [lastSignal]);
|
|
44
|
-
const onUpdate = () => {
|
|
45
|
-
setRefresh(true);
|
|
46
|
-
};
|
|
47
|
-
const styles = useStyles();
|
|
48
|
-
if (error) {
|
|
49
|
-
return /* @__PURE__ */ React.createElement(ErrorPanel, { error: new Error("Failed to load notifications") });
|
|
50
|
-
}
|
|
51
|
-
return /* @__PURE__ */ React.createElement(PageWithHeader, { title: "Notifications", themeId: "tool" }, /* @__PURE__ */ React.createElement(Content, null, /* @__PURE__ */ React.createElement(Grid, { container: true }, /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 2 }, /* @__PURE__ */ React.createElement(
|
|
52
|
-
Button,
|
|
53
|
-
{
|
|
54
|
-
className: styles.filterButton,
|
|
55
|
-
startIcon: /* @__PURE__ */ React.createElement(Inbox, null),
|
|
56
|
-
variant: type === "undone" ? "contained" : "text",
|
|
57
|
-
onClick: () => setType("undone")
|
|
58
|
-
},
|
|
59
|
-
"Inbox"
|
|
60
|
-
), /* @__PURE__ */ React.createElement(
|
|
61
|
-
Button,
|
|
62
|
-
{
|
|
63
|
-
className: styles.filterButton,
|
|
64
|
-
startIcon: /* @__PURE__ */ React.createElement(Check, null),
|
|
65
|
-
variant: type === "done" ? "contained" : "text",
|
|
66
|
-
onClick: () => setType("done")
|
|
67
|
-
},
|
|
68
|
-
"Done"
|
|
69
|
-
), /* @__PURE__ */ React.createElement(
|
|
70
|
-
Button,
|
|
71
|
-
{
|
|
72
|
-
className: styles.filterButton,
|
|
73
|
-
startIcon: /* @__PURE__ */ React.createElement(Bookmark, null),
|
|
74
|
-
variant: type === "saved" ? "contained" : "text",
|
|
75
|
-
onClick: () => setType("saved")
|
|
76
|
-
},
|
|
77
|
-
"Saved"
|
|
78
|
-
)), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 10 }, /* @__PURE__ */ React.createElement(
|
|
79
|
-
NotificationsTable,
|
|
80
|
-
{
|
|
81
|
-
notifications: value,
|
|
82
|
-
type,
|
|
83
|
-
onUpdate
|
|
84
|
-
}
|
|
85
|
-
)))));
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
export { NotificationsPage };
|
|
89
|
-
//# sourceMappingURL=index-9074aad8.esm.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-9074aad8.esm.js","sources":["../../src/components/NotificationsPage/NotificationsPage.tsx"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, { useEffect, useState } from 'react';\nimport {\n Content,\n ErrorPanel,\n PageWithHeader,\n} from '@backstage/core-components';\nimport { NotificationsTable } from '../NotificationsTable';\nimport { useNotificationsApi } from '../../hooks';\nimport { Button, Grid, makeStyles } from '@material-ui/core';\nimport Bookmark from '@material-ui/icons/Bookmark';\nimport Check from '@material-ui/icons/Check';\nimport Inbox from '@material-ui/icons/Inbox';\nimport { NotificationType } from '@backstage/plugin-notifications-common';\nimport { useSignal } from '@backstage/plugin-signals-react';\n\nconst useStyles = makeStyles(_theme => ({\n filterButton: {\n width: '100%',\n justifyContent: 'start',\n },\n}));\n\nexport const NotificationsPage = () => {\n const [type, setType] = useState<NotificationType>('undone');\n const [refresh, setRefresh] = React.useState(false);\n\n const { error, value, retry } = useNotificationsApi(\n api => api.getNotifications({ type }),\n [type],\n );\n\n useEffect(() => {\n if (refresh) {\n retry();\n setRefresh(false);\n }\n }, [refresh, setRefresh, retry]);\n\n const { lastSignal } = useSignal('notifications');\n useEffect(() => {\n if (lastSignal && lastSignal.action) {\n setRefresh(true);\n }\n }, [lastSignal]);\n\n const onUpdate = () => {\n setRefresh(true);\n };\n\n const styles = useStyles();\n if (error) {\n return <ErrorPanel error={new Error('Failed to load notifications')} />;\n }\n\n return (\n <PageWithHeader title=\"Notifications\" themeId=\"tool\">\n <Content>\n <Grid container>\n <Grid item xs={2}>\n <Button\n className={styles.filterButton}\n startIcon={<Inbox />}\n variant={type === 'undone' ? 'contained' : 'text'}\n onClick={() => setType('undone')}\n >\n Inbox\n </Button>\n <Button\n className={styles.filterButton}\n startIcon={<Check />}\n variant={type === 'done' ? 'contained' : 'text'}\n onClick={() => setType('done')}\n >\n Done\n </Button>\n <Button\n className={styles.filterButton}\n startIcon={<Bookmark />}\n variant={type === 'saved' ? 'contained' : 'text'}\n onClick={() => setType('saved')}\n >\n Saved\n </Button>\n </Grid>\n <Grid item xs={10}>\n <NotificationsTable\n notifications={value}\n type={type}\n onUpdate={onUpdate}\n />\n </Grid>\n </Grid>\n </Content>\n </PageWithHeader>\n );\n};\n"],"names":[],"mappings":"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"}
|