mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[AAE-4529] Refactor Notification History Component (#6620)
* [AAE-4529] Refactor Notification History Component * Improve code * Add maxNotifications * More changes * Add documentation * Rebase branch * Fix build * Update notification-history.component.md * Fix e2e tests Co-authored-by: Eugenio Romano <eromano@users.noreply.github.com>
This commit is contained in:
@@ -6,10 +6,11 @@
|
||||
"UNCLAIM": "RELEASE",
|
||||
"START PROCESS": "START PROCESS",
|
||||
"NOTIFICATIONS": {
|
||||
"NO_MESSAGE": "No messages",
|
||||
"NO_MESSAGE": "You have no notifications at this time.",
|
||||
"TITLE": "Notifications",
|
||||
"MARK_AS_READ": "Mark all as read",
|
||||
"SYSTEM": "System"
|
||||
"SYSTEM": "System",
|
||||
"LOAD_MORE": "Load more"
|
||||
},
|
||||
"FORM": {
|
||||
"START_FORM": {
|
||||
|
@@ -43,6 +43,7 @@ import { MatTableModule } from '@angular/material/table';
|
||||
import { MatTabsModule } from '@angular/material/tabs';
|
||||
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { MatBadgeModule } from '@angular/material/badge';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@@ -51,7 +52,7 @@ import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
MatInputModule, MatListModule, MatNativeDateModule, MatOptionModule, MatProgressSpinnerModule, MatRadioModule,
|
||||
MatRippleModule, MatSelectModule, MatSlideToggleModule, MatTableModule, MatTabsModule,
|
||||
MatMenuModule, MatProgressBarModule, MatSidenavModule, MatSnackBarModule, MatToolbarModule,
|
||||
MatTooltipModule, MatDatetimepickerModule, MatNativeDatetimeModule, MatExpansionModule
|
||||
MatTooltipModule, MatDatetimepickerModule, MatNativeDatetimeModule, MatExpansionModule, MatBadgeModule
|
||||
],
|
||||
exports: [
|
||||
MatAutocompleteModule, MatButtonModule, MatCardModule, MatCheckboxModule,
|
||||
@@ -59,7 +60,7 @@ import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
MatInputModule, MatListModule, MatNativeDateModule, MatOptionModule, MatProgressSpinnerModule, MatRadioModule,
|
||||
MatRippleModule, MatSelectModule, MatSlideToggleModule, MatTableModule, MatTabsModule,
|
||||
MatMenuModule, MatProgressBarModule, MatSidenavModule, MatSnackBarModule, MatToolbarModule,
|
||||
MatTooltipModule, MatDatetimepickerModule, MatNativeDatetimeModule, MatExpansionModule
|
||||
MatTooltipModule, MatDatetimepickerModule, MatNativeDatetimeModule, MatExpansionModule, MatBadgeModule
|
||||
]
|
||||
})
|
||||
export class MaterialModule {}
|
||||
|
@@ -1,34 +1,73 @@
|
||||
<div (keyup)="onKeyPress($event)">
|
||||
<button mat-button [matMenuTriggerFor]="menu" class="adf-notification-history-menu_button"
|
||||
id="adf-notification-history-open-button">
|
||||
<mat-icon>mail_outline</mat-icon>
|
||||
<button mat-button
|
||||
[matMenuTriggerFor]="menu"
|
||||
class="adf-notification-history-menu_button"
|
||||
id="adf-notification-history-open-button"
|
||||
(menuOpened)="onMenuOpened()">
|
||||
<mat-icon matBadge="⁠"
|
||||
[matBadgeHidden]="!notifications.length"
|
||||
matBadgeColor="accent"
|
||||
matBadgeSize="small">notifications</mat-icon>
|
||||
</button>
|
||||
<mat-menu #menu="matMenu" [xPosition]="menuPositionX" [yPosition]="menuPositionY"
|
||||
[overlapTrigger]="false" id="adf-notification-history-menu" class="adf-notification-history-menu">
|
||||
<mat-menu #menu="matMenu"
|
||||
[xPosition]="menuPositionX"
|
||||
[yPosition]="menuPositionY"
|
||||
id="adf-notification-history-menu"
|
||||
class="adf-notification-history-menu">
|
||||
|
||||
<div class="adf-notification-history-list"
|
||||
(click)="$event.stopPropagation()">
|
||||
<div mat-subheader>
|
||||
<span>{{ 'NOTIFICATIONS.TITLE' | translate }}</span>
|
||||
<button (click)="markAsRead()"
|
||||
id="adf-notification-history-mark-as-read"
|
||||
mat-button
|
||||
color="accent"
|
||||
*ngIf="notifications.length">
|
||||
{{ 'NOTIFICATIONS.MARK_AS_READ' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div id="adf-notification-history-list">
|
||||
<mat-list>
|
||||
<mat-list-item>
|
||||
<h6 mat-line>{{ 'NOTIFICATIONS.TITLE' | translate }}</h6>
|
||||
</mat-list-item>
|
||||
</mat-list>
|
||||
<mat-divider></mat-divider>
|
||||
|
||||
<mat-list>
|
||||
<mat-list-item *ngFor="let notification of notifications">
|
||||
<mat-icon mat-list-icon>{{ notification | noticicationIcon }}</mat-icon>
|
||||
<h4 *ngFor="let message of notification.messages" mat-line>{{ message }}</h4>
|
||||
<p mat-line> {{notification.datetime | date}} </p>
|
||||
<p mat-line> {{notification.initiator.displayName | translate}} </p>
|
||||
</mat-list-item>
|
||||
<mat-list-item *ngIf="isEmptyNotification()" id="adf-notification-history-component-no-message">
|
||||
<h4 mat-line>{{ 'NOTIFICATIONS.NO_MESSAGE' | translate }}</h4>
|
||||
</mat-list-item>
|
||||
<mat-action-list *ngIf="!isEmptyNotification()" id="adf-notification-history-mark-as-read">
|
||||
<button mat-list-item (click)="markAsRead()">{{ 'NOTIFICATIONS.MARK_AS_READ' | translate }}
|
||||
</button>
|
||||
</mat-action-list>
|
||||
<ng-container *ngIf="notifications.length; else empty_list_template">
|
||||
<mat-list-item *ngFor="let notification of paginatedNotifications"
|
||||
class="adf-notification-history-menu-item"
|
||||
(click)="onNotificationClick(notification)">
|
||||
<div *ngIf="notification.initiator; else no_avatar"
|
||||
matListAvatar
|
||||
[outerHTML]="notification.initiator | usernameInitials:'adf-notification-initiator-pic'">
|
||||
</div>
|
||||
<ng-template #no_avatar>
|
||||
<mat-icon mat-list-icon
|
||||
class="adf-notification-history-menu-initiator">{{ notification | notificationIcon
|
||||
}}</mat-icon>
|
||||
</ng-template>
|
||||
<p class="adf-notification-history-menu-message"
|
||||
*ngFor="let message of notification.messages"
|
||||
mat-line>{{ message }}</p>
|
||||
<p class="adf-notification-history-menu-date"
|
||||
mat-line> {{notification.datetime | adfTimeAgo}} </p>
|
||||
</mat-list-item>
|
||||
</ng-container>
|
||||
<ng-template #empty_list_template>
|
||||
<mat-list-item id="adf-notification-history-component-no-message"
|
||||
class="adf-notification-history-menu-no-message">
|
||||
<h4 mat-line>{{ 'NOTIFICATIONS.NO_MESSAGE' | translate }}</h4>
|
||||
</mat-list-item>
|
||||
</ng-template>
|
||||
</mat-list>
|
||||
|
||||
<mat-divider></mat-divider>
|
||||
|
||||
<div class="adf-notification-history-load-more"
|
||||
*ngIf="hasMoreNotifications()">
|
||||
<button mat-button
|
||||
(click)="loadMore()">
|
||||
{{ 'NOTIFICATIONS.LOAD_MORE' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</mat-menu>
|
||||
</div>
|
||||
|
@@ -1,23 +1,76 @@
|
||||
.adf {
|
||||
@mixin adf-notification-history-theme($theme) {
|
||||
$background: map-get($theme, background);
|
||||
$accent: map-get($theme, accent);
|
||||
|
||||
&-notification-history-menu_button.mat-button {
|
||||
margin-right: 0;
|
||||
border-radius: 90%;
|
||||
padding: 0;
|
||||
min-width: 40px;
|
||||
height: 40px;
|
||||
.adf {
|
||||
&-notification-history-menu_button.mat-button {
|
||||
margin-right: 0;
|
||||
border-radius: 90%;
|
||||
padding: 0;
|
||||
min-width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
&-notification-history-list .mat-subheader {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
&-notification-history-menu {
|
||||
&-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&-item:focus {
|
||||
outline: none;
|
||||
background: mat-color($background, 'hover');
|
||||
}
|
||||
|
||||
&-item:hover {
|
||||
background-color: mat-color($background, 'hover');
|
||||
}
|
||||
|
||||
&-message, &-no-message {
|
||||
font-size: 13px !important;
|
||||
}
|
||||
|
||||
&-date {
|
||||
font-size: 12px !important;
|
||||
}
|
||||
|
||||
&-initiator {
|
||||
margin: 4px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
&-notification-initiator-pic {
|
||||
min-width: 40px;
|
||||
background: mat-color($accent);
|
||||
display: inline-block;
|
||||
height: 40px;
|
||||
border-radius: 100px;
|
||||
text-align: center;
|
||||
font-weight: bolder;
|
||||
font-size: 18px;
|
||||
text-transform: uppercase;
|
||||
vertical-align: middle;
|
||||
line-height: 40px;
|
||||
color: mat-color($mat-grey, 50);
|
||||
}
|
||||
|
||||
&-notification-history-load-more {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-device-width: 480px) {
|
||||
.mat-menu-panel.adf-notification-history-menu {
|
||||
max-height: 450px;
|
||||
min-width: 450px;
|
||||
overflow: auto;
|
||||
padding: 0;
|
||||
min-width: 320px;
|
||||
max-height: 500px;
|
||||
|
||||
.mat-menu-content {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.mat-menu-panel.adf-notification-history-menu .mat-menu-content {
|
||||
padding: 0;
|
||||
}
|
||||
|
@@ -23,10 +23,12 @@ import { OverlayContainer } from '@angular/cdk/overlay';
|
||||
import { NotificationService } from '../services/notification.service';
|
||||
import { StorageService } from '../../services/storage.service';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { NotificationModel, NOTIFICATION_TYPE } from '../models/notification.model';
|
||||
|
||||
describe('Notification History Component', () => {
|
||||
|
||||
let fixture: ComponentFixture<NotificationHistoryComponent>;
|
||||
let component: NotificationHistoryComponent;
|
||||
let element: HTMLElement;
|
||||
let notificationService: NotificationService;
|
||||
let overlayContainerElement: HTMLElement;
|
||||
@@ -48,10 +50,12 @@ describe('Notification History Component', () => {
|
||||
|
||||
beforeEach(async(() => {
|
||||
fixture = TestBed.createComponent(NotificationHistoryComponent);
|
||||
component = fixture.componentInstance;
|
||||
element = fixture.nativeElement;
|
||||
|
||||
storage = TestBed.inject(StorageService);
|
||||
notificationService = TestBed.inject(NotificationService);
|
||||
component.notifications = [];
|
||||
}));
|
||||
|
||||
beforeEach(inject([OverlayContainer], (oc: OverlayContainer) => {
|
||||
@@ -59,6 +63,7 @@ describe('Notification History Component', () => {
|
||||
}));
|
||||
|
||||
afterEach(() => {
|
||||
storage.removeItem('notifications');
|
||||
fixture.destroy();
|
||||
});
|
||||
|
||||
@@ -73,27 +78,110 @@ describe('Notification History Component', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should message be present and empty message not be present when there are notifications in the history', (done) => {
|
||||
it('should remove notification when mark all as read is clicked', (done) => {
|
||||
fixture.detectChanges();
|
||||
notificationService.showInfo('Example Message Removed');
|
||||
openNotification();
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
expect(component.notifications.length).toBe(1);
|
||||
const markAllAsRead = <HTMLButtonElement> overlayContainerElement.querySelector('#adf-notification-history-mark-as-read');
|
||||
markAllAsRead.click();
|
||||
fixture.detectChanges();
|
||||
expect(storage.getItem('notifications')).toBeNull();
|
||||
expect(component.notifications.length).toBe(0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should message be present and empty message not be present when there are notifications in the history', (done) => {
|
||||
fixture.detectChanges();
|
||||
notificationService.showInfo('Example Message');
|
||||
openNotification();
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
expect(overlayContainerElement.querySelector('#adf-notification-history-component-no-message')).toBeNull();
|
||||
expect(overlayContainerElement.querySelector('#adf-notification-history-list').innerHTML).toContain('Example Message');
|
||||
expect(overlayContainerElement.querySelector('.adf-notification-history-list').innerHTML).toContain('Example Message');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should remove notification from storage when mark all as read', (done) => {
|
||||
it('should show message when pushed directly to Notification History', (done) => {
|
||||
const callBackSpy = jasmine.createSpy('callBack');
|
||||
fixture.detectChanges();
|
||||
notificationService.pushToNotificationHistory(
|
||||
{
|
||||
clickCallBack: callBackSpy,
|
||||
messages: ['My new message'],
|
||||
datetime: new Date(),
|
||||
type: NOTIFICATION_TYPE.RECURSIVE
|
||||
|
||||
} as NotificationModel
|
||||
);
|
||||
openNotification();
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
const markAllAsRead = <HTMLButtonElement> overlayContainerElement.querySelector('#adf-notification-history-mark-as-read button');
|
||||
markAllAsRead.click();
|
||||
fixture.detectChanges();
|
||||
expect(storage.getItem('notifications')).toBeNull();
|
||||
const notification = <HTMLButtonElement> overlayContainerElement.querySelector('.adf-notification-history-menu-item');
|
||||
notification.click();
|
||||
expect(callBackSpy).toHaveBeenCalled();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should show load more button when there are more notifications', (done) => {
|
||||
fixture.detectChanges();
|
||||
notificationService.showInfo('Example Message 1');
|
||||
notificationService.showInfo('Example Message 2');
|
||||
notificationService.showInfo('Example Message 3');
|
||||
notificationService.showInfo('Example Message 4');
|
||||
notificationService.showInfo('Example Message 5');
|
||||
notificationService.showInfo('Example Message 6');
|
||||
openNotification();
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
const loadMoreButton = <HTMLButtonElement> overlayContainerElement.querySelector('.adf-notification-history-load-more');
|
||||
expect(component.paginatedNotifications.length).toBe(5);
|
||||
expect(loadMoreButton).toBeDefined();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should read notifications from local storage', (done) => {
|
||||
storage.setItem('notifications', JSON.stringify([{
|
||||
messages: ['My new message'],
|
||||
datetime: new Date(),
|
||||
type: NOTIFICATION_TYPE.RECURSIVE
|
||||
|
||||
} as NotificationModel]));
|
||||
fixture.detectChanges();
|
||||
openNotification();
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
const notification = <HTMLButtonElement> overlayContainerElement.querySelector('.adf-notification-history-menu-item');
|
||||
expect(notification).toBeDefined();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should be able to change the maximum number of notifications displayed', (done) => {
|
||||
component.maxNotifications = 10;
|
||||
fixture.detectChanges();
|
||||
notificationService.showInfo('Example Message 1');
|
||||
notificationService.showInfo('Example Message 2');
|
||||
notificationService.showInfo('Example Message 3');
|
||||
notificationService.showInfo('Example Message 4');
|
||||
notificationService.showInfo('Example Message 5');
|
||||
notificationService.showInfo('Example Message 6');
|
||||
openNotification();
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
const notifications = overlayContainerElement.querySelectorAll('.adf-notification-history-menu-item');
|
||||
expect(notifications.length).toBe(6);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -15,26 +15,23 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Component, Input, ViewChild, OnDestroy } from '@angular/core';
|
||||
import { Component, Input, ViewChild, OnDestroy, OnInit, AfterViewInit, ChangeDetectorRef } from '@angular/core';
|
||||
import { NotificationService } from '../services/notification.service';
|
||||
import { NotificationModel } from '../models/notification.model';
|
||||
import { NotificationModel, NOTIFICATION_TYPE } from '../models/notification.model';
|
||||
import { MatMenuTrigger } from '@angular/material/menu';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
import { Subject } from 'rxjs';
|
||||
import { StorageService } from '../../services/storage.service';
|
||||
import { Pagination } from '@alfresco/js-api';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-notification-history',
|
||||
styleUrls: ['notification-history.component.scss'],
|
||||
templateUrl: 'notification-history.component.html'
|
||||
})
|
||||
export class NotificationHistoryComponent implements OnDestroy {
|
||||
export class NotificationHistoryComponent implements OnDestroy, OnInit, AfterViewInit {
|
||||
|
||||
onDestroy$ = new Subject<boolean>();
|
||||
|
||||
notifications: NotificationModel[] = [];
|
||||
|
||||
MAX_NOTIFICATION_STACK_LENGTH = 100;
|
||||
public static MAX_NOTIFICATION_STACK_LENGTH = 100;
|
||||
|
||||
@ViewChild(MatMenuTrigger, { static: true })
|
||||
trigger: MatMenuTrigger;
|
||||
@@ -47,33 +44,33 @@ export class NotificationHistoryComponent implements OnDestroy {
|
||||
@Input()
|
||||
menuPositionY: string = 'below';
|
||||
|
||||
/** Maximum number of notifications to display. The rest will remain hidden until load more is clicked */
|
||||
@Input()
|
||||
maxNotifications: number = 5;
|
||||
|
||||
onDestroy$ = new Subject<boolean>();
|
||||
notifications: NotificationModel[] = [];
|
||||
paginatedNotifications = [];
|
||||
pagination: Pagination;
|
||||
|
||||
constructor(
|
||||
private notificationService: NotificationService, public storageService: StorageService) {
|
||||
this.notifications = JSON.parse(storageService.getItem('notifications')) || [];
|
||||
private notificationService: NotificationService,
|
||||
public storageService: StorageService,
|
||||
public cd: ChangeDetectorRef) {
|
||||
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.notifications = JSON.parse(this.storageService.getItem('notifications')) || [];
|
||||
}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
this.notificationService.notifications$
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe((message) => {
|
||||
this.notifications.push(message);
|
||||
|
||||
if (this.notifications.length > this.MAX_NOTIFICATION_STACK_LENGTH) {
|
||||
this.notifications.shift();
|
||||
}
|
||||
|
||||
storageService.setItem('notifications', JSON.stringify(this.notifications));
|
||||
});
|
||||
}
|
||||
|
||||
isEmptyNotification(): boolean {
|
||||
return (!this.notifications || this.notifications.length === 0);
|
||||
}
|
||||
|
||||
onKeyPress(event: KeyboardEvent) {
|
||||
this.closeUserModal(event);
|
||||
}
|
||||
|
||||
markAsRead() {
|
||||
this.storageService.removeItem('notifications');
|
||||
this.notifications = [];
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe((notification: NotificationModel) => {
|
||||
this.addNewNotification(notification);
|
||||
this.cd.detectChanges();
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
@@ -81,9 +78,69 @@ export class NotificationHistoryComponent implements OnDestroy {
|
||||
this.onDestroy$.complete();
|
||||
}
|
||||
|
||||
addNewNotification(notification: NotificationModel) {
|
||||
this.notifications.unshift(notification);
|
||||
|
||||
if (this.notifications.length > NotificationHistoryComponent.MAX_NOTIFICATION_STACK_LENGTH) {
|
||||
this.notifications.shift();
|
||||
}
|
||||
|
||||
this.saveNotifications();
|
||||
this.createPagination();
|
||||
}
|
||||
|
||||
saveNotifications() {
|
||||
this.storageService.setItem('notifications', JSON.stringify(this.notifications.filter((notification) =>
|
||||
notification.type !== NOTIFICATION_TYPE.RECURSIVE
|
||||
)));
|
||||
}
|
||||
|
||||
onMenuOpened() {
|
||||
this.createPagination();
|
||||
}
|
||||
|
||||
onKeyPress(event: KeyboardEvent) {
|
||||
this.closeUserModal(event);
|
||||
}
|
||||
|
||||
private closeUserModal($event: KeyboardEvent) {
|
||||
if ($event.keyCode === 27) {
|
||||
this.trigger.closeMenu();
|
||||
}
|
||||
}
|
||||
|
||||
markAsRead() {
|
||||
this.notifications = [];
|
||||
this.paginatedNotifications = [];
|
||||
this.storageService.removeItem('notifications');
|
||||
this.createPagination();
|
||||
this.trigger.closeMenu();
|
||||
}
|
||||
|
||||
createPagination() {
|
||||
this.pagination = {
|
||||
skipCount: this.maxNotifications,
|
||||
maxItems: this.maxNotifications,
|
||||
totalItems: this.notifications.length,
|
||||
hasMoreItems: this.notifications.length > this.maxNotifications
|
||||
};
|
||||
this.paginatedNotifications = this.notifications.slice(0, this.pagination.skipCount);
|
||||
}
|
||||
|
||||
loadMore() {
|
||||
this.pagination.skipCount = this.pagination.maxItems + this.pagination.skipCount;
|
||||
this.pagination.hasMoreItems = this.notifications.length > this.pagination.skipCount;
|
||||
this.paginatedNotifications = this.notifications.slice(0, this.pagination.skipCount);
|
||||
}
|
||||
|
||||
hasMoreNotifications(): boolean {
|
||||
return this.pagination?.hasMoreItems;
|
||||
}
|
||||
|
||||
onNotificationClick(notification: NotificationModel) {
|
||||
if (notification.clickCallBack) {
|
||||
notification.clickCallBack(notification.args);
|
||||
this.trigger.closeMenu();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -23,7 +23,7 @@ import {
|
||||
|
||||
export const rootInitiator: NotificationInitiator = {
|
||||
key: '*',
|
||||
displayName: 'NOTIFICATIONS.SYSTEM'
|
||||
displayName: 'SYSTEM'
|
||||
};
|
||||
|
||||
export function info(messages: string | string[], initiator: NotificationInitiator = rootInitiator): NotificationModel {
|
||||
|
@@ -18,12 +18,15 @@
|
||||
export enum NOTIFICATION_TYPE {
|
||||
INFO = 'info',
|
||||
WARN = 'warning',
|
||||
ERROR = 'error'
|
||||
ERROR = 'error',
|
||||
RECURSIVE = 'recursive'
|
||||
}
|
||||
|
||||
export interface NotificationInitiator {
|
||||
key: string | Symbol;
|
||||
displayName: string;
|
||||
firstName?: string;
|
||||
lastName?: string;
|
||||
extra?: any;
|
||||
}
|
||||
|
||||
@@ -32,4 +35,7 @@ export interface NotificationModel {
|
||||
initiator: NotificationInitiator;
|
||||
datetime: Date;
|
||||
messages: string[];
|
||||
icon?: string;
|
||||
clickCallBack?: any;
|
||||
args?: any;
|
||||
}
|
||||
|
@@ -18,16 +18,19 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { MaterialModule } from '../material.module';
|
||||
|
||||
import { PipeModule } from './../pipes/pipe.module';
|
||||
import { NotificationHistoryComponent } from './components/notification-history.component';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { NotificationIconPipe } from './pipes/notification-icon.pipe';
|
||||
import { PaginationModule } from './../pagination/pagination.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
MaterialModule,
|
||||
TranslateModule
|
||||
TranslateModule,
|
||||
PipeModule,
|
||||
PaginationModule
|
||||
],
|
||||
declarations: [
|
||||
NotificationHistoryComponent,
|
||||
|
@@ -19,18 +19,22 @@ import { Pipe, PipeTransform } from '@angular/core';
|
||||
import { NotificationModel, NOTIFICATION_TYPE } from '../models/notification.model';
|
||||
|
||||
@Pipe({
|
||||
name: 'noticicationIcon'
|
||||
name: 'notificationIcon'
|
||||
})
|
||||
export class NotificationIconPipe implements PipeTransform {
|
||||
|
||||
transform(notification: NotificationModel): string {
|
||||
switch (notification.type) {
|
||||
case NOTIFICATION_TYPE.ERROR:
|
||||
return 'error';
|
||||
case NOTIFICATION_TYPE.WARN:
|
||||
return 'warning';
|
||||
default:
|
||||
return 'info';
|
||||
if (notification.icon) {
|
||||
return notification.icon;
|
||||
} else {
|
||||
switch (notification.type) {
|
||||
case NOTIFICATION_TYPE.ERROR:
|
||||
return 'error';
|
||||
case NOTIFICATION_TYPE.WARN:
|
||||
return 'warning';
|
||||
default:
|
||||
return 'info';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -102,6 +102,14 @@ export class NotificationService {
|
||||
return this.snackBar.dismiss();
|
||||
}
|
||||
|
||||
/**
|
||||
* Push new notification to Notification History
|
||||
* @param notification - Notification model to be pushed.
|
||||
*/
|
||||
pushToNotificationHistory(notification: NotificationModel) {
|
||||
this.notifications$.next(notification);
|
||||
}
|
||||
|
||||
private dispatchNotification(message: string, action?: string, config?: number | MatSnackBarConfig, interpolateArgs?: any): MatSnackBarRef<any> {
|
||||
const translatedMessage: string = this.translationService.instant(message, interpolateArgs);
|
||||
const translatedAction: string = this.translationService.instant(action, interpolateArgs);
|
||||
|
@@ -38,6 +38,7 @@
|
||||
@import '../../core/search-text/search-text-input.component';
|
||||
@import './snackbar';
|
||||
@import '../directives/tooltip-card/tooltip-card.component';
|
||||
@import '../notifications/components/notification-history.component';
|
||||
|
||||
@mixin adf-core-theme($theme) {
|
||||
@include adf-colors-theme($theme);
|
||||
@@ -81,4 +82,5 @@
|
||||
@include mat-datetimepicker-theme--fix($theme);
|
||||
@include adf-search-text-input-theme($theme);
|
||||
@include adf-tooltip-card-directive($theme);
|
||||
@include adf-notification-history-theme($theme);
|
||||
}
|
||||
|
Reference in New Issue
Block a user