mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-15 05:53:03 +00:00
144 lines
4.4 KiB
TypeScript
144 lines
4.4 KiB
TypeScript
import {
|
|
ChangeDetectionStrategy,
|
|
ChangeDetectorRef,
|
|
Component,
|
|
EventEmitter,
|
|
Input,
|
|
OnDestroy,
|
|
OnInit,
|
|
Output,
|
|
ViewEncapsulation
|
|
} from '@angular/core';
|
|
import { NotificationsService } from '../notifications.service';
|
|
import { Store } from '@ngrx/store';
|
|
import { AppState } from '../../../app.reducer';
|
|
import { notificationsStateSelector } from '../selectors';
|
|
import { difference } from 'lodash';
|
|
import { INotification } from '../models/notification.model';
|
|
import { NotificationsState } from '../notifications.reducers';
|
|
import { INotificationBoardOptions } from '../models/notification-options.model';
|
|
import { Subscription } from 'rxjs/Subscription';
|
|
|
|
@Component({
|
|
selector: 'ds-notifications-board',
|
|
encapsulation: ViewEncapsulation.None,
|
|
templateUrl: './notifications-board.component.html',
|
|
styleUrls: ['./notifications-board.component.scss'],
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
})
|
|
export class NotificationsBoardComponent implements OnInit, OnDestroy {
|
|
|
|
@Input()
|
|
set options(opt: INotificationBoardOptions) {
|
|
this.attachChanges(opt);
|
|
}
|
|
|
|
@Output() onCreate = new EventEmitter();
|
|
@Output() onDestroy = new EventEmitter();
|
|
|
|
public notifications: INotification[] = [];
|
|
public position: ['top' | 'bottom' | 'middle', 'right' | 'left' | 'center'] = ['bottom', 'right'];
|
|
|
|
// Received values
|
|
private maxStack = 8;
|
|
private sub: Subscription;
|
|
|
|
// Sent values
|
|
public rtl = false;
|
|
public animate: 'fade' | 'fromTop' | 'fromRight' | 'fromBottom' | 'fromLeft' | 'rotate' | 'scale' = 'fromRight';
|
|
|
|
constructor(private service: NotificationsService,
|
|
private store: Store<AppState>,
|
|
private cdr: ChangeDetectorRef) {
|
|
}
|
|
|
|
ngOnInit(): void {
|
|
this.sub = this.store.select(notificationsStateSelector)
|
|
.subscribe((state: NotificationsState) => {
|
|
if (state.length === 0) {
|
|
this.notifications = [];
|
|
} else if (state.length > this.notifications.length) {
|
|
// Add
|
|
const newElem = difference(state, this.notifications);
|
|
console.log('new Elements #', newElem.length);
|
|
|
|
newElem.forEach((notification) => {
|
|
this.add(notification);
|
|
});
|
|
} else {
|
|
// Remove
|
|
const delElem = difference(this.notifications, state);
|
|
delElem.forEach((notification) => {
|
|
this.notifications = this.notifications.filter((item: INotification) => item.id !== notification.id);
|
|
|
|
});
|
|
}
|
|
this.cdr.detectChanges();
|
|
});
|
|
}
|
|
|
|
// Add the new notification to the notification array
|
|
add(item: INotification): void {
|
|
const toBlock: boolean = this.block(item);
|
|
if (!toBlock) {
|
|
if (this.notifications.length >= this.maxStack) {
|
|
this.notifications.splice(this.notifications.length - 1, 1);
|
|
}
|
|
this.notifications.splice(0, 0, item);
|
|
} else {
|
|
// Remove the notification from the store
|
|
// This notification was in the store, but not in this.notifications
|
|
// because it was a blocked duplicate
|
|
this.service.remove(item);
|
|
}
|
|
}
|
|
|
|
block(item: INotification): boolean {
|
|
const toCheck = item.html ? this.checkHtml : this.checkStandard;
|
|
this.notifications.forEach((notification) => {
|
|
if (toCheck(notification, item)) {
|
|
return true;
|
|
}
|
|
});
|
|
|
|
if (this.notifications.length > 0) {
|
|
this.notifications.forEach((notification) => {
|
|
if (toCheck(notification, item)) {
|
|
return true;
|
|
}
|
|
});
|
|
}
|
|
|
|
let comp: INotification;
|
|
if (this.notifications.length > 0) {
|
|
comp = this.notifications[0];
|
|
} else {
|
|
return false;
|
|
}
|
|
return toCheck(comp, item);
|
|
}
|
|
|
|
checkStandard(checker: INotification, item: INotification): boolean {
|
|
return checker.type === item.type && checker.title === item.title && checker.content === item.content;
|
|
}
|
|
|
|
checkHtml(checker: INotification, item: INotification): boolean {
|
|
return checker.html ? checker.type === item.type && checker.title === item.title && checker.content === item.content && checker.html === item.html : false;
|
|
}
|
|
|
|
// Attach all the changes received in the options object
|
|
attachChanges(options: any): void {
|
|
Object.keys(options).forEach((a) => {
|
|
if (this.hasOwnProperty(a)) {
|
|
(this as any)[a] = options[a];
|
|
}
|
|
});
|
|
}
|
|
|
|
ngOnDestroy(): void {
|
|
if (this.sub) {
|
|
this.sub.unsubscribe();
|
|
}
|
|
}
|
|
}
|