refactor notification service

This commit is contained in:
Dan Percic 2021-07-15 01:09:28 +03:00
parent 6932fa6b30
commit 75553f562a
30 changed files with 303 additions and 454 deletions

View File

@ -2,24 +2,12 @@
<div *ngIf="title" [attr.aria-label]="title" [class]="options.titleClass">
{{ title }}
</div>
<div
*ngIf="message && options.enableHtml"
[class]="options.messageClass"
[innerHTML]="message"
aria-live="polite"
role="alert"
></div>
<div
*ngIf="message && !options.enableHtml"
[attr.aria-label]="message"
[class]="options.messageClass"
aria-live="polite"
role="alert"
>
<div *ngIf="message && options.enableHtml" [class]="options.messageClass" [innerHTML]="message" aria-live="polite" role="alert"></div>
<div *ngIf="message && !options.enableHtml" [attr.aria-label]="message" [class]="options.messageClass" aria-live="polite" role="alert">
{{ message }}
</div>
<div *ngIf="actions && actions.length" class="actions-wrapper">
<div *ngIf="actions?.length" class="actions-wrapper">
<a (click)="callAction($event, action.action)" *ngFor="let action of actions">
{{ action.title }}
</a>

View File

@ -1,26 +1,21 @@
import { Component } from '@angular/core';
import { Toast, ToastPackage, ToastrService } from 'ngx-toastr';
import { ToasterOptions } from '@services/toaster.service';
@Component({
selector: 'redaction-toast',
templateUrl: './toast.component.html',
styleUrls: ['./toast.component.scss']
})
export class ToastComponent extends Toast {
constructor(
protected readonly _toastrService: ToastrService,
readonly toastPackage: ToastPackage
) {
constructor(protected readonly _toastrService: ToastrService, readonly toastPackage: ToastPackage) {
super(_toastrService, toastPackage);
}
get actions() {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
return this.options.actions;
return (this.options as ToasterOptions)?.actions;
}
callAction($event: MouseEvent, action: Function) {
callAction($event: MouseEvent, action: () => void) {
$event.stopPropagation();
if (action) {
action();

View File

@ -3,7 +3,7 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { DictionaryControllerService, TypeValue } from '@redaction/red-ui-http';
import { Observable } from 'rxjs';
import { NotificationService, NotificationType } from '@services/notification.service';
import { Toaster } from '@services/toaster.service';
import { TranslateService } from '@ngx-translate/core';
import { TypeValueWrapper } from '@models/file/type-value.wrapper';
import { humanize } from '../../../../utils/functions';
@ -21,7 +21,7 @@ export class AddEditDictionaryDialogComponent {
constructor(
private readonly _dictionaryControllerService: DictionaryControllerService,
private readonly _formBuilder: FormBuilder,
private readonly _notificationService: NotificationService,
private readonly _toaster: Toaster,
private readonly _translateService: TranslateService,
private readonly _dialogRef: MatDialogRef<AddEditDictionaryDialogComponent>,
@Inject(MAT_DIALOG_DATA)
@ -89,20 +89,16 @@ export class AddEditDictionaryDialogComponent {
() => this._dialogRef.close(true),
error => {
if (error.status === 409) {
this._notifyError('add-edit-dictionary.error.dictionary-already-exists');
this._toaster.error('add-edit-dictionary.error.dictionary-already-exists');
} else if (error.status === 400) {
this._notifyError('add-edit-dictionary.error.invalid-color-or-rank');
this._toaster.error('add-edit-dictionary.error.invalid-color-or-rank');
} else {
this._notifyError('add-edit-dictionary.error.generic');
this._toaster.error('add-edit-dictionary.error.generic');
}
}
);
}
private _notifyError(message: string) {
this._notificationService.showToastNotification(this._translateService.instant(message), null, NotificationType.ERROR);
}
private _formToObject(): TypeValue {
return {
caseInsensitive: !this.dictionaryForm.get('caseSensitive').value,

View File

@ -1,12 +1,12 @@
import { Component, Inject } from '@angular/core';
import { Component, Inject, OnDestroy } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { DossierAttributeConfig, FileAttributeConfig } from '@redaction/red-ui-http';
import { AppStateService } from '@state/app-state.service';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { LoadingService } from '@services/loading.service';
import { ErrorMessageService } from '@services/error-message.service';
import { NotificationService, NotificationType } from '@services/notification.service';
import { LoadingService } from '../../../../services/loading.service';
import { HttpErrorResponse } from '@angular/common/http';
import { Toaster } from '../../../../services/toaster.service';
import { AutoUnsubscribeComponent } from '../../../shared/base/auto-unsubscribe.component';
import { DossierAttributesService } from '@shared/services/controller-wrappers/dossier-attributes.service';
@Component({
@ -14,7 +14,7 @@ import { DossierAttributesService } from '@shared/services/controller-wrappers/d
templateUrl: './add-edit-dossier-attribute-dialog.component.html',
styleUrls: ['./add-edit-dossier-attribute-dialog.component.scss']
})
export class AddEditDossierAttributeDialogComponent {
export class AddEditDossierAttributeDialogComponent extends AutoUnsubscribeComponent implements OnDestroy {
dossierAttributeForm: FormGroup;
dossierAttribute: DossierAttributeConfig;
dossierTemplateId: string;
@ -30,12 +30,12 @@ export class AddEditDossierAttributeDialogComponent {
private readonly _formBuilder: FormBuilder,
private readonly _loadingService: LoadingService,
private readonly _dossierAttributesService: DossierAttributesService,
private readonly _errorMessageService: ErrorMessageService,
private readonly _notificationService: NotificationService,
private readonly _toaster: Toaster,
public dialogRef: MatDialogRef<AddEditDossierAttributeDialogComponent>,
@Inject(MAT_DIALOG_DATA)
public data: { dossierAttribute: DossierAttributeConfig; dossierTemplateId: string }
) {
super();
this.dossierAttribute = data.dossierAttribute;
this.dossierTemplateId = data.dossierTemplateId;
@ -76,14 +76,10 @@ export class AddEditDossierAttributeDialogComponent {
() => {
this.dialogRef.close(true);
},
(err: HttpErrorResponse) => {
this._loadingService.stop();
this._notificationService.showToastNotification(
this._errorMessageService.getMessage(err, 'add-edit-dossier-attribute.error.generic'),
null,
NotificationType.ERROR
);
}
);
(error: HttpErrorResponse) => {
this._loadingService.stop();
this._toaster.error('add-edit-dossier-attribute.error.generic', { error: error });
}
);
}
}

View File

@ -1,7 +1,7 @@
import { Component, Inject } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { Colors, DictionaryControllerService } from '@redaction/red-ui-http';
import { NotificationService, NotificationType } from '@services/notification.service';
import { Toaster } from '../../../../services/toaster.service';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { TranslateService } from '@ngx-translate/core';
@ -20,7 +20,7 @@ export class EditColorDialogComponent {
constructor(
private readonly _formBuilder: FormBuilder,
private readonly _dictionaryControllerService: DictionaryControllerService,
private readonly _notificationService: NotificationService,
private readonly _toaster: Toaster,
private readonly _translateService: TranslateService,
private readonly _dialogRef: MatDialogRef<EditColorDialogComponent>,
@Inject(MAT_DIALOG_DATA)
@ -49,17 +49,10 @@ export class EditColorDialogComponent {
try {
await this._dictionaryControllerService.setColors(colors, this._dossierTemplateId).toPromise();
this._dialogRef.close(true);
this._notificationService.showToastNotification(
this._translateService.instant('edit-color-dialog.success', {
color: this._translateService.instant('default-colors-screen.types.' + this.colorKey)
})
);
const color = this._translateService.instant(`default-colors-screen.types.${this.colorKey}`);
this._toaster.info('edit-color-dialog.success', { params: { color: color } });
} catch (e) {
this._notificationService.showToastNotification(
this._translateService.instant('edit-color-dialog.error'),
null,
NotificationType.ERROR
);
this._toaster.error('edit-color-dialog.error');
}
}
}

View File

@ -6,7 +6,7 @@ import * as Papa from 'papaparse';
import { FileAttributeConfig, FileAttributesConfig, FileAttributesControllerService } from '@redaction/red-ui-http';
import { Observable } from 'rxjs';
import { map, startWith } from 'rxjs/operators';
import { NotificationService, NotificationType } from '@services/notification.service';
import { Toaster } from '../../../../services/toaster.service';
import { TranslateService } from '@ngx-translate/core';
import { FilterService } from '@shared/services/filter.service';
import { SearchService } from '@shared/services/search.service';
@ -48,7 +48,7 @@ export class FileAttributesCsvImportDialogComponent extends BaseListingComponent
private readonly _appStateService: AppStateService,
private readonly _fileAttributesControllerService: FileAttributesControllerService,
private readonly _translateService: TranslateService,
private readonly _notificationService: NotificationService,
private readonly _toaster: Toaster,
private readonly _formBuilder: FormBuilder,
public dialogRef: MatDialogRef<FileAttributesCsvImportDialogComponent>,
protected readonly _injector: Injector,
@ -202,19 +202,9 @@ export class FileAttributesCsvImportDialogComponent extends BaseListingComponent
try {
await this._fileAttributesControllerService.setFileAttributesConfig(fileAttributes, this.dossierTemplateId).toPromise();
this._notificationService.showToastNotification(
this._translateService.instant('file-attributes-csv-import.save.success', {
count: this.activeFields.length
}),
null,
NotificationType.SUCCESS
);
this._toaster.success('file-attributes-csv-import.save.success', { params: { count: this.activeFields.length } });
} catch (e) {
this._notificationService.showToastNotification(
this._translateService.instant('file-attributes-csv-import.save.error'),
null,
NotificationType.ERROR
);
this._toaster.error('file-attributes-csv-import.save.error');
}
this.dialogRef.close(true);

View File

@ -22,19 +22,8 @@
<div class="red-content-inner">
<div class="content-container">
<div class="content-container-content">
<form
(keyup)="formChanged()"
*ngIf="digitalSignatureForm"
[formGroup]="digitalSignatureForm"
autocomplete="off"
>
<input
#fileInput
(change)="fileChanged($event, fileInput)"
class="file-upload-input"
hidden
type="file"
/>
<form *ngIf="digitalSignatureForm" [formGroup]="digitalSignatureForm" autocomplete="off">
<input #fileInput (change)="fileChanged($event, fileInput)" class="file-upload-input" hidden type="file" />
<redaction-empty-state
(action)="fileInput.click()"
@ -43,18 +32,10 @@
screen="digital-signature-screen"
></redaction-empty-state>
<div
[class.hidden]="!hasDigitalSignatureSet"
class="red-input-group required w-300"
>
<label
translate="digital-signature-screen.certificate-name.label"
></label>
<div [class.hidden]="!hasDigitalSignatureSet" class="red-input-group required w-300">
<label translate="digital-signature-screen.certificate-name.label"></label>
<input
[placeholder]="
'digital-signature-screen.certificate-name.placeholder'
| translate
"
[placeholder]="'digital-signature-screen.certificate-name.placeholder' | translate"
formControlName="certificateName"
name="certificateName"
/>
@ -67,9 +48,7 @@
>
<label translate="digital-signature-screen.password.label"></label>
<input
[placeholder]="
'digital-signature-screen.password.placeholder' | translate
"
[placeholder]="'digital-signature-screen.password.placeholder' | translate"
formControlName="keySecret"
name="keySecret"
/>
@ -78,9 +57,7 @@
<div [class.hidden]="!hasDigitalSignatureSet" class="red-input-group w-300">
<label translate="digital-signature-screen.reason.label"></label>
<input
[placeholder]="
'digital-signature-screen.reason.placeholder' | translate
"
[placeholder]="'digital-signature-screen.reason.placeholder' | translate"
formControlName="reason"
name="reason"
/>
@ -89,9 +66,7 @@
<div [class.hidden]="!hasDigitalSignatureSet" class="red-input-group w-300">
<label translate="digital-signature-screen.location.label"></label>
<input
[placeholder]="
'digital-signature-screen.location.placeholder' | translate
"
[placeholder]="'digital-signature-screen.location.placeholder' | translate"
formControlName="location"
name="location"
/>
@ -100,9 +75,7 @@
<div [class.hidden]="!hasDigitalSignatureSet" class="red-input-group w-300">
<label translate="digital-signature-screen.contact-info.label"></label>
<input
[placeholder]="
'digital-signature-screen.contact-info.placeholder' | translate
"
[placeholder]="'digital-signature-screen.contact-info.placeholder' | translate"
formControlName="contactInfo"
name="contactInfo"
/>
@ -139,6 +112,4 @@
</div>
</section>
<redaction-full-page-loading-indicator
[displayed]="!viewReady"
></redaction-full-page-loading-indicator>
<redaction-full-page-loading-indicator [displayed]="!viewReady"></redaction-full-page-loading-indicator>

View File

@ -1,17 +1,17 @@
import { Component } from '@angular/core';
import { Component, OnDestroy } from '@angular/core';
import { DigitalSignature, DigitalSignatureControllerService } from '@redaction/red-ui-http';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { NotificationService, NotificationType } from '@services/notification.service';
import { TranslateService } from '@ngx-translate/core';
import { Toaster } from '../../../../services/toaster.service';
import { PermissionsService } from '@services/permissions.service';
import { lastIndexOfEnd } from '@utils/functions';
import { AutoUnsubscribeComponent } from '../../../shared/base/auto-unsubscribe.component';
@Component({
selector: 'redaction-digital-signature-screen',
templateUrl: './digital-signature-screen.component.html',
styleUrls: ['./digital-signature-screen.component.scss']
})
export class DigitalSignatureScreenComponent {
export class DigitalSignatureScreenComponent extends AutoUnsubscribeComponent implements OnDestroy {
digitalSignature: DigitalSignature;
digitalSignatureForm: FormGroup;
@ -20,11 +20,11 @@ export class DigitalSignatureScreenComponent {
constructor(
private readonly _digitalSignatureControllerService: DigitalSignatureControllerService,
private readonly _notificationService: NotificationService,
private readonly _toaster: Toaster,
private readonly _formBuilder: FormBuilder,
private readonly _translateService: TranslateService,
readonly permissionsService: PermissionsService
) {
super();
this.loadDigitalSignatureAndInitializeForm();
}
@ -43,50 +43,28 @@ export class DigitalSignatureScreenComponent {
? this._digitalSignatureControllerService.updateDigitalSignature(digitalSignature)
: this._digitalSignatureControllerService.saveDigitalSignature(digitalSignature);
observable.subscribe(
this.addSubscription = observable.subscribe(
() => {
this.loadDigitalSignatureAndInitializeForm();
this._notificationService.showToastNotification(
this._translateService.instant('digital-signature-screen.action.save-success'),
null,
NotificationType.SUCCESS
);
this._toaster.success('digital-signature-screen.action.save-success');
},
error => {
if (error.status === 400) {
this._notificationService.showToastNotification(
this._translateService.instant('digital-signature-screen.action.certificate-not-valid-error'),
null,
NotificationType.ERROR
);
this._toaster.error('digital-signature-screen.action.certificate-not-valid-error');
} else {
this._notificationService.showToastNotification(
this._translateService.instant('digital-signature-screen.action.save-error'),
null,
NotificationType.ERROR
);
this._toaster.error('digital-signature-screen.action.save-error');
}
}
);
}
removeDigitalSignature() {
this._digitalSignatureControllerService.deleteDigitalSignature().subscribe(
this.addSubscription = this._digitalSignatureControllerService.deleteDigitalSignature().subscribe(
() => {
this.loadDigitalSignatureAndInitializeForm();
this._notificationService.showToastNotification(
this._translateService.instant('digital-signature-screen.action.delete-success'),
null,
NotificationType.SUCCESS
);
this._toaster.success('digital-signature-screen.action.delete-success');
},
() => {
this._notificationService.showToastNotification(
this._translateService.instant('digital-signature-screen.action.delete-error'),
null,
NotificationType.ERROR
);
}
() => this._toaster.error('digital-signature-screen.action.delete-error')
);
}
@ -105,7 +83,7 @@ export class DigitalSignatureScreenComponent {
loadDigitalSignatureAndInitializeForm() {
this.viewReady = false;
this._digitalSignatureControllerService
this.addSubscription = this._digitalSignatureControllerService
.getDigitalSignature()
.subscribe(
digitalSignature => {
@ -123,8 +101,6 @@ export class DigitalSignatureScreenComponent {
});
}
formChanged() {}
private _initForm() {
this.digitalSignatureForm = this._formBuilder.group({
certificateName: [this.digitalSignature.certificateName, Validators.required],

View File

@ -1,7 +1,7 @@
import { Component, ElementRef, ViewChild } from '@angular/core';
import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
import { PermissionsService } from '@services/permissions.service';
import { RulesControllerService } from '@redaction/red-ui-http';
import { NotificationService, NotificationType } from '@services/notification.service';
import { Toaster } from '../../../../services/toaster.service';
import { TranslateService } from '@ngx-translate/core';
import { saveAs } from 'file-saver';
import { ComponentHasChanges } from '@guards/can-deactivate.guard';
@ -17,7 +17,7 @@ import IStandaloneEditorConstructionOptions = monaco.editor.IStandaloneEditorCon
templateUrl: './rules-screen.component.html',
styleUrls: ['./rules-screen.component.scss']
})
export class RulesScreenComponent extends ComponentHasChanges {
export class RulesScreenComponent extends ComponentHasChanges implements OnInit {
editorOptions: IStandaloneEditorConstructionOptions = {
theme: 'vs',
language: 'java',
@ -39,13 +39,16 @@ export class RulesScreenComponent extends ComponentHasChanges {
readonly permissionsService: PermissionsService,
private readonly _rulesControllerService: RulesControllerService,
private readonly _appStateService: AppStateService,
private readonly _notificationService: NotificationService,
private readonly _toaster: Toaster,
protected readonly _translateService: TranslateService,
private readonly _activatedRoute: ActivatedRoute
) {
super(_translateService);
this._appStateService.activateDossierTemplate(_activatedRoute.snapshot.params.dossierTemplateId);
this._initialize();
_appStateService.activateDossierTemplate(_activatedRoute.snapshot.params.dossierTemplateId);
}
async ngOnInit() {
await this._initialize();
}
get hasChanges(): boolean {
@ -83,27 +86,20 @@ export class RulesScreenComponent extends ComponentHasChanges {
async save(): Promise<void> {
this.processing = true;
this._rulesControllerService
await this._rulesControllerService
.uploadRules({
rules: this._codeEditor.getModel().getValue(),
dossierTemplateId: this._appStateService.activeDossierTemplateId
})
.subscribe(
() => {
this._initialize();
this._notificationService.showToastNotification(
this._translateService.instant('rules-screen.success.generic'),
null,
NotificationType.SUCCESS
);
.toPromise()
.then(
async () => {
await this._initialize();
this._toaster.success('rules-screen.success.generic');
},
() => {
this.processing = false;
this._notificationService.showToastNotification(
this._translateService.instant('rules-screen.error.generic'),
null,
NotificationType.ERROR
);
this._toaster.error('rules-screen.error.generic');
}
);
}
@ -148,13 +144,16 @@ export class RulesScreenComponent extends ComponentHasChanges {
} as IModelDeltaDecoration;
}
private _initialize() {
this._rulesControllerService.downloadRules(this._appStateService.activeDossierTemplateId).subscribe(
rules => {
this.currentLines = this.initialLines = rules.rules.split('\n');
this.revert();
},
() => (this.processing = false)
);
private async _initialize() {
await this._rulesControllerService
.downloadRules(this._appStateService.activeDossierTemplateId)
.toPromise()
.then(
rules => {
this.currentLines = this.initialLines = rules.rules.split('\n');
this.revert();
},
() => (this.processing = false)
);
}
}

View File

@ -1,4 +1,4 @@
import { Component, OnInit } from '@angular/core';
import { Component, OnDestroy, OnInit } from '@angular/core';
import { PermissionsService } from '@services/permissions.service';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { AdminDialogService } from '../../services/admin-dialog.service';
@ -8,15 +8,15 @@ import {
SmtpConfigurationControllerService,
SMTPConfigurationModel
} from '@redaction/red-ui-http';
import { NotificationService, NotificationType } from '@services/notification.service';
import { TranslateService } from '@ngx-translate/core';
import { Toaster } from '../../../../services/toaster.service';
import { AutoUnsubscribeComponent } from '../../../shared/base/auto-unsubscribe.component';
@Component({
selector: 'redaction-smtp-config-screen',
templateUrl: './smtp-config-screen.component.html',
styleUrls: ['./smtp-config-screen.component.scss']
})
export class SmtpConfigScreenComponent implements OnInit {
export class SmtpConfigScreenComponent extends AutoUnsubscribeComponent implements OnInit, OnDestroy {
viewReady = false;
configForm: FormGroup;
generalSettings: GeneralConfigurationModel = {
@ -31,11 +31,11 @@ export class SmtpConfigScreenComponent implements OnInit {
private readonly _smtpConfigService: SmtpConfigurationControllerService,
private readonly _formBuilder: FormBuilder,
private readonly _dialogService: AdminDialogService,
private readonly _notificationService: NotificationService,
private readonly _translateService: TranslateService,
private readonly _toaster: Toaster,
private readonly _generalSettingsControllerService: GeneralSettingsControllerService
) {
this.configForm = this._formBuilder.group({
super();
this.configForm = _formBuilder.group({
host: [undefined, Validators.required],
port: [25],
from: [undefined, [Validators.required, Validators.email]],
@ -50,7 +50,7 @@ export class SmtpConfigScreenComponent implements OnInit {
password: [undefined]
});
this.configForm.controls.auth.valueChanges.subscribe(auth => {
this.addSubscription = this.configForm.controls.auth.valueChanges.subscribe(auth => {
if (auth) {
this.openAuthConfigDialog();
}
@ -110,17 +110,9 @@ export class SmtpConfigScreenComponent implements OnInit {
this.viewReady = false;
try {
await this._smtpConfigService.testSMTPConfiguration(this.configForm.getRawValue()).toPromise();
this._notificationService.showToastNotification(
this._translateService.instant('smtp-config-screen.test.success'),
undefined,
NotificationType.SUCCESS
);
this._toaster.success('smtp-config-screen.test.success');
} catch (e) {
this._notificationService.showToastNotification(
this._translateService.instant('smtp-config-screen.test.error'),
undefined,
NotificationType.ERROR
);
this._toaster.error('smtp-config-screen.test.error');
} finally {
this.viewReady = true;
}

View File

@ -7,8 +7,7 @@ import { HttpClient } from '@angular/common/http';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { debounce } from '@utils/debounce';
import { WatermarkControllerService, WatermarkModelRes } from '@redaction/red-ui-http';
import { NotificationService, NotificationType } from '@services/notification.service';
import { TranslateService } from '@ngx-translate/core';
import { Toaster } from '../../../../services/toaster.service';
import { ActivatedRoute } from '@angular/router';
import { BASE_HREF } from '../../../../tokens';
import { stampPDFPage } from '../../../../utils/page-stamper';
@ -39,15 +38,14 @@ export class WatermarkScreenComponent implements OnInit {
readonly permissionsService: PermissionsService,
readonly appStateService: AppStateService,
@Inject(BASE_HREF) private readonly _baseHref: string,
private readonly _translateService: TranslateService,
private readonly _watermarkControllerService: WatermarkControllerService,
private readonly _notificationService: NotificationService,
private readonly _toaster: Toaster,
private readonly _http: HttpClient,
private readonly _changeDetectorRef: ChangeDetectorRef,
private readonly _formBuilder: FormBuilder,
private readonly _activatedRoute: ActivatedRoute
) {
this.appStateService.activateDossierTemplate(_activatedRoute.snapshot.params.dossierTemplateId);
appStateService.activateDossierTemplate(_activatedRoute.snapshot.params.dossierTemplateId);
this._initForm();
}
@ -81,24 +79,12 @@ export class WatermarkScreenComponent implements OnInit {
? this._watermarkControllerService.saveWatermark(watermark, this.appStateService.activeDossierTemplateId)
: this._watermarkControllerService.deleteWatermark(this.appStateService.activeDossierTemplateId);
observable.subscribe(
observable.toPromise().then(
() => {
this._loadWatermark();
this._notificationService.showToastNotification(
this._translateService.instant(
watermark.text ? 'watermark-screen.action.change-success' : 'watermark-screen.action.delete-success'
),
null,
NotificationType.SUCCESS
);
this._toaster.success(watermark.text ? 'watermark-screen.action.change-success' : 'watermark-screen.action.delete-success');
},
() => {
this._notificationService.showToastNotification(
this._translateService.instant('watermark-screen.action.error'),
null,
NotificationType.ERROR
);
}
() => this._toaster.error('watermark-screen.action.error')
);
}
@ -188,11 +174,41 @@ export class WatermarkScreenComponent implements OnInit {
private _initForm() {
this.configForm = this._formBuilder.group({
text: [{ value: null, disabled: !this.permissionsService.isAdmin() }],
hexColor: [{ value: null, disabled: !this.permissionsService.isAdmin() }, Validators.required],
opacity: [{ value: null, disabled: !this.permissionsService.isAdmin() }, Validators.required],
fontSize: [{ value: null, disabled: !this.permissionsService.isAdmin() }, Validators.required],
fontType: [{ value: null, disabled: !this.permissionsService.isAdmin() }, Validators.required],
orientation: [{ value: null, disabled: !this.permissionsService.isAdmin() }, Validators.required]
hexColor: [
{
value: null,
disabled: !this.permissionsService.isAdmin()
},
Validators.required
],
opacity: [
{
value: null,
disabled: !this.permissionsService.isAdmin()
},
Validators.required
],
fontSize: [
{
value: null,
disabled: !this.permissionsService.isAdmin()
},
Validators.required
],
fontType: [
{
value: null,
disabled: !this.permissionsService.isAdmin()
},
Validators.required
],
orientation: [
{
value: null,
disabled: !this.permissionsService.isAdmin()
},
Validators.required
]
});
}
}

View File

@ -7,9 +7,9 @@ import { TranslateChartService } from '@services/translate-chart.service';
import { StatusSorter } from '@utils/sorters/status-sorter';
import { UserService } from '@services/user.service';
import { User } from '@redaction/red-ui-http';
import { NotificationService } from '@services/notification.service';
import { FilterService } from '@shared/services/filter.service';
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
import { Toaster } from '../../../../services/toaster.service';
import { FilterService } from '../../../shared/services/filter.service';
import { FileStatusWrapper } from '../../../../models/file/file-status.wrapper';
import { DossierAttributeWithValue } from '@models/dossier-attributes.model';
@Component({
@ -34,7 +34,7 @@ export class DossierDetailsComponent implements OnInit {
readonly filterService: FilterService<FileStatusWrapper>,
private readonly _changeDetectorRef: ChangeDetectorRef,
private readonly _userService: UserService,
private readonly _notificationService: NotificationService
private readonly _toaster: Toaster
) {}
get memberIds(): string[] {
@ -86,6 +86,6 @@ export class DossierDetailsComponent implements OnInit {
const ownerName = this._userService.getNameForId(this.owner.userId);
const dossierName = this.appStateService.activeDossier.name;
const msg = 'Successfully assigned ' + ownerName + ' to dossier: ' + dossierName;
this._notificationService.showToastNotification(msg);
this._toaster.info(msg);
}
}

View File

@ -2,9 +2,9 @@ import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from
import { PermissionsService } from '@services/permissions.service';
import { FormBuilder, FormGroup } from '@angular/forms';
import { PageRange, ReanalysisControllerService } from '@redaction/red-ui-http';
import { FileDataModel } from '@models/file/file-data.model';
import { NotificationService, NotificationType } from '@services/notification.service';
import { LoadingService } from '@services/loading.service';
import { FileDataModel } from '../../../../models/file/file-data.model';
import { Toaster } from '../../../../services/toaster.service';
import { LoadingService } from '../../../../services/loading.service';
import { TranslateService } from '@ngx-translate/core';
@Component({
@ -23,9 +23,8 @@ export class PageExclusionComponent implements OnChanges {
readonly permissionsService: PermissionsService,
private readonly _formBuilder: FormBuilder,
private readonly _reanalysisControllerService: ReanalysisControllerService,
private readonly _notificationService: NotificationService,
private readonly _loadingService: LoadingService,
private readonly _translateService: TranslateService
private readonly _toaster: Toaster,
private readonly _loadingService: LoadingService
) {
this.excludePagesForm = this._formBuilder.group({
value: ['']
@ -80,11 +79,7 @@ export class PageExclusionComponent implements OnChanges {
this.excludePagesForm.reset();
this.actionPerformed.emit('exclude-pages');
} catch (e) {
this._notificationService.showToastNotification(
this._translateService.instant('file-preview.tabs.exclude-pages.error'),
null,
NotificationType.ERROR
);
this._toaster.error('file-preview.tabs.exclude-pages.error');
this._loadingService.stop();
}
}

View File

@ -1,8 +1,8 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { Dossier, DossierControllerService, StatusControllerService } from '@redaction/red-ui-http';
import { Dossier } from '@redaction/red-ui-http';
import { AppStateService } from '@state/app-state.service';
import { UserService } from '@services/user.service';
import { NotificationService, NotificationType } from '@services/notification.service';
import { Toaster } from '../../../../services/toaster.service';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { DossierWrapper } from '@state/model/dossier.wrapper';
@ -21,10 +21,8 @@ export class TeamMembersManagerComponent implements OnInit {
constructor(
readonly userService: UserService,
private readonly _dossierControllerService: DossierControllerService,
private readonly _notificationService: NotificationService,
private readonly _toaster: Toaster,
private readonly _formBuilder: FormBuilder,
private readonly _statusControllerService: StatusControllerService,
private readonly _appStateService: AppStateService
) {}
@ -91,11 +89,7 @@ export class TeamMembersManagerComponent implements OnInit {
result = await this._appStateService.createOrUpdateDossier(dw.dossier);
this.save.emit(result);
} catch (error) {
this._notificationService.showToastNotification(
'Failed: ' + error.error ? error.error.message : error,
null,
NotificationType.ERROR
);
this._toaster.error('Failed: ' + error.error ? error.error.message : error);
}
}

View File

@ -1,9 +1,9 @@
import { Component, Inject } from '@angular/core';
import { DossierControllerService, StatusControllerService } from '@redaction/red-ui-http';
import { StatusControllerService } from '@redaction/red-ui-http';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { AppStateService } from '@state/app-state.service';
import { UserService } from '@services/user.service';
import { NotificationService, NotificationType } from '@services/notification.service';
import { Toaster } from '../../../../services/toaster.service';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
import { DossierWrapper } from '@state/model/dossier.wrapper';
@ -16,7 +16,6 @@ class DialogData {
}
@Component({
selector: 'redaction-dossier-details-dialog',
templateUrl: './assign-reviewer-approver-dialog.component.html',
styleUrls: ['./assign-reviewer-approver-dialog.component.scss']
})
@ -26,13 +25,12 @@ export class AssignReviewerApproverDialogComponent {
constructor(
readonly userService: UserService,
private readonly _dossierControllerService: DossierControllerService,
private readonly _notificationService: NotificationService,
private readonly _toaster: Toaster,
private readonly _formBuilder: FormBuilder,
private readonly _statusControllerService: StatusControllerService,
private readonly _appStateService: AppStateService,
public dialogRef: MatDialogRef<AssignReviewerApproverDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: DialogData
private readonly _dialogRef: MatDialogRef<AssignReviewerApproverDialogComponent>,
@Inject(MAT_DIALOG_DATA) readonly data: DialogData
) {
this._loadData();
}
@ -52,10 +50,8 @@ export class AssignReviewerApproverDialogComponent {
return true;
}
const reviewerId = this.selectedSingleUser;
for (const file of this.data.files) {
if (file.currentReviewer !== reviewerId) {
if (file.currentReviewer !== this.selectedSingleUser) {
return true;
}
}
@ -94,14 +90,10 @@ export class AssignReviewerApproverDialogComponent {
file.reviewerName = this.userService.getNameForId(selectedUser);
}
} catch (error) {
this._notificationService.showToastNotification(
'Failed: ' + error.error ? error.error.message : error,
null,
NotificationType.ERROR
);
this._toaster.error('Failed: ' + error.error ? error.error.message : error);
}
this.dialogRef.close();
this._dialogRef.close();
}
private _loadData() {

View File

@ -1,13 +1,10 @@
import { ChangeDetectorRef, Component, Inject, ViewChild } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { FormBuilder } from '@angular/forms';
import { AppStateService } from '@state/app-state.service';
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
import { DossierWrapper } from '../../../../state/model/dossier.wrapper';
import { EditDossierGeneralInfoComponent } from './general-info/edit-dossier-general-info.component';
import { EditDossierDownloadPackageComponent } from './download-package/edit-dossier-download-package.component';
import { EditDossierSectionInterface } from './edit-dossier-section.interface';
import { NotificationService, NotificationType } from '@services/notification.service';
import { TranslateService } from '@ngx-translate/core';
import { Toaster } from '../../../../services/toaster.service';
import { EditDossierDictionaryComponent } from './dictionary/edit-dossier-dictionary.component';
import { EditDossierTeamMembersComponent } from './team-members/edit-dossier-team-members.component';
import { EditDossierAttributesComponent } from './attributes/edit-dossier-attributes.component';
@ -38,12 +35,8 @@ export class EditDossierDialogComponent {
@ViewChild(EditDossierAttributesComponent) attributesComponent: EditDossierAttributesComponent;
constructor(
private readonly _appStateService: AppStateService,
private readonly _formBuilder: FormBuilder,
private readonly _notificationService: NotificationService,
private readonly _translateService: TranslateService,
private readonly _toaster: Toaster,
private readonly _changeRef: ChangeDetectorRef,
private readonly _dialogRef: MatDialogRef<EditDossierDialogComponent>,
@Inject(MAT_DIALOG_DATA)
private readonly _data: {
dossierWrapper: DossierWrapper;
@ -82,11 +75,7 @@ export class EditDossierDialogComponent {
}
updatedDossier(updatedDossier: DossierWrapper) {
this._notificationService.showToastNotification(
this._translateService.instant('edit-dossier-dialog.change-successful'),
null,
NotificationType.SUCCESS
);
this._toaster.success('edit-dossier-dialog.change-successful');
if (updatedDossier) {
this.dossierWrapper = updatedDossier;
@ -111,11 +100,7 @@ export class EditDossierDialogComponent {
changeTab(key: Section) {
if (this.activeComponent.changed) {
this._notificationService.showToastNotification(
this._translateService.instant('edit-dossier-dialog.unsaved-changes'),
null,
NotificationType.ERROR
);
this._toaster.error('edit-dossier-dialog.unsaved-changes');
return;
}
this.activeNav = key;

View File

@ -10,8 +10,7 @@ import { PermissionsService } from '@services/permissions.service';
import { Router } from '@angular/router';
import { MatDialogRef } from '@angular/material/dialog';
import { EditDossierDialogComponent } from '../edit-dossier-dialog.component';
import { NotificationService, NotificationType } from '../../../../../services/notification.service';
import { TranslateService } from '@ngx-translate/core';
import { Toaster } from '../../../../../services/toaster.service';
@Component({
selector: 'redaction-edit-dossier-general-info',
@ -34,8 +33,7 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti
private readonly _dialogService: DossiersDialogService,
private readonly _router: Router,
private readonly _editDossierDialogRef: MatDialogRef<EditDossierDialogComponent>,
private readonly _notificationService: NotificationService,
private readonly _translateService: TranslateService
private readonly _toaster: Toaster
) {}
get changed() {
@ -113,11 +111,7 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti
}
private _notifyDossierDeleted() {
this._notificationService.showToastNotification(
this._translateService.instant('edit-dossier-dialog.delete-successful'),
null,
NotificationType.SUCCESS
);
this._toaster.success('edit-dossier-dialog.delete-successful');
}
private _filterInvalidDossierTemplates() {

View File

@ -3,7 +3,7 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { AppStateService } from '@state/app-state.service';
import { MatDialogRef } from '@angular/material/dialog';
import { ForceRedactionRequest, LegalBasisMappingControllerService } from '@redaction/red-ui-http';
import { NotificationService } from '@services/notification.service';
import { Toaster } from '../../../../services/toaster.service';
import { TranslateService } from '@ngx-translate/core';
import { UserService } from '@services/user.service';
import { ManualAnnotationService } from '../../services/manual-annotation.service';
@ -29,7 +29,7 @@ export class ForceRedactionDialogComponent implements OnInit {
private readonly _appStateService: AppStateService,
private readonly _userService: UserService,
private readonly _formBuilder: FormBuilder,
private readonly _notificationService: NotificationService,
private readonly _notificationService: Toaster,
private readonly _translateService: TranslateService,
private readonly _legalBasisMappingControllerService: LegalBasisMappingControllerService,
private readonly _manualAnnotationService: ManualAnnotationService,

View File

@ -3,7 +3,7 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { AppStateService } from '@state/app-state.service';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { AddRedactionRequest, LegalBasisMappingControllerService } from '@redaction/red-ui-http';
import { NotificationService } from '@services/notification.service';
import { Toaster } from '../../../../services/toaster.service';
import { TranslateService } from '@ngx-translate/core';
import { UserService } from '@services/user.service';
import { ManualRedactionEntryWrapper } from '@models/file/manual-redaction-entry.wrapper';
@ -37,7 +37,7 @@ export class ManualAnnotationDialogComponent implements OnInit {
private readonly _appStateService: AppStateService,
private readonly _userService: UserService,
private readonly _formBuilder: FormBuilder,
private readonly _notificationService: NotificationService,
private readonly _notificationService: Toaster,
private readonly _translateService: TranslateService,
private readonly _legalBasisMappingControllerService: LegalBasisMappingControllerService,
private readonly _manualAnnotationService: ManualAnnotationService,

View File

@ -1,6 +1,6 @@
import { ChangeDetectorRef, Component, ElementRef, HostListener, Injector, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core';
import { NavigationStart, Router } from '@angular/router';
import { NotificationService, NotificationType } from '@services/notification.service';
import { Toaster } from '../../../../services/toaster.service';
import { AppStateService } from '@state/app-state.service';
import { FileDropOverlayService } from '@upload-download/services/file-drop-overlay.service';
import { FileUploadModel } from '@upload-download/model/file-upload.model';
@ -59,7 +59,7 @@ export class DossierOverviewScreenComponent
constructor(
readonly permissionsService: PermissionsService,
private readonly _userService: UserService,
private readonly _notificationService: NotificationService,
private readonly _toaster: Toaster,
private readonly _dialogService: DossiersDialogService,
private readonly _fileUploadService: FileUploadService,
private readonly _statusOverlayService: StatusOverlayService,
@ -149,19 +149,9 @@ export class DossierOverviewScreenComponent
.reanalyzeDossier()
.then(() => {
this.reloadDossiers();
this._notificationService.showToastNotification(
this._translateService.instant('dossier-overview.reanalyse-dossier.success'),
null,
NotificationType.SUCCESS
);
this._toaster.success('dossier-overview.reanalyse-dossier.success');
})
.catch(() => {
this._notificationService.showToastNotification(
this._translateService.instant('dossier-overview.reanalyse-dossier.error'),
null,
NotificationType.ERROR
);
});
.catch(() => this._toaster.error('dossier-overview.reanalyse-dossier.error'));
}
reloadDossiers() {

View File

@ -12,8 +12,7 @@ import { AnnotationData, FileDataModel } from '@models/file/file-data.model';
import { FileActionService } from '../../services/file-action.service';
import { AnnotationDrawService } from '../../services/annotation-draw.service';
import { AnnotationProcessingService } from '../../services/annotation-processing.service';
import { tap } from 'rxjs/operators';
import { NotificationService } from '@services/notification.service';
import { Toaster } from '../../../../services/toaster.service';
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
import { PermissionsService } from '@services/permissions.service';
import { Subscription, timer } from 'rxjs';
@ -37,6 +36,7 @@ import { handleFilterDelta, processFilters } from '@shared/components/filters/po
import { LoadingService } from '../../../../services/loading.service';
import { stampPDFPage } from '../../../../utils/page-stamper';
import { TranslateService } from '@ngx-translate/core';
import { AutoUnsubscribeComponent } from '../../../shared/base/auto-unsubscribe.component';
const ALL_HOTKEY_ARRAY = ['Escape', 'F', 'f'];
@ -45,7 +45,7 @@ const ALL_HOTKEY_ARRAY = ['Escape', 'F', 'f'];
templateUrl: './file-preview-screen.component.html',
styleUrls: ['./file-preview-screen.component.scss']
})
export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach, OnDetach {
export class FilePreviewScreenComponent extends AutoUnsubscribeComponent implements OnInit, OnDestroy, OnAttach, OnDetach {
dialogRef: MatDialogRef<any>;
viewMode: ViewMode = 'STANDARD';
fullScreen = false;
@ -59,7 +59,6 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
secondaryFilters: FilterModel[];
canPerformAnnotationActions: boolean;
filesAutoUpdateTimer: Subscription;
fileReanalysedSubscription: Subscription;
hideSkipped = false;
displayPDFViewer = false;
viewDocumentInfo = false;
@ -81,7 +80,7 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
private readonly _activatedRoute: ActivatedRoute,
private readonly _dialogService: DossiersDialogService,
private readonly _router: Router,
private readonly _notificationService: NotificationService,
private readonly _toaster: Toaster,
private readonly _annotationProcessingService: AnnotationProcessingService,
private readonly _annotationDrawService: AnnotationDrawService,
private readonly _fileActionService: FileActionService,
@ -92,6 +91,7 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
private readonly _loadingService: LoadingService,
private readonly _translateService: TranslateService
) {
super();
document.documentElement.addEventListener('fullscreenchange', () => {
if (!document.fullscreenElement) {
this.fullScreen = false;
@ -221,7 +221,7 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
ngOnDetach() {
this.displayPDFViewer = false;
this.viewReady = false;
this._unsubscribeFromFileUpdates();
super.ngOnDestroy();
}
async ngOnAttach(previousRoute: ActivatedRouteSnapshot) {
@ -249,10 +249,6 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
this.viewReady = true;
}
ngOnDestroy(): void {
this._unsubscribeFromFileUpdates();
}
rebuildFilters(deletePreviousAnnotations: boolean = false) {
const startTime = new Date().getTime();
if (deletePreviousAnnotations) {
@ -469,7 +465,7 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
await this._statusControllerService.setFileReviewer(dossierId, fileId, reviewerId).toPromise();
const msg = `Successfully assigned ${reviewerName} to file: ${filename}`;
this._notificationService.showToastNotification(msg);
this._toaster.info(msg);
await this.appStateService.reloadActiveFile();
this._updateCanPerformActions();
this.editingReviewer = false;
@ -488,7 +484,7 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
}
downloadOriginalFile() {
this._fileManagementControllerService
this.addSubscription = this._fileManagementControllerService
.downloadOriginalFile(this.dossierId, this.fileId, true, this.fileData.fileStatus.cacheIdentifier, 'response')
.subscribe(data => {
download(data, this.fileData.fileStatus.filename);
@ -539,10 +535,8 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
}
private _subscribeToFileUpdates(): void {
this.filesAutoUpdateTimer = timer(0, 5000)
.pipe(tap(async () => await this.appStateService.reloadActiveFile()))
.subscribe();
this.fileReanalysedSubscription = this.appStateService.fileReanalysed.subscribe(async (fileStatus: FileStatusWrapper) => {
this.addSubscription = timer(0, 5000).subscribe(async () => await this.appStateService.reloadActiveFile());
this.addSubscription = this.appStateService.fileReanalysed.subscribe(async (fileStatus: FileStatusWrapper) => {
if (fileStatus.fileId === this.fileId) {
await this._loadFileData(!this._reloadFileOnReanalysis);
this._reloadFileOnReanalysis = false;
@ -553,11 +547,6 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
});
}
private _unsubscribeFromFileUpdates(): void {
this.filesAutoUpdateTimer.unsubscribe();
this.fileReanalysedSubscription.unsubscribe();
}
private _updateCanPerformActions() {
this.canPerformAnnotationActions =
this.permissionsService.canPerformAnnotationActions() &&

View File

@ -7,7 +7,7 @@ import {
ManualRedactionControllerService
} from '@redaction/red-ui-http';
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
import { NotificationService, NotificationType } from '@services/notification.service';
import { Toaster } from '../../../services/toaster.service';
import { TranslateService } from '@ngx-translate/core';
import { tap } from 'rxjs/operators';
import { UserService } from '@services/user.service';
@ -38,7 +38,7 @@ export class ManualAnnotationService {
private readonly _appStateService: AppStateService,
private readonly _userService: UserService,
private readonly _translateService: TranslateService,
private readonly _notificationService: NotificationService,
private readonly _toaster: Toaster,
private readonly _manualRedactionControllerService: ManualRedactionControllerService,
private readonly _dictionaryControllerService: DictionaryControllerService,
private readonly _permissionsService: PermissionsService
@ -76,8 +76,12 @@ export class ManualAnnotationService {
return obs.pipe(
tap(
() => this._notify(this._getMessage(mode)),
error => this._notify(this._getMessage(mode, modifyDictionary, true), NotificationType.ERROR, error)
() => this._toaster.success(this._getMessage(mode), { positionClass: 'toast-file-preview' }),
error =>
this._toaster.error(this._getMessage(mode, modifyDictionary, true), {
params: error,
positionClass: 'toast-file-preview'
})
)
);
}
@ -223,13 +227,6 @@ export class ManualAnnotationService {
}
}
private _notify(key: string, type: NotificationType = NotificationType.SUCCESS, data?: any) {
this._notificationService.showToastNotification(this._translateService.instant(key, data), null, type, {
positionClass: 'toast-file-preview',
actions: []
});
}
private _getMessage(mode: Mode, modifyDictionary?: boolean, error: boolean = false) {
return (
'annotation-actions.message.' +

View File

@ -3,8 +3,6 @@ import { Subscription } from 'rxjs';
/**
* Inherit this class when you need to subscribe to observables in your components
*
* @remarks You must explicitly call super.ngOnDestroy in you component to unsubscribe
*/
@Component({ template: '' })
export abstract class AutoUnsubscribeComponent implements OnDestroy {
@ -21,7 +19,8 @@ export abstract class AutoUnsubscribeComponent implements OnDestroy {
/**
* This method unsubscribes active subscriptions
* Explicitly call this method in your component's ngOnDestroy
* If you implement OnDestroy in a component that inherits AutoUnsubscribeComponent,
* then you must explicitly call super.ngOnDestroy()
*/
ngOnDestroy(): void {
this._subscriptions.unsubscribe();

View File

@ -5,7 +5,6 @@ import { FilterService } from '../services/filter.service';
import { SearchService } from '../services/search.service';
import { ScreenStateService } from '../services/screen-state.service';
import { Observable } from 'rxjs';
import { FilterModel } from '../components/filters/popup-filter/model/filter.model';
import { AutoUnsubscribeComponent } from './auto-unsubscribe.component';
@Component({ template: '' })

View File

@ -1,11 +1,11 @@
import { ChangeDetectionStrategy, Component, Inject, Input } from '@angular/core';
import { ChangeDetectionStrategy, Component, Inject, Input, OnDestroy } from '@angular/core';
import { PermissionsService } from '@services/permissions.service';
import { DossierWrapper } from '@state/model/dossier.wrapper';
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
import { FileDownloadService } from '@upload-download/services/file-download.service';
import { NotificationService } from '@services/notification.service';
import { TranslateService } from '@ngx-translate/core';
import { Toaster } from '@services/toaster.service';
import { BASE_HREF } from '../../../../../tokens';
import { AutoUnsubscribeComponent } from '@shared/base/auto-unsubscribe.component';
export type MenuState = 'OPEN' | 'CLOSED';
@ -15,7 +15,7 @@ export type MenuState = 'OPEN' | 'CLOSED';
styleUrls: ['./file-download-btn.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class FileDownloadBtnComponent {
export class FileDownloadBtnComponent extends AutoUnsubscribeComponent implements OnDestroy {
@Input() dossier: DossierWrapper;
@Input() file: FileStatusWrapper | FileStatusWrapper[];
@Input() tooltipPosition: 'above' | 'below' | 'before' | 'after' = 'above';
@ -27,9 +27,10 @@ export class FileDownloadBtnComponent {
@Inject(BASE_HREF) private readonly _baseHref: string,
private readonly _permissionsService: PermissionsService,
private readonly _fileDownloadService: FileDownloadService,
private readonly _translateService: TranslateService,
private readonly _notificationService: NotificationService
) {}
private readonly _toaster: Toaster
) {
super();
}
get canDownloadFiles() {
if (!Array.isArray(this.file)) {
@ -41,12 +42,10 @@ export class FileDownloadBtnComponent {
downloadFiles($event: MouseEvent) {
$event.stopPropagation();
this._fileDownloadService.downloadFiles(Array.isArray(this.file) ? this.file : [this.file], this.dossier).subscribe(() => {
this._notificationService.showToastNotification(
this._translateService.instant('download-status.queued', {
baseUrl: this._baseHref
})
);
});
this.addSubscription = this._fileDownloadService
.downloadFiles(Array.isArray(this.file) ? this.file : [this.file], this.dossier)
.subscribe(() => {
this._toaster.info('download-status.queued', { params: { baseUrl: this._baseHref } });
});
}
}

View File

@ -1,7 +1,6 @@
import { Injectable } from '@angular/core';
import { Observable, throwError } from 'rxjs';
import { NotificationService, NotificationType } from '@services/notification.service';
import { TranslateService } from '@ngx-translate/core';
import { Toaster } from '../../../services/toaster.service';
import { DictionaryControllerService } from '@redaction/red-ui-http';
import { tap } from 'rxjs/operators';
@ -11,11 +10,7 @@ const MIN_WORD_LENGTH = 2;
providedIn: 'root'
})
export class DictionarySaveService {
constructor(
private readonly _notificationService: NotificationService,
private readonly _translateService: TranslateService,
private readonly _dictionaryControllerService: DictionaryControllerService
) {}
constructor(private readonly _toaster: Toaster, private readonly _dictionaryControllerService: DictionaryControllerService) {}
saveEntries(
entries: string[],
@ -44,29 +39,13 @@ export class DictionarySaveService {
return obs.pipe(
tap(
() => {
if (showToast) {
this._notificationService.showToastNotification(
this._translateService.instant('dictionary-overview.success.generic'),
null,
NotificationType.SUCCESS
);
}
if (showToast) this._toaster.success('dictionary-overview.success.generic');
},
() => {
this._notificationService.showToastNotification(
this._translateService.instant('dictionary-overview.error.generic'),
null,
NotificationType.ERROR
);
}
() => this._toaster.error('dictionary-overview.error.generic')
)
);
} else {
this._notificationService.showToastNotification(
this._translateService.instant('dictionary-overview.error.entries-too-short'),
null,
NotificationType.ERROR
);
this._toaster.error('dictionary-overview.error.entries-too-short');
return throwError('Entries too short');
}

View File

@ -8,11 +8,11 @@ import { HttpErrorResponse } from '@angular/common/http';
export class ErrorMessageService {
constructor(private readonly _translateService: TranslateService) {}
_parseErrorResponse(err: HttpErrorResponse) {
_parseErrorResponse(err: HttpErrorResponse): string {
return err?.error?.message?.includes('message') ? ` ${err.error.message.match('"message":"(.*?)\\"')[1]}` : '';
}
getMessage(err: HttpErrorResponse, defaultMessage: string) {
return this._translateService.instant(defaultMessage) + this._parseErrorResponse(err);
getMessage(error: HttpErrorResponse, defaultMessage: string): string {
return this._translateService.instant(defaultMessage) + this._parseErrorResponse(error);
}
}

View File

@ -1,47 +0,0 @@
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';
export enum NotificationType {
SUCCESS = 'SUCCESS',
WARNING = 'WARNING',
ERROR = 'ERROR',
INFO = 'INFO'
}
export class ToastAction {
title: string;
action?: () => any;
}
@Injectable({
providedIn: 'root'
})
export class NotificationService {
constructor(private readonly _toastr: ToastrService, private readonly _router: Router) {
_router.events.subscribe(event => {
if (event instanceof NavigationStart) {
this._toastr.clear();
}
});
}
showToastNotification(
message: string,
title?: string,
notificationType = NotificationType.INFO,
options?: Partial<IndividualConfig> & { actions?: ToastAction[] }
): ActiveToast<any> {
switch (notificationType) {
case NotificationType.ERROR:
return this._toastr.error(message, title, options);
case NotificationType.SUCCESS:
return this._toastr.success(message, title, options);
case NotificationType.WARNING:
return this._toastr.warning(message, title, options);
case NotificationType.INFO:
return this._toastr.info(message, title, options);
}
}
}

View File

@ -0,0 +1,82 @@
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 { ErrorMessageService } from '@services/error-message.service';
import { filter } from 'rxjs/operators';
export enum NotificationType {
SUCCESS = 'SUCCESS',
WARNING = 'WARNING',
INFO = 'INFO'
}
export interface ToasterOptions extends IndividualConfig {
title?: string;
/**
* These params are used as interpolateParams for translate service
*/
params?: object;
actions?: { title?: string; action: () => void }[];
}
export interface ErrorToasterOptions extends ToasterOptions {
/**
* Pass an http error that will be processed by error message service and shown in toast
*/
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<ErrorToasterOptions>) {
if (options?.error) message = this._errorMessageService.getMessage(options.error, message);
else message = this._translateService.instant(message, options?.params);
return this._toastr.error(message, options?.title, options);
}
info(message: string, options?: Partial<ToasterOptions>) {
return this._showToastNotification(message, NotificationType.INFO, options);
}
success(message: string, options?: Partial<ToasterOptions>) {
return this._showToastNotification(message, NotificationType.SUCCESS, options);
}
warning(message: string, options?: Partial<ToasterOptions>) {
return this._showToastNotification(message, NotificationType.WARNING, options);
}
private _showToastNotification(
message: string,
notificationType = NotificationType.INFO,
options?: Partial<ToasterOptions>
): ActiveToast<any> {
message = this._translateService.instant(message, options?.params);
switch (notificationType) {
case NotificationType.SUCCESS:
return this._toastr.success(message, options?.title, options);
case NotificationType.WARNING:
return this._toastr.warning(message, options?.title, options);
case NotificationType.INFO:
return this._toastr.info(message, options?.title, options);
}
}
}

View File

@ -9,7 +9,7 @@ import {
ReanalysisControllerService,
StatusControllerService
} from '@redaction/red-ui-http';
import { NotificationService, NotificationType } from '@services/notification.service';
import { Toaster } from '../services/toaster.service';
import { TranslateService } from '@ngx-translate/core';
import { Event, NavigationEnd, ResolveStart, Router } from '@angular/router';
import { UserService } from '@services/user.service';
@ -47,7 +47,7 @@ export class AppStateService {
private readonly _router: Router,
private readonly _userService: UserService,
private readonly _dossiersService: DossiersService,
private readonly _notificationService: NotificationService,
private readonly _toaster: Toaster,
private readonly _reanalysisControllerService: ReanalysisControllerService,
private readonly _translateService: TranslateService,
private readonly _dictionaryControllerService: DictionaryControllerService,
@ -239,7 +239,7 @@ export class AppStateService {
this.activeDossierTemplateId,
this._appState.fileAttributesConfig[this.activeDossierTemplateId]
);
this.activeDossier.files = this.activeDossier.files.map(file =>
this.activeDossier.files = this.activeDossier?.files.map(file =>
file.fileId === activeFileWrapper.fileId ? activeFileWrapper : file
);
@ -330,13 +330,7 @@ export class AppStateService {
const index = this.allDossiers.findIndex(p => p.dossierId === dossier.dossierId);
this._appState.dossiers.splice(index, 1);
},
() => {
this._notificationService.showToastNotification(
this._translateService.instant('dossiers.delete.delete-failed', dossier),
null,
NotificationType.ERROR
);
}
() => this._toaster.error('dossiers.delete.delete-failed', { params: dossier })
);
}
@ -353,12 +347,8 @@ export class AppStateService {
this._appState.dossiers = [...this._appState.dossiers];
return foundDossier;
} catch (error) {
this._notificationService.showToastNotification(
this._translateService.instant(
error.status === 409 ? 'add-dossier-dialog.errors.dossier-already-exists' : 'add-dossier-dialog.errors.generic'
),
null,
NotificationType.ERROR
this._toaster.error(
error.status === 409 ? 'add-dossier-dialog.errors.dossier-already-exists' : 'add-dossier-dialog.errors.generic'
);
}
}