From 62141acaeebdb642a4738fb7ed286eea8d083d44 Mon Sep 17 00:00:00 2001 From: Heikki Hellgren Date: Mon, 18 Dec 2023 08:34:51 +0200 Subject: [PATCH] feat: allow specifying mui icon for notification Signed-off-by: Heikki Hellgren --- packages/backend/src/plugins/notifications.ts | 1 + plugins/notifications-common/api-report.md | 7 +++- plugins/notifications-common/package.json | 5 ++- plugins/notifications-common/src/types.ts | 8 +++- plugins/notifications-node/api-report.md | 3 +- .../src/service/NotificationService.ts | 16 ++++++-- .../NotificationsPage/NotificationsPage.tsx | 22 ++++------ .../NotificationsTable/NotificationIcon.tsx | 41 +++++++++++++++++++ .../NotificationsTable/NotificationsTable.tsx | 24 +++++++---- yarn.lock | 1 + 10 files changed, 98 insertions(+), 30 deletions(-) create mode 100644 plugins/notifications/src/components/NotificationsTable/NotificationIcon.tsx diff --git a/packages/backend/src/plugins/notifications.ts b/packages/backend/src/plugins/notifications.ts index 115d872f8d..689e42753a 100644 --- a/packages/backend/src/plugins/notifications.ts +++ b/packages/backend/src/plugins/notifications.ts @@ -30,6 +30,7 @@ export default async function createPlugin( title: 'Test', description: 'This is test notification', link: '/catalog', + icon: 'SwapHorizRounded', }); notifications++; } diff --git a/plugins/notifications-common/api-report.md b/plugins/notifications-common/api-report.md index b33edf3a80..9c085ff521 100644 --- a/plugins/notifications-common/api-report.md +++ b/plugins/notifications-common/api-report.md @@ -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[]; diff --git a/plugins/notifications-common/package.json b/plugins/notifications-common/package.json index 91acf171f7..cda38bd1cb 100644 --- a/plugins/notifications-common/package.json +++ b/plugins/notifications-common/package.json @@ -28,5 +28,8 @@ }, "files": [ "dist" - ] + ], + "dependencies": { + "@material-ui/icons": "^4.9.1" + } } diff --git a/plugins/notifications-common/src/types.ts b/plugins/notifications-common/src/types.ts index 39dab24681..f0e6feae30 100644 --- a/plugins/notifications-common/src/types.ts +++ b/plugins/notifications-common/src/types.ts @@ -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; diff --git a/plugins/notifications-node/api-report.md b/plugins/notifications-node/api-report.md index 31a2bbf3da..4cfe35233e 100644 --- a/plugins/notifications-node/api-report.md +++ b/plugins/notifications-node/api-report.md @@ -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) diff --git a/plugins/notifications-node/src/service/NotificationService.ts b/plugins/notifications-node/src/service/NotificationService.ts index 501f799d31..029df83185 100644 --- a/plugins/notifications-node/src/service/NotificationService.ts +++ b/plugins/notifications-node/src/service/NotificationService.ts @@ -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 { 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(), diff --git a/plugins/notifications/src/components/NotificationsPage/NotificationsPage.tsx b/plugins/notifications/src/components/NotificationsPage/NotificationsPage.tsx index eeaec21ef1..4ebcaa6fc4 100644 --- a/plugins/notifications/src/components/NotificationsPage/NotificationsPage.tsx +++ b/plugins/notifications/src/components/NotificationsPage/NotificationsPage.tsx @@ -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 = () => { - - - + diff --git a/plugins/notifications/src/components/NotificationsTable/NotificationIcon.tsx b/plugins/notifications/src/components/NotificationsTable/NotificationIcon.tsx new file mode 100644 index 0000000000..f5ae2e8c22 --- /dev/null +++ b/plugins/notifications/src/components/NotificationsTable/NotificationIcon.tsx @@ -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 ; + } + + if (notification.image) { + return ( + + ); + } + + return ; +}; diff --git a/plugins/notifications/src/components/NotificationsTable/NotificationsTable.tsx b/plugins/notifications/src/components/NotificationsTable/NotificationsTable.tsx index 9ccc76e1ec..68df969db6 100644 --- a/plugins/notifications/src/components/NotificationsTable/NotificationsTable.tsx +++ b/plugins/notifications/src/components/NotificationsTable/NotificationsTable.tsx @@ -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 ; } - // TODO: Show timestamp relative time (react-relative-time npm package) - // TODO: Add signals listener and refresh data on message return ( @@ -174,16 +173,19 @@ export const NotificationsTable = (props: { {props.notifications?.map(notification => { return ( - + onCheckBoxClick(notification.id)} /> - {notification.icon ?? } + - navigate(notification.link)}> + navigate(notification.link)} + style={{ paddingLeft: 0 }} + > {notification.title} {notification.description} @@ -194,6 +196,14 @@ export const NotificationsTable = (props: { + + navigate(notification.link)} + > + + + diff --git a/yarn.lock b/yarn.lock index 62519ba3a0..3a1a6f0bbf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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