Skip to content

Commit

Permalink
feat(notifications): added notify, notifyAll API
Browse files Browse the repository at this point in the history
  • Loading branch information
xmlking committed Nov 23, 2018
1 parent 74b19c4 commit 8189e5d
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 10 deletions.
5 changes: 5 additions & 0 deletions apps/api/src/app/push/dto/send-notification.dto.ts
Expand Up @@ -7,6 +7,11 @@ export class SendNotificationDto {
@IsString()
id: string;

@ApiModelProperty({ type: String })
@IsNotEmpty()
@IsString()
title: string;

@ApiModelProperty({ type: String })
@IsNotEmpty()
@IsString()
Expand Down
19 changes: 19 additions & 0 deletions apps/api/src/app/push/dto/send-topic-notification.dto.ts
@@ -0,0 +1,19 @@
import { ApiModelProperty } from '@nestjs/swagger';
import { IsNotEmpty, IsString } from 'class-validator';

export class SendTopicNotificationDto {
@ApiModelProperty({ type: String })
@IsNotEmpty()
@IsString()
topic: string;

@ApiModelProperty({ type: String })
@IsNotEmpty()
@IsString()
title: string;

@ApiModelProperty({ type: String })
@IsNotEmpty()
@IsString()
body: string;
}
25 changes: 24 additions & 1 deletion apps/api/src/app/push/push.controller.ts
Expand Up @@ -7,6 +7,7 @@ import { PushService } from './push.service';
import { CreateSubscriptionDto } from './dto/create-subscription.dto';
import { UpdateSubscriptionDto } from './dto/update-subscription.dto';
import { SendNotificationDto } from './dto/send-notification.dto';
import { SendTopicNotificationDto } from './dto/send-topic-notification.dto';

@ApiOAuth2Auth(['read'])
@ApiUseTags('Sumo', 'Push')
Expand Down Expand Up @@ -80,7 +81,7 @@ export class PushController extends CrudController<Subscription> {
@Post('notify')
notify(@Body() notif: SendNotificationDto) {
const notification = {
title: 'NGX WebApp Notification',
title: notif.title,
body: notif.body,
icon: 'assets/icons/icon-72x72.png',
data: {
Expand All @@ -89,4 +90,26 @@ export class PushController extends CrudController<Subscription> {
};
return this.pushService.notify(notif.id, notification as any);
}

@ApiOperation({ title: 'Send Push Notifications to all subscribers to a topic' })
@ApiResponse({
status: HttpStatus.CREATED,
description: 'Push Notifications has been successfully sent.',
})
@ApiResponse({
status: HttpStatus.BAD_REQUEST,
description: 'Invalid input, The response body may contain clues as to what went wrong',
})
@Post('notifyAll')
notifyAll(@Body() notif: SendTopicNotificationDto) {
const notification = {
title: notif.title,
body: notif.body,
icon: 'assets/icons/icon-72x72.png',
data: {
click_url: '/dashboard',
},
};
return this.pushService.notifyAll(notif.topic, notification as any);
}
}
14 changes: 13 additions & 1 deletion apps/api/src/app/push/push.service.ts
Expand Up @@ -2,7 +2,7 @@ import { BadRequestException, Injectable, Logger } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { PushSubscription, sendNotification, setVapidDetails, WebPushError } from 'web-push';
import { CrudService } from '../core';
import { FindConditions, Repository } from 'typeorm';
import { Any, FindConditions, Repository } from 'typeorm';
import { Subscription } from './subscription.entity';
import { environment as env } from '@env-api/environment';

Expand Down Expand Up @@ -31,6 +31,18 @@ export class PushService extends CrudService<Subscription> {
return this._sendNotification({ endpoint, keys: { p256dh, auth } }, notification);
}

async notifyAll(topic: string, notification: Notification) {
// FIXME: https://github.com/typeorm/typeorm/issues/3150
const subscriptions = await this.findAndCount({ topics: Any([topic]) } );
// console.log(subscriptions);
if (subscriptions[1] > 0) {
subscriptions[0].forEach( sub => {
const { endpoint, p256dh, auth } = sub;
this._sendNotification({ endpoint, keys: { p256dh, auth } }, notification);
});
}
}

private async _sendNotification(subscription: PushSubscription, notification: Notification) {
try {
await sendNotification(subscription, JSON.stringify({ notification }));
Expand Down
20 changes: 12 additions & 8 deletions libs/core/src/lib/services/push-notification.service.ts
Expand Up @@ -13,14 +13,7 @@ export class PushNotificationService {
private readonly entityPath = 'push';
private readonly existingSubscription: PushSubscription;

constructor(private readonly swPush: SwPush, private httpClient: HttpClient) {
if (this.swPush.isEnabled) {
// subscribe for new messages for testing
this.swPush.messages.subscribe(message => {
console.log('received push notification', message);
});
}
}
constructor(private readonly swPush: SwPush, private httpClient: HttpClient) {}

async register() {
if (!this.swPush.isEnabled) {
Expand Down Expand Up @@ -60,6 +53,17 @@ export class PushNotificationService {
}
}

async notify(id: string) {
await this.httpClient
.post(`${this.baseUrl}/${this.entityPath}/notify`, {
id: encodeURIComponent(id),
title: 'NGX WebApp Notification',
body: 'test body 321',
})
.pipe(catchError(this.handleError))
.toPromise();
}

private handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
// A client-side or network error occurred. Handle it accordingly.
Expand Down
9 changes: 9 additions & 0 deletions libs/core/src/lib/state/eventbus.ts
@@ -1,5 +1,6 @@
import { Actions, ofActionErrored, ofActionSuccessful, Store } from '@ngxs/store';
import { Inject, Injectable, Renderer2, RendererFactory2 } from '@angular/core';
import { SwPush } from '@angular/service-worker';
import { Login, LoginSuccess } from '@ngx-starter-kit/auth';
import {
AuthenticateWebSocket,
Expand All @@ -25,6 +26,7 @@ export class EventBus {
private actions$: Actions,
private store: Store,
private router: Router,
private readonly swPush: SwPush,
private analytics: GoogleAnalyticsService,
private pageTitle: PageTitleService,
private rendererFactory: RendererFactory2,
Expand Down Expand Up @@ -67,6 +69,13 @@ export class EventBus {
});
}

if (this.swPush.isEnabled) {
// subscribe for new messages for testing
this.swPush.messages.subscribe(message => {
console.log('received push notification', message);
});
}

this.actions$.pipe(ofActionSuccessful(Login)).subscribe(action => console.log('Login........Action Successful'));
this.actions$.pipe(ofActionErrored(Login)).subscribe(action => console.log('Login........Action Errored'));
this.actions$.pipe(ofActionSuccessful(LoginSuccess)).subscribe((action: LoginSuccess) => {
Expand Down

0 comments on commit 8189e5d

Please sign in to comment.