/*
* © 2017 Stratio Big Data Inc., Sucursal en España.
*
* This software is licensed under the Apache License, Version 2.0.
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the terms of the License for more details.
*
* SPDX-License-Identifier: Apache-2.0.
*/
import { AfterViewInit, ChangeDetectorRef, Component, Input, EventEmitter, Output, ElementRef, OnInit, Renderer2,
OnChanges, ChangeDetectionStrategy } from '@angular/core';
import { StatusNotification, StNotificationElement } from './st-foreground-notifications.model';
@Component({
selector: 'st-foreground-notifications',
templateUrl: 'st-foreground-notifications.html',
styleUrls: ['st-foreground-notifications.scss'],
host: {
'[class.visible]': '_visible'
},
changeDetection: ChangeDetectionStrategy.OnPush
})
/**
* @description {Component} [Foreground notifications]
*
* Foreground notifications are made to let the user know info about a process she is performing in real time.
*
* @example
*
* {html}
*
* ```
*
*
* ```
*/
export class StForegroundNotificationsComponent implements AfterViewInit, OnChanges, OnInit {
/** @Input {boolean} [visible=false] When true the notification is shown */
@Input()
set visible(value: boolean) {
if (value !== undefined) {
this._visible = value;
this.visibleChange.emit(this._visible);
}
this.cd.markForCheck();
}
get visible(): boolean {
return this._visible;
}
/** @Input {autoCloseTime} [autoCloseTime='1000'] Defines the time in milliseconds for autoclose the notification.
* The autoclose only applies if only have one notification and status is success
*/
@Input() autoCloseTime: number;
/** @Input {StNotificationElement []} [notifications='[]'] Array of notifications */
@Input() notifications?: StNotificationElement[] = [];
/** @output {clickLinkTemplate} [click] Event emitted when user click in a href link */
@Output() clickLinkTemplate: EventEmitter = new EventEmitter();
/** @output {visibleChange} [click] Event emitted when set param visible */
@Output() visibleChange: EventEmitter = new EventEmitter();
public currentNotification: number = 1;
public statusIconValue: string;
public statusNotificationsValue: string;
public statusValue: string;
public showLinkMore: boolean = false;
public status: string = 'default';
public _visible: boolean = false;
public listStatusNotifications: Array = [];
constructor(private cd: ChangeDetectorRef, private elemRef: ElementRef, private renderer: Renderer2) { }
ngOnInit(): void {
if (this.autoCloseTime) {
if ( this.notifications.length === 1 && this.notifications[0].status === 'success') {
setTimeout(() => this.onClose(), this.autoCloseTime);
}
}
this.fillStatusNotifications();
}
ngAfterViewInit(): void {
let htmlElement = this.elemRef.nativeElement.querySelector('.foreground-notification__html');
if (htmlElement !== null) {
this.addStyleLinks(htmlElement);
}
if ( this.notifications && this.notifications.length > 0) {
this.checkOneLine();
}
this.cd.detectChanges();
}
ngOnChanges(): void {
if (this.notifications && this.notifications.length < this.currentNotification) {
this.currentNotification = this.notifications.length;
}
this.listStatusNotifications = [];
this.fillStatusNotifications();
}
addStyleLinks(htmlElement: any): void {
let links = htmlElement.querySelectorAll('a');
if (links.constructor !== Array) {
links = (Object).values(links);
}
links.forEach((element: any, index: any) => {
let nameEventEmitter = (this.notifications[this.getIndexCurrentNotification()]).nameEvents[index];
if (nameEventEmitter) {
element.addEventListener('click', this.onClickLinkHtmlTemplate.bind(this, nameEventEmitter));
this.renderer.setStyle(element, 'text-decoration', 'underline');
this.renderer.setStyle(element, 'cursor', 'pointer');
}
});
}
checkOneLine(): void {
let element = this.elemRef.nativeElement.querySelectorAll('.foreground-notification__content');
let currentIndex = this.getIndexCurrentNotification();
if (this.listStatusNotifications && this.listStatusNotifications.length > 0) {
if (element[currentIndex].offsetHeight > 40) {
this.listStatusNotifications[currentIndex].showMore = !this.listStatusNotifications[currentIndex].completeText;
if (this.listStatusNotifications[currentIndex].showMore) {
this.listStatusNotifications[currentIndex].completeText = false;
this.renderer.addClass(element[currentIndex], 'limit-one-line');
}
} else {
this.listStatusNotifications[currentIndex].completeText = true;
if (!this.listStatusNotifications[currentIndex].showMore) {
this.removeStyleNotification();
}
}
}
this.checkStatus();
}
checkStatus(): void {
this.statusValue = this.getStatus();
this.statusIconValue = this.getStatusIcon();
this.statusNotificationsValue = this.getStatusNotifications();
this.cd.detectChanges();
}
decrementPage(): void {
this.currentNotification = this.getIndexCurrentNotification();
setTimeout(() => {
this.checkOneLine();
this.cd.detectChanges();
});
this.status = this.notifications[this.getIndexCurrentNotification()].status;
}
fillStatusNotifications(): void {
if (this.notifications && this.notifications.length > 0) {
this.status = this.notifications[this.getIndexCurrentNotification()].status;
this.checkStatus();
}
this.notifications.forEach(() => {
this.listStatusNotifications.push(new StatusNotification(false, false));
});
}
getIndexCurrentNotification(): number {
return this.currentNotification - 1;
}
getStatus(): string {
switch (this.status) {
case 'success':
case 'warning':
case 'critical':
case 'running':
return this.status;
default:
return 'default';
}
}
getStatusIcon(): string {
switch (this.status) {
case 'success':
return 'icon-circle-check';
case 'warning':
return 'icon-alert';
case 'critical':
return 'icon-info1';
case 'running':
return 'icon-info1';
default:
return 'default';
}
}
getStatusNotifications(): string {
return (this.notifications.length > 1) ? 'more-lines' : '';
}
incrementPage(): void {
this.currentNotification = this.currentNotification + 1;
setTimeout(() => {
this.checkOneLine();
this.cd.detectChanges();
});
this.status = this.notifications[this.getIndexCurrentNotification()].status;
}
onClickLinkHtmlTemplate(event: string): void {
this.clickLinkTemplate.emit(event);
}
onClose(): void {
this.visible = false;
this.cd.markForCheck();
}
removeStyleNotification(): void {
let element = this.elemRef.nativeElement.querySelectorAll('.foreground-notification__content');
this.renderer.removeClass(element[this.getIndexCurrentNotification()], 'limit-one-line');
this.cd.markForCheck();
}
showTextComplete(): void {
let currentIndex = this.getIndexCurrentNotification();
if (this.listStatusNotifications && this.listStatusNotifications.length > 0) {
this.listStatusNotifications[currentIndex].showMore = false;
this.listStatusNotifications[currentIndex].completeText = true;
}
this.removeStyleNotification();
this.cd.markForCheck();
}
}