diff --git a/e2e/calc-all-examples.e2e-spec.ts b/e2e/calc-all-examples.e2e-spec.ts index 5d5bcf7de0fef88b3fe3ceedb7245afc86eee5e0..4a078b70d549554132d46ef46ae5fe07c7260aa4 100644 --- a/e2e/calc-all-examples.e2e-spec.ts +++ b/e2e/calc-all-examples.e2e-spec.ts @@ -53,9 +53,10 @@ describe("ngHyd − example sessions −", async () => { if (examples.length > i) { // click example #i await examples[i].click(); - await browser.sleep(50); + await browser.sleep(200); const nbModules = await navbar.getCalculatorEntriesCount(); + await browser.sleep(200); for (let j = 0; j < nbModules; j++) { // select module await navbar.openNthCalculator(j); diff --git a/e2e/examples-empty-fields.e2e-spec.ts b/e2e/examples-empty-fields.e2e-spec.ts index 5730129307b9310b1f38ea3b4e4e3ef2e11d4081..491ef77c6db5260926874508da87d24dca61378f 100644 --- a/e2e/examples-empty-fields.e2e-spec.ts +++ b/e2e/examples-empty-fields.e2e-spec.ts @@ -58,4 +58,97 @@ describe("ngHyd - Check that examples fields are not empty with 'empty fields on const emptys = [false, false, false, false, false]; await checkFields(inputIds, emptys); }); + + it("calculated parameter initial value when discharge law is modified", async () => { + // start page + await navBar.clickNewCalculatorButton(); + await browser.sleep(200); + + // open 1st example + const examples = await element.all(by.css("#examples-list .load-example")); + await examples[0].click(); + await browser.sleep(50); + + // select wall module + await navBar.openNthCalculator(4); + await browser.sleep(50); + + // modify 1st structure discharge law + const dischargeSelect = calcPage.getSelectById("select_loidebit"); + await calcPage.changeSelectValue(dischargeSelect, 1); + await browser.sleep(200); + + // open initial dialog + const initDlgButton = element(by.className("param-computed-more")); + await initDlgButton.click(); + await browser.sleep(200); + + // check input value is not null + const input = calcPage.getInputById("initval-input"); + const underlyingInput = input.element(by.id("0_h1")); + const txt = await underlyingInput.getAttribute("value"); + expect(txt === "").toEqual(false); + }); +}); + +describe("ngHyd - Check that examples work with 'empty fields on calculator creation' enabled - ", () => { + let prefPage: PreferencesPage; + let navBar: Navbar; + let calcPage: CalculatorPage; + + beforeEach(async () => { + prefPage = new PreferencesPage(); + navBar = new Navbar(); + calcPage = new CalculatorPage(); + + // enable evil option "empty fields on module creation" + await prefPage.navigateTo(); + await browser.sleep(200); + await prefPage.enableEvilEmptyFields(); + await browser.sleep(200); + }); + + it("when calculation is run on a generated fish ladder calculator", async () => { + debugger + // start page + await navBar.clickNewCalculatorButton(); + await browser.sleep(200); + + // open 1st example + const examples = await element.all(by.css("#examples-list .load-example")); + await examples[0].click(); + await browser.sleep(50); + + // select wall module + await navBar.openNthCalculator(4); + await browser.sleep(50); + + // run calculation + const calcButton = calcPage.getCalculateButton(); + await calcButton.click(); + await browser.sleep(200); + + // click "generate PAB" button + const genButton = calcPage.getGeneratePabButton(); + await genButton.click(); + await browser.sleep(200); + + // write "6" in basin count input + const nbBassins = calcPage.getInputById("generatePabNbBassins"); + await nbBassins.sendKeys("6"); + await browser.sleep(50); + + // click "Generate PAB" + await element(by.css("dialog-generate-pab button#do-generate")).click(); + await browser.sleep(1000); + + // calculate PAB + const calcButtonPAB = calcPage.getCalculateButton(); + await calcButtonPAB.click(); + await browser.sleep(200); + + // check that result is not empty + const hasResults = await calcPage.hasResults(); + expect(hasResults).toBe(true); + }); }); diff --git a/e2e/ouvrages-empty-fields.e2e-spec.ts b/e2e/ouvrages-empty-fields.e2e-spec.ts index 096393e60d6a7d0d1176231b0c1c6e028daea1dc..6eac089d57e978822582a07de47244ede81f3db7 100644 --- a/e2e/ouvrages-empty-fields.e2e-spec.ts +++ b/e2e/ouvrages-empty-fields.e2e-spec.ts @@ -2,40 +2,44 @@ import { ListPage } from "./list.po"; import { browser, by, element } from "protractor"; import { CalculatorPage } from "./calculator.po"; import { AppPage } from "./app.po"; +import { PreferencesPage } from "./preferences.po"; +import { Navbar } from "./navbar.po"; /** * Check that created/cloned structures have empty fields when * "empty fields on calculator creation" is enabled */ describe("ngHyd - check that created/cloned structures have empty fields - ", () => { - //let prefPage: PreferencesPage; - let startPage: AppPage; + let prefPage: PreferencesPage; let listPage: ListPage; let calcPage: CalculatorPage; + let navBar: Navbar; beforeAll(() => { - //prefPage = new PreferencesPage(); - startPage = new AppPage(); + prefPage = new PreferencesPage(); listPage = new ListPage(); calcPage = new CalculatorPage(); + navBar = new Navbar(); + browser.manage().window().setPosition(2000, 30); }); beforeEach(async () => { // enable evil option "empty fields on module creation" - // await prefPage.navigateTo(); - // await prefPage.enableEvilEmptyFields(); // message "stale element reference: element is not attached to the page document" - // await browser.sleep(200); - - // assume that "empty fields on module creation" is true by default + await prefPage.navigateTo(); + await browser.sleep(200); + await prefPage.enableEvilEmptyFields(); + await browser.sleep(200); + }); + async function setup() { // start page - await startPage.navigateTo(); + await navBar.clickNewCalculatorButton(); await browser.sleep(200); // open structures calculator await listPage.clickMenuEntryForCalcType(8); await browser.sleep(200); - }); + } /** * check that a input set is in a given (empty/filled) state @@ -53,9 +57,11 @@ describe("ngHyd - check that created/cloned structures have empty fields - ", () } it("when a structure calculator is created", async () => { + await setup(); + // check 1st structure empty fields - const inputIds = ["Q", "calc_Z1", "Z2", "0_ZDV", "0_L", "0_W", "0_CdGR"]; - const emptys = [true, false, true, true, true, true, false]; + const inputIds = ["Q", "Z1", "Z2", "0_ZDV", "0_L", "0_W", "0_CdGR"]; + const emptys = [true, true, true, true, true, true, false]; await checkFields(inputIds, emptys); // change 1st structure type to rectangular weir @@ -64,12 +70,14 @@ describe("ngHyd - check that created/cloned structures have empty fields - ", () await browser.sleep(200); // check 1st structure empty fields - const inputIds2 = ["Q", "calc_Z1", "Z2", "0_ZDV", "0_L", "0_CdWR"]; - const emptys2 = [true, false, true, true, true, false]; + const inputIds2 = ["Q", "Z1", "Z2", "0_ZDV", "0_L", "0_CdWR"]; + const emptys2 = [true, true, true, true, true, false]; await checkFields(inputIds2, emptys2); }); it("when a structure is added", async () => { + await setup(); + // add structure const addStruct = calcPage.getAddStructureButton(); await addStruct.click(); @@ -81,6 +89,8 @@ describe("ngHyd - check that created/cloned structures have empty fields - ", () }); it("when a structure is copied", async () => { + await setup(); + // copy structure const addStruct = calcPage.getCopyStructureButton(); await addStruct.click(); @@ -91,7 +101,9 @@ describe("ngHyd - check that created/cloned structures have empty fields - ", () await checkFields(inputIds, emptys); }); - it("when a modified structure is copied", async () => { + it("when a modified structure is copied (type)", async () => { + await setup(); + // change 1st structure type to rectangular weir const structSelect = calcPage.getSelectById("select_structure"); await calcPage.changeSelectValue(structSelect, 1); @@ -103,7 +115,8 @@ describe("ngHyd - check that created/cloned structures have empty fields - ", () await browser.sleep(200); // change 2nd structure type to rectangular gate - const structSelect2 = element(by.className("ng-tns-c3-47")); + const selects = await element.all(by.css("mat-select#select_structure")); + const structSelect2 = selects[1]; await calcPage.changeSelectValue(structSelect2, 4); await browser.sleep(200); @@ -113,7 +126,28 @@ describe("ngHyd - check that created/cloned structures have empty fields - ", () await checkFields(inputIds, emptys); }); + it("when a modified structure is copied (input)", async () => { + await setup(); + + // fill + const inp = calcPage.getInputById("0_ZDV"); + await inp.clear(); + await inp.sendKeys("1"); + + // copy structure + const addStruct = calcPage.getCopyStructureButton(); + await addStruct.click(); + await browser.sleep(200); + + // check empty fields + const inputIds = ["1_ZDV", "1_L", "1_W", "1_CdGR"]; + const emptys = [false, true, true, false]; + await checkFields(inputIds, emptys); + }); + it("except for discharge coefficient when a Larinier weir is used", async () => { + await setup(); + // change 1st structure type to rectangular weir const structSelect = calcPage.getSelectById("select_structure"); await calcPage.changeSelectValue(structSelect, 1); diff --git a/e2e/pab-cloisons-empty-fields.e2e-spec.ts b/e2e/pab-cloisons-empty-fields.e2e-spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..7e99a7de489e6eb9effcb0da652816bed78fbbb4 --- /dev/null +++ b/e2e/pab-cloisons-empty-fields.e2e-spec.ts @@ -0,0 +1,135 @@ +import { ListPage } from "./list.po"; +import { PreferencesPage } from "./preferences.po"; +import { browser, by, element } from "protractor"; +import { CalculatorPage } from "./calculator.po"; +import { AppPage } from "./app.po"; +import { Navbar } from "./navbar.po"; + +/** + * enable evil option "empty fields on module creation" + */ +async function enableEmptyFieldsOption(prefPage: PreferencesPage) { + await prefPage.navigateTo(); + await browser.sleep(200); + await prefPage.enableEvilEmptyFields(); + await browser.sleep(200); +} + +/** + * check that a input set is in a given (empty/filled) state + * @param inputIds id of the inputs to check + * @param emptys empty/not empty state array + */ +async function checkFields(calcPage: CalculatorPage, inputIds: string[], emptys: boolean[]) { + let n = 0; + for (const id of inputIds) { + const inp = await calcPage.getInputById(id); + const txt = await inp.getAttribute("value"); + expect(txt === "").toEqual(emptys[n]); + n++; + } +} + +async function fillInput(calcPage: CalculatorPage, symbol: string) { + const inp = calcPage.getInputById(symbol); + await inp.clear(); + await inp.sendKeys("1"); +} + +/** + * Check that when "empty fields on calculator creation" is enabled + * fields are empty in the "generate fish ladder" dialog of the + * cross walls calculator + */ +describe("ngHyd - check the cross walls calculator has empty fields - ", () => { + let prefPage: PreferencesPage; + let listPage: ListPage; + let calcPage: CalculatorPage; + let navBar: Navbar; + + beforeAll(() => { + prefPage = new PreferencesPage(); + listPage = new ListPage(); + calcPage = new CalculatorPage(); + navBar = new Navbar(); + }); + + beforeEach(async () => { + await enableEmptyFieldsOption(prefPage); + }); + + it("in the 'generate fish ladder' dialog", async () => { + // open cross walls calculator + await navBar.clickNewCalculatorButton(); + await listPage.clickMenuEntryForCalcType(10); + await browser.sleep(200); + + // fill inputs + await fillInput(calcPage, "Z1"); + await fillInput(calcPage, "LB"); + await fillInput(calcPage, "BB"); + await fillInput(calcPage, "PB"); + await fillInput(calcPage, "DH"); + await fillInput(calcPage, "0_h1"); + await fillInput(calcPage, "0_L"); + await fillInput(calcPage, "0_CdWSL"); + + // calculate + const calcButton = calcPage.getCalculateButton(); + await calcButton.click(); + await browser.sleep(200); + + // click "generate PAB" button + const genButton = calcPage.getGeneratePabButton(); + await genButton.click(); + await browser.sleep(200); + + await checkFields(calcPage, ["generatePabNbBassins"], [true]); + }); +}); + +/** + * Check that when "empty fields on calculator creation" is enabled + * fields are not empty after calculation + */ +describe("ngHyd - check the cross walls calculator has no empty field - ", () => { + let prefPage: PreferencesPage; + let listPage: ListPage; + let calcPage: CalculatorPage; + let navBar: Navbar; + + beforeAll(() => { + prefPage = new PreferencesPage(); + listPage = new ListPage(); + calcPage = new CalculatorPage(); + navBar = new Navbar(); + }); + + beforeEach(async () => { + await enableEmptyFieldsOption(prefPage); + }); + + it("after calculation", async () => { + // open cross walls calculator + await navBar.clickNewCalculatorButton(); + await listPage.clickMenuEntryForCalcType(10); + await browser.sleep(200); + + // fill inputs + await fillInput(calcPage, "Z1"); + await fillInput(calcPage, "LB"); + await fillInput(calcPage, "BB"); + await fillInput(calcPage, "PB"); + await fillInput(calcPage, "DH"); + await fillInput(calcPage, "0_h1"); + await fillInput(calcPage, "0_L"); + await fillInput(calcPage, "0_CdWSL"); + + // calculate + const calcButton = calcPage.getCalculateButton(); + await calcButton.click(); + await browser.sleep(200); + + await checkFields(calcPage, ["Z1", "LB", "BB", "PB", "DH", "0_h1", "0_L", "0_CdWSL"], [false, false, false, false, false, false, false, false]); + }); +}); diff --git a/jalhyd_branch b/jalhyd_branch index 189ba8cae35bd6340cbea73ec07eb647cce1af76..626e97d71d9e3364f9abe16f7e3c8d70dea5a7fa 100644 --- a/jalhyd_branch +++ b/jalhyd_branch @@ -1 +1 @@ -307-courbe-de-remous-crash-de-l-application-sur-donnees-erronees \ No newline at end of file +devel \ No newline at end of file diff --git a/src/app/components/base-param-input/base-param-input.component.ts b/src/app/components/base-param-input/base-param-input.component.ts index 25573571b021a64a06672559fa919981d00f8d8a..883fa077213c7a069a3942c163faceecdcf97e41 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 @@ -15,7 +15,7 @@ export class NgBaseParam extends Observable { constructor(symb: string, d: ParamDomain | ParamDomainValue, val: number, unit?: string) { super(); - this._param = new ParamDefinition(null, symb, d, unit, val); + this._param = new ParamDefinition(null, symb, d, unit, val, undefined, undefined, false); } public get param() { diff --git a/src/app/components/calculator-list/calculator-list.component.ts b/src/app/components/calculator-list/calculator-list.component.ts index fcc96d90f5b96ff89aa806113a1e161274abdacb..cd37dad302aa6a325990cc70e314b5a7eeccbb69 100644 --- a/src/app/components/calculator-list/calculator-list.component.ts +++ b/src/app/components/calculator-list/calculator-list.component.ts @@ -181,10 +181,6 @@ export class CalculatorListComponent implements OnInit { } } } - - if (this.appSetupService.enableEmptyFieldsOnFormInit) { - f.emptyFields(); - } } public get nbOpenCalculators() { 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 38bcc40fb662801af72f0d5f4b83463062b34ec3..9037cd52b516c8eb956399ebcba17197100dff78 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 @@ -3,7 +3,7 @@ <form> <div mat-dialog-content> - <ngparam-input [title]="param.title"></ngparam-input> + <ngparam-input id="initval-input" [title]="param.title"></ngparam-input> </div> <div mat-dialog-actions [attr.align]="'end'"> diff --git a/src/app/components/dialog-generate-pab/dialog-generate-pab.component.ts b/src/app/components/dialog-generate-pab/dialog-generate-pab.component.ts index 9634a342bf3e3109f3670613af3adbb00a7cb1ff..202aa1fd89632c45871623cdc91bcbece1f12737 100644 --- a/src/app/components/dialog-generate-pab/dialog-generate-pab.component.ts +++ b/src/app/components/dialog-generate-pab/dialog-generate-pab.component.ts @@ -18,8 +18,6 @@ export class DialogGeneratePABComponent { public coteAmont = 102; - public chute: number; - public nbBassins = 6; constructor( @@ -29,21 +27,18 @@ export class DialogGeneratePABComponent { @Inject(MAT_DIALOG_DATA) public data: any ) { const nDigits = this.appSetupService.displayPrecision; - this.coteAmont = round(data.coteAmont, nDigits); - this.debit = round(data.debit, nDigits); - this.chute = round(data.chute, nDigits); + this.coteAmont = data.coteAmont ? round(data.coteAmont, nDigits) : undefined; + this.debit = data.debit ? round(data.debit, nDigits) : undefined; + this.nbBassins = data.nbBassins; } public generatePAB() { - // calculate downstream elevation - const coteAval = this.coteAmont - (this.chute * this.nbBassins); // create PAB this.dialogRef.close({ generate: true, - debit: this.debit, - coteAmont: this.coteAmont, - coteAval: coteAval, - nbBassins: this.nbBassins + debit: +this.debit, + coteAmont: +this.coteAmont, + nbBassins: +this.nbBassins }); } diff --git a/src/app/components/generic-calculator/calculator.component.ts b/src/app/components/generic-calculator/calculator.component.ts index 2608ce76e149a26609f9fc4f60194b0f0b1c3fbb..9650543c6a0add5f27c5b2c5bb7aa61ea0e44f64 100644 --- a/src/app/components/generic-calculator/calculator.component.ts +++ b/src/app/components/generic-calculator/calculator.component.ts @@ -1,5 +1,7 @@ -import { Component, OnInit, DoCheck, OnDestroy, ViewChild, ViewChildren, - QueryList, AfterViewChecked, ElementRef, Inject, forwardRef, isDevMode } from "@angular/core"; +import { + Component, OnInit, DoCheck, OnDestroy, ViewChild, ViewChildren, + QueryList, AfterViewChecked, ElementRef, Inject, forwardRef, isDevMode +} from "@angular/core"; import { ActivatedRoute, Router } from "@angular/router"; import { @@ -58,6 +60,7 @@ import { MatomoTracker } from "ngx-matomo"; import { sprintf } from "sprintf-js"; import * as XLSX from "xlsx"; +import { ServiceFactory } from "app/services/service-factory"; @Component({ selector: "hydrocalc", @@ -307,7 +310,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe } public get quicknavItems() { - const elts = [ "input", "results" ]; + const elts = ["input", "results"]; if (this.isWide && this.hasResults) { elts.push("charts"); } @@ -328,7 +331,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe * the UI validity state) */ ngDoCheck() { - this.isCalculateDisabled = ! this._isUIValid; + this.isCalculateDisabled = !this._isUIValid; } ngOnDestroy() { @@ -362,7 +365,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe } public ngAfterViewChecked() { - if (! this.firstViewChecked) { + if (!this.firstViewChecked) { this.firstViewChecked = true; this.afterFirstViewChecked(); } @@ -393,7 +396,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe } public doCompute() { - if (! isDevMode()) { + if (!isDevMode()) { this.matomoTracker.trackEvent("userAction", "triggerCalculation", CalculatorType[this._formulaire.currentNub.calcType]); } this._formulaire.resetResults([]); @@ -444,7 +447,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe try { this.appComponent.scrollToQuicknav("results"); } catch (e) { - const element = document.getElementById ("fake-results-anchor"); + const element = document.getElementById("fake-results-anchor"); if (element) { element.scrollIntoView(); } @@ -471,7 +474,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe */ private updateUIValidity() { this._isUIValid = false; - if (! this._formulaire.calculateDisabled) { + if (!this._formulaire.calculateDisabled) { // all fieldsets must be valid this._isUIValid = true; if (this._fieldsetComponents !== undefined) { @@ -694,14 +697,14 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe private allParamsAreFixed(except: string[] = []) { let ret = true; for (const p of this._formulaire.currentNub.parameterIterator) { - if (! except.includes(p.symbol)) { + if (!except.includes(p.symbol)) { if (p.valueMode === ParamValueMode.LINK) { - ret = ret && (! p.hasMultipleValues); + ret = ret && (!p.hasMultipleValues); } else { // avoid calling hasMultipleValues here, because changing parameter mode in GUI // switches valueMode before setting min/max/step or valuesList, and iterator // checker fails to count values that do not exist yet - ret = ret && (! [ ParamValueMode.LISTE, ParamValueMode.MINMAX ].includes(p.valueMode)); + ret = ret && (![ParamValueMode.LISTE, ParamValueMode.MINMAX].includes(p.valueMode)); } } } @@ -716,10 +719,10 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe } public get uitextGeneratePabTitle() { - if (! this.hasResults) { + if (!this.hasResults) { return this.intlService.localizeText("INFO_CALCULATE_FIRST"); } - if (! this.allParamsAreFixed()) { + if (!this.allParamsAreFixed()) { return this.intlService.localizeText("INFO_PARAMETRES_FIXES"); } return ""; @@ -731,41 +734,48 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe public generatePAB() { // création du dialogue de génération d'une passe à bassin const cloisons = (this._formulaire.currentNub as Cloisons); + const chute = cloisons.prms.DH.V; + const debit = cloisons.prms.Q.V; + const zAmont = cloisons.prms.Z1.V; + const nbBassins = ServiceFactory.applicationSetupService.enableEmptyFieldsOnFormInit ? undefined : 6; const dialogRef = this.generatePABDialog.open( - DialogGeneratePABComponent, - { - data: { - chute: cloisons.prms.DH.V, - debit: cloisons.prms.Q.V, - coteAmont: cloisons.prms.Z1.V - }, - disableClose: false - } + DialogGeneratePABComponent, + { + data: { + debit: debit, + coteAmont: zAmont, + nbBassins: nbBassins + }, + disableClose: false + } ); dialogRef.afterClosed().subscribe(async result => { - if (result) { - if (result.generate) { - const f: FormulaireDefinition = await this.formulaireService.createFormulaire(CalculatorType.Pab); - const pab = (f.currentNub as Pab); - const params = pab.prms; - // paramètres hydrauliques - params.Q.singleValue = result.debit; - params.Z1.singleValue = result.coteAmont; - params.Z2.singleValue = result.coteAval; - // création des bassins - pab.deleteChild(0); - pab.addCloisonsFromModel(this._formulaire.currentNub as Cloisons, result.nbBassins); - // go to new PAB - this.router.navigate(["/calculator", f.uid]); + if (result) { + if (result.generate) { + const f: FormulaireDefinition = await this.formulaireService.createFormulaire(CalculatorType.Pab); + const pab = (f.currentNub as Pab); + const params = pab.prms; + // calculate downstream elevation + const chute = cloisons.prms.DH.V; + const coteAval = result.coteAmont - (chute * result.nbBassins); + // paramètres hydrauliques + params.Q.singleValue = result.debit; + params.Z1.singleValue = result.coteAmont; + params.Z2.singleValue = coteAval; + // création des bassins + pab.deleteChild(0); + pab.addCloisonsFromModel(this._formulaire.currentNub as Cloisons, result.nbBassins); + // go to new PAB + this.router.navigate(["/calculator", f.uid]); + } } - } }); } public get generateSPAmontEnabled(): boolean { const bief = (this._formulaire.currentNub as Bief); if (bief.prms.Z1 === bief.calculatedParam) { - return this.hasResults && ! bief.result.hasErrorMessages(); + return this.hasResults && !bief.result.hasErrorMessages(); } else { // check that linked values are available, if any return ( @@ -778,7 +788,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe public get generateSPAvalEnabled(): boolean { const bief = (this._formulaire.currentNub as Bief); if (bief.prms.Z2 === bief.calculatedParam) { - return this.hasResults && ! bief.result.hasErrorMessages(); + return this.hasResults && !bief.result.hasErrorMessages(); } else { // check that linked values are available, if any return ( @@ -789,7 +799,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe } public get uitextGenerateSPAmontTitle(): string { - if (! this.generateSPAmontEnabled) { + if (!this.generateSPAmontEnabled) { return this.intlService.localizeText("INFO_CALCULATE_FIRST"); } else { return ""; @@ -797,7 +807,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe } public get uitextGenerateSPAvalTitle(): string { - if (! this.generateSPAvalEnabled) { + if (!this.generateSPAvalEnabled) { return this.intlService.localizeText("INFO_CALCULATE_FIRST"); } else { return ""; @@ -835,7 +845,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe const bief = (this._formulaire.currentNub as Bief); return generateValuesCombination( bief, - [ Z, ZF ], + [Z, ZF], (nub: Nub, values: { [key: string]: number }): number => { return round(values[Z.symbol] - values[ZF.symbol], 3); } @@ -849,7 +859,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe const bief = (this._formulaire.currentNub as Bief); return generateValuesCombination( bief, - [ bief.prms.ZF1, bief.prms.ZF2, bief.prms.Long ], + [bief.prms.ZF1, bief.prms.ZF2, bief.prms.Long], (nub: Nub, values: { [key: string]: number }): number => { return round((values["ZF1"] - values["ZF2"]) / values["Long"], 5); } @@ -873,7 +883,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe // "If" is hidden in Bief, for ex. bief.section.getParameter(p.symbol).visible // do not link Y and If - && ! [ "If", "Y" ].includes(p.symbol) + && !["If", "Y"].includes(p.symbol) ) { const bP = bief.section.getParameter(p.symbol); if (bP.valueMode === ParamValueMode.LINK) { @@ -895,11 +905,11 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe } public get generateRuSpEnabled(): boolean { - return this.hasResults && ! this._formulaire.currentNub.result.hasErrorMessages(); + return this.hasResults && !this._formulaire.currentNub.result.hasErrorMessages(); } public get uitextGenerateRuSpTitle(): string { - if (! this.generateRuSpEnabled) { + if (!this.generateRuSpEnabled) { return this.intlService.localizeText("INFO_CALCULATE_FIRST"); } else { return ""; @@ -935,7 +945,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe const parCalage = (this._formulaire.currentNub as Par); return ( this.hasResults - && ! parCalage.result.hasErrorMessages() + && !parCalage.result.hasErrorMessages() && parCalage.prms.Z1.isDefined && parCalage.prms.Z2.isDefined ); @@ -943,12 +953,12 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe public get uitextGenerateParSimulationTitle(): string { const parCalage = (this._formulaire.currentNub as Par); - if (! this.hasResults || parCalage.result.hasErrorMessages()) { + if (!this.hasResults || parCalage.result.hasErrorMessages()) { return this.intlService.localizeText("INFO_CALCULATE_FIRST"); } if ( - ! parCalage.prms.Z1.isDefined - || ! parCalage.prms.Z2.isDefined + !parCalage.prms.Z1.isDefined + || !parCalage.prms.Z2.isDefined ) { return this.intlService.localizeText("INFO_Z1_Z2_MUST_BE_DEFINED"); } @@ -1025,7 +1035,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe public get exportAllPbResultsEnabled(): boolean { const pb = (this._formulaire as FormulairePrebarrage).currentNub as PreBarrage; - return (pb.result !== undefined && ! pb.result.hasOnlyErrors); + return (pb.result !== undefined && !pb.result.hasOnlyErrors); } /** @@ -1163,11 +1173,11 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe protected async doGenerateParSimWithValues(v: any) { const parCalage = (this._formulaire.currentNub as Par); const psim = new ParSimulationParams( - round(v.Q, 3), round(v.Z1, 3), round(v.Z2, 3), - round(v.S, 3), round(v.P, 3), round(v.Nb, 3), - round(v.ZR1, 3), round(v.ZD1, 3), round(v.ZR2, 3), - round(v.ZD2, 3), round(v.L, 3), round(v.a, 3), - round(v.N, 3), round(v.M, 3) + round(v.Q, 3), round(v.Z1, 3), round(v.Z2, 3), + round(v.S, 3), round(v.P, 3), round(v.Nb, 3), + round(v.ZR1, 3), round(v.ZD1, 3), round(v.ZR2, 3), + round(v.ZD2, 3), round(v.L, 3), round(v.a, 3), + round(v.N, 3), round(v.M, 3) ); const parSimulation = new ParSimulation(psim); parSimulation.parType = parCalage.parType; @@ -1188,7 +1198,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe const dialogRef = this.loadPredefinedEspeceDialog.open( DialogLoadPredefinedEspeceComponent, { - data: { }, + data: {}, disableClose: false } ); @@ -1211,7 +1221,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe DialogConfirmCloseCalcComponent, { data: { - uid: this._formulaire.currentNub.uid + uid: this._formulaire.currentNub.uid }, disableClose: true } diff --git a/src/app/components/generic-input/generic-input.component.ts b/src/app/components/generic-input/generic-input.component.ts index 5b31ee4e81da662abc5897837387b656547bdf10..3dc390d50f261a0dab352154f62a34000e46b885 100644 --- a/src/app/components/generic-input/generic-input.component.ts +++ b/src/app/components/generic-input/generic-input.component.ts @@ -263,12 +263,7 @@ export abstract class GenericInputComponentDirective implements OnChanges { if (valid && this._uiValue !== "") { val = +this._uiValue; // cast UI value to Number } - if (this.setAndValidateModel(this, val)) { - // set parameter "modified" flag - if (this._model instanceof NgParameter) { - this._model.isValueModified = true; - } - } + this.setAndValidateModel(this, val); } } diff --git a/src/app/components/pb-schema/pb-schema.component.ts b/src/app/components/pb-schema/pb-schema.component.ts index e1e74c9e6fcf715c1a11c1da7dbf121960ea5801..7ea4ba81d47b6bbaede7cb478cbf84bef38b4b36 100644 --- a/src/app/components/pb-schema/pb-schema.component.ts +++ b/src/app/components/pb-schema/pb-schema.component.ts @@ -21,6 +21,7 @@ import { AppComponent } from "../../app.component"; import { fv } from "app/util"; import { FormulaireNode } from "app/formulaire/elements/formulaire-node"; +import { ServiceFactory } from "app/services/service-factory"; /** * The interactive schema for calculator type "PreBarrage" (component) @@ -492,35 +493,10 @@ export class PbSchemaComponent implements AfterViewInit, AfterContentInit, OnIni return this.i18nService.localizeText("INFO_FIELDSET_COPY"); } - /** - * Set value of all single parameters to undefined, except for the given parameter ids - */ - private emptyFields(basin: PbBassin, except: string[] = FormulaireNode.NeverEmptyFields) { - // save current calculated param, as setting value on a CALC param will - // change its mode and choose another calculated param by default - let calcP: ParamDefinition; - for (const p of basin.parameterIterator) { - if ( - [ParamValueMode.SINGLE, ParamValueMode.CALCUL].includes(p.valueMode) - && !except.includes(p.symbol) - ) { - if (p.valueMode === ParamValueMode.CALCUL) { - calcP = p; - } - p.setValue(undefined); - } - } - // restore original calculated param - if (calcP !== undefined) { - calcP.setCalculated(); - } - } - /** Adds a new lone basin */ public onAddBasinClick() { - const newBasin = new PbBassin(new PbBassinParams(20, 99)); + const newBasin = new PbBassin(new PbBassinParams(20, 99, ServiceFactory.applicationSetupService.enableEmptyFieldsOnFormInit)); this.model.addChild(newBasin); - this.emptyFields(newBasin); this.clearResults(); this.refreshWithSelection(newBasin.uid); this.calculatorComponent.showPBInputData = true; diff --git a/src/app/formulaire/definition/form-definition.ts b/src/app/formulaire/definition/form-definition.ts index 442a96ef680fe5e41f5bb28cc62b0ac3e64dc6a4..3fd3ee3a274ab1fedb90e0ae8b2c166701210aea 100644 --- a/src/app/formulaire/definition/form-definition.ts +++ b/src/app/formulaire/definition/form-definition.ts @@ -9,7 +9,8 @@ import { acSection, ParamDefinition, Result, - VariatedDetails + VariatedDetails, + Prop_NullParameters } from "jalhyd"; import { FormulaireElement } from "../elements/formulaire-element"; @@ -110,6 +111,7 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs */ public initNub(props?: Props) { const p = props ? props : new Props(this.defaultProperties); + p.setPropValue(Prop_NullParameters, ServiceFactory.applicationSetupService.enableEmptyFieldsOnFormInit); // transmit "empty fields" flag this.currentNub = Session.getInstance().createSessionNub(p); if (this.currentNub instanceof SectionNub) { diff --git a/src/app/formulaire/definition/form-parallel-structures.ts b/src/app/formulaire/definition/form-parallel-structures.ts index 5e35710f98d06546543fcd44fabc8ca1d6b604c1..9e4dd86d6b05615acc3555d9b8fc6b1441870589 100644 --- a/src/app/formulaire/definition/form-parallel-structures.ts +++ b/src/app/formulaire/definition/form-parallel-structures.ts @@ -1,4 +1,4 @@ -import { Structure, Nub, ParallelStructure, StructureProperties, Props, Session, ParamDefinition } from "jalhyd"; +import { Structure, Nub, ParallelStructure, StructureProperties, Props, Session, ParamDefinition, Prop_NullParameters } from "jalhyd"; import { FieldsetContainer } from "../elements/fieldset-container"; import { FieldSet } from "../elements/fieldset"; @@ -7,6 +7,7 @@ import { NgParameter } from "../elements/ngparam"; import { FieldsetTemplate } from "../elements/fieldset-template"; import { FormulaireNode } from "../elements/formulaire-node"; import { FormulaireRepeatableFieldset } from "./form-repeatable-fieldset"; +import { ServiceFactory } from "app/services/service-factory"; export class FormulaireParallelStructure extends FormulaireRepeatableFieldset { @@ -66,6 +67,7 @@ export class FormulaireParallelStructure extends FormulaireRepeatableFieldset { params["nodeType"] = templ.defaultNodeTypeFromConfig; params["structureType"] = templ.defaultStructTypeFromConfig; params["loiDebit"] = templ.defaultLoiDebitFromConfig; + params[Prop_NullParameters] = ServiceFactory.applicationSetupService.enableEmptyFieldsOnFormInit; return this.createStructure(new Props(params)); } diff --git a/src/app/formulaire/definition/form-prebarrage.ts b/src/app/formulaire/definition/form-prebarrage.ts index ebe3ea8ffdda5ae94f096a9dd6c0a3ceefa1089f..811007d2c1966bc071dc1b9739e3a9485c3ae4ec 100644 --- a/src/app/formulaire/definition/form-prebarrage.ts +++ b/src/app/formulaire/definition/form-prebarrage.ts @@ -322,21 +322,6 @@ export class FormulairePrebarrage extends FormulaireFixedVar { } } - /** - * Set value of all single parameters to undefined, except for the given parameter ids - */ - public emptyFields(except: string[] = FormulaireNode.NeverEmptyFields) { - // save current calculated param, as setting value on a CALC param will - // change its mode and choose another calculated param by default - const paramCalculated = this.currentNub.calculatedParam; - for (const p of this.currentNub.parameterIterator) { - if (! except.includes(p.symbol)) { - p.setValue(undefined); - } - } - this.currentNub.calculatedParam = paramCalculated; - } - /** * Check validity of all model parameters * @param withChildren check parameters of child nub as well diff --git a/src/app/formulaire/definition/form-section.ts b/src/app/formulaire/definition/form-section.ts index fd45ceb50c782c50436c52886767f4abbba236c0..c408e572abe092e6454ee1395e052bc0bfdaac18 100644 --- a/src/app/formulaire/definition/form-section.ts +++ b/src/app/formulaire/definition/form-section.ts @@ -20,11 +20,6 @@ export class FormulaireSection extends FormulaireFixedVar { } // show / hide dependent fields this.refreshFieldsets(); - // empty fields ? only those belonging to the specific section type - if (ServiceFactory.applicationSetupService.enableEmptyFieldsOnFormInit) { - // "LargeurBerge" is hackily used as LargeurFond in Rectangular and Trapez sections, omit it here - this.emptyFields([ "Ks", "Q", "If", "YB", "iPrec", "Y" ]); - } this.reset(); } } diff --git a/src/app/formulaire/elements/fieldset.ts b/src/app/formulaire/elements/fieldset.ts index e5a9ca15af20c8281d7652b8c609727f324f4653..4081f824133ac596b38848c2e926a0793580713e 100644 --- a/src/app/formulaire/elements/fieldset.ts +++ b/src/app/formulaire/elements/fieldset.ts @@ -73,23 +73,13 @@ export class FieldSet extends FormulaireElement implements Observer { * @param backup list of NgParameter object representation * @see backupParameters */ - public restoreParameters(backup: any[], except: string[] = FormulaireNode.NeverEmptyFields) { + public restoreParameters(backup: any[]) { // for (const p of this.allFormElements) { for (const p of this._kids) { if (p instanceof NgParameter) { for (const bp of backup) { if (p.symbol === bp.prmDef.symbol) { - // if source parameter has been user modified, copy value - if (bp.modified) { - p.loadObjectRepresentation(bp); - } - else { - // can parameter be emptied ? - if (ServiceFactory.applicationSetupService.enableEmptyFieldsOnFormInit && !except.includes(bp.prmDef.symbol)) { - p.resetValue(this, undefined); - } - // else let parameter to default value - } + p.loadObjectRepresentation(bp); break; } } @@ -421,10 +411,6 @@ export class FieldSet extends FormulaireElement implements Observer { } } - if (ServiceFactory.applicationSetupService.enableEmptyFieldsOnFormInit) { - const f = this.parentForm; - f.emptyFields(); - } break; // switch (data.action) } } diff --git a/src/app/formulaire/elements/formulaire-node.ts b/src/app/formulaire/elements/formulaire-node.ts index 0ab8a88dfd64f0fd0ec52037fea428d3d701506c..b57bec770d2d128fc76e2fcd53a43370f0efd667 100644 --- a/src/app/formulaire/elements/formulaire-node.ts +++ b/src/app/formulaire/elements/formulaire-node.ts @@ -9,11 +9,6 @@ import { NgParameter } from "./ngparam"; */ export abstract class FormulaireNode implements IObservable { - /** - * fields in fieldset that must not be empty due to enableEmptyFieldsOnFormInit option - */ - public static readonly NeverEmptyFields = ["Cd0", "CdWS", "CdGR", "CdGRS", "CdCunge", "CdWR", "CdO", "CdT"]; - /** aide en ligne */ protected _helpLink: string; @@ -145,32 +140,6 @@ export abstract class FormulaireNode implements IObservable { return new DeepFormulaireElementIterator(this); } - /** - * Set value of all single parameters to undefined, except for the given parameter ids - */ - public emptyFields(except: string[] = FormulaireNode.NeverEmptyFields) { - // save current calculated param, as setting value on a CALC param will - // change its mode and choose another calculated param by default - let calcP: NgParameter; - for (const p of this.allFormElements) { - if (p instanceof NgParameter) { - if ( - [ParamValueMode.SINGLE, ParamValueMode.CALCUL].includes(p.valueMode) - && !except.includes(p.id) && !p.isValueModified - ) { - if (p.valueMode === ParamValueMode.CALCUL) { - calcP = p; - } - p.resetValue(this, undefined); - } - } - } - // restore original calculated param - if (calcP !== undefined) { - calcP.setCalculated(); - } - } - /** * notifie un événement aux observateurs */ diff --git a/src/app/formulaire/elements/ngparam.ts b/src/app/formulaire/elements/ngparam.ts index 59c4e188fe7c766365989ccf95bd175086ad6136..43d7cb29815ed0c8e42baa5fa9910fa2b0b810a5 100644 --- a/src/app/formulaire/elements/ngparam.ts +++ b/src/app/formulaire/elements/ngparam.ts @@ -38,9 +38,6 @@ export class NgParameter extends InputField implements Observer { public disabled: boolean; - /** true if value has been modified by user */ - private _isValueModified = false; - constructor(private _paramDef: ParamDefinition, parent: FormulaireNode) { super(parent); this.radioConfig = this.radioState; @@ -284,14 +281,6 @@ export class NgParameter extends InputField implements Observer { return this._paramDef.valuesIterator; } - public get isValueModified(): boolean { - return this._isValueModified; - } - - public set isValueModified(b: boolean) { - this._isValueModified = b; - } - /** * Reads radio config from parameter calculability */ @@ -404,18 +393,6 @@ export class NgParameter extends InputField implements Observer { ); } - /** - * fixe la valeur du paramètre en tant que valeur par défaut - */ - public resetValue(sender: any, val: number) { - const changed = (this._paramDef.getValue() !== val); - this._isValueModified = false; - if (changed) { - this._paramDef.setValue(val, sender); - this.notifyValueModified(sender); - } - } - /** * fixe la valeur du paramètre. * une notification préalable est envoyée pour laisser l'occasion aux objets liés de préciser le contexte @@ -433,7 +410,6 @@ export class NgParameter extends InputField implements Observer { public resetMinValue(sender: any, v: number) { const changed = (this._paramDef.min !== v); - this._isValueModified = false; if (changed) { this._paramDef.min = v; this.notifyMinValueModified(sender); @@ -444,14 +420,12 @@ export class NgParameter extends InputField implements Observer { const changed = (this._paramDef.min !== v); if (changed) { this._paramDef.min = v; - this._isValueModified = true; this.notifyMinValueModified(sender); } } public resetMaxValue(sender: any, v: number) { const changed = (this._paramDef.max !== v); - this._isValueModified = false; if (changed) { this._paramDef.max = v; this.notifyMaxValueModified(sender); @@ -462,14 +436,12 @@ export class NgParameter extends InputField implements Observer { const changed = (this._paramDef.max !== v); if (changed) { this._paramDef.max = v; - this._isValueModified = true; this.notifyMaxValueModified(sender); } } public resetStepValue(sender: any, v: number) { const changed = (this._paramDef.step !== v); - this._isValueModified = false; if (changed) { this._paramDef.step = v; this.notifyStepValueModified(sender); @@ -480,14 +452,12 @@ export class NgParameter extends InputField implements Observer { const changed = (this._paramDef.step !== v); if (changed) { this._paramDef.step = v; - this._isValueModified = true; this.notifyStepValueModified(sender); } } public resetValueList(sender: any, l: number[]) { const changed = (JSON.stringify(this._paramDef.valueList) !== JSON.stringify(l)); - this._isValueModified = false; if (changed) { this._paramDef.valueList = l; this.notifyListValueModified(sender); @@ -498,7 +468,6 @@ export class NgParameter extends InputField implements Observer { const changed = (JSON.stringify(this._paramDef.valueList) !== JSON.stringify(l)); if (changed) { this._paramDef.valueList = l; - this._isValueModified = true; this.notifyListValueModified(sender); } } @@ -520,7 +489,6 @@ export class NgParameter extends InputField implements Observer { allowEmpty: this._allowEmpty, unit: this.unit, radioConfig: this.radioConfig, - modified: this._isValueModified } } @@ -530,7 +498,6 @@ export class NgParameter extends InputField implements Observer { this._allowEmpty = rep.allowEmpty; this.unit = rep.unit; this.radioConfig = rep.radioConfig; - this._isValueModified = rep._isValueModified; } } diff --git a/src/app/services/app-setup.service.ts b/src/app/services/app-setup.service.ts index d1f01b2af7fbc411487f2e8045bd337299b842b6..32b9f517da6c776b8a43fe6df266d80deedefc55 100644 --- a/src/app/services/app-setup.service.ts +++ b/src/app/services/app-setup.service.ts @@ -24,7 +24,7 @@ export class ApplicationSetupService extends Observable { private _maxIterations = 100; // tied to model public enableNotifications = true; public enableHotkeys = false; - public enableEmptyFieldsOnFormInit = true; + private _enableEmptyFieldsOnFormInit = true; public set computePrecision(p: number) { this._computePrecision = p; @@ -46,6 +46,14 @@ export class ApplicationSetupService extends Observable { return this._maxIterations; } + public get enableEmptyFieldsOnFormInit() { + return this._enableEmptyFieldsOnFormInit; + } + + public set enableEmptyFieldsOnFormInit(b: boolean) { + this._enableEmptyFieldsOnFormInit = b; + } + /** * just stores the current language preference, does not transmit it to I18nService, that is * not available here. @@ -71,6 +79,9 @@ export class ApplicationSetupService extends Observable { // related to @HostListener("window:beforeunload") in AppComponent this.warnBeforeTabClose = true; + // by default, create empty fields for new calculators + this.enableEmptyFieldsOnFormInit = true; + // load JSON config this.readValuesFromConfig().then((data) => { const configLanguage = this.language;