diff --git a/e2e/calculate-all-params.e2e-spec.ts b/e2e/calculate-all-params.e2e-spec.ts index 39129ac615e92f804560d9bd3db5f34e8d14f98b..9003678bdf375829abd642fb6555a3d8ff243914 100644 --- a/e2e/calculate-all-params.e2e-spec.ts +++ b/e2e/calculate-all-params.e2e-spec.ts @@ -4,6 +4,7 @@ import { Navbar } from "./navbar.po"; import { PreferencesPage } from "./preferences.po"; import { browser, element, by } from "protractor"; import { testedCalcTypes } from "./tested_calctypes"; +import { scrollPageToTop } from "./util.po"; /** * For all calculators, try to calculate every parameter: check that only one parameter @@ -65,7 +66,7 @@ describe("ngHyd − calculate all parameters of all calculators", async () => { // that the calculable parameters are shown if (ct === 30 && i > 0) { // prevents "Element is not clickable at point" - await browser.executeScript("window.scrollTo(0, 0);"); + await scrollPageToTop(); const inputLink = element(by.css("#pb-data-results-selector .drs-item a")); await inputLink.click(); } diff --git a/e2e/calculator.po.ts b/e2e/calculator.po.ts index 400f4b0abbc88cf80c09be86d6a159f9362823ea..82d81213ae752de04d5fca0cb695ebe9d2e9fd11 100644 --- a/e2e/calculator.po.ts +++ b/e2e/calculator.po.ts @@ -1,4 +1,5 @@ -import { by, element, ElementFinder, browser } from "protractor"; +import { by, element, ElementFinder, browser, protractor, ElementArrayFinder } from "protractor"; +import { scrollPageToTop, scrollToElement } from "./util.po"; export class CalculatorPage { @@ -25,6 +26,66 @@ export class CalculatorPage { return element(by.css("h1")); } + /** + * return all selects in the calculator which id is in the form "select_*" + */ + getAllCalculatorSelects(): ElementArrayFinder { + return element.all(by.css("mat-select[id^=select_]")); // all mat-select with id starting with "select_" + } + + /** + * get the option count of a select + */ + async getMatselectOptionCount(select: string | ElementFinder) { + const sel = select instanceof ElementFinder ? select : element(by.id(select)); + await scrollToElement(sel); + + if (await sel.isPresent() && await sel.isDisplayed()) { + await sel.click(); + const options = element.all(by.css(".cdk-overlay-container mat-option")); + await sel.sendKeys(protractor.Key.ESCAPE); // close dropdown + return await options.count(); + } + } + + /** + * get the text of the all given select options + */ + async getMatselectOptionsText(select: string | ElementFinder): Promise<string[]> { + const sel = select instanceof ElementFinder ? select : element(by.id(select)); + await scrollToElement(sel); + + if (await sel.isPresent() && await sel.isDisplayed()) { + await sel.click(); + const options = element.all(by.css(".cdk-overlay-container mat-option span")); + let res = []; + const nopt = await options.count(); + for (let o = 0; o < nopt; o++) { + const opt = options.get(o); + res.push(await opt.getText()) + } + await sel.sendKeys(protractor.Key.ESCAPE); // close dropdown + + return res; + } + } + + /** + * get select current option + */ + async getSelectCurrentOption(select: ElementFinder): Promise<ElementFinder> { + const id = await select.getAttribute("id"); + return element(by.css("mat-select#" + id + " div[id^=mat-select-value-]")) + } + + /** + * get text of select current option + */ + async getMatselectCurrentOptionText(select: ElementFinder): Promise<string> { + const currentOption = await this.getSelectCurrentOption(select); + return await currentOption.element(by.css("span span")).getText(); + } + getSelectById(id: string) { return element(by.id(id)); } @@ -91,11 +152,11 @@ export class CalculatorPage { return element.all(by.css("fixedvar-results var-results table tbody tr")); } - scrollTo(elt: ElementFinder) { - browser.controlFlow().execute(function () { - browser.executeScript("arguments[0].scrollIntoView(true)", elt.getWebElement()); - }); - } + // scrollTo(elt: ElementFinder) { + // browser.controlFlow().execute(function () { + // browser.executeScript("arguments[0].scrollIntoView(true)", elt.getWebElement()); + // }); + // } getFixedResultsTable() { return element(by.css(".fixed-results-inner-container table")); @@ -246,6 +307,7 @@ export class CalculatorPage { } async clickSaveCalcButton() { + await scrollPageToTop(); return await element(by.css("#save-calc")).click(); } @@ -287,7 +349,7 @@ export class CalculatorPage { const container = await this.findParentContainer(elt); // find radio buttons const button = container.element(by.css("mat-button-toggle.radio_" + mode + " > button")); - await browser.executeScript("window.scrollTo(0, 0);"); // sometimes button slides behind navbar and click() fails + await scrollPageToTop(); // sometimes button slides behind navbar and click() fails await button.click(); // for "var" mode, close the modal if (mode === "var") { diff --git a/e2e/clone-all-calc.e2e-spec.ts b/e2e/clone-all-calc.e2e-spec.ts index e55c8b3f461791ffad1b8207ee81070e7c2b8879..ca352163c6d9e521ff65dd44fc3fc3160867356a 100644 --- a/e2e/clone-all-calc.e2e-spec.ts +++ b/e2e/clone-all-calc.e2e-spec.ts @@ -4,6 +4,7 @@ import { Navbar } from "./navbar.po"; import { browser } from "protractor"; import { PreferencesPage } from "./preferences.po"; import { testedCalcTypes } from "./tested_calctypes"; +import { scrollPageToTop } from "./util.po"; /** * Clone calculators @@ -48,7 +49,7 @@ describe("ngHyd − clone all calculators with all possible <select> values", () const sourceValues = await calcPage.storeAllInputValues(); // clone calculator - await browser.executeScript("window.scrollTo(0, 0);"); + await scrollPageToTop(); await calcPage.clickCloneCalcButton(); await browser.sleep(300); diff --git a/e2e/clone-calc.e2e-spec.ts b/e2e/clone-calc.e2e-spec.ts index c09edd3c8681301af749ec21aeda27dc34e51a54..038a90e661a28a6526a9b143f407842f3bed4329 100644 --- a/e2e/clone-calc.e2e-spec.ts +++ b/e2e/clone-calc.e2e-spec.ts @@ -4,6 +4,7 @@ import { CalculatorPage } from "./calculator.po"; import { Navbar } from "./navbar.po"; import { browser } from "protractor"; import { PreferencesPage } from "./preferences.po"; +import { scrollPageToTop } from "./util.po"; /** * Clone calculators @@ -66,7 +67,7 @@ describe("ngHyd − clone a calculator", () => { await browser.sleep(500); // otherwise clickCloneCalcButton() fails with "Element is not clickable at point" - await browser.executeScript("window.scrollTo(0, 0);"); + await scrollPageToTop(); await calcPage.clickCloneCalcButton(); await browser.sleep(500); diff --git a/e2e/lechapt-calmon.e2e-spec.ts b/e2e/lechapt-calmon.e2e-spec.ts index 4dd2d834c83c4d07e3470c727e06950f8e366bb7..75732b7dd8a5e437f1e23277c9f650bea40d077f 100644 --- a/e2e/lechapt-calmon.e2e-spec.ts +++ b/e2e/lechapt-calmon.e2e-spec.ts @@ -40,7 +40,7 @@ describe("Lechapt&Calmon - ", () => { await browser.sleep(200); } - xit("when material is modified, results should change", async () => { // temporairement débranché, cf. jalhyd#334 / nghyd#585 + it("when material is modified, results should change", async () => { await setup(); // select last material type diff --git a/e2e/load-save-session.e2e-spec.ts b/e2e/load-save-session.e2e-spec.ts index 6535d326565c835c536cb993be69d7025922ca9d..31780b9fe2b1a741ca0798b33fe10baf18afb514 100644 --- a/e2e/load-save-session.e2e-spec.ts +++ b/e2e/load-save-session.e2e-spec.ts @@ -3,21 +3,84 @@ import { ListPage } from "./list.po"; import { CalculatorPage } from "./calculator.po"; import { Navbar } from "./navbar.po"; import { SideNav } from "./sidenav.po"; -import { browser } from "protractor"; +import { browser, by, element } from "protractor"; import { PreferencesPage } from "./preferences.po"; +import { expectNumber } from "./util.po"; + +const fs = require("fs"); +const path = require("path"); +const os = require("os"); + +let startPage: AppPage; +let listPage: ListPage; +let calcPage: CalculatorPage; +let navbar: Navbar; +let sidenav: SideNav; +let prefPage: PreferencesPage; + +async function saveSession(): Promise<string> { + await calcPage.clickSaveCalcButton(); + await browser.sleep(500); + + // see: https://stackoverflow.com/questions/21935696/protractor-e2e-test-case-for-downloading-pdf-file + const filename = path.resolve(os.homedir(), "Téléchargements/session.json"); + if (fs.existsSync(filename)) { + // Make sure the browser doesn't have to rename the download. + fs.unlinkSync(filename); + } + + // Le code laissé en commentaire tente de corriger un bug : + // il s'écoule 40 secondes entre le clic sur le bouton menu (en haut à gauche) et l'ouverture du sidenav. + // Ceci ne se produit que lorsqu'on sauve effectivement la session : si on annule la sauvegarde, il n'y a pas de délai. + // https://stackoverflow.com/questions/75235558/delay-after-downloading-a-file-in-protractor-test + + //browser.manage().timeouts().implicitlyWait(100); + //browser.ignoreSynchronization = true; + // await browser.waitForAngularEnabled(false); + + if (true) { + await calcPage.getSaveSessionButton().click(); + } else { + const cancel = element(by.css("dialog-save-session button.mat-primary")); + await cancel.click(); + } + await browser.sleep(200); + // browser.ignoreSynchronization = false; + // await browser.waitForAngularEnabled(true); + + // browser.executeScript('window.stop();'); + + // const wins = await browser.driver.getAllWindowHandles(); + // await browser.switchTo().window(wins[0]); + + // await browser.switchTo().activeElement(); + + // const bd = element(by.css("body")); + // await browser.actions().mouseMove(bd, { x: 0, y: 0 }).click().perform(); + + // await navbar.clickCalculatorTab(0); + // await browser.sleep(200); + + // browser.actions().sendKeys(protractor.Key.ESCAPE).perform(); + + return filename; +} + +async function loadSession(path: string) { + await navbar.clickMenuButton(); + await browser.sleep(200); + + await sidenav.clickLoadSessionButton(); + await browser.sleep(200); + + await sidenav.loadSessionFile(path); +} /** * Save and load (serialise and unserialise) calculators to/from JSON files */ describe("ngHyd − save and load sessions", () => { - let startPage: AppPage; - let listPage: ListPage; - let calcPage: CalculatorPage; - let navbar: Navbar; - let sidenav: SideNav; - let prefPage: PreferencesPage; - - beforeEach(() => { + beforeAll(() => { startPage = new AppPage(); listPage = new ListPage(); calcPage = new CalculatorPage(); @@ -26,17 +89,16 @@ describe("ngHyd − save and load sessions", () => { prefPage = new PreferencesPage(); }); + beforeEach(() => { + jasmine.DEFAULT_TIMEOUT_INTERVAL = 45 * 60 * 1000; // 45 min + browser.manage().window().setPosition(2000, 30); + }); + it("when loading session-6-calc.test.json file from home page, 6 calculators should be loaded", async () => { await startPage.navigateTo(); - await navbar.clickMenuButton(); - await browser.sleep(200); - - await sidenav.clickLoadSessionButton(); - await browser.sleep(200); - - await sidenav.loadSessionFile("./session/session-6-calc.test.json"); - await browser.sleep(200); + await loadSession("./session/session-6-calc.test.json"); + await browser.sleep(1000); expect(await navbar.getAllCalculatorTabs().count()).toBe(6); }); @@ -44,13 +106,7 @@ describe("ngHyd − save and load sessions", () => { it("when loading session-optional-params.test.json file from home page, the calculator should be loaded", async () => { await startPage.navigateTo(); - await navbar.clickMenuButton(); - await browser.sleep(200); - - await sidenav.clickLoadSessionButton(); - await browser.sleep(200); - - await sidenav.loadSessionFile("./session/session-optional-params.test.json"); + await loadSession("./session/session-optional-params.test.json"); await browser.sleep(200); expect(await navbar.getAllCalculatorTabs().count()).toBe(1); @@ -73,19 +129,7 @@ describe("ngHyd − save and load sessions", () => { await calcPage.getInputById("Ks").sendKeys("42"); await browser.sleep(1000); - await calcPage.clickSaveCalcButton(); - - // see: https://stackoverflow.com/questions/21935696/protractor-e2e-test-case-for-downloading-pdf-file - const fs = require("fs"); - const path = require("path"); - const os = require("os"); - const filename = path.resolve(os.homedir(), "Téléchargements/session.json"); - if (fs.existsSync(filename)) { - // Make sure the browser doesn't have to rename the download. - fs.unlinkSync(filename); - } - - await calcPage.getSaveSessionButton().click(); + const filename = await saveSession(); await browser.sleep(1000); const fileContent = fs.readFileSync(filename, { encoding: "utf8" }); @@ -93,4 +137,92 @@ describe("ngHyd − save and load sessions", () => { expect(fileContent).toContain(`{"symbol":"Ks","mode":"SINGLE","value":42}`); }); + it("select value must be recovered when loading a session file", async () => { + // start page + await startPage.navigateTo(); + await browser.sleep(200); + + const calcTypes = await listPage.getAvailableCalcTypes(); + + const excludedCalculators = [ + 34, // vérificateur (nécessite d'ouvrir plusieurs calculettes) + ]; + + for (let i = 0; i < calcTypes.length; i++) { + const ct = calcTypes[i]; + if (!excludedCalculators.includes(ct)) { + if (i == 0) { + // enable evil option "empty fields on module creation" + await prefPage.navigateTo(); + await prefPage.disableEvilEmptyFields(); + await browser.sleep(200); + + // start page + await navbar.clickNewCalculatorButton(); + await browser.sleep(200); + } + else { + // empty session + await navbar.clickMenuButton(); + await browser.sleep(200); + await sidenav.clickNewSessionButton(); + await browser.sleep(200); + } + + // open calculator + await listPage.clickMenuEntryForCalcType(ct); + await browser.sleep(200); + + // detect selects + const selects = calcPage.getAllCalculatorSelects(); + const nsel = await selects.count(); + for (let s = 0; s < nsel; s++) { // /!\ ElementArrayFinder.each() is ASYNCHRONOUS !! https://www.protractortest.org/#/api?view=ElementArrayFinder.prototype.each + const sel = selects.get(s); + const selId = await sel.getAttribute("id"); + + const options = await calcPage.getMatselectOptionsText(sel); + const optionCount = options.length; + + if (optionCount > 0) { + // index of current selected option + const optTxt = await calcPage.getMatselectCurrentOptionText(sel); + const ind = options.indexOf(optTxt); + + // select next select option (optionally looping) + const nextInd = (ind + 1) % optionCount; + await calcPage.changeSelectValue(sel, nextInd); + await browser.sleep(200); + + // save session + const filename = await saveSession(); + await browser.sleep(200); + + // load session + await loadSession(filename); // bug here : the click on the menu button (top left) takes 40s to take effect and open the side nav!) + await browser.sleep(200); + // the displayed calculator is now the loaded one + + // check the calculator has been loaded + expectNumber("num calcs", await navbar.getCalculatorEntriesCount(), 2); + + // check the select in the loaded session points to the same option + const sel2 = calcPage.getSelectById(selId); + + // check the same option is in the select + const optTxt2 = await calcPage.getMatselectCurrentOptionText(sel2); + await browser.sleep(100); + const ind2 = options.indexOf(optTxt2); + expectNumber("opt index", ind2, nextInd); + + // close last calculator (the loaded one) + await navbar.middleClickCalculatorTab(1); + await browser.sleep(200); + + // check last calculator has been closed + expectNumber("num calcs(2)", await navbar.getCalculatorEntriesCount(), 1); + } + } + } + } + }); }); diff --git a/e2e/navbar.po.ts b/e2e/navbar.po.ts index 4fd34062accddf803373854bdaa30e18aa968298..814da4e216a54d63cb9e2bc443e9786a746a8964 100644 --- a/e2e/navbar.po.ts +++ b/e2e/navbar.po.ts @@ -31,8 +31,11 @@ export class Navbar { const dropDown = element(by.css("mat-select#selectCalculator")); if (await dropDown.isPresent() && await dropDown.isDisplayed()) { await dropDown.click(); - const optionId = ".cdk-overlay-container mat-option#mat-option-" + n; - const option = element(by.css(optionId)); + + // 1st option is not necessarly "mat-option-0"... + const options = element.all(by.css(".cdk-overlay-container mat-option")); + const option = options.get(n); + await option.click(); } else { const tabs = this.getAllCalculatorTabs(); diff --git a/e2e/pab.e2e-spec.ts b/e2e/pab.e2e-spec.ts index 2f75f8df9d326d084d4302160a18b7ff431de7ac..866f67fb57da855a5c8ce10d407efd3da5616ffc 100644 --- a/e2e/pab.e2e-spec.ts +++ b/e2e/pab.e2e-spec.ts @@ -5,6 +5,7 @@ import { browser, by, element } from "protractor"; import { AppPage } from "./app.po"; import { SideNav } from "./sidenav.po"; import { PreferencesPage } from "./preferences.po"; +import { scrollPageToTop } from "./util.po"; /** * Clone calculators @@ -124,7 +125,7 @@ describe("ngHyd − Passe à Bassins", () => { await calcButtonCl.click(); // make sure "Generate PAB" button is visible (it might be hidden behind navbar) - await browser.executeScript("window.scrollTo(0, 0);"); + await scrollPageToTop(); // generate PAB const genButton = calcPage.getGeneratePabButton(); await genButton.isPresent(); @@ -182,7 +183,7 @@ describe("ngHyd − Passe à Bassins", () => { await calcButtonCl.click(); // make sure "Generate PAB" button is visible (it might be hidden behind navbar) - await browser.executeScript("window.scrollTo(0, 0);"); + await scrollPageToTop(); // create PAB from it, changing modal parameters const genButton = calcPage.getGeneratePabButton(); await genButton.click(); diff --git a/e2e/solveur.e2e-spec.ts b/e2e/solveur.e2e-spec.ts index a542f32ba20103af9ac8f1e42e886e1df209998e..89ca70d6ed4b357ddf9999ae61b08f9b4c4e5a9c 100644 --- a/e2e/solveur.e2e-spec.ts +++ b/e2e/solveur.e2e-spec.ts @@ -5,6 +5,7 @@ import { Navbar } from "./navbar.po"; import { browser, by, element } from "protractor"; import { SideNav } from "./sidenav.po"; import { PreferencesPage } from "./preferences.po"; +import { scrollPageToTop } from "./util.po"; /** * Clone calculators @@ -124,8 +125,8 @@ describe("Solveur - ", () => { const hasResults = await calcPage.hasResults(); expect(hasResults).toBe(true); - // otherwise clickCloneCalcButton() fails with "Element is not clickable at point" - await browser.executeScript("window.scrollTo(0, 0);"); + await scrollPageToTop(); // otherwise clickCloneCalcButton() fails with "Element is not clickable at point" + await calcPage.clickCloneCalcButton(); await browser.sleep(500); diff --git a/e2e/util.po.ts b/e2e/util.po.ts new file mode 100644 index 0000000000000000000000000000000000000000..e772a28ce9c01e0c54f85d0bce84a01df90e7ac5 --- /dev/null +++ b/e2e/util.po.ts @@ -0,0 +1,29 @@ +import { ElementFinder, browser } from "protractor"; + +/** + * scroll page to make element visible + */ +export async function scrollToElement(elem: ElementFinder) { + await browser.executeScript("arguments[0].scrollIntoView({ block: 'center' });", elem.getWebElement()); + await browser.sleep(50); +} + +/** + * scroll page to top + */ +export async function scrollPageToTop() { + await browser.executeScript("window.scrollTo(0, 0);"); +} + +/** + * execute expect() on numbers and displays a failure message + * @param msg message in caase of failure + * @param val value to check + * @param expected expected value + */ +export function expectNumber(msg: string, val: number, expected: number) { + if (val !== expected) { + console.log(msg, "got", val, "expected", expected); + } + expect(val).toEqual(expected); +} diff --git a/jalhyd_branch b/jalhyd_branch index 9e2dece83480eba1020a4a59afd1ed3e8eb63c31..0bd0de8433c44aa322701f9bf4b87ff6d54b525c 100644 --- a/jalhyd_branch +++ b/jalhyd_branch @@ -1 +1 @@ -338-optimiser-l-affichage-des-unites +334-restructurer-lechapt-et-calmon-pour-de-nouvelles-lois-de-pertes-de-charge diff --git a/package-lock.json b/package-lock.json index 9661a8c876a23a46f8118a8d679270b97149b3f7..87ddd2409a061f0e0cd71c99eeb5c547a9235478 100644 --- a/package-lock.json +++ b/package-lock.json @@ -84,6 +84,7 @@ "license": "LGPL-3.0-or-later", "dependencies": { "@types/base-64": "^1.0.0", + "@types/lodash": "^4.14.191", "base-64": "^1.0.0" }, "devDependencies": { @@ -4138,6 +4139,11 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, + "node_modules/@types/lodash": { + "version": "4.14.191", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.191.tgz", + "integrity": "sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ==" + }, "node_modules/@types/marked": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/@types/marked/-/marked-4.0.7.tgz", @@ -23282,6 +23288,11 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, + "@types/lodash": { + "version": "4.14.191", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.191.tgz", + "integrity": "sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ==" + }, "@types/marked": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/@types/marked/-/marked-4.0.7.tgz", @@ -29813,6 +29824,7 @@ "requires": { "@types/base-64": "^1.0.0", "@types/jasmine": "^4.0.3", + "@types/lodash": "^4.14.191", "@types/node": "^18.0.3", "@typescript-eslint/eslint-plugin": "^5.30.6", "@typescript-eslint/parser": "^5.30.6", diff --git a/src/app/components/fieldset-container/fieldset-container.component.ts b/src/app/components/fieldset-container/fieldset-container.component.ts index f612f362aa0ac7e2475b785e0e2bbf76bbded771..042df751799ed61418e5b9a869e2277cb627110d 100644 --- a/src/app/components/fieldset-container/fieldset-container.component.ts +++ b/src/app/components/fieldset-container/fieldset-container.component.ts @@ -89,8 +89,8 @@ export class FieldsetContainerComponent implements DoCheck, AfterViewInit { const prms = after.backupParameters(); // replace in-place to change properties (overkill) // @WTF why only those two ? - newFs.setNubPropValue("structureType", after.properties.getPropValue("structureType")); - newFs.setNubPropValue("loiDebit", after.properties.getPropValue("loiDebit")); + newFs.setPropValue("structureType", after.getPropValue("structureType")); + newFs.setPropValue("loiDebit", after.getPropValue("loiDebit")); // au cas où un des paramètres du fieldset source est en mode calcul, // on met le paramètre copié en mode fixé (nghyd#567) diff --git a/src/app/components/macrorugo-compound-results/macrorugo-compound-results.component.ts b/src/app/components/macrorugo-compound-results/macrorugo-compound-results.component.ts index 86eba4301034bb0bc758ebed7904cf1e4ae25f11..f388647dafbcf7d653fcffd263b87d3dfff40718 100644 --- a/src/app/components/macrorugo-compound-results/macrorugo-compound-results.component.ts +++ b/src/app/components/macrorugo-compound-results/macrorugo-compound-results.component.ts @@ -92,7 +92,7 @@ export class MacrorugoCompoundResultsComponent extends ResultsComponentDirective this.mrcResults && this.mrcResults.result && this.mrcResults.result.sourceNub - && this.mrcResults.result.sourceNub.properties.getPropValue("inclinedApron") === MRCInclination.INCLINED + && this.mrcResults.result.sourceNub.getPropValue("inclinedApron") === MRCInclination.INCLINED ); } diff --git a/src/app/components/modules-diagram/modules-diagram.component.ts b/src/app/components/modules-diagram/modules-diagram.component.ts index 6f227edcbd98057673505915f06def23886df2b3..0b607e51e10e25cb2f5505c3e1bdf0993dfcffe5 100644 --- a/src/app/components/modules-diagram/modules-diagram.component.ts +++ b/src/app/components/modules-diagram/modules-diagram.component.ts @@ -265,11 +265,11 @@ export class ModulesDiagramComponent implements AfterContentInit, AfterViewCheck */ private describe(n: Nub) { let type = CalculatorType[n.calcType]; - const nt = n.properties.getPropValue("nodeType"); + const nt = n.getPropValue("nodeType"); if (nt) { type = SectionType[nt]; } else { - const ld = n.properties.getPropValue("loiDebit"); + const ld = n.getPropValue("loiDebit"); if (ld !== undefined) { type = LoiDebit[ld]; } diff --git a/src/app/components/pab-profile-chart/pab-profile-chart.component.ts b/src/app/components/pab-profile-chart/pab-profile-chart.component.ts index c8eff7ec5fbb007f2b11bf6f48ca87a94e3edab1..ee664e43ad59b3c77bd6e000921cbb11d8c32ea6 100644 --- a/src/app/components/pab-profile-chart/pab-profile-chart.component.ts +++ b/src/app/components/pab-profile-chart/pab-profile-chart.component.ts @@ -268,7 +268,7 @@ export class PabProfileChartComponent extends ResultsComponentDirective implemen ddSeries[sti] = []; } // orifices have no relevant ZDV - if (st.properties.getPropValue("loiDebit") !== LoiDebit.OrificeSubmerged) { + if (st.getPropValue("loiDebit") !== LoiDebit.OrificeSubmerged) { // 2 points, to draw a segment ddSeries[sti].push({ x: xs[i], @@ -305,7 +305,7 @@ export class PabProfileChartComponent extends ResultsComponentDirective implemen } // orifices have no relevant ZDV; lift gate will be drawn later for each series if (! [ LoiDebit.OrificeSubmerged, LoiDebit.VanLevLarinier, LoiDebit.VanLevVillemonte ] - .includes(st.properties.getPropValue("loiDebit")) + .includes(st.getPropValue("loiDebit")) ) { // 2 points, to draw a segment ddSeries[sti].push({ @@ -403,7 +403,7 @@ export class PabProfileChartComponent extends ResultsComponentDirective implemen // draw lift gate if any if (isLastAbscissa) { for (const st of dw.structures) { - if ([ LoiDebit.VanLevLarinier, LoiDebit.VanLevVillemonte ].includes(st.properties.getPropValue("loiDebit"))) { + if ([LoiDebit.VanLevLarinier, LoiDebit.VanLevVillemonte].includes(st.getPropValue("loiDebit"))) { // skip a point to disjoin line dataN.push({ x: x, diff --git a/src/app/components/pab-table/pab-table.component.ts b/src/app/components/pab-table/pab-table.component.ts index 8ef4e14c146d960d5b7d726f0fbb1c824a1d3da1..ead6072f13b0af083cdf29b590ab1172de57f28a 100644 --- a/src/app/components/pab-table/pab-table.component.ts +++ b/src/app/components/pab-table/pab-table.component.ts @@ -594,7 +594,7 @@ export class PabTableComponent implements AfterViewInit, AfterViewChecked, OnIni if (i === 0) { // 1st row deviceParamRow.cells.push({ model: ouvrage, - modelValue: ouvrage.properties.getPropValue("loiDebit"), + modelValue: ouvrage.getPropValue("loiDebit"), options: loisCloisons, selectable: ouvrage }); @@ -719,7 +719,7 @@ export class PabTableComponent implements AfterViewInit, AfterViewChecked, OnIni if (i === 0) { // 1st row deviceParamRowDW.cells.push({ model: ouvrage, - modelValue: ouvrage.properties.getPropValue("loiDebit"), + modelValue: ouvrage.getPropValue("loiDebit"), options: loisAval }); } diff --git a/src/app/formulaire/definition/form-courbe-remous.ts b/src/app/formulaire/definition/form-courbe-remous.ts index 3762c846cb3fd3c5a11a21d850746f0a024c9074..62c8d3b3b20b6f9d962f626aa482b10cf27b1c2c 100644 --- a/src/app/formulaire/definition/form-courbe-remous.ts +++ b/src/app/formulaire/definition/form-courbe-remous.ts @@ -31,7 +31,7 @@ export class FormulaireCourbeRemous extends FormulaireSection { this._remousResults.parameters = prmCR; // variable supplémentaire à calculer - this._remousResults.extraParamSymbol = this.currentNub.properties.getPropValue("varCalc"); + this._remousResults.extraParamSymbol = this.currentNub.getPropValue("varCalc"); // calcul this._remousResults.result = cr.CalcSerie(); diff --git a/src/app/formulaire/definition/form-definition.ts b/src/app/formulaire/definition/form-definition.ts index f2141323a49d79f1ff4fee955ce54213479efdf7..146d1746a8b74f4ffbaf36e2655da910816a9d1f 100644 --- a/src/app/formulaire/definition/form-definition.ts +++ b/src/app/formulaire/definition/form-definition.ts @@ -81,14 +81,18 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs return this._calculateDisabled; } + private getPropValue(key: string): any { + if (this._currentNub === undefined) + return this.defaultProperties[key]; + return this._currentNub.getPropValue(key); + } + public get calculatorType(): CalculatorType { - const props = this._currentNub === undefined ? this.defaultProperties : (this._currentNub.properties as Props).props; - return props["calcType"]; + return this.getPropValue("calcType") } public get nodeType(): SectionType { - const props = this._currentNub === undefined ? this.defaultProperties : (this._currentNub.properties as Props).props; - return props["nodeType"]; + return this.getPropValue("nodeType") } public get calculatorName() { @@ -113,6 +117,27 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs return this._props; } + public parseConfigToProps(): Props { + const res: Props = new Props(); + + const jp = new ConfigParser(this._jsonConfig); + for (const fs of jp.forAll("fieldset")) { + const fsp = new ConfigParser(fs["fields"]); + for (const sel of fsp.forAll("select")) { + const p = sel["property"]; + if (p !== undefined) { // if select has associated property + const v = sel["default"]; + if (v !== undefined) { // if select has a default value for associated property + const enumClass = Props.enumFromProperty[p]; + res.setPropValue(p, enumClass[v]); + } + } + } + } + + return res; + } + /** * Creates a Nub from the given properties, and associates it to the current form */ @@ -127,7 +152,7 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs } public set currentNub(n: Nub) { - const nubCalcType = (n.properties as Props).getPropValue("calcType"); + const nubCalcType = n.getPropValue("calcType"); if (this._props["calcType"] !== nubCalcType) { throw new Error( `Nub ${n.properties["calcType"]} incompatible avec le formulaire ${this._calculatorName} (${this._props["calcType"]})` diff --git a/src/app/formulaire/definition/form-espece.ts b/src/app/formulaire/definition/form-espece.ts index 10ded3b83c1994fec8e6ff43cd5d5a684d13a79b..f0a36b93e1f5c9d4213438bd9095b25a7170292b 100644 --- a/src/app/formulaire/definition/form-espece.ts +++ b/src/app/formulaire/definition/form-espece.ts @@ -10,7 +10,7 @@ export class FormulaireEspece extends FormulaireFixedVar { protected completeParse(firstNotif: boolean = true) { super.completeParse(firstNotif); - this.updateDivingJetCriteriaInputs(this.currentNub.properties.getPropValue("divingJetSupported")); + this.updateDivingJetCriteriaInputs(this.currentNub.getPropValue("divingJetSupported")); } /** diff --git a/src/app/formulaire/definition/form-fixedvar.ts b/src/app/formulaire/definition/form-fixedvar.ts index 0a329f489308d59093da98d30da932a160e249fa..8eb6917e75496d210925a4bd8ab355c6ece3e107 100644 --- a/src/app/formulaire/definition/form-fixedvar.ts +++ b/src/app/formulaire/definition/form-fixedvar.ts @@ -63,7 +63,7 @@ export class FormulaireFixedVar extends FormulaireDefinition { public afterParseFieldset(fs: FieldSet) { // observe all Select fields @see this.update() - fs.properties.addObserver(this); + fs.addPropertiesObserver(this); } protected completeParse(firstNotif: boolean = true) { diff --git a/src/app/formulaire/definition/form-macrorugo-compound.ts b/src/app/formulaire/definition/form-macrorugo-compound.ts index ec470e645ca81406ae5e353736467e77427508ba..306332cb56def101c15cd82afcb095fb06aa4fb3 100644 --- a/src/app/formulaire/definition/form-macrorugo-compound.ts +++ b/src/app/formulaire/definition/form-macrorugo-compound.ts @@ -56,7 +56,7 @@ export class FormulaireMacrorugoCompound extends FormulaireRepeatableFieldset { super.completeParse(firstNotif); this.fieldsetContainer.addObserver(this); if (firstNotif) { - this.updateApronState(this.currentNub.properties.getPropValue("inclinedApron")); + this.updateApronState(this.currentNub.getPropValue("inclinedApron")); } } diff --git a/src/app/formulaire/definition/form-parallel-structures.ts b/src/app/formulaire/definition/form-parallel-structures.ts index b47c4808b021bba832df9c201b65ebc4aadb76f5..a5de99edd14ca3a699a0e1f3c502e49879046d80 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, Prop_NullParameters } from "jalhyd"; +import { Structure, Nub, ParallelStructure, StructureProperties, Props, Session, ParamDefinition, Prop_NullParameters, IProperties } from "jalhyd"; import { FieldsetContainer } from "../elements/fieldset-container"; import { FieldSet } from "../elements/fieldset"; @@ -71,7 +71,7 @@ export class FormulaireParallelStructure extends FormulaireRepeatableFieldset { * and return it; does not store it in the Session (for Structures, not for Calculator Modules) * @param p properties for the new Nub */ - protected createStructure(p: Props): Structure { + protected createStructure(p: IProperties): Structure { return Session.getInstance().createNub(p, this.currentNub as ParallelStructure) as Structure; } @@ -81,9 +81,9 @@ export class FormulaireParallelStructure extends FormulaireRepeatableFieldset { * @param sn Structure to replace * @param params properties to build the new Nub (calcType, loiDebit...) */ - protected replaceNub(sn: Structure, params: Props): Nub { + protected replaceNub(sn: Structure): Nub { const parent = (this.currentNub as ParallelStructure); - const newStructure = this.createStructure(params); + const newStructure = this.createStructure(sn); parent.replaceChildInplace(sn, newStructure); return newStructure; } @@ -108,7 +108,7 @@ export class FormulaireParallelStructure extends FormulaireRepeatableFieldset { * @param name nom de la propriété qui vient de changer * @param val nouvelle valeur de la propriété */ - protected adjustProperties(props: Props, name: string, val: any) { + protected adjustProperties(props: IProperties, name: string, val: any) { if (name === "structureType") { if (! StructureProperties.isCompatibleValues( val, props.getPropValue("loiDebit"), this.currentNub as ParallelStructure @@ -159,12 +159,12 @@ export class FormulaireParallelStructure extends FormulaireRepeatableFieldset { } else if (sender instanceof FieldSet && data.action === "propertyChange") { switch (sender.id) { case "fs_ouvrage": - const props = sender.properties; // ensure loiDebit is set - props.setPropValue("loiDebit", data.value); - this.adjustProperties(props, data["name"], data["value"]); + //props.setPropValue("loiDebit", data.value); // ?? et si la propriété modifiée n'est pas la loi de débit ? + + this.adjustProperties(sender, data["name"], data["value"]); // replace Structure Nub - const newNub = this.replaceNub((sender.nub as Structure), props); + const newNub = this.replaceNub(sender.nub as Structure); sender.setNub(newNub); // treat the fieldset as new to re-subscribe to Nub properties change events this.afterParseFieldset(sender); diff --git a/src/app/formulaire/definition/form-pb-cloison.ts b/src/app/formulaire/definition/form-pb-cloison.ts index 25910c87d6a1ed5681bd8d7af9e5a45092f876c0..145c03fe403d38338dc557da1f3cb41a2cf29c89 100644 --- a/src/app/formulaire/definition/form-pb-cloison.ts +++ b/src/app/formulaire/definition/form-pb-cloison.ts @@ -27,12 +27,12 @@ export class FormulairePbCloison extends FormulaireParallelStructure { } else if (sender instanceof FieldSet && data.action === "propertyChange") { switch (sender.id) { case "fs_ouvrage": - const props = sender.properties; // ensure loiDebit is set - props.setPropValue("loiDebit", data.value); - this.adjustProperties(props, data["name"], data["value"]); + //props.setPropValue("loiDebit", data.value); // ?? et si la propriété modifiée n'est pas la loi de débit ? + + this.adjustProperties(sender, data["name"], data["value"]); // replace Structure Nub - const newNub = this.replaceNub((sender.nub as Structure), props); + const newNub = this.replaceNub(sender.nub as Structure); sender.setNub(newNub); // treat the fieldset as new to re-subscribe to Nub properties change events this.afterParseFieldset(sender); diff --git a/src/app/formulaire/definition/form-prebarrage.ts b/src/app/formulaire/definition/form-prebarrage.ts index 95e5f65498b3ad929c00730266a3fa0ccb33d221..c9a0d9e0db35efb7ff665b637520798032944bf6 100644 --- a/src/app/formulaire/definition/form-prebarrage.ts +++ b/src/app/formulaire/definition/form-prebarrage.ts @@ -367,7 +367,7 @@ export class FormulairePrebarrage extends FormulaireFixedVar { } catch (e) { let res; if (p.parentNub.calcType === CalculatorType.Structure) { - res = p.parentNub.getParent().uid; + res = p.parentNub.parent.uid; } else { res = p.parentNub.uid; } diff --git a/src/app/formulaire/definition/form-pressureloss.ts b/src/app/formulaire/definition/form-pressureloss.ts index 60c98da99b692a86de8de20bc0025ff96d6327c6..4b1e7ceb4188e1d4cb2d4f4caf03b4da1f827b80 100644 --- a/src/app/formulaire/definition/form-pressureloss.ts +++ b/src/app/formulaire/definition/form-pressureloss.ts @@ -1,4 +1,4 @@ -import { PressureLoss, Props, PressureLossType } from "jalhyd"; +import { PressureLoss, Props, PressureLossType, Session, PressureLossLaw, CalculatorType } from "jalhyd"; import { FormulaireFixedVar } from "./form-fixedvar"; /** @@ -17,8 +17,19 @@ export class FormulairePressureLoss extends FormulaireFixedVar { if (props === undefined) { props = new Props(); } + + // create pressure loss parent nub + const pll = this.defaultProperties["pressureLossType"]; props.setPropValue("calcType", this.calculatorType); - props.setPropValue("pressureLossType", this.defaultProperties["pressureLossType"]); + props.setPropValue("pressureLossType", pll); super.initNub(props); + + // create pressure loss law child nub + const propsLaw: Props = new Props(); + const pressureLossCalc: CalculatorType = PressureLossLaw.calcTypeFromPressureLossLaw[pll]; + propsLaw.setPropValue("calcType", pressureLossCalc); + const law = Session.getInstance().createNub(propsLaw) as PressureLossLaw; + const pl: PressureLoss = this.currentNub as PressureLoss; + pl.setLaw(law); } } diff --git a/src/app/formulaire/definition/form-section.ts b/src/app/formulaire/definition/form-section.ts index 8f8be0af96d577110333fe270c861ec7297c621f..bf06c16b257e578889469d86dc696f6ea15249a0 100644 --- a/src/app/formulaire/definition/form-section.ts +++ b/src/app/formulaire/definition/form-section.ts @@ -7,16 +7,14 @@ import { SectionType } from "jalhyd"; export class FormulaireSection extends FormulaireFixedVar { - /** for SectionNubs only */ - protected _defaultSectionType; - /** * determine default section type from select configuration */ private parseDefaultSectionType() { - if (this._defaultSectionType === undefined) { + if (this.defaultProperties["nodeType"] === undefined) // still use "nodeType" for consistency, should be named "sectionType" + { const def = this.parseSelectDefaultValue(this._jsonConfig, "select_section"); - this._defaultSectionType = SectionType[def]; + this.defaultProperties["nodeType"] = SectionType[def]; } } @@ -31,7 +29,7 @@ export class FormulaireSection extends FormulaireFixedVar { // add new Section as first child, from given nodeType const propsSection = new Props(); propsSection.setPropValue("calcType", CalculatorType.Section); - propsSection.setPropValue("nodeType", this._defaultSectionType); + propsSection.setPropValue("nodeType", this.defaultProperties["nodeType"]); propsSection.setPropValue(Prop_NullParameters, ServiceFactory.applicationSetupService.enableEmptyFieldsOnFormInit); const section = Session.getInstance().createNub(propsSection); this.currentNub.setSection(section as acSection); diff --git a/src/app/formulaire/definition/form-solveur.ts b/src/app/formulaire/definition/form-solveur.ts index f658c98eefb762eece2bae95a7180273a8f307ae..0a3d446efac3a99a2fa2165f3b0916462fcfeb5a 100644 --- a/src/app/formulaire/definition/form-solveur.ts +++ b/src/app/formulaire/definition/form-solveur.ts @@ -58,7 +58,7 @@ export class FormulaireSolveur extends FormulaireFixedVar { // if searchedParam is set to a value that won't be available anymore // once nubToCalculate is updated, setPropValue throws an error, but // nubToCalculate is updated anyway; here, just inhibit the error - this._currentNub.properties.setPropValue("nubToCalculate", data.value.value); + this._currentNub.setPropValue("nubToCalculate", data.value.value); } catch (e) { } // refresh targetted result selector const trSel = this.getFormulaireNodeById(this._targettedResultSelectId) as SelectField; @@ -73,7 +73,7 @@ export class FormulaireSolveur extends FormulaireFixedVar { // update Solveur property: searched Parameter try { const p: ParamDefinition = data.value.value; - this._currentNub.properties.setPropValue( + this._currentNub.setPropValue( "searchedParameter", p.nubUid + "/" + p.symbol ); diff --git a/src/app/formulaire/definition/form-verificateur.ts b/src/app/formulaire/definition/form-verificateur.ts index 893754665a7cb997437bf7ab7aaa26b6643c9695..337bc789a44d1b06666e4133196d80f3aeb2736e 100644 --- a/src/app/formulaire/definition/form-verificateur.ts +++ b/src/app/formulaire/definition/form-verificateur.ts @@ -97,7 +97,7 @@ export class FormulaireVerificateur extends FormulaireFixedVar { this.reset(); // reset results if (sender.id === "select_target_pass" && data.action === "select") { // update Verificateur property: Pass to check - this._currentNub.properties.setPropValue("nubToVerify", data.value ? data.value.value : undefined); + this._currentNub.setPropValue("nubToVerify", data.value ? data.value.value : undefined); } else if (sender.id === "select_species_list" && data.action === "select") { // update Verificateur property: Species list (string[]) diff --git a/src/app/formulaire/elements/fieldset.ts b/src/app/formulaire/elements/fieldset.ts index d0229afe762326464684558389b299439dd7f7d0..3637d892d27725fe0d7a7d84ad805c3ee589f63b 100644 --- a/src/app/formulaire/elements/fieldset.ts +++ b/src/app/formulaire/elements/fieldset.ts @@ -1,7 +1,7 @@ import { CalculatorType, ParamDefinition, - Props, + IProperties, Observer, Nub, enumValueFromString @@ -16,7 +16,7 @@ import { SelectFieldFactory } from "./select/select-field-factory"; import { FormulaireFixedVar } from "../definition/form-fixedvar"; import { SelectEntry } from "./select/select-entry"; -export class FieldSet extends FormulaireElement implements Observer { +export class FieldSet extends FormulaireElement implements IProperties { /** Nub associé */ private _nub: Nub; @@ -45,7 +45,7 @@ export class FieldSet extends FormulaireElement implements Observer { } private addField(f: Field) { - if (! f) { + if (!f) { throw new Error("FieldSet.addField() : argument incorrect (undefined)"); } this.kids.push(f); @@ -114,40 +114,8 @@ export class FieldSet extends FormulaireElement implements Observer { return res; } - public get properties(): Props { - return this.nub.properties; - } - - private get sectionProperties(): Props { - const section = this.nub.getChildren()[0]; - if (section) { - return section.properties; - } else { - return new Props(); - } - } - - /** - * get associated nub property value - * @param key property name - * @param inSection if true, will look for the required property in the Nub's section (children[0]) - */ - private getNubPropValue(key: string, inSection: boolean = false): any { - if (inSection) { - return this.sectionProperties.getPropValue(key); - } else { - return this.properties.getPropValue(key); - } - } - - /** - * assign associated nub property - * @param key nub property name - * @param val value to assign with - * @returns true if property value has changed - */ - public setNubPropValue(key: string, val: any): boolean { - return this.properties.setPropValue(key, val, this); + public addPropertiesObserver(o: Observer) { + this.nub.addPropertiesObserver(o); } private getNubParamFromSymbol(symbol: string): ParamDefinition { @@ -250,7 +218,7 @@ export class FieldSet extends FormulaireElement implements Observer { private setSelectValueFromProperty(selectId: string, inSection: boolean = false) { const selectField: SelectField = this.getFormulaireNodeById(selectId) as SelectField; if (selectField) { - let propVal: any = this.getNubPropValue(selectField.associatedProperty, inSection); + let propVal: any = this.getPropValue(selectField.associatedProperty, inSection); if (propVal === undefined) { propVal = ""; // clodo bullet-proof loading } @@ -277,9 +245,9 @@ export class FieldSet extends FormulaireElement implements Observer { this._helpLink = json["help"]; const ct: string = json["calcType"]; - const currentCt = this.properties.getPropValue("calcType"); + const currentCt = this.getPropValue("calcType"); const calc_type: CalculatorType = currentCt ? currentCt : (ct ? CalculatorType[ct] : this.parentForm.calculatorType); - this.setNubPropValue("calcType", calc_type); + this.setPropValue("calcType", calc_type); // parse fields once, so that SelectField elements are present // when setting default properties below @@ -293,9 +261,9 @@ export class FieldSet extends FormulaireElement implements Observer { const prop = sel.associatedProperty; const defaultValue = sel.configDefaultValue; // Sets Nub default property, unless this property is already set - const currentValue = this.properties.getPropValue(prop); + const currentValue = this.getPropValue(prop); if (defaultValue !== undefined && currentValue === undefined) { - this.setNubPropValue(prop, enumValueFromString(prop, defaultValue)); + this.setPropValue(prop, enumValueFromString(prop, defaultValue)); } } } @@ -314,7 +282,7 @@ export class FieldSet extends FormulaireElement implements Observer { public getNodeParameterValue(symbol: string): number { const p = this.getNodeParameter(symbol); - if (! p) { + if (!p) { throw new Error(`FieldSet.getNodeParameterValue() : pas de paramètre ${symbol} trouvé`); } @@ -336,7 +304,7 @@ export class FieldSet extends FormulaireElement implements Observer { public getSelectedValue(selectFieldId: string): string | string[] { for (const p of this.kids) { if (p instanceof SelectField && p.isDisplayed && p.id === selectFieldId) { - if (! p.multiple) { + if (!p.multiple) { const value: string = (p.getValue() as SelectEntry).value; return FormulaireElement.removePrefix(value, selectFieldId + "_"); } else { @@ -359,7 +327,7 @@ export class FieldSet extends FormulaireElement implements Observer { if (senderId === "select_section") { // sections paramétrées, courbes de remous, régimes uniformes // "nodeType" is a property of the section child, not of the parent - const oldNodeType = this.nub.getChildren()[0].properties.getPropValue("nodeType"); + const oldNodeType = this.nub.getChildren()[0].getPropValue("nodeType"); if (oldNodeType !== data.value.value) { // avoid infinite loops // manually notify parent so that it replaces the child Nub @WARNING clodo trick this.parentForm.update(this, { @@ -380,9 +348,9 @@ export class FieldSet extends FormulaireElement implements Observer { const prop = sel.associatedProperty; // for multiple select if (Array.isArray(data.value)) { - this.setNubPropValue(prop, data.value.map((v: any) => v.value)); + this.setPropValue(prop, data.value.map((v: any) => v.value)); } else { - this.setNubPropValue(prop, data.value.value); + this.setPropValue(prop, data.value.value); } } } @@ -394,4 +362,43 @@ export class FieldSet extends FormulaireElement implements Observer { } } } + + // interface IProperties + + public hasProperty(key: string): boolean { + return this._nub.hasProperty(key); + } + + /** + * list of properties keys + */ + public get keys(): string[] { + return this._nub.keys; + } + + /** + * get associated nub property value + * @param key property name + * @param inSection if true, will look for the required property in the Nub's section (children[0]) + */ + public getPropValue(key: string, inSection: boolean = false): any { + if (inSection) { + const section = this.nub.getChildren()[0]; + if (section) { + return section.getPropValue(key); + } + return undefined; + } + return this.nub.getPropValue(key); + } + + /** + * assign associated nub property + * @param key nub property name + * @param val value to assign with + * @returns true if property value has changed + */ + public setPropValue(key: string, val: any): boolean { + return this.nub.setPropValue(key, val, this); + } } diff --git a/src/app/formulaire/elements/formulaire-element.ts b/src/app/formulaire/elements/formulaire-element.ts index 579b62648b34a662d8edba307d86920a98ff32d3..25b5943fa846c1790b151d0aa5d01cfec1aae4da 100644 --- a/src/app/formulaire/elements/formulaire-element.ts +++ b/src/app/formulaire/elements/formulaire-element.ts @@ -56,6 +56,10 @@ export abstract class FormulaireElement extends FormulaireNode { */ public get parentForm(): FormulaireDefinition { let res = this.parent; + if (res === undefined) { + return undefined; + } + // while (!(res instanceof FormulaireDefinition)) while (!("calculatorName" in res)) { // pour éviter de faire référence au type FormulaireDefinition, supprimer l'import correspondant et diff --git a/src/app/formulaire/elements/select/select-field-device-loi-debit.ts b/src/app/formulaire/elements/select/select-field-device-loi-debit.ts index 07c1f555a52e05e8664209e9ec2ee510ed83ad01..683adebaefa22e1b2a35176cdb90bc19889f8377 100644 --- a/src/app/formulaire/elements/select/select-field-device-loi-debit.ts +++ b/src/app/formulaire/elements/select/select-field-device-loi-debit.ts @@ -34,7 +34,7 @@ export class SelectFieldDeviceLoiDebit extends SelectField { */ private get loiDebit(): LoiDebit { const child = this.nub.getChildren()[this.parent.indexAsKid()]; - return child.properties.getPropValue("loiDebit"); + return child.getPropValue("loiDebit"); } protected populate() { diff --git a/src/app/formulaire/elements/select/select-field-device-structure-type.ts b/src/app/formulaire/elements/select/select-field-device-structure-type.ts index 7b188d114de529c84e9c403274e689986f9d408a..0d1ce351d60caaf53c572e8f91f7bef415917c0d 100644 --- a/src/app/formulaire/elements/select/select-field-device-structure-type.ts +++ b/src/app/formulaire/elements/select/select-field-device-structure-type.ts @@ -21,6 +21,14 @@ export class SelectFieldDeviceStructureType extends SelectField { this._configDefaultValue = json["default"]; } + /** + * get discharge law linked to this select's nub + */ + private get structureType(): StructureType { + const child = this.nub.getChildren()[this.parent.indexAsKid()]; + return child.getPropValue("structureType"); + } + protected populate() { // possible values depend on CalcType for (const st in (this.nub as ParallelStructure).getLoisAdmissibles()) { @@ -30,6 +38,6 @@ export class SelectFieldDeviceStructureType extends SelectField { } protected initSelectedValue() { - this.findAndSetDefaultValue(); + this.findAndSetDefaultValue(StructureType[this.structureType]); } } diff --git a/src/app/formulaire/elements/select/select-field-nub-prop.ts b/src/app/formulaire/elements/select/select-field-nub-prop.ts index 4fa8c4e862ff14dbbbde8b26d2a31ff49fcc50ac..233502db06a61c1133285507ce23046cf615f396 100644 --- a/src/app/formulaire/elements/select/select-field-nub-prop.ts +++ b/src/app/formulaire/elements/select/select-field-nub-prop.ts @@ -1,6 +1,5 @@ -import { Session } from "jalhyd"; +import { Props } from "jalhyd"; import { FormulaireNode } from "../formulaire-node"; -import { SelectEntry } from "./select-entry"; import { SelectField } from "./select-field"; /* @@ -27,7 +26,7 @@ export class SelectFieldNubProperty extends SelectField { protected populate() { // find enum associated to property - const enumClass = Session.enumFromProperty[this._associatedProperty]; + const enumClass = Props.enumFromProperty[this._associatedProperty]; if (enumClass !== undefined) { // add one select entry per enum entry, in the enum order for (let j = 0; j < Object.keys(enumClass).length / 2; j++) { diff --git a/src/app/formulaire/elements/select/select-field.ts b/src/app/formulaire/elements/select/select-field.ts index 86a9880048beb87da66730ef9ec3b69a45c770b3..2b9b65aa97fc770e1548718791597698decb7a09 100644 --- a/src/app/formulaire/elements/select/select-field.ts +++ b/src/app/formulaire/elements/select/select-field.ts @@ -50,6 +50,10 @@ export abstract class SelectField extends Field { * associated nub */ protected get nub(): Nub { + const parent = this.parentForm; + if (parent === undefined) { + return undefined; + } return (this.parentForm as FormulaireDefinition).currentNub; } @@ -128,22 +132,39 @@ export abstract class SelectField extends Field { } /** - * try to find a default value to select + * Try to find a default value to select. + * Priority order : + * - passed parameter + * - nub value for associated property + * - default value from configuration file + * - first select entry */ protected findAndSetDefaultValue(value?: string) { // default to first available entry if any if (this._entries.length > 0) { let val: SelectEntry; + if (value !== undefined) { val = this.getEntryFromValue(enumValueFromString(this._associatedProperty, value)); - } else if (this._configDefaultValue === undefined) { - val = this._entries[0]; + if (val === undefined) { + throw Error("invalid select default value " + value + " for " + this._associatedProperty + " property"); + } } else { - val = this.getEntryFromValue(enumValueFromString(this._associatedProperty, this._configDefaultValue)); + if (this.nub !== undefined) { + val = this.getEntryFromValue(this.nub.getPropValue(this._associatedProperty)); + // nub may not have "this._associatedProperty" as a property + } + if (val === undefined && this._configDefaultValue !== undefined) { + val = this.getEntryFromValue(enumValueFromString(this._associatedProperty, this._configDefaultValue)); + if (val === undefined) { + throw Error("invalid select default value " + this._configDefaultValue + " for " + this._associatedProperty + " property"); + } + } if (val === undefined) { - throw Error("invalid select default value " + this._configDefaultValue + " for " + this._associatedProperty + " property"); + val = this._entries[0]; } } + if (this._multiple) { this.setValue([val]); } else { diff --git a/src/app/services/formulaire.service.ts b/src/app/services/formulaire.service.ts index 880741539bbb62d7a033a5dedc60ad76cc84eeaf..a32a1aec446448eb849d26fcddc3c5d77b81497f 100644 --- a/src/app/services/formulaire.service.ts +++ b/src/app/services/formulaire.service.ts @@ -371,7 +371,9 @@ export class FormulaireService extends Observable { if (nub) { f.currentNub = nub; } else { - f.initNub(); + const confProps = f.parseConfigToProps(); + confProps.setPropValue("calcType", ct); + f.initNub(confProps); } // Restaure le nom du module, sinon affecte le nom par défaut