feat: allow specifying mui icon for notification

Signed-off-by: Heikki Hellgren <heikki.hellgren@op.fi>
This commit is contained in:
Heikki Hellgren
2023-12-18 08:34:51 +02:00
parent fb8fc24df0
commit 62141acaee
10 changed files with 98 additions and 30 deletions
@@ -30,6 +30,7 @@ export default async function createPlugin(
title: 'Test',
description: 'This is test notification',
link: '/catalog',
icon: 'SwapHorizRounded',
});
notifications++;
}
+6 -1
View File
@@ -3,6 +3,8 @@
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
```ts
import * as muiIcons from '@material-ui/icons';
// @public (undocumented)
type Notification_2 = {
id: string;
@@ -10,7 +12,7 @@ type Notification_2 = {
title: string;
description: string;
link: string;
icon?: string;
icon?: NotificationIcon;
image?: string;
created: Date;
read?: Date;
@@ -18,6 +20,9 @@ type Notification_2 = {
};
export { Notification_2 as Notification };
// @public (undocumented)
export type NotificationIcon = keyof typeof muiIcons;
// @public (undocumented)
export type NotificationIds = {
ids: string[];
+4 -1
View File
@@ -28,5 +28,8 @@
},
"files": [
"dist"
]
],
"dependencies": {
"@material-ui/icons": "^4.9.1"
}
}
+6 -2
View File
@@ -14,9 +14,14 @@
* limitations under the License.
*/
import * as muiIcons from '@material-ui/icons';
/** @public */
export type NotificationType = 'read' | 'unread' | 'saved';
/** @public */
export type NotificationIcon = keyof typeof muiIcons;
/** @public */
export type Notification = {
id: string;
@@ -24,8 +29,7 @@ export type Notification = {
title: string;
description: string;
link: string;
// TODO: Icon should be typed so that we know what to render
icon?: string;
icon?: NotificationIcon;
image?: string;
created: Date;
read?: Date;
+2 -1
View File
@@ -4,6 +4,7 @@
```ts
import { Notification as Notification_2 } from '@backstage/plugin-notifications-common';
import { NotificationIcon } from '@backstage/plugin-notifications-common';
import { NotificationStatus } from '@backstage/plugin-notifications-common';
import { NotificationType } from '@backstage/plugin-notifications-common';
import { PluginDatabaseManager } from '@backstage/backend-common';
@@ -57,7 +58,7 @@ export type NotificationSendOptions = {
description: string;
link: string;
image?: string;
icon?: string;
icon?: NotificationIcon;
};
// @public (undocumented)
@@ -13,7 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Notification } from '@backstage/plugin-notifications-common';
import {
Notification,
NotificationIcon,
} from '@backstage/plugin-notifications-common';
import { CatalogApi, CatalogClient } from '@backstage/catalog-client';
import { NotificationsStore } from '../database/NotificationsStore';
import { v4 as uuid } from 'uuid';
@@ -43,7 +46,7 @@ export type NotificationSendOptions = {
description: string;
link: string;
image?: string;
icon?: string;
icon?: NotificationIcon;
};
/** @public */
@@ -68,9 +71,16 @@ export class NotificationService {
async send(options: NotificationSendOptions): Promise<Notification[]> {
const { entityRef, title, description, link, icon, image } = options;
const users = await this.getUsersForEntityRef(entityRef);
const notifications = [];
let users = [];
try {
users = await this.getUsersForEntityRef(entityRef);
} catch (e) {
return [];
}
const store = await this.getStore();
for (const user of users) {
const notification = {
id: uuid(),
@@ -22,13 +22,7 @@ import {
} from '@backstage/core-components';
import { NotificationsTable } from '../NotificationsTable';
import { useNotificationsApi } from '../../hooks';
import {
Button,
Grid,
makeStyles,
Paper,
TableContainer,
} from '@material-ui/core';
import { Button, Grid, makeStyles } from '@material-ui/core';
import Bookmark from '@material-ui/icons/Bookmark';
import Check from '@material-ui/icons/Check';
import Inbox from '@material-ui/icons/Inbox';
@@ -90,14 +84,12 @@ export const NotificationsPage = () => {
</Button>
</Grid>
<Grid item xs={10}>
<TableContainer component={Paper}>
<NotificationsTable
notifications={value}
type={type}
loading={loading}
onUpdate={onUpdate}
/>
</TableContainer>
<NotificationsTable
notifications={value}
type={type}
loading={loading}
onUpdate={onUpdate}
/>
</Grid>
</Grid>
</Content>
@@ -0,0 +1,41 @@
/*
* Copyright 2023 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
import NotificationsIcon from '@material-ui/icons/Notifications';
import { Notification } from '@backstage/plugin-notifications-common';
// eslint-disable-next-line no-restricted-imports
import * as muiIcons from '@material-ui/icons';
import Avatar from '@material-ui/core/Avatar';
/** @internal */
export const NotificationIcon = (props: { notification: Notification }) => {
const { notification } = props;
if (notification.icon && notification.icon in muiIcons) {
const Icon = muiIcons[notification.icon];
return <Icon fontSize="small" />;
}
if (notification.image) {
return (
<Avatar
src={notification.image}
style={{ width: '20px', height: '20px' }}
/>
);
}
return <NotificationsIcon fontSize="small" />;
};
@@ -31,7 +31,6 @@ import {
NotificationType,
} from '@backstage/plugin-notifications-common';
import { useNavigate } from 'react-router-dom';
import NotificationsIcon from '@material-ui/icons/Notifications';
import Checkbox from '@material-ui/core/Checkbox';
import Check from '@material-ui/icons/Check';
import Bookmark from '@material-ui/icons/Bookmark';
@@ -42,6 +41,8 @@ import CloseIcon from '@material-ui/icons/Close';
import { Skeleton } from '@material-ui/lab';
// @ts-ignore
import RelativeTime from 'react-relative-time';
import { NotificationIcon } from './NotificationIcon';
import ArrowForwardIcon from '@material-ui/icons/ArrowForward';
const useStyles = makeStyles(theme => ({
notificationRow: {
@@ -53,7 +54,7 @@ const useStyles = makeStyles(theme => ({
display: 'none',
},
'&:hover': {
backgroundColor: theme.palette.linkHover,
backgroundColor: theme.palette.background.paper,
'& .hideOnHover': {
display: 'none',
},
@@ -110,8 +111,6 @@ export const NotificationsTable = (props: {
return <Skeleton variant="rect" height={200} />;
}
// TODO: Show timestamp relative time (react-relative-time npm package)
// TODO: Add signals listener and refresh data on message
return (
<Table size="small">
<TableHead>
@@ -174,16 +173,19 @@ export const NotificationsTable = (props: {
{props.notifications?.map(notification => {
return (
<TableRow key={notification.id} className={styles.notificationRow}>
<TableCell width={100} style={{ verticalAlign: 'center' }}>
<TableCell width="90px" style={{ verticalAlign: 'center' }}>
<Checkbox
className={styles.checkBox}
size="small"
checked={isChecked(notification.id)}
onClick={() => onCheckBoxClick(notification.id)}
/>
{notification.icon ?? <NotificationsIcon fontSize="small" />}
<NotificationIcon notification={notification} />
</TableCell>
<TableCell onClick={() => navigate(notification.link)}>
<TableCell
onClick={() => navigate(notification.link)}
style={{ paddingLeft: 0 }}
>
<Typography variant="subtitle2">{notification.title}</Typography>
<Typography variant="body2">
{notification.description}
@@ -194,6 +196,14 @@ export const NotificationsTable = (props: {
<RelativeTime value={notification.created} />
</Box>
<Box className="showOnHover">
<Tooltip title={notification.link}>
<IconButton
className={styles.actionButton}
onClick={() => navigate(notification.link)}
>
<ArrowForwardIcon />
</IconButton>
</Tooltip>
<Tooltip
title={notification.read ? 'Move to inbox' : 'Mark as done'}
>
+1
View File
@@ -7807,6 +7807,7 @@ __metadata:
resolution: "@backstage/plugin-notifications-common@workspace:plugins/notifications-common"
dependencies:
"@backstage/cli": "workspace:^"
"@material-ui/icons": ^4.9.1
languageName: unknown
linkType: soft