From 89101061d014e37a4bbc18b4c294eff8b49408ff Mon Sep 17 00:00:00 2001 From: Tiago Melo Date: Tue, 10 Apr 2018 15:55:44 +0100 Subject: [PATCH] mgr/dashboard: Add notification service This service should be used to display any notification/toast to the user. Signed-off-by: Tiago Melo --- .../app/shared/enum/notification-type.enum.ts | 5 ++ .../src/app/shared/models/cd-notification.ts | 40 +++++++++ .../services/notification.service.spec.ts | 17 ++++ .../shared/services/notification.service.ts | 85 +++++++++++++++++++ .../app/shared/services/services.module.ts | 4 +- 5 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/shared/enum/notification-type.enum.ts create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/shared/models/cd-notification.ts create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/shared/services/notification.service.spec.ts create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/shared/services/notification.service.ts diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/enum/notification-type.enum.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/enum/notification-type.enum.ts new file mode 100644 index 00000000000..c82929fb51f --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/enum/notification-type.enum.ts @@ -0,0 +1,5 @@ +export enum NotificationType { + error, + info, + success +} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/models/cd-notification.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/cd-notification.ts new file mode 100644 index 00000000000..f9274889e04 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/cd-notification.ts @@ -0,0 +1,40 @@ +import { NotificationType } from '../enum/notification-type.enum'; + +export class CdNotification { + message: string; + timestamp: string; + title: string; + type: NotificationType; + + constructor(type: NotificationType = NotificationType.info, message?: string, title?: string) { + this.type = type; + this.message = message; + this.title = title; + + /* string representation of the Date object so it can be directly compared + with the timestamps parsed from localStorage */ + this.timestamp = new Date().toJSON(); + } + + textClass() { + switch (this.type) { + case NotificationType.error: + return 'text-danger'; + case NotificationType.info: + return 'text-info'; + case NotificationType.success: + return 'text-success'; + } + } + + iconClass() { + switch (this.type) { + case NotificationType.error: + return 'fa-exclamation-triangle'; + case NotificationType.info: + return 'text-info'; + case NotificationType.success: + return 'fa-check'; + } + } +} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/notification.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/notification.service.spec.ts new file mode 100644 index 00000000000..768ec5e130a --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/notification.service.spec.ts @@ -0,0 +1,17 @@ +import { inject, TestBed } from '@angular/core/testing'; + +import { ToastOptions, ToastsManager } from 'ng2-toastr'; + +import { NotificationService } from './notification.service'; + +describe('NotificationService', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [NotificationService, ToastsManager, ToastOptions] + }); + }); + + it('should be created', inject([NotificationService], (service: NotificationService) => { + expect(service).toBeTruthy(); + })); +}); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/notification.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/notification.service.ts new file mode 100644 index 00000000000..4770890b07b --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/notification.service.ts @@ -0,0 +1,85 @@ +import { Injectable } from '@angular/core'; + +import * as _ from 'lodash'; +import { ToastsManager } from 'ng2-toastr'; +import { BehaviorSubject } from 'rxjs/BehaviorSubject'; + +import { NotificationType } from '../enum/notification-type.enum'; +import { CdNotification } from '../models/cd-notification'; + +@Injectable() +export class NotificationService { + // Observable sources + private dataSource = new BehaviorSubject([]); + + // Observable streams + data$ = this.dataSource.asObservable(); + + KEY = 'cdNotifications'; + + constructor(public toastr: ToastsManager) { + const stringNotifications = localStorage.getItem(this.KEY); + let notifications: CdNotification[] = []; + + if (_.isString(stringNotifications)) { + notifications = JSON.parse(stringNotifications, (key, value) => { + if (_.isPlainObject(value)) { + return _.assign(new CdNotification(), value); + } + return value; + }); + } + + this.dataSource.next(notifications); + } + + /** + * Removes all current saved notifications + */ + removeAll() { + localStorage.removeItem(this.KEY); + this.dataSource.next([]); + } + + /** + * Method used for saving a shown notification (check show() method). + * @param {Notification} notification + */ + save(type: NotificationType, message: string, title?: string) { + const notification = new CdNotification(type, message, title); + + const recent = this.dataSource.getValue(); + recent.push(notification); + while (recent.length > 10) { + recent.shift(); + } + + this.dataSource.next(recent); + localStorage.setItem(this.KEY, JSON.stringify(recent)); + } + + /** + * Method for showing a notification. + * + * @param {NotificationType} type toastr type + * @param {string} message + * @param {string} [title] + * @param {*} [options] toastr compatible options, used when creating a toastr + * @memberof NotificationService + */ + show(type: NotificationType, message: string, title?: string, options?: any) { + this.save(type, message, title); + + switch (type) { + case NotificationType.error: + this.toastr.error(message, title, options); + break; + case NotificationType.info: + this.toastr.info(message, title, options); + break; + case NotificationType.success: + this.toastr.success(message, title, options); + break; + } + } +} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/services.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/services.module.ts index eb1a23d6840..eddd3b02b47 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/services.module.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/services.module.ts @@ -4,6 +4,7 @@ import { NgModule } from '@angular/core'; import { AuthGuardService } from './auth-guard.service'; import { AuthStorageService } from './auth-storage.service'; import { FormatterService } from './formatter.service'; +import { NotificationService } from './notification.service'; import { SummaryService } from './summary.service'; @NgModule({ @@ -13,7 +14,8 @@ import { SummaryService } from './summary.service'; AuthGuardService, AuthStorageService, FormatterService, - SummaryService + SummaryService, + NotificationService ] }) export class ServicesModule {} -- 2.39.5