From e4ba0480fe68374a63f301d87c763712e252a568 Mon Sep 17 00:00:00 2001 From: Michael Beckemeyer Date: Tue, 19 Nov 2024 16:52:32 +0100 Subject: [PATCH] Add convenience methods to Notifier (#76, #77) Co-authored-by: Antonia van Eek --- .changeset/many-snails-hang.md | 13 +++ .../notifier/NotificationServiceImpl.test.ts | 92 ++++++++++++++++++- .../notifier/NotificationServiceImpl.ts | 30 +++++- src/packages/notifier/api.ts | 21 +++++ 4 files changed, 152 insertions(+), 4 deletions(-) create mode 100644 .changeset/many-snails-hang.md diff --git a/.changeset/many-snails-hang.md b/.changeset/many-snails-hang.md new file mode 100644 index 00000000..92c2d156 --- /dev/null +++ b/.changeset/many-snails-hang.md @@ -0,0 +1,13 @@ +--- +"@open-pioneer/notifier": minor +--- + +Introduce new convenience methods on the `NotificationService` in addition to the existing `notify()` method: + +```js +const notifier = ...; // injected +notifier.success(/* ... */) +notifier.info(/* ... */) +notifier.warning(/* ... */) +notifier.error(/* ... */) +``` diff --git a/src/packages/notifier/NotificationServiceImpl.test.ts b/src/packages/notifier/NotificationServiceImpl.test.ts index 0b408ad1..a2127cde 100644 --- a/src/packages/notifier/NotificationServiceImpl.test.ts +++ b/src/packages/notifier/NotificationServiceImpl.test.ts @@ -6,9 +6,7 @@ import { NotificationServiceImpl, Notification } from "./NotificationServiceImpl it("dispatches events to the notification handler", async () => { const service = await createService(NotificationServiceImpl, {}); - const events: unknown[] = []; - const handlerResource = service.registerHandler({ showNotification(notification: Notification) { events.push({ type: "notification", notification: notification }); @@ -51,11 +49,99 @@ it("dispatches events to the notification handler", async () => { expect(events).toHaveLength(0); }); -it("dispatches events to a later registered notification handler", async () => { +it("dispatches events with convenience methods with object parameter", async () => { const service = await createService(NotificationServiceImpl, {}); + const events: unknown[] = []; + service.registerHandler({ + showNotification(notification: Notification) { + events.push(notification); + }, + closeAll() {} + }); + + service.success({ title: "test1" }); + service.info({ title: "test2" }); + service.warning({ title: "test3" }); + service.error({ title: "test4" }); + + expect(events).toMatchInlineSnapshot(` + [ + { + "displayDuration": undefined, + "level": "success", + "message": undefined, + "title": "test1", + }, + { + "displayDuration": undefined, + "level": "info", + "message": undefined, + "title": "test2", + }, + { + "displayDuration": undefined, + "level": "warning", + "message": undefined, + "title": "test3", + }, + { + "displayDuration": undefined, + "level": "error", + "message": undefined, + "title": "test4", + }, + ] + `); +}); +it("dispatches events with convenience methods with string parameter", async () => { + const service = await createService(NotificationServiceImpl, {}); const events: unknown[] = []; + service.registerHandler({ + showNotification(notification: Notification) { + events.push(notification); + }, + closeAll() {} + }); + + service.success("test1"); + service.info("test2"); + service.warning("test3"); + service.error("test4"); + expect(events).toMatchInlineSnapshot(` + [ + { + "displayDuration": undefined, + "level": "success", + "message": "test1", + "title": undefined, + }, + { + "displayDuration": undefined, + "level": "info", + "message": "test2", + "title": undefined, + }, + { + "displayDuration": undefined, + "level": "warning", + "message": "test3", + "title": undefined, + }, + { + "displayDuration": undefined, + "level": "error", + "message": "test4", + "title": undefined, + }, + ] + `); +}); + +it("dispatches events to a later registered notification handler", async () => { + const service = await createService(NotificationServiceImpl, {}); + const events: unknown[] = []; service.notify({ title: "test" }); service.closeAll(); service.notify({ title: "test2" }); diff --git a/src/packages/notifier/NotificationServiceImpl.ts b/src/packages/notifier/NotificationServiceImpl.ts index 64ab9d85..58f67579 100644 --- a/src/packages/notifier/NotificationServiceImpl.ts +++ b/src/packages/notifier/NotificationServiceImpl.ts @@ -1,6 +1,11 @@ // SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer) // SPDX-License-Identifier: Apache-2.0 -import type { NotificationLevel, NotificationOptions, NotificationService } from "./api"; +import type { + NotificationLevel, + NotificationOptions, + NotificationService, + SimpleNotificationOptions +} from "./api"; import { Resource, createLogger } from "@open-pioneer/core"; import type { ReactNode } from "react"; const LOG = createLogger("notifier:NotificationService"); @@ -62,6 +67,29 @@ export class NotificationServiceImpl implements InternalNotificationAPI { }); } + success(options: SimpleNotificationOptions): void { + this.#sendSimpleNotification("success", options); + } + + info(options: SimpleNotificationOptions): void { + this.#sendSimpleNotification("info", options); + } + + warning(options: SimpleNotificationOptions): void { + this.#sendSimpleNotification("warning", options); + } + + error(options: SimpleNotificationOptions): void { + this.#sendSimpleNotification("error", options); + } + + #sendSimpleNotification(level: NotificationLevel, options: SimpleNotificationOptions): void { + if (typeof options === "string") { + options = { message: options }; + } + this.notify({ ...options, level }); + } + closeAll(): void { this.#dispatchHandlerMethod("closeAll"); } diff --git a/src/packages/notifier/api.ts b/src/packages/notifier/api.ts index 6c58ae3d..a74eeaa8 100644 --- a/src/packages/notifier/api.ts +++ b/src/packages/notifier/api.ts @@ -31,6 +31,15 @@ export interface NotificationOptions { displayDuration?: number | undefined; } +/** + * Options used when emitting a new notification via {@link NotificationService} + * using convenience methods like `warning` and `error`. + * + * Options can either be an object that is the same as {@link NotificationOptions}, but without the `level` property + * or a string, which will be used as the `message` of the Notification. + */ +export type SimpleNotificationOptions = Omit | string; + /** * The `NotificationService` allows any part of the application to emit * notifications to the user. @@ -48,6 +57,18 @@ export interface NotificationService extends DeclaredService<"notifier.Notificat */ notify(options: NotificationOptions): void; + /** Emits a success notification. Same as {@link notify} with `type: "success"`. */ + success(options: SimpleNotificationOptions): void; + + /** Emits an info notification. Same as {@link notify} with `type: "info"`. */ + info(options: SimpleNotificationOptions): void; + + /** Emits a warning notification. Same as {@link notify} with `type: "warning"`. */ + warning(options: SimpleNotificationOptions): void; + + /** Emits an error notification. Same as {@link notify} with `type: "error"`. */ + error(options: SimpleNotificationOptions): void; + /** Closes all active notifications. */ closeAll(): void; }