diff --git a/DEVELOPERS.md b/DEVELOPERS.md index d5d7cb3a7a7d098ea85ca6892957746fe5f048e9..207e7687ef0e0a1db871490ab3023fe1d1f9f812 100644 --- a/DEVELOPERS.md +++ b/DEVELOPERS.md @@ -270,7 +270,7 @@ case CalculatorType.MacroRugoCompound: Les listes déroulantes sont toujours associées à des **propriétés** du Nub. -En général les valeurs autorisées sont tirées de l'**enum** correspondant, d'après le tableau `Session.enumFromProperty` de JaLHyd. Pour les autres cas, voir "si la liste n'est pas associée à un enum" ci-dessous. +En général les valeurs autorisées sont tirées de l'**enum** correspondant, d'après le tableau `Session.enumFromProperty` de JaLHyd. Pour les autres cas, voir les paragraphes "si la liste est associée à …" ci-dessous. #### configuration @@ -309,7 +309,7 @@ Dans le fichier de configuration du module, ajouter la définition des listes d Une liste déroulante peut être associée à une **source**, qui détermine quels sont les choix possibles. -Pour ajouter une source, modifier la méthode `parseConfig()` de la classe `SelectField`, dans le fichier `src/app/formulaire/elements/select-field.ts`. +Pour ajouter une source, modifier la méthode `loadEntriesFromSource()` de la classe `SelectField`, dans le fichier `src/app/formulaire/elements/select-field.ts`. Exemple pour la source "remous_target" associée à la propriété "varCalc", dans le module CourbeRemous : diff --git a/e2e/check-translations.e2e-spec.ts b/e2e/check-translations.e2e-spec.ts index ddcd763d363899deed0de4c3cd7bfcab52bc40ce..e74d7f21004f417559d4d21aa7f541a811c35505 100644 --- a/e2e/check-translations.e2e-spec.ts +++ b/e2e/check-translations.e2e-spec.ts @@ -77,11 +77,7 @@ describe("ngHyd − check translation of all calculators", () => { } // check absence of "*** message not found" in whole DOM - const ps = await browser.getPageSource(); - expect(ps).not.toContain("*** message not found"); - /* const pos = ps.indexOf("*** message not found"); - const bout = ps.substring(pos - 50, pos + 50); - console.log("------------ BOUT ---------------", bout); */ + expect(await browser.getPageSource()).not.toContain("*** message not found", "missing translations found"); // empty session await navBar.clickMenuButton(); diff --git a/src/app/calculators/solveur/config.json b/src/app/calculators/solveur/config.json index fa1da444fcb444a1f7418c60118b999565ffb87c..03262ac7d9120f865f2d8b225f01b1d522eef6c9 100644 --- a/src/app/calculators/solveur/config.json +++ b/src/app/calculators/solveur/config.json @@ -5,8 +5,7 @@ "fields": [ { "id": "select_target_nub", - "type": "select_reference", - "reference": "nub", + "type": "select_custom", "source": "solveur_target" }, { @@ -25,8 +24,7 @@ "fields": [ { "id": "select_searched_param", - "type": "select_reference", - "reference": "parameter", + "type": "select_custom", "source": "solveur_searched" }, "Xinit" diff --git a/src/app/calculators/verificateur/config.json b/src/app/calculators/verificateur/config.json index 5b03751eda6393520a76969e37a8c169ce5dc25f..8ec8d41caf8aef98f29807dbb55cca905f00a9ac 100644 --- a/src/app/calculators/verificateur/config.json +++ b/src/app/calculators/verificateur/config.json @@ -5,8 +5,7 @@ "fields": [ { "id": "select_target_pass", - "type": "select_reference", - "reference": "nub", + "type": "select_custom", "source": "verificateur_target" }, { @@ -24,6 +23,7 @@ { "type": "select", "id": "select_species_list", + "property": "speciesList", "source": "verificateur_species", "multiple": true } @@ -31,7 +31,7 @@ }, { "type": "options", - "selectIds": [ "select_pab_jet_type" ], + "selectIds": [ "select_pab_jet_type", "select_species_list" ], "targetPassSelectId": "select_target_pass", "speciesListSelectId": "select_species_list", "help": "verification/verificateur.html" diff --git a/src/app/components/select-field-line/select-field-line.component.ts b/src/app/components/select-field-line/select-field-line.component.ts index f2c43341da3dddd48d88d66c2dd2a0ecf95fc468..c432c19e787e147f69437aaf599be10d26602fe4 100644 --- a/src/app/components/select-field-line/select-field-line.component.ts +++ b/src/app/components/select-field-line/select-field-line.component.ts @@ -3,8 +3,8 @@ import { Component, Input, OnInit } from "@angular/core"; import { SelectField } from "../../formulaire/elements/select-field"; import { SelectEntry } from "../../formulaire/elements/select-entry"; import { I18nService } from "../../services/internationalisation.service"; -import { SelectFieldReference } from "../../formulaire/elements/select-field-reference"; import { ApplicationSetupService } from "../../services/app-setup.service"; +import { SelectFieldCustom } from "../../formulaire/elements/select-field-custom"; @Component({ selector: "select-field-line", @@ -115,9 +115,7 @@ export class SelectFieldLineComponent implements OnInit { // called every time we navigate to the module ngOnInit(): void { - console.log("> ngOnInit()", this.selectId); - if (this._select instanceof SelectFieldReference) { - console.log(">> updateEntries() !", this.selectId); + if (this._select instanceof SelectFieldCustom) { this._select.updateEntries(); } } diff --git a/src/app/formulaire/definition/form-solveur.ts b/src/app/formulaire/definition/form-solveur.ts index b6987a5d5ee756ebf556c71dee6f19f5a915604e..fad442e8512f35b90792eb4e14f6ace9a85f46d0 100644 --- a/src/app/formulaire/definition/form-solveur.ts +++ b/src/app/formulaire/definition/form-solveur.ts @@ -1,7 +1,6 @@ import { IObservable, ParamDefinition, Nub } from "jalhyd"; -import { SelectFieldNub } from "../elements/select-field-nub"; -import { SelectFieldParameter } from "../elements/select-field-parameter"; +import { SelectFieldCustom } from "../elements/select-field-custom"; import { NgParameter } from "../elements/ngparam"; import { FormulaireFixedVar } from "./form-fixedvar"; import { SelectField } from "../elements/select-field"; @@ -36,7 +35,7 @@ export class FormulaireSolveur extends FormulaireFixedVar { sel.addObserver(this); if (firstNotif) { // force 1st observation - (sel as SelectFieldNub).notifySelectValueChanged(); + (sel as SelectFieldCustom).notifyValueChanged(); } } } @@ -56,7 +55,7 @@ export class FormulaireSolveur extends FormulaireFixedVar { sel.addObserver(this); if (firstNotif) { // force 1st observation - (sel as SelectFieldNub).notifySelectValueChanged(); + (sel as SelectFieldCustom).notifyValueChanged(); } } } @@ -80,8 +79,8 @@ export class FormulaireSolveur extends FormulaireFixedVar { this.reset(); } - if (sender instanceof SelectFieldNub) { - if (data.action === "select") { + if (sender instanceof SelectFieldCustom) { + if (sender.id === "select_target_nub" && data.action === "select") { // update Solveur property: Nub to calculate try { // if searchedParam is set to a value that won't be available anymore @@ -98,9 +97,7 @@ export class FormulaireSolveur extends FormulaireFixedVar { } // refresh parameters selector this.refreshParameterEntries(); - } - } else if (sender instanceof SelectFieldParameter) { - if (data.action === "select") { + } else if (sender.id === "select_searched_param" && data.action === "select") { // update Solveur property: searched Parameter try { const p: ParamDefinition = data.value.value; @@ -125,7 +122,7 @@ export class FormulaireSolveur extends FormulaireFixedVar { * Re-populate searched parameter selector with fresh entries */ private refreshParameterEntries() { - const pSel = this.getFormulaireNodeById(this._searchedParamSelectId) as SelectFieldParameter; + const pSel = this.getFormulaireNodeById(this._searchedParamSelectId) as SelectFieldCustom; if (pSel) { pSel.updateEntries(); // reflect changes in GUI diff --git a/src/app/formulaire/definition/form-verificateur.ts b/src/app/formulaire/definition/form-verificateur.ts index 50560319a8a37fff9cb39fc273ddb48134035a81..b7253882286a2c7282e287359b9835ebcbc825fd 100644 --- a/src/app/formulaire/definition/form-verificateur.ts +++ b/src/app/formulaire/definition/form-verificateur.ts @@ -1,7 +1,8 @@ -import { IObservable, Nub } from "jalhyd"; +import { IObservable, Nub, Verificateur } from "jalhyd"; -import { SelectFieldNub } from "../elements/select-field-nub"; +import { SelectFieldCustom } from "../elements/select-field-custom"; import { FormulaireFixedVar } from "./form-fixedvar"; +import { SelectField } from '../elements/select-field'; /** * Formulaire pour les Vérificateurs @@ -16,7 +17,7 @@ export class FormulaireVerificateur extends FormulaireFixedVar { protected parseOptions(json: {}) { super.parseOptions(json); - this._targetPassSelectId = this.getOption(json, "targetPassSelectI"); + this._targetPassSelectId = this.getOption(json, "targetPassSelectId"); this._speciesListSelectId = this.getOption(json, "speciesListSelectId"); } @@ -28,21 +29,10 @@ export class FormulaireVerificateur extends FormulaireFixedVar { sel.addObserver(this); if (firstNotif) { // force 1st observation - (sel as SelectFieldNub).notifySelectValueChanged(); + (sel as SelectFieldCustom).notifyValueChanged(); } } } - if (this._speciesListSelectId) { - const sel = this.getFormulaireNodeById(this._speciesListSelectId); - /* if (sel) { - sel.addObserver(this); - if (firstNotif) { - // force 1st observation - (sel as SelectFieldNub).notifySelectValueChanged(); - } - } */ - } - } // interface Observer @@ -62,30 +52,30 @@ export class FormulaireVerificateur extends FormulaireFixedVar { this.reset(); } - if (sender instanceof SelectFieldNub) { + console.log("> update", data, sender.constructor.name); + + if (sender instanceof SelectFieldCustom) { if (data.action === "select") { // update Verificateur property: Pass to check - this._currentNub.properties.setPropValue("nubToVerify", data.value.value); + let v = undefined; + if (data && data.value && data.value.value) { + v = data.value.value; + } + this._currentNub.properties.setPropValue("nubToVerify", data.value); // @TODO refresh jet type selector } - }/* else if (sender instanceof SelectField) { - if (sender.id === "select_target_result") { - // refresh parameters selector - this.refreshParameterEntries(); - } - } */ + } } - /** - * Re-populate searched parameter selector with fresh entries - */ - /* private refreshParameterEntries() { - const pSel = this.getFormulaireNodeById(this._speciesListSelectId) as SelectFieldParameter; + public onCalculatorInit() { + // refresh species list selector on each display, because Session might have gained new Espece nubs + console.log(">>>> speciesList avant rafraîchissement :", (this.currentNub as Verificateur).speciesList); + const pSel = this.getFormulaireNodeById(this._speciesListSelectId) as SelectField; if (pSel) { - pSel.updateEntries(); - // reflect changes in GUI - const inputYtarget = this.getFormulaireNodeById("Ytarget") as NgParameter; - inputYtarget.notifyValueModified(this); + /* pSel.clearEntries(); + pSel.parseConfig(); */ + // (pSel.parent as FieldSet).updateFields() } - } */ + } + } diff --git a/src/app/formulaire/elements/fieldset.ts b/src/app/formulaire/elements/fieldset.ts index 3e3b2714db410ebf1f7ec28c25c9f2d4066a7deb..13ee41a8d95e66a4717d930af421803699692010 100644 --- a/src/app/formulaire/elements/fieldset.ts +++ b/src/app/formulaire/elements/fieldset.ts @@ -13,8 +13,7 @@ import { SelectField } from "./select-field"; import { NgParameter, ParamRadioConfig } from "./ngparam"; import { StringMap } from "../../stringmap"; import { FieldsetContainer } from "./fieldset-container"; -import { SelectFieldNub } from "./select-field-nub"; -import { SelectFieldParameter } from "./select-field-parameter"; +import { SelectFieldCustom } from "./select-field-custom"; import { FormulaireFixedVar } from "../definition/form-fixedvar"; import { SelectEntry } from './select-entry'; @@ -84,23 +83,12 @@ export class FieldSet extends FormulaireElement implements Observer { return res; } - private parse_select_reference(json: {}): SelectField { - const refType = json["reference"]; + private parse_select_custom(json: {}): SelectField { const source = json["source"]; - let res: SelectField; if (source === undefined || source === "") { - throw new Error(`Fieldset.parse_select_reference(): "source" must not be empty`); - } - switch (refType) { - case "nub": // @TODO upstreamNub / downstreamNub ? - res = new SelectFieldNub(this, source); - break; - case "parameter": - res = new SelectFieldParameter(this, source); - break; - default: - throw new Error(`Fieldset.parse_select_reference(): unknown reference type ${refType}`); + throw new Error(`Fieldset.parse_select_custom(): "source" must not be empty`); } + const res: SelectField = new SelectFieldCustom(this); res.parseConfig(json); res.addObserver(this); return res; @@ -198,8 +186,8 @@ export class FieldSet extends FormulaireElement implements Observer { this.addField(param); break; - case "select_reference": - param = this.parse_select_reference(field); + case "select_custom": + param = this.parse_select_custom(field); this.addField(param); break; @@ -391,7 +379,12 @@ export class FieldSet extends FormulaireElement implements Observer { const fe = this.parentForm.getFieldById(sId); if (fe && data.value !== undefined) { const prop = (fe as SelectField).associatedProperty; - this.setPropValue(prop, data.value.value); + // for multiple select + if (Array.isArray(data.value)) { + this.setPropValue(prop, data.value.map((v: any) => v.value)); + } else { + this.setPropValue(prop, data.value.value); + } } } } diff --git a/src/app/formulaire/elements/select-field-custom.ts b/src/app/formulaire/elements/select-field-custom.ts new file mode 100644 index 0000000000000000000000000000000000000000..6c57eba105229a228bf06798eb654df23999a7ba --- /dev/null +++ b/src/app/formulaire/elements/select-field-custom.ts @@ -0,0 +1,216 @@ +import { SelectEntry } from "./select-entry"; +import { ServiceFactory } from "../../services/service-factory"; +import { decodeHtml, arraysAreEqual } from "../../util"; + +import { Session, Solveur, FishPass, CalculatorType, Verificateur, Nub } from "jalhyd"; +import { SelectField } from './select-field'; + +/** + * A select field that populates itself with custom stuff (ex: references to Nubs, Parameters…) + */ +export class SelectFieldCustom extends SelectField { + + /** + * Loads UI with the value held by the model + */ + protected initSelectedValue() { + const nub = this.parentForm.currentNub; + console.log("[X] I S V", nub.constructor.name, this.source); + switch (this.source) { + + case "solveur_target": // Solveur, module cible (à calculer) + const ntc = (nub as Solveur).nubToCalculate; + if (ntc !== undefined) { + this.setValueFromId(this._entriesBaseId + ntc.uid); + } + break; + + case "solveur_searched": // Solveur, paramètre recherché (à faire varier) + const sp = (nub as Solveur).searchedParameter; + if (sp !== undefined) { + this.setValueFromId(this._entriesBaseId + sp.nubUid + "_" + sp.symbol); + } + break; + + case "verificateur_target": // Vérificateur, passe cible (à vérifier) + const ntv = (nub as Verificateur).nubToVerify; + if (ntv !== undefined) { + this.setValueFromId(this._entriesBaseId + ntv.uid); + } + break; + } + } + + /** + * Populates entries with available options + */ + protected populate() { + const fs = ServiceFactory.instance.formulaireService; + let candidateNubs: any[]; + switch (this.source) { + + case "solveur_target": // Solveur, module cible (à calculer) + // find all Nubs having at least one link to another Nub's result + candidateNubs = + Session.getInstance().getDownstreamNubs().concat( + Session.getInstance().getUpstreamNubsHavingExtraResults() + ).filter( + (element, index, self) => self.findIndex((e) => e.uid === element.uid) === index + ); + for (const cn of candidateNubs) { + const nub = fs.getFormulaireFromId(cn.uid); + if (nub) { + const calc = nub.calculatorName; + let label = calc; + // calculated param + if (cn.calculatedParam !== undefined) { + const varName = fs.expandVariableName(cn.calcType, cn.calculatedParam.symbol); + label += ` / ${varName} (${cn.calculatedParam.symbol})`; + } + this.addEntry(new SelectEntry(this._entriesBaseId + cn.uid, cn.uid, decodeHtml(label))); + } else { + // silent fail, this Solveur nub was probably loaded before all the candidate nubs are done loading + } + } + break; + + case "solveur_searched": // Solveur, paramètre recherché (à faire varier) + // find all non-calculated, non-linked parameters of all Nubs that + // the current "target" Nub depends on (if any) + const solv = this.parentForm.currentNub as Solveur; + const ntc: Nub = solv.nubToCalculate; + const searchableParams = Solveur.getDependingNubsSearchableParams( + ntc, + solv.targettedResult !== undefined && solv.targettedResult !== "" + ); + for (const p of searchableParams) { + if (p.visible) { + const calc = fs.getFormulaireFromId(p.originNub.uid).calculatorName; + const varName = fs.expandVariableName(p.originNub.calcType, p.symbol); + const label = `${p.symbol} - ${varName} (${calc})`; + this.addEntry(new SelectEntry(this._entriesBaseId + p.originNub.uid + "_" + p.symbol, p, decodeHtml(label))); + } + } + break; + + case "verificateur_target": // Vérificateur, passe cible (à vérifier) + // find all Nubs of type FishPass + candidateNubs = Session.getInstance().getAllNubs().filter((element) => { + return ( + (element instanceof FishPass) + && element.calcType !== CalculatorType.Par // ParSimulation extends Par @TODO find something better + ); + }); + for (const cn of candidateNubs) { + const nub = fs.getFormulaireFromId(cn.uid); + if (nub) { + const label = nub.calculatorName + " (" + fs.getLocalisedTitleFromCalculatorType(nub.calculatorType) + ")"; + this.addEntry(new SelectEntry(this._entriesBaseId + cn.uid, cn.uid, decodeHtml(label))); + } else { + // silent fail, this Verificateur nub was probably loaded before all the candidate nubs are done loading + } + } + break; + + } + } + + protected setDefaultValue() { + // default to first available entry if any + if (this._entries.length > 0) { + if (this._multiple) { + this.setValue([ this._entries[0] ]); + } else { + this.setValue(this._entries[0]); + } + } else { + // notify observers that no value is selected anymore + this.notifyValueChanged(); + } + } + + /** + * Once config is parsed, init original value from model + * (needs config, for this._entriesBaseId to be set) + */ + protected afterParseConfig() { + this.populate(); + this.initSelectedValue(); + } + + /** + * Reloads available entries, trying to keep the current selected + * value; does not notify observers if value did not change + */ + public updateEntries() { + // store previous selected entry + const pse = this._selectedEntry; + // empty + this.clearEntries(); + // populate + this.populate(); + // if no entry is available anymore, unset value + if (this.entries.length === 0) { + if (this.multiple) { + super.setValue([]); + } else { + super.setValue(undefined); + } + } else { + // keep previously selected entry if possible @TODO manage multiple values + if (pse && ! Array.isArray(pse) && pse.id) { + this.setValueFromId(pse.id); + } else { + this.setDefaultValue(); + } + } + } + + /** + * Updates selectedValue; notifies observers only if + * value.id has changed + */ + public setValue(v: SelectEntry | SelectEntry[]) { + const previousSelectedEntry = this._selectedEntry; + this._selectedEntry = v; + // if value changed + let valueChanged = ( + ! previousSelectedEntry + || ( + ! Array.isArray(previousSelectedEntry) + && ! Array.isArray(v) + && previousSelectedEntry.id !== v.id + ) + || ( + Array.isArray(previousSelectedEntry) + && Array.isArray(v) + && arraysAreEqual(previousSelectedEntry, v, "id", true) + ) + ); + if (valueChanged) { + this.notifyValueChanged(); + } + } + + /** + * Sets value from given ID; if it was not found, sets the + * first available entry as selectedValue + */ + public setValueFromId(id: string) { + let found = false; + for (const e of this._entries) { + if (e.id === id) { + found = true; + if (this._multiple) { + this.setValue([ e ]); + } else { + this.setValue(e); + } + } + } + if (! found) { + this.setDefaultValue(); + } + } + +} diff --git a/src/app/formulaire/elements/select-field-nub.ts b/src/app/formulaire/elements/select-field-nub.ts deleted file mode 100644 index 9942f160fb3efb461cb51fd7d8b24a1c6b7dc64b..0000000000000000000000000000000000000000 --- a/src/app/formulaire/elements/select-field-nub.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { SelectFieldReference } from "./select-field-reference"; -import { SelectEntry } from "./select-entry"; -import { ServiceFactory } from "../../services/service-factory"; -import { decodeHtml } from "../../util"; - -import { Session, Solveur, FishPass, CalculatorType } from "jalhyd"; - -/** - * A select field that populates itself with references to Nubs - */ -export class SelectFieldNub extends SelectFieldReference { - - protected initSelectedValue() { - const nub = this.parentForm.currentNub; - if (nub instanceof Solveur) { - const ntc = nub.nubToCalculate; - if (ntc !== undefined) { - this.setValueFromId(this._entriesBaseId + ntc.uid); - } - } - } - - /** - * Populates entries with available references - */ - protected populate() { - const fs = ServiceFactory.instance.formulaireService; - let candidateNubs: any[]; - switch (this._source) { - case "solveur_target": // Solveur, module cible (à calculer) - // find all Nubs having at least one link to another Nub's result - candidateNubs = - Session.getInstance().getDownstreamNubs().concat( - Session.getInstance().getUpstreamNubsHavingExtraResults() - ).filter( - (element, index, self) => self.findIndex((e) => e.uid === element.uid) === index - ); - for (const cn of candidateNubs) { - const nub = fs.getFormulaireFromId(cn.uid); - if (nub) { - const calc = nub.calculatorName; - let label = calc; - // calculated param - if (cn.calculatedParam !== undefined) { - const varName = fs.expandVariableName(cn.calcType, cn.calculatedParam.symbol); - label += ` / ${varName} (${cn.calculatedParam.symbol})`; - } - this.addEntry(new SelectEntry(this._entriesBaseId + cn.uid, cn.uid, decodeHtml(label))); - } else { - // silent fail, this Solveur nub was probably loaded before all the candidate nubs are done loading - } - } - break; - - case "verificateur_target": // Vérificateur, passe cible (à vérifier) - // find all Nubs of type FishPass - candidateNubs = Session.getInstance().getAllNubs().filter((element) => { - return ( - (element instanceof FishPass) - && element.calcType !== CalculatorType.Par // ParSimulation extends Par @TODO find something better - ); - }); - for (const cn of candidateNubs) { - const nub = fs.getFormulaireFromId(cn.uid); - if (nub) { - const label = nub.calculatorName + " (" + fs.getLocalisedTitleFromCalculatorType(nub.calculatorType) + ")"; - this.addEntry(new SelectEntry(this._entriesBaseId + cn.uid, cn.uid, decodeHtml(label))); - } else { - // silent fail, this Verificateur nub was probably loaded before all the candidate nubs are done loading - } - } - break; - } - } - -} diff --git a/src/app/formulaire/elements/select-field-parameter.ts b/src/app/formulaire/elements/select-field-parameter.ts deleted file mode 100644 index c5a9d7291af5589382f0e54ebc698df7ce1cae4f..0000000000000000000000000000000000000000 --- a/src/app/formulaire/elements/select-field-parameter.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { SelectFieldReference } from "./select-field-reference"; -import { SelectEntry } from "./select-entry"; -import { decodeHtml } from "../../util"; -import { ServiceFactory } from "../../services/service-factory"; - -import { Nub, Solveur } from "jalhyd"; - -/** - * A select field that populates itself with references to ParamDefinitions - */ -export class SelectFieldParameter extends SelectFieldReference { - - protected initSelectedValue() { - const nub = this.parentForm.currentNub; - if (nub instanceof Solveur) { - const sp = nub.searchedParameter; - if (sp !== undefined) { - this.setValueFromId(this._entriesBaseId + sp.nubUid + "_" + sp.symbol); - } - } - } - - /** - * Populates entries with available references - */ - protected populate() { - switch (this._source) { - case "solveur_searched": // Solveur, paramètre recherché (à faire varier) - // find all non-calculated, non-linked parameters of all Nubs that - // the current "target" Nub depends on (if any) - const fs = ServiceFactory.instance.formulaireService; - const solv = this.parentForm.currentNub as Solveur; - const ntc: Nub = solv.nubToCalculate; - const searchableParams = Solveur.getDependingNubsSearchableParams( - ntc, - solv.targettedResult !== undefined && solv.targettedResult !== "" - ); - for (const p of searchableParams) { - if (p.visible) { - const calc = fs.getFormulaireFromId(p.originNub.uid).calculatorName; - const varName = fs.expandVariableName(p.originNub.calcType, p.symbol); - const label = `${p.symbol} - ${varName} (${calc})`; - this.addEntry(new SelectEntry(this._entriesBaseId + p.originNub.uid + "_" + p.symbol, p, decodeHtml(label))); - } - } - break; - } - } - -} diff --git a/src/app/formulaire/elements/select-field-reference.ts b/src/app/formulaire/elements/select-field-reference.ts deleted file mode 100644 index c4024feea76a86f7aa518dc4fd106f22ab230aae..0000000000000000000000000000000000000000 --- a/src/app/formulaire/elements/select-field-reference.ts +++ /dev/null @@ -1,132 +0,0 @@ -import { SelectField } from "./select-field"; -import { SelectEntry } from "./select-entry"; -import { FormulaireNode } from "./formulaire-node"; - -import { arraysAreEqual } from "../../util"; - -/** - * A select field that populates itself with references to - * available objects (for ex. Nub or ParamDefinition) - */ -export abstract class SelectFieldReference extends SelectField { - - /** source identifier for populate() method */ - protected _source: string; - - constructor(parent: FormulaireNode, source: string) { - super(parent); - this._source = source; - } - - protected abstract initSelectedValue(); - - /** - * Populates entries with available references - */ - protected abstract populate(); - - /** - * Once config is parsed, init original value from model - * (needs config, for this._entriesBaseId to be set) - */ - protected afterParseConfig() { - this.populate(); - this.initSelectedValue(); - } - - /** - * Reloads available entries, trying to keep the current selected - * value; does not notify observers if value did not change - */ - public updateEntries() { - // store previous selected entry - const pse = this._selectedEntry; - // empty - this.clearEntries(); - // populate - this.populate(); - // if no entry is available anymore, unset value - if (this.entries.length === 0) { - if (this.multiple) { - super.setValue([]); - } else { - super.setValue(undefined); - } - } else { - // keep previously selected entry if possible @TODO manage multiple values - if (pse && ! Array.isArray(pse) && pse.id) { - this.setValueFromId(pse.id); - } else { - this.setDefaultValue(); - } - } - } - - /** - * Updates selectedValue; notifies observers only if - * value.id has changed - */ - public setValue(v: SelectEntry | SelectEntry[]) { - const previousSelectedEntry = this._selectedEntry; - this._selectedEntry = v; - // if value changed - let valueChanged = ( - ! previousSelectedEntry - || ( - ! Array.isArray(previousSelectedEntry) - && ! Array.isArray(v) - && previousSelectedEntry.id !== v.id - ) - || ( - Array.isArray(previousSelectedEntry) - && Array.isArray(v) - && arraysAreEqual(previousSelectedEntry, v, "id", true) - ) - ); - if (valueChanged) { - this.notifySelectValueChanged(); - } - } - - public notifySelectValueChanged() { - this.notifyObservers({ - "action": "select", - "value": this._selectedEntry - }, this); - } - - /** - * Sets value from given ID; if it was not found, sets the - * first available entry as selectedValue - */ - public setValueFromId(id: string) { - let found = false; - for (const e of this._entries) { - if (e.id === id) { - found = true; - if (this._multiple) { - this.setValue([ e ]); - } else { - this.setValue(e); - } - } - } - if (! found) { - this.setDefaultValue(); - } - } - - protected setDefaultValue() { - // default to first available entry if any - if (this._entries.length > 0) { - if (this._multiple) { - this.setValue([ this._entries[0] ]); - } else { - this.setValue(this._entries[0]); - } - } else { - // notify observers that no value is selected anymore - this.notifySelectValueChanged(); - } - } -} diff --git a/src/app/formulaire/elements/select-field.ts b/src/app/formulaire/elements/select-field.ts index 4818e570918731128fe9a2e13284374b36b1ab83..4b10ec0b7e60b77680252d854a928c5477572f25 100644 --- a/src/app/formulaire/elements/select-field.ts +++ b/src/app/formulaire/elements/select-field.ts @@ -16,6 +16,7 @@ import { FormulaireNode } from "./formulaire-node"; import { FormulaireDefinition } from "../definition/form-definition"; import { ServiceFactory } from "../../services/service-factory"; import { FishSpecies } from 'jalhyd/build/verification/fish_species'; +import { sprintf } from 'sprintf-js'; export class SelectField extends Field { @@ -35,6 +36,9 @@ export class SelectField extends Field { /** if true, user can select multiple values */ protected _multiple = false; + /** soruce identifier for populating with available values */ + protected source: string; + constructor(parent: FormulaireNode) { super(parent); this.clearEntries(); @@ -75,30 +79,6 @@ export class SelectField extends Field { } } - /** - * Reloads available entries, trying to keep the current selected - * value; should not notify observers if value did not change - */ - public updateEntries() { - // store previous selected entry - const pse = this._selectedEntry; - this._selectedEntry = undefined; - // empty - this.clearEntries(); - // populate - this.populate(); - // keep previously selected entry if possible - if (pse) { - this.setValue(pse); - } - } - - /** - * Empties then refills entries list with available entries; does - * nothing by default (to be overloaded) - */ - protected populate() { } - /** * Triggered at the end of parseConfig() */ @@ -124,6 +104,7 @@ export class SelectField extends Field { } public notifyValueChanged() { + console.log("NOT VAL CHA", this.id, this._selectedEntry) this.notifyObservers({ "action": "select", "value": this._selectedEntry @@ -150,11 +131,20 @@ export class SelectField extends Field { if (field["multiple"] !== undefined) { this._multiple = field["multiple"]; } - const source = field["source"]; + this.source = field["source"]; + this.loadEntriesFromSource(); + + this.afterParseConfig(); + } + + /** + * Adds available entries to the selector, depending on the "source" identifier + */ + protected loadEntriesFromSource() { const nub: Nub = (this.parentForm as FormulaireDefinition).currentNub; // ad-hoc cases - switch (source) { + switch (this.source) { // driven by string[], not enum (easier for variable names) case "remous_target": this.addEntry(new SelectEntry(this._entriesBaseId + "none", "")); @@ -211,13 +201,22 @@ export class SelectField extends Field { } break; - // possible values depend on Session + // possible values depend on Session @TODO does not work, because not refreshed when Session gets new Espece nubs case "verificateur_species": + console.log("[i] loading verif species"); // add UIDs of all Espece type Nubs in the session const especeNubs = Session.getInstance().getAllNubs().filter((element) => element.calcType === CalculatorType.Espece); - console.log("especeNubs", especeNubs); for (const en of especeNubs) { - this.addEntry(new SelectEntry(en.uid, en.uid, "Espèce personnalisée : " + en.uid)); + this.addEntry( + new SelectEntry( + en.uid, + en.uid, + sprintf( + ServiceFactory.instance.i18nService.localizeText("INFO_VERIFICATEUR_CUSTOM_SPECIES"), + ServiceFactory.instance.formulaireService.getFormulaireFromNubId(en.uid).calculatorName + ) + ) + ); } // add all FishSpecies for (let j = 0; j < Object.keys(FishSpecies).length / 2; j++) { @@ -236,7 +235,6 @@ export class SelectField extends Field { } } } - - this.afterParseConfig(); } + } diff --git a/src/locale/messages.en.json b/src/locale/messages.en.json index fb4e4605e9cb9f3e531e22ee2eab7e34d00428f0..88ab30d875391f4710274d3a9271c9f3b1c1fd2e 100644 --- a/src/locale/messages.en.json +++ b/src/locale/messages.en.json @@ -532,6 +532,7 @@ "INFO_YAXB_TITRE_COURT": "Linear f.", "INFO_TRIGO_TITRE": "Trigonometric function", "INFO_TRIGO_TITRE_COURT": "Trigo. f.", + "INFO_VERIFICATEUR_CUSTOM_SPECIES": "Custom species: %s", "INFO_VERIFICATEUR_TITRE": "Fish pass verification", "INFO_VERIFICATEUR_TITRE_COURT": "Verification", "INFO_ESPECE_TITRE": "Fish species characteristics", diff --git a/src/locale/messages.fr.json b/src/locale/messages.fr.json index da9489786236b7f7d42117d08e049d7fc8a7a2e3..97e80ba3f088f098b5d1945ad08ed3f24b0e271a 100644 --- a/src/locale/messages.fr.json +++ b/src/locale/messages.fr.json @@ -533,6 +533,7 @@ "INFO_YAXB_TITRE_COURT": "F. affine", "INFO_TRIGO_TITRE": "Fonction trigonométrique", "INFO_TRIGO_TITRE_COURT": "F. trigo.", + "INFO_VERIFICATEUR_CUSTOM_SPECIES": "Espèce personnalisée : %s", "INFO_VERIFICATEUR_TITRE": "Vérification d'une passe", "INFO_VERIFICATEUR_TITRE_COURT": "Vérification", "INFO_ESPECE_TITRE": "Caractéristiques d'une espèce",