diff --git a/.classpath b/.classpath index 88a6962..32eaa78 100644 --- a/.classpath +++ b/.classpath @@ -31,19 +31,16 @@ - - - - - - - - - + + + + + + diff --git a/src/main/java/org/gcube/informationsystem/service/InformationSystemService.java b/src/main/java/org/gcube/informationsystem/service/InformationSystemService.java index ae5deca..7513c56 100644 --- a/src/main/java/org/gcube/informationsystem/service/InformationSystemService.java +++ b/src/main/java/org/gcube/informationsystem/service/InformationSystemService.java @@ -167,7 +167,7 @@ public class InformationSystemService { switch(typeForClient) { case "Boolean": tmp="boolean"; break; - case "Date": tmp="date"; + case "Date": tmp="datetime"; break; case "String": tmp="text"; break; @@ -198,7 +198,7 @@ public class InformationSystemService { if(fp.isMandatory()) { ValidationObjDTO vv = new ValidationObjDTO(); - vv.setMessage("The field is required"); + vv.setMessage("This field is required"); vv.setName("required"); vv.setValidator("required"); validations.add(vv); @@ -211,6 +211,13 @@ public class InformationSystemService { vv.setValidator("required"); validations.add(vv); } + if(fp.getPropertyType().equals("Date")) { + ValidationObjDTO vv = new ValidationObjDTO(); + vv.setMessage("A valid ISO datetime is required"); + vv.setName("datetime"); + vv.setValidator("this.validateDatetime()"); + validations.add(vv); + } if(StringUtils.isNotEmpty(fp.getRegexp())) { ValidationObjDTO vv = new ValidationObjDTO(); diff --git a/src/main/webapp/app/facet-composer/facet-composer.component.html b/src/main/webapp/app/facet-composer/facet-composer.component.html index 715973b..24353a7 100644 --- a/src/main/webapp/app/facet-composer/facet-composer.component.html +++ b/src/main/webapp/app/facet-composer/facet-composer.component.html @@ -78,10 +78,9 @@ {{prop.label}} - - {{checkForPropErrors(facetTemplate.key,ind,prop)}} - + + + {{checkForPropErrors(facetTemplate.key,ind,prop)}} @@ -118,7 +117,7 @@ value - + {{checkForErrorsIn(facetTemplate.key,ind,i,'datetime')}} @@ -137,15 +136,6 @@ {{checkForErrorsIn(facetTemplate.key,ind,i,'float')}} - - diff --git a/src/main/webapp/app/facet-composer/facet-composer.component.ts b/src/main/webapp/app/facet-composer/facet-composer.component.ts index 6038377..bce2ded 100644 --- a/src/main/webapp/app/facet-composer/facet-composer.component.ts +++ b/src/main/webapp/app/facet-composer/facet-composer.component.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ /* eslint-disable no-labels */ /* eslint-disable no-useless-escape */ /* eslint-disable @typescript-eslint/restrict-plus-operands */ @@ -6,7 +7,7 @@ /* eslint-disable no-console */ import { CommonModule, DatePipe } from '@angular/common'; import { Component, Inject, OnInit } from '@angular/core'; -import { AbstractControl, FormArray, FormBuilder, FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms'; +import { AbstractControl, FormArray, FormBuilder, FormControl, FormGroup, ReactiveFormsModule, ValidationErrors, ValidatorFn, Validators } from '@angular/forms'; import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog'; import { IContextNode } from 'app/services/i-context-node'; import { IResource } from 'app/services/i-resource'; @@ -19,6 +20,7 @@ import { MatExpansionModule } from '@angular/material/expansion'; import { IFacetComposer, IFacetProps } from './i-facet-composer'; import { SharedModule } from 'app/shared/shared.module'; import { MatSelectFilterModule } from 'mat-select-filter'; +import { isEmpty } from 'rxjs'; @Component({ standalone: true, @@ -129,15 +131,17 @@ defaultValue={new Date().toISOString().substring(0, (new Date().toISOString().in tipo:[''] }) - } - + } + get val():FormControl{ return this.fb.control({ + updateOn: 'change' }) } get props():FormGroup{ return this.fb.group({ + updateOn: 'change' }) } @@ -159,12 +163,13 @@ defaultValue={new Date().toISOString().substring(0, (new Date().toISOString().in this.getExtraPropsArray(denoFacet, indexFct).removeAt(index); } + + updateExtraPropType(denoFacet:string, indexFct:number, index:number, newValue:string):void{ this.getExtraPropsArray(denoFacet, indexFct).controls[index].get('tipo')?.setValue(newValue); const valFc:AbstractControl = this.getExtraPropsArray(denoFacet, indexFct).controls[index].get('val')!; if(newValue==='boolean'){ valFc.setValue(''); - //valFc.addValidators(Validators.pattern('^\s*(true|false)\s*$')) valFc.setValue('false'); // eslint-disable-next-line no-useless-escape valFc.setValidators([Validators.required,Validators.pattern('^\s*(true|false)\s*$')]); @@ -172,8 +177,11 @@ defaultValue={new Date().toISOString().substring(0, (new Date().toISOString().in if(newValue==='datetime'){ valFc.setValue(''); valFc.setValue(new Date().toISOString()); - const patt = '\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)'; - valFc.setValidators([Validators.required,Validators.pattern(patt)]); + valFc.setValidators([Validators.required, this.validateDatetime()]); + } + if(newValue==='date'){ + valFc.setValue(''); + valFc.setValidators([Validators.required]); } if(newValue==='password'||newValue==='text'||newValue==='number'){ valFc.setValue(''); @@ -192,7 +200,16 @@ defaultValue={new Date().toISOString().substring(0, (new Date().toISOString().in } - + private validateDatetime():ValidatorFn { + // alert('prova!'); + return (control: AbstractControl): ValidationErrors |null => { + const value = control.value; + const isFormallyCorrect = /^(19|20)\d{2}-(0[1-9]|1[0,1,2])-(0[1-9]|[12][0-9]|3[01])T(0[0-9]|1[0-9]|2[0-4]):(0[0-9]|[1-5][0-9]):(0[0-9]|[1-5][0-9])\.[0-9]{3}Z$/.test(value); + const datetimeValid = isFormallyCorrect && this.isIsoDate(control.value); + alert('datetimeValid?...'+datetimeValid); + return !datetimeValid ? {datetimeIso:true}: null; + } + } checkForErrors(valFc:AbstractControl, inputType:string): string{ let errorMsg: string; @@ -201,37 +218,60 @@ defaultValue={new Date().toISOString().substring(0, (new Date().toISOString().in if(valFc.hasError('required')){ errorMsg = 'The field must not be empty'; } - if(valFc.hasError('pattern')){ - errorMsg = ''+ valFc.value+'is not a correct value'; - if(!this.checkIfEmpty(valFc.value)&& inputType==='float'){ - errorMsg = 'input is not a decimal number (use . as a separator)'; - } - if(!this.checkIfEmpty(valFc.value)&& inputType==='boolean'){ - errorMsg = 'please enter true or false'; - } - if(!this.checkIfEmpty(valFc.value)&& inputType==='datetime'){ - errorMsg = 'datetime provided is not in ISO format'; - } - if(!this.checkIfEmpty(valFc.value)&& inputType==='date'){ + if(!this.checkIfEmpty(valFc.value)&& inputType==='datetime'){ + if(!this.isIsoDate(valFc.value)){ + errorMsg = 'Date is not in correct ISO format'; + } + }else{ + if(valFc.hasError('pattern')){ + errorMsg = ''+ valFc.value+'is not a correct value'; + if(!this.checkIfEmpty(valFc.value)&& inputType==='float'){ + errorMsg = 'input is not a decimal number (use . as a separator)'; + } + if(!this.checkIfEmpty(valFc.value)&& inputType==='boolean'){ + errorMsg = 'please enter true or false'; + } + if(!this.checkIfEmpty(valFc.value)&& inputType==='date'){ errorMsg = 'date or date format is not correct'; - } - - } + } + } + } return errorMsg; } + + + checkDatetime(denoFacet:string, indexFct:number, prop:IFacetProps):string{ + let errorMsg: string; + // eslint-disable-next-line prefer-const + errorMsg=''; + const valFc = this.getPropsGroup(denoFacet,indexFct).get(prop.name)!; + + if(!this.isIsoDate(valFc.value)){ + errorMsg = 'Date is not in correct ISO format'; + } + + return errorMsg; + } + + isIsoDate(str:string):boolean { + const d = new Date(str); + return d instanceof Date && !isNaN(d.getTime()) && d.toISOString()===str; // valid date + } + checkForPropErrors(denoFacet:string, indexFct:number, prop:IFacetProps):string{ - const abstractControl = this.getPropsGroup(denoFacet,indexFct).get(prop.name)!; - //TODO: usare questi campi per costruire la validazione: - //prop.validations - for(let i=0; i