diff --git a/src/app/components/app-setup/app-setup.component.html b/src/app/components/app-setup/app-setup.component.html index 6b13d7452e50075941d000a8b58897c28d08c32d..f4fccc0edd743e224887e2c68db4bb2b76a4726b 100644 --- a/src/app/components/app-setup/app-setup.component.html +++ b/src/app/components/app-setup/app-setup.component.html @@ -74,6 +74,11 @@ {{ uitextEnableHotkeys }} </mat-checkbox> + <!-- empty all fields when creating a new form --> + <mat-checkbox name="emptyFields" [(ngModel)]="enableEmptyFieldsOnFormInit" [ngModelOptions]="{standalone: true}"> + {{ uitextEnableEmptyFieldsOnFormInit }} + </mat-checkbox> + <!-- langue --> <mat-form-field> <mat-select [placeholder]="uitextLanguage" [(value)]="currentLanguageCode" data-testid="language-select"> diff --git a/src/app/components/app-setup/app-setup.component.scss b/src/app/components/app-setup/app-setup.component.scss index 8cf82ff5c3de05fd78d557ad64dd17c84f9bffa9..fc0c077a107f987ea03286146535119273d3682c 100644 --- a/src/app/components/app-setup/app-setup.component.scss +++ b/src/app/components/app-setup/app-setup.component.scss @@ -11,6 +11,18 @@ } } + mat-checkbox { + display: block; + + ::ng-deep .mat-checkbox-label { + white-space: normal; + } + + ::ng-deep .mat-checkbox-inner-container { + margin-top: 4px; + } + } + mat-form-field { margin-top: 1.2em; display: block; diff --git a/src/app/components/app-setup/app-setup.component.ts b/src/app/components/app-setup/app-setup.component.ts index 249a25f82f0993c17d362fb1233542a452a187e5..e27840dcf61ac0e9a156f6456a82a32722e609ed 100644 --- a/src/app/components/app-setup/app-setup.component.ts +++ b/src/app/components/app-setup/app-setup.component.ts @@ -72,6 +72,15 @@ export class ApplicationSetupComponent implements Observer, OnInit { this.appSetupService.enableHotkeys = v; } + /** empty all fields when creating a new form */ + public get enableEmptyFieldsOnFormInit(): boolean { + return this.appSetupService.enableEmptyFieldsOnFormInit; + } + + public set enableEmptyFieldsOnFormInit(v: boolean) { + this.appSetupService.enableEmptyFieldsOnFormInit = v; + } + public get uitextTitle(): string { return this.intlService.localizeText("INFO_SETUP_TITLE"); } @@ -100,6 +109,10 @@ export class ApplicationSetupComponent implements Observer, OnInit { return this.intlService.localizeText("INFO_SETUP_ENABLE_HOTKEYS"); } + public get uitextEnableEmptyFieldsOnFormInit(): string { + return this.intlService.localizeText("INFO_SETUP_ENABLE_EMPTY_FIELDS"); + } + public get uitextMustBeANumber(): string { return this.intlService.localizeText("ERROR_PARAM_MUST_BE_A_NUMBER"); } diff --git a/src/app/components/calculator-list/calculator-list.component.ts b/src/app/components/calculator-list/calculator-list.component.ts index e8e75569c2439d826a9fafebb7c3d2979eb4d823..ef48404663b02d0e9ee0dc905f66c5a74b3451d1 100644 --- a/src/app/components/calculator-list/calculator-list.component.ts +++ b/src/app/components/calculator-list/calculator-list.component.ts @@ -13,6 +13,7 @@ import { HttpService } from "../../services/http.service"; import { AppComponent } from "../../app.component"; import { FormulaireMacrorugoCompound } from "../../formulaire/definition/concrete/form-macrorugo-compound"; import { FormulaireSPP } from "../../formulaire/definition/concrete/form-spp"; +import { ApplicationSetupService } from "../../services/app-setup.service"; @Component({ @@ -27,7 +28,8 @@ export class CalculatorListComponent implements OnInit { @Inject(forwardRef(() => AppComponent)) private appComponent: AppComponent, private router: Router, private httpService: HttpService, - private intlService: I18nService + private intlService: I18nService, + private appSetupService: ApplicationSetupService ) { ServiceFactory.instance.i18nService.addObserver(this); ServiceFactory.instance.applicationSetupService.addObserver(this); @@ -146,6 +148,10 @@ export class CalculatorListComponent implements OnInit { } } } + + if (this.appSetupService.enableEmptyFieldsOnFormInit) { + f.emptyFields(); + } }); } diff --git a/src/app/components/fieldset-container/fieldset-container.component.ts b/src/app/components/fieldset-container/fieldset-container.component.ts index 8f22524ebefbcd33f6350777ceabc413423df9e4..04e6b058cd57204bde05f1227809ee0a5bd2bc5e 100644 --- a/src/app/components/fieldset-container/fieldset-container.component.ts +++ b/src/app/components/fieldset-container/fieldset-container.component.ts @@ -5,6 +5,7 @@ import { FieldSetComponent } from "../field-set/field-set.component"; import { FieldSet } from "../../formulaire/fieldset"; import { FormulaireDefinition } from "../../formulaire/definition/form-definition"; import { I18nService } from "../../services/internationalisation.service"; +import { ApplicationSetupService } from "../../services/app-setup.service"; @Component({ selector: "fieldset-container", @@ -64,7 +65,10 @@ export class FieldsetContainerComponent implements DoCheck, AfterViewInit { @Output() protected tabPressed = new EventEmitter<any>(); - public constructor(private i18nService: I18nService) {} + public constructor( + private i18nService: I18nService, + private appSetupService: ApplicationSetupService + ) {} /** * Ajoute un nouveau sous-nub (Structure, PabCloisons, YAXN… selon le cas) @@ -73,6 +77,9 @@ export class FieldsetContainerComponent implements DoCheck, AfterViewInit { private addSubNub(after?: FieldSet, clone: boolean = false) { if (after) { const newFs = this._container.addFromTemplate(0, after.indexAsKid()); + if (this.appSetupService.enableEmptyFieldsOnFormInit && ! clone) { + newFs.emptyFields(); + } if (clone) { // replace in-place to change properties (overkill) // @TODO why only those two ? loop over all properties in a generic way ? @@ -84,7 +91,10 @@ export class FieldsetContainerComponent implements DoCheck, AfterViewInit { } } } else { - this._container.addFromTemplate(0); + const newFs = this._container.addFromTemplate(0); + if (this.appSetupService.enableEmptyFieldsOnFormInit && ! clone) { + newFs.emptyFields(); + } } } diff --git a/src/app/config.json b/src/app/config.json index 55c2352e46bbccece0549f96f672334d6f2aac03..f9d36885cc825e0af03a659ed6445a8674c90178 100644 --- a/src/app/config.json +++ b/src/app/config.json @@ -5,6 +5,7 @@ "maxIterations": 100, "enableNotifications": true, "enableHotkeys": false, + "enableEmptyFieldsOnFormInit": true, "language": "fr" }, "themes": [ diff --git a/src/app/formulaire/definition/concrete/form-macrorugo-compound.ts b/src/app/formulaire/definition/concrete/form-macrorugo-compound.ts index b9690657eec530045c5c6ee2a0bdd482d8796b45..359fbf1ed40bd4f59cf0795b23f1b0336b40c067 100644 --- a/src/app/formulaire/definition/concrete/form-macrorugo-compound.ts +++ b/src/app/formulaire/definition/concrete/form-macrorugo-compound.ts @@ -57,19 +57,6 @@ export class FormulaireMacrorugoCompound extends FormulaireBase { return Session.getInstance().createNub(p, this.mrcNub) as MacroRugo; } - /** - * Replaces the given MacroRugo sn in the current calculator module, - * with a new one built with properties "params" - * @param mr MacroRugo to replace - * @param params properties to build the new Nub (calcType) - */ - protected replaceNub(mr: MacroRugo, params: Props): Nub { - const parent = this.mrcNub; - const newStructure = this.createMacroRugo(params); - parent.replaceChildInplace(mr, newStructure); - return newStructure; - } - public createFieldset(parent: FormulaireNode, json: {}, data?: {}, nub?: Nub): FieldSet { if (json["calcType"] === "MacroRugo") { // indice après lequel insérer le nouveau FieldSet diff --git a/src/app/formulaire/definition/concrete/form-spp.ts b/src/app/formulaire/definition/concrete/form-spp.ts index a12a196b676fa84a28b143a0a57e209c051eb016..986d40301b903e6e33d6361c86e9647773377c7b 100644 --- a/src/app/formulaire/definition/concrete/form-spp.ts +++ b/src/app/formulaire/definition/concrete/form-spp.ts @@ -56,19 +56,6 @@ export class FormulaireSPP extends FormulaireBase { return Session.getInstance().createNub(p, this.sppNub) as YAXN; } - /** - * Replaces the given YAXN sn in the current calculator module, - * with a new one built with properties "params" - * @param mr YAXN to replace - * @param params properties to build the new Nub (calcType) - */ - protected replaceNub(mr: YAXN, params: Props): Nub { - const parent = this.sppNub; - const newStructure = this.createYaxn(params); - parent.replaceChildInplace(mr, newStructure); - return newStructure; - } - public createFieldset(parent: FormulaireNode, json: {}, data?: {}, nub?: Nub): FieldSet { if (json["calcType"] === "YAXN") { // indice après lequel insérer le nouveau FieldSet diff --git a/src/app/formulaire/definition/form-definition.ts b/src/app/formulaire/definition/form-definition.ts index 438111702de544a58997daef9f92dd26a9da8c2f..908c91caf63ede6c0ae62c72ee39b72d6734b91b 100644 --- a/src/app/formulaire/definition/form-definition.ts +++ b/src/app/formulaire/definition/form-definition.ts @@ -1,4 +1,4 @@ -import { CalculatorType, ComputeNodeType, Nub, Props, Observer, Session, SectionNub, acSection } from "jalhyd"; +import { CalculatorType, ComputeNodeType, Nub, Props, Observer, Session, SectionNub, acSection, ParamValueMode } from "jalhyd"; import { FormulaireElement } from "../formulaire-element"; import { NgParameter, ParamRadioConfig } from "../ngparam"; @@ -9,7 +9,6 @@ import { FieldSet } from "../fieldset"; import { FieldsetContainer } from "../fieldset-container"; import { SelectField } from "../select-field"; import { DeepFieldsetIterator } from "../form-iterator/deep-fieldset-iterator"; -import { DeepFormulaireElementIterator } from "../form-iterator/deep-element-iterator"; import { TopFormulaireElementIterator } from "../form-iterator/top-element-iterator"; import { CalculatorResults } from "../../results/calculator-results"; import { ServiceFactory } from "../../services/service-factory"; @@ -435,13 +434,6 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs return new DeepFieldsetIterator(this); } - /** - * itère sur tous les FormulaireElement - */ - public get allFormElements(): IterableIterator<FormulaireElement> { - return new DeepFormulaireElementIterator(this); - } - /** * itère sur tous les FormulaireElement de 1er niveau */ diff --git a/src/app/formulaire/fieldset.ts b/src/app/formulaire/fieldset.ts index 03c9fb022532530ec2e75160563e2bab7cd98712..03cfa6701d32dda84e711697deacfaeaa9bee182 100644 --- a/src/app/formulaire/fieldset.ts +++ b/src/app/formulaire/fieldset.ts @@ -10,7 +10,6 @@ import { GrilleType, GrilleProfile, BiefRegime, - Solveur, TrigoOperation, TrigoUnit, SPPOperation, diff --git a/src/app/formulaire/formulaire-element.ts b/src/app/formulaire/formulaire-element.ts index 05c5965471ebdfbebdf85326dc219ffac5f2101b..96153bcc4be56b488a79e7c5a61b59121d410d99 100644 --- a/src/app/formulaire/formulaire-element.ts +++ b/src/app/formulaire/formulaire-element.ts @@ -90,11 +90,4 @@ export abstract class FormulaireElement extends FormulaireNode { public toString() { return "id:" + this.id + (this._isDisplayed ? " displayed" : " NOT displayed") + " label:" + this.label; } - - /** - * itère sur tous les FormulaireElement - */ - public get allFormElements(): IterableIterator<FormulaireElement> { - return new DeepFormulaireElementIterator(this); - } } diff --git a/src/app/formulaire/formulaire-node.ts b/src/app/formulaire/formulaire-node.ts index 7425f0a9fe44ef509704b33aa4a56d360301aa1d..e0166c3be90c95e31cdd66e9c478dcd6a4c0b746 100644 --- a/src/app/formulaire/formulaire-node.ts +++ b/src/app/formulaire/formulaire-node.ts @@ -1,4 +1,7 @@ -import { JalhydObject, IObservable, Observer, Observable } from "jalhyd"; +import { JalhydObject, IObservable, Observer, Observable, ParamValueMode } from "jalhyd"; +import { FormulaireElement } from "./formulaire-element"; +import { DeepFormulaireElementIterator } from "./form-iterator/deep-element-iterator"; +import { NgParameter } from "./ngparam"; /** * représentation sous forme d'arbre du formulaire et de ses éléments @@ -129,6 +132,26 @@ export abstract class FormulaireNode implements IObservable { this._observable.removeObserver(o); } + /** + * itère sur tous les FormulaireElement + */ + public get allFormElements(): IterableIterator<FormulaireElement> { + return new DeepFormulaireElementIterator(this); + } + + /** + * Set value of all single parameters to undefined, except for the given parameter ids + */ + public emptyFields(except: string[] = [ "Cd0", "CdWS", "CdGR", "CdWR", "CdO", "CdT", "CdWSL" ]) { + for (const p of this.allFormElements ) { + if (p instanceof NgParameter) { + if (p.valueMode === ParamValueMode.SINGLE && ! except.includes(p.id)) { + p.setValue(this, undefined); + } + } + } + } + /** * notifie un événement aux observateurs */ diff --git a/src/app/services/app-setup.service.ts b/src/app/services/app-setup.service.ts index fe7a624da10b34a7c58072012ef9131581a1de9b..2850c2c7ba63aec24f1c6c3e1967bc4371d8fa83 100644 --- a/src/app/services/app-setup.service.ts +++ b/src/app/services/app-setup.service.ts @@ -24,6 +24,7 @@ export class ApplicationSetupService extends Observable { private _maxIterations = 100; // tied to model public enableNotifications = true; public enableHotkeys = false; + public enableEmptyFieldsOnFormInit = true; public set computePrecision(p: number) { this._computePrecision = p; @@ -106,6 +107,7 @@ export class ApplicationSetupService extends Observable { this.storage.set(this.LOCAL_STORAGE_PREFIX + "maxIterations", this.maxIterations); this.storage.set(this.LOCAL_STORAGE_PREFIX + "enableNotifications", this.enableNotifications); this.storage.set(this.LOCAL_STORAGE_PREFIX + "enableHotkeys", this.enableHotkeys); + this.storage.set(this.LOCAL_STORAGE_PREFIX + "enableEmptyFieldsOnFormInit", this.enableEmptyFieldsOnFormInit); this.storage.set(this.LOCAL_STORAGE_PREFIX + "language", this.language); } @@ -127,7 +129,7 @@ export class ApplicationSetupService extends Observable { */ private readValuesFromLocalStorage(): string[] { const loadedKeys = []; - // get all config values (volontarily non-generic to prevent side-effects) + // get all config values (voluntarily non-generic to prevent side-effects) const displayPrecision = this.storage.get(this.LOCAL_STORAGE_PREFIX + "displayPrecision"); if (displayPrecision !== undefined) { this.displayPrecision = displayPrecision; @@ -153,6 +155,11 @@ export class ApplicationSetupService extends Observable { this.enableHotkeys = enableHotkeys; loadedKeys.push("enableHotkeys"); } + const enableEmptyFieldsOnFormInit = this.storage.get(this.LOCAL_STORAGE_PREFIX + "enableEmptyFieldsOnFormInit"); + if (enableEmptyFieldsOnFormInit !== undefined) { + this.enableEmptyFieldsOnFormInit = enableEmptyFieldsOnFormInit; + loadedKeys.push("enableEmptyFieldsOnFormInit"); + } const language = this.storage.get(this.LOCAL_STORAGE_PREFIX + "language"); if (language !== undefined) { this.language = language; @@ -172,6 +179,7 @@ export class ApplicationSetupService extends Observable { this.maxIterations = data.params.maxIterations; this.enableNotifications = data.params.enableNotifications; this.enableHotkeys = data.params.enableHotkeys; + this.enableEmptyFieldsOnFormInit = data.params.enableEmptyFieldsOnFormInit; this.language = data.params.language; // load themes for calculators list page this.themes = data.themes; diff --git a/src/locale/messages.en.json b/src/locale/messages.en.json index aa7a1e17dab614c7dad9853036f8ea2a9cdb6798..4a632d1cd0cda03869acce1af46264414a78bbc3 100644 --- a/src/locale/messages.en.json +++ b/src/locale/messages.en.json @@ -433,6 +433,7 @@ "INFO_SECTIONPARAMETREE_TITRE_COURT": "Param. section", "INFO_SECTIONPARAMETREE_TITRE": "Parametric section", "INFO_SETUP_ENABLE_HOTKEYS": "Enable keyboard shortcuts", + "INFO_SETUP_ENABLE_EMPTY_FIELDS": "Create new calculators with empty fields (no default values)", "INFO_SETUP_ENABLE_NOTIFICATIONS": "Enable on-screen notifications", "INFO_SETUP_LANGUAGE": "Language", "INFO_SETUP_NEWTON_MAX_ITER": "Solver iteration limit", diff --git a/src/locale/messages.fr.json b/src/locale/messages.fr.json index 5ea07e5bae9c0b417da32966bffaa5b8a9d27f6d..4d86f3a4af2edc11134c82fbdce48681d7278843 100644 --- a/src/locale/messages.fr.json +++ b/src/locale/messages.fr.json @@ -432,6 +432,7 @@ "INFO_SECTIONPARAMETREE_TITRE_COURT": "Sec. param.", "INFO_SECTIONPARAMETREE_TITRE": "Section paramétrée", "INFO_SETUP_ENABLE_HOTKEYS": "Activer les raccourcis clavier", + "INFO_SETUP_ENABLE_EMPTY_FIELDS": "Créer les nouveaux modules avec des champs vides (aucune valeur par défaut)", "INFO_SETUP_ENABLE_NOTIFICATIONS": "Activer les notifications à l'écran", "INFO_SETUP_LANGUAGE": "Langue", "INFO_SETUP_NEWTON_MAX_ITER": "Solveur : nombre d'itérations maximum",