diff --git a/packages/backend/src/index.ts b/packages/backend/src/index.ts index c140e6dcf5..032bcfbb9f 100644 --- a/packages/backend/src/index.ts +++ b/packages/backend/src/index.ts @@ -105,7 +105,7 @@ function makeCreateEnv(config: Config) { const signalService = DefaultSignalService.create({ eventBroker, }); - const notificationService = DefaultNotificationService.create({ + const defaultNotificationService = DefaultNotificationService.create({ logger: root.child({ type: 'plugin' }), discovery, tokenManager, @@ -119,6 +119,7 @@ function makeCreateEnv(config: Config) { const database = databaseManager.forPlugin(plugin); const cache = cacheManager.forPlugin(plugin); const scheduler = taskScheduler.forPlugin(plugin); + const notificationService = defaultNotificationService.forPlugin(plugin); return { logger, diff --git a/plugins/notifications-backend/migrations/20231215_init.js b/plugins/notifications-backend/migrations/20231215_init.js index 329906ca99..65139e6d07 100644 --- a/plugins/notifications-backend/migrations/20231215_init.js +++ b/plugins/notifications-backend/migrations/20231215_init.js @@ -19,14 +19,17 @@ exports.up = async function up(knex) { table.uuid('id').primary(); table.string('userRef').notNullable(); table.string('title').notNullable(); - table.text('description').notNullable(); + table.text('description').nullable(); + table.text('severity').notNullable(); table.text('link').notNullable(); + table.text('origin').notNullable(); + table.text('scope').nullable(); table.text('topic').nullable(); table.datetime('created').defaultTo(knex.fn.now()).notNullable(); table.datetime('updated').nullable(); table.datetime('read').nullable(); table.datetime('done').nullable(); - table.boolean('saved').defaultTo(false).notNullable(); + table.datetime('saved').nullable(); }); }; diff --git a/plugins/notifications-backend/src/database/DatabaseNotificationsStore.ts b/plugins/notifications-backend/src/database/DatabaseNotificationsStore.ts index a0a262b95b..34fa42423b 100644 --- a/plugins/notifications-backend/src/database/DatabaseNotificationsStore.ts +++ b/plugins/notifications-backend/src/database/DatabaseNotificationsStore.ts @@ -95,7 +95,7 @@ export class DatabaseNotificationsStore implements NotificationsStore { } } - if ('ids' in options && options.ids) { + if (options.ids) { query.whereIn('id', options.ids); } @@ -131,13 +131,15 @@ export class DatabaseNotificationsStore implements NotificationsStore { }; } - async getExistingTopicNotification(options: { + async getExistingScopeNotification(options: { user_ref: string; - topic: string; + scope: string; + origin: string; }) { const query = this.db('notifications') .where('userRef', options.user_ref) - .where('topic', options.topic) + .where('scope', options.scope) + .where('origin', options.origin) .select('*') .limit(1); @@ -156,11 +158,12 @@ export class DatabaseNotificationsStore implements NotificationsStore { .where('id', options.id) .where('userRef', options.notification.userRef); const rows = await query.update({ - title: options.notification.title, - description: options.notification.description, - link: options.notification.link, - topic: options.notification.topic, + title: options.notification.payload.title, + description: options.notification.payload.description, + link: options.notification.payload.link, + topic: options.notification.payload.topic, updated: options.notification.created, + severity: options.notification.payload.severity, read: null, done: null, }); @@ -205,11 +208,11 @@ export class DatabaseNotificationsStore implements NotificationsStore { async markSaved(options: NotificationModifyOptions): Promise { const notificationQuery = this.getNotificationsBaseQuery(options); - await notificationQuery.update({ saved: true }); + await notificationQuery.update({ saved: new Date() }); } async markUnsaved(options: NotificationModifyOptions): Promise { const notificationQuery = this.getNotificationsBaseQuery(options); - await notificationQuery.update({ saved: false }); + await notificationQuery.update({ saved: null }); } } diff --git a/plugins/notifications-backend/src/database/NotificationsStore.ts b/plugins/notifications-backend/src/database/NotificationsStore.ts index ec13bc42b0..d24a5e6991 100644 --- a/plugins/notifications-backend/src/database/NotificationsStore.ts +++ b/plugins/notifications-backend/src/database/NotificationsStore.ts @@ -23,6 +23,8 @@ import { /** @public */ export type NotificationGetOptions = { user_ref: string; + + ids?: string[]; type?: NotificationType; offset?: number; limit?: number; @@ -40,9 +42,10 @@ export interface NotificationsStore { saveNotification(notification: Notification): Promise; - getExistingTopicNotification(options: { + getExistingScopeNotification(options: { user_ref: string; - topic: string; + scope: string; + origin: string; }): Promise; restoreExistingNotification(options: { diff --git a/plugins/notifications-backend/src/service/router.ts b/plugins/notifications-backend/src/service/router.ts index e28026abf4..ee66e410c8 100644 --- a/plugins/notifications-backend/src/service/router.ts +++ b/plugins/notifications-backend/src/service/router.ts @@ -209,104 +209,67 @@ export async function createRouter( res.send(status); }); - router.post('/done', async (req, res) => { + router.post('/update', async (req, res) => { const user = await getUser(req); - const { ids } = req.body; + const { ids, done, read, saved } = req.body; if (!ids || !Array.isArray(ids)) { res.status(400).send(); return; } - await store.markDone({ user_ref: user, ids }); + if (done === true) { + await store.markDone({ user_ref: user, ids }); + if (signalService) { + await signalService.publish({ + recipients: [user], + message: { action: 'done', notification_ids: ids }, + channel: 'notifications', + }); + } + } else if (done === false) { + await store.markUndone({ user_ref: user, ids }); + if (signalService) { + await signalService.publish({ + recipients: [user], + message: { action: 'undone', notification_ids: ids }, + channel: 'notifications', + }); + } + } - if (signalService) { - await signalService.publish({ - recipients: [user], - message: { action: 'done', notification_ids: ids }, - channel: 'notifications', - }); - } - res.status(200).send({ ids }); - }); + if (read === true) { + await store.markRead({ user_ref: user, ids }); - router.post('/undo', async (req, res) => { - const user = await getUser(req); - const { ids } = req.body; - if (!ids || !Array.isArray(ids)) { - res.status(400).send(); - return; - } - await store.markUndone({ user_ref: user, ids }); - if (signalService) { - await signalService.publish({ - recipients: [user], - message: { action: 'undone', notification_ids: ids }, - channel: 'notifications', - }); - } - res.status(200).send({ ids }); - }); + if (signalService) { + await signalService.publish({ + recipients: [user], + message: { action: 'mark_read', notification_ids: ids }, + channel: 'notifications', + }); + } + } else if (read === false) { + await store.markUnread({ user_ref: user, ids }); - router.post('/read', async (req, res) => { - const user = await getUser(req); - const { ids } = req.body; - if (!ids || !Array.isArray(ids)) { - res.status(400).send(); - return; + if (signalService) { + await signalService.publish({ + recipients: [user], + message: { action: 'mark_unread', notification_ids: ids }, + channel: 'notifications', + }); + } } - await store.markRead({ user_ref: user, ids }); - if (signalService) { - await signalService.publish({ - recipients: [user], - message: { action: 'mark_read', notification_ids: ids }, - channel: 'notifications', - }); + if (saved === true) { + await store.markSaved({ user_ref: user, ids }); + } else if (saved === false) { + await store.markUnsaved({ user_ref: user, ids }); } - res.status(200).send({ ids }); - }); - router.post('/unread', async (req, res) => { - const user = await getUser(req); - const { ids } = req.body; - if (!ids || !Array.isArray(ids)) { - res.status(400).send(); - return; - } - await store.markUnread({ user_ref: user, ids }); - if (signalService) { - await signalService.publish({ - recipients: [user], - message: { action: 'mark_unread', notification_ids: ids }, - channel: 'notifications', - }); - } - res.status(200).send({ ids }); - }); - - router.post('/save', async (req, res) => { - const user = await getUser(req); - const { ids } = req.body; - if (!ids || !Array.isArray(ids)) { - res.status(400).send(); - return; - } - await store.markSaved({ user_ref: user, ids }); - res.status(200).send({ ids }); - }); - - router.post('/unsave', async (req, res) => { - const user = await getUser(req); - const { ids } = req.body; - if (!ids || !Array.isArray(ids)) { - res.status(400).send(); - return; - } - await store.markUnsaved({ user_ref: user, ids }); - res.status(200).send({ ids }); + const notifications = await store.getNotifications({ ids, user_ref: user }); + res.status(200).send(notifications); }); router.post('/notifications', async (req, res) => { - const { receivers, title, description, link, topic } = req.body; + const { recipients, origin, payload } = req.body; const notifications = []; let users = []; @@ -318,9 +281,17 @@ export async function createRouter( return; } + const { title, link, description, scope } = payload; + + if (!recipients || !title || !origin || !link) { + logger.error(`Invalid notification request received`); + res.status(400).send(); + return; + } + let entityRef = null; - if (receivers.entityRef && receivers.type === 'entity') { - entityRef = receivers.entityRef; + if (recipients.entityRef && recipients.type === 'entity') { + entityRef = recipients.entityRef; } try { @@ -331,13 +302,13 @@ export async function createRouter( return; } - const baseNotification = { - title, - description, - link, - topic, + const baseNotification: Omit = { + payload: { + ...payload, + severity: payload.severity ?? 'normal', + }, + origin, created: new Date(), - saved: false, }; for (const user of users) { @@ -349,10 +320,11 @@ export async function createRouter( const notification = await decorateNotification(userNotification); let existingNotification; - if (topic) { - existingNotification = await store.getExistingTopicNotification({ + if (scope) { + existingNotification = await store.getExistingScopeNotification({ user_ref: user, - topic, + scope, + origin, }); } diff --git a/plugins/notifications-common/api-report.md b/plugins/notifications-common/api-report.md index 0770c94fae..9ada705f31 100644 --- a/plugins/notifications-common/api-report.md +++ b/plugins/notifications-common/api-report.md @@ -7,23 +7,29 @@ type Notification_2 = { id: string; userRef: string; - title: string; - description: string; - link: string; - topic?: string; created: Date; - updated?: Date; + saved?: Date; read?: Date; - done?: Date; - saved: boolean; + updated?: Date; + origin: string; + payload: NotificationPayload; }; export { Notification_2 as Notification }; // @public (undocumented) -export type NotificationIds = { - ids: string[]; +export type NotificationPayload = { + title: string; + description?: string; + link: string; + severity: NotificationSeverity; + topic?: string; + scope?: string; + icon?: string; }; +// @public (undocumented) +export type NotificationSeverity = 'critical' | 'high' | 'normal' | 'low'; + // @public (undocumented) export type NotificationStatus = { unread: number; diff --git a/plugins/notifications-common/src/types.ts b/plugins/notifications-common/src/types.ts index 43de9c725f..c717073403 100644 --- a/plugins/notifications-common/src/types.ts +++ b/plugins/notifications-common/src/types.ts @@ -17,19 +17,32 @@ /** @public */ export type NotificationType = 'undone' | 'done' | 'saved'; +/** @public */ +export type NotificationSeverity = 'critical' | 'high' | 'normal' | 'low'; + +/** @public */ +export type NotificationPayload = { + title: string; + description?: string; + link: string; + // TODO: Add support for additional links + // additionalLinks?: string[]; + severity: NotificationSeverity; + topic?: string; + scope?: string; + icon?: string; +}; + /** @public */ export type Notification = { id: string; userRef: string; - title: string; - description: string; - link: string; - topic?: string; created: Date; - updated?: Date; + saved?: Date; read?: Date; - done?: Date; - saved: boolean; + updated?: Date; + origin: string; + payload: NotificationPayload; }; /** @public */ @@ -37,8 +50,3 @@ export type NotificationStatus = { unread: number; read: number; }; - -/** @public */ -export type NotificationIds = { - ids: string[]; -}; diff --git a/plugins/notifications-node/README.md b/plugins/notifications-node/README.md index c3d8e93fe7..60d1e35c24 100644 --- a/plugins/notifications-node/README.md +++ b/plugins/notifications-node/README.md @@ -15,15 +15,18 @@ import { NotificationService } from '@backstage/plugin-notifications-node'; function makeCreateEnv(config: Config) { // ... - const notificationService = DefaultNotificationService.create({ + const defaultNotificationService = DefaultNotificationService.create({ logger: root.child({ type: 'plugin' }), discovery, tokenManager, + signalService, }); // ... return (plugin: string): PluginEnvironment => { // ... + const notificationService = defaultNotificationService.forPlugin(plugin); + return { // ... notificationService, @@ -55,4 +58,4 @@ a user, the notification will be sent to only that user. If it's a group, the no members of the group. If it's some other entity, the notification will be sent to the owner of that entity. If the notification has `topic` set and user already has notification with that topic, the existing notification -will be updated with the new notification values and moved to inbox as unread. +will be updated with the new notification values and moved to inbox as unread. diff --git a/plugins/notifications-node/api-report.md b/plugins/notifications-node/api-report.md index 6f655d9f18..17b172a8e5 100644 --- a/plugins/notifications-node/api-report.md +++ b/plugins/notifications-node/api-report.md @@ -5,7 +5,7 @@ ```ts import { DiscoveryService } from '@backstage/backend-plugin-api'; import { LoggerService } from '@backstage/backend-plugin-api'; -import { Notification as Notification_2 } from '@backstage/plugin-notifications-common'; +import { NotificationPayload } from '@backstage/plugin-notifications-common'; import { ServiceRef } from '@backstage/backend-plugin-api'; import { SignalService } from '@backstage/plugin-signals-node'; import { TokenManager } from '@backstage/backend-common'; @@ -19,28 +19,29 @@ export class DefaultNotificationService implements NotificationService { discovery, }: NotificationServiceOptions): DefaultNotificationService; // (undocumented) - send(options: NotificationSendOptions): Promise; + forPlugin(pluginId: string): NotificationService; + // (undocumented) + send(notification: NotificationSendOptions): Promise; } // @public (undocumented) -export type NotificationReceivers = { +export type NotificationRecipients = { type: 'entity'; entityRef: string | string[]; }; // @public (undocumented) export type NotificationSendOptions = { - receivers: NotificationReceivers; - title: string; - description: string; - link: string; - topic?: string; + recipients: NotificationRecipients; + payload: NotificationPayload; }; // @public (undocumented) export interface NotificationService { // (undocumented) - send(options: NotificationSendOptions): Promise; + forPlugin(pluginId: string): NotificationService; + // (undocumented) + send(options: NotificationSendOptions): Promise; } // @public (undocumented) diff --git a/plugins/notifications-node/src/lib.ts b/plugins/notifications-node/src/lib.ts index 41773143d2..67bb3c315d 100644 --- a/plugins/notifications-node/src/lib.ts +++ b/plugins/notifications-node/src/lib.ts @@ -30,18 +30,20 @@ export const notificationService = createServiceRef({ createServiceFactory({ service, deps: { - logger: coreServices.logger, + logger: coreServices.rootLogger, discovery: coreServices.discovery, tokenManager: coreServices.tokenManager, + pluginMetadata: coreServices.pluginMetadata, signals: signalService, }, - factory({ logger, discovery, tokenManager, signals }) { + factory({ logger, discovery, tokenManager, signals, pluginMetadata }) { + // TODO: Convert to use createRootContext return DefaultNotificationService.create({ logger, discovery, tokenManager, signalService: signals, - }); + }).forPlugin(pluginMetadata.getId()); }, }), }); diff --git a/plugins/notifications-node/src/service/DefaultNotificationService.ts b/plugins/notifications-node/src/service/DefaultNotificationService.ts index d92e92f61c..3348c02a6e 100644 --- a/plugins/notifications-node/src/service/DefaultNotificationService.ts +++ b/plugins/notifications-node/src/service/DefaultNotificationService.ts @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Notification } from '@backstage/plugin-notifications-common'; import { TokenManager } from '@backstage/backend-common'; import { NotificationService } from './NotificationService'; import { DiscoveryService, LoggerService } from '@backstage/backend-plugin-api'; import { SignalService } from '@backstage/plugin-signals-node'; +import { NotificationPayload } from '@backstage/plugin-notifications-common'; /** @public */ export type NotificationServiceOptions = { @@ -28,7 +28,7 @@ export type NotificationServiceOptions = { }; /** @public */ -export type NotificationReceivers = { +export type NotificationRecipients = { type: 'entity'; entityRef: string | string[]; }; @@ -38,11 +38,8 @@ export type NotificationReceivers = { /** @public */ export type NotificationSendOptions = { - receivers: NotificationReceivers; - title: string; - description: string; - link: string; - topic?: string; + recipients: NotificationRecipients; + payload: NotificationPayload; }; /** @public */ @@ -51,6 +48,7 @@ export class DefaultNotificationService implements NotificationService { private readonly logger: LoggerService, private readonly discovery: DiscoveryService, private readonly tokenManager: TokenManager, + private readonly pluginId?: string, ) {} static create({ @@ -61,22 +59,36 @@ export class DefaultNotificationService implements NotificationService { return new DefaultNotificationService(logger, discovery, tokenManager); } - async send(options: NotificationSendOptions): Promise { + forPlugin(pluginId: string): NotificationService { + return new DefaultNotificationService( + this.logger, + this.discovery, + this.tokenManager, + pluginId, + ); + } + + async send(notification: NotificationSendOptions): Promise { + if (!this.pluginId) { + throw new Error('Invalid initialization of the NotificationService'); + } + try { const baseUrl = await this.discovery.getBaseUrl('notifications'); const { token } = await this.tokenManager.getToken(); - const response = await fetch(`${baseUrl}/notifications`, { + await fetch(`${baseUrl}/notifications`, { method: 'POST', - body: JSON.stringify(options), + body: JSON.stringify({ + ...notification, + origin: `plugin-${this.pluginId}`, + }), headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}`, }, }); - return await response.json(); } catch (error) { this.logger.error(`Failed to send notifications: ${error}`); - return []; } } } diff --git a/plugins/notifications-node/src/service/NotificationService.ts b/plugins/notifications-node/src/service/NotificationService.ts index 68b0c13a9e..5c76dd8088 100644 --- a/plugins/notifications-node/src/service/NotificationService.ts +++ b/plugins/notifications-node/src/service/NotificationService.ts @@ -15,9 +15,10 @@ */ import { NotificationSendOptions } from './DefaultNotificationService'; -import { Notification } from '@backstage/plugin-notifications-common'; /** @public */ export interface NotificationService { - send(options: NotificationSendOptions): Promise; + forPlugin(pluginId: string): NotificationService; + + send(options: NotificationSendOptions): Promise; } diff --git a/plugins/notifications/api-report.md b/plugins/notifications/api-report.md index 93c6eaedf7..3d96934438 100644 --- a/plugins/notifications/api-report.md +++ b/plugins/notifications/api-report.md @@ -11,7 +11,6 @@ import { DiscoveryApi } from '@backstage/core-plugin-api'; import { FetchApi } from '@backstage/core-plugin-api'; import { JSX as JSX_2 } from 'react'; import { Notification as Notification_2 } from '@backstage/plugin-notifications-common'; -import { NotificationIds } from '@backstage/plugin-notifications-common'; import { NotificationStatus } from '@backstage/plugin-notifications-common'; import { NotificationType } from '@backstage/plugin-notifications-common'; import { default as React_2 } from 'react'; @@ -34,17 +33,9 @@ export interface NotificationsApi { // (undocumented) getStatus(): Promise; // (undocumented) - markDone(ids: string[]): Promise; - // (undocumented) - markRead(ids: string[]): Promise; - // (undocumented) - markSaved(ids: string[]): Promise; - // (undocumented) - markUndone(ids: string[]): Promise; - // (undocumented) - markUnread(ids: string[]): Promise; - // (undocumented) - markUnsaved(ids: string[]): Promise; + updateNotifications( + options: UpdateNotificationsOptions, + ): Promise; } // @public (undocumented) @@ -60,17 +51,9 @@ export class NotificationsClient implements NotificationsApi { // (undocumented) getStatus(): Promise; // (undocumented) - markDone(ids: string[]): Promise; - // (undocumented) - markRead(ids: string[]): Promise; - // (undocumented) - markSaved(ids: string[]): Promise; - // (undocumented) - markUndone(ids: string[]): Promise; - // (undocumented) - markUnread(ids: string[]): Promise; - // (undocumented) - markUnsaved(ids: string[]): Promise; + updateNotifications( + options: UpdateNotificationsOptions, + ): Promise; } // @public (undocumented) @@ -94,6 +77,14 @@ export const NotificationsTable: (props: { notifications?: Notification_2[]; }) => React_2.JSX.Element; +// @public (undocumented) +export type UpdateNotificationsOptions = { + ids: string[]; + done?: boolean; + read?: boolean; + saved?: boolean; +}; + // @public (undocumented) export function useNotificationsApi( f: (api: NotificationsApi) => Promise, diff --git a/plugins/notifications/src/api/NotificationsApi.ts b/plugins/notifications/src/api/NotificationsApi.ts index 95d8cd6297..775dc6b244 100644 --- a/plugins/notifications/src/api/NotificationsApi.ts +++ b/plugins/notifications/src/api/NotificationsApi.ts @@ -16,7 +16,6 @@ import { createApiRef } from '@backstage/core-plugin-api'; import { Notification, - NotificationIds, NotificationStatus, NotificationType, } from '@backstage/plugin-notifications-common'; @@ -34,21 +33,21 @@ export type GetNotificationsOptions = { search?: string; }; +/** @public */ +export type UpdateNotificationsOptions = { + ids: string[]; + done?: boolean; + read?: boolean; + saved?: boolean; +}; + /** @public */ export interface NotificationsApi { getNotifications(options?: GetNotificationsOptions): Promise; getStatus(): Promise; - markDone(ids: string[]): Promise; - - markUndone(ids: string[]): Promise; - - markRead(ids: string[]): Promise; - - markUnread(ids: string[]): Promise; - - markSaved(ids: string[]): Promise; - - markUnsaved(ids: string[]): Promise; + updateNotifications( + options: UpdateNotificationsOptions, + ): Promise; } diff --git a/plugins/notifications/src/api/NotificationsClient.ts b/plugins/notifications/src/api/NotificationsClient.ts index a4398e4cb8..3dd5651ec5 100644 --- a/plugins/notifications/src/api/NotificationsClient.ts +++ b/plugins/notifications/src/api/NotificationsClient.ts @@ -13,12 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { GetNotificationsOptions, NotificationsApi } from './NotificationsApi'; +import { + GetNotificationsOptions, + NotificationsApi, + UpdateNotificationsOptions, +} from './NotificationsApi'; import { DiscoveryApi, FetchApi } from '@backstage/core-plugin-api'; import { ResponseError } from '@backstage/errors'; import { Notification, - NotificationIds, NotificationStatus, } from '@backstage/plugin-notifications-common'; @@ -61,50 +64,12 @@ export class NotificationsClient implements NotificationsApi { return await this.request('status'); } - async markDone(ids: string[]): Promise { - return await this.request('done', { + async updateNotifications( + options: UpdateNotificationsOptions, + ): Promise { + return await this.request('update', { method: 'POST', - body: JSON.stringify({ ids: ids }), - headers: { 'Content-Type': 'application/json' }, - }); - } - - async markUndone(ids: string[]): Promise { - return await this.request('undone', { - method: 'POST', - body: JSON.stringify({ ids: ids }), - headers: { 'Content-Type': 'application/json' }, - }); - } - - async markRead(ids: string[]): Promise { - return await this.request('read', { - method: 'POST', - body: JSON.stringify({ ids: ids }), - headers: { 'Content-Type': 'application/json' }, - }); - } - - async markUnread(ids: string[]): Promise { - return await this.request('unread', { - method: 'POST', - body: JSON.stringify({ ids: ids }), - headers: { 'Content-Type': 'application/json' }, - }); - } - - async markSaved(ids: string[]): Promise { - return await this.request('save', { - method: 'POST', - body: JSON.stringify({ ids: ids }), - headers: { 'Content-Type': 'application/json' }, - }); - } - - async markUnsaved(ids: string[]): Promise { - return await this.request('unsave', { - method: 'POST', - body: JSON.stringify({ ids: ids }), + body: JSON.stringify(options), headers: { 'Content-Type': 'application/json' }, }); } diff --git a/plugins/notifications/src/components/NotificationsTable/NotificationsTable.tsx b/plugins/notifications/src/components/NotificationsTable/NotificationsTable.tsx index 75d273bfc9..8328da1c6d 100644 --- a/plugins/notifications/src/components/NotificationsTable/NotificationsTable.tsx +++ b/plugins/notifications/src/components/NotificationsTable/NotificationsTable.tsx @@ -148,7 +148,7 @@ export const NotificationsTable = (props: { startIcon={} onClick={() => { notificationsApi - .markUndone(selected) + .updateNotifications({ ids: selected, done: false }) .then(() => props.onUpdate()); setSelected([]); }} @@ -162,7 +162,7 @@ export const NotificationsTable = (props: { startIcon={} onClick={() => { notificationsApi - .markDone(selected) + .updateNotifications({ ids: selected, done: true }) .then(() => props.onUpdate()); setSelected([]); }} @@ -197,16 +197,16 @@ export const NotificationsTable = (props: { notificationsApi - .markRead([notification.id]) - .then(() => navigate(notification.link)) + .updateNotifications({ ids: [notification.id], read: true }) + .then(() => navigate(notification.payload.link)) } style={{ paddingLeft: 0 }} > - {notification.title} + {notification.payload.title} - {notification.description} + {notification.payload.description} @@ -214,13 +214,16 @@ export const NotificationsTable = (props: { - + notificationsApi - .markRead([notification.id]) - .then(() => navigate(notification.link)) + .updateNotifications({ + ids: [notification.id], + read: true, + }) + .then(() => navigate(notification.payload.link)) } > @@ -234,13 +237,19 @@ export const NotificationsTable = (props: { onClick={() => { if (notification.read) { notificationsApi - .markUndone([notification.id]) + .updateNotifications({ + ids: [notification.id], + done: false, + }) .then(() => { props.onUpdate(); }); } else { notificationsApi - .markDone([notification.id]) + .updateNotifications({ + ids: [notification.id], + done: true, + }) .then(() => { props.onUpdate(); }); @@ -262,13 +271,19 @@ export const NotificationsTable = (props: { onClick={() => { if (notification.saved) { notificationsApi - .markUnsaved([notification.id]) + .updateNotifications({ + ids: [notification.id], + saved: false, + }) .then(() => { props.onUpdate(); }); } else { notificationsApi - .markSaved([notification.id]) + .updateNotifications({ + ids: [notification.id], + saved: true, + }) .then(() => { props.onUpdate(); });