Dataset Wizard. Table Of Contents entries show error state (not visible yet, only implementation). Fix Bug on DMP Editor: "Save & Add" doesn't validate datasets to proceed anymore.
This commit is contained in:
parent
6f52f77459
commit
97db10be12
|
@ -54,7 +54,7 @@
|
|||
<div (click)="changeStep(0)" *ngIf="datasetInfoValid()" class="main-info" [ngClass]="{'active': this.step === 0}">0. {{'DMP-EDITOR.STEPPER.MAIN-INFO' | translate}} (<mat-icon class="done-icon">done</mat-icon>)</div>
|
||||
<div class="row toc-pane-container" #boundary (click)="changeStep(1)">
|
||||
<div #spacer></div>
|
||||
<table-of-contents [TOCENTRY_ID_PREFIX]="TOCENTRY_ID_PREFIX" [hasFocus]="step === 1" [formGroup]="formGroup" *ngIf="formGroup && formGroup.get('datasetProfileDefinition')" [links]="links" [boundary]="boundary" [spacer]="spacer" [isActive]="step !== 0" stickyThing (stepFound)="onStepFound($event)" (currentLinks)="getLinks($event)" [visibilityRules]="formGroup.get('datasetProfileDefinition').get('rules').value"></table-of-contents>
|
||||
<table-of-contents [showErrors]="showtocentriesErrors" [TOCENTRY_ID_PREFIX]="TOCENTRY_ID_PREFIX" [hasFocus]="step === 1" [formGroup]="formGroup" *ngIf="formGroup && formGroup.get('datasetProfileDefinition')" [links]="links" [boundary]="boundary" [spacer]="spacer" [isActive]="step !== 0" stickyThing (stepFound)="onStepFound($event)" (currentLinks)="getLinks($event)" [visibilityRules]="formGroup.get('datasetProfileDefinition').get('rules').value"></table-of-contents>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -88,6 +88,9 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <mat-slide-toggle [(ngModel)]="showtocentriesErrors">
|
||||
|
||||
</mat-slide-toggle> -->
|
||||
|
||||
<!-- <div class="row">
|
||||
<div class="col-12">
|
||||
|
|
|
@ -92,6 +92,7 @@ export class DatasetWizardComponent extends BaseComponent implements OnInit, IBr
|
|||
links: Link[] = [];
|
||||
//the table seraches for elements to scroll on page with id (TOCENTRY_ID_PREFIX+fieldsetId<Tocentry>)
|
||||
TOCENTRY_ID_PREFIX="TocEntRy";
|
||||
showtocentriesErrors = false;
|
||||
|
||||
constructor(
|
||||
private datasetWizardService: DatasetWizardService,
|
||||
|
@ -615,7 +616,7 @@ export class DatasetWizardComponent extends BaseComponent implements OnInit, IBr
|
|||
|
||||
if(aControl.invalid){
|
||||
|
||||
if(aControl.errors){//although here should always be true
|
||||
if(aControl.errors){
|
||||
//check if has placeholder
|
||||
if( (<any>aControl).nativeElement !== undefined && (<any>aControl).nativeElement !== null){
|
||||
controlName = this._getPlaceHolder(aControl);
|
||||
|
@ -625,6 +626,9 @@ export class DatasetWizardComponent extends BaseComponent implements OnInit, IBr
|
|||
errmess.push(...errorMessage);
|
||||
}
|
||||
|
||||
/*in case the aControl is FormControl then the it should have provided its error messages above.
|
||||
No need to check case of FormControl below*/
|
||||
|
||||
if(aControl instanceof FormGroup){
|
||||
|
||||
const fg = aControl as FormGroup;
|
||||
|
|
|
@ -429,7 +429,20 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC
|
|||
return this.formGroup.get('datasets')['controls'][0].valid;
|
||||
}
|
||||
|
||||
private showValidationErrorsDialog(projectOnly?: boolean) {
|
||||
private showValidationErrorsDialog(projectOnly?: boolean, errmess?: string[]) {
|
||||
|
||||
if(errmess){
|
||||
|
||||
const dialogRef = this.dialog.open(FormValidationErrorsDialogComponent, {
|
||||
disableClose: true,
|
||||
autoFocus: false,
|
||||
restoreFocus: false,
|
||||
data: {
|
||||
errorMessages:errmess,
|
||||
projectOnly: projectOnly
|
||||
},
|
||||
});
|
||||
}else{
|
||||
const dialogRef = this.dialog.open(FormValidationErrorsDialogComponent, {
|
||||
disableClose: true,
|
||||
autoFocus: false,
|
||||
|
@ -441,6 +454,8 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC
|
|||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
onSubmit(addNew?: boolean, showAddDatasetDialog?: boolean): void {
|
||||
this.scrollTop = document.getElementById('editor-form').scrollTop;
|
||||
|
||||
|
@ -734,8 +749,124 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC
|
|||
this.formSubmit(true);
|
||||
}
|
||||
|
||||
//checks if the dpm is valid not taking into account the datasets validity
|
||||
private _isDMPDescriptionValid():boolean{
|
||||
|
||||
const form: FormGroup = this.formGroup;
|
||||
if(form.controls){
|
||||
return Object.keys(form.controls)
|
||||
.map(controlName=>{//get validity of each control
|
||||
if(controlName === 'datasets'){//we dont care if datasets are valid
|
||||
return true;
|
||||
}
|
||||
return !form.get(controlName).invalid;//!! in case the control is disabled, we consider it valid
|
||||
})
|
||||
.reduce((isFormValid,isControlValid)=>{//aggregate validities
|
||||
return isControlValid && isFormValid;
|
||||
}, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private _getErrorMessage(formControl: AbstractControl, name: string): string[] {
|
||||
const errors: string[] = [];
|
||||
Object.keys(formControl.errors).forEach(key => {
|
||||
if (key === 'required') { errors.push(this.language.instant(name + ": " + this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.REQUIRED'))); }
|
||||
// if (key === 'required') { errors.push(this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.THIS-FIELD') + ' "' + this.getPlaceHolder(formControl) + '" ' + this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.HAS-ERROR') + ', ' + this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.REQUIRED')); }
|
||||
else if (key === 'email') { errors.push(this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.THIS-FIELD') + ' "' + name + '" ' + this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.HAS-ERROR') + ', ' + this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.EMAIL')); }
|
||||
else if (key === 'min') { errors.push(this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.THIS-FIELD') + ' "' + name + '" ' + this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.HAS-ERROR') + ', ' + this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.MIN-VALUE', { 'min': formControl.getError('min').min })); }
|
||||
else if (key === 'max') { errors.push(this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.THIS-FIELD') + ' "' + name + '" ' + this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.HAS-ERROR') + ', ' + this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.MAX-VALUE', { 'max': formControl.getError('max').max })); }
|
||||
else { errors.push(this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.THIS-FIELD') + ' "' + name + '" ' + this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.HAS-ERROR') + ', ' + formControl.errors[key].message); }
|
||||
});
|
||||
return errors;
|
||||
}
|
||||
|
||||
private _getPlaceHolder(formControl: any): string {
|
||||
if (formControl.nativeElement.localName === 'input' || formControl.nativeElement.localName === 'textarea') {
|
||||
return formControl.nativeElement.getAttribute('placeholder');
|
||||
} else if (formControl.nativeElement.localName === 'mat-select') {
|
||||
return formControl.nativeElement.getAttribute('aria-label');
|
||||
} else if (formControl.nativeElement.localName === 'app-single-auto-complete') {
|
||||
return (Array.from(formControl.nativeElement.firstChild.children).filter((x: any) => x.localName === 'input')[0] as any).getAttribute('placeholder');
|
||||
} else if (formControl.nativeElement.localName === 'app-multiple-auto-complete') {
|
||||
return (Array.from(formControl.nativeElement.firstChild.children).filter((x: any) => x.localName === 'input')[0] as any).getAttribute('placeholder');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private _buildDMPDescriptionErrorMessages(): string[]{//not including datasets
|
||||
const errmess: string[] = [];
|
||||
Object.keys(this.formGroup.controls).forEach(controlName=>{
|
||||
if(controlName != 'datasets' && this.formGroup.get(controlName).invalid){
|
||||
errmess.push(...this._buildErrorMessagesForAbstractControl(this.formGroup.get(controlName), controlName));
|
||||
}
|
||||
})
|
||||
|
||||
return errmess;
|
||||
}
|
||||
|
||||
// takes as an input an abstract control and gets its error messages[]
|
||||
private _buildErrorMessagesForAbstractControl(aControl: AbstractControl, controlName: string):string[]{
|
||||
const errmess:string[] = [];
|
||||
|
||||
if(aControl.invalid){
|
||||
|
||||
if(aControl.errors){
|
||||
//check if has placeholder
|
||||
if( (<any>aControl).nativeElement !== undefined && (<any>aControl).nativeElement !== null){
|
||||
controlName = this._getPlaceHolder(aControl);
|
||||
}
|
||||
const errorMessage = this._getErrorMessage(aControl, controlName);
|
||||
|
||||
errmess.push(...errorMessage);
|
||||
}
|
||||
/*in case the aControl is FormControl then the it should have provided its error messages above.
|
||||
No need to check case of FormControl below*/
|
||||
|
||||
if(aControl instanceof FormGroup){
|
||||
|
||||
const fg = aControl as FormGroup;
|
||||
//check children
|
||||
Object.keys(fg.controls).forEach(controlName=>{
|
||||
errmess.push(...this._buildErrorMessagesForAbstractControl(fg.get(controlName), controlName));
|
||||
});
|
||||
}else if(aControl instanceof FormArray){
|
||||
|
||||
const fa = aControl as FormArray;
|
||||
|
||||
fa.controls.forEach((control,index)=>{
|
||||
errmess.push(... this._buildErrorMessagesForAbstractControl(control, `${controlName} --> ${index+1}`));
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return errmess;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
addDataset() {
|
||||
this.formSubmit(true, false);
|
||||
|
||||
|
||||
if(!this._isDMPDescriptionValid()){
|
||||
const errmess = this._buildDMPDescriptionErrorMessages();
|
||||
this.showValidationErrorsDialog(undefined, errmess);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
this.onSubmit(true, false);
|
||||
// this.formSubmit(true, false);
|
||||
|
||||
|
||||
|
||||
|
||||
// Add dataset to list
|
||||
// if (!this.formGroup.get('datasets')) {
|
||||
// this.formGroup.addControl('datasets', new FormBuilder().array(new Array<FormControl>()));
|
||||
|
|
|
@ -10,9 +10,13 @@
|
|||
[ngStyle]="calculateStyle(entry)"
|
||||
[ngClass]="calculateClass(entry)"
|
||||
>
|
||||
<span>
|
||||
<span [class.text-danger]="showErrors && entry.form.invalid && entry.type === tocEntryTypeEnum.FieldSet">
|
||||
{{entry.numbering}}. {{entry.label}}
|
||||
</span>
|
||||
<mat-icon style="transform: translateY(3px);" class="text-danger"
|
||||
*ngIf="showErrors && entry.form.invalid && entry.type !== tocEntryTypeEnum.FieldSet && !expandChildren[idx]">
|
||||
priority_high
|
||||
</mat-icon>
|
||||
<!-- <ng-container *ngIf="entry.subEntries && entry.subEntries.length && !expandChildren[idx]">
|
||||
<small>
|
||||
({{entry.subEntries.length}})
|
||||
|
@ -28,7 +32,8 @@
|
|||
*ngIf="entry.subEntries && entry.subEntries.length && expandChildren[idx]"
|
||||
(entrySelected)="onEntrySelected($event)"
|
||||
[selected]="selected"
|
||||
[TOCENTRY_ID_PREFIX]="TOCENTRY_ID_PREFIX">
|
||||
[TOCENTRY_ID_PREFIX]="TOCENTRY_ID_PREFIX"
|
||||
[showErrors]="showErrors">
|
||||
|
||||
</table-of-contents-internal>
|
||||
</div>
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
.internal-table{
|
||||
margin-left: 1em;
|
||||
padding-left: 0.2rem;
|
||||
|
||||
}
|
||||
.table-entry{
|
||||
|
||||
|
@ -26,3 +27,7 @@
|
|||
font-weight: 700 !important;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
.section{
|
||||
line-height: 1.7em;
|
||||
}
|
|
@ -24,6 +24,7 @@ export class TableOfContentsInternal implements OnInit {
|
|||
expandChildren:boolean[];
|
||||
tocEntryTypeEnum = ToCEntryType;
|
||||
@Input() TOCENTRY_ID_PREFIX="";
|
||||
@Input() showErrors: boolean = false;
|
||||
|
||||
|
||||
constructor(public visibilityRulesService: VisibilityRulesService){
|
||||
|
@ -84,11 +85,16 @@ export class TableOfContentsInternal implements OnInit {
|
|||
}
|
||||
|
||||
calculateClass(entry:ToCEntry){
|
||||
const myClass= {};
|
||||
|
||||
if(this.selected && entry.id === this.selected.id){
|
||||
return{'selected': true};
|
||||
myClass['selected'] = true;
|
||||
}
|
||||
|
||||
return {};
|
||||
if(entry.type != this.tocEntryTypeEnum.FieldSet){
|
||||
myClass['section'] = true;
|
||||
}
|
||||
|
||||
return myClass;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
<div class="scroll-container col-12 internal-table">
|
||||
<table-of-contents-internal [TOCENTRY_ID_PREFIX]="TOCENTRY_ID_PREFIX" [tocentries]="tocentries"
|
||||
[showErrors]="showErrors"
|
||||
(entrySelected)="onToCentrySelected($event)"
|
||||
[selected]="tocentrySelected"
|
||||
|
||||
|
|
|
@ -4,9 +4,10 @@ import {TableOfContents} from './table-of-contents';
|
|||
import {RouterModule} from '@angular/router';
|
||||
import { TableOfContentsInternal } from './table-of-contents-internal/table-of-contents-internal';
|
||||
import { VisibilityRulesService } from '../visibility-rules/visibility-rules.service';
|
||||
import { MatIconModule } from '@angular/material';
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule, RouterModule],
|
||||
imports: [CommonModule, RouterModule, MatIconModule],
|
||||
declarations: [TableOfContents, TableOfContentsInternal],
|
||||
exports: [TableOfContents],
|
||||
entryComponents: [TableOfContents],
|
||||
|
|
|
@ -48,6 +48,7 @@ export class TableOfContents extends BaseComponent implements OnInit {
|
|||
@Input() TOCENTRY_ID_PREFIX = '';
|
||||
// visibilityRules:Rule[] = [];
|
||||
@Input() visibilityRules:Rule[] = [];
|
||||
@Input() showErrors: boolean = false;
|
||||
|
||||
private _tocentrySelected:ToCEntry = null;
|
||||
get tocentrySelected(){
|
||||
|
|
Loading…
Reference in New Issue