import { RouterModule } from '@angular/router';
import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
+import { PopoverModule } from 'ngx-bootstrap/popover';
import { AppRoutingModule } from '../../app-routing.module';
import { SharedModule } from '../../shared/shared.module';
import { AuthModule } from '../auth/auth.module';
import { NavigationComponent } from './navigation/navigation.component';
+import { NotificationsComponent } from './notifications/notifications.component';
@NgModule({
imports: [
CommonModule,
AuthModule,
BsDropdownModule.forRoot(),
+ PopoverModule.forRoot(),
AppRoutingModule,
SharedModule,
RouterModule
],
- declarations: [NavigationComponent],
+ declarations: [NavigationComponent, NotificationsComponent],
exports: [NavigationComponent]
})
export class NavigationModule {}
<!-- /.navbar-primary -->
<ul class="nav navbar-nav navbar-utility">
+ <li>
+ <cd-notifications class="oa-navbar"></cd-notifications>
+ </li>
+
<li class="tc_logout">
<cd-logout class="oa-navbar"></cd-logout>
</li>
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
+import { PopoverModule } from 'ngx-bootstrap/popover';
+
+import { NotificationService } from '../../../shared/services/notification.service';
import { SharedModule } from '../../../shared/shared.module';
import { LogoutComponent } from '../../auth/logout/logout.component';
+import { NotificationsComponent } from '../notifications/notifications.component';
import { NavigationComponent } from './navigation.component';
describe('NavigationComponent', () => {
let component: NavigationComponent;
let fixture: ComponentFixture<NavigationComponent>;
- beforeEach(async(() => {
- TestBed.configureTestingModule({
- imports: [
- SharedModule,
- RouterTestingModule,
- HttpClientTestingModule
- ],
- declarations: [
- NavigationComponent,
- LogoutComponent
- ]
+ const fakeService = new NotificationService(null);
+
+ beforeEach(
+ async(() => {
+ TestBed.configureTestingModule({
+ imports: [
+ SharedModule,
+ RouterTestingModule,
+ HttpClientTestingModule,
+ PopoverModule.forRoot()
+ ],
+ declarations: [NavigationComponent, NotificationsComponent, LogoutComponent],
+ providers: [{ provide: NotificationService, useValue: fakeService }]
+ }).compileComponents();
})
- .compileComponents();
- }));
+ );
beforeEach(() => {
fixture = TestBed.createComponent(NavigationComponent);
--- /dev/null
+<ng-template #popTemplate>
+ <div *ngIf="notifications.length > 0">
+ <div class="separator">
+ Recent Notifications
+
+ <div *ngIf="notifications.length > 0"
+ class="pull-right">
+ <a (click)="removeAll()"
+ i18n>Remove all</a>
+ </div>
+ </div>
+ <hr>
+ <div *ngFor="let notification of notifications">
+ <table>
+ <tr>
+ <td rowspan="3" class="icon-col text-center">
+ <span [ngClass]="['fa-stack fa-2x', notification.textClass()]">
+ <i class="fa fa-circle fa-stack-2x"></i>
+ <i [ngClass]="['fa fa-stack-1x fa-inverse', notification.iconClass()]"></i>
+ </span>
+ </td>
+ <td>
+ <strong>{{ notification.title }}</strong>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ {{ notification.message }}
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <small class="date">{{ notification.timestamp | date: 'medium' }}</small>
+ </td>
+ </tr>
+ </table>
+ <hr>
+ </div>
+ </div>
+ <!-- Empty -->
+ <div *ngIf="notifications.length === 0">
+ <div class="message">
+ There are no notifications.
+ </div>
+ </div>
+</ng-template>
+<a [popover]="popTemplate"
+ placement="bottom"
+ container="body"
+ outsideClick="true">
+ <i class="fa fa-bell"></i>
+ <span i18n>Recent Notifications</span>
+</a>
--- /dev/null
+@import '../../../../styles/popover.scss';
+
+.icon-col {
+ width: 70px !important;
+}
--- /dev/null
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { PopoverModule } from 'ngx-bootstrap/popover';
+
+import { NotificationService } from '../../../shared/services/notification.service';
+import { NotificationsComponent } from './notifications.component';
+
+describe('NotificationsComponent', () => {
+ let component: NotificationsComponent;
+ let fixture: ComponentFixture<NotificationsComponent>;
+
+ const fakeService = new NotificationService(null);
+
+ beforeEach(
+ async(() => {
+ TestBed.configureTestingModule({
+ imports: [PopoverModule.forRoot()],
+ declarations: [NotificationsComponent],
+ providers: [{ provide: NotificationService, useValue: fakeService }]
+ }).compileComponents();
+ })
+ );
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(NotificationsComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
--- /dev/null
+import { Component, OnInit } from '@angular/core';
+
+import { NotificationType } from '../../../shared/enum/notification-type.enum';
+import { CdNotification } from '../../../shared/models/cd-notification';
+import { NotificationService } from '../../../shared/services/notification.service';
+
+@Component({
+ selector: 'cd-notifications',
+ templateUrl: './notifications.component.html',
+ styleUrls: ['./notifications.component.scss']
+})
+export class NotificationsComponent implements OnInit {
+ notifications: CdNotification[];
+ notificationType = NotificationType;
+
+ constructor(private notificationService: NotificationService) {
+ this.notifications = [];
+ }
+
+ ngOnInit() {
+ this.notificationService.data$.subscribe((notifications) => {
+ this.notifications = notifications;
+ });
+ }
+
+ removeAll () {
+ this.notificationService.removeAll();
+ }
+}
--- /dev/null
+::ng-deep .popover-content {
+ padding: 0px 0px;
+ height: auto;
+ max-height: 700px;
+ overflow-x: hidden;
+}
+
+::ng-deep .popover {
+ min-width: 276px !important;
+}
+
+.separator {
+ padding: 5px 12px;
+ color: #90949c;
+ background-color: #f6f7f9;
+ font-size: 12px;
+}
+
+.message {
+ padding: 10px 16px;
+ color: #474544;
+ font-size: 12px;
+}
+
+table {
+ width: 252px;
+ margin: 5px 12px 5px 5px;
+ font-size: 12px;
+ color: #474544;
+}
+
+.icon-col {
+ width: 20px;
+ font-size: 15px;
+}
+
+.date {
+ color: #777777;
+}
+
+hr {
+ margin-top: 0px;
+ margin-bottom: 0px;
+}