@backstage/plugin-notifications 0.1.0-next.2 → 0.1.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 CHANGED
@@ -1,5 +1,28 @@
1
1
  # @backstage/plugin-notifications
2
2
 
3
+ ## 0.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 6e6d096: notifications can be newly sorted by list of predefined options
8
+ - cd96173: Notifications-backend URL query parameters changed from `sort/sortOrder` to `orderField` and `created_after` to `createdAfter` to unify with other plugins.
9
+ - 07abfe1: The NotificationsPage newly uses pagination implemented on the backend layer to avoid large dataset transfers
10
+ - 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.
11
+
12
+ ### Patch Changes
13
+
14
+ - dff7a7e: All notifications can be marked and filtered by severity critical, high, normal or low, the default is 'normal'
15
+ - 75f2d84: the user can newly mark notifications as "Saved" for their better visibility in the future
16
+ - 5d9c5ba: The Notifications can be newly filtered based on the Created Date.
17
+ - Updated dependencies
18
+ - @backstage/plugin-notifications-common@0.0.2
19
+ - @backstage/core-components@0.14.1
20
+ - @backstage/errors@1.2.4
21
+ - @backstage/theme@0.5.2
22
+ - @backstage/core-plugin-api@1.9.1
23
+ - @backstage/types@1.1.1
24
+ - @backstage/plugin-signals-react@0.0.2
25
+
3
26
  ## 0.1.0-next.2
4
27
 
5
28
  ### Minor Changes
@@ -11,6 +11,12 @@ import 'lodash/throttle';
11
11
  import 'react-relative-time';
12
12
  import '@material-ui/icons/Markunread';
13
13
  import '@material-ui/icons/CheckCircle';
14
+ import '@material-ui/icons/LabelOff';
15
+ import '@material-ui/icons/Label';
16
+ import '@material-ui/icons/CheckOutlined';
17
+ import '@material-ui/icons/ErrorOutline';
18
+ import '@material-ui/icons/WarningOutlined';
19
+ import '@material-ui/icons/InfoOutlined';
14
20
 
15
21
  const CreatedAfterOptions = {
16
22
  last24h: {
@@ -68,51 +74,77 @@ const getSortByText = (sortBy) => {
68
74
  }
69
75
  return "newest";
70
76
  };
77
+ const AllSeverityOptions = {
78
+ critical: "Critical",
79
+ high: "High",
80
+ normal: "Normal",
81
+ low: "Low"
82
+ };
71
83
  const NotificationsFilters = ({
72
84
  sorting,
73
85
  onSortingChanged,
74
86
  unreadOnly,
75
87
  onUnreadOnlyChanged,
76
88
  createdAfter,
77
- onCreatedAfterChanged
89
+ onCreatedAfterChanged,
90
+ saved,
91
+ onSavedChanged,
92
+ severity,
93
+ onSeverityChanged
78
94
  }) => {
79
95
  const sortByText = getSortByText(sorting);
80
96
  const handleOnCreatedAfterChanged = (event) => {
81
97
  onCreatedAfterChanged(event.target.value);
82
98
  };
83
- const handleOnUnreadOnlyChanged = (event) => {
84
- let value = void 0;
85
- if (event.target.value === "unread")
86
- value = true;
87
- if (event.target.value === "read")
88
- value = false;
89
- onUnreadOnlyChanged(value);
99
+ const handleOnViewChanged = (event) => {
100
+ if (event.target.value === "unread") {
101
+ onUnreadOnlyChanged(true);
102
+ onSavedChanged(void 0);
103
+ } else if (event.target.value === "read") {
104
+ onUnreadOnlyChanged(false);
105
+ onSavedChanged(void 0);
106
+ } else if (event.target.value === "saved") {
107
+ onUnreadOnlyChanged(void 0);
108
+ onSavedChanged(true);
109
+ } else {
110
+ onUnreadOnlyChanged(void 0);
111
+ onSavedChanged(void 0);
112
+ }
90
113
  };
91
114
  const handleOnSortByChanged = (event) => {
92
115
  const idx = event.target.value || "newest";
93
116
  const option = SortByOptions[idx];
94
117
  onSortingChanged({ ...option.sortBy });
95
118
  };
96
- let unreadOnlyValue = "all";
97
- if (unreadOnly)
98
- unreadOnlyValue = "unread";
99
- if (unreadOnly === false)
100
- unreadOnlyValue = "read";
119
+ let viewValue = "all";
120
+ if (saved) {
121
+ viewValue = "saved";
122
+ } else if (unreadOnly) {
123
+ viewValue = "unread";
124
+ } else if (unreadOnly === false) {
125
+ viewValue = "read";
126
+ }
127
+ const handleOnSeverityChanged = (event) => {
128
+ const value = event.target.value || "normal";
129
+ onSeverityChanged(value);
130
+ };
101
131
  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(
102
132
  Select,
103
133
  {
104
134
  labelId: "notifications-filter-view",
105
135
  label: "View",
106
- value: unreadOnlyValue,
107
- onChange: handleOnUnreadOnlyChanged
136
+ value: viewValue,
137
+ onChange: handleOnViewChanged
108
138
  },
109
139
  /* @__PURE__ */ React.createElement(MenuItem, { value: "unread" }, "New only"),
140
+ /* @__PURE__ */ React.createElement(MenuItem, { value: "saved" }, "Saved"),
110
141
  /* @__PURE__ */ React.createElement(MenuItem, { value: "read" }, "Marked as read"),
111
142
  /* @__PURE__ */ React.createElement(MenuItem, { value: "all" }, "All")
112
- ))), /* @__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(
143
+ ))), /* @__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-created" }, "Created after"), /* @__PURE__ */ React.createElement(
113
144
  Select,
114
145
  {
115
146
  label: "Created after",
147
+ labelId: "notifications-filter-created",
116
148
  placeholder: "Notifications since",
117
149
  value: createdAfter,
118
150
  onChange: handleOnCreatedAfterChanged
@@ -122,11 +154,21 @@ const NotificationsFilters = ({
122
154
  Select,
123
155
  {
124
156
  label: "Sort by",
157
+ labelId: "notifications-filter-sort",
125
158
  placeholder: "Field to sort by",
126
159
  value: sortByText,
127
160
  onChange: handleOnSortByChanged
128
161
  },
129
162
  Object.keys(SortByOptions).map((key) => /* @__PURE__ */ React.createElement(MenuItem, { value: key, key }, SortByOptions[key].label))
163
+ ))), /* @__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-severity" }, "Severity"), /* @__PURE__ */ React.createElement(
164
+ Select,
165
+ {
166
+ label: "Severity",
167
+ labelId: "notifications-filter-severity",
168
+ value: severity,
169
+ onChange: handleOnSeverityChanged
170
+ },
171
+ Object.keys(AllSeverityOptions).map((key) => /* @__PURE__ */ React.createElement(MenuItem, { value: key, key }, AllSeverityOptions[key]))
130
172
  )))));
131
173
  };
132
174
 
@@ -134,6 +176,7 @@ const NotificationsPage = () => {
134
176
  const [refresh, setRefresh] = React.useState(false);
135
177
  const { lastSignal } = useSignal("notifications");
136
178
  const [unreadOnly, setUnreadOnly] = React.useState(true);
179
+ const [saved, setSaved] = React.useState(void 0);
137
180
  const [pageNumber, setPageNumber] = React.useState(0);
138
181
  const [pageSize, setPageSize] = React.useState(5);
139
182
  const [containsText, setContainsText] = React.useState();
@@ -141,24 +184,38 @@ const NotificationsPage = () => {
141
184
  const [sorting, setSorting] = React.useState(
142
185
  SortByOptions.newest.sortBy
143
186
  );
187
+ const [severity, setSeverity] = React.useState("low");
144
188
  const { error, value, retry, loading } = useNotificationsApi(
145
189
  (api) => {
146
190
  const options = {
147
191
  search: containsText,
148
192
  limit: pageSize,
149
193
  offset: pageNumber * pageSize,
194
+ minimumSeverity: severity,
150
195
  ...sorting || {}
151
196
  };
152
197
  if (unreadOnly !== void 0) {
153
198
  options.read = !unreadOnly;
154
199
  }
200
+ if (saved !== void 0) {
201
+ options.saved = saved;
202
+ }
155
203
  const createdAfterDate = CreatedAfterOptions[createdAfter].getDate();
156
204
  if (createdAfterDate.valueOf() > 0) {
157
205
  options.createdAfter = createdAfterDate;
158
206
  }
159
207
  return api.getNotifications(options);
160
208
  },
161
- [containsText, unreadOnly, createdAfter, pageNumber, pageSize, sorting]
209
+ [
210
+ containsText,
211
+ unreadOnly,
212
+ createdAfter,
213
+ pageNumber,
214
+ pageSize,
215
+ sorting,
216
+ saved,
217
+ severity
218
+ ]
162
219
  );
163
220
  useEffect(() => {
164
221
  if (refresh) {
@@ -185,7 +242,11 @@ const NotificationsPage = () => {
185
242
  createdAfter,
186
243
  onCreatedAfterChanged: setCreatedAfter,
187
244
  onSortingChanged: setSorting,
188
- sorting
245
+ sorting,
246
+ saved,
247
+ onSavedChanged: setSaved,
248
+ severity,
249
+ onSeverityChanged: setSeverity
189
250
  }
190
251
  )), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 10 }, /* @__PURE__ */ React.createElement(
191
252
  NotificationsTable,
@@ -204,4 +265,4 @@ const NotificationsPage = () => {
204
265
  };
205
266
 
206
267
  export { NotificationsPage };
207
- //# sourceMappingURL=index-cd12b44c.esm.js.map
268
+ //# sourceMappingURL=index-9328bf59.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-9328bf59.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';\nimport { GetNotificationsOptions } from '../../api';\nimport { NotificationSeverity } from '@backstage/plugin-notifications-common';\n\nexport type SortBy = Required<\n Pick<GetNotificationsOptions, 'sort' | 'sortOrder'>\n>;\n\nexport type NotificationsFiltersProps = {\n unreadOnly?: boolean;\n onUnreadOnlyChanged: (checked: boolean | undefined) => void;\n createdAfter?: string;\n onCreatedAfterChanged: (value: string) => void;\n sorting: SortBy;\n onSortingChanged: (sortBy: SortBy) => void;\n saved?: boolean;\n onSavedChanged: (checked: boolean | undefined) => void;\n severity: NotificationSeverity;\n onSeverityChanged: (severity: NotificationSeverity) => 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\nexport const SortByOptions: {\n [key: string]: {\n label: string;\n sortBy: SortBy;\n };\n} = {\n newest: {\n label: 'Newest on top',\n sortBy: {\n sort: 'created',\n sortOrder: 'desc',\n },\n },\n oldest: {\n label: 'Oldest on top',\n sortBy: {\n sort: 'created',\n sortOrder: 'asc',\n },\n },\n topic: {\n label: 'Topic',\n sortBy: {\n sort: 'topic',\n sortOrder: 'asc',\n },\n },\n origin: {\n label: 'Origin',\n sortBy: {\n sort: 'origin',\n sortOrder: 'asc',\n },\n },\n};\n\nconst getSortByText = (sortBy?: SortBy): string => {\n if (sortBy?.sort === 'created' && sortBy?.sortOrder === 'asc') {\n return 'oldest';\n }\n if (sortBy?.sort === 'topic') {\n return 'topic';\n }\n if (sortBy?.sort === 'origin') {\n return 'origin';\n }\n\n return 'newest';\n};\n\nconst AllSeverityOptions: { [key in NotificationSeverity]: string } = {\n critical: 'Critical',\n high: 'High',\n normal: 'Normal',\n low: 'Low',\n};\n\nexport const NotificationsFilters = ({\n sorting,\n onSortingChanged,\n unreadOnly,\n onUnreadOnlyChanged,\n createdAfter,\n onCreatedAfterChanged,\n saved,\n onSavedChanged,\n severity,\n onSeverityChanged,\n}: NotificationsFiltersProps) => {\n const sortByText = getSortByText(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 handleOnViewChanged = (\n event: React.ChangeEvent<{ name?: string; value: unknown }>,\n ) => {\n if (event.target.value === 'unread') {\n onUnreadOnlyChanged(true);\n onSavedChanged(undefined);\n } else if (event.target.value === 'read') {\n onUnreadOnlyChanged(false);\n onSavedChanged(undefined);\n } else if (event.target.value === 'saved') {\n onUnreadOnlyChanged(undefined);\n onSavedChanged(true);\n } else {\n // All\n onUnreadOnlyChanged(undefined);\n onSavedChanged(undefined);\n }\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 onSortingChanged({ ...option.sortBy });\n };\n\n let viewValue = 'all';\n if (saved) {\n viewValue = 'saved';\n } else if (unreadOnly) {\n viewValue = 'unread';\n } else if (unreadOnly === false) {\n viewValue = 'read';\n }\n\n const handleOnSeverityChanged = (\n event: React.ChangeEvent<{ name?: string; value: unknown }>,\n ) => {\n const value: NotificationSeverity =\n (event.target.value as NotificationSeverity) || 'normal';\n onSeverityChanged(value);\n };\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\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={viewValue}\n onChange={handleOnViewChanged}\n >\n <MenuItem value=\"unread\">New only</MenuItem>\n <MenuItem value=\"saved\">Saved</MenuItem>\n <MenuItem value=\"read\">Marked as read</MenuItem>\n <MenuItem value=\"all\">All</MenuItem>\n </Select>\n </FormControl>\n </Grid>\n\n <Grid item xs={12}>\n <FormControl fullWidth variant=\"outlined\" size=\"small\">\n <InputLabel id=\"notifications-filter-created\">\n Created after\n </InputLabel>\n\n <Select\n label=\"Created after\"\n labelId=\"notifications-filter-created\"\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 <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 labelId=\"notifications-filter-sort\"\n placeholder=\"Field to sort by\"\n value={sortByText}\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\n <Grid item xs={12}>\n <FormControl fullWidth variant=\"outlined\" size=\"small\">\n <InputLabel id=\"notifications-filter-severity\">Severity</InputLabel>\n\n <Select\n label=\"Severity\"\n labelId=\"notifications-filter-severity\"\n value={severity}\n onChange={handleOnSeverityChanged}\n >\n {Object.keys(AllSeverityOptions).map((key: string) => (\n <MenuItem value={key} key={key}>\n {AllSeverityOptions[key as NotificationSeverity]}\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 SortBy,\n SortByOptions,\n} from '../NotificationsFilters';\nimport { GetNotificationsOptions } from '../../api';\nimport { NotificationSeverity } from '@backstage/plugin-notifications-common';\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 [saved, setSaved] = React.useState<boolean | undefined>(undefined);\n const [pageNumber, setPageNumber] = React.useState(0);\n const [pageSize, setPageSize] = React.useState(5);\n const [containsText, setContainsText] = React.useState<string>();\n const [createdAfter, setCreatedAfter] = React.useState<string>('lastWeek');\n const [sorting, setSorting] = React.useState<SortBy>(\n SortByOptions.newest.sortBy,\n );\n const [severity, setSeverity] = React.useState<NotificationSeverity>('low');\n\n const { error, value, retry, loading } = useNotificationsApi(\n api => {\n const options: GetNotificationsOptions = {\n search: containsText,\n limit: pageSize,\n offset: pageNumber * pageSize,\n minimumSeverity: severity,\n ...(sorting || {}),\n };\n if (unreadOnly !== undefined) {\n options.read = !unreadOnly;\n }\n if (saved !== undefined) {\n options.saved = saved;\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 [\n containsText,\n unreadOnly,\n createdAfter,\n pageNumber,\n pageSize,\n sorting,\n saved,\n severity,\n ],\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 onSortingChanged={setSorting}\n sorting={sorting}\n saved={saved}\n onSavedChanged={setSaved}\n severity={severity}\n onSeverityChanged={setSeverity}\n />\n </Grid>\n <Grid item xs={10}>\n <NotificationsTable\n isLoading={loading}\n notifications={value?.notifications}\n onUpdate={onUpdate}\n setContainsText={setContainsText}\n onPageChange={setPageNumber}\n onRowsPerPageChange={setPageSize}\n page={pageNumber}\n pageSize={pageSize}\n totalCount={value?.totalCount}\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 { Notification as Notification$1, NotificationStatus } from '@backstage/plugin-notifications-common';
6
+ import { NotificationSeverity, Notification as Notification$1, NotificationStatus } from '@backstage/plugin-notifications-common';
7
7
  import { TableProps } from '@backstage/core-components';
8
8
 
9
9
  /** @public */
@@ -21,9 +21,11 @@ type GetNotificationsOptions = {
21
21
  limit?: number;
22
22
  search?: string;
23
23
  read?: boolean;
24
+ saved?: boolean;
24
25
  createdAfter?: Date;
25
26
  sort?: 'created' | 'topic' | 'origin';
26
27
  sortOrder?: 'asc' | 'desc';
28
+ minimumSeverity?: NotificationSeverity;
27
29
  };
28
30
  /** @public */
29
31
  type UpdateNotificationsOptions = {
package/dist/index.esm.js CHANGED
@@ -7,9 +7,15 @@ import NotificationsIcon from '@material-ui/icons/Notifications';
7
7
  import { useSignal } from '@backstage/plugin-signals-react';
8
8
  import throttle from 'lodash/throttle';
9
9
  import RelativeTime from 'react-relative-time';
10
- import { Box, Typography, Tooltip, IconButton } from '@material-ui/core';
10
+ import { Box, Typography, Grid, Tooltip, IconButton } from '@material-ui/core';
11
11
  import MarkAsUnreadIcon from '@material-ui/icons/Markunread';
12
12
  import MarkAsReadIcon from '@material-ui/icons/CheckCircle';
13
+ import MarkAsUnsavedIcon from '@material-ui/icons/LabelOff';
14
+ import MarkAsSavedIcon from '@material-ui/icons/Label';
15
+ import NormalIcon from '@material-ui/icons/CheckOutlined';
16
+ import CriticalIcon from '@material-ui/icons/ErrorOutline';
17
+ import HighIcon from '@material-ui/icons/WarningOutlined';
18
+ import LowIcon from '@material-ui/icons/InfoOutlined';
13
19
 
14
20
  const rootRouteRef = createRouteRef({
15
21
  id: "notifications"
@@ -33,6 +39,7 @@ class NotificationsClient {
33
39
  this.fetchApi = options.fetchApi;
34
40
  }
35
41
  async getNotifications(options) {
42
+ var _a;
36
43
  const queryString = new URLSearchParams();
37
44
  if ((options == null ? void 0 : options.limit) !== void 0) {
38
45
  queryString.append("limit", options.limit.toString(10));
@@ -41,10 +48,10 @@ class NotificationsClient {
41
48
  queryString.append("offset", options.offset.toString(10));
42
49
  }
43
50
  if ((options == null ? void 0 : options.sort) !== void 0) {
44
- queryString.append("sort", options.sort);
45
- }
46
- if ((options == null ? void 0 : options.sortOrder) !== void 0) {
47
- queryString.append("sort_order", options.sortOrder);
51
+ queryString.append(
52
+ "orderField",
53
+ `${options.sort},${(_a = options == null ? void 0 : options.sortOrder) != null ? _a : "desc"}`
54
+ );
48
55
  }
49
56
  if (options == null ? void 0 : options.search) {
50
57
  queryString.append("search", options.search);
@@ -52,8 +59,14 @@ class NotificationsClient {
52
59
  if ((options == null ? void 0 : options.read) !== void 0) {
53
60
  queryString.append("read", options.read ? "true" : "false");
54
61
  }
62
+ if ((options == null ? void 0 : options.saved) !== void 0) {
63
+ queryString.append("saved", options.saved ? "true" : "false");
64
+ }
55
65
  if ((options == null ? void 0 : options.createdAfter) !== void 0) {
56
- queryString.append("created_after", options.createdAfter.toISOString());
66
+ queryString.append("createdAfter", options.createdAfter.toISOString());
67
+ }
68
+ if ((options == null ? void 0 : options.minimumSeverity) !== void 0) {
69
+ queryString.append("minimal_severity", options.minimumSeverity);
57
70
  }
58
71
  const urlSegment = `?${queryString}`;
59
72
  return await this.request(urlSegment);
@@ -98,7 +111,7 @@ const notificationsPlugin = createPlugin({
98
111
  const NotificationsPage = notificationsPlugin.provide(
99
112
  createRoutableExtension({
100
113
  name: "NotificationsPage",
101
- component: () => import('./esm/index-cd12b44c.esm.js').then((m) => m.NotificationsPage),
114
+ component: () => import('./esm/index-9328bf59.esm.js').then((m) => m.NotificationsPage),
102
115
  mountPoint: rootRouteRef
103
116
  })
104
117
  );
@@ -248,6 +261,22 @@ const NotificationsSidebarItem = (props) => {
248
261
  );
249
262
  };
250
263
 
264
+ const SeverityIcon = ({
265
+ severity
266
+ }) => {
267
+ switch (severity) {
268
+ case "critical":
269
+ return /* @__PURE__ */ React.createElement(CriticalIcon, { htmlColor: "#C9190B" });
270
+ case "high":
271
+ return /* @__PURE__ */ React.createElement(HighIcon, { htmlColor: "#F0AB00" });
272
+ case "low":
273
+ return /* @__PURE__ */ React.createElement(LowIcon, { htmlColor: "#2B9AF3" });
274
+ case "normal":
275
+ default:
276
+ return /* @__PURE__ */ React.createElement(NormalIcon, { htmlColor: "#5BA352" });
277
+ }
278
+ };
279
+
251
280
  const ThrottleDelayMs = 1e3;
252
281
  const NotificationsTable = ({
253
282
  isLoading,
@@ -270,12 +299,28 @@ const NotificationsTable = ({
270
299
  },
271
300
  [notificationsApi, onUpdate]
272
301
  );
302
+ const onSwitchSavedStatus = React.useCallback(
303
+ (notification) => {
304
+ notificationsApi.updateNotifications({
305
+ ids: [notification.id],
306
+ saved: !notification.saved
307
+ }).then(() => onUpdate());
308
+ },
309
+ [notificationsApi, onUpdate]
310
+ );
273
311
  const throttledContainsTextHandler = useMemo(
274
312
  () => throttle(setContainsText, ThrottleDelayMs),
275
313
  [setContainsText]
276
314
  );
277
315
  const compactColumns = React.useMemo(
278
316
  () => [
317
+ {
318
+ width: "1rem",
319
+ render: (notification) => {
320
+ var _a;
321
+ return /* @__PURE__ */ React.createElement(SeverityIcon, { severity: (_a = notification.payload) == null ? void 0 : _a.severity });
322
+ }
323
+ },
279
324
  {
280
325
  customFilterAndSearch: () => true,
281
326
  render: (notification) => {
@@ -304,13 +349,22 @@ const NotificationsTable = ({
304
349
  // },
305
350
  // },
306
351
  {
307
- // TODO: action for saving notifications
308
352
  // actions
309
353
  width: "1rem",
310
354
  render: (notification) => {
311
355
  const markAsReadText = !!notification.read ? "Return among unread" : "Mark as read";
312
356
  const IconComponent = !!notification.read ? MarkAsUnreadIcon : MarkAsReadIcon;
313
- return /* @__PURE__ */ React.createElement(Tooltip, { title: markAsReadText }, /* @__PURE__ */ React.createElement(
357
+ const markAsSavedText = !!notification.saved ? "Undo save" : "Save for later";
358
+ const SavedIconComponent = !!notification.saved ? MarkAsUnsavedIcon : MarkAsSavedIcon;
359
+ return /* @__PURE__ */ React.createElement(Grid, { container: true, wrap: "nowrap" }, /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(Tooltip, { title: markAsSavedText }, /* @__PURE__ */ React.createElement(
360
+ IconButton,
361
+ {
362
+ onClick: () => {
363
+ onSwitchSavedStatus(notification);
364
+ }
365
+ },
366
+ /* @__PURE__ */ React.createElement(SavedIconComponent, { "aria-label": markAsSavedText })
367
+ ))), /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(Tooltip, { title: markAsReadText }, /* @__PURE__ */ React.createElement(
314
368
  IconButton,
315
369
  {
316
370
  onClick: () => {
@@ -318,11 +372,11 @@ const NotificationsTable = ({
318
372
  }
319
373
  },
320
374
  /* @__PURE__ */ React.createElement(IconComponent, { "aria-label": markAsReadText })
321
- ));
375
+ ))));
322
376
  }
323
377
  }
324
378
  ],
325
- [onSwitchReadStatus]
379
+ [onSwitchReadStatus, onSwitchSavedStatus]
326
380
  );
327
381
  return /* @__PURE__ */ React.createElement(
328
382
  Table,
@@ -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} 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 sort?: 'created' | 'topic' | 'origin';\n sortOrder?: 'asc' | 'desc';\n};\n\n/** @public */\nexport type UpdateNotificationsOptions = {\n ids: string[];\n read?: boolean;\n saved?: boolean;\n};\n\n/** @public */\nexport type GetNotificationsResponse = {\n notifications: Notification[];\n totalCount: number;\n};\n\n/** @public */\nexport interface NotificationsApi {\n getNotifications(\n options?: GetNotificationsOptions,\n ): Promise<GetNotificationsResponse>;\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 GetNotificationsResponse,\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<GetNotificationsResponse> {\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?.sort !== undefined) {\n queryString.append('sort', options.sort);\n }\n if (options?.sortOrder !== undefined) {\n queryString.append('sort_order', options.sortOrder);\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<GetNotificationsResponse>(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';\n// @ts-ignore\nimport RelativeTime from 'react-relative-time';\nimport { Box, IconButton, Tooltip, Typography } from '@material-ui/core';\nimport { Notification } from '@backstage/plugin-notifications-common';\n\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';\nimport {\n Link,\n Table,\n TableProps,\n TableColumn,\n} from '@backstage/core-components';\n\nconst ThrottleDelayMs = 1000;\n\n/** @public */\nexport type NotificationsTableProps = Pick<\n TableProps,\n 'onPageChange' | 'onRowsPerPageChange' | 'page' | 'totalCount'\n> & {\n isLoading?: boolean;\n notifications?: Notification[];\n onUpdate: () => void;\n setContainsText: (search: string) => void;\n pageSize: number;\n};\n\n/** @public */\nexport const NotificationsTable = ({\n isLoading,\n notifications = [],\n onUpdate,\n setContainsText,\n onPageChange,\n onRowsPerPageChange,\n page,\n pageSize,\n totalCount,\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}&nbsp;&bull;&nbsp;</>\n )}\n {notification.payload.topic && (\n <>{notification.payload.topic}&nbsp;&bull;&nbsp;</>\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 // &nbsp;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 paging: true,\n pageSize,\n header: false,\n sorting: false,\n }}\n onPageChange={onPageChange}\n onRowsPerPageChange={onRowsPerPageChange}\n page={page}\n totalCount={totalCount}\n onSearchChange={throttledContainsTextHandler}\n data={notifications}\n columns={compactColumns}\n />\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/SeverityIcon.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 NotificationSeverity,\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 saved?: boolean;\n createdAfter?: Date;\n sort?: 'created' | 'topic' | 'origin';\n sortOrder?: 'asc' | 'desc';\n minimumSeverity?: NotificationSeverity;\n};\n\n/** @public */\nexport type UpdateNotificationsOptions = {\n ids: string[];\n read?: boolean;\n saved?: boolean;\n};\n\n/** @public */\nexport type GetNotificationsResponse = {\n notifications: Notification[];\n totalCount: number;\n};\n\n/** @public */\nexport interface NotificationsApi {\n getNotifications(\n options?: GetNotificationsOptions,\n ): Promise<GetNotificationsResponse>;\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 GetNotificationsResponse,\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<GetNotificationsResponse> {\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?.sort !== undefined) {\n queryString.append(\n 'orderField',\n `${options.sort},${options?.sortOrder ?? 'desc'}`,\n );\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?.saved !== undefined) {\n queryString.append('saved', options.saved ? 'true' : 'false');\n }\n if (options?.createdAfter !== undefined) {\n queryString.append('createdAfter', options.createdAfter.toISOString());\n }\n if (options?.minimumSeverity !== undefined) {\n queryString.append('minimal_severity', options.minimumSeverity);\n }\n const urlSegment = `?${queryString}`;\n\n return await this.request<GetNotificationsResponse>(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 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';\nimport { NotificationSeverity } from '@backstage/plugin-notifications-common';\nimport NormalIcon from '@material-ui/icons/CheckOutlined';\nimport CriticalIcon from '@material-ui/icons/ErrorOutline';\nimport HighIcon from '@material-ui/icons/WarningOutlined';\nimport LowIcon from '@material-ui/icons/InfoOutlined';\n\nexport const SeverityIcon = ({\n severity,\n}: {\n severity?: NotificationSeverity;\n}) => {\n switch (severity) {\n case 'critical':\n return <CriticalIcon htmlColor=\"#C9190B\" />;\n case 'high':\n return <HighIcon htmlColor=\"#F0AB00\" />;\n case 'low':\n return <LowIcon htmlColor=\"#2B9AF3\" />;\n case 'normal':\n default:\n return <NormalIcon htmlColor=\"#5BA352\" />;\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';\n// @ts-ignore\nimport RelativeTime from 'react-relative-time';\nimport { Box, Grid, IconButton, Tooltip, Typography } from '@material-ui/core';\nimport { Notification } from '@backstage/plugin-notifications-common';\n\nimport { notificationsApiRef } from '../../api';\nimport { useApi } from '@backstage/core-plugin-api';\nimport {\n Link,\n Table,\n TableProps,\n TableColumn,\n} from '@backstage/core-components';\n\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 { SeverityIcon } from './SeverityIcon';\n\nconst ThrottleDelayMs = 1000;\n\n/** @public */\nexport type NotificationsTableProps = Pick<\n TableProps,\n 'onPageChange' | 'onRowsPerPageChange' | 'page' | 'totalCount'\n> & {\n isLoading?: boolean;\n notifications?: Notification[];\n onUpdate: () => void;\n setContainsText: (search: string) => void;\n pageSize: number;\n};\n\n/** @public */\nexport const NotificationsTable = ({\n isLoading,\n notifications = [],\n onUpdate,\n setContainsText,\n onPageChange,\n onRowsPerPageChange,\n page,\n pageSize,\n totalCount,\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 onSwitchSavedStatus = React.useCallback(\n (notification: Notification) => {\n notificationsApi\n .updateNotifications({\n ids: [notification.id],\n saved: !notification.saved,\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 width: '1rem',\n render: (notification: Notification) => (\n <SeverityIcon severity={notification.payload?.severity} />\n ),\n },\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}&nbsp;&bull;&nbsp;</>\n )}\n {notification.payload.topic && (\n <>{notification.payload.topic}&nbsp;&bull;&nbsp;</>\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 // &nbsp;More info\n // </Link>\n // </Grid>\n // </Grid>\n // )\n // );\n // },\n // },\n {\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 const markAsSavedText = !!notification.saved\n ? 'Undo save'\n : 'Save for later';\n\n const SavedIconComponent = !!notification.saved\n ? MarkAsUnsavedIcon\n : MarkAsSavedIcon;\n\n return (\n <Grid container wrap=\"nowrap\">\n <Grid item>\n <Tooltip title={markAsSavedText}>\n <IconButton\n onClick={() => {\n onSwitchSavedStatus(notification);\n }}\n >\n <SavedIconComponent aria-label={markAsSavedText} />\n </IconButton>\n </Tooltip>\n </Grid>\n\n <Grid item>\n <Tooltip title={markAsReadText}>\n <IconButton\n onClick={() => {\n onSwitchReadStatus(notification);\n }}\n >\n <IconComponent aria-label={markAsReadText} />\n </IconButton>\n </Tooltip>\n </Grid>\n </Grid>\n );\n },\n },\n ],\n [onSwitchReadStatus, onSwitchSavedStatus],\n );\n\n return (\n <Table<Notification>\n isLoading={isLoading}\n options={{\n search: true,\n paging: true,\n pageSize,\n header: false,\n sorting: false,\n }}\n onPageChange={onPageChange}\n onRowsPerPageChange={onRowsPerPageChange}\n page={page}\n totalCount={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.1.0-next.2",
3
+ "version": "0.1.0",
4
4
  "main": "dist/index.esm.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "license": "Apache-2.0",
@@ -28,12 +28,12 @@
28
28
  "postpack": "backstage-cli package postpack"
29
29
  },
30
30
  "dependencies": {
31
- "@backstage/core-components": "^0.14.1-next.2",
32
- "@backstage/core-plugin-api": "^1.9.1-next.1",
33
- "@backstage/errors": "^1.2.4-next.0",
34
- "@backstage/plugin-notifications-common": "^0.0.2-next.1",
35
- "@backstage/plugin-signals-react": "^0.0.2-next.1",
36
- "@backstage/theme": "^0.5.2-next.0",
31
+ "@backstage/core-components": "^0.14.1",
32
+ "@backstage/core-plugin-api": "^1.9.1",
33
+ "@backstage/errors": "^1.2.4",
34
+ "@backstage/plugin-notifications-common": "^0.0.2",
35
+ "@backstage/plugin-signals-react": "^0.0.2",
36
+ "@backstage/theme": "^0.5.2",
37
37
  "@backstage/types": "^1.1.1",
38
38
  "@material-ui/core": "^4.9.13",
39
39
  "@material-ui/icons": "^4.9.1",
@@ -48,10 +48,10 @@
48
48
  "react-router-dom": "6.0.0-beta.0 || ^6.3.0"
49
49
  },
50
50
  "devDependencies": {
51
- "@backstage/cli": "^0.25.3-next.2",
52
- "@backstage/core-app-api": "^1.12.1-next.1",
53
- "@backstage/dev-utils": "^1.0.28-next.2",
54
- "@backstage/test-utils": "^1.5.1-next.1",
51
+ "@backstage/cli": "^0.26.0",
52
+ "@backstage/core-app-api": "^1.12.1",
53
+ "@backstage/dev-utils": "^1.0.28",
54
+ "@backstage/test-utils": "^1.5.1",
55
55
  "@testing-library/jest-dom": "^6.0.0",
56
56
  "@testing-library/react": "^14.0.0",
57
57
  "@testing-library/user-event": "^14.0.0",
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-cd12b44c.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';\nimport { GetNotificationsOptions } from '../../api';\n\nexport type SortBy = Required<\n Pick<GetNotificationsOptions, 'sort' | 'sortOrder'>\n>;\n\nexport type NotificationsFiltersProps = {\n unreadOnly?: boolean;\n onUnreadOnlyChanged: (checked: boolean | undefined) => void;\n createdAfter?: string;\n onCreatedAfterChanged: (value: string) => void;\n sorting: SortBy;\n onSortingChanged: (sortBy: SortBy) => 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\nexport const SortByOptions: {\n [key: string]: {\n label: string;\n sortBy: SortBy;\n };\n} = {\n newest: {\n label: 'Newest on top',\n sortBy: {\n sort: 'created',\n sortOrder: 'desc',\n },\n },\n oldest: {\n label: 'Oldest on top',\n sortBy: {\n sort: 'created',\n sortOrder: 'asc',\n },\n },\n topic: {\n label: 'Topic',\n sortBy: {\n sort: 'topic',\n sortOrder: 'asc',\n },\n },\n origin: {\n label: 'Origin',\n sortBy: {\n sort: 'origin',\n sortOrder: 'asc',\n },\n },\n};\n\nconst getSortByText = (sortBy?: SortBy): string => {\n if (sortBy?.sort === 'created' && sortBy?.sortOrder === 'asc') {\n return 'oldest';\n }\n if (sortBy?.sort === 'topic') {\n return 'topic';\n }\n if (sortBy?.sort === 'origin') {\n return 'origin';\n }\n\n return 'newest';\n};\n\nexport const NotificationsFilters = ({\n sorting,\n onSortingChanged,\n unreadOnly,\n onUnreadOnlyChanged,\n createdAfter,\n onCreatedAfterChanged,\n}: NotificationsFiltersProps) => {\n const sortByText = getSortByText(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 onSortingChanged({ ...option.sortBy });\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 <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={sortByText}\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 SortBy,\n SortByOptions,\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 [pageNumber, setPageNumber] = React.useState(0);\n const [pageSize, setPageSize] = React.useState(5);\n const [containsText, setContainsText] = React.useState<string>();\n const [createdAfter, setCreatedAfter] = React.useState<string>('lastWeek');\n const [sorting, setSorting] = React.useState<SortBy>(\n SortByOptions.newest.sortBy,\n );\n\n const { error, value, retry, loading } = useNotificationsApi(\n api => {\n const options: GetNotificationsOptions = {\n search: containsText,\n limit: pageSize,\n offset: pageNumber * pageSize,\n ...(sorting || {}),\n };\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, pageNumber, pageSize, sorting],\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 onSortingChanged={setSorting}\n sorting={sorting}\n />\n </Grid>\n <Grid item xs={10}>\n <NotificationsTable\n isLoading={loading}\n notifications={value?.notifications}\n onUpdate={onUpdate}\n setContainsText={setContainsText}\n onPageChange={setPageNumber}\n onRowsPerPageChange={setPageSize}\n page={pageNumber}\n pageSize={pageSize}\n totalCount={value?.totalCount}\n />\n </Grid>\n </Grid>\n </Content>\n </PageWithHeader>\n );\n};\n"],"names":[],"mappings":"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"}