]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: Add notification service
authorTiago Melo <tmelo@suse.com>
Tue, 10 Apr 2018 14:55:44 +0000 (15:55 +0100)
committerTiago Melo <tmelo@suse.com>
Tue, 10 Apr 2018 15:07:26 +0000 (16:07 +0100)
This service should be used to display any notification/toast to the user.

Signed-off-by: Tiago Melo <tmelo@suse.com>
src/pybind/mgr/dashboard/frontend/src/app/shared/enum/notification-type.enum.ts [new file with mode: 0644]
src/pybind/mgr/dashboard/frontend/src/app/shared/models/cd-notification.ts [new file with mode: 0644]
src/pybind/mgr/dashboard/frontend/src/app/shared/services/notification.service.spec.ts [new file with mode: 0644]
src/pybind/mgr/dashboard/frontend/src/app/shared/services/notification.service.ts [new file with mode: 0644]
src/pybind/mgr/dashboard/frontend/src/app/shared/services/services.module.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 (file)
index 0000000..c82929f
--- /dev/null
@@ -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 (file)
index 0000000..f927488
--- /dev/null
@@ -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 (file)
index 0000000..768ec5e
--- /dev/null
@@ -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 (file)
index 0000000..4770890
--- /dev/null
@@ -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<CdNotification[]>([]);
+
+  // 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;
+    }
+  }
+}
index eb1a23d68408ee1e1f2a39e8f08bb90c9f9a2367..eddd3b02b479b05f449a4381598761ca2e308aa1 100644 (file)
@@ -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 {}