diff --git a/jalhyd_branch b/jalhyd_branch index c804db3857d251df847812f210b18049b526da6d..5f6e767f0cb49d2f5a889a9ddd564a6000de42cf 100644 --- a/jalhyd_branch +++ b/jalhyd_branch @@ -1 +1 @@ -46-gestion-de-la-session-dans-la-lib +47-ajouter-la-suppression-d-un-ouvrage-dans-les-ouvrages-paralleles diff --git a/src/app/components/field-set/field-set.component.html b/src/app/components/field-set/field-set.component.html index 50c2405b0c634e5a09900bec421bfe3a95bbf49b..a180abdcf55b0049ce1050d1062c6b4e98b2de93 100644 --- a/src/app/components/field-set/field-set.component.html +++ b/src/app/components/field-set/field-set.component.html @@ -1,7 +1,13 @@ <div class="row"> - <div class="col-12 fieldset_title"> + <div class="col fieldset_title"> {{title}} </div> + <div *ngIf="_showButtons" class="col-2 backgrd"> + <i class="fa fa-plus fa-2x float-right" (click)='onAddClick()'></i> + <i class="fa fa-trash fa-2x float-right" [style.color]='removeButtonColor' (click)='onRemoveClick()'></i> + <i class="fa fa-arrow-up fa-2x float-right" [style.color]='upButtonColor' (click)='onMoveUpClick()'></i> + <i class="fa fa-arrow-down fa-2x float-right" [style.color]='downButtonColor' (click)='onMoveDownClick()'></i> + </div> </div> <!-- diff --git a/src/app/components/field-set/field-set.component.ts b/src/app/components/field-set/field-set.component.ts index f822498e87f6c8c067d1d7a090533eb66158f73f..1c14aafc4185fa19cc05fc904844a2b2a092313d 100644 --- a/src/app/components/field-set/field-set.component.ts +++ b/src/app/components/field-set/field-set.component.ts @@ -13,12 +13,14 @@ import { CheckField } from "../../formulaire/check-field"; templateUrl: "./field-set.component.html", styles: [`.fieldset_title { font-weight: bold; - margin: 0.3em 0 0.2em; padding: 0.3em; background-color: #eeeeee; }`, `.radio_param_header { width: 10em; + }`, + `.backgrd { + background-color: #eeeeee; }` ] }) @@ -37,26 +39,90 @@ export class FieldSetComponent implements DoCheck { private _paramComponents: QueryList<ParamFieldLineComponent>; /** - * événément de changement de validité + * événement de changement de validité */ @Output() private validChange = new EventEmitter(); /** - * événément de changement de valeur d'un input + * événement de changement de valeur d'un input */ @Output() private inputChange = new EventEmitter(); + /** + * événement de demande d'ajout d'un fieldset (FieldSet dans un FieldsetContainer) + */ + @Output() + private addFieldset = new EventEmitter(); + + /** + * événement de demande de remontée d'un fieldset dans la liste (FieldSet dans un FieldsetContainer) + */ + @Output() + private moveFieldsetUp = new EventEmitter(); + + /** + * événement de demande de descente d'un fieldset dans la liste (FieldSet dans un FieldsetContainer) + */ + @Output() + private moveFieldsetDown = new EventEmitter(); + + /** + * événement de demande de suppression d'un fieldset (FieldSet dans un FieldsetContainer) + */ + @Output() + private removeFieldset = new EventEmitter(); + /** * flag de validité de la saisie */ private _isValid: boolean = false; + /** + * flag d'affichage des boutons ajouter, supprimer, monter, descendre + */ + private _showButtons: boolean = false; + + /** + * flag d'activation du bouton monter + */ + private _enableUpButton: boolean = true; + + /** + * flag d'activation du bouton descendre + */ + private _enableDownButton: boolean = true; + + /** + * flag d'activation du bouton supprimer + */ + private _enableRemoveButton: boolean = true; + private get fields() { return this._fieldSet.kids; } + public set showButtons(b: boolean) { + this._showButtons = b; + } + + public set enableUpButton(b: boolean) { + this._enableUpButton = b; + } + + public set enableDownButton(b: boolean) { + this._enableDownButton = b; + } + + public set enableRemoveButton(b: boolean) { + this._enableRemoveButton = b; + } + + public set fieldsetNumber(n: number) { + this._fieldSet.labelNumber = n; + } + private hasRadioFix(): boolean { if (this._fieldSet.hasInputs) switch (this._fieldSet.getInput(0).radioConfig) { @@ -134,7 +200,7 @@ export class FieldSetComponent implements DoCheck { } /** - * événément de changement d'état d'un radio + * événement de changement d'état d'un radio */ @Output() private onRadio = new EventEmitter<any>(); @@ -194,4 +260,56 @@ export class FieldSetComponent implements DoCheck { public updateParametersFromUI() { this._paramComponents.forEach(fsc => fsc.updateParameterFromUI()); } + + /** + * clic sur le bouton ajouter + */ + private onAddClick() { + this.addFieldset.emit(this._fieldSet); + } + + /** + * clic sur le bouton supprimer + */ + private onRemoveClick() { + if (this._enableRemoveButton) + this.removeFieldset.emit(this._fieldSet); + } + + /** + * clic sur le bouton monter + */ + private onMoveUpClick() { + if (this._enableUpButton) + this.moveFieldsetUp.emit(this._fieldSet); + } + + /** + * clic sur le bouton descendre + */ + private onMoveDownClick() { + if (this._enableDownButton) + this.moveFieldsetDown.emit(this._fieldSet); + } + + /** + * couleur du bouton monter + */ + private get upButtonColor(): string { + return this._enableUpButton ? "black" : "lightgrey"; + } + + /** + * couleur du bouton descendre + */ + private get downButtonColor(): string { + return this._enableDownButton ? "black" : "lightgrey"; + } + + /** + * couleur du bouton supprimer + */ + private get removeButtonColor(): string { + return this._enableRemoveButton ? "black" : "lightgrey"; + } } diff --git a/src/app/components/fieldset-container/fieldset-container.component.html b/src/app/components/fieldset-container/fieldset-container.component.html index 9ba68f2347d8b34feee3203451948883f8be36ff..2d50dba9b97b4af55e7f43b12bdd81083d93cf08 100644 --- a/src/app/components/fieldset-container/fieldset-container.component.html +++ b/src/app/components/fieldset-container/fieldset-container.component.html @@ -2,10 +2,9 @@ <div class="row"> <h4>{{title}}</h4> </div> - <div class="row"> - <!-- bouton d'ajout d'un ouvrage --> - <button type="button" class="btn btn-grey waves-light" mdbRippleRadius (click)="addStructure()">Ajouter un ouvrage</button> - </div> - <field-set *ngFor="let fs of fieldsets" [fieldSet]=fs (onRadio)=onRadioClick($event) (onValid)=onFieldsetValid() (inputChange)=onInputChange()> + + <field-set *ngFor="let fs of fieldsets" [fieldSet]=fs (onRadio)=onRadioClick($event) (onValid)=onFieldsetValid() (inputChange)=onInputChange() + (addFieldset)=onAddFieldset($event) (removeFieldset)=onRemoveFieldset($event) (moveFieldsetUp)=onMoveFieldsetUp($event) + (moveFieldsetDown)=onMoveFieldsetDown($event)> </field-set> </div> \ No newline at end of file diff --git a/src/app/components/fieldset-container/fieldset-container.component.ts b/src/app/components/fieldset-container/fieldset-container.component.ts index 8c58ebd5becbf41999f3d3bb8b5a05809d9f87cf..baa3ce41893bea13e3479e6365f2cebdf03cddb8 100644 --- a/src/app/components/fieldset-container/fieldset-container.component.ts +++ b/src/app/components/fieldset-container/fieldset-container.component.ts @@ -1,13 +1,15 @@ -import { Component, Input, Output, EventEmitter, QueryList, ViewChildren, DoCheck } from "@angular/core"; +import { Component, Input, Output, EventEmitter, QueryList, ViewChildren, DoCheck, AfterViewInit } from "@angular/core"; import { FieldsetContainer } from "../../formulaire/fieldset-container"; import { FieldSetComponent } from "../field-set/field-set.component"; +import { FieldSet } from "../../formulaire/fieldset"; +import { FormulaireDefinition } from "../../formulaire/definition/form-definition"; @Component({ selector: "fieldset-container", templateUrl: "./fieldset-container.component.html" }) -export class FieldsetContainerComponent implements DoCheck { +export class FieldsetContainerComponent implements DoCheck, AfterViewInit { @Input("container") private _container: FieldsetContainer; @@ -32,8 +34,47 @@ export class FieldsetContainerComponent implements DoCheck { return this._container.fieldsets; } - private addStructure() { - this._container.addFromTemplate(0); + private addStructure(after?: FieldSet) { + if (after) + this._container.addFromTemplate(0, after.indexAsKid()); + else + this._container.addFromTemplate(0); + } + + private onFielsetListChange() { + // affichage des boutons ajouter, supprimer, monter, descendre + this._fieldsetComponents.forEach(fs => fs.showButtons = true); + + // désactivation du bouton supprimer s'il n'en reste qu'un + if (this._fieldsetComponents.length == 1) { + const fs = this._fieldsetComponents.last as FieldSetComponent; + fs.enableRemoveButton = false; + } + else + this._fieldsetComponents.forEach(fs => fs.enableRemoveButton = true); + + // désactivation du bouton monter pour le 1er + this._fieldsetComponents.forEach(fs => { + fs.enableUpButton = true; + fs.enableDownButton = true; + }); + this._fieldsetComponents.first.enableUpButton = false + + // désactivation du bouton monter pour le dernier + this._fieldsetComponents.last.enableDownButton = false + + // renumérotation + let n = 1; + this._fieldsetComponents.forEach(fsc => { + fsc.fieldsetNumber = n; + n++; + } + ); + } + + public ngAfterViewInit() { + this._fieldsetComponents.changes.subscribe(_ => this.onFielsetListChange()); + this.addStructure(); } /* @@ -119,4 +160,35 @@ export class FieldsetContainerComponent implements DoCheck { public updateParametersFromUI() { this._fieldsetComponents.forEach(fsc => fsc.updateParametersFromUI()); } + + /** + * réception d'un événement de demande d'ajout d'un FieldSet + */ + private onAddFieldset(fs: FieldSet) { + this.addStructure(fs); + } + + /** + * réception d'un événement de demande de suppression d'un FieldSet + */ + private onRemoveFieldset(fs: FieldSet) { + const form = this._container.parent as FormulaireDefinition; + form.removeFieldset(fs); + } + + /** + * réception d'un événement de demande de remontée d'un FieldSet + */ + private onMoveFieldsetUp(fs: FieldSet) { + const form = this._container.parent as FormulaireDefinition; + form.moveFieldsetUp(fs); + } + + /** + * réception d'un événement de demande de descente d'un FieldSet + */ + private onMoveFieldsetDown(fs: FieldSet) { + const form = this._container.parent as FormulaireDefinition; + form.moveFieldsetDown(fs); + } } diff --git a/src/app/formulaire/definition/concrete/form-parallel-structures.ts b/src/app/formulaire/definition/concrete/form-parallel-structures.ts index 11e85caf9f0a154d29cce6d57628ec8af205fab7..66838edba6c3e52e30279889cec8c0936ebf6fe4 100644 --- a/src/app/formulaire/definition/concrete/form-parallel-structures.ts +++ b/src/app/formulaire/definition/concrete/form-parallel-structures.ts @@ -52,8 +52,13 @@ export class FormulaireParallelStructure extends FormulaireDefinition { return paramService.createSessionNub(params); } - private addStructureNub(st: Structure) { - this.parallelStructureNub.addStructure(st); + /** + * ajoute un Nub Structure + * @param st structure à ajouter + * @param after position après laquelle insérer la structure, à la fin sinon + */ + private addStructureNub(st: Structure, after?: number) { + this.parallelStructureNub.addStructure(st, after); } private get parallelStructureNub(): ParallelStructure { @@ -66,15 +71,25 @@ export class FormulaireParallelStructure extends FormulaireDefinition { public createFieldset(parent: FormulaireNode, json: {}, data?: {}): FieldSet { if (json["calcType"] === "Structure") { + // indice après lequel insérer le nouveau FieldSet + const after = data["after"]; + const res: FieldSet = new FieldSet(parent); const sn = this.createStructNub(data["template"]); - this.addStructureNub(sn.nub as Structure); + this.addStructureNub(sn.nub as Structure, after); res.setSessionNub(sn, false); - parent.kids.push(res); + + if (after !== undefined) + parent.kids.splice(after + 1, 0, res); + else + parent.kids.push(res); + + this.resetResults(); + return res; } else - return super.createFieldset(parent, json); + return super.createFieldset(parent, json, data); } protected initParse() { @@ -86,7 +101,6 @@ export class FormulaireParallelStructure extends FormulaireDefinition { this.__ouvrageSelectId = this.getOption(json, "ouvrageSelectId"); } - public afterParseFieldset(fs: FieldSet) { // si le FieldSet contient le select de type d'ouvrage if (this.__ouvrageSelectId) { @@ -98,6 +112,45 @@ export class FormulaireParallelStructure extends FormulaireDefinition { } } + public moveFieldsetUp(fs: FieldSet) { + if (fs.sessionNub.nub instanceof Structure) { + // déplacement du nub + this._paramService.moveStructureNubUp(fs.sessionNub); + + // déplacement du fieldset + this.fieldsetContainer.moveFieldsetUp(fs); + + this.resetResults(); + } + else super.moveFieldsetUp(fs); + } + + public moveFieldsetDown(fs: FieldSet) { + if (fs.sessionNub.nub instanceof Structure) { + // déplacement du nub + this._paramService.moveStructureNubDown(fs.sessionNub); + + // déplacement du fieldset + this.fieldsetContainer.moveFieldsetDown(fs); + + this.resetResults(); + } + else super.moveFieldsetDown(fs); + } + + public removeFieldset(fs: FieldSet) { + if (fs.sessionNub.nub instanceof Structure) { + // suppression du nub + this._paramService.deleteSessionNub(fs.sessionNub); + + // suppression du fieldset + this.fieldsetContainer.removeFieldset(fs); + + this.resetResults(); + } + else super.removeFieldset(fs); + } + protected completeParse(json: {}) { this._formParamCalc.parseOptions(json); this.subscribeFieldsetContainer(); @@ -132,15 +185,18 @@ export class FormulaireParallelStructure extends FormulaireDefinition { return this._formResult.results; } + private get fieldsetContainer(): FieldsetContainer { + const n = this.getFormulaireNodeById("struct_container"); + if (n == undefined || !(n instanceof FieldsetContainer)) + throw new Error("l'élément 'struct_container' n'est pas du type FieldsetContainer"); + return n as FieldsetContainer; + } + /** * abonnement en tant qu'observateur du FieldsetContainer */ private subscribeFieldsetContainer() { - const n = this.getFormulaireNodeById("struct_container"); - if (n == undefined || !(n instanceof FieldsetContainer)) - throw new Error("l'élément 'struct_container' n'est pas du type FieldsetContainer"); - const fsc: FieldsetContainer = n as FieldsetContainer; - fsc.addObserver(this); + this.fieldsetContainer.addObserver(this); } /** diff --git a/src/app/formulaire/definition/form-compute-parallel-structures.ts b/src/app/formulaire/definition/form-compute-parallel-structures.ts index aaba5b3c5edd4225d195bf1fb35cfbd3e5dd3b2f..380f000fb4c87a172bf405c9abb9480ac838c368 100644 --- a/src/app/formulaire/definition/form-compute-parallel-structures.ts +++ b/src/app/formulaire/definition/form-compute-parallel-structures.ts @@ -33,7 +33,7 @@ export class FormComputeParallelStructures extends FormComputeFixedVar { if (parent1 instanceof FieldSet) { const parent2 = parent1.parent; if (parent2 instanceof FieldsetContainer) { - const fsIndex = parent1.indexAsKid(this._formBase); + const fsIndex = parent1.indexAsKid(); return [parent2, parent1, fsIndex]; } } diff --git a/src/app/formulaire/definition/form-definition.ts b/src/app/formulaire/definition/form-definition.ts index f6e05c3a8c76e530b9cbb6f2fd9b5e4be0694a0d..b331672608a81ae7066941f27fea07da6d0a4389 100644 --- a/src/app/formulaire/definition/form-definition.ts +++ b/src/app/formulaire/definition/form-definition.ts @@ -114,6 +114,10 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs throw new Error(`FormulaireDefinition.getNubParamFromSymbol() : pas de Nub trouvé pour ${params}`) } + protected deleteSessionNub(sn: SessionNub) { + this._paramService.deleteSessionNub(sn); + } + protected initParse() { } @@ -140,6 +144,15 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs return res; } + public moveFieldsetUp(fs: FieldSet) { + } + + public moveFieldsetDown(fs: FieldSet) { + } + + public removeFieldset(fs: FieldSet) { + } + private parse_fieldset(json: {}) { const fs = this.createFieldset(this, json); fs.parseConfig(json, { "parentForm": this }); diff --git a/src/app/formulaire/fieldset-container.ts b/src/app/formulaire/fieldset-container.ts index 67af3f159fe9c266d0d8a25f0f4bdbb9e5204784..a354d2a7d9ca17355f08fd16d03ae576c932386a 100644 --- a/src/app/formulaire/fieldset-container.ts +++ b/src/app/formulaire/fieldset-container.ts @@ -32,10 +32,46 @@ export class FieldsetContainer extends FormulaireElement { this.fieldsets.push(fs); } - public addFromTemplate(index: number) { - const templ: FieldsetTemplate = this._templates[index]; + public moveFieldsetUp(fs: FieldSet) { + let i = 0; + for (const f of this.kids) { + if (f.uid === fs.uid && i > 0) { + const t = this.kids[i - 1]; + this.kids[i - 1] = this.kids[i]; + this.kids[i] = t; + return; + } + i++; + } + } + + public moveFieldsetDown(fs: FieldSet) { + let i = 0; + for (const f of this.kids) { + if (f.uid === fs.uid && i < this.kids.length - 1) { + const t = this.kids[i]; + this.kids[i] = this.kids[i + 1]; + this.kids[i + 1] = t; + return; + } + i++; + } + } + + public removeFieldset(fs: FieldSet) { + const i = fs.indexAsKid(); + this.kids.splice(i, 1); + } + + /** + * crée un FieldSet à partir d'un template + * @param templateIndex indice du template dans la liste + * @param after insère le nouveau FieldSet après cette position, à la fin sinon + */ + public addFromTemplate(templateIndex: number, after?: number) { + const templ: FieldsetTemplate = this._templates[templateIndex]; - const inst: FieldSet = templ.instantiateTemplate(this); + const inst: FieldSet = templ.instantiateTemplate(this, after); this.updateLocalisation(); diff --git a/src/app/formulaire/fieldset-template.ts b/src/app/formulaire/fieldset-template.ts index c21455761a1f062442e62b817c7573f9eb5f9546..a5d61834921dcdeb5408047af79db76c29386f53 100644 --- a/src/app/formulaire/fieldset-template.ts +++ b/src/app/formulaire/fieldset-template.ts @@ -38,9 +38,14 @@ export class FieldsetTemplate { return nodeType; } - public instantiateTemplate(cont: FieldsetContainer): FieldSet { + /** + * crée une instance de Fieldset et l'ajoute dans un conteneur + * @param cont conteneur + * @param at position à laquelle on ajoute le nouveau FieldSet + */ + public instantiateTemplate(cont: FieldsetContainer, after: number): FieldSet { const parentForm = cont.parent as FormulaireDefinition; - const res = parentForm.createFieldset(cont, this._jsonConfig, { "template": this }); + const res = parentForm.createFieldset(cont, this._jsonConfig, { "template": this, "after": after }); res.parseConfig(this._jsonConfig, { "parentForm": parentForm }); parentForm.afterParseFieldset(res); return res; diff --git a/src/app/formulaire/formulaire-element.ts b/src/app/formulaire/formulaire-element.ts index 00bdce133d895b354b086c7855e522ae278452d4..94311583903421552d7d5ae7bc7e46ede318aff6 100644 --- a/src/app/formulaire/formulaire-element.ts +++ b/src/app/formulaire/formulaire-element.ts @@ -22,6 +22,11 @@ export abstract class FormulaireElement extends FormulaireNode { */ private _label: string; + /** + * n° d'ordre ajouté à l'étiquette + */ + private _labelNumber: number; + protected _dependencies: Dependency[] = []; constructor(parent: FormulaireNode) { @@ -40,7 +45,14 @@ export abstract class FormulaireElement extends FormulaireNode { } get label(): string { - return this._label; + let res = this._label; + if (res && this._labelNumber) + res += " n°" + String(this._labelNumber); + return res; + } + + public set labelNumber(n: number) { + this._labelNumber = n; } public getKids(): FormulaireElement[] { @@ -135,7 +147,8 @@ export abstract class FormulaireElement extends FormulaireNode { public updateLocalisation(loc: StringMap, key?: string) { if (!key) key = this._confId; - this._label = loc[key]; + if (loc) + this._label = loc[key]; if (this._label == undefined) console.log(`WARNING : pas de traduction pour l'id ${this.id}`); diff --git a/src/app/formulaire/formulaire-node.ts b/src/app/formulaire/formulaire-node.ts index b323f214b94ed098738c494791062863fe4e4727..814d47c88f0734d4a1940a527ba12d81ece7b1f7 100644 --- a/src/app/formulaire/formulaire-node.ts +++ b/src/app/formulaire/formulaire-node.ts @@ -107,9 +107,8 @@ export abstract class FormulaireNode implements IObservable { /** * retourne l'indice de this dans la liste des enfants de son parent * (cad rang par rapport à ses frères) - * @param root FormulaireNode racine dont on part pour rechercher le parent */ - public indexAsKid(root: FormulaireNode): number { + public indexAsKid(): number { return this._parentNode.kidIndex(this); } diff --git a/src/app/services/param/param.service.ts b/src/app/services/param/param.service.ts index 6bcc6f831913534cea2bfd0cb6de8d8c342e4d86..0b5dea30679d99ce1f1f9732326d8f9885426e36 100644 --- a/src/app/services/param/param.service.ts +++ b/src/app/services/param/param.service.ts @@ -103,4 +103,16 @@ export class ParamService { public replaceSessionNub(sn: SessionNub, params: Props): SessionNub { return NubFactory.getInstance().replaceSessionNub(sn, params); } + + public moveStructureNubUp(sn: SessionNub) { + NubFactory.getInstance().moveStructureNubUp(sn); + } + + public moveStructureNubDown(sn: SessionNub) { + NubFactory.getInstance().moveStructureNubDown(sn); + } + + public deleteSessionNub(sn: SessionNub) { + NubFactory.getInstance().deleteSessionNub(sn); + } }