diff --git a/src/app/app.component.ts b/src/app/app.component.ts index f99d49adc5c600a890a1d883d2124ac2ec70a367..4f605afb85ab6124ef69fa46f496786499ca563f 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -177,6 +177,7 @@ export class AppComponent implements OnInit, OnDestroy, Observer { // cf. src/environments/*, ng build --env=<mode> (par ex : ng build --env=prod) private get ruler(): boolean { return !environment.production; + // return false; } // sidenav @@ -194,5 +195,10 @@ export class AppComponent implements OnInit, OnDestroy, Observer { this.toList(); } + private params() { + this.closeNav(); + this.router.navigate(['/setup']); + } + // sidenav } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 5acde2f69539b72daa318bb1f6554bdaadaec0cd..f435bcba1827aa0fdc3b40723bb1c661aa46d697 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -30,10 +30,13 @@ import { SectionCanvasComponent } from './components/section-canvas/section-canv import { RemousResultsComponent } from './components/remous-results/remous-results.component'; import { LogComponent } from './components/log/log.component'; import { CalculatorListComponent } from './components/calculator-list/calculator-list.component'; +import { ApplicationSetupComponent } from './components/app-setup/app-setup.component'; +import { BaseParamInputComponent } from './components/base-param-input/base-param-input.component'; const appRoutes: Routes = [ { path: 'list', component: CalculatorListComponent }, { path: 'calculator/:uid', component: GenericCalculatorComponent }, + { path: 'setup', component: ApplicationSetupComponent }, { path: '**', component: CalculatorListComponent } ]; @@ -60,6 +63,8 @@ const appRoutes: Routes = [ ParamFieldLineComponent, SelectFieldLineComponent, CheckFieldLineComponent, LogComponent, CalculatorListComponent, + ApplicationSetupComponent, + BaseParamInputComponent, GenericCalculatorComponent, // AlertDialog, CalculatorResultsComponent, FixedVarResultsComponent, SectionResultsComponent, RemousResultsComponent, diff --git a/src/app/calculators/cond_distri/cond_distri.config.json b/src/app/calculators/cond_distri/cond_distri.config.json index 52397b384f66d83719a4fd2bc6efbe1fba09fbaf..7001c739e621acc1fcff03831a498b02dc10cbef 100644 --- a/src/app/calculators/cond_distri/cond_distri.config.json +++ b/src/app/calculators/cond_distri/cond_distri.config.json @@ -42,8 +42,7 @@ { "type": "input", "id": "Pr", - "unit": "m", - "value": 0.001 + "unit": "m" } ] }, diff --git a/src/app/calculators/lechapt-calmon/lechapt-calmon.config.json b/src/app/calculators/lechapt-calmon/lechapt-calmon.config.json index 77ce3598fb6a629352bca369f4490fb3481d7ea0..93498287d1e17dfe44c156229421046b76de07f0 100644 --- a/src/app/calculators/lechapt-calmon/lechapt-calmon.config.json +++ b/src/app/calculators/lechapt-calmon/lechapt-calmon.config.json @@ -231,8 +231,7 @@ { "type": "input", "id": "Pr", - "unit": "m", - "value": 0.001 + "unit": "m" } ] }, diff --git a/src/app/calculators/ouvrages/ouvrages.config.json b/src/app/calculators/ouvrages/ouvrages.config.json index 1dcdb14cbca965dbda6a1aca1650dd59291691a0..fbb8930e7350651bd252ee9387e8c45bc869ad4e 100644 --- a/src/app/calculators/ouvrages/ouvrages.config.json +++ b/src/app/calculators/ouvrages/ouvrages.config.json @@ -227,8 +227,7 @@ { "type": "input", "id": "Pr", - "unit": "m", - "value": 0.001 + "unit": "m" } ] }, diff --git a/src/app/calculators/regime-uniforme/regime-uniforme.config.json b/src/app/calculators/regime-uniforme/regime-uniforme.config.json index d8ff1194517e3c2f19d493423f962afd07348b8b..5434719eefd2976c3c293b37ed2de429a39da936 100644 --- a/src/app/calculators/regime-uniforme/regime-uniforme.config.json +++ b/src/app/calculators/regime-uniforme/regime-uniforme.config.json @@ -159,8 +159,7 @@ { "type": "input", "id": "Pr", - "unit": "m", - "value": 0.001 + "unit": "m" } ] }, diff --git a/src/app/calculators/remous/remous.config.json b/src/app/calculators/remous/remous.config.json index 4399886be3622f0c1788f621805acbfeed054f84..4952eee19fbb6783b72013dd43d2cbf76956b355 100644 --- a/src/app/calculators/remous/remous.config.json +++ b/src/app/calculators/remous/remous.config.json @@ -177,8 +177,7 @@ { "type": "input", "id": "Pr", - "unit": "m", - "value": 0.0001 + "unit": "m" }, { "id": "select_resolution", diff --git a/src/app/calculators/section-param/section-param.config.json b/src/app/calculators/section-param/section-param.config.json index fa20969c327d9c6d5e477a32d8810f9359f3c8f3..53cb4e654c560f53e6dc71a43787d98bab0980f2 100644 --- a/src/app/calculators/section-param/section-param.config.json +++ b/src/app/calculators/section-param/section-param.config.json @@ -159,8 +159,7 @@ { "type": "input", "id": "Pr", - "unit": "m", - "value": 0.001 + "unit": "m" } ] }, diff --git a/src/app/components/app-setup/app-setup.component.html b/src/app/components/app-setup/app-setup.component.html new file mode 100644 index 0000000000000000000000000000000000000000..e274b1f639830bd7e256fa89350c2f15ee38fd4d --- /dev/null +++ b/src/app/components/app-setup/app-setup.component.html @@ -0,0 +1,22 @@ +<div class="container-fluid"> + <div class="row"> + <div class="col-4 mx-auto"> + <h1>Paramètres de l'application</h1> + <br/> + </div> + </div> + + <!-- précision d'affichage --> + <div class="row"> + <div class="col-4 mx-auto"> + <base-param-input title="Précision d'affichage" [param]="_displayPrec"></base-param-input> + </div> + </div> + + <!-- précision de calcul --> + <div class="row"> + <div class="col-4 mx-auto"> + <base-param-input title="Précision de calcul" [param]="_computePrec"></base-param-input> + </div> + </div> +</div> \ No newline at end of file diff --git a/src/app/components/app-setup/app-setup.component.ts b/src/app/components/app-setup/app-setup.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..9fc5f5784351ed2f1cbb5d6fdfa0f7eb58e4e2a5 --- /dev/null +++ b/src/app/components/app-setup/app-setup.component.ts @@ -0,0 +1,46 @@ +import { Component } from "@angular/core"; + +import { BaseParam, ParamDomainValue } from "jalhyd"; + +import { ApplicationSetupService } from '../../services/app-setup/app-setup.service'; +import { NgBaseParam } from "../base-param-input/base-param-input.component"; +import { Observer } from "../../services/observer"; + +@Component({ + selector: "setup", + templateUrl: "./app-setup.component.html", +}) +export class ApplicationSetupComponent implements Observer { + /** + * précision d'affichage + */ + private _displayPrec: NgBaseParam; + + /** + * précision de calcul + */ + private _computePrec: NgBaseParam; + + constructor(private appSetupService: ApplicationSetupService) { + this._displayPrec = new NgBaseParam("dp", ParamDomainValue.NOT_NULL, this.appSetupService.displayPrecision); + this._displayPrec.addObserver(this); + + this._computePrec = new NgBaseParam("cp", ParamDomainValue.NOT_NULL, this.appSetupService.computePrecision); + this._computePrec.addObserver(this); + } + + // interface Observer + + public update(sender: any, data: any): void { + const p: NgBaseParam = sender; + switch (p.symbol) { + case "dp": + this.appSetupService.displayPrecision = +data; + break; + + case "cp": + this.appSetupService.computePrecision = +data; + break; + } + } +} diff --git a/src/app/components/base-param-input/base-param-input.component.html b/src/app/components/base-param-input/base-param-input.component.html new file mode 100644 index 0000000000000000000000000000000000000000..2e1af91be2ee365ae2d2697b4adf14c634696f9a --- /dev/null +++ b/src/app/components/base-param-input/base-param-input.component.html @@ -0,0 +1,5 @@ +<div class="md-form form-sm"> + <input mdbActive type="text" id="form1" class="form-control" [ngModel]="_uiValue.uncheckedValueString" (ngModelChange)="setValue($event)"> + <label for="form1">{{_title}}</label> + <small class="text-danger">{{_message}}</small> +</div> \ No newline at end of file diff --git a/src/app/components/base-param-input/base-param-input.component.ts b/src/app/components/base-param-input/base-param-input.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..1006d13f3cd9462212e16af9712a7f0d241efa79 --- /dev/null +++ b/src/app/components/base-param-input/base-param-input.component.ts @@ -0,0 +1,218 @@ +// cf. https://blog.thoughtram.io/angular/2016/07/27/custom-form-controls-in-angular-2.html + +import { Component, Input, forwardRef, OnInit, DoCheck, ChangeDetectorRef } from "@angular/core"; +import { ControlValueAccessor, NG_VALUE_ACCESSOR, NG_VALIDATORS, FormControl } from "@angular/forms"; + +import { BaseParam, NumericalString, Message, ParamDomain, ParamDomainValue } from "jalhyd"; + +import { InternationalisationService, LanguageCode } from "../../services/internationalisation/internationalisation.service"; +import { Observable } from "../../services/observer"; + +export class NgBaseParam extends Observable { + private _param: BaseParam; + + constructor(symb: string, d: ParamDomain | ParamDomainValue, val: number) { + super(); + this._param = new BaseParam(symb, d, val); + } + + public get symbol() { + return this._param.symbol; + } + + public get isDefined() { + return this._param.isDefined; + } + + public getValue() { + return this._param.getValue(); + } + + public checkValue(val: number) { + return this._param.checkValue(val); + } + + public setValue(val: number) { + this._param.setValue(val); + this.notifyObservers(val); + } +} + +@Component({ + selector: "base-param-input", + templateUrl: "./base-param-input.component.html", + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => BaseParamInputComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => BaseParamInputComponent), + multi: true + } + ] +}) +export class BaseParamInputComponent implements ControlValueAccessor, DoCheck { + /** + * enable/disable input field + */ + @Input('inputDisabled') + private _inputDisabled: boolean; + + /** + * managed parameter + */ + @Input('param') + private _paramDef: NgBaseParam; + + @Input('title') + private _title: string; + + private _message: string; + + /** + * flag d'affichage du titre + */ + public displayTitle: boolean = false; + + /** + * true si la modification du paramètre géré vient de l'interface utilisateur + * false si la modification du paramètre géré vient d'un appel du code + */ + private _fromUI: boolean; + + /** + * valeur dans le contrôle (saisie par l'utilisateur) + */ + private _uiValue: NumericalString; + + constructor(private changeDetector: ChangeDetectorRef, private intlService: InternationalisationService) { + this._uiValue = new NumericalString(); + } + + /** + * fonction appelée lorsque l'utilisateur fait une saisie + * @param event valeur du contrôle + */ + private setValue(event: any) { + this._fromUI = true; + this._uiValue.value = event; + // this.log(this._uiValue.toString()); + return this.validateUIValue(); + } + + /** + * fonction appelée lors d'un rafraîchissement de l'UI + */ + ngDoCheck(): void { + // this.log("ngDoCheck start : " + this.getSParam() + this.getSUIvalue() + this.getSfromUI()); + + if (this._fromUI) + this.updateMessage(this._uiValue); + else { + if (this._paramDef.isDefined) { + this.updateMessage(new NumericalString(this._paramDef.getValue())); + this._uiValue.value = String(this._paramDef.getValue()); + } + else + this.updateMessage(this._uiValue); + } + + // this.log("ngDoCheck end : " + this.getSParam() + this.getSUIvalue()); + + this._fromUI = false; + } + + private updateMessage(v: NumericalString) { + // this.log("updateMessage start :" + this.getSParam() + this.getSfromUI() + this.getSUIvalue(v) + " message=" + this._message); + + if (v.isNumerical) { + this._message = undefined; + + try { + this._paramDef.checkValue(v.numericalValue); + } + catch (e) { + if (e instanceof Message) + this._message = this.intlService.localizeMessage(e); + else + this._message = "invalid value"; + } + } + else { + switch (this.intlService.currentLanguage.code) { + case LanguageCode.FRENCH: + this._message = "Veuillez entrer une valeur numérique"; + break; + + default: + this._message = "Please enter a numerical value"; + } + } + + // this.log("updateMessage end :" + this.getSParam() + this.getSfromUI() + this.getSUIvalue(v) + " message=" + this._message); + } + + private validateUIValue() { + // this.log(""); + // this.log("validateValue start : val '" + this._uiValue.toString() + "'" + this.getSParam() + this.getSfromUI()); + + let ok: boolean = this._uiValue.isNumerical; + if (ok) { + try { + if (!this._paramDef.isDefined || this._paramDef.getValue() != this._uiValue.numericalValue) { + this._paramDef.setValue(this._uiValue.numericalValue); + this.changeDetector.detectChanges(); // provoque une détection des changements dans les contrôles + } + } + catch (e) { + ok = false; + } + } + + if (!ok) { + // this.log("validateValue end : " + this.getSParam()); + + let err = { + rangeError: { + // given: val, + given: this._uiValue.toString(), + max: 4, + min: 0 + } + }; + return err; + } + + // this.log("validateValue end : " + this.getSParam()); + return null; + } + + // private log(m: string) { + // console.log("ParamInputComponent(" + this._id + ") : " + m); + // } + + // ControlValueAccessor interface + + propagateChange = (_: any) => { }; + + /* + //From ControlValueAccessor interface + writeValue(value: any) { + if (value !== this.innerValue) { + this.innerValue = value; + } + } + */ + writeValue(value: any) { + // this.log("writeValue " + value); + } + + registerOnChange(fn: any) { + this.propagateChange = fn; + } + + registerOnTouched() { } +} diff --git a/src/app/formulaire/formulaire-definition.ts b/src/app/formulaire/formulaire-definition.ts index 82771cde8dd5a788e7a4823fd796cc74587af03e..62d38b6d5b43d0a8a001b9a851378af990b32b11 100644 --- a/src/app/formulaire/formulaire-definition.ts +++ b/src/app/formulaire/formulaire-definition.ts @@ -5,6 +5,7 @@ import { ConduiteDistrib, ConduiteDistribParams, LechaptCalmon, LechaptCalmonPar import { ParamService } from "../services/param/param.service"; import { InternationalisationService } from "../services/internationalisation/internationalisation.service"; +import { ApplicationSetupService } from "../services/app-setup/app-setup.service"; import { Field } from "./field"; import { NgParameter, ParamRadioConfig } from "./ngparam"; import { InputField } from "./input-field"; @@ -76,7 +77,8 @@ export class FormulaireDefinition { constructor( private _calcType: CalculatorType, private paramService: ParamService, - private intlService: InternationalisationService + private intlService: InternationalisationService, + private appSetupService: ApplicationSetupService ) { this._uid = FormulaireDefinition.uidGenerator(); this._fixVarResults = new FixedVarResults(); @@ -497,7 +499,10 @@ export class FormulaireDefinition { throw "pas de paramètre '" + input_id + "' trouvé dans le noeud " + ComputeNodeType[node_type] + "(" + node_type + ") ou " + ComputeNodeType[this._defaultNodeType] + "(" + this._defaultNodeType + ")"; res.unit = field["unit"]; - let val = field["value"]; + if (input_id == "Pr") + var val = this.appSetupService.computePrecision; + else + val = field["value"]; if (val != undefined) res.setValue(+val); res.radioConfig = NgParameter.getRadioConfig(fieldset["option"]); diff --git a/src/app/services/app-setup/app-setup.service.ts b/src/app/services/app-setup/app-setup.service.ts index 25a9f8d70bf706161f9e0d45bdc293695841c0b8..caa5df91346f31d8a16d4d52d7f9416622ad8bd8 100644 --- a/src/app/services/app-setup/app-setup.service.ts +++ b/src/app/services/app-setup/app-setup.service.ts @@ -16,6 +16,10 @@ export class ApplicationSetupService { return this._displayPrecision; } + public set displayPrecision(p: number) { + this._displayPrecision = p; + } + public get displayDigits() { return -Math.log10(this._displayPrecision); } @@ -23,4 +27,8 @@ export class ApplicationSetupService { public get computePrecision() { return this._computePrecision; } + + public set computePrecision(p: number) { + this._computePrecision = p; + } } diff --git a/src/app/services/formulaire/formulaire.service.ts b/src/app/services/formulaire/formulaire.service.ts index 1b833bc14e79d4960f03fa567103a79d792b4e15..5451adbefdb7c577dd5335fd9c698f30b514bab7 100644 --- a/src/app/services/formulaire/formulaire.service.ts +++ b/src/app/services/formulaire/formulaire.service.ts @@ -6,6 +6,7 @@ import "rxjs/add/operator/toPromise"; import { ParamService } from "../param/param.service"; import { HttpService } from "../../services/http/http.service"; import { InternationalisationService } from "../../services/internationalisation/internationalisation.service"; +import { ApplicationSetupService } from "../../services/app-setup/app-setup.service"; import { FormulaireDefinition, CalculatorType } from "../../formulaire/formulaire-definition"; import { FormulaireElement } from "../../formulaire/formulaire-element"; import { InputField } from "../../formulaire/input-field"; @@ -23,7 +24,8 @@ export class FormulaireService extends Observable { constructor(private paramService: ParamService, private httpService: HttpService, - private intlService: InternationalisationService + private intlService: InternationalisationService, + private appSetupService: ApplicationSetupService ) { super(); this._formulaires = []; @@ -92,7 +94,7 @@ export class FormulaireService extends Observable { if (ct == undefined) throw "FormulaireService.createFormulaire() : invalid undefined CalculatorType" - let f = new FormulaireDefinition(ct, this.paramService, this.intlService); + let f = new FormulaireDefinition(ct, this.paramService, this.intlService, this.appSetupService); this._formulaires.push(f); let prom: Promise<Response> = this.loadConfig(f, ct); return prom.then(_ => {