Skip to content

Commit

Permalink
chore(web-ui): send notification subscription to backend (#894)
Browse files Browse the repository at this point in the history
* chore(web-ui): send notification subscription to backend

* refactor(web-ui): use vapid key from backend

* feat(api): add endpoint to save subscription

---------

Co-authored-by: Johan Book <{ID}+{username}@users.noreply.github.com>
  • Loading branch information
johanbook and Johan Book authored Jul 19, 2024
1 parent e126a0d commit 78e77d9
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import {
IsNumber,
IsOptional,
IsString,
IsUrl,
ValidateNested,
} from "class-validator";

import { NotificationSubscriptionKeysDetails } from "../dtos/notification-subscription-keys.dto";

export class SaveNotificationSubscriptionCommand {
@IsUrl()
@IsString()
endpoint?: string;

@IsOptional()
@IsNumber()
expirationTime?: number | null;

@ValidateNested()
keys?: NotificationSubscriptionKeysDetails;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { IsString } from "class-validator";

export class NotificationSubscriptionKeysDetails {
@IsString()
auth!: string;

@IsString()
p256dh!: string;
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import {
Body,
Controller,
Get,
NotImplementedException,
Post,
Query,
} from "@nestjs/common";
import { QueryBus } from "@nestjs/cqrs";
import { CommandBus, QueryBus } from "@nestjs/cqrs";
import { ApiTags } from "@nestjs/swagger";

import { map } from "src/core/mapper";
import { getRequiredStringConfig } from "src/utils/config.helper";

import { SaveNotificationSubscriptionCommand } from "../../application/contracts/commands/save-notification-subscription.command";
import { NotificationMetaDetails } from "../../application/contracts/dtos/notification-meta.dto";
import { NotificationDetails } from "../../application/contracts/dtos/notification.dto";
import { VapidDetails } from "../../application/contracts/dtos/vapid.dto";
Expand All @@ -18,7 +21,7 @@ import { GetNotificationListQuery } from "../../application/contracts/queries/ge
@Controller("notifications")
@ApiTags("notifications")
export class NotificationsController {
constructor(private queryBus: QueryBus) {}
constructor(private commandBus: CommandBus, private queryBus: QueryBus) {}

@Get()
async getNotifactions(
Expand All @@ -32,6 +35,13 @@ export class NotificationsController {
throw new NotImplementedException();
}

@Post("subscription")
async saveSubscription(
@Body() command: SaveNotificationSubscriptionCommand,
): Promise<void> {
return await this.commandBus.execute(command);
}

@Get("vapid")
getVapid(): VapidDetails {
return map(VapidDetails, {
Expand Down
3 changes: 2 additions & 1 deletion services/web-ui/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { registerWebVitalsReporter } from "src/core/web-vitals";

import { App } from "./App";
import { config } from "./config";
import { registerServiceWorker } from "./registerServiceWorker";

registerI18n();
registerExceptionLogger();
Expand All @@ -27,5 +28,5 @@ if (config.MONITORING.REPORT_WEB_VITALS) {
}

if ("serviceWorker" in navigator) {
navigator.serviceWorker.register("service-worker.js");
registerServiceWorker();
}
29 changes: 29 additions & 0 deletions services/web-ui/src/registerServiceWorker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { notificationsApi } from "./apis";

const SERVICE_WORKER_PATH = "service-worker.js";

export async function registerServiceWorker() {
const registration = await navigator.serviceWorker.register(
SERVICE_WORKER_PATH
);

let subscription = await registration.pushManager.getSubscription();

if (!subscription) {
await Notification.requestPermission();

const vapid = await notificationsApi.getVapid();

subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: vapid.key,
});
}

const saveNotificationSubscriptionCommand = subscription.toJSON();

await notificationsApi.saveSubscription({
// @ts-expect-error // TODO: Fix this type
saveNotificationSubscriptionCommand,
});
}

0 comments on commit 78e77d9

Please sign in to comment.