Newer
Older
import {Injectable} from '@angular/core';
import {NavigationEnd, NavigationStart, Router} from '@angular/router';
import {lastValueFrom, Observable, Subject} from 'rxjs';

Joze RIHTARSIC
committed
import {HttpErrorResponse} from "@angular/common/http";
import {TranslateService} from "@ngx-translate/core";

Joze RIHTARSIC
committed
/**
* AlertMessageRO is the object that will be used to display the message in the SMP alert component in overlay.
* These messages are not the same to SMP alerts, which are used to display alert the page.
* It contains the type of the message (success, error, info, warning), the text of the message and the timeout in seconds.
*/
export interface AlertMessageRO {
type: string,
text: string,
timeoutInSeconds?: number
}

Sebastian-Ion TINCU
committed

Joze RIHTARSIC
committed
// the default timeout duration
readonly DEFAULT_TIMEOUT: number = 3;

Sebastian-Ion TINCU
committed

Joze RIHTARSIC
committed
private subject = new Subject<any>();
private previousRoute:string = '';
private keepAfterNavigationChange:boolean = false;
private message: AlertMessageRO;
constructor(private router: Router,
private translateService: TranslateService) {
// clear alert message on route change
router.events.subscribe(event => {
if (event instanceof NavigationStart) {
if (this.isRouteChanged(event.url)) {
this.clearAlert();
}
} else if (event instanceof NavigationEnd) {

Joze RIHTARSIC
committed
if (this.keepAfterNavigationChange) {

Sebastian-Ion TINCU
committed
this.displayCurrentMessage();
this.reset();
}

Joze RIHTARSIC
committed
private reset() {
this.keepAfterNavigationChange = false;

Sebastian-Ion TINCU
committed
this.message = null;
}

Joze RIHTARSIC
committed
getPath(url: string): string {

Sebastian-Ion TINCU
committed
const parser = document.createElement('a');
parser.href = url;
return parser.pathname;
}

Joze RIHTARSIC
committed
isRouteChanged(currentRoute: string): boolean {
let previousRoutePath = this.getPath(this.previousRoute);
let currentRoutePath = this.getPath(currentRoute);

Sebastian-Ion TINCU
committed
return previousRoutePath !== currentRoutePath;

Joze RIHTARSIC
committed
clearAlert(force = false): void {
if (!force && this.keepAfterNavigationChange) {

Sebastian-Ion TINCU
committed
return;
}

Joze RIHTARSIC
committed
setKeepAfterNavigationChange(keepAfterNavigation: boolean) {
this.keepAfterNavigationChange = keepAfterNavigation;

Sebastian-Ion TINCU
committed
}

Joze RIHTARSIC
committed
displayCurrentMessage() {

Sebastian-Ion TINCU
committed
this.subject.next(this.message);
}

Joze RIHTARSIC
committed
/**
* Extract the message from the object return it as a string. The object can be a string or an HttpErrorResponse
*
* @param messageObject
*/
getObjectMessage(messageObject: any): string {
if (typeof messageObject === 'string') {
return messageObject;
}
if (messageObject instanceof HttpErrorResponse) {
return this.getHttpErrorResponseMessage(messageObject);
}

Joze RIHTARSIC
committed
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/**
* Extract the message from the HttpErrorResponse and return it as a string
* @param httpErrorResponse
*/
getHttpErrorResponseMessage(httpErrorResponse: HttpErrorResponse): string {
let message: string;
if (httpErrorResponse.error) {
if (httpErrorResponse.error.errorDescription) {
message = httpErrorResponse.error.errorDescription;
} else if (httpErrorResponse.error.message) {
message = httpErrorResponse.error.message;
}
} else {
message = httpErrorResponse.statusText + ': ' + httpErrorResponse.message;
}
return message;
}
/**
* Show a message of a given type
* @param messageObject The message to display
* @param type The type of the message (success, error, info, warning)
* @param keepAfterNavigationChange If true, the message will be displayed after a navigation changed
*/
showMessage(messageObject: any, type: string, keepAfterNavigationChange:boolean = false, timeoutInSeconds: number = null) {
this.setKeepAfterNavigationChange(keepAfterNavigationChange);
this.message = {
type: type,
text: this.getObjectMessage(messageObject),
// if the timeoutInSeconds is not set, we use the default timeout for success messages
timeoutInSeconds: !timeoutInSeconds && type =="success" ?this.DEFAULT_TIMEOUT: timeoutInSeconds
};

Sebastian-Ion TINCU
committed
this.displayCurrentMessage();
async showMessageForTranslation(translationCode: string,type: string, keepAfterNavigationChange = false, timeoutInSeconds: number = null) : Promise<void> {
let message = await lastValueFrom(this.translateService.get(translationCode))
this.showMessage(message, type, keepAfterNavigationChange, timeoutInSeconds);
}
successForTranslation(translationCode: string, keepAfterNavigationChange = false, timeoutInSeconds: number = null) {
this.showMessageForTranslation(translationCode, 'success', keepAfterNavigationChange, timeoutInSeconds);
}

Joze RIHTARSIC
committed
success(message: string, keepAfterNavigationChange = false, timeoutInSeconds: number = null) {
this.showMessage(message, 'success', keepAfterNavigationChange, timeoutInSeconds);
}

Sebastian-Ion TINCU
committed
warning(message: string, keepAfterNavigationChange = false, timeoutInSeconds: number = null) {
this.showMessage(message, 'warning', keepAfterNavigationChange, timeoutInSeconds);
}
errorForTranslation(translationCode: string, keepAfterNavigationChange = false, timeoutInSeconds: number = null) {
this.showMessageForTranslation(translationCode, 'error', keepAfterNavigationChange, timeoutInSeconds);
}

Joze RIHTARSIC
committed
error(message: any, keepAfterNavigationChange = false, timeoutInSeconds: number = null) {
this.showMessage(message, 'error', keepAfterNavigationChange, timeoutInSeconds);
}
exception(message: string, error: any, keepAfterNavigationChange = false): void {
const errMsg = error.message || (error.json ? error.json().message : error);
this.error(message + ' \n' + errMsg, keepAfterNavigationChange);
}

Joze RIHTARSIC
committed
getMessage(): Observable<any> {
return this.subject.asObservable();
}
}