From 39019b9d50966df18cab397b41fa9dab52ad7f80 Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Fri, 15 Mar 2019 17:50:55 +0100 Subject: [PATCH 01/39] =?UTF-8?q?[WIP]=20nouveau=20syst=C3=A8me=20de=20par?= =?UTF-8?q?am=C3=A8tres=20li=C3=A9s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- e2e/calculate-all-params.e2e-spec.ts | 2 - jalhyd_branch | 2 +- .../app-setup/app-setup.component.ts | 4 +- .../dialog-edit-param-values.component.html | 6 +- .../dialog-edit-param-values.component.scss | 1 + .../dialog-edit-param-values.component.ts | 38 +++++- .../generic-input/generic-input.component.ts | 2 - .../param-field-line.component.html | 4 +- .../param-field-line.component.ts | 4 +- .../param-link/param-link.component.html | 3 - .../param-link/param-link.component.ts | 123 ++++++++---------- .../param-values/param-values.component.ts | 38 ++++-- .../concrete/form-parallel-structures.ts | 2 - .../definition/form-def-fixedvar.ts | 16 +-- .../definition/form-def-paramcalc.ts | 8 +- .../formulaire/definition/form-definition.ts | 16 +-- src/app/formulaire/fieldset.ts | 3 +- src/app/formulaire/ngparam.ts | 86 +++++++----- src/app/results/var-results.ts | 1 - .../services/formulaire/formulaire.service.ts | 98 ++++---------- src/locale/messages.en.json | 1 + src/locale/messages.fr.json | 1 + 22 files changed, 225 insertions(+), 234 deletions(-) diff --git a/e2e/calculate-all-params.e2e-spec.ts b/e2e/calculate-all-params.e2e-spec.ts index e71105a54..eebcfa7e8 100644 --- a/e2e/calculate-all-params.e2e-spec.ts +++ b/e2e/calculate-all-params.e2e-spec.ts @@ -32,11 +32,9 @@ describe("ngHyd − calculate all parameters of all calculators", () => { // get all parameters IDs const inputs = await calcPage.getParamInputsHavingCalcMode(); - // console.log("> Inputs having calc", inputs.length); if (inputs.length > 0) { // for each param for (const input of inputs) { - // console.log(">> Trying", await input.getAttribute("id")); // click "calc" mode button for this parameter await calcPage.setParamMode(input, "cal"); // check that only 1 button is in "calc" state diff --git a/jalhyd_branch b/jalhyd_branch index 1f7391f92..6ba102133 100644 --- a/jalhyd_branch +++ b/jalhyd_branch @@ -1 +1 @@ -master +54-ameliorer-le-filtre-de-choix-des-parametres-pouvant-etre-lies diff --git a/src/app/components/app-setup/app-setup.component.ts b/src/app/components/app-setup/app-setup.component.ts index 0b373a0d2..87b96145b 100644 --- a/src/app/components/app-setup/app-setup.component.ts +++ b/src/app/components/app-setup/app-setup.component.ts @@ -83,7 +83,7 @@ export class ApplicationSetupComponent extends BaseComponent implements Observer public storePreferences() { this.appSetupService.saveValuesIntoLocalStorage(); this.snackBar.open(this.intlService.localizeText("INFO_SNACKBAR_SETTINGS_SAVED"), "OK", { - duration: 1200 + duration: 2500 }); } @@ -91,7 +91,7 @@ export class ApplicationSetupComponent extends BaseComponent implements Observer const text = this.intlService.localizeText("INFO_SNACKBAR_DEFAULT_SETTINGS_RESTORED"); this.appSetupService.restoreDefaultValues().then(() => { this.snackBar.open(text, "OK", { - duration: 1200 + duration: 2500 }); }); } diff --git a/src/app/components/dialog-edit-param-values/dialog-edit-param-values.component.html b/src/app/components/dialog-edit-param-values/dialog-edit-param-values.component.html index c4ace21ec..8fbe604a5 100644 --- a/src/app/components/dialog-edit-param-values/dialog-edit-param-values.component.html +++ b/src/app/components/dialog-edit-param-values/dialog-edit-param-values.component.html @@ -20,7 +20,7 @@ <form> <mat-form-field> <input matInput class="form-control" type="number" inputmode="numeric" name="min-value" step="0.01" - [placeholder]="uitextValeurMini" [(ngModel)]="param.minValue" #min="ngModel" name="min" + [placeholder]="uitextValeurMini" [(ngModel)]="minValue" #min="ngModel" name="min" [appJalhydModelValidationMin]="param" required pattern="^-?([0-9]*\.)?([0-9]+[Ee]-?)?[0-9]+$"> <mat-error *ngIf="min.errors"> @@ -35,7 +35,7 @@ <mat-form-field> <input matInput class="form-control" type="number" inputmode="numeric" name="max-value" step="0.01" - [placeholder]="uitextValeurMaxi" [(ngModel)]="param.maxValue" #max="ngModel" name="max" + [placeholder]="uitextValeurMaxi" [(ngModel)]="maxValue" #max="ngModel" name="max" [appJalhydModelValidationMax]="param" required pattern="^-?([0-9]*\.)?([0-9]+[Ee]-?)?[0-9]+$"> <mat-error *ngIf="max.errors"> @@ -50,7 +50,7 @@ <mat-form-field> <input matInput class="form-control" type="number" inputmode="numeric" name="step-value" step="0.01" - [placeholder]="uitextPasVariation" [(ngModel)]="param.stepValue" #step="ngModel" name="step" + [placeholder]="uitextPasVariation" [(ngModel)]="stepValue" #step="ngModel" name="step" [appJalhydModelValidationStep]="param" required pattern="^-?([0-9]*\.)?([0-9]+[Ee]-?)?[0-9]+$"> <mat-error *ngIf="step.errors"> diff --git a/src/app/components/dialog-edit-param-values/dialog-edit-param-values.component.scss b/src/app/components/dialog-edit-param-values/dialog-edit-param-values.component.scss index 111eef749..0ffd355d6 100644 --- a/src/app/components/dialog-edit-param-values/dialog-edit-param-values.component.scss +++ b/src/app/components/dialog-edit-param-values/dialog-edit-param-values.component.scss @@ -19,6 +19,7 @@ mat-form-field { .min-max-step-container { margin-top: -8px; + padding-bottom: 1em; // for possible mat-error on step field } .mat-dialog-content { diff --git a/src/app/components/dialog-edit-param-values/dialog-edit-param-values.component.ts b/src/app/components/dialog-edit-param-values/dialog-edit-param-values.component.ts index 0d1ad08b8..bb9168725 100644 --- a/src/app/components/dialog-edit-param-values/dialog-edit-param-values.component.ts +++ b/src/app/components/dialog-edit-param-values/dialog-edit-param-values.component.ts @@ -114,6 +114,32 @@ export class DialogEditParamValuesComponent implements OnInit { }; } + // proxy to model values + + public get minValue() { + return this.param.minValue; + } + + public set minValue(v) { + this.param.setMinValue(this, v); + } + + public get maxValue() { + return this.param.maxValue; + } + + public set maxValue(v) { + this.param.setMaxValue(this, v); + } + + public get stepValue() { + return this.param.stepValue; + } + + public set stepValue(v) { + this.param.setStepValue(this, v); + } + /** * regular expression pattern for values list validation (depends on decimal separator) */ @@ -172,7 +198,7 @@ export class DialogEditParamValuesComponent implements OnInit { vals.push(Number(e)); } }); - this.param.valueList = vals; + this.param.setValueList(this, vals); } public toggleViewChart() { @@ -280,24 +306,24 @@ export class DialogEditParamValuesComponent implements OnInit { // init min / max / step if (this.isMinMax) { if (this.param.minValue === undefined) { - this.param.minValue = this.param.getValue() / 2; + this.param.setMinValue(this, this.param.getValue() / 2); } if (this.param.maxValue === undefined) { - this.param.maxValue = this.param.getValue() * 2; + this.param.setMaxValue(this, this.param.getValue() * 2); } let step = this.param.stepValue; if (step === undefined) { step = (this.param.maxValue - this.param.minValue) / 20; } - this.param.stepValue = step; + this.param.setStepValue(this, step); } // init values list if (this.isListe) { if (this.param.valueList === undefined) { if (this.param.isDefined) { - this.param.valueList = [ this.param.getValue() ]; + this.param.setValueList(this, [ this.param.getValue() ]); } else { - this.param.valueList = []; + this.param.setValueList(this, []); } // set form control initial value this.valuesListForm.controls.valuesList.setValue(this.valuesList); diff --git a/src/app/components/generic-input/generic-input.component.ts b/src/app/components/generic-input/generic-input.component.ts index 4b34c8113..8f9f2f7a2 100644 --- a/src/app/components/generic-input/generic-input.component.ts +++ b/src/app/components/generic-input/generic-input.component.ts @@ -182,7 +182,6 @@ export abstract class GenericInputComponent extends BaseComponent implements OnC * événement de changement de la valeur du modèle */ private emitModelChanged() { - // console.log("emit model change", this.constructor.name); this.change.emit({ "action": "model", "value": this.getModelValue() }); } @@ -240,7 +239,6 @@ export abstract class GenericInputComponent extends BaseComponent implements OnC * appelé quand les @Input changent */ public ngOnChanges() { - // console.log("ng on changes (generic input)", this.constructor.name); this.updateAll(); } diff --git a/src/app/components/param-field-line/param-field-line.component.html b/src/app/components/param-field-line/param-field-line.component.html index a9847d2b2..973ec8c81 100644 --- a/src/app/components/param-field-line/param-field-line.component.html +++ b/src/app/components/param-field-line/param-field-line.component.html @@ -10,10 +10,10 @@ <param-computed *ngIf="isRadioCalChecked" [title]="title" [param]="param"></param-computed> <!-- composant pour gérer le cas "paramètre à varier" (min-max/liste de valeurs) --> - <param-values *ngIf="isRadioVarChecked" [title]="title" [param]="param" (valid)=onParamValuesValid($event)></param-values> + <param-values *ngIf="isRadioVarChecked" [title]="title" [param]="param" (change)="onInputChange($event)" (valid)=onParamValuesValid($event)></param-values> <!-- composant pour gérer le cas "paramètre lié" --> - <param-link *ngIf="isRadioLinkChecked" [title]="title" [param]="param" (valid)=onParamValuesValid($event)></param-link> + <param-link *ngIf="isRadioLinkChecked" [title]="title" [param]="param" (change)="onInputChange($event)" (valid)=onParamValuesValid($event)></param-link> </div> <div class="toggle-group-container" fxFlex="0 0 auto"> diff --git a/src/app/components/param-field-line/param-field-line.component.ts b/src/app/components/param-field-line/param-field-line.component.ts index 435f63cfb..198dc15cd 100644 --- a/src/app/components/param-field-line/param-field-line.component.ts +++ b/src/app/components/param-field-line/param-field-line.component.ts @@ -199,14 +199,14 @@ export class ParamFieldLineComponent implements OnChanges { if (this._formService.formulaires.length > 0) { // au moins 2 modules de calcul ouverts if (this._formService.formulaires.length > 1) { - return this._formService.filterLinkableValues(this._formService.getLinkableValues(this.param)).length > 0; + return this._formService.getLinkableValues(this.param).length > 0; } // ou un seul module de calcul "ouvrages parallèles" if (this._formService.formulaires[0].calculatorType === CalculatorType.ParallelStructure) { const ps: ParallelStructure = this._formService.formulaires[0].currentNub as ParallelStructure; if (ps.structures.length > 1) { - return this._formService.filterLinkableValues(this._formService.getLinkableValues(this.param)).length > 0; + return this._formService.getLinkableValues(this.param).length > 0; } } diff --git a/src/app/components/param-link/param-link.component.html b/src/app/components/param-link/param-link.component.html index c1a76465e..9f8fce8bf 100644 --- a/src/app/components/param-link/param-link.component.html +++ b/src/app/components/param-link/param-link.component.html @@ -5,9 +5,6 @@ {{ selectItemLabel(e) }} </mat-option> </mat-select> - <mat-error> - {{ message }} - </mat-error> </mat-form-field> <mat-icon #tooltip="matTooltip" [matTooltip]="tooltipText" matTooltipClass="linked-param-tooltip" diff --git a/src/app/components/param-link/param-link.component.ts b/src/app/components/param-link/param-link.component.ts index a382729a4..5601ced0a 100644 --- a/src/app/components/param-link/param-link.component.ts +++ b/src/app/components/param-link/param-link.component.ts @@ -2,7 +2,7 @@ import { Component, Input, Output, EventEmitter, OnChanges, OnDestroy } from "@a import { NgParameter } from "../../formulaire/ngparam"; import { ServiceFactory } from "../../services/service-factory"; -import { ParamValueMode, Observer, Structure, ParallelStructure } from "jalhyd"; +import { LinkedValue, ParamValueMode, Observer, Structure } from "jalhyd"; import { FormulaireService } from "../../services/formulaire/formulaire.service"; import { I18nService } from "../../services/internationalisation/internationalisation.service"; import { FormulaireDefinition } from "../../formulaire/definition/form-definition"; @@ -26,32 +26,18 @@ export class ParamLinkComponent implements OnChanges, Observer, OnDestroy { private valid: EventEmitter<boolean>; /** - * indice actuel du paramètre sélectionné dans la liste + * événement signalant un changement de valeur du modèle + * @TODO l'utiliser aussi pour le changement de validité à + * la place de this.valid, comme dans GenericInputComponent */ - private _currentIndex = -1; + @Output() + protected change = new EventEmitter<any>(); - /** - * message affiché à côté du select des paramètres - */ - private _message: string; + /** indice actuel du paramètre sélectionné dans la liste */ + private _currentIndex = -1; - /** - * liste des paramètres liables sous la forme - * {"name":<étiquette>, "value":<valeur liable>, "nub":<Nub d'origine du paramètre>, "formTitle":<nom du module de calcul lié au nub>} - * - * l'étiquette "name" (cf. INubReference.defineReference dans jalhyd) est de la forme <n | ouvrage[n] | N1>[.[N2]] - * n : indice de de l'ouvrage dans le cas des ouvrages parallèles - * N1 : un nom de paramètre/résultat (dans le cas d'un résultat, il est suivi d'un point) - * N2 : nom de résultat complémentaire (optionnel) - * ex : - * Q, Z1 (paramètres) - * J. (résultat) - * .Yf (résultat complémentaire du résultat courant) - * Q.Yf (résultat complémentaire du résultat nommé "Q") - * 0.Q : paramètre Q du 1er ouvrage (ouvrages parallèles) - * ouvrage[1].Q_Mode : résultat complémentaire du 2ème ouvrage (ouvrages parallèles) - */ - private _linkableParams: any[]; + /** liste des paramètres liables */ + private _linkableParams: LinkedValue[]; private _formService: FormulaireService; @@ -71,24 +57,21 @@ export class ParamLinkComponent implements OnChanges, Observer, OnDestroy { return this._linkableParams; } - public get message() { - return this._message; - } - public get label() { return this.intlService.localizeText("INFO_PARAMFIELD_PARAMLIE_LABEL"); } - public set currentLinkedParam(p: any) { + public set currentLinkedParam(p: LinkedValue) { for (let i = 0; i < this._linkableParams.length; i++) { - if (this._linkableParams[i].nub.uid === p.nub.uid) { + const li = this._linkableParams[i]; + if (li.equals(p)) { this.linkTo(i); break; } } } - public get currentLinkedParam() { + public get currentLinkedParam(): LinkedValue { if (this._linkableParams !== undefined) { if (this._currentIndex !== -1 && this._currentIndex < this._linkableParams.length) { return this._linkableParams[this._currentIndex]; @@ -117,47 +100,40 @@ export class ParamLinkComponent implements OnChanges, Observer, OnDestroy { } /** - * attribut "label" d'une entrée du select des paramètres + * Label d'une entrée du select des paramètres liés */ - private selectItemLabel(i: any): string { - const s = i.name; // nom associé au paramètre/à la valeur - const c = i.formTitle; // nom du module de calcul + private selectItemLabel(i: LinkedValue): string { + const s = i.symbol; // nom associé au paramètre/à la valeur + const c = i.meta["formTitle"]; // nom du module de calcul - // pointeur direct vers une Structure dans un Nub de type parallèle - if (i.nub && i.nub instanceof Structure) { + // 1. Paramètre / résultat d'un ouvrage dans un Nub de type parallèle + if (i.nub instanceof Structure) { let p: number; p = i.nub.findPositionInParent(); - // forme xxx. (résultat) - const re4 = /([^\.]+)\.$/; - const match4 = re4.exec(s); - if (match4 !== null) { + if (i.isResult()) { // résultat d'ouvrage - return `${match4[1]} (résultat de ${c}, ouvrage ${p + 1})`; + return `${s} (résultat de ${c}, ouvrage ${p + 1})`; } else { // paramètre d'ouvrage return `${s} (${c}, ouvrage ${p + 1})`; } + } else + // 2. Résultat + if (i.isResult()) { + return `${s} (résultat de ${c})`; + } else + // 3. Résultat complémentaire + if (i.isExtraResult()) { + if (i.meta["result"]) { + // @TODO not used ? + return `${s} (${c}, résultat complémentaire de ${i.meta["result"]})`; + } else { + return `${s} (${c}, résultat complémentaire)`; + } + } else { + // 4. Paramètre (cas général) + return `${s} (${c})`; } - - const re1 = /([^\.]+)\.$/; // forme xxx. (résultat) - const match1 = re1.exec(s); - if (match1 !== null) { - return `${match1[1]} (résultat de ${c})`; - } - - const re2 = /([^\.]+)\.(.+)/; // forme xxx.yyy (résultat complémentaire) - const match2 = re2.exec(s); - if (match2 !== null) { - return `${match2[2]} (${c}, résultat complémentaire de ${match2[1]})`; - } - - const re3 = /^\.(.+)/; // forme .xxx (résultat complémentaire) - const match3 = re3.exec(s); - if (match3 !== null) { - return `${match3[1]} (${c}, résultat complémentaire)`; - } - - return `${s} (${c})`; // forme simple (paramètre) } /** @@ -168,14 +144,23 @@ export class ParamLinkComponent implements OnChanges, Observer, OnDestroy { if (this._currentIndex !== index) { this._currentIndex = index; const lp = this._linkableParams[index]; - this.param.linkToParameter(lp.nub, lp.name); + this.param.linkToValue(lp); + // reset form results when a new target is selected + this.emitModelChanged(); } } + /** + * événement de changement de la valeur du modèle + */ + private emitModelChanged() { + this.change.emit({ "action": "model", "value": this.currentLinkedParam.getValue() }); + } + public updateParamList() { // liste des paramètres liables if (this.param.valueMode === ParamValueMode.LINK) { - this._linkableParams = this._formService.filterLinkableValues(this._formService.getLinkableValues(this.param)); + this._linkableParams = this._formService.getLinkableValues(this.param); } else { this._linkableParams = []; } @@ -187,8 +172,8 @@ export class ParamLinkComponent implements OnChanges, Observer, OnDestroy { if (this.param.valueMode === ParamValueMode.LINK && this._linkableParams !== undefined) { let i = 0; for (const e of this._linkableParams) { - if (this.param.paramDefinition.paramValues.referencedNub - && e.nub.uid === this.param.paramDefinition.paramValues.referencedNub["_uid"]) { + const refValue = this.param.paramDefinition.referencedValue; + if (refValue && e.equals(refValue)) { this._currentIndex = i; break; } else { @@ -198,10 +183,8 @@ export class ParamLinkComponent implements OnChanges, Observer, OnDestroy { } this.linkTo(Math.max(this._currentIndex, 0)); // might still be -1 } - this._message = undefined; } else { this._currentIndex = -1; - this._message = "Aucun paramètre compatible trouvé"; } } @@ -234,12 +217,12 @@ export class ParamLinkComponent implements OnChanges, Observer, OnDestroy { if ( lp.nub.uid === f.currentNub.uid || ( // repeatable structure inside parent module - lp.nub.parent instanceof ParallelStructure + lp.nub instanceof Structure && lp.nub.parent.uid === f.currentNub.uid ) ) { // update <select> option - lp.formTitle = data.value; + lp.meta["formTitle"] = data.value; } } break; diff --git a/src/app/components/param-values/param-values.component.ts b/src/app/components/param-values/param-values.component.ts index d9020c604..07a32d455 100644 --- a/src/app/components/param-values/param-values.component.ts +++ b/src/app/components/param-values/param-values.component.ts @@ -1,10 +1,8 @@ -import { Component, Input, AfterViewInit } from "@angular/core"; +import { Component, Input, AfterViewInit, Output, EventEmitter } from "@angular/core"; import { NgParameter } from "../../formulaire/ngparam"; import { DialogEditParamValuesComponent } from "../dialog-edit-param-values/dialog-edit-param-values.component"; import { MatDialog } from "@angular/material"; -import { ParamValueMode } from "jalhyd"; -import { I18nService } from "../../services/internationalisation/internationalisation.service"; -import { ApplicationSetupService } from "../../services/app-setup/app-setup.service"; +import { ParamValueMode, Observer } from "jalhyd"; @Component({ selector: "param-values", @@ -13,7 +11,7 @@ import { ApplicationSetupService } from "../../services/app-setup/app-setup.serv "./param-values.component.scss" ] }) -export class ParamValuesComponent implements AfterViewInit { +export class ParamValuesComponent implements AfterViewInit, Observer { @Input() public param: NgParameter; @@ -21,11 +19,14 @@ export class ParamValuesComponent implements AfterViewInit { @Input() public title: string; + /** + * événement signalant un changement de valeur du modèle + */ + @Output() + protected change = new EventEmitter<any>(); constructor( - private editValuesDialog: MatDialog, - private intlService: I18nService, - private appSetupService: ApplicationSetupService + private editValuesDialog: MatDialog ) { } public get isMinMax() { @@ -62,5 +63,26 @@ export class ParamValuesComponent implements AfterViewInit { this.openDialog(); }); } + // subscribe to parameter values change (through dialog actions) @TODO draft + this.param.addObserver(this); } + + /** + * événement de changement de la valeur du modèle + */ + private emitModelChanged() { + this.change.emit({ "action": "model", "value": this.param.getValue() }); + } + + public update(sender: any, data: any): void { + if (sender instanceof DialogEditParamValuesComponent) { + switch (data.action) { + case "ngparamAfterValue": + // tell the form to clear the results + this.emitModelChanged(); + break; + } + } + } + } diff --git a/src/app/formulaire/definition/concrete/form-parallel-structures.ts b/src/app/formulaire/definition/concrete/form-parallel-structures.ts index 2f3f6bd41..e6f7550fc 100644 --- a/src/app/formulaire/definition/concrete/form-parallel-structures.ts +++ b/src/app/formulaire/definition/concrete/form-parallel-structures.ts @@ -168,14 +168,12 @@ export class FormulaireParallelStructure extends FormulaireDefinition { } public removeFieldset(fs: FieldSet) { - // console.log("==> FormParallelStructures removeFieldset", fs.uid); if (fs.nub instanceof Structure) { // suppression du sous-nub dans le Nub parent this.deleteNub(fs.nub); // suppression du fieldset this.fieldsetContainer.removeFieldset(fs); - // console.log("====> nb struct dans le parent après", (this.currentNub as ParallelStructure).structures.length); this.resetResults(); } else { super.removeFieldset(fs); } diff --git a/src/app/formulaire/definition/form-def-fixedvar.ts b/src/app/formulaire/definition/form-def-fixedvar.ts index d34f67110..d4add5b8f 100644 --- a/src/app/formulaire/definition/form-def-fixedvar.ts +++ b/src/app/formulaire/definition/form-def-fixedvar.ts @@ -82,16 +82,9 @@ export class FormDefFixedVar { break; case ParamValueMode.LINK: // nouvel état - if (sourceParam.paramDefinition.hasMultipleValues) { + if (sourceParam.paramDefinition.isReferenceDefined() && sourceParam.paramDefinition.hasMultipleValues) { this.resetOtherRadio(sourceParam, ParamRadioConfig.CAL); - } else { - const refParamValues = sourceParam.paramDefinition.referencedParamValues; - if (refParamValues !== undefined) { // cad si on référence un paramètre et non un Result par ex - if (refParamValues.valueMode === ParamValueMode.LINK) { - throw new Error(`références de paramètre en chaîne non pris en charge`); - } - } // cas à traiter - } + } // @TODO vérifier tous les cas problématiques (liens en chaîne ?) break; } break; @@ -105,10 +98,11 @@ export class FormDefFixedVar { case ParamValueMode.LINK: // nouvel état // mode du paramètre référencé - const refParamValues = sourceParam.paramDefinition.referencedParamValues; + /* const refParamValues = sourceParam.paramDefinition.referencedParamValues; if (refParamValues.valueMode === ParamValueMode.LINK) { throw new Error(`références de paramètre en chaîne non pris en charge`); - } + } */ + // @TODO vérifier tous les cas problématiques (liens en chaîne ?) break; } break; diff --git a/src/app/formulaire/definition/form-def-paramcalc.ts b/src/app/formulaire/definition/form-def-paramcalc.ts index cd867bde8..ac743a1ff 100644 --- a/src/app/formulaire/definition/form-def-paramcalc.ts +++ b/src/app/formulaire/definition/form-def-paramcalc.ts @@ -1,4 +1,4 @@ -import { ParamValueMode } from "jalhyd"; +import { ParamValueMode, ParamDefinition } from "jalhyd"; import { NgParameter } from "../ngparam"; import { FormulaireDefinition } from "./form-definition"; @@ -82,9 +82,9 @@ export class FormDefParamToCalculate extends FormDefFixedVar { this.setDefault(); } else { // mode du paramètre référencé - const refParamValues = sourceParam.paramDefinition.referencedParamValues; - if (refParamValues !== undefined) { - switch (refParamValues.valueMode) { + const refValue = sourceParam.paramDefinition.referencedValue; + if (refValue && refValue.isParameter()) { + switch ((refValue.element as ParamDefinition).valueMode) { case ParamValueMode.MINMAX: case ParamValueMode.LISTE: case ParamValueMode.CALCUL: diff --git a/src/app/formulaire/definition/form-definition.ts b/src/app/formulaire/definition/form-definition.ts index 37d42aeb2..564726436 100644 --- a/src/app/formulaire/definition/form-definition.ts +++ b/src/app/formulaire/definition/form-definition.ts @@ -269,17 +269,6 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs } this.completeParse(this._jsonConfig); - - // console.log("-----"); - - // for (const n of Session.getInstance().NubIterator) { - // console.log(n.nub); - // for (const p of n.nub.parameterIterator) - // console.log(`${p.symbol} uid ${p.uid} props ${n.properties} mode ${p.valueMode} val ${p.uncheckedValue}`); - // } - - // logObject(this._fieldSets, "fieldsets"); - // logObject(this._dependencies, "dependences"); this.parseDependencies(this._jsonConfig); } @@ -435,7 +424,10 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs * gestion d'un clic sur les radios */ public onRadioClick(info: any) { - this.reset(); + // if mdoe changed, reset form results + if (info.oldValueMode !== info.param.valueMode) { + this.reset(); + } } /** diff --git a/src/app/formulaire/fieldset.ts b/src/app/formulaire/fieldset.ts index 5dd19f2e5..9c001b21d 100644 --- a/src/app/formulaire/fieldset.ts +++ b/src/app/formulaire/fieldset.ts @@ -153,7 +153,8 @@ export class FieldSet extends FormulaireElement implements Observer { if (res) { res.parseConfig(json, { "radioConfig": default_radio_config }); // set parent Nub on Parameter to ensure UID availability - res.paramDefinition.parent = this._nub; + // should always be done @TODO check + // res.paramDefinition.parent = this._nub; } return res; diff --git a/src/app/formulaire/ngparam.ts b/src/app/formulaire/ngparam.ts index 30ec5d0d5..8a4364854 100644 --- a/src/app/formulaire/ngparam.ts +++ b/src/app/formulaire/ngparam.ts @@ -1,5 +1,5 @@ import { Interval, ParamDefinition, ParamDomain, ParamValueMode, INumberIterator, - Nub, Observer, asObservable, ParamCalculability } from "jalhyd"; + Nub, Observer, asObservable, ParamCalculability, LinkedValue } from "jalhyd"; import { sprintf } from "sprintf-js"; @@ -54,7 +54,7 @@ export class NgParameter extends InputField implements Observer { */ public static preview(p: ParamDefinition): string { let valuePreview: string; - + // console.log("NgParam::preview()", p.symbol, ParamValueMode[p.valueMode], p); switch (p.valueMode) { case ParamValueMode.SINGLE: valuePreview = String(p.getValue()); @@ -89,8 +89,16 @@ export class NgParameter extends InputField implements Observer { } break; case ParamValueMode.LINK: - // recursive call - valuePreview = NgParameter.preview(p.referencedObject as ParamDefinition); + if (p.isReferenceDefined()) { + if (p.referencedValue.isParameter()) { + // recursive call + valuePreview = NgParameter.preview(p.referencedValue.element as ParamDefinition); + } else { + // @TODO what if the result was already computed ? + // Is the computed value fresh or stale ? + valuePreview = ServiceFactory.instance.i18nService.localizeText("INFO_PARAMFIELD_IN_CALCULATION"); + } + } } return valuePreview; @@ -101,7 +109,7 @@ export class NgParameter extends InputField implements Observer { } get domain(): ParamDomain { - return this._paramDef.getDomain(); + return this._paramDef.domain; } public set confId(id: string) { @@ -144,6 +152,7 @@ export class NgParameter extends InputField implements Observer { return this._paramDef.valueMode; } + // @TODO vérifier : ça a une tête à faire 40x trop d'opérations pour rien public set valueMode(m: ParamValueMode) { // undefined si on clique en dehors du select après l'avoir ouvert (cad sans avoir fait de sélection) // et au même niveau, cad à côté du bouton et non à côté du menu déroulant @@ -165,18 +174,10 @@ export class NgParameter extends InputField implements Observer { return this._paramValues.min; } - public set minValue(v: number) { - this._paramValues.min = v; - } - public get maxValue() { return this._paramValues.max; } - public set maxValue(v: number) { - this._paramValues.max = v; - } - public get stepRefValue(): Interval { return this._paramValues.stepRefValue; } @@ -185,18 +186,10 @@ export class NgParameter extends InputField implements Observer { return this._paramValues.step; } - public set stepValue(v: number) { - this._paramValues.step = v; - } - public get valueList() { return this._paramValues.valueList; } - public set valueList(l: number[]) { - this._paramValues.valueList = l; - } - public get isValid() { if (this.radioState === undefined) { return false; @@ -265,11 +258,43 @@ export class NgParameter extends InputField implements Observer { this.notifyValueModified(sender); } + public setMinValue(sender: any, v: number) { + const changed = (this._paramValues.min !== v); + this._paramValues.min = v; + if (changed) { + this.notifyValueModified(sender); + } + } + + public setMaxValue(sender: any, v: number) { + const changed = (this._paramValues.max !== v); + this._paramValues.max = v; + if (changed) { + this.notifyValueModified(sender); + } + } + + public setStepValue(sender: any, v: number) { + const changed = (this._paramValues.step !== v); + this._paramValues.step = v; + if (changed) { + this.notifyValueModified(sender); + } + } + + public setValueList(sender: any, l: number[]) { + const changed = (JSON.stringify(this._paramValues.valueList) !== JSON.stringify(l)); + this._paramValues.valueList = l; + if (changed) { + this.notifyValueModified(sender); + } + } + /** * supprime un lien avec un paramètre */ private unlinkParameter() { - const o = asObservable(this._paramDef.referencedObject); + const o = asObservable(this._paramDef.referencedValue); if (this.valueMode === ParamValueMode.LINK) { this._paramDef.undefineReference(); if (o !== undefined) { @@ -281,21 +306,24 @@ export class NgParameter extends InputField implements Observer { /** * crée le lien avec un paramètre */ - public linkToParameter(n: Nub, ref: string) { + public linkToValue(target: LinkedValue) { const changed: boolean = - this._paramDef.valueMode !== ParamValueMode.LINK || this._paramDef.referencedNub !== n || - this._paramDef.referenceDefinition !== ref; + // changement de mode + ! this._paramDef.isReferenceDefined() + // ou changement de référence + || ! this._paramDef.referencedValue.equals(target); + if (changed) { - let o = asObservable(this._paramDef.referencedObject); + let o = asObservable(this._paramDef.referencedValue); if (o !== undefined) { o.removeObserver(this); } - this.valueMode = ParamValueMode.LINK; + // this.valueMode = ParamValueMode.LINK; // supposed to be done at model level by instruction below // changement de lien - this._paramDef.defineReference(n, ref); + this._paramDef.defineReferenceFromLinkedValue(target); - o = asObservable(this._paramDef.referencedObject); + o = asObservable(this._paramDef.referencedValue); if (o !== undefined) { o.addObserver(this); // pour être prévenu des changements de valeur de l'object référencé } diff --git a/src/app/results/var-results.ts b/src/app/results/var-results.ts index 752664fcb..51208365d 100644 --- a/src/app/results/var-results.ts +++ b/src/app/results/var-results.ts @@ -116,7 +116,6 @@ export class VarResults extends CalculatedParamResults { * @param symbol parameter / result symbol (ex: "Q") */ public getValuesSeries(symbol: string) { - // console.log("GVS for symbol", symbol); const series = []; // 1. calculated param ? if (this._calculatedParam.symbol === symbol) { diff --git a/src/app/services/formulaire/formulaire.service.ts b/src/app/services/formulaire/formulaire.service.ts index 066e82f7a..f841c194f 100644 --- a/src/app/services/formulaire/formulaire.service.ts +++ b/src/app/services/formulaire/formulaire.service.ts @@ -3,7 +3,7 @@ import { Injectable } from "@angular/core"; import { decode } from "he"; import { saveAs } from "file-saver"; -import { CalculatorType, EnumEx, Observable, ParamDefinition, Session, Nub, ParallelStructure } from "jalhyd"; +import { CalculatorType, LinkedValue, Observable, ParamDefinition, Session, Nub, ParallelStructure } from "jalhyd"; import { HttpService } from "../../services/http/http.service"; import { I18nService } from "../../services/internationalisation/internationalisation.service"; @@ -545,78 +545,36 @@ export class FormulaireService extends Observable { } /** - * MAJ des liens entre paramètres lors de la désérialisation + * Demande à la Session JalHYd la liste des paramètres/résultats pouvant être liés au + * paramètre fourni */ - /* private updateParamsLinks(json: {}, formInfos: any[], oldFormCount: number) { - // table de correspondance des uid fichier <-> objets mémoire - // forme : tableau d'objets de la forme : - // { "type" : <type de l'objet. "form" pour formulaire>, - // "old": <uid dans le fichier>, - // "new": <uid de l'objet mémoire>} - const uidMap = []; - for (const ks in json) { - switch (ks) { - case "elements": - let n = oldFormCount; - for (const e of json[ks]) { - if (Object.keys(e)[0] === "form") { - uidMap.push({ - "type": "form", - "old": e["form"]["uid"], - "new": this._formulaires[n].uid - }); - n++; - } - } - } - } - // MAJ liens - for (const ks in json) { - switch (ks) { - case "elements": - let n = 0; - for (const e of json[ks]) { - if (Object.keys(e)[0] === "form") { - this.updateFormLinks(e["form"], formInfos, this._formulaires[n + oldFormCount], uidMap); - n++; + public getLinkableValues(p: NgParameter): LinkedValue[] { + let linkableValues: LinkedValue[] = []; + if (p) { + linkableValues = Session.getInstance().getLinkableValues(p.paramDefinition); + // join form names to ease usage + for (let i = 0; i < linkableValues.length; i++) { + const lv = linkableValues[i]; + for (const f of this._formulaires) { + if (f.currentNub) { + if (f.currentNub.uid === lv.nub.uid) { + lv.meta["formTitle"] = f.calculatorName; + } else { + // child structures ? + if (f.currentNub instanceof ParallelStructure) { + for (const s of f.currentNub.structures) { + if (s.uid === lv.nub.uid) { + lv.meta["formTitle"] = f.calculatorName; + } + } + } } } - break; - - default: - throw new Error(`session file : invalid key '${ks}' in session object`); - } - } - } */ - - /** - * @returns liste des valeurs liables à un paramètre sous la forme d'un tableau d'objets - * {"param":<paramètre lié>, "nub":<Nub d'origine du paramètre lié>, "formTitle":<nom du module de calcul liée au nub>} - * @param p paramètre qui sert de clé de recherche des paramètres liables - */ - public getLinkableValues(p: NgParameter): any[] { - const res: any[] = []; - if (p !== undefined) { - for (const f of this._formulaires) { - // nub associé au formulaire - const sn = f.currentNub; - try { - // on vérifie que le paramètre en entrée appartient au nub - const np = sn.getParameter(p.symbol); - // si oui, on demande à exclure des valeurs retournées le résultat du même nom que le paramètre - const exclude = np !== undefined ? p.paramDefinition.uid === np.uid : false; - // valeurs liables - const ps = sn.getLinkableValues(p.paramDefinition, undefined, exclude); - for (const npp of ps) { - npp["formTitle"] = f.calculatorName; - res.push(npp); - } - } catch (e) { - // p.symbol n'existe pas dans le nub testé } } } - return res; + linkableValues = this.filterLinkableValues(linkableValues); + return linkableValues; } /** @@ -626,16 +584,12 @@ export class FormulaireService extends Observable { * @param values valeurs liables (modifié par la méthode) */ public filterLinkableValues(values: any[]): any[] { - // suppression des paramètres non affichés - for (let i = values.length - 1; i >= 0; i--) { const v = values[i].value; if (v instanceof ParamDefinition) { // pour chaque paramètre... const prm: ParamDefinition = v; - const parentForm: FormulaireDefinition = this.getParamdefParentForm(prm); - // ... on cherche s'il est affiché dans son parent let found = false; if (parentForm !== undefined) { @@ -648,13 +602,11 @@ export class FormulaireService extends Observable { } } } - if (!found) { values.splice(i, 1); } } } - return values; } } diff --git a/src/locale/messages.en.json b/src/locale/messages.en.json index bed80e332..0c952da55 100644 --- a/src/locale/messages.en.json +++ b/src/locale/messages.en.json @@ -22,6 +22,7 @@ "ERROR_PARAMDEF_VALUE_POS": "value %value% of '%symbol%' parameter is invalid (cannot be <=0)", "ERROR_PARAMDEF_VALUE_POSNULL": "value %value% of '%symbol%' parameter is invalid (cannot be <0)", "ERROR_PARAMDEF_VALUE_UNDEFINED": "value of '%symbol%' parameter is undefined", + "ERROR_PARAMDEF_LINKED_VALUE_UNDEFINED": "value of '%symbol%' linked parameter is undefined", "ERROR_PARAMDOMAIN_INTERVAL_BOUNDS": "invalid %minValue%/%maxValue% min/max boundaries for 'interval' parameter definition domain", "ERROR_PARAMDOMAIN_INVALID": "parameter '%symbol%: non supported '%domain%' definition domain", "ERROR_REMOUS_PAS_CALCUL_DEPUIS_AMONT": "Upstream boundary condition < Critical elevation: no possible calculation from upstream", diff --git a/src/locale/messages.fr.json b/src/locale/messages.fr.json index ea0bae031..e48c43e99 100644 --- a/src/locale/messages.fr.json +++ b/src/locale/messages.fr.json @@ -22,6 +22,7 @@ "ERROR_PARAMDEF_VALUE_POS": "La valeur %value% du paramètre '%symbol%' est incorrecte (<=0)", "ERROR_PARAMDEF_VALUE_POSNULL": "La valeur %value% du paramètre '%symbol%' est incorrecte (<0)", "ERROR_PARAMDEF_VALUE_UNDEFINED": "La valeur du paramètre %symbol% n'est pas définie", + "ERROR_PARAMDEF_LINKED_VALUE_UNDEFINED": "La valeur du paramètre lié %symbol% n'est pas définie", "ERROR_PARAMDOMAIN_INTERVAL_BOUNDS": "Les bornes (%minValue%/%maxValue%) de l'intervalle sont incorrectes", "ERROR_PARAMDOMAIN_INVALID": "Paramètre '%symbol%' : le domaine de définition '%domain%' est incorrect", "ERROR_REMOUS_PAS_CALCUL_DEPUIS_AMONT": "Condition limite amont > Hauteur critique : pas de calcul possible depuis l'amont", -- GitLab From bc35330bcba61f315f7f2e46ddc92b2ff33b230b Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Mon, 18 Mar 2019 17:09:38 +0100 Subject: [PATCH 02/39] Fix #166 --- .../dialog-confirm-close-calc.component.html | 13 ++++++++++- .../dialog-confirm-close-calc.component.scss | 3 +++ .../dialog-confirm-close-calc.component.ts | 22 ++++++++++++++++++- .../calculator.component.ts | 7 +++++- src/locale/messages.en.json | 1 + src/locale/messages.fr.json | 1 + 6 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 src/app/components/dialog-confirm-close-calc/dialog-confirm-close-calc.component.scss diff --git a/src/app/components/dialog-confirm-close-calc/dialog-confirm-close-calc.component.html b/src/app/components/dialog-confirm-close-calc/dialog-confirm-close-calc.component.html index 8018436a7..f1abc0500 100644 --- a/src/app/components/dialog-confirm-close-calc/dialog-confirm-close-calc.component.html +++ b/src/app/components/dialog-confirm-close-calc/dialog-confirm-close-calc.component.html @@ -1,7 +1,18 @@ <h1 mat-dialog-title [innerHTML]="uitextCloseCalcTitle"></h1> <div mat-dialog-content> - <p [innerHTML]="uitextCloseCalcBody"></p> + + <div *ngIf="dependingNubs.length"> + {{ uitextDependingModules }} + <mat-list role="list"> + <mat-list-item role="listitem" *ngFor="let dn of dependingNubs"> + {{ dn }} + </mat-list-item> + </mat-list> + </div> </div> + +<p [innerHTML]="uitextCloseCalcBody"></p> + <div mat-dialog-actions> <button mat-raised-button color="primary" [mat-dialog-close]="false" cdkFocusInitial> {{ uitextNo }} diff --git a/src/app/components/dialog-confirm-close-calc/dialog-confirm-close-calc.component.scss b/src/app/components/dialog-confirm-close-calc/dialog-confirm-close-calc.component.scss new file mode 100644 index 000000000..268f18ad8 --- /dev/null +++ b/src/app/components/dialog-confirm-close-calc/dialog-confirm-close-calc.component.scss @@ -0,0 +1,3 @@ +.mat-list-base .mat-list-item { + height: 24px; +} diff --git a/src/app/components/dialog-confirm-close-calc/dialog-confirm-close-calc.component.ts b/src/app/components/dialog-confirm-close-calc/dialog-confirm-close-calc.component.ts index e8a1f44ca..63cdc8fa4 100644 --- a/src/app/components/dialog-confirm-close-calc/dialog-confirm-close-calc.component.ts +++ b/src/app/components/dialog-confirm-close-calc/dialog-confirm-close-calc.component.ts @@ -1,18 +1,30 @@ import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material"; import { Inject, Component } from "@angular/core"; +import { FormulaireService } from "../../services/formulaire/formulaire.service"; import { I18nService } from "../../services/internationalisation/internationalisation.service"; +import { Session } from "jalhyd"; @Component({ selector: "dialog-confirm-close-calc", templateUrl: "dialog-confirm-close-calc.component.html", + styleUrls: [ + "dialog-confirm-close-calc.component.scss" + ] }) export class DialogConfirmCloseCalcComponent { + private _dependingNubs: any[] = []; + constructor( public dialogRef: MatDialogRef<DialogConfirmCloseCalcComponent>, private intlService: I18nService, + private formService: FormulaireService, @Inject(MAT_DIALOG_DATA) public data: any - ) { } + ) { + this._dependingNubs = Session.getInstance().getDependingNubs(data.uid).map((n) => { + return this.formService.getFormulaireFromNubId(n.uid).calculatorName; + }); + } public get uitextYes() { return this.intlService.localizeText("INFO_OPTION_YES"); @@ -30,4 +42,12 @@ export class DialogConfirmCloseCalcComponent { return this.intlService.localizeText("INFO_CLOSE_DIALOGUE_TEXT"); } + public get uitextDependingModules() { + return this.intlService.localizeText("INFO_CLOSE_DIALOGUE_DEPENDING_MODULES"); + } + + public get dependingNubs() { + return this._dependingNubs; + } + } diff --git a/src/app/components/generic-calculator/calculator.component.ts b/src/app/components/generic-calculator/calculator.component.ts index af807c109..a0cc4b468 100644 --- a/src/app/components/generic-calculator/calculator.component.ts +++ b/src/app/components/generic-calculator/calculator.component.ts @@ -386,7 +386,12 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit, public closeCalculator() { const dialogRef = this.confirmCloseCalcDialog.open( DialogConfirmCloseCalcComponent, - { disableClose: true } + { + data: { + uid: this._formulaire.currentNub.uid + }, + disableClose: true + } ); dialogRef.afterClosed().subscribe(result => { if (result) { diff --git a/src/locale/messages.en.json b/src/locale/messages.en.json index 0c952da55..506bda9e7 100644 --- a/src/locale/messages.en.json +++ b/src/locale/messages.en.json @@ -44,6 +44,7 @@ "INFO_CLOISONS_TITRE_COURT": "Cross walls", "INFO_CLOSE_DIALOGUE_TEXT": "Warning ! Parameters and results will be lost. Really close?", "INFO_CLOSE_DIALOGUE_TITRE": "Please confirm", + "INFO_CLOSE_DIALOGUE_DEPENDING_MODULES": "The following modules depend on the one you are closing:", "INFO_CONDUITEDISTRIBUTRICE_TITRE": "Distributor pipe", "INFO_CONDUITEDISTRIBUTRICE_TITRE_COURT": "D. pipe", "INFO_COURBEREMOUS_TITRE": "Backwater curves", diff --git a/src/locale/messages.fr.json b/src/locale/messages.fr.json index e48c43e99..90b8466f0 100644 --- a/src/locale/messages.fr.json +++ b/src/locale/messages.fr.json @@ -44,6 +44,7 @@ "INFO_CLOISONS_TITRE_COURT": "Cloisons", "INFO_CLOSE_DIALOGUE_TEXT": "Attention ! Les paramètres et résultats du module de calcul seront perdus. Vraiment fermer ?", "INFO_CLOSE_DIALOGUE_TITRE": "Confirmer la fermeture", + "INFO_CLOSE_DIALOGUE_DEPENDING_MODULES": "Les modules suivants dépendent de celui que vous êtes en train de fermer :", "INFO_CONDUITEDISTRIBUTRICE_TITRE": "Conduite distributrice", "INFO_CONDUITEDISTRIBUTRICE_TITRE_COURT": "Conduite distri.", "INFO_COURBEREMOUS_TITRE": "Courbes de remous", -- GitLab From 71e006eaf195f04b790c38597343fcbd91e5cf64 Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Tue, 19 Mar 2019 11:13:12 +0100 Subject: [PATCH 03/39] Localisation: do not reload / recompute whole form eery time it is loaded --- .../formulaire/definition/form-definition.ts | 13 +++++++-- .../services/formulaire/formulaire.service.ts | 28 ++++++------------- 2 files changed, 19 insertions(+), 22 deletions(-) diff --git a/src/app/formulaire/definition/form-definition.ts b/src/app/formulaire/definition/form-definition.ts index 564726436..fe7e94009 100644 --- a/src/app/formulaire/definition/form-definition.ts +++ b/src/app/formulaire/definition/form-definition.ts @@ -36,6 +36,9 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs /** clé-valeurs du fichier de localisation spécifique à ce module */ private _specificLocalisation: StringMap; + /** ISO 639-1 language code of the current language (to avoid unnecessary localisation reload) */ + private _currentLanguage: string; + constructor() { super(undefined); } @@ -54,6 +57,10 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs return this._specificLocalisation; } + public get currentLanguage() { + return this._currentLanguage; + } + public get calculatorType(): CalculatorType { const props = this._currentNub === undefined ? this.defaultProperties : (this._currentNub.properties as Props).props; return props["calcType"]; @@ -387,14 +394,14 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs public abstract get hasResults(): boolean; public abstract get results(): CalculatorResults[]; - public updateLocalisation(localisation: StringMap) { + public updateLocalisation(localisation: StringMap, lang: string) { this._specificLocalisation = localisation; + this._currentLanguage = lang; for (const fe of this.topFormElements) { fe.updateLocalisation(localisation); } - if (this.hasResults) { - this.doCompute(); // pour mettre à jour la langue + this.doCompute(); // pour mettre à jour la langue des intitulés de résultats } } diff --git a/src/app/services/formulaire/formulaire.service.ts b/src/app/services/formulaire/formulaire.service.ts index f841c194f..59a85bd44 100644 --- a/src/app/services/formulaire/formulaire.service.ts +++ b/src/app/services/formulaire/formulaire.service.ts @@ -97,27 +97,17 @@ export class FormulaireService extends Observable { } /** - * Met à jour la langue du formulaire - * @param formId id unique du formulaire - * @param localisation ensemble id-message traduit - */ - private updateFormulaireLocalisation(formId: string, localisation: StringMap) { - for (const f of this._formulaires) { - if (f.uid === formId) { - f.updateLocalisation(localisation); - break; - } - } - } - - /** - * charge la localisation et met à jour la langue du formulaire + * Loads localisation file corresponding to current language then updates all form strings, + * only if form language was not already set to current language */ public loadUpdateFormulaireLocalisation(f: FormulaireDefinition): Promise<FormulaireDefinition> { - return this.loadLocalisation(f.calculatorType).then(localisation => { - this.updateFormulaireLocalisation(f.uid, localisation); - return f; - }); + const requiredLang = this._intlService.currentLanguage; + if (requiredLang !== f.currentLanguage) { + return this.loadLocalisation(f.calculatorType).then(localisation => { + f.updateLocalisation(localisation, requiredLang); + return f; + }); + } } /** -- GitLab From deec5e98c45c8556ec2b4b252a782c4e92c1fafa Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Tue, 19 Mar 2019 12:27:34 +0100 Subject: [PATCH 04/39] Factorisation de code dans les Formulaires --- .../definition/concrete/form-base.ts | 16 ++++--- .../definition/concrete/form-courbe-remous.ts | 24 ++-------- .../concrete/form-lechapt-calmon.ts | 8 ++++ .../concrete/form-parallel-structures.ts | 47 ++----------------- .../concrete/form-regime-uniforme.ts | 46 ++---------------- .../concrete/form-section-parametree.ts | 40 ++-------------- 6 files changed, 31 insertions(+), 150 deletions(-) diff --git a/src/app/formulaire/definition/concrete/form-base.ts b/src/app/formulaire/definition/concrete/form-base.ts index 6b28a0a2f..1d1c0e26e 100644 --- a/src/app/formulaire/definition/concrete/form-base.ts +++ b/src/app/formulaire/definition/concrete/form-base.ts @@ -1,24 +1,24 @@ -import { FormDefFixedVar } from "../form-def-fixedvar"; -import { FormResultFixedVar } from "../form-result-fixedvar"; import { FormulaireDefinition } from "../form-definition"; import { CalculatorResults } from "../../../results/calculator-results"; import { FormDefParamToCalculate } from "../form-def-paramcalc"; +import { FormResult } from "../form-result"; +import { FormCompute } from "../form-compute"; +import { FormResultFixedVar } from "../form-result-fixedvar"; import { FormComputeFixedVar } from "../form-compute-fixedvar"; export class FormulaireBase extends FormulaireDefinition { - private _formParamCalc: FormDefParamToCalculate; + protected _formParamCalc: FormDefParamToCalculate; - private _formCompute: FormComputeFixedVar; + protected _formCompute: FormCompute; - private _formResult: FormResultFixedVar; + protected _formResult: FormResult; constructor() { super(); - // this._formFixedVar = new FormDefFixedVar(this); this._formParamCalc = new FormDefParamToCalculate(this); this._formResult = new FormResultFixedVar(this, false); - this._formCompute = new FormComputeFixedVar(this, this._formResult); + this._formCompute = new FormComputeFixedVar(this, (this._formResult as FormResultFixedVar)); } protected completeParse(json: {}) { @@ -35,6 +35,8 @@ export class FormulaireBase extends FormulaireDefinition { public resetResults() { this._formResult.resetResults(); + // @TODO cascade + // @TODO this.notifyReset() ? } public doCompute() { diff --git a/src/app/formulaire/definition/concrete/form-courbe-remous.ts b/src/app/formulaire/definition/concrete/form-courbe-remous.ts index e65fc2e3b..ee2e61019 100644 --- a/src/app/formulaire/definition/concrete/form-courbe-remous.ts +++ b/src/app/formulaire/definition/concrete/form-courbe-remous.ts @@ -3,16 +3,12 @@ import { IObservable, MethodeResolution } from "jalhyd"; import { FormResultRemous } from "../form-result-remous"; import { FormDefSection } from "../form-def-section"; import { FormComputeCourbeRemous } from "../form-compute-courbe-remous"; -import { FormulaireDefinition } from "../form-definition"; -import { CalculatorResults } from "../../../results/calculator-results"; import { FieldSet } from "../../fieldset"; +import { FormulaireBase } from "./form-base"; -export class FormulaireCourbeRemous extends FormulaireDefinition { - private _formSection: FormDefSection; - - private _formCompute: FormComputeCourbeRemous; +export class FormulaireCourbeRemous extends FormulaireBase { - private _formResult: FormResultRemous; + private _formSection: FormDefSection; /** * id du select configurant la méthode de résolution @@ -23,7 +19,7 @@ export class FormulaireCourbeRemous extends FormulaireDefinition { super(); this._formSection = new FormDefSection(this); this._formResult = new FormResultRemous(this); - this._formCompute = new FormComputeCourbeRemous(this, this._formSection, this._formResult); + this._formCompute = new FormComputeCourbeRemous(this, this._formSection, (this._formResult as FormResultRemous)); // default properties this._props["methodeResolution"] = MethodeResolution.Trapezes; this._props["varCalc"] = undefined; // important @@ -56,18 +52,6 @@ export class FormulaireCourbeRemous extends FormulaireDefinition { this.notifyReset(); } - public doCompute() { - this._formCompute.doCompute(); - } - - public get hasResults(): boolean { - return this._formResult.hasResults; - } - - public get results(): CalculatorResults[] { - return this._formResult.results; - } - // interface Observer update(sender: IObservable, data: any) { diff --git a/src/app/formulaire/definition/concrete/form-lechapt-calmon.ts b/src/app/formulaire/definition/concrete/form-lechapt-calmon.ts index 69124f646..c84864baa 100644 --- a/src/app/formulaire/definition/concrete/form-lechapt-calmon.ts +++ b/src/app/formulaire/definition/concrete/form-lechapt-calmon.ts @@ -2,9 +2,17 @@ import { Observer } from "jalhyd"; import { SelectField } from "../../select-field"; import { FormulaireBase } from "./form-base"; import { NgParamInputComponent } from "../../../components/ngparam-input/ngparam-input.component"; +import { FormResultFixedVar } from "../form-result-fixedvar"; +import { FormComputeFixedVar } from "../form-compute-fixedvar"; export class FormulaireLechaptCalmon extends FormulaireBase implements Observer { + constructor() { + super(); + this._formResult = new FormResultFixedVar(this, false); + this._formCompute = new FormComputeFixedVar(this, (this._formResult as FormResultFixedVar)); + } + protected completeParse(json: {}) { super.completeParse(json); // abonnement au changement de valeur du select de matériau diff --git a/src/app/formulaire/definition/concrete/form-parallel-structures.ts b/src/app/formulaire/definition/concrete/form-parallel-structures.ts index e6f7550fc..d71119c87 100644 --- a/src/app/formulaire/definition/concrete/form-parallel-structures.ts +++ b/src/app/formulaire/definition/concrete/form-parallel-structures.ts @@ -1,8 +1,5 @@ import { Structure, Nub, ParallelStructure, StructureType, LoiDebit, StructureProperties, Props, Session } from "jalhyd"; -import { FormulaireDefinition } from "../form-definition"; -import { CalculatorResults } from "../../../results/calculator-results"; -import { FormDefParamToCalculate } from "../form-def-paramcalc"; import { FormDefParallelStructures } from "../form-def-parallel-structures"; import { FormComputeParallelStructures } from "../form-compute-parallel-structures"; import { FormResultFixedVar } from "../form-result-fixedvar"; @@ -12,19 +9,12 @@ import { SelectField } from "../../select-field"; import { NgParameter } from "../../ngparam"; import { FieldsetTemplate } from "../../fieldset-template"; import { FormulaireNode } from "../../formulaire-node"; +import { FormulaireBase } from "./form-base"; -export class FormulaireParallelStructure extends FormulaireDefinition { - - // private _formFixedVar: FormDefFixedVar; +export class FormulaireParallelStructure extends FormulaireBase { private _formParallelStruct: FormDefParallelStructures; - private _formParamCalc: FormDefParamToCalculate; - - private _formCompute: FormComputeParallelStructures; - - private _formResult: FormResultFixedVar; - /** * id du select configurant le type d'ouvrage */ @@ -32,11 +22,9 @@ export class FormulaireParallelStructure extends FormulaireDefinition { constructor() { super(); - // this._formFixedVar = new FormDefFixedVar(this); - this._formParamCalc = new FormDefParamToCalculate(this); this._formResult = new FormResultFixedVar(this, false); this._formParallelStruct = new FormDefParallelStructures(); - this._formCompute = new FormComputeParallelStructures(this, this._formParallelStruct, this._formResult); + this._formCompute = new FormComputeParallelStructures(this, this._formParallelStruct, (this._formResult as FormResultFixedVar)); } private createStructNub(templ: FieldsetTemplate): Nub { @@ -184,35 +172,6 @@ export class FormulaireParallelStructure extends FormulaireDefinition { this.subscribeFieldsetContainer(); } - /** - * gestion du clic sur les radios "paramètre fixé, à varier, à calculer" - */ - public onRadioClick(info: string) { - super.onRadioClick(info); - this._formParamCalc.onRadioClick(info); - } - - /** - * @return une chaîne représentant le "contexte" courant (ici, combinaison type d'ouvrage-loi de débit) - * @param fs FieldSet contenant les listes déroulantes type d'ouvrage et loi de débit - */ - - public resetResults() { - this._formResult.resetResults(); - } - - public doCompute() { - this._formCompute.doCompute(); - } - - public get hasResults(): boolean { - return this._formResult.hasResults; - } - - public get results(): CalculatorResults[] { - return this._formResult.results; - } - private get fieldsetContainer(): FieldsetContainer { const n = this.getFormulaireNodeById("struct_container"); if (n === undefined || !(n instanceof FieldsetContainer)) { diff --git a/src/app/formulaire/definition/concrete/form-regime-uniforme.ts b/src/app/formulaire/definition/concrete/form-regime-uniforme.ts index 7e607af99..35a08225c 100644 --- a/src/app/formulaire/definition/concrete/form-regime-uniforme.ts +++ b/src/app/formulaire/definition/concrete/form-regime-uniforme.ts @@ -1,31 +1,19 @@ -import { FormDefFixedVar } from "../form-def-fixedvar"; import { IObservable, Observer } from "jalhyd"; import { FormResultFixedVar } from "../form-result-fixedvar"; -import { FormulaireDefinition } from "../form-definition"; import { FormDefSection } from "../form-def-section"; -import { CalculatorResults } from "../../../results/calculator-results"; -import { FormDefParamToCalculate } from "../form-def-paramcalc"; import { FieldSet } from "../../fieldset"; import { FormComputeFixedVar } from "../form-compute-fixedvar"; +import { FormulaireBase } from "./form-base"; -export class FormulaireRegimeUniforme extends FormulaireDefinition implements Observer { - private _formFixedVar: FormDefFixedVar; - - private _formParamCalc: FormDefParamToCalculate; +export class FormulaireRegimeUniforme extends FormulaireBase implements Observer { private _formSection: FormDefSection; - private _formCompute: FormComputeFixedVar; - - private _formResult: FormResultFixedVar; - constructor() { super(); - this._formFixedVar = new FormDefFixedVar(this); - this._formParamCalc = new FormDefParamToCalculate(this); this._formSection = new FormDefSection(this); this._formResult = new FormResultFixedVar(this, true); - this._formCompute = new FormComputeFixedVar(this, this._formResult); + this._formCompute = new FormComputeFixedVar(this, (this._formResult as FormResultFixedVar)); } protected parseOptions(json: {}) { @@ -42,34 +30,6 @@ export class FormulaireRegimeUniforme extends FormulaireDefinition implements Ob super.completeParse(json); } - /** - * gestion du clic sur les radios "paramètre fixé, à varier, à calculer" - */ - public onRadioClick(info: string) { - super.onRadioClick(info); - this._formParamCalc.onRadioClick(info); - } - - public resetResults() { - this._formResult.resetResults(); - } - - public doCompute() { - this._formCompute.doCompute(); - } - - public get hasResults(): boolean { - return this._formResult.hasResults; - } - - public get results(): CalculatorResults[] { - return this._formResult.results; - } - - public reset() { - super.reset(); - } - // interface Observer update(sender: IObservable, data: any) { diff --git a/src/app/formulaire/definition/concrete/form-section-parametree.ts b/src/app/formulaire/definition/concrete/form-section-parametree.ts index 04508ccaf..9c48c038b 100644 --- a/src/app/formulaire/definition/concrete/form-section-parametree.ts +++ b/src/app/formulaire/definition/concrete/form-section-parametree.ts @@ -3,26 +3,18 @@ import { IObservable } from "jalhyd"; import { FormResultSection } from "../form-result-section"; import { FormDefSection } from "../form-def-section"; import { FormComputeSectionParametree } from "../form-compute-section-parametree"; -import { FormulaireDefinition } from "../form-definition"; -import { CalculatorResults } from "../../../results/calculator-results"; -import { FormDefFixedVar } from "../form-def-fixedvar"; import { FieldSet } from "../../fieldset"; +import { FormulaireBase } from "./form-base"; -export class FormulaireSectionParametree extends FormulaireDefinition { - private _formFixedVar: FormDefFixedVar; +export class FormulaireSectionParametree extends FormulaireBase { private _formSection: FormDefSection; - private _formCompute: FormComputeSectionParametree; - - private _formSectionResult: FormResultSection; - constructor() { super(); - this._formFixedVar = new FormDefFixedVar(this); this._formSection = new FormDefSection(this); - this._formSectionResult = new FormResultSection(this, this._formSection); - this._formCompute = new FormComputeSectionParametree(this, this._formSection, this._formSectionResult); + this._formResult = new FormResultSection(this, this._formSection); + this._formCompute = new FormComputeSectionParametree(this, this._formSection, (this._formResult as FormResultSection)); // default properties this._props["varCalc"] = "Hs"; } @@ -36,30 +28,6 @@ export class FormulaireSectionParametree extends FormulaireDefinition { this._formSection.afterParseFieldset(fs); } - /** - * gestion du clic sur les radios "paramètre fixé, à varier, à calculer" - */ - public onRadioClick(info: string) { - super.onRadioClick(info); - this._formFixedVar.onRadioClick(info); - } - - public resetResults() { - this._formSectionResult.resetResults(); - } - - public doCompute() { - this._formCompute.doCompute(); - } - - public get hasResults(): boolean { - return this._formSectionResult.hasResults; - } - - public get results(): CalculatorResults[] { - return this._formSectionResult.results; - } - // interface Observer update(sender: IObservable, data: any) { -- GitLab From e2ce663f5fea14cde6d5509448b2f91ff8793170 Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Tue, 19 Mar 2019 14:15:01 +0100 Subject: [PATCH 05/39] Fix #171 --- src/app/formulaire/definition/concrete/form-base.ts | 5 +++-- .../definition/concrete/form-courbe-remous.ts | 6 ------ src/app/services/formulaire/formulaire.service.ts | 13 +++++++++++++ 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/app/formulaire/definition/concrete/form-base.ts b/src/app/formulaire/definition/concrete/form-base.ts index 1d1c0e26e..9d7e4b120 100644 --- a/src/app/formulaire/definition/concrete/form-base.ts +++ b/src/app/formulaire/definition/concrete/form-base.ts @@ -5,6 +5,7 @@ import { FormResult } from "../form-result"; import { FormCompute } from "../form-compute"; import { FormResultFixedVar } from "../form-result-fixedvar"; import { FormComputeFixedVar } from "../form-compute-fixedvar"; +import { ServiceFactory } from "../../../services/service-factory"; export class FormulaireBase extends FormulaireDefinition { @@ -35,8 +36,8 @@ export class FormulaireBase extends FormulaireDefinition { public resetResults() { this._formResult.resetResults(); - // @TODO cascade - // @TODO this.notifyReset() ? + // reset the results of all forms depending on this one + ServiceFactory.instance.formulaireService.resetAllDependingFormsResults(this); } public doCompute() { diff --git a/src/app/formulaire/definition/concrete/form-courbe-remous.ts b/src/app/formulaire/definition/concrete/form-courbe-remous.ts index ee2e61019..4e96da330 100644 --- a/src/app/formulaire/definition/concrete/form-courbe-remous.ts +++ b/src/app/formulaire/definition/concrete/form-courbe-remous.ts @@ -46,12 +46,6 @@ export class FormulaireCourbeRemous extends FormulaireBase { } } - public resetResults() { - this._formResult.resetResults(); - // prévenir les composants qu'il faut détecter les changements - this.notifyReset(); - } - // interface Observer update(sender: IObservable, data: any) { diff --git a/src/app/services/formulaire/formulaire.service.ts b/src/app/services/formulaire/formulaire.service.ts index 59a85bd44..755083ba6 100644 --- a/src/app/services/formulaire/formulaire.service.ts +++ b/src/app/services/formulaire/formulaire.service.ts @@ -521,6 +521,7 @@ export class FormulaireService extends Observable { /** * met à jour les liens d'un formulaire + * @TODO rewrite * @param json conf du formulaire * @param formInfos métadonnées sur les formulaires chargés * @param form formulaire dont on met à jour les liens @@ -599,4 +600,16 @@ export class FormulaireService extends Observable { } return values; } + + /** + * Resets the results of all forms depending on the given form "f" + * @param f + */ + public resetAllDependingFormsResults(f: FormulaireDefinition) { + const dependingNubs = Session.getInstance().getDependingNubs(f.currentNub.uid); + for (const dn of dependingNubs) { + const form = this.getFormulaireFromNubId(dn.uid); + form.resetResults(); + } + } } -- GitLab From 63b8715c6778eb5aedb37055bb6ccbbe7c0b7508 Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Tue, 19 Mar 2019 14:16:23 +0100 Subject: [PATCH 06/39] Comments --- .../dialog-edit-param-computed.component.html | 1 - .../components/param-field-line/param-field-line.component.ts | 2 +- src/app/formulaire/definition/form-def-fixedvar.ts | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/app/components/dialog-edit-param-computed/dialog-edit-param-computed.component.html b/src/app/components/dialog-edit-param-computed/dialog-edit-param-computed.component.html index 9efaf2887..517a0f0d1 100644 --- a/src/app/components/dialog-edit-param-computed/dialog-edit-param-computed.component.html +++ b/src/app/components/dialog-edit-param-computed/dialog-edit-param-computed.component.html @@ -4,7 +4,6 @@ <div mat-dialog-content> <ngparam-input [title]="param.title" ></ngparam-input> - <!-- (change)="onInputChange($event)" --> </div> <div mat-dialog-actions> diff --git a/src/app/components/param-field-line/param-field-line.component.ts b/src/app/components/param-field-line/param-field-line.component.ts index 198dc15cd..ed9bb5063 100644 --- a/src/app/components/param-field-line/param-field-line.component.ts +++ b/src/app/components/param-field-line/param-field-line.component.ts @@ -219,7 +219,7 @@ export class ParamFieldLineComponent implements OnChanges { switch (option) { case "fix": this.param.valueMode = ParamValueMode.SINGLE; - // @WTF why do we reset the value here ? + // reset the value to avoid "undefined" after exiting CALC or LINK mode this.param.setValue(this, this.param.paramDefinition.paramValues.singleValue); break; diff --git a/src/app/formulaire/definition/form-def-fixedvar.ts b/src/app/formulaire/definition/form-def-fixedvar.ts index d4add5b8f..4474e9a7c 100644 --- a/src/app/formulaire/definition/form-def-fixedvar.ts +++ b/src/app/formulaire/definition/form-def-fixedvar.ts @@ -148,7 +148,7 @@ export class FormDefFixedVar { } } // if the current calculated parameter was set to another mode, set a new param - // to calculated mode (there must always be at least one) + // to calculated mode (there must always be exactly one) if (newCal) { newCal.valueMode = ParamValueMode.CALCUL; } -- GitLab From 15d8df116b292c7bca1565a4fae25358004cc141 Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Tue, 19 Mar 2019 14:27:50 +0100 Subject: [PATCH 07/39] Linked param: back to FIX mode when no more targets are available --- src/app/components/param-link/param-link.component.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/app/components/param-link/param-link.component.ts b/src/app/components/param-link/param-link.component.ts index 5601ced0a..edad76498 100644 --- a/src/app/components/param-link/param-link.component.ts +++ b/src/app/components/param-link/param-link.component.ts @@ -137,7 +137,9 @@ export class ParamLinkComponent implements OnChanges, Observer, OnDestroy { } /** - * lie le paramètre géré à un des paramètres liables de la liste + * lie le paramètre géré à un des paramètres liables de la liste; appelé + * systématiquement lorsqu'on construit le formulaire, même si le + * paramètre est déjà lié * @param index indice dans la liste */ private linkTo(index: number) { @@ -185,6 +187,8 @@ export class ParamLinkComponent implements OnChanges, Observer, OnDestroy { } } else { this._currentIndex = -1; + // back to SINGLE mode by default + this.param.valueMode = ParamValueMode.SINGLE; } } -- GitLab From e488c13671807505b2d1d25f929f5cdd79ea1990 Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Tue, 19 Mar 2019 14:35:33 +0100 Subject: [PATCH 08/39] Reset all depending forms results when closing a calculator --- src/app/services/formulaire/formulaire.service.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/app/services/formulaire/formulaire.service.ts b/src/app/services/formulaire/formulaire.service.ts index 755083ba6..d8db5e661 100644 --- a/src/app/services/formulaire/formulaire.service.ts +++ b/src/app/services/formulaire/formulaire.service.ts @@ -403,6 +403,8 @@ export class FormulaireService extends Observable { "action": "closeForm", "form": form }); + // reset the results of all forms depending on this one + this.resetAllDependingFormsResults(form); } if (nub) { Session.getInstance().deleteNub(nub); -- GitLab From c43d270da8fc9b5e711361b2d0f8f487b769f8ea Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Tue, 19 Mar 2019 17:40:18 +0100 Subject: [PATCH 09/39] =?UTF-8?q?Aper=C3=A7u=20des=20param=C3=A8tres=20li?= =?UTF-8?q?=C3=A9s:=20gestion=20des=20r=C3=A9sultats=20de=20calcul?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/formulaire/ngparam.ts | 49 ++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/src/app/formulaire/ngparam.ts b/src/app/formulaire/ngparam.ts index 8a4364854..de3ce46dc 100644 --- a/src/app/formulaire/ngparam.ts +++ b/src/app/formulaire/ngparam.ts @@ -51,9 +51,11 @@ export class NgParameter extends InputField implements Observer { /** * Returns a text preview of the current value(s), depending on the value mode + * @TODO use display precision to limit decimals */ public static preview(p: ParamDefinition): string { let valuePreview: string; + const i18n = ServiceFactory.instance.i18nService; // console.log("NgParam::preview()", p.symbol, ParamValueMode[p.valueMode], p); switch (p.valueMode) { case ParamValueMode.SINGLE: @@ -73,30 +75,59 @@ export class NgParameter extends InputField implements Observer { if (step) { step = step.toFixed(nDigits); } - valuePreview = ServiceFactory.instance.i18nService.localizeText("INFO_PARAMFIELD_PARAMVARIER_MINMAXSTEP"); + valuePreview = i18n.localizeText("INFO_PARAMFIELD_PARAMVARIER_MINMAXSTEP"); valuePreview = sprintf(valuePreview, min, max, step); break; case ParamValueMode.LISTE: - valuePreview = ServiceFactory.instance.i18nService.localizeText("INFO_PARAMFIELD_PARAMVARIER_VALUES"); + valuePreview = i18n.localizeText("INFO_PARAMFIELD_PARAMVARIER_VALUES"); const vals = p.paramValues.valueList || []; valuePreview += " " + vals.slice(0, 5).join("; ") + "…"; break; case ParamValueMode.CALCUL: - valuePreview = ServiceFactory.instance.i18nService.localizeText("INFO_PARAMFIELD_IN_CALCULATION"); + valuePreview = i18n.localizeText("INFO_PARAMFIELD_IN_CALCULATION"); if (p.calculability === ParamCalculability.DICHO) { - valuePreview += " (" + ServiceFactory.instance.i18nService.localizeText("INFO_PARAMFIELD_IN_CALCULATION_INITIAL_VALUE") + valuePreview += " (" + i18n.localizeText("INFO_PARAMFIELD_IN_CALCULATION_INITIAL_VALUE") + ": " + p.getValue() + ")"; } break; case ParamValueMode.LINK: if (p.isReferenceDefined()) { if (p.referencedValue.isParameter()) { - // recursive call - valuePreview = NgParameter.preview(p.referencedValue.element as ParamDefinition); + const targetParam = (p.referencedValue.element as ParamDefinition); + // calculated param ? + if (targetParam.valueMode === ParamValueMode.CALCUL) { + // was the result already computed ? + if (p.referencedValue.nub.result) { + if (p.referencedValue.hasMultipleValues()) { + // like LIST mode + valuePreview = i18n.localizeText("INFO_PARAMFIELD_PARAMVARIER_VALUES"); + valuePreview += " " + p.referencedValue.nub.result.getCalculatedValues().slice(0, 5).join("; ") + "…"; + } else { + valuePreview = String(p.referencedValue.nub.result.vCalc); + } + } else { + valuePreview = i18n.localizeText("INFO_PARAMFIELD_IN_CALCULATION"); + } + } else { + // recursive call + valuePreview = NgParameter.preview(targetParam); + } } else { - // @TODO what if the result was already computed ? - // Is the computed value fresh or stale ? - valuePreview = ServiceFactory.instance.i18nService.localizeText("INFO_PARAMFIELD_IN_CALCULATION"); + // was the result already computed ? + try { + const remoteValues = p.referencedValue.getParamValues(); + // @TODO is the computed value fresh or stale ? + if (p.referencedValue.hasMultipleValues()) { + // like LIST mode + valuePreview = i18n.localizeText("INFO_PARAMFIELD_PARAMVARIER_VALUES"); + valuePreview += " " + remoteValues.valueList.slice(0, 5).join("; ") + "…"; + } else { + // like SINGLE mode + valuePreview = String(remoteValues.currentValue); + } + } catch (e) { + valuePreview = i18n.localizeText("INFO_PARAMFIELD_IN_CALCULATION"); + } } } } -- GitLab From 82a6d8111c48a4baa5d0fbe3882b7595bb58ba41 Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Wed, 20 Mar 2019 11:40:51 +0100 Subject: [PATCH 10/39] Fix #172 --- .../param-field-line.component.ts | 1 + .../definition/form-def-fixedvar.ts | 8 ----- src/app/formulaire/ngparam.ts | 29 ++++++++++++------- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/app/components/param-field-line/param-field-line.component.ts b/src/app/components/param-field-line/param-field-line.component.ts index ed9bb5063..e147f1f9f 100644 --- a/src/app/components/param-field-line/param-field-line.component.ts +++ b/src/app/components/param-field-line/param-field-line.component.ts @@ -220,6 +220,7 @@ export class ParamFieldLineComponent implements OnChanges { case "fix": this.param.valueMode = ParamValueMode.SINGLE; // reset the value to avoid "undefined" after exiting CALC or LINK mode + // @TODO not always necessary; find out why this.param.setValue(this, this.param.paramDefinition.paramValues.singleValue); break; diff --git a/src/app/formulaire/definition/form-def-fixedvar.ts b/src/app/formulaire/definition/form-def-fixedvar.ts index 4474e9a7c..469bda41b 100644 --- a/src/app/formulaire/definition/form-def-fixedvar.ts +++ b/src/app/formulaire/definition/form-def-fixedvar.ts @@ -155,14 +155,6 @@ export class FormDefFixedVar { } } - private logParams() { - for (const fe of this._formBase.allFormElements) { - if (fe instanceof NgParameter) { - console.log(`${fe.paramDefinition.symbol} : ${ParamValueMode[fe.paramDefinition.valueMode]}`); - } - } - } - /** * gestion des événements clic sur les radios */ diff --git a/src/app/formulaire/ngparam.ts b/src/app/formulaire/ngparam.ts index de3ce46dc..ffc0b9183 100644 --- a/src/app/formulaire/ngparam.ts +++ b/src/app/formulaire/ngparam.ts @@ -56,13 +56,13 @@ export class NgParameter extends InputField implements Observer { public static preview(p: ParamDefinition): string { let valuePreview: string; const i18n = ServiceFactory.instance.i18nService; + const nDigits = ServiceFactory.instance.applicationSetupService.displayDigits; // console.log("NgParam::preview()", p.symbol, ParamValueMode[p.valueMode], p); switch (p.valueMode) { case ParamValueMode.SINGLE: - valuePreview = String(p.getValue()); + valuePreview = String(p.getValue().toFixed(nDigits)); break; case ParamValueMode.MINMAX: - const nDigits = ServiceFactory.instance.applicationSetupService.displayDigits; let min: any = p.paramValues.min; let max: any = p.paramValues.max; let step: any = p.paramValues.step; @@ -81,13 +81,15 @@ export class NgParameter extends InputField implements Observer { case ParamValueMode.LISTE: valuePreview = i18n.localizeText("INFO_PARAMFIELD_PARAMVARIER_VALUES"); const vals = p.paramValues.valueList || []; - valuePreview += " " + vals.slice(0, 5).join("; ") + "…"; + valuePreview += " " + vals.slice(0, 5).map((v) => { + return v.toFixed(nDigits); + }).join("; ") + "…"; break; case ParamValueMode.CALCUL: valuePreview = i18n.localizeText("INFO_PARAMFIELD_IN_CALCULATION"); if (p.calculability === ParamCalculability.DICHO) { valuePreview += " (" + i18n.localizeText("INFO_PARAMFIELD_IN_CALCULATION_INITIAL_VALUE") - + ": " + p.getValue() + ")"; + + ": " + p.getValue().toFixed(nDigits) + ")"; } break; case ParamValueMode.LINK: @@ -101,9 +103,11 @@ export class NgParameter extends InputField implements Observer { if (p.referencedValue.hasMultipleValues()) { // like LIST mode valuePreview = i18n.localizeText("INFO_PARAMFIELD_PARAMVARIER_VALUES"); - valuePreview += " " + p.referencedValue.nub.result.getCalculatedValues().slice(0, 5).join("; ") + "…"; + valuePreview += " " + p.referencedValue.nub.result.getCalculatedValues().map((v) => { + return v.toFixed(nDigits); + }).slice(0, 5).join("; ") + "…"; } else { - valuePreview = String(p.referencedValue.nub.result.vCalc); + valuePreview = String(p.referencedValue.nub.result.vCalc.toFixed(nDigits)); } } else { valuePreview = i18n.localizeText("INFO_PARAMFIELD_IN_CALCULATION"); @@ -120,10 +124,12 @@ export class NgParameter extends InputField implements Observer { if (p.referencedValue.hasMultipleValues()) { // like LIST mode valuePreview = i18n.localizeText("INFO_PARAMFIELD_PARAMVARIER_VALUES"); - valuePreview += " " + remoteValues.valueList.slice(0, 5).join("; ") + "…"; + valuePreview += " " + remoteValues.valueList.slice(0, 5).map((v) => { + return v.toFixed(nDigits); + }).join("; ") + "…"; } else { // like SINGLE mode - valuePreview = String(remoteValues.currentValue); + valuePreview = String(remoteValues.currentValue.toFixed(nDigits)); } } catch (e) { valuePreview = i18n.localizeText("INFO_PARAMFIELD_IN_CALCULATION"); @@ -183,16 +189,19 @@ export class NgParameter extends InputField implements Observer { return this._paramDef.valueMode; } - // @TODO vérifier : ça a une tête à faire 40x trop d'opérations pour rien + /** + * Unlinks the parameter and updates its value when value mode changes + */ public set valueMode(m: ParamValueMode) { // undefined si on clique en dehors du select après l'avoir ouvert (cad sans avoir fait de sélection) // et au même niveau, cad à côté du bouton et non à côté du menu déroulant if (m !== undefined && this._paramDef.valueMode !== m) { + const nDigits = ServiceFactory.instance.applicationSetupService.displayDigits; this.unlinkParameter(); this._paramDef.valueMode = m; this.notifyObservers({ "action": "valueModeChange", - "value": this._paramDef.getValue() + "value": Number(this._paramDef.getValue().toFixed(nDigits)) }); } } -- GitLab From 33a5a24de86e2cff824ea0873af41d622ecaf1aa Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Wed, 20 Mar 2019 13:59:19 +0100 Subject: [PATCH 11/39] =?UTF-8?q?Invalidation=20des=20r=C3=A9sultats=20?= =?UTF-8?q?=C3=A0=20l'aval=20:=20r=C3=A9percussion=20sur=20le=20mod=C3=A8l?= =?UTF-8?q?e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/formulaire/definition/concrete/form-base.ts | 4 +++- src/app/services/formulaire/formulaire.service.ts | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/app/formulaire/definition/concrete/form-base.ts b/src/app/formulaire/definition/concrete/form-base.ts index 9d7e4b120..27ee0ab3f 100644 --- a/src/app/formulaire/definition/concrete/form-base.ts +++ b/src/app/formulaire/definition/concrete/form-base.ts @@ -36,7 +36,9 @@ export class FormulaireBase extends FormulaireDefinition { public resetResults() { this._formResult.resetResults(); - // reset the results of all forms depending on this one + // reset model results + this.currentNub.resetResult(); + // reset the result panels of all forms depending on this one ServiceFactory.instance.formulaireService.resetAllDependingFormsResults(this); } diff --git a/src/app/services/formulaire/formulaire.service.ts b/src/app/services/formulaire/formulaire.service.ts index d8db5e661..1c4bfc87b 100644 --- a/src/app/services/formulaire/formulaire.service.ts +++ b/src/app/services/formulaire/formulaire.service.ts @@ -403,7 +403,10 @@ export class FormulaireService extends Observable { "action": "closeForm", "form": form }); - // reset the results of all forms depending on this one + + // reset model results + form.currentNub.resetResult(); + // reset the result panels of all forms depending on this one this.resetAllDependingFormsResults(form); } if (nub) { -- GitLab From 209b9cbc56bdf9555e5255f8cf38106e0aa65ebf Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Wed, 20 Mar 2019 15:06:12 +0100 Subject: [PATCH 12/39] Onglets: correction CSS pour Chrome --- src/app/app.component.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/app.component.scss b/src/app/app.component.scss index c45d95ed1..98e0c6c01 100644 --- a/src/app/app.component.scss +++ b/src/app/app.component.scss @@ -115,7 +115,7 @@ button:focus { border-bottom: none; } .calculator-button.mat-raised-button { - height: calc(#{$navbar_height} - 3px); + height: calc(#{$navbar_height} - 5px); &:not([class*="mat-elevation-z"]) { box-shadow: -1px -2px 2px 0 rgba(0,0,0,.4),1px -2px 5px 0 rgba(0,0,0,.1); -- GitLab From 5996ec78082bbcf73c1e3fc564868b983c975941 Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Thu, 21 Mar 2019 10:21:20 +0100 Subject: [PATCH 13/39] Fix #167 --- src/app/app.module.ts | 2 + .../dialog-load-session.component.html | 17 ++++- .../dialog-load-session.component.scss | 21 ++++++ .../dialog-load-session.component.ts | 74 +++++++++++++++++++ .../services/formulaire/formulaire.service.ts | 28 +++++-- src/locale/messages.en.json | 2 + src/locale/messages.fr.json | 2 + 7 files changed, 138 insertions(+), 8 deletions(-) diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 2759ef9f5..a1f172ab0 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -19,6 +19,7 @@ import { MatCardModule, MatTableModule, MatSnackBarModule, + MatBadgeModule, ErrorStateMatcher, MatButtonToggleModule } from "@angular/material"; @@ -104,6 +105,7 @@ const appRoutes: Routes = [ ChartModule, HttpClientModule, FlexLayoutModule, + MatBadgeModule, MatButtonModule, MatButtonToggleModule, MatCardModule, diff --git a/src/app/components/dialog-load-session/dialog-load-session.component.html b/src/app/components/dialog-load-session/dialog-load-session.component.html index 0473b4cde..97e2d6e42 100644 --- a/src/app/components/dialog-load-session/dialog-load-session.component.html +++ b/src/app/components/dialog-load-session/dialog-load-session.component.html @@ -13,7 +13,8 @@ </mat-form-field> <div class="cb-container"> - <mat-checkbox [name]="c.uid" *ngFor="let c of calculators" [(ngModel)]="c.selected" [ngModelOptions]="{standalone: true}"> + <mat-checkbox [name]="c.uid" *ngFor="let c of calculators" (change)="checkLinkedParamsDependencies()" + [(ngModel)]="c.selected" [ngModelOptions]="{standalone: true}"> {{ c.title }} </mat-checkbox> </div> @@ -26,6 +27,20 @@ {{ uitextNone }} </button> </div> + + <div class="dependencies-problems" *ngIf="dependenciesProblems.length > 0"> + <mat-list role="list"> + <mat-list-item role="listitem" *ngFor="let dp of dependenciesProblems"> + <mat-icon color="warn">error_outline</mat-icon> {{ dp.message }} + </mat-list-item> + </mat-list> + <p> + <button mat-raised-button (click)="fixDependencies()" + [matBadge]="dependenciesProblems.length" matBadgeColor="warn"> + {{ uitextFixMissingDependencies }} + </button> + </p> + </div> </div> <div mat-dialog-actions> diff --git a/src/app/components/dialog-load-session/dialog-load-session.component.scss b/src/app/components/dialog-load-session/dialog-load-session.component.scss index e612ad2cf..f9cad2765 100644 --- a/src/app/components/dialog-load-session/dialog-load-session.component.scss +++ b/src/app/components/dialog-load-session/dialog-load-session.component.scss @@ -17,3 +17,24 @@ mat-form-field { margin-right: 5px; } } + +.dependencies-problems { + + .mat-list-base { + padding-top: 0; + + .mat-list-item { + height: 32px; + font-size: .9em; + + ::ng-deep .mat-list-item-content { + padding-left: 0; + + mat-icon { + transform: scale(0.8); + margin-right: 5px; + } + } + } + } +} diff --git a/src/app/components/dialog-load-session/dialog-load-session.component.ts b/src/app/components/dialog-load-session/dialog-load-session.component.ts index 3aa55c836..b4bb4c836 100644 --- a/src/app/components/dialog-load-session/dialog-load-session.component.ts +++ b/src/app/components/dialog-load-session/dialog-load-session.component.ts @@ -17,6 +17,8 @@ export class DialogLoadSessionComponent { public loadSessionForm: FormGroup; + public dependenciesProblems: any[] = []; + constructor( public dialogRef: MatDialogRef<DialogLoadSessionComponent>, private intlService: I18nService, @@ -40,6 +42,74 @@ export class DialogLoadSessionComponent { } } + public checkLinkedParamsDependencies() { + this.dependenciesProblems = []; + // for all checked Nubs + this.calculators.forEach((c) => { + if (c.selected) { + // do all required nubs are checked ? + c.requires.forEach((r) => { + if (! this.isCalculatorOrParentSelected(r)) { + const realUid = this.getUidOrParentUid(r); + const depTitle = this.getTitleFromUid(realUid); + this.dependenciesProblems.push({ + requiring: c.title, + required: depTitle, + requiredUid: realUid, + message: c.title + " " + this.intlService.localizeText("INFO_REQUIRES") + " " + depTitle + }); + } + }); + } + }); + } + + public fixDependencies() { + for (const dp of this.dependenciesProblems) { + this.selectRequiredModule(dp.requiredUid); + } + } + + private isCalculatorOrParentSelected(uid: string): boolean { + let isSelected = false; + this.calculators.forEach((c) => { + if (c.uid === uid || c.children.includes(uid)) { + isSelected = c.selected; + } + }); + return isSelected; + } + + private getUidOrParentUid(uid: string): string { + let realUid: string; + this.calculators.forEach((c) => { + if (c.uid === uid || c.children.includes(uid)) { + realUid = c.uid; + } + }); + return realUid; + } + + private getTitleFromUid(uid: string): string { + let title: string; + this.calculators.forEach((c) => { + if (c.uid === uid) { + title = c.title; + } + }); + return title; + } + + private selectRequiredModule(uid: string) { + this.calculators.forEach((c) => { + if (c.uid === uid) { + c.selected = true; + } + }); + // re-run dependency checking + this.checkLinkedParamsDependencies(); + } + public onFileSelected(event: any) { if (event.target.files && event.target.files.length) { this.file = event.target.files[0]; @@ -94,4 +164,8 @@ export class DialogLoadSessionComponent { public get uitextLoadSessionTitle() { return this.intlService.localizeText("INFO_DIALOG_LOAD_SESSION_TITLE"); } + + public get uitextFixMissingDependencies() { + return this.intlService.localizeText("INFO_DIALOG_FIX_MISSING_DEPENDENCIES"); + } } diff --git a/src/app/services/formulaire/formulaire.service.ts b/src/app/services/formulaire/formulaire.service.ts index 1c4bfc87b..7a34e00ae 100644 --- a/src/app/services/formulaire/formulaire.service.ts +++ b/src/app/services/formulaire/formulaire.service.ts @@ -451,16 +451,13 @@ export class FormulaireService extends Observable { private readSingleFile(file: File): Promise<any> { return new Promise<any>((resolve, reject) => { const fr = new FileReader(); - fr.onload = () => { resolve(fr.result); }; - fr.onerror = () => { fr.abort(); reject(new Error(`Erreur de lecture du fichier ${file.name}`)); }; - fr.readAsText(file); }); } @@ -507,10 +504,27 @@ export class FormulaireService extends Observable { // liste des noms de modules de calcul if (data.session && Array.isArray(data.session)) { data.session.forEach((e: any) => { - res.push({ - uid: e.uid, - title: e.meta && e.meta.title ? e.meta.title : undefined - }); + const nubInfo = { + uid: e.uid, + title: e.meta && e.meta.title ? e.meta.title : undefined, + requires: [], + children: [] + }; + // list linked params dependencies for each Nub + if (e.parameters) { + e.parameters.forEach((p) => { + if (p.targetNub && ! nubInfo.requires.includes(p.targetNub)) { + nubInfo.requires.push(p.targetNub); + } + }); + } + // list children nubs for each Nub + if (e.structures) { + e.structures.forEach((p) => { + nubInfo.children.push(p.uid); + }); + } + res.push(nubInfo); }); } return res; diff --git a/src/locale/messages.en.json b/src/locale/messages.en.json index 506bda9e7..d265692b8 100644 --- a/src/locale/messages.en.json +++ b/src/locale/messages.en.json @@ -62,6 +62,7 @@ "INFO_EXTRARES_ENUM_STRUCTUREFLOWREGIME_2": "Submerged", "INFO_EXTRARES_ENUM_STRUCTUREFLOWREGIME_3": "Zero flow", "INFO_DIALOG_COMPUTED_VALUE_TITLE": "Edit initial value", + "INFO_DIALOG_FIX_MISSING_DEPENDENCIES": "Fix missing dependencies", "INFO_DIALOG_LOAD_SESSION_FILENAME": "Choose a file", "INFO_DIALOG_LOAD_SESSION_TITLE": "Load calculator modules", "INFO_DIALOG_SAVE_SESSION_FILENAME": "File name", @@ -196,6 +197,7 @@ "INFO_REMOUS_LARGEUR_BERGE": "Width at embankment level = %B% m", "INFO_REMOUS_RESSAUT_DEHORS": "Hydraulic jump detected %sens% abscissa %x% m", "INFO_REMOUS_RESSAUT_HYDRO": "Hydraulic jump detected between abscissa %xmin% and %xmax% m", + "INFO_REQUIRES": "requires", "INFO_SECTIONPARAMETREE_TITRE": "Parametric section", "INFO_SECTIONPARAMETREE_TITRE_COURT": "Param. section", "INFO_SETUP_NEWTON_MAX_ITER": "Newton iteration limit", diff --git a/src/locale/messages.fr.json b/src/locale/messages.fr.json index 90b8466f0..5c40ca5d0 100644 --- a/src/locale/messages.fr.json +++ b/src/locale/messages.fr.json @@ -62,6 +62,7 @@ "INFO_EXTRARES_ENUM_STRUCTUREFLOWREGIME_2": "Noyé", "INFO_EXTRARES_ENUM_STRUCTUREFLOWREGIME_3": "Débit nul", "INFO_DIALOG_COMPUTED_VALUE_TITLE": "Modifier la valeur initiale", + "INFO_DIALOG_FIX_MISSING_DEPENDENCIES": "Résoudre les dépendances", "INFO_DIALOG_LOAD_SESSION_FILENAME": "Choisir un fichier", "INFO_DIALOG_LOAD_SESSION_TITLE": "Charger des modules de calcul", "INFO_DIALOG_SAVE_SESSION_FILENAME": "Nom de fichier", @@ -196,6 +197,7 @@ "INFO_REMOUS_LARGEUR_BERGE": "Largeur au niveau des berges = %B% m", "INFO_REMOUS_RESSAUT_DEHORS": "Ressaut hydraulique détecté à l'%sens% de l'abscisse %x% m", "INFO_REMOUS_RESSAUT_HYDRO": "Ressaut hydraulique détecté entre les abscisses %xmin% et %xmax% m", + "INFO_REQUIRES": "dépend de", "INFO_SECTIONPARAMETREE_TITRE": "Section paramétrée", "INFO_SECTIONPARAMETREE_TITRE_COURT": "Sec. param.", "INFO_SETUP_NEWTON_MAX_ITER": "Newton : nombre d'itérations maximum", -- GitLab From 0abdc81a3af664b223dc48d4889486c699ca7bc6 Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Thu, 21 Mar 2019 10:22:15 +0100 Subject: [PATCH 14/39] Ajout test e2e chargement de session avec liens complexes --- e2e/calculator.po.ts | 4 + e2e/load-linked-params.e2e-spec.ts | 89 +++++++++ e2e/session-liens-spaghetti.json | 307 +++++++++++++++++++++++++++++ 3 files changed, 400 insertions(+) create mode 100644 e2e/load-linked-params.e2e-spec.ts create mode 100644 e2e/session-liens-spaghetti.json diff --git a/e2e/calculator.po.ts b/e2e/calculator.po.ts index 75d501000..c9276cad4 100644 --- a/e2e/calculator.po.ts +++ b/e2e/calculator.po.ts @@ -29,6 +29,10 @@ export class CalculatorPage { return element(by.css("mat-select#" + id)); } + async getSelectValueText(select: ElementFinder) { + return await select.element(by.css(".mat-select-value-text > span")).getText(); + } + getInputById(id: string) { return element(by.css("input#" + id)); } diff --git a/e2e/load-linked-params.e2e-spec.ts b/e2e/load-linked-params.e2e-spec.ts new file mode 100644 index 000000000..62405f439 --- /dev/null +++ b/e2e/load-linked-params.e2e-spec.ts @@ -0,0 +1,89 @@ +import { AppPage } from "./app.po"; +import { CalculatorPage } from "./calculator.po"; +import { Navbar } from "./navbar.po"; +import { SideNav } from "./sidenav.po"; +import { browser } from "protractor"; + +/** + * Load a session containing 4 calculators, having multiple linked parameters + * from one to another + * @TODO les valeurs des Select sont comparées au français, pas très générique :/ + */ +describe("ngHyd − load session with multiple linked parameters", () => { + let startPage: AppPage; + let calcPage: CalculatorPage; + let navbar: Navbar; + let sidenav: SideNav; + + function init() { + startPage = new AppPage(); + calcPage = new CalculatorPage(); + navbar = new Navbar(); + sidenav = new SideNav(); + } + beforeEach(init); + + it("when loading session-liens-spaghetti.json, all links should point to the right target - ", async () => { + await startPage.navigateTo(); + + await navbar.clickMenuButton(); + await browser.sleep(200); + + await sidenav.clickLoadSessionButton(); + await browser.sleep(200); + + await sidenav.loadSessionFile("./session-liens-spaghetti.json"); + await browser.sleep(200); + + expect(await navbar.getAllCalculatorTabs().count()).toBe(4); + + // 1. check Section paramétrée + await navbar.clickCalculatorTab(0); + + // check target params values + const sp_lb = calcPage.getSelectById("linked_LargeurBerge"); + const sp_lbv = await calcPage.getSelectValueText(sp_lb); + expect(sp_lbv).toEqual("L (Ouvrages, ouvrage 3)"); + + // 2. check Passe à macro-rugosités + await navbar.clickCalculatorTab(1); + + // check target params values + const mr_b = calcPage.getSelectById("linked_B"); + const mr_bv = await calcPage.getSelectValueText(mr_b); + expect(mr_bv).toEqual("L (résultat de Ouvrages, ouvrage 1)"); + + const mr_q = calcPage.getSelectById("linked_Q"); + const mr_qv = await calcPage.getSelectValueText(mr_q); + expect(mr_qv).toEqual("Q (résultat de R. uniforme)"); + + // 3. check Lois d'ouvrages + await navbar.clickCalculatorTab(2); + + // check target params values + const lo_z1 = calcPage.getSelectById("linked_Z1"); + const lo_z1v = await calcPage.getSelectValueText(lo_z1); + expect(lo_z1v).toEqual("ZF2 (Macro-rugo., résultat complémentaire)"); + + const lo_l = calcPage.getSelectById("linked_L"); // attention ID non unique, voir nghyd#173 + const lo_lv = await calcPage.getSelectValueText(lo_l); + expect(lo_lv).toEqual("L (résultat de Ouvrages, ouvrage 1)"); + + const lo_w = calcPage.getSelectById("linked_W"); // attention ID non unique, voir nghyd#173 + const lo_wv = await calcPage.getSelectValueText(lo_w); + expect(lo_wv).toEqual("W (Ouvrages, ouvrage 2)"); + + const lo_cd = calcPage.getSelectById("linked_Cd"); // attention ID non unique, voir nghyd#173 + const lo_cdv = await calcPage.getSelectValueText(lo_cd); + expect(lo_cdv).toEqual("Cd (Ouvrages, ouvrage 1)"); + + // 4. check Régime uniforme + await navbar.clickCalculatorTab(3); + + // check target params values + const lo_y = calcPage.getSelectById("linked_Y"); + const lo_yv = await calcPage.getSelectValueText(lo_y); + expect(lo_yv).toEqual("Yt (Sec. param., résultat complémentaire)"); + }); + +}); diff --git a/e2e/session-liens-spaghetti.json b/e2e/session-liens-spaghetti.json new file mode 100644 index 000000000..4cc7304df --- /dev/null +++ b/e2e/session-liens-spaghetti.json @@ -0,0 +1,307 @@ +{ + "session": [ + { + "uid": "OW9rd3", + "props": { + "varCalc": "Hs", + "calcType": 2, + "nodeType": 2 + }, + "meta": { + "title": "Sec. param." + }, + "parameters": [ + { + "symbol": "Pr", + "mode": "SINGLE", + "value": 0.0001 + }, + { + "symbol": "Ks", + "mode": "SINGLE", + "value": 40 + }, + { + "symbol": "Q", + "mode": "SINGLE", + "value": 1.2 + }, + { + "symbol": "If", + "mode": "SINGLE", + "value": 0.001 + }, + { + "symbol": "YB", + "mode": "SINGLE", + "value": 1 + }, + { + "symbol": "Y", + "mode": "SINGLE", + "value": 0.8 + }, + { + "symbol": "LargeurBerge", + "mode": "LINK", + "targetNub": "dmh4Z3", + "targetParam": "L" + } + ] + }, + { + "uid": "dTB3ZG", + "props": { + "calcType": 11, + "nodeType": 0 + }, + "meta": { + "title": "Macro-rugo." + }, + "parameters": [ + { + "symbol": "Pr", + "mode": "SINGLE", + "value": 0.0001 + }, + { + "symbol": "ZF1", + "mode": "SINGLE", + "value": 12.5 + }, + { + "symbol": "L", + "mode": "SINGLE", + "value": 6 + }, + { + "symbol": "B", + "mode": "LINK", + "targetNub": "cjdyYW", + "targetParam": "L" + }, + { + "symbol": "If", + "mode": "SINGLE", + "value": 0.05 + }, + { + "symbol": "Q", + "mode": "LINK", + "targetNub": "OGhuZj", + "targetParam": "Q" + }, + { + "symbol": "Y", + "mode": "CALCUL" + }, + { + "symbol": "Ks", + "mode": "SINGLE", + "value": 0.01 + }, + { + "symbol": "C", + "mode": "SINGLE", + "value": 0.05 + }, + { + "symbol": "PBD", + "mode": "SINGLE", + "value": 0.5 + }, + { + "symbol": "PBH", + "mode": "SINGLE", + "value": 0.8 + }, + { + "symbol": "Cd0", + "mode": "MINMAX", + "min": 0.75, + "max": 3, + "step": 0.1125 + } + ] + }, + { + "uid": "ZW9icn", + "props": { + "calcType": 8, + "nodeType": 0 + }, + "meta": { + "title": "Ouvrages" + }, + "structures": [ + { + "uid": "cjdyYW", + "props": { + "calcType": 7, + "nodeType": 5, + "structureType": 1, + "loiDebit": 1 + }, + "parameters": [ + { + "symbol": "ZDV", + "mode": "SINGLE", + "value": 100 + }, + { + "symbol": "W", + "mode": "SINGLE", + "value": 0.5 + }, + { + "symbol": "L", + "mode": "CALCUL" + }, + { + "symbol": "Cd", + "mode": "SINGLE", + "value": 0.6 + } + ] + }, + { + "uid": "Ynpnaj", + "props": { + "calcType": 7, + "nodeType": 5, + "structureType": 1, + "loiDebit": 1 + }, + "parameters": [ + { + "symbol": "ZDV", + "mode": "SINGLE", + "value": 100 + }, + { + "symbol": "W", + "mode": "SINGLE", + "value": 0.5 + }, + { + "symbol": "L", + "mode": "LINK", + "targetNub": "cjdyYW", + "targetParam": "L" + }, + { + "symbol": "Cd", + "mode": "SINGLE", + "value": 0.6 + } + ] + }, + { + "uid": "dmh4Z3", + "props": { + "calcType": 7, + "nodeType": 5, + "structureType": 1, + "loiDebit": 1 + }, + "parameters": [ + { + "symbol": "ZDV", + "mode": "SINGLE", + "value": 100 + }, + { + "symbol": "W", + "mode": "LINK", + "targetNub": "Ynpnaj", + "targetParam": "W" + }, + { + "symbol": "L", + "mode": "SINGLE", + "value": 2 + }, + { + "symbol": "Cd", + "mode": "LINK", + "targetNub": "cjdyYW", + "targetParam": "Cd" + } + ] + } + ], + "parameters": [ + { + "symbol": "Pr", + "mode": "SINGLE", + "value": 0.0001 + }, + { + "symbol": "Q", + "mode": "SINGLE", + "value": 0.5 + }, + { + "symbol": "Z1", + "mode": "LINK", + "targetNub": "dTB3ZG", + "targetParam": "ZF2" + }, + { + "symbol": "Z2", + "mode": "SINGLE", + "value": 101.5 + } + ] + }, + { + "uid": "OGhuZj", + "props": { + "calcType": 3, + "nodeType": 2 + }, + "meta": { + "title": "R. uniforme" + }, + "parameters": [ + { + "symbol": "Pr", + "mode": "SINGLE", + "value": 0.0001 + }, + { + "symbol": "Ks", + "mode": "SINGLE", + "value": 40 + }, + { + "symbol": "Q", + "mode": "CALCUL" + }, + { + "symbol": "If", + "mode": "MINMAX", + "min": 0.0005, + "max": 0.002, + "step": 0.00007500000000000001 + }, + { + "symbol": "YB", + "mode": "SINGLE", + "value": 1 + }, + { + "symbol": "Y", + "mode": "LINK", + "targetNub": "OW9rd3", + "targetParam": "Yt" + }, + { + "symbol": "LargeurBerge", + "mode": "SINGLE", + "value": 2.5 + } + ] + } + ] +} \ No newline at end of file -- GitLab From 01a93892cc4a6224fe030f8760782d968a7e4bbd Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Fri, 22 Mar 2019 14:51:55 +0100 Subject: [PATCH 15/39] =?UTF-8?q?Chargement=20de=20session:=20meilleure=20?= =?UTF-8?q?d=C3=A9tection=20des=20d=C3=A9pendances?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dialog-load-session/dialog-load-session.component.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/app/components/dialog-load-session/dialog-load-session.component.ts b/src/app/components/dialog-load-session/dialog-load-session.component.ts index b4bb4c836..b91673e4b 100644 --- a/src/app/components/dialog-load-session/dialog-load-session.component.ts +++ b/src/app/components/dialog-load-session/dialog-load-session.component.ts @@ -34,12 +34,16 @@ export class DialogLoadSessionComponent { for (const c of this.calculators) { c.selected = true; } + // re-run dependency checking + this.checkLinkedParamsDependencies(); } public selectNone() { for (const c of this.calculators) { c.selected = false; } + // re-run dependency checking + this.checkLinkedParamsDependencies(); } public checkLinkedParamsDependencies() { -- GitLab From cf8616f603a787716d937e9358b22314e4f0868a Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Fri, 22 Mar 2019 14:52:41 +0100 Subject: [PATCH 16/39] =?UTF-8?q?=C3=89vite=20une=20boucle=20infinie=20dan?= =?UTF-8?q?s=20la=20r=C3=A9initialisation=20des=20r=C3=A9sultats?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../generic-calculator/calculator.component.ts | 2 +- .../section-results/section-results.component.ts | 1 - src/app/formulaire/definition/concrete/form-base.ts | 10 ++++++++-- src/app/formulaire/definition/form-definition.ts | 4 ++-- src/app/formulaire/ngparam.ts | 2 +- src/app/services/formulaire/formulaire.service.ts | 13 ++++++++----- 6 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/app/components/generic-calculator/calculator.component.ts b/src/app/components/generic-calculator/calculator.component.ts index a0cc4b468..890d21a4a 100644 --- a/src/app/components/generic-calculator/calculator.component.ts +++ b/src/app/components/generic-calculator/calculator.component.ts @@ -362,7 +362,7 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit, * réception d'un événement de changement de valeur d'un input */ private onInputChange() { - this._formulaire.resetResults(); + this._formulaire.resetResults([]); } /** diff --git a/src/app/components/section-results/section-results.component.ts b/src/app/components/section-results/section-results.component.ts index 34248eae2..40eb93801 100644 --- a/src/app/components/section-results/section-results.component.ts +++ b/src/app/components/section-results/section-results.component.ts @@ -6,7 +6,6 @@ import { SectionCanvasComponent } from "../section-canvas/section-canvas.compone import { SectionResults } from "../../results/section-results"; import { ApplicationSetupService } from "../../services/app-setup/app-setup.service"; import { CalculatorResults } from "../../results/calculator-results"; -import { FixedResults } from "../../results/fixed-results"; @Component({ selector: "section-results", diff --git a/src/app/formulaire/definition/concrete/form-base.ts b/src/app/formulaire/definition/concrete/form-base.ts index 27ee0ab3f..edc9f93c2 100644 --- a/src/app/formulaire/definition/concrete/form-base.ts +++ b/src/app/formulaire/definition/concrete/form-base.ts @@ -34,12 +34,18 @@ export class FormulaireBase extends FormulaireDefinition { this._formParamCalc.onRadioClick(info); } - public resetResults() { + /** + * Resets the form results, the results panel on screen, the model + * results, and does the same for all depending modules + */ + public resetResults(visited: string[] = []) { + visited.push(this.currentNub.uid); + // reset GUI results this._formResult.resetResults(); // reset model results this.currentNub.resetResult(); // reset the result panels of all forms depending on this one - ServiceFactory.instance.formulaireService.resetAllDependingFormsResults(this); + ServiceFactory.instance.formulaireService.resetAllDependingFormsResults(this, visited); } public doCompute() { diff --git a/src/app/formulaire/definition/form-definition.ts b/src/app/formulaire/definition/form-definition.ts index fe7e94009..585e1d9a0 100644 --- a/src/app/formulaire/definition/form-definition.ts +++ b/src/app/formulaire/definition/form-definition.ts @@ -356,7 +356,7 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs * effacement des résultats, application des dépendances, ... */ public reset() { - this.resetResults(); + this.resetResults([]); this.applyDependencies(); // prévenir les composants qu'il faut détecter les changements @@ -389,7 +389,7 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs } } - public abstract resetResults(); + public abstract resetResults(visited: string[]); public abstract doCompute(); public abstract get hasResults(): boolean; public abstract get results(): CalculatorResults[]; diff --git a/src/app/formulaire/ngparam.ts b/src/app/formulaire/ngparam.ts index ffc0b9183..809b9d1f7 100644 --- a/src/app/formulaire/ngparam.ts +++ b/src/app/formulaire/ngparam.ts @@ -57,7 +57,7 @@ export class NgParameter extends InputField implements Observer { let valuePreview: string; const i18n = ServiceFactory.instance.i18nService; const nDigits = ServiceFactory.instance.applicationSetupService.displayDigits; - // console.log("NgParam::preview()", p.symbol, ParamValueMode[p.valueMode], p); + switch (p.valueMode) { case ParamValueMode.SINGLE: valuePreview = String(p.getValue().toFixed(nDigits)); diff --git a/src/app/services/formulaire/formulaire.service.ts b/src/app/services/formulaire/formulaire.service.ts index 7a34e00ae..0bbc9aece 100644 --- a/src/app/services/formulaire/formulaire.service.ts +++ b/src/app/services/formulaire/formulaire.service.ts @@ -404,12 +404,13 @@ export class FormulaireService extends Observable { "form": form }); - // reset model results - form.currentNub.resetResult(); // reset the result panels of all forms depending on this one + // @TODO UI should detect model change instead of doing this manually this.resetAllDependingFormsResults(form); } if (nub) { + // reset model results (important, also resets dependent Nubs results in chain) + form.currentNub.resetResult(); Session.getInstance().deleteNub(nub); } } @@ -624,11 +625,13 @@ export class FormulaireService extends Observable { * Resets the results of all forms depending on the given form "f" * @param f */ - public resetAllDependingFormsResults(f: FormulaireDefinition) { + public resetAllDependingFormsResults(f: FormulaireDefinition, visited: string[] = []) { const dependingNubs = Session.getInstance().getDependingNubs(f.currentNub.uid); for (const dn of dependingNubs) { - const form = this.getFormulaireFromNubId(dn.uid); - form.resetResults(); + if (! visited.includes(dn.uid)) { + const form = this.getFormulaireFromNubId(dn.uid); + form.resetResults(visited); + } } } } -- GitLab From 486a60f69f3d7e42d8846e9db6b99fb59e576bb9 Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Fri, 22 Mar 2019 15:57:26 +0100 Subject: [PATCH 17/39] =?UTF-8?q?M=C3=A0J=20fichier=20de=20session=20de=20?= =?UTF-8?q?test=20e2e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- e2e/session-liens-spaghetti.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/session-liens-spaghetti.json b/e2e/session-liens-spaghetti.json index 4cc7304df..bbccd213b 100644 --- a/e2e/session-liens-spaghetti.json +++ b/e2e/session-liens-spaghetti.json @@ -245,7 +245,7 @@ "symbol": "Z1", "mode": "LINK", "targetNub": "dTB3ZG", - "targetParam": "ZF2" + "targetParam": "ZF1" }, { "symbol": "Z2", -- GitLab From 3abba8f11083d6de65938c5456af60d8ba43ede5 Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Fri, 22 Mar 2019 17:12:32 +0100 Subject: [PATCH 18/39] =?UTF-8?q?Nouveau=20service=20de=20notifications=20?= =?UTF-8?q?multiples;=20l'utilisateur=20est=20averti=20lorsque=20des=20r?= =?UTF-8?q?=C3=A9sultats=20sont=20invalid=C3=A9s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/app.module.ts | 2 + .../services/formulaire/formulaire.service.ts | 13 ++++- .../notifications/notifications.service.ts | 49 +++++++++++++++++++ src/locale/messages.en.json | 1 + src/locale/messages.fr.json | 1 + 5 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 src/app/services/notifications/notifications.service.ts diff --git a/src/app/app.module.ts b/src/app/app.module.ts index a1f172ab0..da7f30bba 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -44,6 +44,7 @@ import { FormulaireService } from "./services/formulaire/formulaire.service"; import { I18nService } from "./services/internationalisation/internationalisation.service"; import { HttpService } from "./services/http/http.service"; import { ApplicationSetupService } from "./services/app-setup/app-setup.service"; +import { NotificationsService } from "./services/notifications/notifications.service"; import { AppComponent } from "./app.component"; import { NgParamInputComponent } from "./components/ngparam-input/ngparam-input.component"; @@ -191,6 +192,7 @@ const appRoutes: Routes = [ FormulaireService, HttpService, I18nService, + NotificationsService, { provide: ErrorStateMatcher, useClass: ImmediateErrorStateMatcher diff --git a/src/app/services/formulaire/formulaire.service.ts b/src/app/services/formulaire/formulaire.service.ts index 0bbc9aece..5bd1cf92a 100644 --- a/src/app/services/formulaire/formulaire.service.ts +++ b/src/app/services/formulaire/formulaire.service.ts @@ -22,6 +22,7 @@ import { FormulaireParallelStructure } from "../../formulaire/definition/concret import { NgParameter } from "../../formulaire/ngparam"; import { FieldsetContainer } from "../..//formulaire/fieldset-container"; import { ApplicationSetupService } from "../app-setup/app-setup.service"; +import { NotificationsService } from "../notifications/notifications.service"; @Injectable() export class FormulaireService extends Observable { @@ -36,7 +37,9 @@ export class FormulaireService extends Observable { constructor( private i18nService: I18nService, private appSetupService: ApplicationSetupService, - private httpService: HttpService + private httpService: HttpService, + private intlService: I18nService, + private notificationsService: NotificationsService ) { super(); this._formulaires = []; @@ -630,7 +633,13 @@ export class FormulaireService extends Observable { for (const dn of dependingNubs) { if (! visited.includes(dn.uid)) { const form = this.getFormulaireFromNubId(dn.uid); - form.resetResults(visited); + if (form.hasResults) { + form.resetResults(visited); + this.notificationsService.notify( + this.intlService.localizeText("INFO_SNACKBAR_RESULTS_INVALIDATED") + " " + form.calculatorName, + 2000 + ); + } } } } diff --git a/src/app/services/notifications/notifications.service.ts b/src/app/services/notifications/notifications.service.ts new file mode 100644 index 000000000..9caf0d7ff --- /dev/null +++ b/src/app/services/notifications/notifications.service.ts @@ -0,0 +1,49 @@ +import { Injectable } from "@angular/core"; +import { MatSnackBar } from "@angular/material"; + +/** + * Displays a notifications queue as consecutive snackbars + */ +@Injectable() +export class NotificationsService { + + /** FIFO queue for notifications */ + private notifications: any[]; + + private isOpen: boolean; + + public constructor( + private snackBar: MatSnackBar + ) { + this.notifications = []; + this.isOpen = false; + } + + /** Push a notification and display it as soon as possible */ + public notify(message: string, duration: number, action: string = "OK") { + this.notifications.push({ + message: message, + duration: duration, + action: action + }); + this.show(); + } + + /** Show all messages in the FIFO queue one after another */ + public show() { + if (! this.isOpen) { + // process next notification + if (this.notifications.length > 0) { + const notif = this.notifications.shift(); + this.isOpen = true; + const ref = this.snackBar.open(notif.message, notif.action, { + duration: notif.duration + }); + ref.afterDismissed().subscribe(() => { + this.isOpen = false; + this.show(); + }); + } + } + } +} diff --git a/src/locale/messages.en.json b/src/locale/messages.en.json index d265692b8..859d160ba 100644 --- a/src/locale/messages.en.json +++ b/src/locale/messages.en.json @@ -204,6 +204,7 @@ "INFO_SETUP_PRECISION_AFFICHAGE": "Display accuracy", "INFO_SETUP_PRECISION_CALCUL": "Computation accuracy", "INFO_SETUP_TITLE": "Application setup", + "INFO_SNACKBAR_RESULTS_INVALIDATED": "Results invalidated for", "INFO_SNACKBAR_SETTINGS_SAVED": "Settings saved on this device", "INFO_SNACKBAR_DEFAULT_SETTINGS_RESTORED": "Default settings restored", "INFO_THEME_CREDITS": "Credit", diff --git a/src/locale/messages.fr.json b/src/locale/messages.fr.json index 5c40ca5d0..350dd11ad 100644 --- a/src/locale/messages.fr.json +++ b/src/locale/messages.fr.json @@ -204,6 +204,7 @@ "INFO_SETUP_PRECISION_AFFICHAGE": "Précision d'affichage", "INFO_SETUP_PRECISION_CALCUL": "Précision de calcul", "INFO_SETUP_TITLE": "Paramètres de l'application", + "INFO_SNACKBAR_RESULTS_INVALIDATED": "Résultats invalidés pour", "INFO_SNACKBAR_SETTINGS_SAVED": "Paramètres enregistrés sur cet appareil", "INFO_SNACKBAR_DEFAULT_SETTINGS_RESTORED": "Paramètres par défaut restaurés", "INFO_THEME_CREDITS": "Crédit", -- GitLab From 5f0e2b5c34daa4d19291e70f9d4adee192223dfd Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Fri, 22 Mar 2019 17:24:55 +0100 Subject: [PATCH 19/39] Pas de snackbar lorsqu'on ferme un module --- src/app/services/formulaire/formulaire.service.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/app/services/formulaire/formulaire.service.ts b/src/app/services/formulaire/formulaire.service.ts index 5bd1cf92a..78b0e303c 100644 --- a/src/app/services/formulaire/formulaire.service.ts +++ b/src/app/services/formulaire/formulaire.service.ts @@ -409,7 +409,7 @@ export class FormulaireService extends Observable { // reset the result panels of all forms depending on this one // @TODO UI should detect model change instead of doing this manually - this.resetAllDependingFormsResults(form); + this.resetAllDependingFormsResults(form, [], false); } if (nub) { // reset model results (important, also resets dependent Nubs results in chain) @@ -628,17 +628,19 @@ export class FormulaireService extends Observable { * Resets the results of all forms depending on the given form "f" * @param f */ - public resetAllDependingFormsResults(f: FormulaireDefinition, visited: string[] = []) { + public resetAllDependingFormsResults(f: FormulaireDefinition, visited: string[] = [], notify: boolean = true) { const dependingNubs = Session.getInstance().getDependingNubs(f.currentNub.uid); for (const dn of dependingNubs) { if (! visited.includes(dn.uid)) { const form = this.getFormulaireFromNubId(dn.uid); if (form.hasResults) { form.resetResults(visited); - this.notificationsService.notify( - this.intlService.localizeText("INFO_SNACKBAR_RESULTS_INVALIDATED") + " " + form.calculatorName, - 2000 - ); + if (notify) { + this.notificationsService.notify( + this.intlService.localizeText("INFO_SNACKBAR_RESULTS_INVALIDATED") + " " + form.calculatorName, + 2000 + ); + } } } } -- GitLab From 8d7670751419511eebd354196cfd48ce5bd5a906 Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Fri, 22 Mar 2019 17:41:57 +0100 Subject: [PATCH 20/39] =?UTF-8?q?M=C3=A0J=20test=20e2e=20param=C3=A8tres?= =?UTF-8?q?=20li=C3=A9s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- e2e/load-linked-params.e2e-spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/load-linked-params.e2e-spec.ts b/e2e/load-linked-params.e2e-spec.ts index 62405f439..e77ed5aea 100644 --- a/e2e/load-linked-params.e2e-spec.ts +++ b/e2e/load-linked-params.e2e-spec.ts @@ -63,7 +63,7 @@ describe("ngHyd − load session with multiple linked parameters", () => { // check target params values const lo_z1 = calcPage.getSelectById("linked_Z1"); const lo_z1v = await calcPage.getSelectValueText(lo_z1); - expect(lo_z1v).toEqual("ZF2 (Macro-rugo., résultat complémentaire)"); + expect(lo_z1v).toEqual("ZF1 (Macro-rugo.)"); const lo_l = calcPage.getSelectById("linked_L"); // attention ID non unique, voir nghyd#173 const lo_lv = await calcPage.getSelectValueText(lo_l); -- GitLab From c0e1d3e78f68a61a5b68fdb293dfcd6286b02673 Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Mon, 25 Mar 2019 09:43:04 +0100 Subject: [PATCH 21/39] Fix #134 --- .../formulaire/definition/form-definition.ts | 20 --------- src/app/formulaire/fieldset.ts | 42 ------------------- .../services/formulaire/formulaire.service.ts | 16 ------- 3 files changed, 78 deletions(-) diff --git a/src/app/formulaire/definition/form-definition.ts b/src/app/formulaire/definition/form-definition.ts index 585e1d9a0..e34b286f2 100644 --- a/src/app/formulaire/definition/form-definition.ts +++ b/src/app/formulaire/definition/form-definition.ts @@ -476,26 +476,6 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs return undefined; } - /** - * @param json conf du formulaire - * @param uidMap table de correspondance uid dans le fichier de conf <-> uid en mémoire - */ - public updateParamsLinks(json: {}, uidMap: {}[]) { - for (const ks in json) { - switch (ks) { - case "elements": - let n = 0; - for (const e of json[ks]) { - if (Object.keys(e)[0] === "fieldset") { - this.getNthFieldset(n).updateParamsLinks(e["fieldset"], uidMap); - n++; - } - } - break; - } - } - } - // interface Observer public update(sender: any, data: any) { diff --git a/src/app/formulaire/fieldset.ts b/src/app/formulaire/fieldset.ts index 9c001b21d..06106cf6f 100644 --- a/src/app/formulaire/fieldset.ts +++ b/src/app/formulaire/fieldset.ts @@ -402,46 +402,4 @@ export class FieldSet extends FormulaireElement implements Observer { } } } - - /** - * MAJ des liens entre paramètres lors de la désérialisation - * @param json conf du fieldset issue du fichier - * @param uidMap table de correspondance uid dans le fichier de conf <-> uid en mémoire - */ - public updateParamsLinks(json: {}, uidMap: {}[]) { - for (const ks in json) { - switch (ks) { - case "elements": - for (const e of json[ks]) { - if (Object.keys(e)[0] === "param") { - const prm = e["param"]; - if (prm["values"]["mode"] === "LINK") { - // id du formulaire cible dans le fichier - const oldFormUid = +prm["values"]["form_uid"]; - - // correspondance avec l'objet mémoire - let newFormUid: string; - for (const m of uidMap) { - if (m["type"] === "form" && m["old"] === oldFormUid) { - newFormUid = m["new"]; - break; - } - } - - // formulaire dont le Nub est la cible du lien - const destForm: FormulaireDefinition - = ServiceFactory.instance.formulaireService.getFormulaireFromId(newFormUid); - - // paramètre source (celui qui est lié à une valeur) - const src: NgParameter = this.getFormulaireNodeById(prm["id"]) as NgParameter; - - // création du lien - src.paramDefinition.defineReference(destForm.currentNub, prm["values"]["ref"]); - } - break; - } - } - } - } - } } diff --git a/src/app/services/formulaire/formulaire.service.ts b/src/app/services/formulaire/formulaire.service.ts index 78b0e303c..49533c522 100644 --- a/src/app/services/formulaire/formulaire.service.ts +++ b/src/app/services/formulaire/formulaire.service.ts @@ -542,22 +542,6 @@ export class FormulaireService extends Observable { }); } - /** - * met à jour les liens d'un formulaire - * @TODO rewrite - * @param json conf du formulaire - * @param formInfos métadonnées sur les formulaires chargés - * @param form formulaire dont on met à jour les liens - * @param uidMap table de correspondance uid dans le fichier de conf <-> uid en mémoire - */ - private updateFormLinks(json: {}, formInfos: any[], form: FormulaireDefinition, uidMap: {}[]) { - for (const i of formInfos) { - if (i["uid"] === json["uid"] && i["selected"]) { - form.updateParamsLinks(json, uidMap); - } - } - } - /** * Demande à la Session JalHYd la liste des paramètres/résultats pouvant être liés au * paramètre fourni -- GitLab From 3841aeeacda02f9c83217dab0d5d3e155b060836 Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Mon, 25 Mar 2019 10:49:21 +0100 Subject: [PATCH 22/39] =?UTF-8?q?Ajout=20test=20e2e=20pour=20calcul=20en?= =?UTF-8?q?=20cha=C3=AEne?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- e2e/compute-reset-chained-links.e2e-spec.ts | 160 +++++++++ e2e/load-linked-params.e2e-spec.ts | 4 +- e2e/navbar.po.ts | 9 + e2e/session-6-calc.test.json | 343 +++++++++++++++++++- e2e/session-cascade-params.json | 146 +++++++++ e2e/session-cascade-results.json | 191 +++++++++++ e2e/session-optional-params.test.json | 58 +++- src/app/app.component.html | 6 +- 8 files changed, 910 insertions(+), 7 deletions(-) create mode 100644 e2e/compute-reset-chained-links.e2e-spec.ts create mode 100644 e2e/session-cascade-params.json create mode 100644 e2e/session-cascade-results.json diff --git a/e2e/compute-reset-chained-links.e2e-spec.ts b/e2e/compute-reset-chained-links.e2e-spec.ts new file mode 100644 index 000000000..17a716766 --- /dev/null +++ b/e2e/compute-reset-chained-links.e2e-spec.ts @@ -0,0 +1,160 @@ +import { AppPage } from "./app.po"; +import { CalculatorPage } from "./calculator.po"; +import { Navbar } from "./navbar.po"; +import { SideNav } from "./sidenav.po"; +import { browser } from "protractor"; + +/** + * Load a session containing 3 calculators, having linked parameters + * from one to another, triggers computation from the top-most, triggers + * results reset from the bottom-most. + * Does it once with parameters linked to parameters, once with parameters + * linked to results. + */ +describe("ngHyd − compute then reset chained results", () => { + let startPage: AppPage; + let calcPage: CalculatorPage; + let navbar: Navbar; + let sidenav: SideNav; + + function init() { + startPage = new AppPage(); + calcPage = new CalculatorPage(); + navbar = new Navbar(); + sidenav = new SideNav(); + } + beforeEach(init); + + async function doTheJob(filename: string, topMostId: string, bottomMostId: string) { + // load session file + await startPage.navigateTo(); + await navbar.clickMenuButton(); + await browser.sleep(200); + await sidenav.clickLoadSessionButton(); + await browser.sleep(200); + await sidenav.loadSessionFile(filename); + await browser.sleep(500); + expect(await navbar.getAllCalculatorTabs().count()).toBe(3); + + // 1. get top most module + await navbar.clickCalculatorTabForUid(topMostId); + + // check that "compute" button is active + const calcButton = calcPage.getCalculateButton(); + const disabledState = await calcButton.getAttribute("disabled"); + expect(disabledState).not.toBe("disabled"); + // click "compute" button + await calcButton.click(); + + // check all 3 modules for results + for (let i = 0; i < 3; i++) { + await navbar.clickCalculatorTab(i); + const hasResults = await calcPage.hasResults(); + expect(hasResults).toBe(true); + } + + // 2. get bottom-most module + await navbar.clickCalculatorTabForUid(bottomMostId); + + // modify any input (for ex. "Ks") + await calcPage.getInputById("Ks").clear(); + await calcPage.getInputById("Ks").sendKeys("42"); + + // check all 3 modules for absence of results + for (let i = 0; i < 3; i++) { + await navbar.clickCalculatorTab(i); + const hasResults = await calcPage.hasResults(); + expect(hasResults).toBe(false); + } + } + + it("when loading session-cascade-params.json, computation should not be chained, but results reset should", async () => { + // load session file + await startPage.navigateTo(); + await navbar.clickMenuButton(); + await browser.sleep(200); + await sidenav.clickLoadSessionButton(); + await browser.sleep(200); + await sidenav.loadSessionFile("./session-cascade-params.json"); + await browser.sleep(500); + expect(await navbar.getAllCalculatorTabs().count()).toBe(3); + + // 1. get top most module + await navbar.clickCalculatorTabForUid("dWs5bm"); + + // check that "compute" button is active + const calcButton = calcPage.getCalculateButton(); + const disabledState = await calcButton.getAttribute("disabled"); + expect(disabledState).not.toBe("disabled"); + // click "compute" button + await calcButton.click(); + + // only top-most module should have results + let hasResults = await calcPage.hasResults(); + // other two should not + await navbar.clickCalculatorTabForUid("OGFzOH"); + hasResults = await calcPage.hasResults(); + expect(hasResults).toBe(false); + await navbar.clickCalculatorTabForUid("NWp1a3"); + hasResults = await calcPage.hasResults(); + expect(hasResults).toBe(false); + + // 2. get bottom-most module + await navbar.clickCalculatorTabForUid("OGFzOH"); + + // modify any input (for ex. "Ks") + await calcPage.getInputById("Ks").clear(); + await calcPage.getInputById("Ks").sendKeys("42"); + + // check all 3 modules for absence of results + for (let i = 0; i < 3; i++) { + await navbar.clickCalculatorTab(i); + hasResults = await calcPage.hasResults(); + expect(hasResults).toBe(false); + } + }); + + it("when loading session-cascade-results.json, computation and results reset should be chained", async () => { + // load session file + await startPage.navigateTo(); + await navbar.clickMenuButton(); + await browser.sleep(200); + await sidenav.clickLoadSessionButton(); + await browser.sleep(200); + await sidenav.loadSessionFile("./session-cascade-results.json"); + await browser.sleep(500); + expect(await navbar.getAllCalculatorTabs().count()).toBe(3); + + // 1. get top most module + await navbar.clickCalculatorTabForUid("YWFqMD"); + + // check that "compute" button is active + const calcButton = calcPage.getCalculateButton(); + const disabledState = await calcButton.getAttribute("disabled"); + expect(disabledState).not.toBe("disabled"); + // click "compute" button + await calcButton.click(); + + // check all 3 modules for results + for (let i = 0; i < 3; i++) { + await navbar.clickCalculatorTab(i); + const hasResults = await calcPage.hasResults(); + expect(hasResults).toBe(true); + } + + // 2. get bottom-most module + await navbar.clickCalculatorTabForUid("ZHd0ej"); + + // modify any input (for ex. "Ks") + await calcPage.getInputById("Ks").clear(); + await calcPage.getInputById("Ks").sendKeys("42"); + + // check all 3 modules for absence of results + for (let i = 0; i < 3; i++) { + await navbar.clickCalculatorTab(i); + const hasResults = await calcPage.hasResults(); + expect(hasResults).toBe(false); + } + }); + +}); diff --git a/e2e/load-linked-params.e2e-spec.ts b/e2e/load-linked-params.e2e-spec.ts index e77ed5aea..cd0b97a4c 100644 --- a/e2e/load-linked-params.e2e-spec.ts +++ b/e2e/load-linked-params.e2e-spec.ts @@ -23,7 +23,7 @@ describe("ngHyd − load session with multiple linked parameters", () => { } beforeEach(init); - it("when loading session-liens-spaghetti.json, all links should point to the right target - ", async () => { + it("when loading session-liens-spaghetti.json, all links should point to the right target", async () => { await startPage.navigateTo(); await navbar.clickMenuButton(); @@ -33,7 +33,7 @@ describe("ngHyd − load session with multiple linked parameters", () => { await browser.sleep(200); await sidenav.loadSessionFile("./session-liens-spaghetti.json"); - await browser.sleep(200); + await browser.sleep(500); expect(await navbar.getAllCalculatorTabs().count()).toBe(4); diff --git a/e2e/navbar.po.ts b/e2e/navbar.po.ts index 2112ceecf..621416ac9 100644 --- a/e2e/navbar.po.ts +++ b/e2e/navbar.po.ts @@ -5,6 +5,10 @@ export class Navbar { return element.all(by.css("#tabs-container > button.calculator-button")); } + getCalculatorTabForUid(uid: string) { + return element(by.css("#tabs-container > button.calculator-button.calculator-uid-" + uid)); + } + getNewCalculatorButton() { return element(by.css("#new-calculator")); } @@ -18,6 +22,11 @@ export class Navbar { await tabs.get(n).click(); } + async clickCalculatorTabForUid(uid: string) { + const tab = this.getCalculatorTabForUid(uid); + await tab.click(); + } + async clickRandomCalculatorTab(n: number) { const tabs = this.getAllCalculatorTabs(); const l = await tabs.count(); diff --git a/e2e/session-6-calc.test.json b/e2e/session-6-calc.test.json index 54df75d63..a24a0012f 100644 --- a/e2e/session-6-calc.test.json +++ b/e2e/session-6-calc.test.json @@ -1 +1,342 @@ -{"session":[{"uid":"NHY0cX","props":{"calcType":5,"nodeType":0},"meta":{"title":"PAB : dimensions"},"parameters":[{"symbol":"Pr","mode":"SINGLE","value":0.0001},{"symbol":"L","mode":"SINGLE","value":2},{"symbol":"W","mode":"SINGLE","value":1},{"symbol":"Y","mode":"SINGLE","value":0.5},{"symbol":"V","mode":"CALCUL"}]},{"uid":"YzAwMW","props":{"calcType":11,"nodeType":0},"meta":{"title":"Macro-rugo."},"parameters":[{"symbol":"Pr","mode":"SINGLE","value":0.0001},{"symbol":"ZF1","mode":"SINGLE","value":12.5},{"symbol":"L","mode":"SINGLE","value":6},{"symbol":"B","mode":"SINGLE","value":1},{"symbol":"If","mode":"SINGLE","value":0.05},{"symbol":"Q","mode":"CALCUL"},{"symbol":"Y","mode":"SINGLE","value":0.6},{"symbol":"Ks","mode":"SINGLE","value":0.01},{"symbol":"C","mode":"SINGLE","value":0.05},{"symbol":"PBD","mode":"SINGLE","value":0.5},{"symbol":"PBH","mode":"SINGLE","value":0.8},{"symbol":"Cd0","mode":"SINGLE","value":1.5}]},{"uid":"dGc5MD","props":{"calcType":8,"nodeType":0},"meta":{"title":"Ouvrages"},"structures":[{"uid":"NjZob3","props":{"calcType":7,"nodeType":5,"structureType":1,"loiDebit":1},"parameters":[{"symbol":"ZDV","mode":"SINGLE","value":100},{"symbol":"W","mode":"SINGLE","value":0.5},{"symbol":"L","mode":"SINGLE","value":2},{"symbol":"Cd","mode":"SINGLE","value":0.6}]}],"parameters":[{"symbol":"Pr","mode":"SINGLE","value":0.0001},{"symbol":"Q","mode":"CALCUL"},{"symbol":"Z1","mode":"SINGLE","value":102},{"symbol":"Z2","mode":"SINGLE","value":101.5}]},{"uid":"OGZ4cm","props":{"varCalc":"Hs","calcType":2,"nodeType":2},"meta":{"title":"Sec. param."},"parameters":[{"symbol":"Pr","mode":"SINGLE","value":0.0001},{"symbol":"Ks","mode":"SINGLE","value":40},{"symbol":"Q","mode":"SINGLE","value":1.2},{"symbol":"If","mode":"SINGLE","value":0.001},{"symbol":"YB","mode":"SINGLE","value":1},{"symbol":"Y","mode":"SINGLE","value":0.8},{"symbol":"LargeurBerge","mode":"SINGLE","value":2.5}]},{"uid":"ZTNvMD","props":{"methodeResolution":0,"calcType":4,"nodeType":2},"meta":{"title":"Remous"},"parameters":[{"symbol":"Pr","mode":"SINGLE","value":0.0001},{"symbol":"Yamont","mode":"SINGLE","value":0.15},{"symbol":"Yaval","mode":"SINGLE","value":0.4},{"symbol":"Long","mode":"SINGLE","value":100},{"symbol":"Dx","mode":"SINGLE","value":5},{"symbol":"Ks","mode":"SINGLE","value":40},{"symbol":"Q","mode":"SINGLE","value":1.2},{"symbol":"If","mode":"SINGLE","value":0.001},{"symbol":"YB","mode":"SINGLE","value":1},{"symbol":"Y","mode":"SINGLE","value":0.2863766123093061},{"symbol":"LargeurBerge","mode":"SINGLE","value":2.5}]},{"uid":"eWllan","props":{"calcType":1,"nodeType":0},"meta":{"title":"Lechapt-Calmon"},"parameters":[{"symbol":"Pr","mode":"SINGLE","value":0.0001},{"symbol":"Q","mode":"SINGLE","value":3},{"symbol":"D","mode":"SINGLE","value":1.2},{"symbol":"J","mode":"CALCUL"},{"symbol":"Lg","mode":"SINGLE","value":100},{"symbol":"L","mode":"SINGLE","value":"1.863"},{"symbol":"M","mode":"SINGLE","value":"2"},{"symbol":"N","mode":"SINGLE","value":"5.33"}]}]} \ No newline at end of file +{ + "session": [ + { + "uid": "NHY0cX", + "props": { + "calcType": 5, + "nodeType": 0 + }, + "meta": { + "title": "PAB : dimensions" + }, + "parameters": [ + { + "symbol": "Pr", + "mode": "SINGLE", + "value": 0.0001 + }, + { + "symbol": "L", + "mode": "SINGLE", + "value": 2 + }, + { + "symbol": "W", + "mode": "SINGLE", + "value": 1 + }, + { + "symbol": "Y", + "mode": "SINGLE", + "value": 0.5 + }, + { + "symbol": "V", + "mode": "CALCUL" + } + ] + }, + { + "uid": "YzAwMW", + "props": { + "calcType": 11, + "nodeType": 0 + }, + "meta": { + "title": "Macro-rugo." + }, + "parameters": [ + { + "symbol": "Pr", + "mode": "SINGLE", + "value": 0.0001 + }, + { + "symbol": "ZF1", + "mode": "SINGLE", + "value": 12.5 + }, + { + "symbol": "L", + "mode": "SINGLE", + "value": 6 + }, + { + "symbol": "B", + "mode": "SINGLE", + "value": 1 + }, + { + "symbol": "If", + "mode": "SINGLE", + "value": 0.05 + }, + { + "symbol": "Q", + "mode": "CALCUL" + }, + { + "symbol": "Y", + "mode": "SINGLE", + "value": 0.6 + }, + { + "symbol": "Ks", + "mode": "SINGLE", + "value": 0.01 + }, + { + "symbol": "C", + "mode": "SINGLE", + "value": 0.05 + }, + { + "symbol": "PBD", + "mode": "SINGLE", + "value": 0.5 + }, + { + "symbol": "PBH", + "mode": "SINGLE", + "value": 0.8 + }, + { + "symbol": "Cd0", + "mode": "SINGLE", + "value": 1.5 + } + ] + }, + { + "uid": "dGc5MD", + "props": { + "calcType": 8, + "nodeType": 0 + }, + "meta": { + "title": "Ouvrages" + }, + "structures": [ + { + "uid": "NjZob3", + "props": { + "calcType": 7, + "nodeType": 5, + "structureType": 1, + "loiDebit": 1 + }, + "parameters": [ + { + "symbol": "ZDV", + "mode": "SINGLE", + "value": 100 + }, + { + "symbol": "W", + "mode": "SINGLE", + "value": 0.5 + }, + { + "symbol": "L", + "mode": "SINGLE", + "value": 2 + }, + { + "symbol": "Cd", + "mode": "SINGLE", + "value": 0.6 + } + ] + } + ], + "parameters": [ + { + "symbol": "Pr", + "mode": "SINGLE", + "value": 0.0001 + }, + { + "symbol": "Q", + "mode": "CALCUL" + }, + { + "symbol": "Z1", + "mode": "SINGLE", + "value": 102 + }, + { + "symbol": "Z2", + "mode": "SINGLE", + "value": 101.5 + } + ] + }, + { + "uid": "OGZ4cm", + "props": { + "varCalc": "Hs", + "calcType": 2, + "nodeType": 2 + }, + "meta": { + "title": "Sec. param." + }, + "parameters": [ + { + "symbol": "Pr", + "mode": "SINGLE", + "value": 0.0001 + }, + { + "symbol": "Ks", + "mode": "SINGLE", + "value": 40 + }, + { + "symbol": "Q", + "mode": "SINGLE", + "value": 1.2 + }, + { + "symbol": "If", + "mode": "SINGLE", + "value": 0.001 + }, + { + "symbol": "YB", + "mode": "SINGLE", + "value": 1 + }, + { + "symbol": "Y", + "mode": "SINGLE", + "value": 0.8 + }, + { + "symbol": "LargeurBerge", + "mode": "SINGLE", + "value": 2.5 + } + ] + }, + { + "uid": "ZTNvMD", + "props": { + "methodeResolution": 0, + "calcType": 4, + "nodeType": 2 + }, + "meta": { + "title": "Remous" + }, + "parameters": [ + { + "symbol": "Pr", + "mode": "SINGLE", + "value": 0.0001 + }, + { + "symbol": "Yamont", + "mode": "SINGLE", + "value": 0.15 + }, + { + "symbol": "Yaval", + "mode": "SINGLE", + "value": 0.4 + }, + { + "symbol": "Long", + "mode": "SINGLE", + "value": 100 + }, + { + "symbol": "Dx", + "mode": "SINGLE", + "value": 5 + }, + { + "symbol": "Ks", + "mode": "SINGLE", + "value": 40 + }, + { + "symbol": "Q", + "mode": "SINGLE", + "value": 1.2 + }, + { + "symbol": "If", + "mode": "SINGLE", + "value": 0.001 + }, + { + "symbol": "YB", + "mode": "SINGLE", + "value": 1 + }, + { + "symbol": "Y", + "mode": "SINGLE", + "value": 0.2863766123093061 + }, + { + "symbol": "LargeurBerge", + "mode": "SINGLE", + "value": 2.5 + } + ] + }, + { + "uid": "eWllan", + "props": { + "calcType": 1, + "nodeType": 0 + }, + "meta": { + "title": "Lechapt-Calmon" + }, + "parameters": [ + { + "symbol": "Pr", + "mode": "SINGLE", + "value": 0.0001 + }, + { + "symbol": "Q", + "mode": "SINGLE", + "value": 3 + }, + { + "symbol": "D", + "mode": "SINGLE", + "value": 1.2 + }, + { + "symbol": "J", + "mode": "CALCUL" + }, + { + "symbol": "Lg", + "mode": "SINGLE", + "value": 100 + }, + { + "symbol": "L", + "mode": "SINGLE", + "value": "1.863" + }, + { + "symbol": "M", + "mode": "SINGLE", + "value": "2" + }, + { + "symbol": "N", + "mode": "SINGLE", + "value": "5.33" + } + ] + } + ] +} \ No newline at end of file diff --git a/e2e/session-cascade-params.json b/e2e/session-cascade-params.json new file mode 100644 index 000000000..773053d54 --- /dev/null +++ b/e2e/session-cascade-params.json @@ -0,0 +1,146 @@ +{ + "session": [ + { + "uid": "OGFzOH", + "props": { + "varCalc": "Hs", + "calcType": 2, + "nodeType": 2 + }, + "meta": { + "title": "Sec. param." + }, + "parameters": [ + { + "symbol": "Pr", + "mode": "SINGLE", + "value": 0.0001 + }, + { + "symbol": "Ks", + "mode": "SINGLE", + "value": 40 + }, + { + "symbol": "Q", + "mode": "SINGLE", + "value": 1.2 + }, + { + "symbol": "If", + "mode": "SINGLE", + "value": 0.001 + }, + { + "symbol": "YB", + "mode": "SINGLE", + "value": 1 + }, + { + "symbol": "Y", + "mode": "SINGLE", + "value": 0.8 + }, + { + "symbol": "LargeurBerge", + "mode": "SINGLE", + "value": 2.5 + } + ] + }, + { + "uid": "NWp1a3", + "props": { + "calcType": 3, + "nodeType": 2 + }, + "meta": { + "title": "R. uniforme" + }, + "parameters": [ + { + "symbol": "Pr", + "mode": "SINGLE", + "value": 0.0001 + }, + { + "symbol": "Ks", + "mode": "SINGLE", + "value": 40 + }, + { + "symbol": "Q", + "mode": "CALCUL" + }, + { + "symbol": "If", + "mode": "SINGLE", + "value": 0.001 + }, + { + "symbol": "YB", + "mode": "SINGLE", + "value": 1 + }, + { + "symbol": "Y", + "mode": "SINGLE", + "value": 0.8 + }, + { + "symbol": "LargeurBerge", + "mode": "LINK", + "targetNub": "OGFzOH", + "targetParam": "LargeurBerge" + } + ] + }, + { + "uid": "dWs5bm", + "props": { + "calcType": 3, + "nodeType": 2 + }, + "meta": { + "title": "R. uniforme 1" + }, + "parameters": [ + { + "symbol": "Pr", + "mode": "SINGLE", + "value": 0.0001 + }, + { + "symbol": "Ks", + "mode": "SINGLE", + "value": 40 + }, + { + "symbol": "Q", + "mode": "CALCUL" + }, + { + "symbol": "If", + "mode": "SINGLE", + "value": 0.001 + }, + { + "symbol": "YB", + "mode": "SINGLE", + "value": 1 + }, + { + "symbol": "Y", + "mode": "SINGLE", + "value": 0.8 + }, + { + "symbol": "LargeurBerge", + "mode": "LINK", + "targetNub": "NWp1a3", + "targetParam": "LargeurBerge" + } + ] + } + ] +} \ No newline at end of file diff --git a/e2e/session-cascade-results.json b/e2e/session-cascade-results.json new file mode 100644 index 000000000..9825f301c --- /dev/null +++ b/e2e/session-cascade-results.json @@ -0,0 +1,191 @@ +{ + "session": [ + { + "uid": "YWFqMD", + "props": { + "calcType": 11, + "nodeType": 0 + }, + "meta": { + "title": "Macro-rugo." + }, + "parameters": [ + { + "symbol": "Pr", + "mode": "SINGLE", + "value": 0.0001 + }, + { + "symbol": "ZF1", + "mode": "SINGLE", + "value": 12.5 + }, + { + "symbol": "L", + "mode": "SINGLE", + "value": 6 + }, + { + "symbol": "B", + "mode": "CALCUL" + }, + { + "symbol": "If", + "mode": "SINGLE", + "value": 0.05 + }, + { + "symbol": "Q", + "mode": "LINK", + "targetNub": "MXB0en", + "targetParam": "Q" + }, + { + "symbol": "Y", + "mode": "SINGLE", + "value": 0.6 + }, + { + "symbol": "Ks", + "mode": "SINGLE", + "value": 0.01 + }, + { + "symbol": "C", + "mode": "SINGLE", + "value": 0.05 + }, + { + "symbol": "PBD", + "mode": "SINGLE", + "value": 0.5 + }, + { + "symbol": "PBH", + "mode": "SINGLE", + "value": 0.8 + }, + { + "symbol": "Cd0", + "mode": "SINGLE", + "value": 1.5 + } + ] + }, + { + "uid": "MXB0en", + "props": { + "calcType": 3, + "nodeType": 2 + }, + "meta": { + "title": "R. uniforme" + }, + "parameters": [ + { + "symbol": "Pr", + "mode": "SINGLE", + "value": 0.0001 + }, + { + "symbol": "Ks", + "mode": "SINGLE", + "value": 40 + }, + { + "symbol": "Q", + "mode": "CALCUL" + }, + { + "symbol": "If", + "mode": "SINGLE", + "value": 0.001 + }, + { + "symbol": "YB", + "mode": "LINK", + "targetNub": "ZHd0ej", + "targetParam": "Yco" + }, + { + "symbol": "Y", + "mode": "SINGLE", + "value": 0.8 + }, + { + "symbol": "LargeurBerge", + "mode": "SINGLE", + "value": 2.5 + } + ] + }, + { + "uid": "ZHd0ej", + "props": { + "methodeResolution": 0, + "calcType": 4, + "nodeType": 2 + }, + "meta": { + "title": "Remous" + }, + "parameters": [ + { + "symbol": "Pr", + "mode": "SINGLE", + "value": 0.0001 + }, + { + "symbol": "Yamont", + "mode": "SINGLE", + "value": 0.15 + }, + { + "symbol": "Yaval", + "mode": "SINGLE", + "value": 0.4 + }, + { + "symbol": "Long", + "mode": "SINGLE", + "value": 100 + }, + { + "symbol": "Dx", + "mode": "SINGLE", + "value": 5 + }, + { + "symbol": "Ks", + "mode": "SINGLE", + "value": 40 + }, + { + "symbol": "Q", + "mode": "SINGLE", + "value": 1.2 + }, + { + "symbol": "If", + "mode": "SINGLE", + "value": 0.001 + }, + { + "symbol": "YB", + "mode": "SINGLE", + "value": 1 + }, + { + "symbol": "Y", + "mode": "SINGLE", + "value": 0.5643749999999994 + }, + { + "symbol": "LargeurBerge", + "mode": "SINGLE", + "value": 2.5 + } + ] + } + ] +} \ No newline at end of file diff --git a/e2e/session-optional-params.test.json b/e2e/session-optional-params.test.json index 804c559cb..6fb0e40e8 100644 --- a/e2e/session-optional-params.test.json +++ b/e2e/session-optional-params.test.json @@ -1 +1,57 @@ -{"session":[{"uid":"N2U4OH","props":{"varCalc":"Hs","calcType":2,"nodeType":4},"meta":{"title":"Sec. param."},"parameters":[{"symbol":"Pr","mode":"SINGLE","value":0.0001},{"symbol":"Ks","mode":"SINGLE","value":40},{"symbol":"Q","mode":"SINGLE","value":1.2},{"symbol":"If","mode":"SINGLE","value":0.001},{"symbol":"YB","mode":"SINGLE","value":1},{"symbol":"Y","mode":"SINGLE","value":0.8},{"symbol":"LargeurBerge","mode":"SINGLE","value":4},{"symbol":"k","mode":"SINGLE","value":0.5}]}]} \ No newline at end of file +{ + "session": [ + { + "uid": "N2U4OH", + "props": { + "varCalc": "Hs", + "calcType": 2, + "nodeType": 4 + }, + "meta": { + "title": "Sec. param." + }, + "parameters": [ + { + "symbol": "Pr", + "mode": "SINGLE", + "value": 0.0001 + }, + { + "symbol": "Ks", + "mode": "SINGLE", + "value": 40 + }, + { + "symbol": "Q", + "mode": "SINGLE", + "value": 1.2 + }, + { + "symbol": "If", + "mode": "SINGLE", + "value": 0.001 + }, + { + "symbol": "YB", + "mode": "SINGLE", + "value": 1 + }, + { + "symbol": "Y", + "mode": "SINGLE", + "value": 0.8 + }, + { + "symbol": "LargeurBerge", + "mode": "SINGLE", + "value": 4 + }, + { + "symbol": "k", + "mode": "SINGLE", + "value": 0.5 + } + ] + } + ] +} \ No newline at end of file diff --git a/src/app/app.component.html b/src/app/app.component.html index f2863b8e4..fc3d49453 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -40,9 +40,9 @@ <!-- calculators list as a tabs bar--> <div id="tabs-container" [hidden]="! tabsFitInNavbar"> - <button mat-raised-button color="primary" *ngFor="let c of calculators" class="calculator-button" [title]="c.title" - [routerLink]="['/calculator/',c.uid]" [color]="c.active ? '' : 'primary'" [class.active]="c.active" - (click)="setActiveCalc(c.uid)"> + <button mat-raised-button color="primary" *ngFor="let c of calculators" class="" [title]="c.title" + [routerLink]="['/calculator/',c.uid]" [color]="c.active ? '' : 'primary'" (click)="setActiveCalc(c.uid)" + [ngClass]="['calculator-button', 'calculator-uid-' + c.uid, c.active ? 'active' : '' ]"> <span class="calc-name"> {{ c.title }} -- GitLab From 66513ecae431b119bee582a8f3fb54905a884067 Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Mon, 25 Mar 2019 11:09:43 +0100 Subject: [PATCH 23/39] =?UTF-8?q?Am=C3=A9lioration=20de=20l'invalidation?= =?UTF-8?q?=20des=20r=C3=A9sultats=20en=20cascade?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- e2e/compute-reset-chained-links.e2e-spec.ts | 4 +- e2e/session-cascade-results.json | 46 ++++++------------- .../services/formulaire/formulaire.service.ts | 6 ++- 3 files changed, 19 insertions(+), 37 deletions(-) diff --git a/e2e/compute-reset-chained-links.e2e-spec.ts b/e2e/compute-reset-chained-links.e2e-spec.ts index 17a716766..44fb7022b 100644 --- a/e2e/compute-reset-chained-links.e2e-spec.ts +++ b/e2e/compute-reset-chained-links.e2e-spec.ts @@ -126,7 +126,7 @@ describe("ngHyd − compute then reset chained results", () => { expect(await navbar.getAllCalculatorTabs().count()).toBe(3); // 1. get top most module - await navbar.clickCalculatorTabForUid("YWFqMD"); + await navbar.clickCalculatorTabForUid("YjJua2"); // check that "compute" button is active const calcButton = calcPage.getCalculateButton(); @@ -143,7 +143,7 @@ describe("ngHyd − compute then reset chained results", () => { } // 2. get bottom-most module - await navbar.clickCalculatorTabForUid("ZHd0ej"); + await navbar.clickCalculatorTabForUid("OGd2em"); // modify any input (for ex. "Ks") await calcPage.getInputById("Ks").clear(); diff --git a/e2e/session-cascade-results.json b/e2e/session-cascade-results.json index 9825f301c..e0284cc66 100644 --- a/e2e/session-cascade-results.json +++ b/e2e/session-cascade-results.json @@ -1,7 +1,7 @@ { "session": [ { - "uid": "YWFqMD", + "uid": "YjJua2", "props": { "calcType": 11, "nodeType": 0 @@ -37,7 +37,7 @@ { "symbol": "Q", "mode": "LINK", - "targetNub": "MXB0en", + "targetNub": "eW1hY3", "targetParam": "Q" }, { @@ -73,7 +73,7 @@ ] }, { - "uid": "MXB0en", + "uid": "eW1hY3", "props": { "calcType": 3, "nodeType": 2 @@ -103,14 +103,14 @@ }, { "symbol": "YB", - "mode": "LINK", - "targetNub": "ZHd0ej", - "targetParam": "Yco" + "mode": "SINGLE", + "value": 1 }, { "symbol": "Y", - "mode": "SINGLE", - "value": 0.8 + "mode": "LINK", + "targetNub": "OGd2em", + "targetParam": "Yco" }, { "symbol": "LargeurBerge", @@ -120,14 +120,14 @@ ] }, { - "uid": "ZHd0ej", + "uid": "OGd2em", "props": { - "methodeResolution": 0, - "calcType": 4, + "varCalc": "Hs", + "calcType": 2, "nodeType": 2 }, "meta": { - "title": "Remous" + "title": "Sec. param." }, "parameters": [ { @@ -135,26 +135,6 @@ "mode": "SINGLE", "value": 0.0001 }, - { - "symbol": "Yamont", - "mode": "SINGLE", - "value": 0.15 - }, - { - "symbol": "Yaval", - "mode": "SINGLE", - "value": 0.4 - }, - { - "symbol": "Long", - "mode": "SINGLE", - "value": 100 - }, - { - "symbol": "Dx", - "mode": "SINGLE", - "value": 5 - }, { "symbol": "Ks", "mode": "SINGLE", @@ -178,7 +158,7 @@ { "symbol": "Y", "mode": "SINGLE", - "value": 0.5643749999999994 + "value": 0.8 }, { "symbol": "LargeurBerge", diff --git a/src/app/services/formulaire/formulaire.service.ts b/src/app/services/formulaire/formulaire.service.ts index 49533c522..fe3e0bfe6 100644 --- a/src/app/services/formulaire/formulaire.service.ts +++ b/src/app/services/formulaire/formulaire.service.ts @@ -617,8 +617,10 @@ export class FormulaireService extends Observable { for (const dn of dependingNubs) { if (! visited.includes(dn.uid)) { const form = this.getFormulaireFromNubId(dn.uid); - if (form.hasResults) { - form.resetResults(visited); + const hadResults = form.hasResults; + // form might not have a result, but still have another form depending on it ! + form.resetResults(visited); + if (hadResults) { if (notify) { this.notificationsService.notify( this.intlService.localizeText("INFO_SNACKBAR_RESULTS_INVALIDATED") + " " + form.calculatorName, -- GitLab From a8bef84f531f5fe746a66265a6010f6d3fa41f96 Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Mon, 25 Mar 2019 16:14:15 +0100 Subject: [PATCH 24/39] =?UTF-8?q?Adaptation=20=C3=A0=20la=20nouvelle=20rep?= =?UTF-8?q?r=C3=A9sentation=20des=20variables=20de=20Structure=20=C3=A0=20?= =?UTF-8?q?calculer;=20mise=20=C3=A0=20jour=20des=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- e2e/load-linked-params.e2e-spec.ts | 22 ++++-- e2e/session-liens-spaghetti.json | 77 +++++++++++++++++-- .../form-compute-parallel-structures.ts | 18 +++-- .../formulaire/definition/form-definition.ts | 2 +- .../services/formulaire/formulaire.service.ts | 20 ++--- 5 files changed, 109 insertions(+), 30 deletions(-) diff --git a/e2e/load-linked-params.e2e-spec.ts b/e2e/load-linked-params.e2e-spec.ts index cd0b97a4c..56f84364a 100644 --- a/e2e/load-linked-params.e2e-spec.ts +++ b/e2e/load-linked-params.e2e-spec.ts @@ -35,7 +35,7 @@ describe("ngHyd − load session with multiple linked parameters", () => { await sidenav.loadSessionFile("./session-liens-spaghetti.json"); await browser.sleep(500); - expect(await navbar.getAllCalculatorTabs().count()).toBe(4); + expect(await navbar.getAllCalculatorTabs().count()).toBe(5); // 1. check Section paramétrée await navbar.clickCalculatorTab(0); @@ -51,11 +51,11 @@ describe("ngHyd − load session with multiple linked parameters", () => { // check target params values const mr_b = calcPage.getSelectById("linked_B"); const mr_bv = await calcPage.getSelectValueText(mr_b); - expect(mr_bv).toEqual("L (résultat de Ouvrages, ouvrage 1)"); + expect(mr_bv).toEqual("L (résultat de Ouvrages)"); const mr_q = calcPage.getSelectById("linked_Q"); const mr_qv = await calcPage.getSelectValueText(mr_q); - expect(mr_qv).toEqual("Q (résultat de R. uniforme)"); + expect(mr_qv).toEqual("Q (R. uniforme)"); // 3. check Lois d'ouvrages await navbar.clickCalculatorTab(2); @@ -67,7 +67,7 @@ describe("ngHyd − load session with multiple linked parameters", () => { const lo_l = calcPage.getSelectById("linked_L"); // attention ID non unique, voir nghyd#173 const lo_lv = await calcPage.getSelectValueText(lo_l); - expect(lo_lv).toEqual("L (résultat de Ouvrages, ouvrage 1)"); + expect(lo_lv).toEqual("L (résultat de Ouvrages)"); const lo_w = calcPage.getSelectById("linked_W"); // attention ID non unique, voir nghyd#173 const lo_wv = await calcPage.getSelectValueText(lo_w); @@ -81,9 +81,17 @@ describe("ngHyd − load session with multiple linked parameters", () => { await navbar.clickCalculatorTab(3); // check target params values - const lo_y = calcPage.getSelectById("linked_Y"); - const lo_yv = await calcPage.getSelectValueText(lo_y); - expect(lo_yv).toEqual("Yt (Sec. param., résultat complémentaire)"); + const lo_q = calcPage.getSelectById("linked_Q"); + const lo_qv = await calcPage.getSelectValueText(lo_q); + expect(lo_qv).toEqual("CvQT (Déver. dénoyés, résultat complémentaire)"); + + // 5. check Déver. dénoyés + await navbar.clickCalculatorTab(4); + + // check target params values + const lo_br = calcPage.getSelectById("linked_BR"); + const lo_brv = await calcPage.getSelectValueText(lo_br); + expect(lo_brv).toEqual("LargeurBerge (Sec. param.)"); }); }); diff --git a/e2e/session-liens-spaghetti.json b/e2e/session-liens-spaghetti.json index bbccd213b..87b17d2a1 100644 --- a/e2e/session-liens-spaghetti.json +++ b/e2e/session-liens-spaghetti.json @@ -77,7 +77,7 @@ { "symbol": "B", "mode": "LINK", - "targetNub": "cjdyYW", + "targetNub": "ZW9icn", "targetParam": "L" }, { @@ -186,7 +186,7 @@ { "symbol": "L", "mode": "LINK", - "targetNub": "cjdyYW", + "targetNub": "ZW9icn", "targetParam": "L" }, { @@ -276,7 +276,9 @@ }, { "symbol": "Q", - "mode": "CALCUL" + "mode": "LINK", + "targetNub": "NGlpMn", + "targetParam": "CvQT" }, { "symbol": "If", @@ -292,14 +294,77 @@ }, { "symbol": "Y", + "mode": "SINGLE", + "value": 0.8 + }, + { + "symbol": "LargeurBerge", + "mode": "CALCUL" + } + ] + }, + { + "uid": "NGlpMn", + "props": { + "calcType": 9, + "nodeType": 0 + }, + "meta": { + "title": "Déver. dénoyés" + }, + "structures": [ + { + "uid": "M29rcW", + "props": { + "calcType": 7, + "nodeType": 5, + "structureType": 0, + "loiDebit": 7 + }, + "parameters": [ + { + "symbol": "ZDV", + "mode": "SINGLE", + "value": 100 + }, + { + "symbol": "L", + "mode": "SINGLE", + "value": 2 + }, + { + "symbol": "Cd", + "mode": "SINGLE", + "value": 0.4 + } + ] + } + ], + "parameters": [ + { + "symbol": "Pr", + "mode": "SINGLE", + "value": 0.0001 + }, + { + "symbol": "Q", + "mode": "CALCUL" + }, + { + "symbol": "Z1", + "mode": "SINGLE", + "value": 102 + }, + { + "symbol": "BR", "mode": "LINK", "targetNub": "OW9rd3", - "targetParam": "Yt" + "targetParam": "LargeurBerge" }, { - "symbol": "LargeurBerge", + "symbol": "ZR", "mode": "SINGLE", - "value": 2.5 + "value": 99 } ] } diff --git a/src/app/formulaire/definition/form-compute-parallel-structures.ts b/src/app/formulaire/definition/form-compute-parallel-structures.ts index 9daa4cbd6..580a52f08 100644 --- a/src/app/formulaire/definition/form-compute-parallel-structures.ts +++ b/src/app/formulaire/definition/form-compute-parallel-structures.ts @@ -1,4 +1,4 @@ -import { ComputeNode, ParallelStructure } from "jalhyd"; +import { ComputeNode, ParallelStructure, Structure } from "jalhyd"; import { FormComputeFixedVar } from "./form-compute-fixedvar"; import { FormResultFixedVar } from "./form-result-fixedvar"; @@ -38,15 +38,19 @@ export class FormComputeParallelStructures extends FormComputeFixedVar { } /** - * construit un identifiant de type "n.X" avec "n" l'index de l'ouvrage auquel appartient le paramètre et "X" son symbole + * construit un identifiant de type { uid: "abcdef", symbol: "X" } + * avec "abcdef" l'index de l'ouvrage et "X" son paramètre */ - protected getParameterRefid(p: NgParameter) { - const [fsc, fs, i] = this.structureParents(p); - if (i === -1) { + protected getParameterRefid(p: NgParameter): any { + const nub = p.paramDefinition.parentComputeNode; + if (nub instanceof Structure) { + return { + uid: nub.uid, + symbol: p.symbol + }; + } else { return super.getParameterRefid(p); } - - return `${i}.${p.symbol}`; } protected setParameterValue(node: ComputeNode, p: NgParameter, val: number) { diff --git a/src/app/formulaire/definition/form-definition.ts b/src/app/formulaire/definition/form-definition.ts index e34b286f2..e1d9f5433 100644 --- a/src/app/formulaire/definition/form-definition.ts +++ b/src/app/formulaire/definition/form-definition.ts @@ -162,7 +162,7 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs * @param uid id à rechercher */ public hasNubId(uid: string): boolean { - return this._currentNub.uid === uid; + return (this._currentNub && this._currentNub.uid === uid); } public moveFieldsetUp(fs: FieldSet) { diff --git a/src/app/services/formulaire/formulaire.service.ts b/src/app/services/formulaire/formulaire.service.ts index fe3e0bfe6..c9d21d2d3 100644 --- a/src/app/services/formulaire/formulaire.service.ts +++ b/src/app/services/formulaire/formulaire.service.ts @@ -617,15 +617,17 @@ export class FormulaireService extends Observable { for (const dn of dependingNubs) { if (! visited.includes(dn.uid)) { const form = this.getFormulaireFromNubId(dn.uid); - const hadResults = form.hasResults; - // form might not have a result, but still have another form depending on it ! - form.resetResults(visited); - if (hadResults) { - if (notify) { - this.notificationsService.notify( - this.intlService.localizeText("INFO_SNACKBAR_RESULTS_INVALIDATED") + " " + form.calculatorName, - 2000 - ); + if (form) { + const hadResults = form.hasResults; + // form might not have a result, but still have another form depending on it ! + form.resetResults(visited); + if (hadResults) { + if (notify) { + this.notificationsService.notify( + this.intlService.localizeText("INFO_SNACKBAR_RESULTS_INVALIDATED") + " " + form.calculatorName, + 2000 + ); + } } } } -- GitLab From 6deadcb5befedf3cbd031359fddc926206d8ddec Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Mon, 25 Mar 2019 16:34:02 +0100 Subject: [PATCH 25/39] =?UTF-8?q?M=C3=A0J=20tests=20e2e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- e2e/calculate-all-params.e2e-spec.ts | 2 +- e2e/compute-reset-chained-links.e2e-spec.ts | 57 +++--------------- e2e/session-cascade-results.json | 64 +++++++++------------ 3 files changed, 34 insertions(+), 89 deletions(-) diff --git a/e2e/calculate-all-params.e2e-spec.ts b/e2e/calculate-all-params.e2e-spec.ts index eebcfa7e8..eaff7587d 100644 --- a/e2e/calculate-all-params.e2e-spec.ts +++ b/e2e/calculate-all-params.e2e-spec.ts @@ -43,7 +43,7 @@ describe("ngHyd − calculate all parameters of all calculators", () => { // check that "compute" button is active const calcButton = calcPage.getCalculateButton(); const disabledState = await calcButton.getAttribute("disabled"); - expect(disabledState).not.toBe("disabled"); + expect(disabledState).not.toBe("true"); // click "compute" button await calcButton.click(); // check that result is not empty diff --git a/e2e/compute-reset-chained-links.e2e-spec.ts b/e2e/compute-reset-chained-links.e2e-spec.ts index 44fb7022b..6399c764c 100644 --- a/e2e/compute-reset-chained-links.e2e-spec.ts +++ b/e2e/compute-reset-chained-links.e2e-spec.ts @@ -25,49 +25,6 @@ describe("ngHyd − compute then reset chained results", () => { } beforeEach(init); - async function doTheJob(filename: string, topMostId: string, bottomMostId: string) { - // load session file - await startPage.navigateTo(); - await navbar.clickMenuButton(); - await browser.sleep(200); - await sidenav.clickLoadSessionButton(); - await browser.sleep(200); - await sidenav.loadSessionFile(filename); - await browser.sleep(500); - expect(await navbar.getAllCalculatorTabs().count()).toBe(3); - - // 1. get top most module - await navbar.clickCalculatorTabForUid(topMostId); - - // check that "compute" button is active - const calcButton = calcPage.getCalculateButton(); - const disabledState = await calcButton.getAttribute("disabled"); - expect(disabledState).not.toBe("disabled"); - // click "compute" button - await calcButton.click(); - - // check all 3 modules for results - for (let i = 0; i < 3; i++) { - await navbar.clickCalculatorTab(i); - const hasResults = await calcPage.hasResults(); - expect(hasResults).toBe(true); - } - - // 2. get bottom-most module - await navbar.clickCalculatorTabForUid(bottomMostId); - - // modify any input (for ex. "Ks") - await calcPage.getInputById("Ks").clear(); - await calcPage.getInputById("Ks").sendKeys("42"); - - // check all 3 modules for absence of results - for (let i = 0; i < 3; i++) { - await navbar.clickCalculatorTab(i); - const hasResults = await calcPage.hasResults(); - expect(hasResults).toBe(false); - } - } - it("when loading session-cascade-params.json, computation should not be chained, but results reset should", async () => { // load session file await startPage.navigateTo(); @@ -85,7 +42,7 @@ describe("ngHyd − compute then reset chained results", () => { // check that "compute" button is active const calcButton = calcPage.getCalculateButton(); const disabledState = await calcButton.getAttribute("disabled"); - expect(disabledState).not.toBe("disabled"); + expect(disabledState).not.toBe("true"); // click "compute" button await calcButton.click(); @@ -125,13 +82,13 @@ describe("ngHyd − compute then reset chained results", () => { await browser.sleep(500); expect(await navbar.getAllCalculatorTabs().count()).toBe(3); - // 1. get top most module - await navbar.clickCalculatorTabForUid("YjJua2"); + // 1. get top most module (PAB Dimensions) + await navbar.clickCalculatorTabForUid("bGZqcz"); // check that "compute" button is active const calcButton = calcPage.getCalculateButton(); - const disabledState = await calcButton.getAttribute("disabled"); - expect(disabledState).not.toBe("disabled"); + const disabledState = await calcButton.getAttribute("true"); + expect(disabledState).not.toBe("true"); // click "compute" button await calcButton.click(); @@ -142,8 +99,8 @@ describe("ngHyd − compute then reset chained results", () => { expect(hasResults).toBe(true); } - // 2. get bottom-most module - await navbar.clickCalculatorTabForUid("OGd2em"); + // 2. get bottom-most module (Macro-rugo) + await navbar.clickCalculatorTabForUid("dnRiY2"); // modify any input (for ex. "Ks") await calcPage.getInputById("Ks").clear(); diff --git a/e2e/session-cascade-results.json b/e2e/session-cascade-results.json index e0284cc66..3c1441850 100644 --- a/e2e/session-cascade-results.json +++ b/e2e/session-cascade-results.json @@ -1,7 +1,7 @@ { "session": [ { - "uid": "YjJua2", + "uid": "dnRiY2", "props": { "calcType": 11, "nodeType": 0 @@ -27,18 +27,17 @@ }, { "symbol": "B", - "mode": "CALCUL" + "mode": "SINGLE", + "value": 1 }, { "symbol": "If", - "mode": "SINGLE", - "value": 0.05 + "mode": "CALCUL" }, { "symbol": "Q", - "mode": "LINK", - "targetNub": "eW1hY3", - "targetParam": "Q" + "mode": "SINGLE", + "value": 1.57 }, { "symbol": "Y", @@ -73,7 +72,7 @@ ] }, { - "uid": "eW1hY3", + "uid": "YjZyND", "props": { "calcType": 3, "nodeType": 2 @@ -94,7 +93,9 @@ }, { "symbol": "Q", - "mode": "CALCUL" + "mode": "LINK", + "targetNub": "dnRiY2", + "targetParam": "Q_GuideTech" }, { "symbol": "If", @@ -108,26 +109,23 @@ }, { "symbol": "Y", - "mode": "LINK", - "targetNub": "OGd2em", - "targetParam": "Yco" + "mode": "SINGLE", + "value": 0.8 }, { "symbol": "LargeurBerge", - "mode": "SINGLE", - "value": 2.5 + "mode": "CALCUL" } ] }, { - "uid": "OGd2em", + "uid": "bGZqcz", "props": { - "varCalc": "Hs", - "calcType": 2, - "nodeType": 2 + "calcType": 5, + "nodeType": 0 }, "meta": { - "title": "Sec. param." + "title": "PAB : dimensions" }, "parameters": [ { @@ -136,34 +134,24 @@ "value": 0.0001 }, { - "symbol": "Ks", - "mode": "SINGLE", - "value": 40 - }, - { - "symbol": "Q", - "mode": "SINGLE", - "value": 1.2 - }, - { - "symbol": "If", + "symbol": "L", "mode": "SINGLE", - "value": 0.001 + "value": 2 }, { - "symbol": "YB", - "mode": "SINGLE", - "value": 1 + "symbol": "W", + "mode": "LINK", + "targetNub": "YjZyND", + "targetParam": "LargeurBerge" }, { "symbol": "Y", "mode": "SINGLE", - "value": 0.8 + "value": 0.5 }, { - "symbol": "LargeurBerge", - "mode": "SINGLE", - "value": 2.5 + "symbol": "V", + "mode": "CALCUL" } ] } -- GitLab From fe2b90121bf946ea51814d2f7aadcc9059b8af6f Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Mon, 25 Mar 2019 16:59:48 +0100 Subject: [PATCH 26/39] =?UTF-8?q?Suppression=20de=20code=20inutilis=C3=A9?= =?UTF-8?q?=20:=20champ=20checkbox?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/app.module.ts | 2 -- .../check-field-line.component.html | 6 ---- .../check-field-line.component.ts | 20 ------------- .../field-set/field-set.component.html | 2 -- .../field-set/field-set.component.ts | 8 ------ src/app/formulaire/check-field.ts | 28 ------------------- src/app/formulaire/fieldset.ts | 10 ------- .../services/formulaire/formulaire.service.ts | 9 ------ 8 files changed, 85 deletions(-) delete mode 100644 src/app/components/check-field-line/check-field-line.component.html delete mode 100644 src/app/components/check-field-line/check-field-line.component.ts delete mode 100644 src/app/formulaire/check-field.ts diff --git a/src/app/app.module.ts b/src/app/app.module.ts index da7f30bba..059c34d50 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -54,7 +54,6 @@ import { ParamComputedComponent } from "./components/param-computed/param-comput import { ParamFieldLineComponent } from "./components/param-field-line/param-field-line.component"; import { ParamValuesComponent } from "./components/param-values/param-values.component"; import { SelectFieldLineComponent } from "./components/select-field-line/select-field-line.component"; -import { CheckFieldLineComponent } from "./components/check-field-line/check-field-line.component"; import { CalculatorResultsComponent } from "./components/calculator-results/calculator-results.component"; import { FixedVarResultsComponent } from "./components/fixedvar-results/fixedvar-results.component"; import { SectionResultsComponent } from "./components/section-results/section-results.component"; @@ -143,7 +142,6 @@ const appRoutes: Routes = [ CalculatorListComponent, CalculatorNameComponent, CalculatorResultsComponent, - CheckFieldLineComponent, DialogConfirmCloseCalcComponent, DialogConfirmEmptySessionComponent, DialogEditParamComputedComponent, diff --git a/src/app/components/check-field-line/check-field-line.component.html b/src/app/components/check-field-line/check-field-line.component.html deleted file mode 100644 index f00f6fca5..000000000 --- a/src/app/components/check-field-line/check-field-line.component.html +++ /dev/null @@ -1,6 +0,0 @@ -<tr> - <td align="right">{{ check.label }}</td> - <td colspan="3"> - <input type="checkbox" [(ngModel)]=currentValue (ngModelChange)="onChange($event)"> - </td> -</tr> \ No newline at end of file diff --git a/src/app/components/check-field-line/check-field-line.component.ts b/src/app/components/check-field-line/check-field-line.component.ts deleted file mode 100644 index ae159f511..000000000 --- a/src/app/components/check-field-line/check-field-line.component.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Component, Input, Output, EventEmitter } from "@angular/core"; - -import { CheckField } from "../../formulaire/check-field"; - -@Component({ - selector: "check-field-line", - templateUrl: "./check-field-line.component.html", -}) -export class CheckFieldLineComponent { - @Input() - public check: CheckField; - - public currentValue: boolean; - - constructor() { } - - public onChange(event: any) { - this.check.setValue(event); - } -} diff --git a/src/app/components/field-set/field-set.component.html b/src/app/components/field-set/field-set.component.html index e048b3915..444001156 100644 --- a/src/app/components/field-set/field-set.component.html +++ b/src/app/components/field-set/field-set.component.html @@ -25,7 +25,5 @@ <select-field-line *ngIf="isSelectField(p)" [_select]=p> </select-field-line> - - <check-field-line *ngIf="isCheckField(p)" [check]=p></check-field-line> </ng-template> </mat-card-content> diff --git a/src/app/components/field-set/field-set.component.ts b/src/app/components/field-set/field-set.component.ts index 170ba7cda..1541cba64 100644 --- a/src/app/components/field-set/field-set.component.ts +++ b/src/app/components/field-set/field-set.component.ts @@ -6,7 +6,6 @@ import { ParamFieldLineComponent } from "../param-field-line/param-field-line.co import { Field } from "../../formulaire/field"; import { InputField } from "../../formulaire/input-field"; import { SelectField } from "../../formulaire/select-field"; -import { CheckField } from "../../formulaire/check-field"; @Component({ selector: "field-set", @@ -172,13 +171,6 @@ export class FieldSetComponent implements DoCheck { return f instanceof SelectField && f.isDisplayed; } - /** - * détermine si un Field est du type CheckField - */ - private isCheckField(f: Field): boolean { - return f instanceof CheckField && f.isDisplayed; - } - /* * gestion des événements clic sur les radios : * réception d'un message du composant enfant (param-field) diff --git a/src/app/formulaire/check-field.ts b/src/app/formulaire/check-field.ts deleted file mode 100644 index 073816613..000000000 --- a/src/app/formulaire/check-field.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Field } from "./field"; -import { FormulaireNode } from "./formulaire-node"; - -export class CheckField extends Field { - private _value: boolean; - - constructor(parent: FormulaireNode) { - super(parent); - this._value = false; - } - - public getValue(): boolean { - return this._value; - } - - public setValue(val: boolean) { - this._value = val; - } - - public get isValid(): boolean { - return true; - } - - public parseConfig(json: {}, data?: {}) { - this._confId = json["id"]; - this.setValue(json["value"] === "true"); - } -} diff --git a/src/app/formulaire/fieldset.ts b/src/app/formulaire/fieldset.ts index 06106cf6f..14e44ce41 100644 --- a/src/app/formulaire/fieldset.ts +++ b/src/app/formulaire/fieldset.ts @@ -2,7 +2,6 @@ import { CalculatorType, ComputeNodeType, ParamDefinition, LoiDebit, StructureTy import { FormulaireElement } from "./formulaire-element"; import { Field } from "./field"; -import { CheckField } from "./check-field"; import { SelectField } from "./select-field"; import { NgParameter, ParamRadioConfig } from "./ngparam"; import { ServiceFactory } from "../services/service-factory"; @@ -87,12 +86,6 @@ export class FieldSet extends FormulaireElement implements Observer { return res; } - private parse_check(json: {}): CheckField { - const res: CheckField = new CheckField(this); - res.parseConfig(json); - return res; - } - private parse_select(json: {}): SelectField { const res: SelectField = new SelectField(this); res.parseConfig(json); @@ -175,9 +168,6 @@ export class FieldSet extends FormulaireElement implements Observer { } else if (field["type"] === "select") { const param = this.parse_select(field); this.addField(param); - } else if (field["type"] === "check") { - const param = this.parse_check(field); - this.addField(param); } } } diff --git a/src/app/services/formulaire/formulaire.service.ts b/src/app/services/formulaire/formulaire.service.ts index c9d21d2d3..367b8d5b7 100644 --- a/src/app/services/formulaire/formulaire.service.ts +++ b/src/app/services/formulaire/formulaire.service.ts @@ -11,7 +11,6 @@ import { FormulaireDefinition } from "../../formulaire/definition/form-definitio import { FormulaireElement } from "../../formulaire/formulaire-element"; import { InputField } from "../../formulaire/input-field"; import { SelectField } from "../../formulaire/select-field"; -import { CheckField } from "../../formulaire/check-field"; import { StringMap } from "../../stringmap"; import { FormulaireBase } from "../../formulaire/definition/concrete/form-base"; import { FormulaireLechaptCalmon } from "../../formulaire/definition/concrete/form-lechapt-calmon"; @@ -295,14 +294,6 @@ export class FormulaireService extends Observable { return <InputField>s; } - public getCheckField(formId: string, elemId: string): CheckField { - const s = this.getFormulaireElementById(formId, elemId); - if (!(s instanceof CheckField)) { - throw new Error("Form element with id '" + elemId + "' is not a checkbox"); - } - return <CheckField>s; - } - public getSelectField(formId: string, elemId: string): SelectField { const s = this.getFormulaireElementById(formId, elemId); if (!(s instanceof SelectField)) { -- GitLab From 393ebdcdefa29953531682b9596639f0a91a7dcd Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Mon, 25 Mar 2019 17:55:44 +0100 Subject: [PATCH 27/39] Suppression de code de validation inutile --- .../generic-calculator/calc-name.component.ts | 7 -- .../calculator.component.ts | 47 +++----- .../generic-input/generic-input.component.ts | 113 +----------------- .../formulaire/definition/form-definition.ts | 10 -- src/app/formulaire/field.ts | 1 - src/app/formulaire/fieldset.ts | 12 -- src/app/formulaire/select-field.ts | 4 - 7 files changed, 21 insertions(+), 173 deletions(-) diff --git a/src/app/components/generic-calculator/calc-name.component.ts b/src/app/components/generic-calculator/calc-name.component.ts index 208d11e97..3de415d2e 100644 --- a/src/app/components/generic-calculator/calc-name.component.ts +++ b/src/app/components/generic-calculator/calc-name.component.ts @@ -76,11 +76,4 @@ export class CalculatorNameComponent extends GenericInputComponent { return { isValid: valid, message: msg }; } - - /** - * convertit une valeur saisie dans l'UI en valeur affectable au modèle - */ - protected uiToModel(ui: string): any { - return ui; - } } diff --git a/src/app/components/generic-calculator/calculator.component.ts b/src/app/components/generic-calculator/calculator.component.ts index 890d21a4a..c6c9afed1 100644 --- a/src/app/components/generic-calculator/calculator.component.ts +++ b/src/app/components/generic-calculator/calculator.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit, DoCheck, OnDestroy, ViewChild, ViewChildren, QueryList, AfterViewChecked } from "@angular/core"; import { ActivatedRoute, Router } from "@angular/router"; -import { Observer, Session, ParallelStructure } from "jalhyd"; +import { Observer, Session } from "jalhyd"; import { FormulaireService } from "../../services/formulaire/formulaire.service"; import { I18nService } from "../../services/internationalisation/internationalisation.service"; @@ -122,7 +122,7 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit, /** * détermine si un FormulaireElement est du type FieldsetContainer */ - private isFieldsetContainer(fe: any): boolean { + public isFieldsetContainer(fe: any): boolean { return fe instanceof FieldsetContainer; } @@ -164,9 +164,8 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit, } ngDoCheck() { - if (this._formulaire !== undefined) { - this.isCalculateDisabled = !(this._formulaire.isValid && this._isUIValid); - } + console.log(">>> UI validity", this._isUIValid); + this.isCalculateDisabled = ! this._isUIValid; } ngOnDestroy() { @@ -192,7 +191,7 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit, /* * gestion des événements clic sur les radios */ - private onRadioClick(info: any) { + public onRadioClick(info: any) { this.updateLinkedParameters(); this._pendingRadioClick = true; this._pendingRadioClickInfo = info; @@ -246,11 +245,6 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit, } } - private getFieldsetStyleDisplay(id: string) { - const isDisplayed: boolean = this._formulaire.isDisplayed(id); - return isDisplayed ? "block" : "none"; - } - private setForm(f: FormulaireDefinition) { if (this._formulaire !== undefined) { this._formulaire.removeObserver(this); @@ -313,11 +307,7 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit, // accumulator (valeur précédente du résultat) acc, // currentValue (élément courant dans le tableau) - fieldset, - // currentIndex (indice courant dans le tableau) - currIndex, - // array (tableau parcouru) - array + fieldset ) => { return acc && fieldset.isValid; } @@ -331,11 +321,7 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit, // accumulator (valeur précédente du résultat) acc, // currentValue (élément courant dans le tableau) - fieldsetContainer, - // currentIndex (indice courant dans le tableau) - currIndex, - // array (tableau parcouru) - array + fieldsetContainer ) => { return acc && fieldsetContainer.isValid; } @@ -344,27 +330,36 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit, } } + public getFieldsetStyleDisplay(id: string) { + const isDisplayed: boolean = this._formulaire.isDisplayed(id); + return isDisplayed ? "block" : "none"; + } + /** * réception d'un événement de validité d'un FieldSetComponent */ - private OnFieldsetValid() { + public OnFieldsetValid() { this.updateUIValidity(); } /** * réception d'un événement de validité d'un FieldsetContainerComponent */ - private onFieldsetContainerValid() { + public onFieldsetContainerValid() { this.updateUIValidity(); } /** * réception d'un événement de changement de valeur d'un input */ - private onInputChange() { + public onInputChange() { this._formulaire.resetResults([]); } + public openHelp() { + window.open("assets/docs-fr/calculators/" + this._formulaire.helpLink + "/", "_blank"); + } + /** * flag d'affichage du bouton d'aide */ @@ -375,10 +370,6 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit, return false; } - private openHelp() { - window.open("assets/docs-fr/calculators/" + this._formulaire.helpLink + "/", "_blank"); - } - public saveCalculator() { this.formulaireService.saveForm(this._formulaire); } diff --git a/src/app/components/generic-input/generic-input.component.ts b/src/app/components/generic-input/generic-input.component.ts index 8f9f2f7a2..213dfeeaa 100644 --- a/src/app/components/generic-input/generic-input.component.ts +++ b/src/app/components/generic-input/generic-input.component.ts @@ -204,7 +204,7 @@ export abstract class GenericInputComponent extends BaseComponent implements OnC * MAJ et validation de l'UI */ protected updateAndValidateUI() { - this._uiValue = this.modelToUI(this.getModelValue()); + this._uiValue = String(this.getModelValue()); this.validateUI(); } @@ -226,7 +226,7 @@ export abstract class GenericInputComponent extends BaseComponent implements OnC */ public updateModelFromUI() { if (this.validateUI()) { - this.setAndValidateModel(this, this.uiToModel(this._uiValue)); + this.setAndValidateModel(this, +this._uiValue); // cast UI value to Number } } @@ -270,13 +270,6 @@ export abstract class GenericInputComponent extends BaseComponent implements OnC */ protected abstract validateModelValue(v: any): { isValid: boolean, message: string }; - /** - * convertit le modèle en valeur affichable par l'UI - */ - protected modelToUI(v: any): string { - return String(v); - } - /** * valide une valeur saisie dans l'UI (forme de la saisie : est ce bien une date, un nombre, ...) * @param ui saisie à valider @@ -295,106 +288,4 @@ export abstract class GenericInputComponent extends BaseComponent implements OnC return { isValid: valid, message: msg }; } - - /** - * convertit une valeur saisie dans l'UI en valeur affectable au modèle - */ - protected uiToModel(ui: string): any { - return +ui; - } -} - -/* - * exemples d'utilisation de GenericInputComponent - */ - -/* -import { Component } from "@angular/core"; - -import { isNumeric, Message } from "jalhyd"; - -// exemple où le modèle est un type simple (number) - -@Component({ - selector: "test-input", - template: `<div class="md-form form-sm"> - <input type="text" id="form1" class="form-control" [disabled]="isDisabled" [(ngModel)]="uiValue"> - <label for="form1">{{title}}</label> - <small *ngIf="showError" class="text-danger">{{errorMessage}}</small> -</div>` -}) -export class TestInputComponent extends GenericInputComponent { - constructor() { - super(); - this._model = 0; - } - - protected getModelValue(): any { - return this._model; - } - - protected setModelValue(v: any) { - this._model = v; - } - - protected validateModelValue(v: any): { isValid: boolean, message: string } { - let msg = undefined; - let valid = false; - - if (v < 0) - msg = "La valeur n'est pas >= 0 "; - else - valid = true; - - return { isValid: valid, message: msg }; - } - - protected uiToModel(ui: string): any { - return +ui; - } -} - - -// exemple où le modèle est une classe dont on ne gère qu'un membre - -import { ParamDefinition } from "jalhyd"; - -@Component({ - selector: "test2-input", - template: `<div class="md-form form-sm"> - <input type="text" id="form1" class="form-control" [disabled]="isDisabled" [(ngModel)]="uiValue"> - <label for="form1">{{title}}</label> - <small *ngIf="showError" class="text-danger">{{errorMessage}}</small> -</div>` -}) -export class Test2InputComponent extends GenericInputComponent { - constructor() { - super(); - } - - // paramètre géré - private get _param(): ParamDefinition { - return this._model; - } - - protected getModelValue(): any { - return this._param.getValue(); - } - - protected setModelValue(v: any) { - this._param.setValue(v); - } - - protected validateModelValue(v: any): { isValid: boolean, message: string } { - let msg = undefined; - let valid = false; - - if (v < 0) - msg = "La valeur n'est pas >= 0 "; - else - valid = true; - - return { isValid: valid, message: msg }; - } } -/**/ diff --git a/src/app/formulaire/definition/form-definition.ts b/src/app/formulaire/definition/form-definition.ts index e1d9f5433..4d14b15b7 100644 --- a/src/app/formulaire/definition/form-definition.ts +++ b/src/app/formulaire/definition/form-definition.ts @@ -417,16 +417,6 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs return (<FormulaireElement>this.getFormulaireNodeById(id)).isDisplayed; } - public get isValid(): boolean { - let res = true; - for (const fs of this.allFieldsets) { - if (fs.isDisplayed) { - res = res && fs.isValid; - } - } - return res; - } - /** * gestion d'un clic sur les radios */ diff --git a/src/app/formulaire/field.ts b/src/app/formulaire/field.ts index c8d2f84b6..3bdbef3c0 100644 --- a/src/app/formulaire/field.ts +++ b/src/app/formulaire/field.ts @@ -4,7 +4,6 @@ import { Dependency } from "./dependency/dependency"; import { isNumber } from "util"; export abstract class Field extends FormulaireElement { - public abstract get isValid(); public abstract getValue(): any; public abstract setValue(sender: any, val: any): void; diff --git a/src/app/formulaire/fieldset.ts b/src/app/formulaire/fieldset.ts index 14e44ce41..ffa32a38d 100644 --- a/src/app/formulaire/fieldset.ts +++ b/src/app/formulaire/fieldset.ts @@ -74,18 +74,6 @@ export class FieldSet extends FormulaireElement implements Observer { } } - public get isValid(): boolean { - let res = true; - for (const f of this.kids) { - if (f instanceof Field) { - if (f.isDisplayed) { - res = res && f.isValid; - } - } - } - return res; - } - private parse_select(json: {}): SelectField { const res: SelectField = new SelectField(this); res.parseConfig(json); diff --git a/src/app/formulaire/select-field.ts b/src/app/formulaire/select-field.ts index df078bfbf..c60b4dd50 100644 --- a/src/app/formulaire/select-field.ts +++ b/src/app/formulaire/select-field.ts @@ -51,10 +51,6 @@ export class SelectField extends Field { } } - public get isValid(): boolean { - return true; - } - public getLabel() { if (this._selectedEntry) { return this._selectedEntry.label; -- GitLab From c2970c6f7b6fe9431c5fa3c03d9d758dfb5ffa4f Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Tue, 26 Mar 2019 15:41:19 +0100 Subject: [PATCH 28/39] =?UTF-8?q?Fix=20#174,=20#177=20-=20modules=20li?= =?UTF-8?q?=C3=A9s=20par=20leurs=20r=C3=A9sultats:=20calcul=20en=20cha?= =?UTF-8?q?=C3=AEne=20de=20l'aval=20vers=20l'amont?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- e2e/clone-calc.e2e-spec.ts | 3 -- .../base-param-input.component.ts | 2 +- .../fixedvar-results.component.ts | 1 + .../param-values/param-values.component.ts | 2 +- .../definition/concrete/form-courbe-remous.ts | 3 ++ .../concrete/form-lechapt-calmon.ts | 3 ++ .../concrete/form-parallel-structures.ts | 3 ++ .../concrete/form-regime-uniforme.ts | 3 ++ .../concrete/form-section-parametree.ts | 3 ++ .../definition/form-compute-courbe-remous.ts | 20 ++++++-- .../definition/form-compute-fixedvar.ts | 18 ++++--- .../form-compute-section-parametree.ts | 19 +++++--- src/app/formulaire/definition/form-compute.ts | 48 ++++++++++++++++--- .../form-def-parallel-structures.ts | 4 -- .../formulaire/definition/form-definition.ts | 31 +++++++++++- src/app/formulaire/fieldset.ts | 3 -- src/app/formulaire/ngparam.ts | 16 +++++-- 17 files changed, 140 insertions(+), 42 deletions(-) diff --git a/e2e/clone-calc.e2e-spec.ts b/e2e/clone-calc.e2e-spec.ts index 459b3d767..dab35d149 100644 --- a/e2e/clone-calc.e2e-spec.ts +++ b/e2e/clone-calc.e2e-spec.ts @@ -2,7 +2,6 @@ import { AppPage } from "./app.po"; import { ListPage } from "./list.po"; import { CalculatorPage } from "./calculator.po"; import { Navbar } from "./navbar.po"; -import { SideNav } from "./sidenav.po"; import { browser } from "protractor"; /** @@ -13,14 +12,12 @@ describe("ngHyd − clone a calculator", () => { let listPage: ListPage; let calcPage: CalculatorPage; let navbar: Navbar; - let sidenav: SideNav; beforeEach(() => { startPage = new AppPage(); listPage = new ListPage(); calcPage = new CalculatorPage(); navbar = new Navbar(); - sidenav = new SideNav(); }); it("when cloning a calculator, the clone should have the same values for all parameters", async () => { 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 index e04b0a460..001a186d7 100644 --- a/src/app/components/base-param-input/base-param-input.component.ts +++ b/src/app/components/base-param-input/base-param-input.component.ts @@ -75,7 +75,7 @@ export class NgBaseParam extends Observable { valid = true; } catch (e) { if (e instanceof Message) { - // @TODO ici au début le service de localisation n'a pas encore chargé ses messages… + // ici au début le service de localisation n'a pas encore chargé ses messages… msg = ServiceFactory.instance.i18nService.localizeMessage(e); } else { msg = "invalid value"; diff --git a/src/app/components/fixedvar-results/fixedvar-results.component.ts b/src/app/components/fixedvar-results/fixedvar-results.component.ts index d6dca7a41..3392fb698 100644 --- a/src/app/components/fixedvar-results/fixedvar-results.component.ts +++ b/src/app/components/fixedvar-results/fixedvar-results.component.ts @@ -98,6 +98,7 @@ export class FixedVarResultsComponent implements DoCheck { this.resultsGraphComponent.results = undefined; } + // set _doUpdate flag so that results are rebuilt on the next Angular display cycle this._doUpdate = false; if (this._fixedResults !== undefined) { this._doUpdate = this._fixedResults.hasResults || this._fixedResults.hasLog; diff --git a/src/app/components/param-values/param-values.component.ts b/src/app/components/param-values/param-values.component.ts index 07a32d455..95c9e3c71 100644 --- a/src/app/components/param-values/param-values.component.ts +++ b/src/app/components/param-values/param-values.component.ts @@ -63,7 +63,7 @@ export class ParamValuesComponent implements AfterViewInit, Observer { this.openDialog(); }); } - // subscribe to parameter values change (through dialog actions) @TODO draft + // subscribe to parameter values change (through dialog actions) this.param.addObserver(this); } diff --git a/src/app/formulaire/definition/concrete/form-courbe-remous.ts b/src/app/formulaire/definition/concrete/form-courbe-remous.ts index 4e96da330..99be68efb 100644 --- a/src/app/formulaire/definition/concrete/form-courbe-remous.ts +++ b/src/app/formulaire/definition/concrete/form-courbe-remous.ts @@ -49,6 +49,9 @@ export class FormulaireCourbeRemous extends FormulaireBase { // interface Observer update(sender: IObservable, data: any) { + + super.update(sender, data); + if (sender instanceof FieldSet && data.action === "propertyChange") { switch (sender.id) { case "fs_section": diff --git a/src/app/formulaire/definition/concrete/form-lechapt-calmon.ts b/src/app/formulaire/definition/concrete/form-lechapt-calmon.ts index c84864baa..db2991206 100644 --- a/src/app/formulaire/definition/concrete/form-lechapt-calmon.ts +++ b/src/app/formulaire/definition/concrete/form-lechapt-calmon.ts @@ -26,6 +26,9 @@ export class FormulaireLechaptCalmon extends FormulaireBase implements Observer // interface Observer public update(sender: any, data: any) { + + super.update(sender, data); + // en cas de changement de valeur du select de matériau, effacement des résultats et MAJ des champs L,M,N if (sender instanceof SelectField) { if (data.action === "select") { diff --git a/src/app/formulaire/definition/concrete/form-parallel-structures.ts b/src/app/formulaire/definition/concrete/form-parallel-structures.ts index d71119c87..ec840a970 100644 --- a/src/app/formulaire/definition/concrete/form-parallel-structures.ts +++ b/src/app/formulaire/definition/concrete/form-parallel-structures.ts @@ -338,6 +338,9 @@ export class FormulaireParallelStructure extends FormulaireBase { // interface Observer public update(sender: any, data: any) { + + super.update(sender, data); + if (sender instanceof FieldsetContainer) { switch (data.action) { case "newFieldset": diff --git a/src/app/formulaire/definition/concrete/form-regime-uniforme.ts b/src/app/formulaire/definition/concrete/form-regime-uniforme.ts index 35a08225c..503bdaba7 100644 --- a/src/app/formulaire/definition/concrete/form-regime-uniforme.ts +++ b/src/app/formulaire/definition/concrete/form-regime-uniforme.ts @@ -33,6 +33,9 @@ export class FormulaireRegimeUniforme extends FormulaireBase implements Observer // interface Observer update(sender: IObservable, data: any) { + + super.update(sender, data); + // changement de propriété du FieldSet contenant le select de choix du type de section if (sender instanceof FieldSet && sender.id === "fs_section" && data.action === "propertyChange") { this.replaceCurrentNub(sender.properties); diff --git a/src/app/formulaire/definition/concrete/form-section-parametree.ts b/src/app/formulaire/definition/concrete/form-section-parametree.ts index 9c48c038b..1a3ef62b1 100644 --- a/src/app/formulaire/definition/concrete/form-section-parametree.ts +++ b/src/app/formulaire/definition/concrete/form-section-parametree.ts @@ -31,6 +31,9 @@ export class FormulaireSectionParametree extends FormulaireBase { // interface Observer update(sender: IObservable, data: any) { + + super.update(sender, data); + // changement de propriété du FieldSet contenant le select de choix du type de section if (sender instanceof FieldSet && data.action === "propertyChange") { switch (sender.id) { diff --git a/src/app/formulaire/definition/form-compute-courbe-remous.ts b/src/app/formulaire/definition/form-compute-courbe-remous.ts index dc3a6a2e2..b69986e83 100644 --- a/src/app/formulaire/definition/form-compute-courbe-remous.ts +++ b/src/app/formulaire/definition/form-compute-courbe-remous.ts @@ -7,6 +7,11 @@ import { FormCompute } from "./form-compute"; import { FormResultRemous } from "./form-result-remous"; export class FormComputeCourbeRemous extends FormCompute { + + private resultYn: Result; + + private resultYc: Result; + constructor(formBase: FormulaireDefinition, private _formSection: FormDefSection, formResult: FormResultRemous) { super(formBase, formResult); } @@ -21,8 +26,15 @@ export class FormComputeCourbeRemous extends FormCompute { const prmCR: CourbeRemousParams = cr.prms as CourbeRemousParams; const sect: acSection = prmCR.Sn; - const Yn: Result = sect.Calc("Yn"); // hauteur normale - const Yc: Result = sect.Calc("Yc"); // hauteur critique + this.resultYn = sect.Calc("Yn"); // hauteur normale + this.resultYc = sect.Calc("Yc"); // hauteur critique + + this.reaffectResultComponents(); + } + + protected reaffectResultComponents() { + const cr: CourbeRemous = this._formBase.currentNub as CourbeRemous; + const prmCR: CourbeRemousParams = cr.prms as CourbeRemousParams; this.remousResults.parameters = prmCR; @@ -33,8 +45,8 @@ export class FormComputeCourbeRemous extends FormCompute { this.remousResults.result = cr.calculRemous(this.remousResults.extraParamSymbol); // données du graphe - this.remousResults.hauteurNormale = Yn.resultElement; - this.remousResults.hauteurCritique = Yc.resultElement; + this.remousResults.hauteurNormale = this.resultYn.resultElement; + this.remousResults.hauteurCritique = this.resultYc.resultElement; if (this.remousResults.extraParamSymbol) { this.remousResults.extraGraph = ["Hs", "Hsc", "Yf", "Yt", "Yco"].indexOf(this.remousResults.extraParamSymbol) === -1; } else { diff --git a/src/app/formulaire/definition/form-compute-fixedvar.ts b/src/app/formulaire/definition/form-compute-fixedvar.ts index 151b875bf..616899160 100644 --- a/src/app/formulaire/definition/form-compute-fixedvar.ts +++ b/src/app/formulaire/definition/form-compute-fixedvar.ts @@ -1,4 +1,4 @@ -import { Nub, Result, ComputeNode, ParamValueMode } from "jalhyd"; +import { Nub, Result, ComputeNode } from "jalhyd"; import { FormCompute } from "./form-compute"; import { NgParameter, ParamRadioConfig } from "../ngparam"; @@ -45,22 +45,28 @@ export class FormComputeFixedVar extends FormCompute { protected compute() { const nub: Nub = this._formBase.currentNub; const computedParam: NgParameter = this.getComputedParameter(); + + const res: Result = this.runNubCalc(nub, computedParam); + + this.reaffectResultComponents(); + } + + protected reaffectResultComponents() { + const nub: Nub = this._formBase.currentNub; + const computedParam: NgParameter = this.getComputedParameter(); this.formResult.addFixedParameters(); const varParam: NgParameter = this.getVariatedParameter(); if (varParam === undefined) { // pas de paramètre à varier - const res: Result = this.runNubCalc(nub, computedParam); - this.formResult.fixedResults.result = res; + this.formResult.fixedResults.result = nub.result; this.formResult.fixedResults.calculatedParameter = computedParam; } else { // il y a un paramètre à varier - const res: Result = this.runNubCalc(nub, computedParam); - this.formResult.varResults.variatedParameter = varParam; this.formResult.varResults.calculatedParameter = computedParam; - this.formResult.varResults.result = res; + this.formResult.varResults.result = nub.result; this.formResult.varResults.update(false); } } diff --git a/src/app/formulaire/definition/form-compute-section-parametree.ts b/src/app/formulaire/definition/form-compute-section-parametree.ts index fc41974d9..068dce9d2 100644 --- a/src/app/formulaire/definition/form-compute-section-parametree.ts +++ b/src/app/formulaire/definition/form-compute-section-parametree.ts @@ -12,6 +12,8 @@ import { FormulaireNode } from "../formulaire-node"; export class FormComputeSectionParametree extends FormCompute { + private tmpResult: Result; + constructor(formBase: FormulaireDefinition, private _formSection: FormDefSection, formResult: FormResult) { super(formBase, formResult); } @@ -62,20 +64,25 @@ export class FormComputeSectionParametree extends FormCompute { const sectNub: SectionParametree = this._formBase.currentNub as SectionParametree; - const sect: acSection = sectNub.section; - this._sectionResults.section = sect; - - const tmpResult: Result = sectNub.CalcSerie( + this.tmpResult = sectNub.CalcSerie( undefined, // valeur initiale, non utilisée dans ce cas undefined // variable à calculer, non utilisée ); + this.reaffectResultComponents(); + } + + protected reaffectResultComponents() { + const sectNub: SectionParametree = this._formBase.currentNub as SectionParametree; + const sect: acSection = sectNub.section; + this._sectionResults.section = sect; + // résultats de section (avec le graphique de section) - this._sectionResults.result = tmpResult; + this._sectionResults.result = this.tmpResult; // résultats complémentaires des paramètres fixés this._formSectionResult.addSectionFixedParameters(false); - this._formSectionResult.fixedResults.result = tmpResult; + this._formSectionResult.fixedResults.result = this.tmpResult; } /** diff --git a/src/app/formulaire/definition/form-compute.ts b/src/app/formulaire/definition/form-compute.ts index 4e8494753..d1e848b28 100644 --- a/src/app/formulaire/definition/form-compute.ts +++ b/src/app/formulaire/definition/form-compute.ts @@ -1,11 +1,14 @@ -import { Nub, Result, ParamDomainValue } from "jalhyd"; +import { Nub, Result, ParamDomainValue, Observer } from "jalhyd"; import { FormResult } from "./form-result"; import { FormulaireDefinition } from "./form-definition"; import { NgParameter } from "../ngparam"; -export abstract class FormCompute { +export abstract class FormCompute implements Observer { + constructor(protected _formBase: FormulaireDefinition, protected _formResult: FormResult) { + // indirectly subscribe to Nub result updates + this._formBase.addObserver(this); } protected abstract compute(); @@ -23,14 +26,25 @@ export abstract class FormCompute { } /** - * lance le calcul d'un paramètre en déterminant une valeur initiale + * Copies current Nub result into result components for display on page. + * Should be called every time the Nub result changes + */ + protected abstract reaffectResultComponents(); + + /** + * Lance le calcul d'un paramètre en déterminant une valeur initiale. + * Si nécessaire déclenche un calcul en chaîne des modules en amont. */ protected runNubCalc(nub: Nub, computedParam: NgParameter): Result { let init: number; + // require chain computation; redundant with Nub.CalcSerie but required + // to get initial value here... + const computedParamValue = computedParam.getValue(true); + switch (computedParam.domain.domain) { case ParamDomainValue.ANY: if (computedParam && computedParam.isDefined) { - init = computedParam.getValue(); + init = computedParamValue; } if (init === undefined) { init = 0; @@ -39,7 +53,7 @@ export abstract class FormCompute { case ParamDomainValue.POS_NULL: if (computedParam && computedParam.isDefined) { - init = Math.max(computedParam.getValue(), 0); + init = Math.max(computedParamValue, 0); } if (init === undefined) { init = 0; @@ -52,7 +66,7 @@ export abstract class FormCompute { case ParamDomainValue.NOT_NULL: if (computedParam && computedParam.isDefined) { - init = computedParam.getValue(); + init = computedParamValue; } if (init === undefined || init === 0) { init = 1e-8; @@ -61,7 +75,7 @@ export abstract class FormCompute { case ParamDomainValue.POS: if (computedParam && computedParam.isDefined) { - init = Math.max(computedParam.getValue(), 1e-8); + init = Math.max(computedParamValue, 1e-8); } if (init === undefined) { init = 1e-8; @@ -72,6 +86,9 @@ export abstract class FormCompute { return nub.CalcSerie(init, this.getParameterRefid(computedParam)); } + /** + * Triggers computation of the Nub, updates form results + */ public doCompute() { this._formResult.resetResults(); @@ -81,4 +98,21 @@ export abstract class FormCompute { "action": "resultsUpdated", }, this._formBase); } + + // interface Observer + + public update(sender: any, data: any): void { + if (sender instanceof Nub) { + switch (data.action) { + case "nubResultUpdated": + // forward Nub results update notification to FormCompute objects + this.reaffectResultComponents(); + /* console.log("_____forwarding 2"); + this._formBase.notifyObservers({ + "action": "resultsUpdated", + }, this._formBase); */ + break; + } + } + } } diff --git a/src/app/formulaire/definition/form-def-parallel-structures.ts b/src/app/formulaire/definition/form-def-parallel-structures.ts index a4856994d..5206d9cc0 100644 --- a/src/app/formulaire/definition/form-def-parallel-structures.ts +++ b/src/app/formulaire/definition/form-def-parallel-structures.ts @@ -1,7 +1,3 @@ -import { CalculatorType, StructureType, LoiDebit } from "jalhyd"; - -import { FieldSet } from "../fieldset"; - /** * gestion des formulaires "ouvrages parallèles" */ diff --git a/src/app/formulaire/definition/form-definition.ts b/src/app/formulaire/definition/form-definition.ts index 4d14b15b7..daa57be19 100644 --- a/src/app/formulaire/definition/form-definition.ts +++ b/src/app/formulaire/definition/form-definition.ts @@ -1,4 +1,4 @@ -import { CalculatorType, ComputeNodeType, Nub, Props, Observer, Session, ParallelStructure } from "jalhyd"; +import { CalculatorType, ComputeNodeType, Nub, Props, Observer, Session } from "jalhyd"; import { FormulaireElement } from "../formulaire-element"; import { NgParameter, ParamRadioConfig } from "../ngparam"; @@ -94,7 +94,7 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs } public initNub(props?: Props) { - this._currentNub = this.createNub(props ? props : new Props(this.defaultProperties)); + this.currentNub = this.createNub(props ? props : new Props(this.defaultProperties)); } public get currentNub(): Nub { @@ -108,7 +108,15 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs `Nub ${n.properties["calcType"]} incompatible avec le formulaire ${this._calculatorName} (${this._props["calcType"]})` ); } + // unsubscribe from old Nub + if (this._currentNub) { + this._currentNub.removeObserver(this); + } + // replace Nub this._currentNub = n; + // subscribe to new Nub (for result updates) + console.log("SET CURRENT NUB -- (re)subscribe to Nub", this._currentNub.uid); + this._currentNub.addObserver(this); } /** @@ -351,6 +359,16 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs }, this); } + /** + * Forwards Nub's result updated notification. + * Used by FormCompute to update results display + */ + protected notifyNubResultUpdated(sender) { + this.notifyObservers({ + action: "nubResultUpdated" + }, sender); + } + /** * réinitialisation du formulaire suite à un changement d'une valeur, d'une option, ... : * effacement des résultats, application des dépendances, ... @@ -469,5 +487,14 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs // interface Observer public update(sender: any, data: any) { + console.log("--- FormDefinition received update", sender.constructor.name, data); + if (sender instanceof Nub) { + switch (data.action) { + case "resultUpdated": + // forward Nub results update notification to FormCompute objects + this.notifyNubResultUpdated(sender); + break; + } + } } } diff --git a/src/app/formulaire/fieldset.ts b/src/app/formulaire/fieldset.ts index ffa32a38d..ff2789eb3 100644 --- a/src/app/formulaire/fieldset.ts +++ b/src/app/formulaire/fieldset.ts @@ -133,9 +133,6 @@ export class FieldSet extends FormulaireElement implements Observer { if (res) { res.parseConfig(json, { "radioConfig": default_radio_config }); - // set parent Nub on Parameter to ensure UID availability - // should always be done @TODO check - // res.paramDefinition.parent = this._nub; } return res; diff --git a/src/app/formulaire/ngparam.ts b/src/app/formulaire/ngparam.ts index 809b9d1f7..10ed51962 100644 --- a/src/app/formulaire/ngparam.ts +++ b/src/app/formulaire/ngparam.ts @@ -51,7 +51,6 @@ export class NgParameter extends InputField implements Observer { /** * Returns a text preview of the current value(s), depending on the value mode - * @TODO use display precision to limit decimals */ public static preview(p: ParamDefinition): string { let valuePreview: string; @@ -107,7 +106,12 @@ export class NgParameter extends InputField implements Observer { return v.toFixed(nDigits); }).slice(0, 5).join("; ") + "…"; } else { - valuePreview = String(p.referencedValue.nub.result.vCalc.toFixed(nDigits)); + const vCalc = p.referencedValue.nub.result.vCalc; + if (vCalc) { + valuePreview = String(vCalc.toFixed(nDigits)); + } else { + throw new Error("NgParameter.preview() : No vCalc for computed target Nub !"); + } } } else { valuePreview = i18n.localizeText("INFO_PARAMFIELD_IN_CALCULATION"); @@ -120,7 +124,6 @@ export class NgParameter extends InputField implements Observer { // was the result already computed ? try { const remoteValues = p.referencedValue.getParamValues(); - // @TODO is the computed value fresh or stale ? if (p.referencedValue.hasMultipleValues()) { // like LIST mode valuePreview = i18n.localizeText("INFO_PARAMFIELD_PARAMVARIER_VALUES"); @@ -269,8 +272,11 @@ export class NgParameter extends InputField implements Observer { throw new Error("invalid parameter radio configuration " + s); } - public getValue() { - return this._paramDef.v; + /** + * Asks the ParamDefinition for its current value + */ + public getValue(triggerChainComputation: boolean = false) { + return this._paramDef.getValue(triggerChainComputation); } /** -- GitLab From 2e519f7710185e4c7706cdfeee532d0ed990640e Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Tue, 26 Mar 2019 17:26:01 +0100 Subject: [PATCH 29/39] Removed debug messages; worked on notifications for chained computation --- src/app/app.component.ts | 14 ++++---------- .../calculator.component.ts | 2 +- src/app/formulaire/definition/form-compute.ts | 19 +++++++++++++++---- .../formulaire/definition/form-definition.ts | 2 -- .../services/formulaire/formulaire.service.ts | 2 +- src/app/services/service-factory.ts | 3 +++ src/locale/messages.en.json | 1 + src/locale/messages.fr.json | 1 + 8 files changed, 26 insertions(+), 18 deletions(-) diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 4e9c48e53..e12e52603 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -18,6 +18,7 @@ import { nghydDateRev } from "../date_revision"; import { DialogConfirmEmptySessionComponent } from "./components/dialog-confirm-empty-session/dialog-confirm-empty-session.component"; import { DialogLoadSessionComponent } from "./components/dialog-load-session/dialog-load-session.component"; import { DialogSaveSessionComponent } from "./components/dialog-save-session/dialog-save-session.component"; +import { NotificationsService } from "./services/notifications/notifications.service"; @Component({ @@ -66,6 +67,7 @@ export class AppComponent implements OnInit, OnDestroy, Observer { private router: Router, private formulaireService: FormulaireService, private httpService: HttpService, + private notificationsService: NotificationsService, private confirmEmptySessionDialog: MatDialog, private saveSessionDialog: MatDialog, private loadSessionDialog: MatDialog, @@ -76,6 +78,7 @@ export class AppComponent implements OnInit, OnDestroy, Observer { ServiceFactory.instance.applicationSetupService = appSetupService; ServiceFactory.instance.i18nService = intlService; ServiceFactory.instance.formulaireService = formulaireService; + ServiceFactory.instance.notificationsService = notificationsService; this.router.events.subscribe((event: Event) => { // close side navigation when clicking a calculator tab @@ -217,16 +220,7 @@ export class AppComponent implements OnInit, OnDestroy, Observer { // interface Observer update(sender: any, data: any): void { - if (sender instanceof ErrorService) { - // on ouvre un dialogue avec le message d'erreur reçu - // if (this._displayErrorDialog) { - // let dialogRef = this.dialog.open(AlertDialog); - // let ad: AlertDialog = dialogRef.componentInstance; - // ad.text = String(data); - // } - // else - console.log(data); - } else if (sender instanceof FormulaireService) { + if (sender instanceof FormulaireService) { switch (data["action"]) { case "createForm": // add newly created form to calculators list diff --git a/src/app/components/generic-calculator/calculator.component.ts b/src/app/components/generic-calculator/calculator.component.ts index c6c9afed1..d385c1f60 100644 --- a/src/app/components/generic-calculator/calculator.component.ts +++ b/src/app/components/generic-calculator/calculator.component.ts @@ -164,7 +164,6 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit, } ngDoCheck() { - console.log(">>> UI validity", this._isUIValid); this.isCalculateDisabled = ! this._isUIValid; } @@ -203,6 +202,7 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit, this._formulaire.onRadioClick(this._pendingRadioClickInfo); this._pendingRadioClickInfo = undefined; } + // @TODO call this._isUIValid here ? } public onCloseForm() { diff --git a/src/app/formulaire/definition/form-compute.ts b/src/app/formulaire/definition/form-compute.ts index d1e848b28..9a32be715 100644 --- a/src/app/formulaire/definition/form-compute.ts +++ b/src/app/formulaire/definition/form-compute.ts @@ -3,12 +3,22 @@ import { Nub, Result, ParamDomainValue, Observer } from "jalhyd"; import { FormResult } from "./form-result"; import { FormulaireDefinition } from "./form-definition"; import { NgParameter } from "../ngparam"; +import { NotificationsService } from "../../services/notifications/notifications.service"; +import { ServiceFactory } from "../../services/service-factory"; +import { I18nService } from "../../services/internationalisation/internationalisation.service"; export abstract class FormCompute implements Observer { + private notificationsService: NotificationsService; + + private intlService: I18nService; + constructor(protected _formBase: FormulaireDefinition, protected _formResult: FormResult) { // indirectly subscribe to Nub result updates this._formBase.addObserver(this); + + this.notificationsService = ServiceFactory.instance.notificationsService; + this.intlService = ServiceFactory.instance.i18nService; } protected abstract compute(); @@ -107,10 +117,11 @@ export abstract class FormCompute implements Observer { case "nubResultUpdated": // forward Nub results update notification to FormCompute objects this.reaffectResultComponents(); - /* console.log("_____forwarding 2"); - this._formBase.notifyObservers({ - "action": "resultsUpdated", - }, this._formBase); */ + // @TODO reenable later wen chain computation is executed only once or it is a snackbar hell ! + /* this.notificationsService.notify( + this.intlService.localizeText("INFO_SNACKBAR_RESULTS_CALCULATED") + " " + this._formBase.calculatorName, + 1500 + ); */ break; } } diff --git a/src/app/formulaire/definition/form-definition.ts b/src/app/formulaire/definition/form-definition.ts index daa57be19..be1369a87 100644 --- a/src/app/formulaire/definition/form-definition.ts +++ b/src/app/formulaire/definition/form-definition.ts @@ -115,7 +115,6 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs // replace Nub this._currentNub = n; // subscribe to new Nub (for result updates) - console.log("SET CURRENT NUB -- (re)subscribe to Nub", this._currentNub.uid); this._currentNub.addObserver(this); } @@ -487,7 +486,6 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs // interface Observer public update(sender: any, data: any) { - console.log("--- FormDefinition received update", sender.constructor.name, data); if (sender instanceof Nub) { switch (data.action) { case "resultUpdated": diff --git a/src/app/services/formulaire/formulaire.service.ts b/src/app/services/formulaire/formulaire.service.ts index 367b8d5b7..79f728dcb 100644 --- a/src/app/services/formulaire/formulaire.service.ts +++ b/src/app/services/formulaire/formulaire.service.ts @@ -616,7 +616,7 @@ export class FormulaireService extends Observable { if (notify) { this.notificationsService.notify( this.intlService.localizeText("INFO_SNACKBAR_RESULTS_INVALIDATED") + " " + form.calculatorName, - 2000 + 1500 ); } } diff --git a/src/app/services/service-factory.ts b/src/app/services/service-factory.ts index 0627bdf99..838a00cfc 100644 --- a/src/app/services/service-factory.ts +++ b/src/app/services/service-factory.ts @@ -2,6 +2,7 @@ import { ApplicationSetupService } from "./app-setup/app-setup.service"; import { FormulaireService } from "./formulaire/formulaire.service"; import { I18nService } from "./internationalisation/internationalisation.service"; import { HttpService } from "./http/http.service"; +import { NotificationsService } from "./notifications/notifications.service"; export class ServiceFactory { private static _instance: ServiceFactory; // instance pour le pattern singleton @@ -16,6 +17,8 @@ export class ServiceFactory { public httpService: HttpService; + public notificationsService: NotificationsService; + public static get instance() { if (ServiceFactory._instance === undefined) { ServiceFactory._instance = new ServiceFactory(); diff --git a/src/locale/messages.en.json b/src/locale/messages.en.json index 859d160ba..beb07be9f 100644 --- a/src/locale/messages.en.json +++ b/src/locale/messages.en.json @@ -204,6 +204,7 @@ "INFO_SETUP_PRECISION_AFFICHAGE": "Display accuracy", "INFO_SETUP_PRECISION_CALCUL": "Computation accuracy", "INFO_SETUP_TITLE": "Application setup", + "INFO_SNACKBAR_RESULTS_CALCULATED": "Results calculated for", "INFO_SNACKBAR_RESULTS_INVALIDATED": "Results invalidated for", "INFO_SNACKBAR_SETTINGS_SAVED": "Settings saved on this device", "INFO_SNACKBAR_DEFAULT_SETTINGS_RESTORED": "Default settings restored", diff --git a/src/locale/messages.fr.json b/src/locale/messages.fr.json index 350dd11ad..2dddd1782 100644 --- a/src/locale/messages.fr.json +++ b/src/locale/messages.fr.json @@ -204,6 +204,7 @@ "INFO_SETUP_PRECISION_AFFICHAGE": "Précision d'affichage", "INFO_SETUP_PRECISION_CALCUL": "Précision de calcul", "INFO_SETUP_TITLE": "Paramètres de l'application", + "INFO_SNACKBAR_RESULTS_CALCULATED": "Résultats calculés pour", "INFO_SNACKBAR_RESULTS_INVALIDATED": "Résultats invalidés pour", "INFO_SNACKBAR_SETTINGS_SAVED": "Paramètres enregistrés sur cet appareil", "INFO_SNACKBAR_DEFAULT_SETTINGS_RESTORED": "Paramètres par défaut restaurés", -- GitLab From bc36bc597496d58e9cb8f0dc03193d29df14fd70 Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Wed, 27 Mar 2019 09:30:01 +0100 Subject: [PATCH 30/39] =?UTF-8?q?Suppression=20code=20inutilis=C3=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/formulaire/definition/form-compute.ts | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/app/formulaire/definition/form-compute.ts b/src/app/formulaire/definition/form-compute.ts index 9a32be715..3e5683d6e 100644 --- a/src/app/formulaire/definition/form-compute.ts +++ b/src/app/formulaire/definition/form-compute.ts @@ -3,22 +3,12 @@ import { Nub, Result, ParamDomainValue, Observer } from "jalhyd"; import { FormResult } from "./form-result"; import { FormulaireDefinition } from "./form-definition"; import { NgParameter } from "../ngparam"; -import { NotificationsService } from "../../services/notifications/notifications.service"; -import { ServiceFactory } from "../../services/service-factory"; -import { I18nService } from "../../services/internationalisation/internationalisation.service"; export abstract class FormCompute implements Observer { - private notificationsService: NotificationsService; - - private intlService: I18nService; - constructor(protected _formBase: FormulaireDefinition, protected _formResult: FormResult) { // indirectly subscribe to Nub result updates this._formBase.addObserver(this); - - this.notificationsService = ServiceFactory.instance.notificationsService; - this.intlService = ServiceFactory.instance.i18nService; } protected abstract compute(); @@ -117,11 +107,6 @@ export abstract class FormCompute implements Observer { case "nubResultUpdated": // forward Nub results update notification to FormCompute objects this.reaffectResultComponents(); - // @TODO reenable later wen chain computation is executed only once or it is a snackbar hell ! - /* this.notificationsService.notify( - this.intlService.localizeText("INFO_SNACKBAR_RESULTS_CALCULATED") + " " + this._formBase.calculatorName, - 1500 - ); */ break; } } -- GitLab From 8f2a171536854bd85f2b4d7afcee3db39c1241fd Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Wed, 27 Mar 2019 11:07:38 +0100 Subject: [PATCH 31/39] Fix #183 --- src/app/formulaire/ngparam.ts | 4 +++- src/locale/messages.en.json | 1 + src/locale/messages.fr.json | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/app/formulaire/ngparam.ts b/src/app/formulaire/ngparam.ts index 10ed51962..9d9ce7c9c 100644 --- a/src/app/formulaire/ngparam.ts +++ b/src/app/formulaire/ngparam.ts @@ -98,6 +98,7 @@ export class NgParameter extends InputField implements Observer { // calculated param ? if (targetParam.valueMode === ParamValueMode.CALCUL) { // was the result already computed ? + // @WAARNING .result might be set but the computation might have failed (dichotomy for ex.) if (p.referencedValue.nub.result) { if (p.referencedValue.hasMultipleValues()) { // like LIST mode @@ -110,7 +111,8 @@ export class NgParameter extends InputField implements Observer { if (vCalc) { valuePreview = String(vCalc.toFixed(nDigits)); } else { - throw new Error("NgParameter.preview() : No vCalc for computed target Nub !"); + // computation has been run but has failed + valuePreview = i18n.localizeText("INFO_PARAMFIELD_CALCULATION_FAILED"); } } } else { diff --git a/src/locale/messages.en.json b/src/locale/messages.en.json index beb07be9f..d4e1a6420 100644 --- a/src/locale/messages.en.json +++ b/src/locale/messages.en.json @@ -159,6 +159,7 @@ "INFO_PARAMFIELD_GRAPH_TYPE_HISTOGRAM": "Histogram", "INFO_PARAMFIELD_GRAPH_SELECT_X_AXIS": "Variable for X axis", "INFO_PARAMFIELD_GRAPH_SELECT_Y_AXIS": "Variable for Y axis", + "INFO_PARAMFIELD_CALCULATION_FAILED": "Calculation failed", "INFO_PARAMFIELD_IN_CALCULATION": "In calculation", "INFO_PARAMFIELD_IN_CALCULATION_INITIAL_VALUE": "initial value", "INFO_PARAMFIELD_PARAMCALCULER": "Calculate", diff --git a/src/locale/messages.fr.json b/src/locale/messages.fr.json index 2dddd1782..8627ade07 100644 --- a/src/locale/messages.fr.json +++ b/src/locale/messages.fr.json @@ -159,6 +159,7 @@ "INFO_PARAMFIELD_GRAPH_TYPE_HISTOGRAM": "Histogramme", "INFO_PARAMFIELD_GRAPH_SELECT_X_AXIS": "Variable en abscisse", "INFO_PARAMFIELD_GRAPH_SELECT_Y_AXIS": "Variable en ordonnée", + "INFO_PARAMFIELD_CALCULATION_FAILED": "Échec du calcul", "INFO_PARAMFIELD_IN_CALCULATION": "En calcul", "INFO_PARAMFIELD_IN_CALCULATION_INITIAL_VALUE": "valeur initiale", "INFO_PARAMFIELD_PARAMCALCULER": "calculer", -- GitLab From cc93de0da3ffe37abfff909c7c1dfdf358a331eb Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Wed, 27 Mar 2019 11:17:05 +0100 Subject: [PATCH 32/39] =?UTF-8?q?R=C3=A9sultat=20=C3=A0=20l'=C3=A9cran:=20?= =?UTF-8?q?=C3=A9vite=20d'ajouter=20plusieurs=20fois=20les=20param=C3=A8tr?= =?UTF-8?q?es=20fix=C3=A9s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/formulaire/definition/form-compute-fixedvar.ts | 1 + src/app/formulaire/definition/form-compute.ts | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/app/formulaire/definition/form-compute-fixedvar.ts b/src/app/formulaire/definition/form-compute-fixedvar.ts index 616899160..873812579 100644 --- a/src/app/formulaire/definition/form-compute-fixedvar.ts +++ b/src/app/formulaire/definition/form-compute-fixedvar.ts @@ -54,6 +54,7 @@ export class FormComputeFixedVar extends FormCompute { protected reaffectResultComponents() { const nub: Nub = this._formBase.currentNub; const computedParam: NgParameter = this.getComputedParameter(); + this.formResult.resetResults(); // to avoid adding fixed parameters more than once (see below) this.formResult.addFixedParameters(); const varParam: NgParameter = this.getVariatedParameter(); diff --git a/src/app/formulaire/definition/form-compute.ts b/src/app/formulaire/definition/form-compute.ts index 3e5683d6e..a9fb302a1 100644 --- a/src/app/formulaire/definition/form-compute.ts +++ b/src/app/formulaire/definition/form-compute.ts @@ -27,7 +27,8 @@ export abstract class FormCompute implements Observer { /** * Copies current Nub result into result components for display on page. - * Should be called every time the Nub result changes + * Should be called every time the Nub result changes. + * Must be idempotent. */ protected abstract reaffectResultComponents(); -- GitLab From 9ce295b75e665db26aa6fa1f74f8f98f5ac968a6 Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Wed, 27 Mar 2019 13:59:49 +0100 Subject: [PATCH 33/39] =?UTF-8?q?Correction=20bug=20passage=20du=20mode=20?= =?UTF-8?q?LI=C3=89=20au=20mode=20CALC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/generic-calculator/calculator.component.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/app/components/generic-calculator/calculator.component.ts b/src/app/components/generic-calculator/calculator.component.ts index d385c1f60..2635777d6 100644 --- a/src/app/components/generic-calculator/calculator.component.ts +++ b/src/app/components/generic-calculator/calculator.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit, DoCheck, OnDestroy, ViewChild, ViewChildren, QueryList, AfterViewChecked } from "@angular/core"; import { ActivatedRoute, Router } from "@angular/router"; -import { Observer, Session } from "jalhyd"; +import { Observer, Session, ParamValueMode } from "jalhyd"; import { FormulaireService } from "../../services/formulaire/formulaire.service"; import { I18nService } from "../../services/internationalisation/internationalisation.service"; @@ -191,7 +191,9 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit, * gestion des événements clic sur les radios */ public onRadioClick(info: any) { - this.updateLinkedParameters(); + if (info.param.valueMode === ParamValueMode.LINK) { + this.updateLinkedParameters(); // only when switching to LINK mode + } this._pendingRadioClick = true; this._pendingRadioClickInfo = info; } -- GitLab From 95d14ff0d525c06d8c326e26ee1a4757a97f659a Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Wed, 27 Mar 2019 14:08:43 +0100 Subject: [PATCH 34/39] Fix #168 --- src/app/formulaire/definition/form-def-paramcalc.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/formulaire/definition/form-def-paramcalc.ts b/src/app/formulaire/definition/form-def-paramcalc.ts index ac743a1ff..230a3257c 100644 --- a/src/app/formulaire/definition/form-def-paramcalc.ts +++ b/src/app/formulaire/definition/form-def-paramcalc.ts @@ -79,7 +79,7 @@ export class FormDefParamToCalculate extends FormDefFixedVar { case ParamValueMode.LINK: // nouvel état if (sourceParam.paramDefinition.hasMultipleValues) { super.resetOtherRadio(sourceParam); - this.setDefault(); + this.setDefault(sourceParam); } else { // mode du paramètre référencé const refValue = sourceParam.paramDefinition.referencedValue; @@ -89,7 +89,7 @@ export class FormDefParamToCalculate extends FormDefFixedVar { case ParamValueMode.LISTE: case ParamValueMode.CALCUL: super.resetOtherRadio(sourceParam); - this.setDefault(); + this.setDefault(sourceParam); break; case ParamValueMode.LINK: -- GitLab From 8ad77bade6f05acdc9e1ab268443aadae3da4829 Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Wed, 27 Mar 2019 16:13:53 +0100 Subject: [PATCH 35/39] =?UTF-8?q?Traduction=20des=20libell=C3=A9s=20de=20v?= =?UTF-8?q?aleurs=20li=C3=A9es?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../param-link/param-link.component.ts | 26 +++++++++++++++---- src/locale/messages.en.json | 5 ++++ src/locale/messages.fr.json | 5 ++++ 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/app/components/param-link/param-link.component.ts b/src/app/components/param-link/param-link.component.ts index edad76498..4d3efa4e0 100644 --- a/src/app/components/param-link/param-link.component.ts +++ b/src/app/components/param-link/param-link.component.ts @@ -6,6 +6,7 @@ import { LinkedValue, ParamValueMode, Observer, Structure } from "jalhyd"; import { FormulaireService } from "../../services/formulaire/formulaire.service"; import { I18nService } from "../../services/internationalisation/internationalisation.service"; import { FormulaireDefinition } from "../../formulaire/definition/form-definition"; +import { sprintf } from "sprintf-js"; @Component({ selector: "param-link", @@ -112,23 +113,38 @@ export class ParamLinkComponent implements OnChanges, Observer, OnDestroy { p = i.nub.findPositionInParent(); if (i.isResult()) { // résultat d'ouvrage - return `${s} (résultat de ${c}, ouvrage ${p + 1})`; + return sprintf( + this.intlService.localizeText("INFO_LINKED_VALUE_DEVICE_RESULT"), + s, c, (p + 1) + ); } else { // paramètre d'ouvrage - return `${s} (${c}, ouvrage ${p + 1})`; + return sprintf( + this.intlService.localizeText("INFO_LINKED_VALUE_DEVICE"), + s, c, (p + 1) + ); } } else // 2. Résultat if (i.isResult()) { - return `${s} (résultat de ${c})`; + return sprintf( + this.intlService.localizeText("INFO_LINKED_VALUE_RESULT"), + s, c + ); } else // 3. Résultat complémentaire if (i.isExtraResult()) { if (i.meta["result"]) { // @TODO not used ? - return `${s} (${c}, résultat complémentaire de ${i.meta["result"]})`; + return sprintf( + this.intlService.localizeText("INFO_LINKED_VALUE_EXTRA_RESULT_OF"), + s, c, i.meta["result"] + ); } else { - return `${s} (${c}, résultat complémentaire)`; + return sprintf( + this.intlService.localizeText("INFO_LINKED_VALUE_EXTRA_RESULT"), + s, c + ); } } else { // 4. Paramètre (cas général) diff --git a/src/locale/messages.en.json b/src/locale/messages.en.json index d4e1a6420..66c9f9d6b 100644 --- a/src/locale/messages.en.json +++ b/src/locale/messages.en.json @@ -127,6 +127,11 @@ "INFO_LIB_ZDV": "Crest weir elevation or gate base", "INFO_LIB_ZRAM": "Upstream apron elevation", "INFO_LIB_ZT": "Triangle top elevation", + "INFO_LINKED_VALUE_DEVICE": "%s (%s, device %s)", + "INFO_LINKED_VALUE_RESULT": "%s (result of %s)", + "INFO_LINKED_VALUE_DEVICE_RESULT": "%s (result of %s, device %s)", + "INFO_LINKED_VALUE_EXTRA_RESULT": "%s (%s, extra result)", + "INFO_LINKED_VALUE_EXTRA_RESULT_OF": "%s (%s, extra result of %s)", "INFO_MACRORUGO_TITRE": "Rock-ramp fishpasses", "INFO_MACRORUGO_TITRE_COURT": "RR fishpasses", "INFO_MENU_HELP_TITLE": "Help", diff --git a/src/locale/messages.fr.json b/src/locale/messages.fr.json index 8627ade07..c8d611b36 100644 --- a/src/locale/messages.fr.json +++ b/src/locale/messages.fr.json @@ -127,6 +127,11 @@ "INFO_LIB_ZDV": "Cote de la crête du déversoir ou du radier de la vanne", "INFO_LIB_ZRAM": "Cote du radier amont", "INFO_LIB_ZT": "Cote haute du triangle", + "INFO_LINKED_VALUE_DEVICE": "%s (%s, ouvrage %s)", + "INFO_LINKED_VALUE_RESULT": "%s (résultat de %s)", + "INFO_LINKED_VALUE_DEVICE_RESULT": "%s (résultat de %s, ouvrage %s)", + "INFO_LINKED_VALUE_EXTRA_RESULT": "%s (%s, résultat complémentaire)", + "INFO_LINKED_VALUE_EXTRA_RESULT_OF": "%s (%s, résultat complémentaire de %s)", "INFO_MENU_HELP_TITLE": "Aide", "INFO_MENU_LOAD_SESSION_TITLE": "Charger une session", "INFO_MENU_SAVE_SESSION_TITLE": "Enregistrer la session", -- GitLab From 0aea540f1139c7f477fe81aaad176addc11e3c23 Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Wed, 27 Mar 2019 17:24:10 +0100 Subject: [PATCH 36/39] Fix #184 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit plus mise à jour test e2e --- e2e/calculator.po.ts | 8 +++++ e2e/load-linked-params.e2e-spec.ts | 31 ++++++++++++++++++- .../field-set/field-set.component.html | 2 +- .../param-field-line.component.ts | 4 +-- 4 files changed, 41 insertions(+), 4 deletions(-) diff --git a/e2e/calculator.po.ts b/e2e/calculator.po.ts index c9276cad4..b47d2ef68 100644 --- a/e2e/calculator.po.ts +++ b/e2e/calculator.po.ts @@ -50,6 +50,14 @@ export class CalculatorPage { return element.all(by.css('mat-button-toggle.radio_cal[ng-reflect-checked="true"]')); } + getAddStructureButton() { + return element(by.css("fieldset-container .hyd-window-btns button.add-structure")); + } + + getAllLinkButtons() { + return element.all(by.css("mat-button-toggle.radio_link")); + } + scrollTo(elt: ElementFinder) { browser.controlFlow().execute(function() { browser.executeScript("arguments[0].scrollIntoView(true)", elt.getWebElement()); diff --git a/e2e/load-linked-params.e2e-spec.ts b/e2e/load-linked-params.e2e-spec.ts index 56f84364a..2d6e91a20 100644 --- a/e2e/load-linked-params.e2e-spec.ts +++ b/e2e/load-linked-params.e2e-spec.ts @@ -1,4 +1,5 @@ import { AppPage } from "./app.po"; +import { ListPage } from "./list.po"; import { CalculatorPage } from "./calculator.po"; import { Navbar } from "./navbar.po"; import { SideNav } from "./sidenav.po"; @@ -11,6 +12,7 @@ import { browser } from "protractor"; */ describe("ngHyd − load session with multiple linked parameters", () => { let startPage: AppPage; + let listPage: ListPage; let calcPage: CalculatorPage; let navbar: Navbar; let sidenav: SideNav; @@ -20,10 +22,11 @@ describe("ngHyd − load session with multiple linked parameters", () => { calcPage = new CalculatorPage(); navbar = new Navbar(); sidenav = new SideNav(); + listPage = new ListPage(); } beforeEach(init); - it("when loading session-liens-spaghetti.json, all links should point to the right target", async () => { + it("when loading session-liens-spaghetti.json, all links should point to the right target", async () => { await startPage.navigateTo(); await navbar.clickMenuButton(); @@ -94,4 +97,30 @@ describe("ngHyd − load session with multiple linked parameters", () => { expect(lo_brv).toEqual("LargeurBerge (Sec. param.)"); }); + it("when creating parallel structures, devices should be linkabke to one another", async () => { + + // 1. check Lois d'ouvrages + await startPage.navigateTo(); + await listPage.clickMenuEntryForCalcType(8); + await calcPage.getAddStructureButton().click(); + const nb1 = await calcPage.getAllLinkButtons().count(); + expect(nb1).toBe(8); // link buttons on children but not on parent + + // 2. check Passe à bassin: Cloisons + await startPage.navigateTo(); + await listPage.clickMenuEntryForCalcType(10); + await calcPage.getAddStructureButton().click(); + const nb2 = await calcPage.getAllLinkButtons().count(); + expect(nb2).toBe(4); // link buttons on children but not on parent + + + // 3. check Lois de déversoirs dénoyés + await startPage.navigateTo(); + await listPage.clickMenuEntryForCalcType(9); + await calcPage.getAddStructureButton().click(); + const nb3 = await calcPage.getAllLinkButtons().count(); + expect(nb3).toBe(6); // link buttons on children but not on parent + + }); + }); diff --git a/src/app/components/field-set/field-set.component.html b/src/app/components/field-set/field-set.component.html index 444001156..b87bbe724 100644 --- a/src/app/components/field-set/field-set.component.html +++ b/src/app/components/field-set/field-set.component.html @@ -3,7 +3,7 @@ {{ title }} </mat-card-title> <div *ngIf="showButtons" class="hyd-window-btns"> - <button type="button" mat-icon-button (click)="onAddClick()"> + <button type="button" mat-icon-button (click)="onAddClick()" class="add-structure"> <mat-icon>add_box</mat-icon> </button> <button type="button" mat-icon-button [disabled]="! enableRemoveButton" (click)="onRemoveClick()"> diff --git a/src/app/components/param-field-line/param-field-line.component.ts b/src/app/components/param-field-line/param-field-line.component.ts index e147f1f9f..47a79d393 100644 --- a/src/app/components/param-field-line/param-field-line.component.ts +++ b/src/app/components/param-field-line/param-field-line.component.ts @@ -203,8 +203,8 @@ export class ParamFieldLineComponent implements OnChanges { } // ou un seul module de calcul "ouvrages parallèles" - if (this._formService.formulaires[0].calculatorType === CalculatorType.ParallelStructure) { - const ps: ParallelStructure = this._formService.formulaires[0].currentNub as ParallelStructure; + if (this._formService.formulaires[0].currentNub instanceof ParallelStructure) { + const ps: ParallelStructure = this._formService.formulaires[0].currentNub; if (ps.structures.length > 1) { return this._formService.getLinkableValues(this.param).length > 0; } -- GitLab From 77de25fff5cbf8bc533bd9309363425e76b5a388 Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Thu, 28 Mar 2019 11:46:33 +0100 Subject: [PATCH 37/39] =?UTF-8?q?Nouveau=20test=20e2e=20pour=20le=20calcul?= =?UTF-8?q?=20de=20param=C3=A8tres=20li=C3=A9s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- e2e/calculate-all-params.e2e-spec.ts | 4 - e2e/calculate-linked-params.e2e-spec.ts | 490 ++++++++++++++++++++++++ e2e/calculator.po.ts | 14 +- e2e/load-linked-params.e2e-spec.ts | 2 +- 4 files changed, 504 insertions(+), 6 deletions(-) create mode 100644 e2e/calculate-linked-params.e2e-spec.ts diff --git a/e2e/calculate-all-params.e2e-spec.ts b/e2e/calculate-all-params.e2e-spec.ts index eaff7587d..49d6cc12c 100644 --- a/e2e/calculate-all-params.e2e-spec.ts +++ b/e2e/calculate-all-params.e2e-spec.ts @@ -1,9 +1,5 @@ -import { AppPage } from "./app.po"; import { ListPage } from "./list.po"; import { CalculatorPage } from "./calculator.po"; -import { Navbar } from "./navbar.po"; -import { SideNav } from "./sidenav.po"; -import { browser } from "protractor"; /** * For all calculators, try to calculate every parameter: check that only one parameter diff --git a/e2e/calculate-linked-params.e2e-spec.ts b/e2e/calculate-linked-params.e2e-spec.ts new file mode 100644 index 000000000..179b55f54 --- /dev/null +++ b/e2e/calculate-linked-params.e2e-spec.ts @@ -0,0 +1,490 @@ +import { AppPage } from "./app.po"; +import { ListPage } from "./list.po"; +import { CalculatorPage } from "./calculator.po"; +import { Navbar } from "./navbar.po"; +import { SideNav } from "./sidenav.po"; +import { browser } from "protractor"; + +/** + * Uses an example configuration to calculate : + * - with a parameter linked to a single parameter + * - with a parameter linked to a single parameter, plus local variated parameter + * - with a parameter linked to a variated parameter + * - with a parameter linked to a single result + * - with a parameter linked to a single result, plus local variated parameter + * - with a parameter linked to a variated result + * - with a parameter linked to a single extra result + * - with a parameter linked to a single extra result, plus local variated parameter + * - with a parameter linked to a variated extra result + * + * => plus all those combinations in indeirect link mode (linked parameter target + * is also a linked parameter) + */ +describe("ngHyd − calculate with linked parameters", () => { + let listPage: ListPage; + let calcPage: CalculatorPage; + let navBar: Navbar; + let startPage: AppPage; + + beforeEach(() => { + listPage = new ListPage(); + calcPage = new CalculatorPage(); + navBar = new Navbar(); + startPage = new AppPage(); + + }); + + async function computeAndCheckPresenceOfResults() { + // check that "compute" button is active + const calcButton = calcPage.getCalculateButton(); + const disabledState = await calcButton.getAttribute("disabled"); + expect(disabledState).not.toBe("true"); + // click "compute" button + await calcButton.click(); + // check that result is not empty + const hasResults = await calcPage.hasResults(); + expect(hasResults).toBe(true); + } + + it(" − direct links : parameter linked to a single parameter", async () => { + // create a Régime uniforme + await startPage.navigateTo(); + await listPage.clickMenuEntryForCalcType(3); + + // create a PAB : dimensions + await navBar.clickNewCalculatorButton(); + await listPage.clickMenuEntryForCalcType(5); + // link Y to Y (R uniforme) + const Y = calcPage.getInputById("Y"); + await calcPage.setParamMode(Y, "link"); + const sel = await calcPage.getLinkedValueSelect(Y); + await calcPage.changeSelectValue(sel, 1); + + await computeAndCheckPresenceOfResults(); + }); + + it(" − direct links : parameter linked to a single parameter, plus local variated parameter", async () => { + // create a Régime uniforme + await startPage.navigateTo(); + await listPage.clickMenuEntryForCalcType(3); + + // create a PAB : dimensions + await navBar.clickNewCalculatorButton(); + await listPage.clickMenuEntryForCalcType(5); + // link Y to Y (R uniforme) + const Y = calcPage.getInputById("Y"); + await calcPage.setParamMode(Y, "link"); + const sel = await calcPage.getLinkedValueSelect(Y); + await calcPage.changeSelectValue(sel, 1); + // vary W + const W = calcPage.getInputById("W"); + await calcPage.setParamMode(W, "var"); + + await computeAndCheckPresenceOfResults(); + }); + + it(" − direct links : parameter linked to a variated parameter", async () => { + // create a Régime uniforme + await startPage.navigateTo(); + await listPage.clickMenuEntryForCalcType(3); + // vary Y + const Y1 = calcPage.getInputById("Y"); + await calcPage.setParamMode(Y1, "var"); + + // create a PAB : dimensions + await navBar.clickNewCalculatorButton(); + await listPage.clickMenuEntryForCalcType(5); + // link Y to Y (R uniforme) + const Y2 = calcPage.getInputById("Y"); + await calcPage.setParamMode(Y2, "link"); + const sel = await calcPage.getLinkedValueSelect(Y2); + await calcPage.changeSelectValue(sel, 1); + + await computeAndCheckPresenceOfResults(); + }); + + it(" − direct links : parameter linked to a single result", async () => { + // create a Régime uniforme + await startPage.navigateTo(); + await listPage.clickMenuEntryForCalcType(3); + // calculate Y + const Y1 = calcPage.getInputById("Y"); + await calcPage.setParamMode(Y1, "cal"); + + // create a PAB : dimensions + await navBar.clickNewCalculatorButton(); + await listPage.clickMenuEntryForCalcType(5); + // link Y to Y (R uniforme) + const Y2 = calcPage.getInputById("Y"); + await calcPage.setParamMode(Y2, "link"); + const sel = await calcPage.getLinkedValueSelect(Y2); + await calcPage.changeSelectValue(sel, 1); + + await computeAndCheckPresenceOfResults(); + }); + + it(" − direct links : parameter linked to a single result, plus local variated parameter", async () => { + // create a Régime uniforme + await startPage.navigateTo(); + await listPage.clickMenuEntryForCalcType(3); + // calculate Y + const Y1 = calcPage.getInputById("Y"); + await calcPage.setParamMode(Y1, "cal"); + + // create a PAB : dimensions + await navBar.clickNewCalculatorButton(); + await listPage.clickMenuEntryForCalcType(5); + // link Y to Y (R uniforme) + const Y2 = calcPage.getInputById("Y"); + await calcPage.setParamMode(Y2, "link"); + const sel = await calcPage.getLinkedValueSelect(Y2); + await calcPage.changeSelectValue(sel, 1); + // vary W + const W = calcPage.getInputById("W"); + await calcPage.setParamMode(W, "var"); + + await computeAndCheckPresenceOfResults(); + }); + + it(" − direct links : parameter linked to a variated result", async () => { + // create a Régime uniforme + await startPage.navigateTo(); + await listPage.clickMenuEntryForCalcType(3); + // vary Q + const Q = calcPage.getInputById("Q"); + await calcPage.setParamMode(Q, "var"); + // calculate Y + const Y1 = calcPage.getInputById("Y"); + await calcPage.setParamMode(Y1, "cal"); + + // create a PAB : dimensions + await navBar.clickNewCalculatorButton(); + await listPage.clickMenuEntryForCalcType(5); + // link Y to Y (R uniforme) + const Y2 = calcPage.getInputById("Y"); + await calcPage.setParamMode(Y2, "link"); + const sel = await calcPage.getLinkedValueSelect(Y2); + await calcPage.changeSelectValue(sel, 1); + + await computeAndCheckPresenceOfResults(); + }); + + it(" − direct links : parameter linked to a single extra result", async () => { + // create a Déversoirs dénoyés + await startPage.navigateTo(); + await listPage.clickMenuEntryForCalcType(9); + + // create a Régime uniforme + await navBar.clickNewCalculatorButton(); + await listPage.clickMenuEntryForCalcType(3); + // link Q to CvQT (Déversoirs dénoyés) + const Q = calcPage.getInputById("Q"); + await calcPage.setParamMode(Q, "link"); + const sel = await calcPage.getLinkedValueSelect(Q); + await calcPage.changeSelectValue(sel, 1); + + await computeAndCheckPresenceOfResults(); + }); + + it(" − direct links : parameter linked to a single extra result, plus local variated parameter", async () => { + // create a Déversoirs dénoyés + await startPage.navigateTo(); + await listPage.clickMenuEntryForCalcType(9); + + // create a Régime uniforme + await navBar.clickNewCalculatorButton(); + await listPage.clickMenuEntryForCalcType(3); + // link Q to CvQT (Déversoirs dénoyés) + const Q = calcPage.getInputById("Q"); + await calcPage.setParamMode(Q, "link"); + const sel = await calcPage.getLinkedValueSelect(Q); + await calcPage.changeSelectValue(sel, 1); + // vary YB + const YB = calcPage.getInputById("YB"); + await calcPage.setParamMode(YB, "var"); + + await computeAndCheckPresenceOfResults(); + }); + + it(" − direct links : parameter linked to a variated extra result", async () => { + // create a Déversoirs dénoyés + await startPage.navigateTo(); + await listPage.clickMenuEntryForCalcType(9); + // vary BR + const BR = calcPage.getInputById("BR"); + await calcPage.setParamMode(BR, "var"); + + // create a Régime uniforme + await navBar.clickNewCalculatorButton(); + await listPage.clickMenuEntryForCalcType(3); + // link Q to CvQT (Déversoirs dénoyés) + const Q = calcPage.getInputById("Q"); + await calcPage.setParamMode(Q, "link"); + const sel = await calcPage.getLinkedValueSelect(Q); + await calcPage.changeSelectValue(sel, 1); + + await computeAndCheckPresenceOfResults(); + }); + + it(" − indirect links : parameter linked to a single parameter", async () => { + // create a Régime uniforme + await startPage.navigateTo(); + await listPage.clickMenuEntryForCalcType(3); + + // create a Section paramétrée + await navBar.clickNewCalculatorButton(); + await listPage.clickMenuEntryForCalcType(2); + // link Y to Y (R uniforme) + const Yproxy = calcPage.getInputById("Y"); + await calcPage.setParamMode(Yproxy, "link"); + const selYproxy = await calcPage.getLinkedValueSelect(Yproxy); + await calcPage.changeSelectValue(selYproxy, 1); + + // create a PAB : dimensions + await navBar.clickNewCalculatorButton(); + await listPage.clickMenuEntryForCalcType(5); + // link Y to Y (Sec param) + const Y = calcPage.getInputById("Y"); + await calcPage.setParamMode(Yproxy, "link"); + const sel = await calcPage.getLinkedValueSelect(Yproxy); + await calcPage.changeSelectValue(selYproxy, 3); + + await computeAndCheckPresenceOfResults(); + }); + + it(" − indirect links : parameter linked to a single parameter, plus local variated parameter", async () => { + // create a Régime uniforme + await startPage.navigateTo(); + await listPage.clickMenuEntryForCalcType(3); + + // create a Section paramétrée + await navBar.clickNewCalculatorButton(); + await listPage.clickMenuEntryForCalcType(2); + // link Y to Y (R uniforme) + const Yproxy = calcPage.getInputById("Y"); + await calcPage.setParamMode(Yproxy, "link"); + const selYproxy = await calcPage.getLinkedValueSelect(Yproxy); + await calcPage.changeSelectValue(selYproxy, 1); + + // create a PAB : dimensions + await navBar.clickNewCalculatorButton(); + await listPage.clickMenuEntryForCalcType(5); + // link Y to Y (Sec param) + const Y = calcPage.getInputById("Y"); + await calcPage.setParamMode(Y, "link"); + const sel = await calcPage.getLinkedValueSelect(Y); + await calcPage.changeSelectValue(sel, 3); + // vary W + const W = calcPage.getInputById("W"); + await calcPage.setParamMode(W, "var"); + + await computeAndCheckPresenceOfResults(); + }); + + it(" − indirect links : parameter linked to a variated parameter", async () => { + // create a Régime uniforme + await startPage.navigateTo(); + await listPage.clickMenuEntryForCalcType(3); + // vary Y + const Y1 = calcPage.getInputById("Y"); + await calcPage.setParamMode(Y1, "var"); + + // create a Section paramétrée + await navBar.clickNewCalculatorButton(); + await listPage.clickMenuEntryForCalcType(2); + // link Y to Y (R uniforme) + const Yproxy = calcPage.getInputById("Y"); + await calcPage.setParamMode(Yproxy, "link"); + const selYproxy = await calcPage.getLinkedValueSelect(Yproxy); + await calcPage.changeSelectValue(selYproxy, 1); + + // create a PAB : dimensions + await navBar.clickNewCalculatorButton(); + await listPage.clickMenuEntryForCalcType(5); + // link Y to Y (Sec param) + const Y2 = calcPage.getInputById("Y"); + await calcPage.setParamMode(Y2, "link"); + const sel = await calcPage.getLinkedValueSelect(Y2); + await calcPage.changeSelectValue(sel, 3); + + await computeAndCheckPresenceOfResults(); + }); + + it(" − indirect links : parameter linked to a single result", async () => { + // create a Régime uniforme + await startPage.navigateTo(); + await listPage.clickMenuEntryForCalcType(3); + // calculate Y + const Y1 = calcPage.getInputById("Y"); + await calcPage.setParamMode(Y1, "cal"); + + // create a Section paramétrée + await navBar.clickNewCalculatorButton(); + await listPage.clickMenuEntryForCalcType(2); + // link Y to Y (R uniforme) + const Yproxy = calcPage.getInputById("Y"); + await calcPage.setParamMode(Yproxy, "link"); + const selYproxy = await calcPage.getLinkedValueSelect(Yproxy); + await calcPage.changeSelectValue(selYproxy, 1); + + // create a PAB : dimensions + await navBar.clickNewCalculatorButton(); + await listPage.clickMenuEntryForCalcType(5); + // link Y to Y (Sec param) + const Y2 = calcPage.getInputById("Y"); + await calcPage.setParamMode(Y2, "link"); + const sel = await calcPage.getLinkedValueSelect(Y2); + await calcPage.changeSelectValue(sel, 3); + + await computeAndCheckPresenceOfResults(); + }); + + it(" − indirect links : parameter linked to a single result, plus local variated parameter", async () => { + // create a Régime uniforme + await startPage.navigateTo(); + await listPage.clickMenuEntryForCalcType(3); + // calculate Y + const Y1 = calcPage.getInputById("Y"); + await calcPage.setParamMode(Y1, "cal"); + + // create a Section paramétrée + await navBar.clickNewCalculatorButton(); + await listPage.clickMenuEntryForCalcType(2); + // link Y to Y (R uniforme) + const Yproxy = calcPage.getInputById("Y"); + await calcPage.setParamMode(Yproxy, "link"); + const selYproxy = await calcPage.getLinkedValueSelect(Yproxy); + await calcPage.changeSelectValue(selYproxy, 1); + + // create a PAB : dimensions + await navBar.clickNewCalculatorButton(); + await listPage.clickMenuEntryForCalcType(5); + // link Y to Y (Sec param) + const Y2 = calcPage.getInputById("Y"); + await calcPage.setParamMode(Y2, "link"); + const sel = await calcPage.getLinkedValueSelect(Y2); + await calcPage.changeSelectValue(sel, 3); + // vary W + const W = calcPage.getInputById("W"); + await calcPage.setParamMode(W, "var"); + + await computeAndCheckPresenceOfResults(); + }); + + it(" − indirect links : parameter linked to a variated result", async () => { + // create a Régime uniforme + await startPage.navigateTo(); + await listPage.clickMenuEntryForCalcType(3); + // vary Q + const Q = calcPage.getInputById("Q"); + await calcPage.setParamMode(Q, "var"); + // calculate Y + const Y1 = calcPage.getInputById("Y"); + await calcPage.setParamMode(Y1, "cal"); + + // create a Section paramétrée + await navBar.clickNewCalculatorButton(); + await listPage.clickMenuEntryForCalcType(2); + // link Y to Y (R uniforme) + const Yproxy = calcPage.getInputById("Y"); + await calcPage.setParamMode(Yproxy, "link"); + const selYproxy = await calcPage.getLinkedValueSelect(Yproxy); + await calcPage.changeSelectValue(selYproxy, 1); + + // create a PAB : dimensions + await navBar.clickNewCalculatorButton(); + await listPage.clickMenuEntryForCalcType(5); + // link Y to Y (Sec param) + const Y2 = calcPage.getInputById("Y"); + await calcPage.setParamMode(Y2, "link"); + const sel = await calcPage.getLinkedValueSelect(Y2); + await calcPage.changeSelectValue(sel, 3); + + await computeAndCheckPresenceOfResults(); + }); + + it(" − indirect links : parameter linked to a single extra result", async () => { + // create a Déversoirs dénoyés + await startPage.navigateTo(); + await listPage.clickMenuEntryForCalcType(9); + + // create a Section paramétrée + await navBar.clickNewCalculatorButton(); + await listPage.clickMenuEntryForCalcType(2); + // link Q to CvQT (Déversoirs dénoyés) + const Qproxy = calcPage.getInputById("Q"); + await calcPage.setParamMode(Qproxy, "link"); + const selYproxy = await calcPage.getLinkedValueSelect(Qproxy); + await calcPage.changeSelectValue(selYproxy, 1); + + // create a Régime uniforme + await navBar.clickNewCalculatorButton(); + await listPage.clickMenuEntryForCalcType(3); + // link Q to CvQT (Sec param) + const Q = calcPage.getInputById("Q"); + await calcPage.setParamMode(Q, "link"); + const sel = await calcPage.getLinkedValueSelect(Q); + await calcPage.changeSelectValue(sel, 3); + + await computeAndCheckPresenceOfResults(); + }); + + it(" − indirect links : parameter linked to a single extra result, plus local variated parameter", async () => { + // create a Déversoirs dénoyés + await startPage.navigateTo(); + await listPage.clickMenuEntryForCalcType(9); + + // create a Section paramétrée + await navBar.clickNewCalculatorButton(); + await listPage.clickMenuEntryForCalcType(2); + // link Q to CvQT (Déversoirs dénoyés) + const Qproxy = calcPage.getInputById("Q"); + await calcPage.setParamMode(Qproxy, "link"); + const selYproxy = await calcPage.getLinkedValueSelect(Qproxy); + await calcPage.changeSelectValue(selYproxy, 1); + + // create a Régime uniforme + await navBar.clickNewCalculatorButton(); + await listPage.clickMenuEntryForCalcType(3); + // link Q to CvQT (Sec param) + const Q = calcPage.getInputById("Q"); + await calcPage.setParamMode(Q, "link"); + const sel = await calcPage.getLinkedValueSelect(Q); + await calcPage.changeSelectValue(sel, 3); + // vary YB + const YB = calcPage.getInputById("YB"); + await calcPage.setParamMode(YB, "var"); + + await computeAndCheckPresenceOfResults(); + }); + + it(" − indirect links : parameter linked to a variated extra result", async () => { + // create a Déversoirs dénoyés + await startPage.navigateTo(); + await listPage.clickMenuEntryForCalcType(9); + // vary BR + const BR = calcPage.getInputById("BR"); + await calcPage.setParamMode(BR, "var"); + + // create a Section paramétrée + await navBar.clickNewCalculatorButton(); + await listPage.clickMenuEntryForCalcType(2); + // link Q to CvQT (Déversoirs dénoyés) + const Qproxy = calcPage.getInputById("Q"); + await calcPage.setParamMode(Qproxy, "link"); + const selYproxy = await calcPage.getLinkedValueSelect(Qproxy); + await calcPage.changeSelectValue(selYproxy, 1); + + // create a Régime uniforme + await navBar.clickNewCalculatorButton(); + await listPage.clickMenuEntryForCalcType(3); + // link Q to CvQT (Sec param) + const Q = calcPage.getInputById("Q"); + await calcPage.setParamMode(Q, "link"); + const sel = await calcPage.getLinkedValueSelect(Q); + await calcPage.changeSelectValue(sel, 3); + + await computeAndCheckPresenceOfResults(); + }); + +}); diff --git a/e2e/calculator.po.ts b/e2e/calculator.po.ts index b47d2ef68..69cc7a7b0 100644 --- a/e2e/calculator.po.ts +++ b/e2e/calculator.po.ts @@ -120,11 +120,23 @@ export class CalculatorPage { await button.click(); // for "var" mode, close the modal if (mode === "var") { - await browser.sleep(500); + await browser.sleep(500); // wait for the modal to appear await element(by.css("dialog-edit-param-values .mat-dialog-actions button")).click(); + await browser.sleep(500); // wait for the navbar to reappear after modal dismissal } } + /** + * @param elt an <input> element + */ + async getLinkedValueSelect(elt: ElementFinder): Promise<ElementFinder> { + // get parent (div.container) + const container = await this.findParentContainer(elt) as ElementFinder; + // find <select> + const select = container.element(by.css("param-link mat-select")); + return select; + } + /** * Returns an object containing all the calculator's inputs values, indexed * by parameter ID diff --git a/e2e/load-linked-params.e2e-spec.ts b/e2e/load-linked-params.e2e-spec.ts index 2d6e91a20..bac4ab8ee 100644 --- a/e2e/load-linked-params.e2e-spec.ts +++ b/e2e/load-linked-params.e2e-spec.ts @@ -10,7 +10,7 @@ import { browser } from "protractor"; * from one to another * @TODO les valeurs des Select sont comparées au français, pas très générique :/ */ -describe("ngHyd − load session with multiple linked parameters", () => { +describe("ngHyd − load session with multiple linked parameters − ", () => { let startPage: AppPage; let listPage: ListPage; let calcPage: CalculatorPage; -- GitLab From 0e72e00f96f3223c85408317d53faf687052b73e Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Thu, 28 Mar 2019 15:41:34 +0100 Subject: [PATCH 38/39] Fix #186 --- .../base-param-input.component.ts | 4 +- .../generic-calculator/calc-name.component.ts | 39 +++++++------------ .../generic-input/generic-input.component.ts | 9 +++-- .../ngparam-input/ngparam-input.component.ts | 4 +- 4 files changed, 22 insertions(+), 34 deletions(-) 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 index 001a186d7..9b69dd05e 100644 --- a/src/app/components/base-param-input/base-param-input.component.ts +++ b/src/app/components/base-param-input/base-param-input.component.ts @@ -92,8 +92,8 @@ export class NgBaseParam extends Observable { templateUrl: "../generic-input/generic-input.component.html", }) export class BaseParamInputComponent extends GenericInputComponent { - constructor(private intlService: I18nService, cdRef: ChangeDetectorRef) { - super(cdRef); + constructor(intlService: I18nService, cdRef: ChangeDetectorRef) { + super(cdRef, intlService); } /** diff --git a/src/app/components/generic-calculator/calc-name.component.ts b/src/app/components/generic-calculator/calc-name.component.ts index 3de415d2e..309526b77 100644 --- a/src/app/components/generic-calculator/calc-name.component.ts +++ b/src/app/components/generic-calculator/calc-name.component.ts @@ -1,6 +1,7 @@ -import { Component, Input } from "@angular/core"; +import { Component } from "@angular/core"; import { GenericInputComponent } from "../generic-input/generic-input.component"; import { FormulaireDefinition } from "../../formulaire/definition/form-definition"; +import { I18nService } from "../../services/internationalisation/internationalisation.service"; @Component({ selector: "calc-name", @@ -11,8 +12,8 @@ import { FormulaireDefinition } from "../../formulaire/definition/form-definitio }) export class CalculatorNameComponent extends GenericInputComponent { - constructor() { - super(null); + constructor(intlService: I18nService) { + super(null, intlService); } /** @@ -39,41 +40,27 @@ export class CalculatorNameComponent extends GenericInputComponent { this.updateAndValidateUI(); } - /** - * valide une valeur de modèle : est ce une valeur acceptable ? (par ex, nombre dans un intervalle, valeur dans une liste, ...) - * @param v valide la valeur du modèle - * @returns isValid : true si la valeur est valide, false sinon - * @returns message : message d'erreur - */ protected validateModelValue(v: any): { isValid: boolean, message: string } { - let msg; - let valid = false; - - if (!(typeof (v) === "string") || v.length < 1) { - msg = "Veuillez entrer un nom"; - } else { - valid = true; - } - - return { isValid: valid, message: msg }; + // no model validation for a simple string + return { isValid: true, message: undefined }; } - /** - * valide une valeur saisie dans l'UI (forme de la saisie : est ce bien une date, un nombre, ...) - * @param ui valide la valeur saisie - * @returns isValid : true si la valeur est valide, false sinon - * @returns message : message d'erreur - */ protected validateUIValue(ui: string): { isValid: boolean, message: string } { let valid = false; let msg: string; if (ui === undefined || ui.length < 1) { - msg = "Veuillez entrer un nom"; + msg = "Veuillez entrer un nom tralala"; } else { valid = true; } return { isValid: valid, message: msg }; } + + public updateModelFromUI() { + if (this.validateUI()) { + this.setAndValidateModel(this, this.uiValue); // do NOT cast UI value to Number + } + } } diff --git a/src/app/components/generic-input/generic-input.component.ts b/src/app/components/generic-input/generic-input.component.ts index 213dfeeaa..1bac27018 100644 --- a/src/app/components/generic-input/generic-input.component.ts +++ b/src/app/components/generic-input/generic-input.component.ts @@ -4,6 +4,7 @@ import { BaseComponent } from "../base/base.component"; import { isNumeric } from "jalhyd"; import { FormulaireDefinition } from "../../formulaire/definition/form-definition"; import { NgParameter } from "../../formulaire/ngparam"; +import { I18nService } from "../../services/internationalisation/internationalisation.service"; /** * classe de gestion générique d'un champ de saisie avec titre, validation et message d'erreur @@ -88,7 +89,7 @@ export abstract class GenericInputComponent extends BaseComponent implements OnC @ViewChild("inputControl") inputField: NgModel; - constructor(private cdRef: ChangeDetectorRef) { + constructor(private cdRef: ChangeDetectorRef, protected intlService: I18nService) { super(); } @@ -129,7 +130,7 @@ export abstract class GenericInputComponent extends BaseComponent implements OnC } } - private validateUI() { + protected validateUI() { const { isValid, message } = this.validateUIValue(this._uiValue); this._errorMessageUI = message; this.detectChanges(); @@ -185,7 +186,7 @@ export abstract class GenericInputComponent extends BaseComponent implements OnC this.change.emit({ "action": "model", "value": this.getModelValue() }); } - private setAndValidateModel(sender: any, v: any) { + protected setAndValidateModel(sender: any, v: any) { this.setModelValue(sender, v); this.emitModelChanged(); @@ -281,7 +282,7 @@ export abstract class GenericInputComponent extends BaseComponent implements OnC let msg: string; if (! isNumeric(ui)) { - msg = "Veuillez entrer une valeur numérique"; + msg = this.intlService.localizeText("ERROR_PARAM_MUST_BE_A_NUMBER"); } else { valid = true; } diff --git a/src/app/components/ngparam-input/ngparam-input.component.ts b/src/app/components/ngparam-input/ngparam-input.component.ts index 7e1af55ce..2717729d8 100644 --- a/src/app/components/ngparam-input/ngparam-input.component.ts +++ b/src/app/components/ngparam-input/ngparam-input.component.ts @@ -29,8 +29,8 @@ export class NgParamInputComponent extends GenericInputComponent implements Obse */ private _tmp: number; - constructor(private intlService: I18nService, cdRef: ChangeDetectorRef) { - super(cdRef); + constructor(intlService: I18nService, cdRef: ChangeDetectorRef) { + super(cdRef, intlService); } /** -- GitLab From e697fb810e3bfcdd63e6f43667ab0bd8867fa9ef Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Wed, 10 Apr 2019 15:36:09 +0200 Subject: [PATCH 39/39] =?UTF-8?q?Adaptation=20=C3=A0=20jalhyd#79?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- e2e/clone-calc.e2e-spec.ts | 17 +- e2e/compute-reset-chained-links.e2e-spec.ts | 10 +- e2e/link-parallel-devices.e2e-spec.ts | 47 ++++++ e2e/load-linked-params.e2e-spec.ts | 26 --- .../base-param-input.component.ts | 4 +- .../generic-calculator/calc-name.component.ts | 2 +- .../calculator.component.ts | 1 - .../param-field-line.component.html | 6 +- .../param-field-line.component.ts | 24 ++- .../param-link/param-link.component.ts | 11 +- .../remous-results.component.ts | 2 +- .../definition/concrete/form-base.ts | 8 - .../concrete/form-regime-uniforme.ts | 1 - .../definition/form-compute-fixedvar.ts | 2 +- .../form-compute-parallel-structures.ts | 6 +- .../form-compute-section-parametree.ts | 2 +- src/app/formulaire/definition/form-compute.ts | 14 +- .../definition/form-def-fixedvar.ts | 154 +----------------- .../definition/form-def-paramcalc.ts | 88 ---------- .../formulaire/definition/form-definition.ts | 2 +- .../definition/form-result-fixedvar.ts | 2 - src/app/formulaire/ngparam.ts | 93 +++++------ 22 files changed, 151 insertions(+), 371 deletions(-) create mode 100644 e2e/link-parallel-devices.e2e-spec.ts diff --git a/e2e/clone-calc.e2e-spec.ts b/e2e/clone-calc.e2e-spec.ts index dab35d149..b768d34f0 100644 --- a/e2e/clone-calc.e2e-spec.ts +++ b/e2e/clone-calc.e2e-spec.ts @@ -72,22 +72,7 @@ describe("ngHyd − clone a calculator", () => { const displayedVal = await calcPage.getInputById(k).getAttribute("value"); expect(displayedVal).toBe("" + v); }); - }); - - it("cloning a parallel-structures calculator should work", async () => { - await startPage.navigateTo(); - - // create source module to clone - await navbar.clickNewCalculatorButton(); - await listPage.clickMenuEntryForCalcType(8); // Lois d'ouvrages - await browser.sleep(500); - - // otherwise clickCloneCalcButton() fails with "Element is not clickable at point" - // await browser.executeScript("window.scrollTo(0, 0);"); - await calcPage.clickCloneCalcButton(); - await browser.sleep(500); - // check existence of the cloned module - expect(await navbar.getAllCalculatorTabs().count()).toBe(2); + // @TODO check linked value (see above) }); }); diff --git a/e2e/compute-reset-chained-links.e2e-spec.ts b/e2e/compute-reset-chained-links.e2e-spec.ts index 6399c764c..dc72e70c0 100644 --- a/e2e/compute-reset-chained-links.e2e-spec.ts +++ b/e2e/compute-reset-chained-links.e2e-spec.ts @@ -36,7 +36,7 @@ describe("ngHyd − compute then reset chained results", () => { await browser.sleep(500); expect(await navbar.getAllCalculatorTabs().count()).toBe(3); - // 1. get top most module + // 1. get down-most module await navbar.clickCalculatorTabForUid("dWs5bm"); // check that "compute" button is active @@ -46,7 +46,7 @@ describe("ngHyd − compute then reset chained results", () => { // click "compute" button await calcButton.click(); - // only top-most module should have results + // only down-most module should have results let hasResults = await calcPage.hasResults(); // other two should not await navbar.clickCalculatorTabForUid("OGFzOH"); @@ -56,7 +56,7 @@ describe("ngHyd − compute then reset chained results", () => { hasResults = await calcPage.hasResults(); expect(hasResults).toBe(false); - // 2. get bottom-most module + // 2. get up-most module await navbar.clickCalculatorTabForUid("OGFzOH"); // modify any input (for ex. "Ks") @@ -82,7 +82,7 @@ describe("ngHyd − compute then reset chained results", () => { await browser.sleep(500); expect(await navbar.getAllCalculatorTabs().count()).toBe(3); - // 1. get top most module (PAB Dimensions) + // 1. get down-most module (PAB Dimensions) await navbar.clickCalculatorTabForUid("bGZqcz"); // check that "compute" button is active @@ -99,7 +99,7 @@ describe("ngHyd − compute then reset chained results", () => { expect(hasResults).toBe(true); } - // 2. get bottom-most module (Macro-rugo) + // 2. get up-most module (Macro-rugo) await navbar.clickCalculatorTabForUid("dnRiY2"); // modify any input (for ex. "Ks") diff --git a/e2e/link-parallel-devices.e2e-spec.ts b/e2e/link-parallel-devices.e2e-spec.ts new file mode 100644 index 000000000..f5c73aa4a --- /dev/null +++ b/e2e/link-parallel-devices.e2e-spec.ts @@ -0,0 +1,47 @@ +import { AppPage } from "./app.po"; +import { ListPage } from "./list.po"; +import { CalculatorPage } from "./calculator.po"; + +/** + * Load a session containing 4 calculators, having multiple linked parameters + * from one to another + * @TODO les valeurs des Select sont comparées au français, pas très générique :/ + */ +describe("ngHyd − load session with multiple linked parameters − ", () => { + let startPage: AppPage; + let listPage: ListPage; + let calcPage: CalculatorPage; + + function init() { + startPage = new AppPage(); + calcPage = new CalculatorPage(); + listPage = new ListPage(); + } + beforeEach(init); + + it("when creating parallel structures, devices should be linkable to one another", async () => { + + // 1. check Lois d'ouvrages + await startPage.navigateTo(); + await listPage.clickMenuEntryForCalcType(8); + await calcPage.getAddStructureButton().click(); + const nb1 = await calcPage.getAllLinkButtons().count(); + expect(nb1).toBe(8); // link buttons on children but not on parent + + // 2. check Passe à bassin: Cloisons + await startPage.navigateTo(); + await listPage.clickMenuEntryForCalcType(10); + await calcPage.getAddStructureButton().click(); + const nb2 = await calcPage.getAllLinkButtons().count(); + expect(nb2).toBe(4); // link buttons on children but not on parent + + + // 3. check Lois de déversoirs dénoyés + await startPage.navigateTo(); + await listPage.clickMenuEntryForCalcType(9); + await calcPage.getAddStructureButton().click(); + const nb3 = await calcPage.getAllLinkButtons().count(); + expect(nb3).toBe(6); // link buttons on children but not on parent + + }); +}); diff --git a/e2e/load-linked-params.e2e-spec.ts b/e2e/load-linked-params.e2e-spec.ts index bac4ab8ee..2b67e12b6 100644 --- a/e2e/load-linked-params.e2e-spec.ts +++ b/e2e/load-linked-params.e2e-spec.ts @@ -97,30 +97,4 @@ describe("ngHyd − load session with multiple linked parameters − ", () => { expect(lo_brv).toEqual("LargeurBerge (Sec. param.)"); }); - it("when creating parallel structures, devices should be linkabke to one another", async () => { - - // 1. check Lois d'ouvrages - await startPage.navigateTo(); - await listPage.clickMenuEntryForCalcType(8); - await calcPage.getAddStructureButton().click(); - const nb1 = await calcPage.getAllLinkButtons().count(); - expect(nb1).toBe(8); // link buttons on children but not on parent - - // 2. check Passe à bassin: Cloisons - await startPage.navigateTo(); - await listPage.clickMenuEntryForCalcType(10); - await calcPage.getAddStructureButton().click(); - const nb2 = await calcPage.getAllLinkButtons().count(); - expect(nb2).toBe(4); // link buttons on children but not on parent - - - // 3. check Lois de déversoirs dénoyés - await startPage.navigateTo(); - await listPage.clickMenuEntryForCalcType(9); - await calcPage.getAddStructureButton().click(); - const nb3 = await calcPage.getAllLinkButtons().count(); - expect(nb3).toBe(6); // link buttons on children but not on parent - - }); - }); 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 index 9b69dd05e..4c31d115f 100644 --- a/src/app/components/base-param-input/base-param-input.component.ts +++ b/src/app/components/base-param-input/base-param-input.component.ts @@ -34,7 +34,7 @@ export class NgBaseParam extends Observable { } public checkValue(val: number) { - return this._param.checkValue(val); + return this._param.checkValueAgainstDomain(val); } public checkMin(min: number): boolean { @@ -71,7 +71,7 @@ export class NgBaseParam extends Observable { msg = ServiceFactory.instance.i18nService.localizeText("ERROR_PARAM_NULL"); } else { try { - this._param.checkValue(v); + this._param.checkValueAgainstDomain(v); valid = true; } catch (e) { if (e instanceof Message) { diff --git a/src/app/components/generic-calculator/calc-name.component.ts b/src/app/components/generic-calculator/calc-name.component.ts index 309526b77..b4c109b6f 100644 --- a/src/app/components/generic-calculator/calc-name.component.ts +++ b/src/app/components/generic-calculator/calc-name.component.ts @@ -50,7 +50,7 @@ export class CalculatorNameComponent extends GenericInputComponent { let msg: string; if (ui === undefined || ui.length < 1) { - msg = "Veuillez entrer un nom tralala"; + msg = "Veuillez entrer un nom"; } else { valid = true; } diff --git a/src/app/components/generic-calculator/calculator.component.ts b/src/app/components/generic-calculator/calculator.component.ts index 2635777d6..31842b969 100644 --- a/src/app/components/generic-calculator/calculator.component.ts +++ b/src/app/components/generic-calculator/calculator.component.ts @@ -204,7 +204,6 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit, this._formulaire.onRadioClick(this._pendingRadioClickInfo); this._pendingRadioClickInfo = undefined; } - // @TODO call this._isUIValid here ? } public onCloseForm() { diff --git a/src/app/components/param-field-line/param-field-line.component.html b/src/app/components/param-field-line/param-field-line.component.html index 973ec8c81..acea333d2 100644 --- a/src/app/components/param-field-line/param-field-line.component.html +++ b/src/app/components/param-field-line/param-field-line.component.html @@ -20,13 +20,13 @@ <mat-button-toggle-group *ngIf="hasRadioFix() || hasRadioVar() || hasRadioCal() || hasRadioLink()"> <mat-button-toggle class="radio_fix" value="radio_fix" - (click)="onRadioClick('fix')" [checked]="isRadioFixChecked"> + (click)="onRadioClick('fix')" [checked]="isRadioFixChecked" [disabled]="! canExitCalcMode()"> <span fxHide.xxs>{{ uitextParamFixe }}</span> <span fxHide.gt-xxs>F</span> </mat-button-toggle> <mat-button-toggle class="radio_var" value="radio_var" *ngIf="hasRadioVar()" - (click)="onRadioClick('var')" [checked]="isRadioVarChecked"> + (click)="onRadioClick('var')" [checked]="isRadioVarChecked" [disabled]="! canExitCalcMode()"> <span fxHide.xxs>{{ uitextParamVarier }}</span> <span fxHide.gt-xxs>V</span> </mat-button-toggle> @@ -38,7 +38,7 @@ </mat-button-toggle> <mat-button-toggle class="radio_link" value="radio_link" *ngIf="hasRadioLink()" - (click)="onRadioClick('link')" [checked]="isRadioLinkChecked"> + (click)="onRadioClick('link')" [checked]="isRadioLinkChecked" [disabled]="! canExitCalcMode()"> <span fxHide.xxs>{{ uitextParamLie }}</span> <span fxHide.gt-xxs>L</span> </mat-button-toggle> diff --git a/src/app/components/param-field-line/param-field-line.component.ts b/src/app/components/param-field-line/param-field-line.component.ts index 47a79d393..06a78419f 100644 --- a/src/app/components/param-field-line/param-field-line.component.ts +++ b/src/app/components/param-field-line/param-field-line.component.ts @@ -4,7 +4,7 @@ import { I18nService } from "../../services/internationalisation/internationalis import { NgParameter, ParamRadioConfig } from "../../formulaire/ngparam"; import { NgParamInputComponent } from "../ngparam-input/ngparam-input.component"; import { ServiceFactory } from "../../services/service-factory"; -import { ParamValueMode, CalculatorType, ParallelStructure } from "jalhyd"; +import { ParamValueMode, ParallelStructure, Nub } from "jalhyd"; import { FormulaireService } from "../../services/formulaire/formulaire.service"; import { ParamLinkComponent } from "../param-link/param-link.component"; import { ParamComputedComponent } from "../param-computed/param-computed.component"; @@ -214,14 +214,28 @@ export class ParamFieldLineComponent implements OnChanges { return false; } - private onRadioClick(option: string) { + /** + * Returns true if the current parameter is in CALC mode but no SINGLE + * parameter is available to take its place + */ + public canExitCalcMode() { + let ret = true; + if (this.param.paramDefinition.isCalculated) { + const nub = this.param.paramDefinition.parentNub; + const p = nub.findFirstSingleParameter(this.param.paramDefinition); + ret = (p !== undefined); + } + return ret; + } + + public onRadioClick(option: string) { const oldValue = this.param.valueMode; switch (option) { case "fix": this.param.valueMode = ParamValueMode.SINGLE; // reset the value to avoid "undefined" after exiting CALC or LINK mode // @TODO not always necessary; find out why - this.param.setValue(this, this.param.paramDefinition.paramValues.singleValue); + this.param.setValue(this, this.param.paramDefinition.singleValue); break; case "var": @@ -237,7 +251,7 @@ export class ParamFieldLineComponent implements OnChanges { break; case "cal": - this.param.valueMode = ParamValueMode.CALCUL; + this.param.setCalculated(); // sets mode to CALCUL and more break; case "link": @@ -278,7 +292,7 @@ export class ParamFieldLineComponent implements OnChanges { /** * réception d'un événement de validité de ParamValuesComponent */ - private onParamValuesValid(event: boolean) { + public onParamValuesValid(event: boolean) { this._isRangeValid = event; this.emitValidity(); } diff --git a/src/app/components/param-link/param-link.component.ts b/src/app/components/param-link/param-link.component.ts index 4d3efa4e0..7c3e8887e 100644 --- a/src/app/components/param-link/param-link.component.ts +++ b/src/app/components/param-link/param-link.component.ts @@ -172,7 +172,16 @@ export class ParamLinkComponent implements OnChanges, Observer, OnDestroy { * événement de changement de la valeur du modèle */ private emitModelChanged() { - this.change.emit({ "action": "model", "value": this.currentLinkedParam.getValue() }); + let value; + try { + value = this.currentLinkedParam.getValue(); + } catch (e) { + // console.log("undefined target value (pending calculation)"); + } + this.change.emit({ + "action": "model", + "value": value + }); } public updateParamList() { diff --git a/src/app/components/remous-results/remous-results.component.ts b/src/app/components/remous-results/remous-results.component.ts index d62a814e0..a59ea0c96 100644 --- a/src/app/components/remous-results/remous-results.component.ts +++ b/src/app/components/remous-results/remous-results.component.ts @@ -350,7 +350,7 @@ export class RemousResultsComponent implements DoCheck { } private get abscisseIterator(): INumberIterator { - return this._remousResults.varResults.variatedParameter.paramDefinition.paramValues.getValuesIterator(); + return this._remousResults.varResults.variatedParameter.paramDefinition.valuesIterator; } private connectRessaut(lineFlu: LineData, lineTor: LineData) { diff --git a/src/app/formulaire/definition/concrete/form-base.ts b/src/app/formulaire/definition/concrete/form-base.ts index edc9f93c2..f1afa17ea 100644 --- a/src/app/formulaire/definition/concrete/form-base.ts +++ b/src/app/formulaire/definition/concrete/form-base.ts @@ -26,14 +26,6 @@ export class FormulaireBase extends FormulaireDefinition { this._formParamCalc.parseOptions(json); } - /** - * gestion du clic sur les radios "paramètre fixé, à varier, à calculer" - */ - public onRadioClick(info: string) { - super.onRadioClick(info); - this._formParamCalc.onRadioClick(info); - } - /** * Resets the form results, the results panel on screen, the model * results, and does the same for all depending modules diff --git a/src/app/formulaire/definition/concrete/form-regime-uniforme.ts b/src/app/formulaire/definition/concrete/form-regime-uniforme.ts index 503bdaba7..3d846e31d 100644 --- a/src/app/formulaire/definition/concrete/form-regime-uniforme.ts +++ b/src/app/formulaire/definition/concrete/form-regime-uniforme.ts @@ -41,7 +41,6 @@ export class FormulaireRegimeUniforme extends FormulaireBase implements Observer this.replaceCurrentNub(sender.properties); for (const fs of this.allFieldsets) { fs.setNub(this._currentNub); - this._formParamCalc.setDefault(); // treat the fieldset as new to re-subscribe to Nub properties change events this.afterParseFieldset(fs); } diff --git a/src/app/formulaire/definition/form-compute-fixedvar.ts b/src/app/formulaire/definition/form-compute-fixedvar.ts index 873812579..205e9e9dc 100644 --- a/src/app/formulaire/definition/form-compute-fixedvar.ts +++ b/src/app/formulaire/definition/form-compute-fixedvar.ts @@ -46,7 +46,7 @@ export class FormComputeFixedVar extends FormCompute { const nub: Nub = this._formBase.currentNub; const computedParam: NgParameter = this.getComputedParameter(); - const res: Result = this.runNubCalc(nub, computedParam); + const res: Result = this.runNubCalc(nub); this.reaffectResultComponents(); } diff --git a/src/app/formulaire/definition/form-compute-parallel-structures.ts b/src/app/formulaire/definition/form-compute-parallel-structures.ts index 580a52f08..8f169e5e3 100644 --- a/src/app/formulaire/definition/form-compute-parallel-structures.ts +++ b/src/app/formulaire/definition/form-compute-parallel-structures.ts @@ -1,4 +1,4 @@ -import { ComputeNode, ParallelStructure, Structure } from "jalhyd"; +import { ComputeNode, ParallelStructure, Structure, ParamDefinition } from "jalhyd"; import { FormComputeFixedVar } from "./form-compute-fixedvar"; import { FormResultFixedVar } from "./form-result-fixedvar"; @@ -41,8 +41,8 @@ export class FormComputeParallelStructures extends FormComputeFixedVar { * construit un identifiant de type { uid: "abcdef", symbol: "X" } * avec "abcdef" l'index de l'ouvrage et "X" son paramètre */ - protected getParameterRefid(p: NgParameter): any { - const nub = p.paramDefinition.parentComputeNode; + protected getParameterRefid(p: ParamDefinition): any { + const nub = p.parentComputeNode; if (nub instanceof Structure) { return { uid: nub.uid, diff --git a/src/app/formulaire/definition/form-compute-section-parametree.ts b/src/app/formulaire/definition/form-compute-section-parametree.ts index 068dce9d2..4c78233a0 100644 --- a/src/app/formulaire/definition/form-compute-section-parametree.ts +++ b/src/app/formulaire/definition/form-compute-section-parametree.ts @@ -51,7 +51,7 @@ export class FormComputeSectionParametree extends FormCompute { const computedParam: NgParameter = this.createParameter(computedParamInfo.symbol, this._formBase); this._varResults.calculatedParameter = computedParam; - this._varResults.result = this.runNubCalc(sectNub, computedParam); + this._varResults.result = this.runNubCalc(sectNub); this._varResults.update(false); } diff --git a/src/app/formulaire/definition/form-compute.ts b/src/app/formulaire/definition/form-compute.ts index a9fb302a1..5f077f0c2 100644 --- a/src/app/formulaire/definition/form-compute.ts +++ b/src/app/formulaire/definition/form-compute.ts @@ -1,4 +1,4 @@ -import { Nub, Result, ParamDomainValue, Observer } from "jalhyd"; +import { Nub, Result, ParamDomainValue, Observer, ParamDefinition } from "jalhyd"; import { FormResult } from "./form-result"; import { FormulaireDefinition } from "./form-definition"; @@ -21,7 +21,7 @@ export abstract class FormCompute implements Observer { * retourne un identifiant du paramètre dans le formulaire * surchargé dans le cas des ouvrages // */ - protected getParameterRefid(p: NgParameter) { + protected getParameterRefid(p: ParamDefinition) { return p.symbol; } @@ -36,11 +36,17 @@ export abstract class FormCompute implements Observer { * Lance le calcul d'un paramètre en déterminant une valeur initiale. * Si nécessaire déclenche un calcul en chaîne des modules en amont. */ - protected runNubCalc(nub: Nub, computedParam: NgParameter): Result { + protected runNubCalc(nub: Nub, computedParam?: ParamDefinition): Result { let init: number; + + // by default, use Nub's calculatedParam + if (computedParam === undefined) { + computedParam = nub.calculatedParam; + } + // require chain computation; redundant with Nub.CalcSerie but required // to get initial value here... - const computedParamValue = computedParam.getValue(true); + const computedParamValue = computedParam.getValue(); switch (computedParam.domain.domain) { case ParamDomainValue.ANY: diff --git a/src/app/formulaire/definition/form-def-fixedvar.ts b/src/app/formulaire/definition/form-def-fixedvar.ts index 469bda41b..efad7a577 100644 --- a/src/app/formulaire/definition/form-def-fixedvar.ts +++ b/src/app/formulaire/definition/form-def-fixedvar.ts @@ -1,166 +1,14 @@ -import { ParamValueMode } from "jalhyd"; - -import { ParamRadioConfig, NgParameter } from "../ngparam"; import { FormulaireDefinition } from "./form-definition"; /** * gestion des formulaires avec "paramètre fixé" et "paramètre à varier" */ export class FormDefFixedVar { + protected _formBase: FormulaireDefinition; constructor(base: FormulaireDefinition) { this._formBase = base; } - /** - * remet les radios de tous les paramètres à FIX sauf "me" et ceux (celui) à l'état "except" - */ - protected resetOtherRadio(me: NgParameter, except?: ParamRadioConfig) { - for (const p of this._formBase.allFormElements) { - if (p instanceof NgParameter) { - if (p !== me && p.radioState !== except - && p.radioState !== ParamRadioConfig.LINK - && p.radioConfig !== ParamRadioConfig.FIX) { - - p.valueMode = ParamValueMode.SINGLE; - } - } - } - } - - /** - * gère un changement de mode pour un paramètre - * règles : - * - 1 seul paramètre CAL à la fois - * - 1 seul paramètre multivalué (VAR) à la fois (directement ou par liaison) - * - plusieurs paramètres FIX à la fois possible - * - plusieurs paramètres LINK à la fois possible si les 2 1ères règles sont respectées - * - * analyse : - * ancien état nouvel état action(s) - * FIX VAR action1 - * FIX CAL action2 - * FIX LINK si paramètre lié FIX : aucune - * si paramètre lié VAR : action1 - * si paramètre lié CAL : si valeur unique : aucune - * si valeur multiple : action1 - * si paramètre lié LINK : recommencer ce cas avec le paramètre lié - * - * VAR FIX aucune - * VAR CAL action2 - * VAR LINK si paramètre lié FIX : aucune - * si paramètre lié VAR : aucune - * si paramètre lié CAL : si valeur unique : aucune - * si valeur multiple : aucune - * si paramètre lié LINK : recommencer ce cas avec le paramètre lié - * - * CAL FIX action5 - * CAL VAR action3 + action5 - * CAL LINK si paramètre lié FIX : aucune - * si paramètre lié VAR : action3 + action4|action5 - * si paramètre lié CAL : action3 + action4|action5 - * si paramètre lié LINK : recommencer ce cas avec le paramètre lié - * - * action1 : reset (à FIX) de tous les autres paramètres que celui modifié sauf celui à CAL - * action2 : reset (à FIX) de tous les autres paramètres que celui modifié sauf celui/ceux à VAR - * action3 : reset (à FIX) de tous les autres paramètres que celui modifié - * action4 : mettre le paramètre désigné par la conf comme "par défault" à CAL - * action5 : mettre le 1er paramètre du module de calcul à CAL - */ - protected processRadioStateChange(sourceParam: NgParameter, oldState: ParamValueMode) { - switch (oldState) { - case ParamValueMode.SINGLE: // ancien état - switch (sourceParam.valueMode) { - case ParamValueMode.MINMAX: // nouvel état - case ParamValueMode.LISTE: - this.resetOtherRadio(sourceParam, ParamRadioConfig.CAL); - break; - - case ParamValueMode.CALCUL: // nouvel état - this.resetOtherRadio(sourceParam, ParamRadioConfig.VAR); - break; - - case ParamValueMode.LINK: // nouvel état - if (sourceParam.paramDefinition.isReferenceDefined() && sourceParam.paramDefinition.hasMultipleValues) { - this.resetOtherRadio(sourceParam, ParamRadioConfig.CAL); - } // @TODO vérifier tous les cas problématiques (liens en chaîne ?) - break; - } - break; - - case ParamValueMode.LISTE: // ancien état - case ParamValueMode.MINMAX: - switch (sourceParam.valueMode) { - case ParamValueMode.CALCUL: // nouvel état - this.resetOtherRadio(sourceParam, ParamRadioConfig.VAR); - break; - - case ParamValueMode.LINK: // nouvel état - // mode du paramètre référencé - /* const refParamValues = sourceParam.paramDefinition.referencedParamValues; - if (refParamValues.valueMode === ParamValueMode.LINK) { - throw new Error(`références de paramètre en chaîne non pris en charge`); - } */ - // @TODO vérifier tous les cas problématiques (liens en chaîne ?) - break; - } - break; - - case ParamValueMode.LINK: // ancien état - switch (sourceParam.valueMode) { - case ParamValueMode.MINMAX: // nouvel état - case ParamValueMode.LISTE: - this.resetOtherRadio(sourceParam, ParamRadioConfig.CAL); - break; - - case ParamValueMode.CALCUL: // nouvel état - this.resetOtherRadio(sourceParam, ParamRadioConfig.VAR); - break; - } - break; - } - } - - /** - * modifie les boutons radio "fix", "var", "cal" de tous les paramètres - * en fonction de la modification de l'état d'un des paramètres - * @param uid id numérique unique du paramètre source - * @param option nouvel état "fix", "var" ou "cal" du paramètre source - */ - protected resetRadiosAndResults(sourceParam: NgParameter, oldState: ParamValueMode) { - this.processRadioStateChange(sourceParam, oldState); - - // on vérifie qu'il y a au moins un paramètre "à calculer" et sinon, on prend le 1er qui est à "fixé" - if (this._formBase.getDisplayedParamFromState(ParamRadioConfig.CAL) === undefined) { - let newCal: NgParameter; - - for (const p of this._formBase.allFormElements) { - if (p instanceof NgParameter) { - // change all radio button groups except the one that sent the event - if (p.radioConfig === ParamRadioConfig.CAL && p.radioState === ParamRadioConfig.FIX && p !== sourceParam) { - newCal = p; - break; - } - } - if (newCal) { - break; - } - } - // if the current calculated parameter was set to another mode, set a new param - // to calculated mode (there must always be exactly one) - if (newCal) { - newCal.valueMode = ParamValueMode.CALCUL; - } - } - } - - /** - * gestion des événements clic sur les radios - */ - public onRadioClick(info: any) { - const param: NgParameter = info.param; // paramètre source de l'événement radio - const old: ParamValueMode = info.oldValueMode; // ancien état (radio) - this.resetRadiosAndResults(param, old); - } } diff --git a/src/app/formulaire/definition/form-def-paramcalc.ts b/src/app/formulaire/definition/form-def-paramcalc.ts index 230a3257c..c16a0397e 100644 --- a/src/app/formulaire/definition/form-def-paramcalc.ts +++ b/src/app/formulaire/definition/form-def-paramcalc.ts @@ -1,6 +1,3 @@ -import { ParamValueMode, ParamDefinition } from "jalhyd"; - -import { NgParameter } from "../ngparam"; import { FormulaireDefinition } from "./form-definition"; import { FormDefFixedVar } from "./form-def-fixedvar"; @@ -8,97 +5,12 @@ import { FormDefFixedVar } from "./form-def-fixedvar"; * gestion des formulaires avec "paramètre à calculer" (conduite distributrice, Lechapt-Calmon, régime uniforme, passes à bassin) */ export class FormDefParamToCalculate extends FormDefFixedVar { - /** - * symbole du paramètre à calculer par défaut (cf config "idCal") - */ - private _defaultCalculatedParam: string; constructor(base: FormulaireDefinition) { super(base); } public parseOptions(json: {}) { - this._defaultCalculatedParam = undefined; - // browse config file to find "options" chapter - for (const k in json) { - const o = json[k]; - if (o.type === "options") { - // id du paramètre à calculer par défaut - this._defaultCalculatedParam = o["idCal"]; - // this._formBase - if (this._defaultCalculatedParam && ! this.findCalculatedParam()) { - const p = this.setDefault(); - p.isDefault = true; - } - } - } - } - - /** - * Find the parameter that is set to CALC mode - */ - private findCalculatedParam() { - for (const p of this._formBase.currentNub.parameterIterator) { - if (p.valueMode === ParamValueMode.CALCUL) { - return p; - } - } - } - - /** - * met le paramètre par défaut à CAL sauf si c'est "except" - * @param except paramètre à ne pas remettre à CAL - */ - public setDefault(except?: NgParameter): NgParameter { - const defaultParamCal: NgParameter = this._formBase.getParamFromSymbol(this._defaultCalculatedParam); - if (except === undefined || defaultParamCal.uid !== except.uid) { - defaultParamCal.valueMode = ParamValueMode.CALCUL; - } - return defaultParamCal; } - /** - * @see FormDefFixedVar.processRadioStateChange pour l'analyse - */ - protected processRadioStateChange(sourceParam: NgParameter, oldState: ParamValueMode) { - super.processRadioStateChange(sourceParam, oldState); - - switch (oldState) { - case ParamValueMode.CALCUL: // ancien état - switch (sourceParam.valueMode) { - case ParamValueMode.SINGLE: // nouvel état - this.setDefault(sourceParam); - break; - - case ParamValueMode.MINMAX: // nouvel état - case ParamValueMode.LISTE: - super.resetOtherRadio(sourceParam); - this.setDefault(sourceParam); - break; - - case ParamValueMode.LINK: // nouvel état - if (sourceParam.paramDefinition.hasMultipleValues) { - super.resetOtherRadio(sourceParam); - this.setDefault(sourceParam); - } else { - // mode du paramètre référencé - const refValue = sourceParam.paramDefinition.referencedValue; - if (refValue && refValue.isParameter()) { - switch ((refValue.element as ParamDefinition).valueMode) { - case ParamValueMode.MINMAX: - case ParamValueMode.LISTE: - case ParamValueMode.CALCUL: - super.resetOtherRadio(sourceParam); - this.setDefault(sourceParam); - break; - - case ParamValueMode.LINK: - throw new Error(`références de paramètre en chaîne non pris en charge`); // cas à traiter - } - } - } - break; - } - } - } } diff --git a/src/app/formulaire/definition/form-definition.ts b/src/app/formulaire/definition/form-definition.ts index be1369a87..0c43a6bf9 100644 --- a/src/app/formulaire/definition/form-definition.ts +++ b/src/app/formulaire/definition/form-definition.ts @@ -438,7 +438,7 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs * gestion d'un clic sur les radios */ public onRadioClick(info: any) { - // if mdoe changed, reset form results + // if mode changed, reset form results if (info.oldValueMode !== info.param.valueMode) { this.reset(); } diff --git a/src/app/formulaire/definition/form-result-fixedvar.ts b/src/app/formulaire/definition/form-result-fixedvar.ts index 291a6373a..be7137587 100644 --- a/src/app/formulaire/definition/form-result-fixedvar.ts +++ b/src/app/formulaire/definition/form-result-fixedvar.ts @@ -1,5 +1,3 @@ -import { ResultElement, cLog, ParamValueMode } from "jalhyd"; - import { FixedResults } from "../../results/fixed-results"; import { GraphType, VarResults } from "../../results/var-results"; import { ParamRadioConfig, NgParameter } from "../ngparam"; diff --git a/src/app/formulaire/ngparam.ts b/src/app/formulaire/ngparam.ts index 9d9ce7c9c..3f9f58711 100644 --- a/src/app/formulaire/ngparam.ts +++ b/src/app/formulaire/ngparam.ts @@ -1,5 +1,5 @@ import { Interval, ParamDefinition, ParamDomain, ParamValueMode, INumberIterator, - Nub, Observer, asObservable, ParamCalculability, LinkedValue } from "jalhyd"; + Observer, asObservable, ParamCalculability, LinkedValue } from "jalhyd"; import { sprintf } from "sprintf-js"; @@ -11,24 +11,16 @@ import { ServiceFactory } from "../services/service-factory"; import { FormulaireNode } from "./formulaire-node"; export enum ParamRadioConfig { - /** - * pas de radio, paramètre modifiable à la main uniquement - */ + /** pas de radio, paramètre modifiable à la main uniquement */ FIX, - /** - * boutons radio "paramètre fixé" et "paramètre à varier" - */ + /** boutons radio "paramètre fixé" et "paramètre à varier" */ VAR, - /** - * boutons radio "paramètre fixé", "paramètre à varier" et "paramètre à calculer" - */ + /** boutons radio "paramètre fixé", "paramètre à varier" et "paramètre à calculer" */ CAL, - /** - * boutons radio "paramètre fixé", "paramètre à varier" et "paramètre à calculer", "paramètre lié" - */ + /** boutons radio "paramètre fixé", "paramètre à varier" et "paramètre à calculer", "paramètre lié" */ LINK } @@ -37,17 +29,13 @@ export enum ParamRadioConfig { */ export class NgParameter extends InputField implements Observer { - constructor(private _paramDef: ParamDefinition, parent: FormulaireNode) { - super(parent); - } public unit: string; public radioConfig: ParamRadioConfig; - /** - * true si ce paramètre est celui par défaut dans un formulaire - * (cf. fichier de conf des modules de calcul, objet "options", champ "idCal") - */ - public isDefault = false; // archi bug du langage ! si on relit cette propriété sans l'avoir modifiée entre-temps, elle vaut undefined ! + constructor(private _paramDef: ParamDefinition, parent: FormulaireNode) { + super(parent); + this.radioConfig = this.radioState; + } /** * Returns a text preview of the current value(s), depending on the value mode @@ -62,9 +50,9 @@ export class NgParameter extends InputField implements Observer { valuePreview = String(p.getValue().toFixed(nDigits)); break; case ParamValueMode.MINMAX: - let min: any = p.paramValues.min; - let max: any = p.paramValues.max; - let step: any = p.paramValues.step; + let min: any = p.min; + let max: any = p.max; + let step: any = p.step; if (min) { min = min.toFixed(nDigits); } @@ -79,7 +67,7 @@ export class NgParameter extends InputField implements Observer { break; case ParamValueMode.LISTE: valuePreview = i18n.localizeText("INFO_PARAMFIELD_PARAMVARIER_VALUES"); - const vals = p.paramValues.valueList || []; + const vals = p.valueList || []; valuePreview += " " + vals.slice(0, 5).map((v) => { return v.toFixed(nDigits); }).join("; ") + "…"; @@ -161,10 +149,6 @@ export class NgParameter extends InputField implements Observer { this._confId = id; } - private get _paramValues() { - return this._paramDef.paramValues; - } - public get paramDefinition() { return this._paramDef; } @@ -216,23 +200,23 @@ export class NgParameter extends InputField implements Observer { } public get minValue() { - return this._paramValues.min; + return this._paramDef.min; } public get maxValue() { - return this._paramValues.max; + return this._paramDef.max; } public get stepRefValue(): Interval { - return this._paramValues.stepRefValue; + return this._paramDef.stepRefValue; } public get stepValue() { - return this._paramValues.step; + return this._paramDef.step; } public get valueList() { - return this._paramValues.valueList; + return this._paramDef.valueList; } public get isValid() { @@ -274,11 +258,19 @@ export class NgParameter extends InputField implements Observer { throw new Error("invalid parameter radio configuration " + s); } + /** + * Sets this parameter as the one to be computed + */ + public setCalculated() { + this.paramDefinition.setCalculated(); + } + /** * Asks the ParamDefinition for its current value + * @TODO replace with singleValue to avoid displaying computation results ? */ - public getValue(triggerChainComputation: boolean = false) { - return this._paramDef.getValue(triggerChainComputation); + public getValue() { + return this._paramDef.getValue(); } /** @@ -307,32 +299,32 @@ export class NgParameter extends InputField implements Observer { } public setMinValue(sender: any, v: number) { - const changed = (this._paramValues.min !== v); - this._paramValues.min = v; + const changed = (this._paramDef.min !== v); + this._paramDef.min = v; if (changed) { this.notifyValueModified(sender); } } public setMaxValue(sender: any, v: number) { - const changed = (this._paramValues.max !== v); - this._paramValues.max = v; + const changed = (this._paramDef.max !== v); + this._paramDef.max = v; if (changed) { this.notifyValueModified(sender); } } public setStepValue(sender: any, v: number) { - const changed = (this._paramValues.step !== v); - this._paramValues.step = v; + const changed = (this._paramDef.step !== v); + this._paramDef.step = v; if (changed) { this.notifyValueModified(sender); } } public setValueList(sender: any, l: number[]) { - const changed = (JSON.stringify(this._paramValues.valueList) !== JSON.stringify(l)); - this._paramValues.valueList = l; + const changed = (JSON.stringify(this._paramDef.valueList) !== JSON.stringify(l)); + this._paramDef.valueList = l; if (changed) { this.notifyValueModified(sender); } @@ -376,15 +368,22 @@ export class NgParameter extends InputField implements Observer { o.addObserver(this); // pour être prévenu des changements de valeur de l'object référencé } + let value; + try { + value = this.getValue(); + } catch (e) { + // console.log("undefined target value (pending calculation)"); + } + this.notifyObservers({ "action": "valueLinkChange", - "value": this.getValue() + "value": value }); } } public checkValue(val: number) { - this._paramDef.checkValue(val); + this._paramDef.checkValueAgainstDomain(val); } public checkList(l: number[]) { @@ -415,8 +414,6 @@ export class NgParameter extends InputField implements Observer { this.setValue(this, +val); } this.radioConfig = NgParameter.getRadioConfig(radioConfig); - // tslint:disable-next-line:max-line-length - this.isDefault = false; // malgré le fait qu'il soit initialisé dans la déclaration de la classe NgParam à false, quand on relit sa valeur, il vaut undefined (merci Microsoft) } public verifiesDependency(d: Dependency): boolean { -- GitLab