From 8226718592923816ac8f3b11c1e7dfd0b3b21855 Mon Sep 17 00:00:00 2001 From: "francois.grand" <francois.grand@irstea.fr> Date: Thu, 4 Jan 2018 10:59:36 +0100 Subject: [PATCH] =?UTF-8?q?Ajout=20d'un=20composant=20de=20param=C3=A9trag?= =?UTF-8?q?e=20de=20l'application=20-=20param=C3=A9trage=20de=20la=20pr?= =?UTF-8?q?=C3=A9cision=20de=20calcul=20et=20d'affichage=20-=20fichiers=20?= =?UTF-8?q?de=20configuration=20JSON=20des=20calculettes=20:=20valeur=20pa?= =?UTF-8?q?r=20d=C3=A9faut=20de=20la=20pr=C3=A9cision=20de=20calcul=20supp?= =?UTF-8?q?rim=C3=A9e,=20remplac=C3=A9e=20par=20la=20valeur=20par=20d?= =?UTF-8?q?=C3=A9faut=20dans=20le=20service=20de=20param=C3=A9trage=20-=20?= =?UTF-8?q?cr=C3=A9ation=20d'un=20composant=20BaseParamInputComponent=20de?= =?UTF-8?q?=20saisie=20de=20param=C3=A8tre=20simple=20NgBaseParam=20(non?= =?UTF-8?q?=20li=C3=A9=20=C3=A0=20un=20param=C3=A8tre=20d'=C3=A9quation=20?= =?UTF-8?q?cad=20avec=20domaine=20et=20symbole=20mais=20sans=20calculabili?= =?UTF-8?q?t=C3=A9=20ni=20noeud=20de=20calcul=20associ=C3=A9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/app.component.ts | 6 + src/app/app.module.ts | 5 + .../cond_distri/cond_distri.config.json | 3 +- .../lechapt-calmon/lechapt-calmon.config.json | 3 +- .../calculators/ouvrages/ouvrages.config.json | 3 +- .../regime-uniforme.config.json | 3 +- src/app/calculators/remous/remous.config.json | 3 +- .../section-param/section-param.config.json | 3 +- .../app-setup/app-setup.component.html | 22 ++ .../app-setup/app-setup.component.ts | 46 ++++ .../base-param-input.component.html | 5 + .../base-param-input.component.ts | 218 ++++++++++++++++++ src/app/formulaire/formulaire-definition.ts | 9 +- .../services/app-setup/app-setup.service.ts | 8 + .../services/formulaire/formulaire.service.ts | 6 +- 15 files changed, 327 insertions(+), 16 deletions(-) create mode 100644 src/app/components/app-setup/app-setup.component.html create mode 100644 src/app/components/app-setup/app-setup.component.ts create mode 100644 src/app/components/base-param-input/base-param-input.component.html create mode 100644 src/app/components/base-param-input/base-param-input.component.ts diff --git a/src/app/app.component.ts b/src/app/app.component.ts index f99d49adc..4f605afb8 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 5acde2f69..f435bcba1 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 52397b384..7001c739e 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 77ce3598f..93498287d 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 1dcdb14cb..fbb8930e7 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 d8ff11945..5434719ee 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 4399886be..4952eee19 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 fa20969c3..53cb4e654 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 000000000..e274b1f63 --- /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 000000000..9fc5f5784 --- /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 000000000..2e1af91be --- /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 000000000..1006d13f3 --- /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 82771cde8..62d38b6d5 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 25a9f8d70..caa5df913 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 1b833bc14..5451adbef 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(_ => { -- GitLab