Add notification messages on click save of user profile

This commit is contained in:
apapachristou 2020-11-17 19:57:39 +02:00
parent af849b6c36
commit 644d616ef8
3 changed files with 94 additions and 21 deletions

View File

@ -20,14 +20,14 @@
<div class="row mb-5">
<div class="col">
<div class="row">
<div class="col-auto field-title">{{'USER-PROFILE.SETTINGS.NAME' | translate}}</div>
<div class="col-auto field-title">{{'USER-PROFILE.SETTINGS.NAME' | translate}} *</div>
</div>
<div class="row">
<div class="col name-form">
<mat-form-field>
<input matInput type="text" name="name" [formControl]="formGroup.get('name')" required>
<!-- <mat-error *ngIf="formGroup.get('label').hasError('backendError')">{{formGroup.get('label').getError('backendError').message}}</mat-error>
<mat-error *ngIf="formGroup.get('label').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error> -->
<input matInput type="text" name="name" placeholder="{{'USER-PROFILE.SETTINGS.NAME' | translate}}" [formControl]="formGroup.get('name')" required>
<!-- <mat-error *ngIf="formGroup.get('name').hasError('backendError')">{{formGroup.get('name').getError('backendError').message}}</mat-error> -->
<mat-error *ngIf="formGroup.get('name').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
</div>
</div>
@ -124,7 +124,7 @@
<div class="row mb-5">
<div class="col">
<div class="row">
<div class="col-auto field-title">{{'USER-PROFILE.SETTINGS.TIMEZONE' | translate}}</div>
<div class="col-auto field-title">{{'USER-PROFILE.SETTINGS.TIMEZONE' | translate}} *</div>
</div>
<div class="row">
<div class="col timezone-form">
@ -135,6 +135,7 @@
{{ timezone | timezoneInfoDisplay }}
</mat-option>
</mat-autocomplete>
<mat-error *ngIf="this.formGroup.get('timezone').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
</div>
</div>
@ -144,7 +145,7 @@
<div class="row mb-5">
<div class="col">
<div class="row">
<div class="col-auto field-title">{{'USER-PROFILE.SETTINGS.CULTURE' | translate}}</div>
<div class="col-auto field-title">{{'USER-PROFILE.SETTINGS.CULTURE' | translate}} *</div>
</div>
<div class="row">
<div class="col culture-form">
@ -155,6 +156,7 @@
{{ culture.displayName }} - {{ culture.nativeName }}
</mat-option>
</mat-autocomplete>
<mat-error *ngIf="this.formGroup.get('culture').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
</div>
</div>
@ -164,7 +166,7 @@
<div class="row mb-5">
<div class="col">
<div class="row">
<div class="col-auto field-title">{{'USER-PROFILE.SETTINGS.LANGUAGE' | translate}}</div>
<div class="col-auto field-title">{{'USER-PROFILE.SETTINGS.LANGUAGE' | translate}} *</div>
</div>
<div class="row">
<div class="col language-form">
@ -174,6 +176,7 @@
{{ language.label | translate }}
</mat-option>
</mat-select>
<mat-error *ngIf="this.formGroup.get('language').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
</div>
</div>

View File

@ -1,5 +1,5 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
import { FormArray, FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
import { ActivatedRoute, Params, Router } from '@angular/router';
import { CultureInfo } from '@app/core/model/culture-info';
import { DmpModel } from '@app/core/model/dmp/dmp';
@ -27,6 +27,8 @@ import { MatDialog } from '@angular/material';
import { UserCredentialModel } from '@app/core/model/user/user-credential';
import { AuthProvider } from '@app/core/common/enum/auth-provider';
import { MergeEmailConfirmationService } from '@app/core/services/merge-email-confirmation/merge-email-confirmation.service';
import { FormValidationErrorsDialogComponent } from '@common/forms/form-validation-errors-dialog/form-validation-errors-dialog.component';
import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service';
const availableLanguages: any[] = require('../../../assets/resources/language.json');
@ -50,6 +52,9 @@ export class UserProfileComponent extends BaseComponent implements OnInit, OnDes
roleOrganizationEnum = RoleOrganizationType;
authProviderEnum = AuthProvider;
private oauthLock: boolean;
errorMessages = [];
nestedCount = [];
nestedIndex = 0;
organisationsAutoCompleteConfiguration: MultipleAutoCompleteConfiguration = {
filterFn: this.filterOrganisations.bind(this),
@ -72,6 +77,7 @@ export class UserProfileComponent extends BaseComponent implements OnInit, OnDes
private languageService: LanguageService,
private configurationService: ConfigurationService,
private oauth2DialogService: Oauth2DialogService,
private uiNotificationService: UiNotificationService,
private dialog: MatDialog,
public enumUtils: EnumUtils,
private mergeEmailConfirmation: MergeEmailConfirmationService
@ -98,20 +104,20 @@ export class UserProfileComponent extends BaseComponent implements OnInit, OnDes
//this.formGroup.get('language').valueChanges.pipe(takeUntil(this._destroyed)).subscribe(x => { if (x) this.translate.use(x.value) })
this.formGroup.get('timezone').valueChanges
.pipe(takeUntil(this._destroyed))
.subscribe(x => { if (x) { this.timezones = this._filterTimezone(x); } });
.pipe(takeUntil(this._destroyed))
.subscribe(x => { if (x) { this.timezones = this._filterTimezone(x); } });
this.formGroup.get('culture').valueChanges
.pipe(takeUntil(this._destroyed))
.subscribe(x => { if (x) { this.cultures = this._filterCulture(x); } });
.pipe(takeUntil(this._destroyed))
.subscribe(x => { if (x) { this.cultures = this._filterCulture(x); } });
// this.initializeDisabledFormGroup();
this.unlock();
return result;
}));
this.userService.getEmails(userId).pipe(takeUntil(this._destroyed))
.subscribe(result => {
this.userCredentials = result;
});
.subscribe(result => {
this.userCredentials = result;
});
});
}
@ -166,7 +172,14 @@ export class UserProfileComponent extends BaseComponent implements OnInit, OnDes
}
save() {
if (!this.formGroup.valid) { return; }
if (!this.formGroup.valid) {
this.printErrors(this.formGroup);
this.showValidationErrorsDialog();
this.nestedCount = [];
this.nestedIndex = 0;
this.errorMessages = [];
return;
}
this.userService.updateUserSettings(this.formGroup.value)
.pipe(takeUntil(this._destroyed))
.subscribe(
@ -176,7 +189,10 @@ export class UserProfileComponent extends BaseComponent implements OnInit, OnDes
this.authService.current().culture = this.formGroup.value.culture.name;
this.authService.me()
.pipe(takeUntil(this._destroyed))
.subscribe(result => this.router.navigate(['/profile']));
.subscribe(result => {
this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE'), SnackBarNotificationLevel.Success);
this.router.navigate(['/profile']);
});
// .subscribe(result => window.location.reload());
},
error => {
@ -213,6 +229,18 @@ export class UserProfileComponent extends BaseComponent implements OnInit, OnDes
});
}
private showValidationErrorsDialog(projectOnly?: boolean) {
const dialogRef = this.dialog.open(FormValidationErrorsDialogComponent, {
disableClose: true,
autoFocus: false,
restoreFocus: false,
data: {
errorMessages: this.errorMessages,
projectOnly: projectOnly
},
});
}
public applyFallbackAvatar(ev: Event) {
(ev.target as HTMLImageElement).src = 'assets/images/profile-placeholder.png';
}
@ -253,8 +281,8 @@ export class UserProfileComponent extends BaseComponent implements OnInit, OnDes
public RemoveZenodo() {
this.userService.deleteDOIToken()
.pipe(takeUntil(this._destroyed))
.subscribe(() => this.router.navigate(['/reload']).then(() => this.router.navigate(['/profile'])));
.pipe(takeUntil(this._destroyed))
.subscribe(() => this.router.navigate(['/reload']).then(() => this.router.navigate(['/profile'])));
}
public removeAccount() {
@ -272,9 +300,49 @@ export class UserProfileComponent extends BaseComponent implements OnInit, OnDes
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
if (result) {
this.mergeEmailConfirmation.sendConfirmationEmail(result).pipe(takeUntil(this._destroyed))
.subscribe(res => {}, err => {});
.subscribe(res => { }, err => { });
}
});
}
printErrors(rootform: FormGroup) {
if (!rootform.valid) {
Object.keys(rootform.controls).forEach(key => {
const errors = rootform.get(key).errors;
if (errors !== null) {
let numbering: string = '';
for (let j = 0; j < this.nestedCount.length; j++) {
numbering += this.nestedCount[j];
if (j < this.nestedIndex) {
numbering += '.';
} else {
break;
}
}
Object.keys(errors).forEach(keyError => {
if (typeof errors[keyError] === 'boolean') {
this.errorMessages.push(numbering + ' ' + key + ' is ' + keyError);
} else {
this.errorMessages.push(numbering + ' ' + key + ': ' + keyError + ': ' + JSON.stringify(errors[keyError]));
}
});
} else {
if (rootform.get(key) instanceof FormGroup) {
this.printErrors(<FormGroup>rootform.get(key));
} else if (rootform.get(key) instanceof FormArray) {
this.nestedIndex++;
this.nestedCount[this.nestedIndex] = 0;
for (let childForm of (<FormArray>rootform.get(key)).controls) {
this.nestedCount[this.nestedIndex]++;
this.printErrors(<any>childForm);
}
this.nestedCount[this.nestedIndex] = 0;
this.nestedIndex--;
}
}
});
}
}
}

View File

@ -2,6 +2,7 @@ import { NgModule } from '@angular/core';
import { FormattingModule } from '@app/core/formatting.module';
import { AutoCompleteModule } from '@app/library/auto-complete/auto-complete.module';
import { CommonFormsModule } from '@common/forms/common-forms.module';
import { FormValidationErrorsDialogModule } from '@common/forms/form-validation-errors-dialog/form-validation-errors-dialog.module';
import { CommonUiModule } from '@common/ui/common-ui.module';
import { LoginComponent } from '../auth/login/login.component';
import { LoginModule } from '../auth/login/login.module';
@ -17,7 +18,8 @@ import { UserProfileRoutingModule } from './user-profile.routing';
FormattingModule,
UserProfileRoutingModule,
AutoCompleteModule,
AddAccountDialogModule
AddAccountDialogModule,
FormValidationErrorsDialogModule
],
declarations: [
UserProfileComponent