From e6e9fcdc723a6545dac16ab5c45dfde9512d2a91 Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Fri, 20 Aug 2021 00:05:56 +0300 Subject: [PATCH] add toaster service --- src/index.ts | 2 + src/lib/services/error-message.service.ts | 19 +++++ src/lib/services/toaster.service.ts | 85 +++++++++++++++++++++++ 3 files changed, 106 insertions(+) create mode 100644 src/lib/services/error-message.service.ts create mode 100644 src/lib/services/toaster.service.ts diff --git a/src/index.ts b/src/index.ts index c9c5448..85cb447 100644 --- a/src/index.ts +++ b/src/index.ts @@ -23,6 +23,8 @@ export * from './lib/sorting/sort-by.pipe'; export * from './lib/sorting/sorting.service'; export * from './lib/sorting/models/sorting-option.model'; export * from './lib/sorting/models/sorting-order.type'; +export * from './lib/services/toaster.service'; +export * from './lib/services/error-message.service'; export * from './lib/search/search.service'; export * from './lib/tables/entities.service'; export * from './lib/tables/listing-component.directive'; diff --git a/src/lib/services/error-message.service.ts b/src/lib/services/error-message.service.ts new file mode 100644 index 0000000..a1a5d5a --- /dev/null +++ b/src/lib/services/error-message.service.ts @@ -0,0 +1,19 @@ +import { Injectable } from '@angular/core'; +import { TranslateService } from '@ngx-translate/core'; +import { HttpErrorResponse } from '@angular/common/http'; + +@Injectable({ + providedIn: 'root' +}) +export class ErrorMessageService { + constructor(private readonly _translateService: TranslateService) {} + + private _parseErrorResponse(err: HttpErrorResponse): string { + // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access,@typescript-eslint/restrict-template-expressions + return err?.error?.message?.includes('message') ? ` ${err.error.message.match('"message":"(.*?)\\"')[1]}` : ''; + } + + getMessage(error: HttpErrorResponse, defaultMessage: string): string { + return (this._translateService.instant(defaultMessage) as string) + this._parseErrorResponse(error); + } +} diff --git a/src/lib/services/toaster.service.ts b/src/lib/services/toaster.service.ts new file mode 100644 index 0000000..0d19ee6 --- /dev/null +++ b/src/lib/services/toaster.service.ts @@ -0,0 +1,85 @@ +import { Injectable } from '@angular/core'; +import { ActiveToast, ToastrService } from 'ngx-toastr'; +import { IndividualConfig } from 'ngx-toastr/toastr/toastr-config'; +import { NavigationStart, Router } from '@angular/router'; +import { TranslateService } from '@ngx-translate/core'; +import { HttpErrorResponse } from '@angular/common/http'; +import { filter } from 'rxjs/operators'; +import { ErrorMessageService } from './error-message.service'; + +const enum NotificationType { + SUCCESS = 'SUCCESS', + WARNING = 'WARNING', + INFO = 'INFO' +} + +export interface ToasterOptions extends IndividualConfig { + readonly title?: string; + /** + * These params are used as interpolateParams for translate service + */ + // eslint-disable-next-line @typescript-eslint/ban-types + readonly params?: object; + readonly actions?: { readonly title?: string; readonly action: () => void }[]; +} + +export interface ErrorToasterOptions extends ToasterOptions { + /** + * Pass an http error that will be processed by error message service and shown in toast + */ + readonly error?: HttpErrorResponse; +} + +@Injectable({ + providedIn: 'root' +}) +export class Toaster { + constructor( + private readonly _toastr: ToastrService, + private readonly _router: Router, + private readonly _translateService: TranslateService, + private readonly _errorMessageService: ErrorMessageService + ) { + _router.events.pipe(filter(event => event instanceof NavigationStart)).subscribe(() => { + _toastr.clear(); + }); + } + + error(message: string, options?: Partial): ActiveToast { + let resultedMsg; + if (options?.error) resultedMsg = this._errorMessageService.getMessage(options.error, message); + else resultedMsg = this._translateService.instant(message, options?.params) as string; + + return this._toastr.error(resultedMsg, options?.title, options); + } + + info(message: string, options?: Partial): ActiveToast { + return this._showToastNotification(message, NotificationType.INFO, options); + } + + success(message: string, options?: Partial): ActiveToast { + return this._showToastNotification(message, NotificationType.SUCCESS, options); + } + + warning(message: string, options?: Partial): ActiveToast { + return this._showToastNotification(message, NotificationType.WARNING, options); + } + + private _showToastNotification( + message: string, + notificationType = NotificationType.INFO, + options?: Partial + ): ActiveToast { + const translatedMsg = this._translateService.instant(message, options?.params) as string; + + switch (notificationType) { + case NotificationType.SUCCESS: + return this._toastr.success(translatedMsg, options?.title, options); + case NotificationType.WARNING: + return this._toastr.warning(translatedMsg, options?.title, options); + case NotificationType.INFO: + default: + return this._toastr.info(translatedMsg, options?.title, options); + } + } +}