feat: support saving and marking notifications done

Signed-off-by: Heikki Hellgren <heikki.hellgren@op.fi>
This commit is contained in:
Heikki Hellgren
2023-12-15 16:13:57 +02:00
parent b3d70e2a4f
commit 49afb1823f
16 changed files with 431 additions and 56 deletions
@@ -19,6 +19,7 @@ import {
} from '@backstage/backend-common';
import {
NotificationGetOptions,
NotificationModifyOptions,
NotificationsStore,
} from './NotificationsStore';
import { Notification } from '@backstage/plugin-notifications-common';
@@ -55,7 +56,9 @@ export class DatabaseNotificationsStore implements NotificationsStore {
return typeof val === 'string' ? Number.parseInt(val, 10) : val ?? 0;
};
private getNotificationsBaseQuery = (options: NotificationGetOptions) => {
private getNotificationsBaseQuery = (
options: NotificationGetOptions | NotificationModifyOptions,
) => {
const { user_ref, type } = options;
const query = this.db('notifications').where('userRef', user_ref);
@@ -63,8 +66,14 @@ export class DatabaseNotificationsStore implements NotificationsStore {
query.whereNull('read');
} else if (type === 'read') {
query.whereNotNull('read');
} else if (type === 'saved') {
query.where('saved', true);
}
// TODO: Saved
if ('ids' in options && options.ids) {
query.whereIn('id', options.ids);
}
return query;
};
@@ -96,4 +105,24 @@ export class DatabaseNotificationsStore implements NotificationsStore {
read: this.mapToInteger((readQuery as any)?.READ),
};
}
async markRead(options: NotificationModifyOptions): Promise<void> {
const notificationQuery = this.getNotificationsBaseQuery(options);
await notificationQuery.update({ read: new Date() });
}
async markUnread(options: NotificationModifyOptions): Promise<void> {
const notificationQuery = this.getNotificationsBaseQuery(options);
await notificationQuery.update({ read: null });
}
async markSaved(options: NotificationModifyOptions): Promise<void> {
const notificationQuery = this.getNotificationsBaseQuery(options);
await notificationQuery.update({ saved: true });
}
async markUnsaved(options: NotificationModifyOptions): Promise<void> {
const notificationQuery = this.getNotificationsBaseQuery(options);
await notificationQuery.update({ saved: false });
}
}
@@ -26,6 +26,11 @@ export type NotificationGetOptions = {
type?: NotificationType;
};
/** @public */
export type NotificationModifyOptions = {
ids: string[];
} & NotificationGetOptions;
/** @public */
export interface NotificationsStore {
getNotifications(options: NotificationGetOptions): Promise<Notification[]>;
@@ -34,5 +39,11 @@ export interface NotificationsStore {
getStatus(options: NotificationGetOptions): Promise<NotificationStatus>;
// TODO: Mark as read/unread by notification id(s)
markRead(options: NotificationModifyOptions): Promise<void>;
markUnread(options: NotificationModifyOptions): Promise<void>;
markSaved(options: NotificationModifyOptions): Promise<void>;
markUnsaved(options: NotificationModifyOptions): Promise<void>;
}
@@ -36,6 +36,16 @@ export type NotificationServiceOptions = {
discovery: PluginEndpointDiscovery;
};
/** @public */
export type NotificationSendOptions = {
entityRef: string | string[];
title: string;
description: string;
link: string;
image?: string;
icon?: string;
};
/** @public */
export class NotificationService {
private store: NotificationsStore | null = null;
@@ -56,12 +66,8 @@ export class NotificationService {
return new NotificationService(database, catalogClient);
}
async send(
entityRef: string | string[],
title: string,
description: string,
link: string,
): Promise<Notification[]> {
async send(options: NotificationSendOptions): Promise<Notification[]> {
const { entityRef, title, description, link, icon, image } = options;
const users = await this.getUsersForEntityRef(entityRef);
const notifications = [];
const store = await this.getStore();
@@ -73,6 +79,9 @@ export class NotificationService {
description,
link,
created: new Date(),
icon,
image,
saved: false,
};
await store.saveNotification(notification);