updated PendingChangesGuard and used it for user profile and notifications preferences screens
This commit is contained in:
parent
d30c270d72
commit
3c697c643c
@ -1,40 +1,32 @@
|
||||
import { CanDeactivate } from '@angular/router';
|
||||
import { Directive, HostListener, Injectable } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { map, Observable } from 'rxjs';
|
||||
import { ConfirmationDialogService } from '../../../../../libs/common-ui/src/lib/dialog/confirmation-dialog.service';
|
||||
import { FormGroup } from '@angular/forms';
|
||||
import { ConfirmOptions } from '../../../../../libs/common-ui/src';
|
||||
|
||||
export interface ComponentCanDeactivate {
|
||||
hasChanges: boolean;
|
||||
}
|
||||
|
||||
@Directive()
|
||||
export abstract class ComponentHasChanges implements ComponentCanDeactivate {
|
||||
abstract hasChanges: boolean;
|
||||
|
||||
protected constructor(protected _translateService: TranslateService) {}
|
||||
|
||||
@HostListener('window:beforeunload', ['$event'])
|
||||
unloadNotification($event: any) {
|
||||
if (this.hasChanges) {
|
||||
// This message will be displayed in IE/Edge
|
||||
$event.returnValue = this._translateService.instant('pending-changes-guard');
|
||||
}
|
||||
}
|
||||
changed: boolean;
|
||||
form: FormGroup;
|
||||
save: () => Promise<void>;
|
||||
}
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class PendingChangesGuard implements CanDeactivate<ComponentCanDeactivate> {
|
||||
constructor(private readonly _translateService: TranslateService) {}
|
||||
constructor(private _dialogService: ConfirmationDialogService) {}
|
||||
|
||||
canDeactivate(component: ComponentCanDeactivate): boolean | Observable<boolean> {
|
||||
// if there are no pending changes, just allow deactivation; else confirm first
|
||||
return !component.hasChanges
|
||||
? true
|
||||
: // NOTE: this warning message will only be shown when navigating elsewhere
|
||||
// within your angular app;
|
||||
// when navigating away from your angular app,
|
||||
// the browser will show a generic warning message
|
||||
// see http://stackoverflow.com/a/42207299/7307355
|
||||
confirm(this._translateService.instant('pending-changes-guard'));
|
||||
if (component.changed) {
|
||||
const dialogRef = this._dialogService.openDialog({ disableConfirm: component.form.invalid });
|
||||
return dialogRef.afterClosed().pipe(
|
||||
map(result => {
|
||||
if (result === ConfirmOptions.CONFIRM) {
|
||||
component.save();
|
||||
}
|
||||
return !!result;
|
||||
}),
|
||||
);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<form (submit)="save()" [formGroup]="formGroup">
|
||||
<form (submit)="save()" [formGroup]="form">
|
||||
<div class="dialog-content">
|
||||
<div *ngFor="let category of notificationCategories">
|
||||
<div class="iqser-input-group header w-full">
|
||||
@ -36,7 +36,7 @@
|
||||
</div>
|
||||
|
||||
<div class="dialog-actions">
|
||||
<button [disabled]="formGroup.invalid" color="primary" mat-flat-button type="submit">
|
||||
<button [disabled]="form.invalid" color="primary" mat-flat-button type="submit">
|
||||
{{ 'user-profile-screen.actions.save' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@ -10,6 +10,7 @@ import {
|
||||
NotificationGroupsKeys,
|
||||
NotificationGroupsValues,
|
||||
} from '@red/domain';
|
||||
import { BaseFormComponent } from '../../../../../../../../../libs/common-ui/src/lib/form/base-form.component';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-notifications-screen',
|
||||
@ -17,57 +18,57 @@ import {
|
||||
styleUrls: ['./notifications-screen.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class NotificationsScreenComponent implements OnInit {
|
||||
export class NotificationsScreenComponent extends BaseFormComponent implements OnInit {
|
||||
readonly emailNotificationScheduleTypes = EmailNotificationScheduleTypesValues;
|
||||
readonly notificationCategories = NotificationCategoriesValues;
|
||||
readonly notificationGroupsKeys = NotificationGroupsKeys;
|
||||
readonly notificationGroupsValues = NotificationGroupsValues;
|
||||
readonly translations = notificationsTranslations;
|
||||
|
||||
readonly formGroup: FormGroup = this._getForm();
|
||||
|
||||
constructor(
|
||||
private readonly _toaster: Toaster,
|
||||
private readonly _formBuilder: FormBuilder,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _notificationPreferencesService: NotificationPreferencesService,
|
||||
) {}
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
async ngOnInit(): Promise<void> {
|
||||
await this._initializeForm();
|
||||
}
|
||||
|
||||
isCategoryActive(category: string) {
|
||||
return this.formGroup.get(`${category}Enabled`).value;
|
||||
return this.form.get(`${category}Enabled`).value;
|
||||
}
|
||||
|
||||
setEmailNotificationType(type: string) {
|
||||
this.formGroup.get('emailNotificationType').setValue(type);
|
||||
this.form.get('emailNotificationType').setValue(type);
|
||||
}
|
||||
|
||||
getEmailNotificationType() {
|
||||
return this.formGroup.get('emailNotificationType').value;
|
||||
return this.form.get('emailNotificationType').value;
|
||||
}
|
||||
|
||||
isPreferenceChecked(category: string, preference: string) {
|
||||
return this.formGroup.get(category).value.includes(preference);
|
||||
return this.form.get(category).value.includes(preference);
|
||||
}
|
||||
|
||||
addRemovePreference(checked: boolean, category: string, preference: string) {
|
||||
const preferences = this.formGroup.get(category).value;
|
||||
const preferences = this.form.get(category).value;
|
||||
if (checked) {
|
||||
preferences.push(preference);
|
||||
} else {
|
||||
const indexOfPreference = preferences.indexOf(preference);
|
||||
preferences.splice(indexOfPreference, 1);
|
||||
}
|
||||
this.formGroup.get(category).setValue(preferences);
|
||||
this.form.get(category).setValue(preferences);
|
||||
}
|
||||
|
||||
async save() {
|
||||
this._loadingService.start();
|
||||
try {
|
||||
await this._notificationPreferencesService.update(this.formGroup.value).toPromise();
|
||||
await this._notificationPreferencesService.update(this.form.value).toPromise();
|
||||
} catch (e) {
|
||||
this._toaster.error(_('notifications-screen.error.generic'));
|
||||
}
|
||||
@ -87,8 +88,10 @@ export class NotificationsScreenComponent implements OnInit {
|
||||
private async _initializeForm() {
|
||||
this._loadingService.start();
|
||||
|
||||
this.form = this._getForm();
|
||||
const notificationPreferences = await this._notificationPreferencesService.get().toPromise();
|
||||
this.formGroup.patchValue(notificationPreferences);
|
||||
this.form.patchValue(notificationPreferences);
|
||||
this.initialFormValue = JSON.parse(JSON.stringify(this.form.getRawValue()));
|
||||
|
||||
this._loadingService.stop();
|
||||
}
|
||||
|
||||
@ -3,8 +3,9 @@ import { RouterModule } from '@angular/router';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { SharedModule } from '@shared/shared.module';
|
||||
import { NotificationsScreenComponent } from './notifications-screen/notifications-screen.component';
|
||||
import { PendingChangesGuard } from '../../../../guards/can-deactivate.guard';
|
||||
|
||||
const routes = [{ path: '', component: NotificationsScreenComponent }];
|
||||
const routes = [{ path: '', component: NotificationsScreenComponent, canDeactivate: [PendingChangesGuard] }];
|
||||
|
||||
@NgModule({
|
||||
declarations: [NotificationsScreenComponent],
|
||||
|
||||
@ -9,6 +9,8 @@ import { PermissionsService } from '../../../../../services/permissions.service'
|
||||
import { UserService } from '../../../../../services/user.service';
|
||||
import { ConfigService } from '../../../../../services/config.service';
|
||||
import { LanguageService } from '../../../../../i18n/language.service';
|
||||
import { ConfirmationDialogService } from '../../../../../../../../../libs/common-ui/src/lib/dialog/confirmation-dialog.service';
|
||||
import { BaseFormComponent } from '../../../../../../../../../libs/common-ui/src/lib/form/base-form.component';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-user-profile-screen',
|
||||
@ -16,8 +18,7 @@ import { LanguageService } from '../../../../../i18n/language.service';
|
||||
styleUrls: ['./user-profile-screen.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class UserProfileScreenComponent implements OnInit {
|
||||
readonly form: FormGroup = this._getForm();
|
||||
export class UserProfileScreenComponent extends BaseFormComponent implements OnInit {
|
||||
changePasswordUrl: SafeResourceUrl;
|
||||
translations = languagesTranslations;
|
||||
|
||||
@ -30,11 +31,12 @@ export class UserProfileScreenComponent implements OnInit {
|
||||
private readonly _configService: ConfigService,
|
||||
private readonly _languageService: LanguageService,
|
||||
private readonly _domSanitizer: DomSanitizer,
|
||||
private readonly _translateService: TranslateService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _dialogService: ConfirmationDialogService,
|
||||
protected readonly _translateService: TranslateService,
|
||||
) {
|
||||
super();
|
||||
this._loadingService.start();
|
||||
|
||||
this.changePasswordUrl = this._domSanitizer.bypassSecurityTrustResourceUrl(
|
||||
`${this._configService.values.OAUTH_URL}/account/password`,
|
||||
);
|
||||
@ -100,6 +102,7 @@ export class UserProfileScreenComponent implements OnInit {
|
||||
|
||||
private _initializeForm(): void {
|
||||
try {
|
||||
this.form = this._getForm();
|
||||
this._profileModel = {
|
||||
email: this._userService.currentUser.email,
|
||||
firstName: this._userService.currentUser.firstName,
|
||||
@ -111,6 +114,7 @@ export class UserProfileScreenComponent implements OnInit {
|
||||
this.form.get('email').disable();
|
||||
}
|
||||
this.form.patchValue(this._profileModel, { emitEvent: false });
|
||||
this.initialFormValue = this.form.getRawValue();
|
||||
} catch (e) {
|
||||
} finally {
|
||||
this._loadingService.stop();
|
||||
|
||||
@ -3,8 +3,9 @@ import { RouterModule } from '@angular/router';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { SharedModule } from '@shared/shared.module';
|
||||
import { UserProfileScreenComponent } from './user-profile-screen/user-profile-screen.component';
|
||||
import { PendingChangesGuard } from '../../../../guards/can-deactivate.guard';
|
||||
|
||||
const routes = [{ path: '', component: UserProfileScreenComponent }];
|
||||
const routes = [{ path: '', component: UserProfileScreenComponent, canDeactivate: [PendingChangesGuard] }];
|
||||
|
||||
@NgModule({
|
||||
declarations: [UserProfileScreenComponent],
|
||||
|
||||
@ -3,7 +3,6 @@ import { AppStateService } from '@state/app-state.service';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { saveAs } from 'file-saver';
|
||||
import { ComponentHasChanges } from '@guards/can-deactivate.guard';
|
||||
import { AdminDialogService } from '../../services/admin-dialog.service';
|
||||
import { DictionaryManagerComponent } from '@shared/components/dictionary-manager/dictionary-manager.component';
|
||||
import { DictionaryService } from '@shared/services/dictionary.service';
|
||||
@ -16,7 +15,7 @@ import { Dictionary } from '@red/domain';
|
||||
templateUrl: './dictionary-overview-screen.component.html',
|
||||
styleUrls: ['./dictionary-overview-screen.component.scss'],
|
||||
})
|
||||
export class DictionaryOverviewScreenComponent extends ComponentHasChanges implements OnInit, OnDestroy {
|
||||
export class DictionaryOverviewScreenComponent implements OnInit, OnDestroy {
|
||||
readonly circleButtonTypes = CircleButtonTypes;
|
||||
readonly currentUser = this._userService.currentUser;
|
||||
|
||||
@ -37,9 +36,7 @@ export class DictionaryOverviewScreenComponent extends ComponentHasChanges imple
|
||||
private readonly _dialogService: AdminDialogService,
|
||||
protected readonly _translateService: TranslateService,
|
||||
private readonly _dictionaryService: DictionaryService,
|
||||
) {
|
||||
super(_translateService);
|
||||
}
|
||||
) {}
|
||||
|
||||
get hasChanges() {
|
||||
return this._dictionaryManager.editor.hasChanges;
|
||||
|
||||
@ -3,7 +3,6 @@ import { PermissionsService } from '@services/permissions.service';
|
||||
import { Debounce, IconButtonTypes, LoadingService, Toaster } from '@iqser/common-ui';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { saveAs } from 'file-saver';
|
||||
import { ComponentHasChanges } from '@guards/can-deactivate.guard';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { RulesService } from '../../services/rules.service';
|
||||
@ -17,7 +16,7 @@ import IStandaloneEditorConstructionOptions = monaco.editor.IStandaloneEditorCon
|
||||
styleUrls: ['./rules-screen.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class RulesScreenComponent extends ComponentHasChanges implements OnInit {
|
||||
export class RulesScreenComponent implements OnInit {
|
||||
readonly iconButtonTypes = IconButtonTypes;
|
||||
readonly editorOptions: IStandaloneEditorConstructionOptions = {
|
||||
theme: 'vs',
|
||||
@ -43,9 +42,7 @@ export class RulesScreenComponent extends ComponentHasChanges implements OnInit
|
||||
private readonly _toaster: Toaster,
|
||||
protected readonly _translateService: TranslateService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
) {
|
||||
super(_translateService);
|
||||
}
|
||||
) {}
|
||||
|
||||
get hasChanges(): boolean {
|
||||
return this.currentLines.toString() !== this.initialLines.toString();
|
||||
|
||||
@ -1 +1 @@
|
||||
Subproject commit 2e36f3cac77411c4cef0ec5b51165aa62a9d075c
|
||||
Subproject commit 867d7b089ee3d10abf42bf6957c02f7f48ffdb7f
|
||||
Loading…
x
Reference in New Issue
Block a user