-
{{'USER-PROFILE.SETTINGS.LANGUAGE' | translate}}
+
{{'USER-PROFILE.SETTINGS.LANGUAGE' | translate}} *
@@ -174,6 +176,7 @@
{{ language.label | translate }}
+ {{'GENERAL.VALIDATION.REQUIRED' | translate}}
diff --git a/dmp-frontend/src/app/ui/user-profile/user-profile.component.ts b/dmp-frontend/src/app/ui/user-profile/user-profile.component.ts
index 727bada0e..86f815057 100644
--- a/dmp-frontend/src/app/ui/user-profile/user-profile.component.ts
+++ b/dmp-frontend/src/app/ui/user-profile/user-profile.component.ts
@@ -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(
rootform.get(key));
+ } else if (rootform.get(key) instanceof FormArray) {
+ this.nestedIndex++;
+ this.nestedCount[this.nestedIndex] = 0;
+ for (let childForm of (rootform.get(key)).controls) {
+ this.nestedCount[this.nestedIndex]++;
+ this.printErrors(childForm);
+ }
+ this.nestedCount[this.nestedIndex] = 0;
+ this.nestedIndex--;
+
+ }
+ }
+ });
+ }
+ }
+
}
diff --git a/dmp-frontend/src/app/ui/user-profile/user-profile.module.ts b/dmp-frontend/src/app/ui/user-profile/user-profile.module.ts
index bdbce2b15..c5efaeb7c 100644
--- a/dmp-frontend/src/app/ui/user-profile/user-profile.module.ts
+++ b/dmp-frontend/src/app/ui/user-profile/user-profile.module.ts
@@ -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