From 935341427623fd4644d64e69764a393ff5e6e4d7 Mon Sep 17 00:00:00 2001 From: "francois.grand" <francois.grand@irstea.fr> Date: Mon, 14 May 2018 15:13:52 +0200 Subject: [PATCH 01/20] #45 ajout d'un bouton de sauvegarde de la calculette --- .../components/generic-calculator/calculator.component.html | 5 +++++ .../components/generic-calculator/calculator.component.ts | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/src/app/components/generic-calculator/calculator.component.html b/src/app/components/generic-calculator/calculator.component.html index 72737bb6f..3eda7ef8c 100644 --- a/src/app/components/generic-calculator/calculator.component.html +++ b/src/app/components/generic-calculator/calculator.component.html @@ -10,6 +10,11 @@ <i *ngIf="enableHelpButton" class="fa fa-question-circle fa-3x" style="color:blue" (click)="openHelp()"></i> </div> + <div class="col-1 px-0 mx-0"> + <!-- bouton de sauvegarde --> + <i class="fa fa-save fa-3x" (click)="saveCalculator()"></i> + </div> + <div class="col-1 px-0 mx-0"> <!-- bouton de fermeture --> <!-- <button type="button" id="close-button" class="btn btn-primary float-right black" (click)="confirmModal.show()">×</button> --> diff --git a/src/app/components/generic-calculator/calculator.component.ts b/src/app/components/generic-calculator/calculator.component.ts index 70abce734..26cb224a1 100644 --- a/src/app/components/generic-calculator/calculator.component.ts +++ b/src/app/components/generic-calculator/calculator.component.ts @@ -371,4 +371,8 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit, private openHelp() { this._formulaire.requestHelp(); } + + + private saveCalculator() { + } } -- GitLab From 1755d171ff48d275d99d1be4a2acd2dd46aee172 Mon Sep 17 00:00:00 2001 From: "francois.grand" <francois.grand@irstea.fr> Date: Tue, 15 May 2018 11:44:31 +0200 Subject: [PATCH 02/20] =?UTF-8?q?=20#45=20cr=C3=A9ation=20d'un=20composant?= =?UTF-8?q?=20dialogue=20de=20sauvegarde=20des=20calculettes=20proposant?= =?UTF-8?q?=20une=20liste=20des=20calculettes=20=C3=A0=20sauver?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/app.component.html | 3 + src/app/app.component.ts | 27 +++++++- src/app/app.module.ts | 6 +- .../calculator.component.ts | 2 +- .../save-calculator-anchor.directive.ts | 27 ++++++++ .../save-calculator.component.html | 20 ++++++ .../save-calculator.component.ts | 69 +++++++++++++++++++ .../services/formulaire/formulaire.service.ts | 7 ++ 8 files changed, 158 insertions(+), 3 deletions(-) create mode 100644 src/app/components/save-calculator/save-calculator-anchor.directive.ts create mode 100644 src/app/components/save-calculator/save-calculator.component.html create mode 100644 src/app/components/save-calculator/save-calculator.component.ts diff --git a/src/app/app.component.html b/src/app/app.component.html index 77966eddc..17a3b0cb7 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -39,6 +39,9 @@ </div> </div> + <!-- sauvegarde des calculettes --> + <div saveCalcDialogAnchor></div> + <!-- règle gradée des colonnes Bootstrap --> <div *ngIf="ruler" class="container-fluid"> <div class="row"> diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 8f89ea119..74ec9f1ca 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,4 +1,4 @@ -import { Component, ApplicationRef, OnInit, OnDestroy } from '@angular/core'; +import { Component, ApplicationRef, OnInit, OnDestroy, ViewChild, ComponentRef } from '@angular/core'; //import { MdDialog } from '@angular/material'; import { Router, ActivatedRoute } from '@angular/router'; @@ -16,6 +16,8 @@ import { ApplicationSetupService } from './services/app-setup/app-setup.service' import { HttpService } from './services/http/http.service'; import { HelpService } from './services/help/help.service'; import { HelpComponent } from './components/help/help.component'; +import { SaveCalcDialogAnchorDirective } from './components/save-calculator/save-calculator-anchor.directive'; +import { SaveCalculatorComponent } from './components/save-calculator/save-calculator.component'; @Component({ @@ -34,6 +36,9 @@ export class AppComponent implements OnInit, OnDestroy, Observer { */ private _currentFormId: number; + @ViewChild(SaveCalcDialogAnchorDirective) + private saveCalcDialogAnchor: SaveCalcDialogAnchorDirective; + /** * composant actuellement affiché par l'élément <router-outlet> */ @@ -147,6 +152,10 @@ export class AppComponent implements OnInit, OnDestroy, Observer { }, 1); break; + case "saveForm": + this.saveForm(data["form"]); + break; + case "closeForm": const form: FormulaireDefinition = data["form"]; this.closeCalculator(form); @@ -183,6 +192,22 @@ export class AppComponent implements OnInit, OnDestroy, Observer { this._calculators[formIndex]["title"] = title; } + private saveForm(form: FormulaireDefinition) { + const compRef: ComponentRef<SaveCalculatorComponent> = this.saveCalcDialogAnchor.createDialog(); + + let list = []; + for (const c of this._calculators) { + const uid = +c["uid"]; + list.push({ + "selected": uid === form.uid, + "title": c["title"], + "uid": uid + }) + } + + compRef.instance.list = list; + } + private closeCalculator(form: FormulaireDefinition) { const formId: number = form.uid; diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 56f5e83b5..3c42eccb6 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -49,6 +49,8 @@ import { VerticalResultElementComponent } from './components/result-element/vert import { LogEntryComponent } from './components/log-entry/log-entry.component'; import { HelpService } from './services/help/help.service'; import { HelpComponent } from './components/help/help.component'; +import { SaveCalculatorComponent } from './components/save-calculator/save-calculator.component'; +import { SaveCalcDialogAnchorDirective } from './components/save-calculator/save-calculator-anchor.directive'; const appRoutes: Routes = [ { path: 'list', component: CalculatorListComponent }, @@ -94,9 +96,11 @@ const appRoutes: Routes = [ CalcCanvasComponent, SectionCanvasComponent, HorizontalResultElementComponent, VerticalResultElementComponent, FixedResultsComponent, VarResultsComponent, - HelpComponent + HelpComponent, + SaveCalculatorComponent, SaveCalcDialogAnchorDirective ], // entryComponents: [AlertDialog], + entryComponents: [SaveCalculatorComponent], providers: [ // services ParamService, InternationalisationService, HttpService, FormulaireService, ApplicationSetupService, HelpService ], diff --git a/src/app/components/generic-calculator/calculator.component.ts b/src/app/components/generic-calculator/calculator.component.ts index 26cb224a1..b7b8a07fc 100644 --- a/src/app/components/generic-calculator/calculator.component.ts +++ b/src/app/components/generic-calculator/calculator.component.ts @@ -372,7 +372,7 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit, this._formulaire.requestHelp(); } - private saveCalculator() { + this.formulaireService.saveForm(this._formulaire); } } diff --git a/src/app/components/save-calculator/save-calculator-anchor.directive.ts b/src/app/components/save-calculator/save-calculator-anchor.directive.ts new file mode 100644 index 000000000..4317ff3ac --- /dev/null +++ b/src/app/components/save-calculator/save-calculator-anchor.directive.ts @@ -0,0 +1,27 @@ +import { Directive, ComponentFactoryResolver, ComponentFactory, ComponentRef } from '@angular/core'; + +import { ViewContainerRef } from '@angular/core'; +import { SaveCalculatorComponent } from './save-calculator.component'; + +@Directive({ + selector: '[saveCalcDialogAnchor]' +}) +export class SaveCalcDialogAnchorDirective { + constructor( + private viewContainer: ViewContainerRef, + private componentFactoryResolver: ComponentFactoryResolver + ) { } + + public createDialog(): ComponentRef<SaveCalculatorComponent> { + this.viewContainer.clear(); + + let compFactory: ComponentFactory<SaveCalculatorComponent> = this.componentFactoryResolver.resolveComponentFactory(SaveCalculatorComponent); + let compRef: ComponentRef<SaveCalculatorComponent> = this.viewContainer.createComponent(compFactory); + + // dialogComponentRef.instance.close.subscribe(() => { + // dialogComponentRef.destroy(); + // }); + + return compRef; + } +} diff --git a/src/app/components/save-calculator/save-calculator.component.html b/src/app/components/save-calculator/save-calculator.component.html new file mode 100644 index 000000000..1cc9083f7 --- /dev/null +++ b/src/app/components/save-calculator/save-calculator.component.html @@ -0,0 +1,20 @@ +<div mdbModal #saveDialog="mdb-modal" class="modal fade" tabindex="-1" role="dialog" aria-hidden="true" [config]="{backdrop: false, ignoreBackdropClick: true,show:true}"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title w-100" id="myModalLabel">{{uitextDialogTitle}}</h4> + </div> + <div class="modal-body"> + <div *ngFor="let c of _calculators"> + <input type="checkbox" value={{c.uid}} checked={{isSelected(c)}} (change)="onCheckCalc($event)">{{c.title}} + </div> + <button type="button" class="btn btn-mdb-color waves-light" (click)="selectAll()" mdbRippleRadius>{{uitextSelectAll}}</button> + <button type="button" class="btn btn-mdb-color waves-light" (click)="deselectAll()" mdbRippleRadius>{{uitextDeselectAll}}</button> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-danger relative waves-light" (click)="saveDialog.hide()" mdbRippleRadius>{{uitextCloseDialogNo}}</button> + <button type="button" class="btn btn-success waves-light" aria-label="Close " (click)="saveDialog.hide();confirmSave()" mdbRippleRadius>{{uitextCloseDialogYes}}</button> + </div> + </div> + </div> +</div> \ No newline at end of file diff --git a/src/app/components/save-calculator/save-calculator.component.ts b/src/app/components/save-calculator/save-calculator.component.ts new file mode 100644 index 000000000..865054a33 --- /dev/null +++ b/src/app/components/save-calculator/save-calculator.component.ts @@ -0,0 +1,69 @@ +import { Component } from "@angular/core"; +import { ServiceFactory } from "../../services/service-factory"; +import { InternationalisationService } from "../../services/internationalisation/internationalisation.service"; + +@Component({ + selector: 'save-calc', + templateUrl: "./save-calculator.component.html" +}) +export class SaveCalculatorComponent { + private _calculators: any[]; + + // services + private intlService: InternationalisationService; + + constructor() { + this.intlService = ServiceFactory.instance.internationalisationService; + } + + private get uitextDialogTitle() { + return "Enregister les calculettes"; + } + + private get uitextCloseDialogYes() { + return this.intlService.localizeText("INFO_OPTION_YES"); + } + + private get uitextCloseDialogNo() { + return this.intlService.localizeText("INFO_OPTION_NO"); + } + + private get uitextSelectAll() { + return "Toutes"; + } + + private get uitextDeselectAll() { + return "Aucune"; + } + + public set list(calc: any[]) { + this._calculators = calc; + } + + private isSelected(c: any) { + return c.selected ? "checked" : undefined; + } + + private onCheckCalc(event: any) { + for (const c of this._calculators) + if (c.uid == +event.target.value) + c.selected = event.target.checked; + } + + private selectAll() { + for (const c of this._calculators) + c.selected = true; + } + + private deselectAll() { + for (const c of this._calculators) + c.selected = false; + } + + private confirmSave() { + console.log("---"); + for (const c of this._calculators) + if (c.selected) + console.log(c.title); + } +} diff --git a/src/app/services/formulaire/formulaire.service.ts b/src/app/services/formulaire/formulaire.service.ts index 50e6ec6f7..cfd900310 100644 --- a/src/app/services/formulaire/formulaire.service.ts +++ b/src/app/services/formulaire/formulaire.service.ts @@ -327,4 +327,11 @@ export class FormulaireService extends Observable { return false; } + + public saveForm(f: FormulaireDefinition) { + this.notifyObservers({ + "action": "saveForm", + "form": f + }); + } } -- GitLab From e7ac088e9dd68681dfcaa2eceaec3ce8a3d83d0a Mon Sep 17 00:00:00 2001 From: "francois.grand" <francois.grand@irstea.fr> Date: Tue, 15 May 2018 15:13:11 +0200 Subject: [PATCH 03/20] =?UTF-8?q?=20#45=20le=20composant=20de=20sauvegarde?= =?UTF-8?q?=20des=20calculettes=20(SaveCalculatorComponent)=20renvoie=20un?= =?UTF-8?q?e=20Promise=20pour=20g=C3=A9rer=20la=20confirmation/annulation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/app.component.ts | 19 ++++++- .../save-calculator.component.html | 2 +- .../save-calculator.component.ts | 50 +++++++++++++++---- 3 files changed, 60 insertions(+), 11 deletions(-) diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 74ec9f1ca..66d453fb4 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -192,9 +192,15 @@ export class AppComponent implements OnInit, OnDestroy, Observer { this._calculators[formIndex]["title"] = title; } + /** + * sauvegarde du/des formulaires + * @param form formulaire à sélectionner par défaut dans la liste + */ private saveForm(form: FormulaireDefinition) { + // création du dialogue de sélection des formulaires à sauver const compRef: ComponentRef<SaveCalculatorComponent> = this.saveCalcDialogAnchor.createDialog(); + // création de la liste des formulaires let list = []; for (const c of this._calculators) { const uid = +c["uid"]; @@ -205,7 +211,18 @@ export class AppComponent implements OnInit, OnDestroy, Observer { }) } - compRef.instance.list = list; + // passage de la liste, récupération d'une Promise pour traiter le résultat + const prom: Promise<any[]> = compRef.instance.run(list); + prom.then(list => { + this.doSaveForm(list) + }); + } + + private doSaveForm(calcList: any[]) { + console.log("---"); + for (const c of calcList) + if (c.selected) + console.log(c.title); } private closeCalculator(form: FormulaireDefinition) { diff --git a/src/app/components/save-calculator/save-calculator.component.html b/src/app/components/save-calculator/save-calculator.component.html index 1cc9083f7..3ead22063 100644 --- a/src/app/components/save-calculator/save-calculator.component.html +++ b/src/app/components/save-calculator/save-calculator.component.html @@ -12,7 +12,7 @@ <button type="button" class="btn btn-mdb-color waves-light" (click)="deselectAll()" mdbRippleRadius>{{uitextDeselectAll}}</button> </div> <div class="modal-footer"> - <button type="button" class="btn btn-danger relative waves-light" (click)="saveDialog.hide()" mdbRippleRadius>{{uitextCloseDialogNo}}</button> + <button type="button" class="btn btn-danger relative waves-light" (click)="saveDialog.hide();cancelSave()" mdbRippleRadius>{{uitextCloseDialogNo}}</button> <button type="button" class="btn btn-success waves-light" aria-label="Close " (click)="saveDialog.hide();confirmSave()" mdbRippleRadius>{{uitextCloseDialogYes}}</button> </div> </div> diff --git a/src/app/components/save-calculator/save-calculator.component.ts b/src/app/components/save-calculator/save-calculator.component.ts index 865054a33..99babe24c 100644 --- a/src/app/components/save-calculator/save-calculator.component.ts +++ b/src/app/components/save-calculator/save-calculator.component.ts @@ -1,4 +1,4 @@ -import { Component } from "@angular/core"; +import { Component, EventEmitter } from "@angular/core"; import { ServiceFactory } from "../../services/service-factory"; import { InternationalisationService } from "../../services/internationalisation/internationalisation.service"; @@ -9,6 +9,12 @@ import { InternationalisationService } from "../../services/internationalisation export class SaveCalculatorComponent { private _calculators: any[]; + /** + * événement émis lors du clic sur "annuler"/"enregister" + * utilisé par la promise de gestion de la confirmation/annulation de la sauvegarde + */ + private confirmResult = new EventEmitter(); + // services private intlService: InternationalisationService; @@ -21,11 +27,13 @@ export class SaveCalculatorComponent { } private get uitextCloseDialogYes() { - return this.intlService.localizeText("INFO_OPTION_YES"); + //return this.intlService.localizeText("INFO_OPTION_YES"); + return "Sauver"; } private get uitextCloseDialogNo() { - return this.intlService.localizeText("INFO_OPTION_NO"); + // return this.intlService.localizeText("INFO_OPTION_NO"); + return "Annuler"; } private get uitextSelectAll() { @@ -36,8 +44,19 @@ export class SaveCalculatorComponent { return "Aucune"; } - public set list(calc: any[]) { - this._calculators = calc; + public run(calcList: any[]): Promise<any[]> { + this._calculators = calcList; + + // promise de gestion de la confirmation/annulation de la sauvegarde + return new Promise((resolve, reject) => { + this.confirmResult.subscribe((confirm) => { + if (confirm) { + resolve(this._calculators); + } else { + reject(); + } + }); + }); } private isSelected(c: any) { @@ -60,10 +79,23 @@ export class SaveCalculatorComponent { c.selected = false; } + private set confirmed(b: boolean) { + setTimeout(() => { + this.confirmResult.next(b); + }, 0); + } + + /** + * appelé quand on clique sur annuler + */ + private cancelSave() { + this.confirmed = false; + } + + /** + * appelé quand on clique sur sauver + */ private confirmSave() { - console.log("---"); - for (const c of this._calculators) - if (c.selected) - console.log(c.title); + this.confirmed = true; } } -- GitLab From 8b4d781ed47dfcac664e8203fe248898c3907126 Mon Sep 17 00:00:00 2001 From: "francois.grand" <francois.grand@irstea.fr> Date: Tue, 15 May 2018 15:41:22 +0200 Subject: [PATCH 04/20] =?UTF-8?q?=20#45=20mise=20en=20place=20du=20m=C3=A9?= =?UTF-8?q?canisme=20de=20s=C3=A9rialisation=20JSON=20des=20formulaires?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/app.component.ts | 5 ++++- src/app/formulaire/formulaire-node.ts | 14 ++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 66d453fb4..6e6a75c47 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -221,8 +221,11 @@ export class AppComponent implements OnInit, OnDestroy, Observer { private doSaveForm(calcList: any[]) { console.log("---"); for (const c of calcList) - if (c.selected) + if (c.selected) { console.log(c.title); + const form: FormulaireDefinition = this.formulaireService.getFormulaireFromId(c.uid); + console.log(JSON.stringify(form.JSONserialise())); + } } private closeCalculator(form: FormulaireDefinition) { diff --git a/src/app/formulaire/formulaire-node.ts b/src/app/formulaire/formulaire-node.ts index 814d47c88..8493c7255 100644 --- a/src/app/formulaire/formulaire-node.ts +++ b/src/app/formulaire/formulaire-node.ts @@ -143,4 +143,18 @@ export abstract class FormulaireNode implements IObservable { notifyObservers(data: any, sender?: any) { this._observable.notifyObservers(data, sender); } + + protected toJSON(): any { + return {}; + } + + /** + * sérialisation en JSON + */ + public JSONserialise(): any { + let res = this.toJSON(); + for (const k of this._kids) + res[k.id] = k.JSONserialise(); + return res; + } } -- GitLab From 06c6e85f9597831b6f491c23728803d6d9f6966a Mon Sep 17 00:00:00 2001 From: "francois.grand" <francois.grand@irstea.fr> Date: Thu, 17 May 2018 11:21:06 +0200 Subject: [PATCH 05/20] #45 ajout du bouton "charger une session" dans le sidenav --- src/app/app.component.html | 1 + src/app/app.component.ts | 9 +++++++++ src/app/services/formulaire/formulaire.service.ts | 3 +++ 3 files changed, 13 insertions(+) diff --git a/src/app/app.component.html b/src/app/app.component.html index 17a3b0cb7..49a4e47eb 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -34,6 +34,7 @@ <!-- ATTENTION ! pas de href="#" sous peine de rechargement de la page et réinitialisation de l'appli --> <a class="closebtn" (click)="closeNav()">×</a> <a (click)="newCalc()">{{uitextSidenavNewCalc}}</a> + <a (click)="loadSession()">{{uitextSidenavLoadSession}}</a> <a (click)="params()">{{uitextSidenavParams}}</a> </div> </div> diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 6e6a75c47..da4891688 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -89,6 +89,10 @@ export class AppComponent implements OnInit, OnDestroy, Observer { return this.intlService.localizeText("INFO_SETUP_TITLE"); } + private get uitextSidenavLoadSession() { + return "Charger une session"; + } + /** * abonnement au service d'erreurs */ @@ -192,6 +196,11 @@ export class AppComponent implements OnInit, OnDestroy, Observer { this._calculators[formIndex]["title"] = title; } + private loadSession() { + this.formulaireService.loadSession(); + this.closeNav(); + } + /** * sauvegarde du/des formulaires * @param form formulaire à sélectionner par défaut dans la liste diff --git a/src/app/services/formulaire/formulaire.service.ts b/src/app/services/formulaire/formulaire.service.ts index cfd900310..681e6c405 100644 --- a/src/app/services/formulaire/formulaire.service.ts +++ b/src/app/services/formulaire/formulaire.service.ts @@ -328,6 +328,9 @@ export class FormulaireService extends Observable { return false; } + public loadSession() { + } + public saveForm(f: FormulaireDefinition) { this.notifyObservers({ "action": "saveForm", -- GitLab From e37dbbcbbc78cec40932d5f5ce60bc38e737fd0b Mon Sep 17 00:00:00 2001 From: "francois.grand" <francois.grand@irstea.fr> Date: Thu, 17 May 2018 11:26:36 +0200 Subject: [PATCH 06/20] #45 classe FieldSet : remplacement du membre _parentForm par un getter --- .../formulaire/definition/form-definition.ts | 2 +- src/app/formulaire/fieldset-template.ts | 2 +- src/app/formulaire/fieldset.ts | 20 +++++++++++-------- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/app/formulaire/definition/form-definition.ts b/src/app/formulaire/definition/form-definition.ts index 37fbddfd4..dbe234bae 100644 --- a/src/app/formulaire/definition/form-definition.ts +++ b/src/app/formulaire/definition/form-definition.ts @@ -160,7 +160,7 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs private parse_fieldset(json: {}) { const fs = this.createFieldset(this, json); - fs.parseConfig(json, { "parentForm": this }); + fs.parseConfig(json); this.afterParseFieldset(fs); } diff --git a/src/app/formulaire/fieldset-template.ts b/src/app/formulaire/fieldset-template.ts index a5d618349..ce3fcf353 100644 --- a/src/app/formulaire/fieldset-template.ts +++ b/src/app/formulaire/fieldset-template.ts @@ -46,7 +46,7 @@ export class FieldsetTemplate { public instantiateTemplate(cont: FieldsetContainer, after: number): FieldSet { const parentForm = cont.parent as FormulaireDefinition; const res = parentForm.createFieldset(cont, this._jsonConfig, { "template": this, "after": after }); - res.parseConfig(this._jsonConfig, { "parentForm": parentForm }); + res.parseConfig(this._jsonConfig); parentForm.afterParseFieldset(res); return res; } diff --git a/src/app/formulaire/fieldset.ts b/src/app/formulaire/fieldset.ts index 434cf1115..c562852e7 100644 --- a/src/app/formulaire/fieldset.ts +++ b/src/app/formulaire/fieldset.ts @@ -15,11 +15,6 @@ import { FieldsetContainer } from "./fieldset-container"; import { FormulaireNode } from "./formulaire-node"; export class FieldSet extends FormulaireElement implements Observer { - /** - * formulaire parent - */ - private _parentForm: FormulaireDefinition; - /** * SessionNub associé */ @@ -45,6 +40,16 @@ export class FieldSet extends FormulaireElement implements Observer { this._props = new Props(); } + /** + * formulaire parent + */ + private get parentForm(): FormulaireDefinition { + let res = this.parent; + while (!(res instanceof FormulaireDefinition)) + res = res.parent; + return res as FormulaireDefinition; + + } public get sessionNub(): SessionNub { return this._sessionNub; } @@ -279,17 +284,16 @@ export class FieldSet extends FormulaireElement implements Observer { // fin MAJ selects - this.applyDependencies(this._parentForm); + this.applyDependencies(this.parentForm); } public parseConfig(json: {}, data?: {}) { this._jsonConfig = json; - this._parentForm = data["parentForm"]; this._confId = json["id"]; const ct: string = json["calcType"]; - const calc_type: CalculatorType = ct == undefined ? this._parentForm.calculatorType : CalculatorType[ct]; + const calc_type: CalculatorType = ct == undefined ? this.parentForm.calculatorType : CalculatorType[ct]; this.setPropValue("calcType", calc_type); const nt: string = json["nodeType"]; -- GitLab From 7c27a891c483cad1f2917694d5ffb6d9ba10380d Mon Sep 17 00:00:00 2001 From: "francois.grand" <francois.grand@irstea.fr> Date: Fri, 18 May 2018 10:08:14 +0200 Subject: [PATCH 07/20] =?UTF-8?q?=20#45=20correction=20d'un=20bug=20de=20I?= =?UTF-8?q?nternationalisationService.translateLabel()=20dans=20le=20cas?= =?UTF-8?q?=20d'un=20label=20ne=20repr=C3=A9sentant=20pas=20un=20code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../internationalisation.service.ts | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/app/services/internationalisation/internationalisation.service.ts b/src/app/services/internationalisation/internationalisation.service.ts index f418a8899..d5e3486b8 100644 --- a/src/app/services/internationalisation/internationalisation.service.ts +++ b/src/app/services/internationalisation/internationalisation.service.ts @@ -192,24 +192,27 @@ export class InternationalisationService extends Observable { default: const match = this.parseLabel(o); - if (match) + if (match) { if (match[1] === "ouvrage") res = this.localizeText("INFO_OUVRAGE") + " n°" + (+match[2] + 1); - const p = match[3]; - switch (p) { - case "Q": - res += " : " + this.localizeText("INFO_GRANDEUR_" + p); - break; + const p = match[3]; + switch (p) { + case "Q": + res += " : " + this.localizeText("INFO_GRANDEUR_" + p); + break; - case "Q_Mode": - res += " : " + this.localizeText("INFO_TYPE_ECOULEMENT"); - break; + case "Q_Mode": + res += " : " + this.localizeText("INFO_TYPE_ECOULEMENT"); + break; - case "Q_Regime": - res += " : " + this.localizeText("INFO_REGIME"); - break; + case "Q_Regime": + res += " : " + this.localizeText("INFO_REGIME"); + break; + } } + else + res = o; break; } } -- GitLab From 8d8339c33d68b6badd36c01550177bcc94b18569 Mon Sep 17 00:00:00 2001 From: "francois.grand" <francois.grand@irstea.fr> Date: Fri, 18 May 2018 16:16:48 +0200 Subject: [PATCH 08/20] =?UTF-8?q?=20#45=20cr=C3=A9ation=20d'un=20composant?= =?UTF-8?q?=20dialogue=20de=20chargement=20des=20calculettes=20(LoadCalcul?= =?UTF-8?q?atorComponent)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/app.component.html | 3 + src/app/app.component.ts | 5 + src/app/app.module.ts | 5 +- .../load-calculator-anchor.directive.ts | 27 ++++ .../load-calculator.component.html | 22 ++++ .../load-calculator.component.ts | 118 ++++++++++++++++++ 6 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 src/app/components/load-calculator/load-calculator-anchor.directive.ts create mode 100644 src/app/components/load-calculator/load-calculator.component.html create mode 100644 src/app/components/load-calculator/load-calculator.component.ts diff --git a/src/app/app.component.html b/src/app/app.component.html index 49a4e47eb..53236b7a7 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -40,6 +40,9 @@ </div> </div> + <!-- chargement des calculettes --> + <div loadCalcDialogAnchor></div> + <!-- sauvegarde des calculettes --> <div saveCalcDialogAnchor></div> diff --git a/src/app/app.component.ts b/src/app/app.component.ts index da4891688..45ef4aefc 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -16,6 +16,8 @@ import { ApplicationSetupService } from './services/app-setup/app-setup.service' import { HttpService } from './services/http/http.service'; import { HelpService } from './services/help/help.service'; import { HelpComponent } from './components/help/help.component'; +import { LoadCalcDialogAnchorDirective } from './components/load-calculator/load-calculator-anchor.directive'; +import { LoadCalculatorComponent } from './components/load-calculator/load-calculator.component'; import { SaveCalcDialogAnchorDirective } from './components/save-calculator/save-calculator-anchor.directive'; import { SaveCalculatorComponent } from './components/save-calculator/save-calculator.component'; @@ -36,6 +38,9 @@ export class AppComponent implements OnInit, OnDestroy, Observer { */ private _currentFormId: number; + @ViewChild(LoadCalcDialogAnchorDirective) + private loadCalcDialogAnchor: LoadCalcDialogAnchorDirective; + @ViewChild(SaveCalcDialogAnchorDirective) private saveCalcDialogAnchor: SaveCalcDialogAnchorDirective; diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 3c42eccb6..e084fe592 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -49,6 +49,8 @@ import { VerticalResultElementComponent } from './components/result-element/vert import { LogEntryComponent } from './components/log-entry/log-entry.component'; import { HelpService } from './services/help/help.service'; import { HelpComponent } from './components/help/help.component'; +import { LoadCalculatorComponent } from './components/load-calculator/load-calculator.component'; +import { LoadCalcDialogAnchorDirective } from './components/load-calculator/load-calculator-anchor.directive'; import { SaveCalculatorComponent } from './components/save-calculator/save-calculator.component'; import { SaveCalcDialogAnchorDirective } from './components/save-calculator/save-calculator-anchor.directive'; @@ -97,10 +99,11 @@ const appRoutes: Routes = [ HorizontalResultElementComponent, VerticalResultElementComponent, FixedResultsComponent, VarResultsComponent, HelpComponent, + LoadCalculatorComponent, LoadCalcDialogAnchorDirective, SaveCalculatorComponent, SaveCalcDialogAnchorDirective ], // entryComponents: [AlertDialog], - entryComponents: [SaveCalculatorComponent], + entryComponents: [LoadCalculatorComponent, SaveCalculatorComponent], providers: [ // services ParamService, InternationalisationService, HttpService, FormulaireService, ApplicationSetupService, HelpService ], diff --git a/src/app/components/load-calculator/load-calculator-anchor.directive.ts b/src/app/components/load-calculator/load-calculator-anchor.directive.ts new file mode 100644 index 000000000..f270813f1 --- /dev/null +++ b/src/app/components/load-calculator/load-calculator-anchor.directive.ts @@ -0,0 +1,27 @@ +import { Directive, ComponentFactoryResolver, ComponentFactory, ComponentRef } from '@angular/core'; + +import { ViewContainerRef } from '@angular/core'; +import { LoadCalculatorComponent } from './load-calculator.component'; + +@Directive({ + selector: '[loadCalcDialogAnchor]' +}) +export class LoadCalcDialogAnchorDirective { + constructor( + private viewContainer: ViewContainerRef, + private componentFactoryResolver: ComponentFactoryResolver + ) { } + + public createDialog(): ComponentRef<LoadCalculatorComponent> { + this.viewContainer.clear(); + + let compFactory: ComponentFactory<LoadCalculatorComponent> = this.componentFactoryResolver.resolveComponentFactory(LoadCalculatorComponent); + let compRef: ComponentRef<LoadCalculatorComponent> = this.viewContainer.createComponent(compFactory); + + // compRef.instance.confirmResult.subscribe(() => { + // compRef.destroy(); + // }); + + return compRef; + } +} diff --git a/src/app/components/load-calculator/load-calculator.component.html b/src/app/components/load-calculator/load-calculator.component.html new file mode 100644 index 000000000..d6ee5866c --- /dev/null +++ b/src/app/components/load-calculator/load-calculator.component.html @@ -0,0 +1,22 @@ +<div mdbModal #loadDialog="mdb-modal" class="modal fade" tabindex="-1" role="dialog" aria-hidden="true" [config]="{backdrop: false, ignoreBackdropClick: true,show:true}"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title w-100" id="myModalLabel">{{uitextDialogTitle}}</h4> + </div> + <div class="modal-body"> + <div> + <input type="file" #fileSelector multiple="false" accept="*.json" (change)="onFileSelect()"> + </div> + <div *ngFor="let c of _calculators"> + <input type="checkbox" value={{c.uid}} checked={{isSelected(c)}} (change)="onCheckCalc($event)">{{c.title}} + </div> + <button *ngIf="showSelectButtons" type="button" class="btn btn-mdb-color waves-light" (click)="selectAll()" mdbRippleRadius>{{uitextSelectAll}}</button> + <button *ngIf="showSelectButtons" type="button" class="btn btn-mdb-color waves-light" (click)="deselectAll()" mdbRippleRadius>{{uitextDeselectAll}}</button> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-danger relative waves-light" (click)="loadDialog.hide();cancelLoad()" mdbRippleRadius>{{uitextCancel}}</button> + </div> + </div> + </div> +</div> \ No newline at end of file diff --git a/src/app/components/load-calculator/load-calculator.component.ts b/src/app/components/load-calculator/load-calculator.component.ts new file mode 100644 index 000000000..f07ecb22a --- /dev/null +++ b/src/app/components/load-calculator/load-calculator.component.ts @@ -0,0 +1,118 @@ +import { Component, EventEmitter, ViewChild } from "@angular/core"; + +import { ServiceFactory } from "../../services/service-factory"; +import { InternationalisationService } from "../../services/internationalisation/internationalisation.service"; + +@Component({ + selector: 'load-calc', + templateUrl: "./load-calculator.component.html" +}) +export class LoadCalculatorComponent { + @ViewChild('fileSelector') fileSelector; + + private _selectFile: File; + + private _calculators: any[]; + + /** + * événement émis lors du clic sur "annuler"/"charger" + * utilisé par la promise de gestion de la confirmation/annulation de la sauvegarde + */ + private _confirmResult = new EventEmitter(); + + // services + private intlService: InternationalisationService; + + constructor() { + this.intlService = ServiceFactory.instance.internationalisationService; + } + + private get uitextDialogTitle() { + return "Charger des calculettes"; + } + + private get uitextCancel() { + // return this.intlService.localizeText("INFO_OPTION_NO"); + return "Annuler"; + } + + private get uitextSelectAll() { + return "Toutes"; + } + + private get uitextDeselectAll() { + return "Aucune"; + } + + public run(): Promise<any[]> { + // promise de gestion de la confirmation/annulation de la sauvegarde + return new Promise((resolve, reject) => { + this._confirmResult.subscribe((confirm) => { + if (confirm) { + resolve(this._calculators); + } else { + reject(); + } + }); + }); + } + + private get showSelectButtons(): boolean { + return this._calculators && this._calculators.length != 0; + } + + private onFileSelect() { + const files: { [key: string]: File } = this.fileSelector.nativeElement.files; + for (let key in files) { + if (!isNaN(parseInt(key))) { + this._selectFile = files[key]; + this.confirmLoad(); + break; + } + } + } + + public get selectedFile(): File { + return this._selectFile; + } + + private isSelected(c: any) { + return c.selected ? "checked" : undefined; + } + + private onCheckCalc(event: any) { + for (const c of this._calculators) + if (c.uid == +event.target.value) + c.selected = event.target.checked; + } + + private selectAll() { + for (const c of this._calculators) + c.selected = true; + } + + private deselectAll() { + for (const c of this._calculators) + c.selected = false; + } + + private set confirmed(b: boolean) { + setTimeout(() => { + this._confirmResult.next(b); + }, 0); + } + + /** + * appelé quand on clique sur annuler + */ + private cancelLoad() { + this.confirmed = false; + } + + /** + * appelé quand on clique sur sauver + */ + private confirmLoad() { + this.confirmed = true; + } +} -- GitLab From 7b3f6531083be0fb4cec86c1ff995b628116372d Mon Sep 17 00:00:00 2001 From: "francois.grand" <francois.grand@irstea.fr> Date: Fri, 18 May 2018 16:30:33 +0200 Subject: [PATCH 09/20] =?UTF-8?q?=20#45=20impl=C3=A9mentation=20de=20la=20?= =?UTF-8?q?(d=C3=A9)s=C3=A9rialisation=20du=20formulaire?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/app.component.ts | 11 ++- .../formulaire/definition/form-definition.ts | 66 +++++++++++++++++ src/app/formulaire/fieldset-container.ts | 57 ++++++++++++++ src/app/formulaire/fieldset.ts | 66 +++++++++++++++++ src/app/formulaire/formulaire-node.ts | 14 ++-- src/app/formulaire/ngparam.ts | 74 +++++++++++++++++++ src/app/formulaire/select-entry.ts | 10 +++ src/app/formulaire/select-field.ts | 35 +++++++++ .../services/formulaire/formulaire.service.ts | 34 +++++++++ 9 files changed, 356 insertions(+), 11 deletions(-) diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 45ef4aefc..9cd3266d5 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -228,18 +228,21 @@ export class AppComponent implements OnInit, OnDestroy, Observer { // passage de la liste, récupération d'une Promise pour traiter le résultat const prom: Promise<any[]> = compRef.instance.run(list); prom.then(list => { - this.doSaveForm(list) + this.saveSession(list) }); } - private doSaveForm(calcList: any[]) { - console.log("---"); + private saveSession(calcList: any[]) { + let elems = []; for (const c of calcList) if (c.selected) { console.log(c.title); const form: FormulaireDefinition = this.formulaireService.getFormulaireFromId(c.uid); - console.log(JSON.stringify(form.JSONserialise())); + elems.push(form.JSONserialise()); } + let session = { "session": { "elements": elems } }; + console.log("---"); + console.log(JSON.stringify(session)); } private closeCalculator(form: FormulaireDefinition) { diff --git a/src/app/formulaire/definition/form-definition.ts b/src/app/formulaire/definition/form-definition.ts index dbe234bae..c596e5f4e 100644 --- a/src/app/formulaire/definition/form-definition.ts +++ b/src/app/formulaire/definition/form-definition.ts @@ -435,6 +435,72 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs return new TopFormulaireElementIterator(this); } + /** + * sérialisation en JSON + */ + public JSONserialise(): {} { + let res = {}; + res["id"] = this.calculatorName; + res["props"] = this._currentSessionNub.properties.props; + res["elements"] = this.serialiseKids(); + return { "form": res }; + } + + private deserialiseFieldset(elements: {}): FieldSet { + const res: FieldSet = this.getFormulaireNodeById(elements["id"]) as FieldSet; + res.deserialiseJSON(elements); + return res; + } + + private deserialiseFieldsetContainer(elements: {}): FieldsetContainer { + const res: FieldsetContainer = this.getFormulaireNodeById(elements["id"]) as FieldsetContainer; + res.deserialiseJSON(elements); + return res; + } + + private deserialiseElement(element: {}) { + const keys = Object.keys(element); + if (keys.length !== 1) + throw new Error(`session file : invalid form object '${element}'`); + + switch (keys[0]) { + case "fieldset": + this.deserialiseFieldset(element[keys[0]]); + break; + + case "fieldset_container": + this.deserialiseFieldsetContainer(element[keys[0]]); + break; + + default: + throw new Error(`session file : invalid key '${keys[0]}' in form object`); + } + } + + /** + * désérialisation depuis JSON + */ + public deserialiseJSON(elements: {}) { + for (const k in elements) { + switch (k) { + case "id": + this._calculatorName = elements[k]; + break; + + case "props": + break; + + case "elements": + for (const e of elements[k]) + this.deserialiseElement(e); + break; + + default: + throw new Error(`session file : invalid key '${k}' in form object`); + } + } + } + // interface Observer public update(sender: any, data: any) { diff --git a/src/app/formulaire/fieldset-container.ts b/src/app/formulaire/fieldset-container.ts index a354d2a7d..64aaee77a 100644 --- a/src/app/formulaire/fieldset-container.ts +++ b/src/app/formulaire/fieldset-container.ts @@ -105,4 +105,61 @@ export class FieldsetContainer extends FormulaireElement { super.updateLocalisation(loc); } + + /** + * sérialisation en JSON + */ + public JSONserialise(): {} { + let res = {}; + res["id"] = this.id; + res["elements"] = this.serialiseKids(); + return { "fieldset_container": res }; + } + + private deserialiseFieldset(elements: {}): FieldSet { + const ind = this.getTemplateIndex(elements["id"]); + const res: FieldSet = this.addFromTemplate(ind); + const props = elements["props"]; + for (const k in props) + if (k !== "calcType" && k !== "nodeType") + res.setPropValue(k, props[k]); + res.deserialiseJSON(elements); + return res; + } + + private deserialiseElement(element: {}) { + const keys = Object.keys(element); + if (keys.length !== 1) + throw new Error(`session file : invalid fieldset object '${element}'`); + + switch (keys[0]) { + case "fieldset": + this.deserialiseFieldset(element[keys[0]]); + break; + + default: + throw new Error(`session file : invalid key '${keys[0]}' in fieldset object`); + } + } + + /** + * désérialisation depuis JSON + */ + public deserialiseJSON(elements: {}) { + for (const k in elements) { + switch (k) { + case "id": + this._confId = elements[k]; + break; + + case "elements": + for (const e of elements[k]) + this.deserialiseElement(e); + break; + + default: + throw new Error(`session file : invalid key '${k}' in form object`); + } + } + } } diff --git a/src/app/formulaire/fieldset.ts b/src/app/formulaire/fieldset.ts index c562852e7..967d8388b 100644 --- a/src/app/formulaire/fieldset.ts +++ b/src/app/formulaire/fieldset.ts @@ -402,4 +402,70 @@ export class FieldSet extends FormulaireElement implements Observer { break; } } + + /** + * sérialisation en JSON + */ + public JSONserialise(): {} { + let res = {}; + res["id"] = this.id; + res["props"] = this._props.props; + res["elements"] = this.serialiseKids(); + return { "fieldset": res }; + } + + private deserialiseParam(elements: {}): NgParameter { + const res: NgParameter = this.getFormulaireNodeById(elements["id"]) as NgParameter; + res.deserialiseJSON(elements); + return res; + } + + private deserialiseSelect(elements: {}): SelectField { + const res: SelectField = this.getFormulaireNodeById(elements["id"]) as SelectField; + res.deserialiseJSON(elements); + return res; + } + + private deserialiseElement(element: {}) { + const keys = Object.keys(element); + if (keys.length !== 1) + throw new Error(`session file : invalid fieldset object '${element}'`); + + switch (keys[0]) { + case "param": + this.deserialiseParam(element[keys[0]]); + break; + + case "select": + this.deserialiseSelect(element[keys[0]]); + break; + + default: + throw new Error(`session file : invalid key '${keys[0]}' in fieldset object`); + } + } + + /** + * désérialisation depuis JSON + */ + public deserialiseJSON(elements: {}) { + for (const k in elements) { + switch (k) { + case "id": + break; + + case "props": + this._props = new Props(elements[k]); + break; + + case "elements": + for (const e of elements[k]) + this.deserialiseElement(e); + break; + + default: + throw new Error(`session file : invalid key '${k}' in form object`); + } + } + } } diff --git a/src/app/formulaire/formulaire-node.ts b/src/app/formulaire/formulaire-node.ts index 8493c7255..aca8ea0c1 100644 --- a/src/app/formulaire/formulaire-node.ts +++ b/src/app/formulaire/formulaire-node.ts @@ -144,17 +144,17 @@ export abstract class FormulaireNode implements IObservable { this._observable.notifyObservers(data, sender); } - protected toJSON(): any { - return {}; + protected serialiseKids() { + const elems = []; + for (const k of this.kids) + elems.push(k.JSONserialise()); + return elems; } /** * sérialisation en JSON */ - public JSONserialise(): any { - let res = this.toJSON(); - for (const k of this._kids) - res[k.id] = k.JSONserialise(); - return res; + public JSONserialise(): {} { + return {}; } } diff --git a/src/app/formulaire/ngparam.ts b/src/app/formulaire/ngparam.ts index 671730429..552594bc4 100644 --- a/src/app/formulaire/ngparam.ts +++ b/src/app/formulaire/ngparam.ts @@ -320,4 +320,78 @@ export class NgParameter extends InputField { super.updateLocalisation(loc, key); } } + + private paramValuesJSON(): any { + let res = {}; + res["mode"] = ParamValueMode[this._paramValues.valueMode]; + switch (this._paramValues.valueMode) { + case ParamValueMode.SINGLE: + res["value"] = this._paramValues.singleValue; + break; + + case ParamValueMode.MINMAX: + res["min"] = this._paramValues.min; + res["max"] = this._paramValues.max; + res["step"] = this._paramValues.step; + break; + + case ParamValueMode.LISTE: + res["values"] = this._paramValues.valueList; + break; + } + return res; + } + + /** + * sérialisation en JSON + */ + public JSONserialise(): {} { + let res = {}; + res["id"] = this.id; + res["values"] = this.paramValuesJSON(); + return { "param": res }; + } + + private deserialiseValues(json: {}) { + const m: ParamValueMode = (<any>ParamValueMode)[json["mode"]]; + switch (m) { + case ParamValueMode.SINGLE: + this._paramValues.setValues(+json["value"]); + break; + + case ParamValueMode.MINMAX: + this._paramValues.setValues(+json["min"], +json["max"], +json["step"]); + break; + + case ParamValueMode.LISTE: + this._paramValues.setValues(json["values"]); + break; + + case ParamValueMode.CALCUL: + this._paramValues.valueMode = ParamValueMode.CALCUL; + break; + + default: + throw new Error(`session file : invalid value mode '${json["mode"]}' in param object`); + } + } + + /** + * désérialisation depuis JSON + */ + public deserialiseJSON(elements: {}) { + for (const k in elements) { + switch (k) { + case "id": + break; + + case "values": + this.deserialiseValues(elements[k]); + break; + + default: + throw new Error(`session file : invalid key '${k}' in param object`); + } + } + } } diff --git a/src/app/formulaire/select-entry.ts b/src/app/formulaire/select-entry.ts index 8da49428e..dc552ff9f 100644 --- a/src/app/formulaire/select-entry.ts +++ b/src/app/formulaire/select-entry.ts @@ -27,4 +27,14 @@ export class SelectEntry { get value(): any { return this._value; } + + /** + * sérialisation en JSON + */ + public JSONserialise() { + let res = {}; + res["id"] = this.id; + res["value"] = this._value; + return res; + } } diff --git a/src/app/formulaire/select-field.ts b/src/app/formulaire/select-field.ts index d6366564c..916fee39c 100644 --- a/src/app/formulaire/select-field.ts +++ b/src/app/formulaire/select-field.ts @@ -117,4 +117,39 @@ export class SelectField extends Field { this.addEntry(e); } } + + /** + * sérialisation en JSON + */ + public JSONserialise(): {} { + let res = {}; + res["id"] = this.id; + res["selected_id"] = this._selectedEntry.id; + return { "select": res }; + } + + /** + * désérialisation depuis JSON + */ + public deserialiseJSON(elements: {}) { + for (const k in elements) { + switch (k) { + case "id": + this._confId = elements[k]; + break; + + case "selected_id": + const sel = elements[k]; + for (const e of this._entries) + if (e.id === sel) { + this._selectedEntry = e; + break; + } + break; + + default: + throw new Error(`session file : invalid key '${k}' in select object`); + } + } + } } diff --git a/src/app/services/formulaire/formulaire.service.ts b/src/app/services/formulaire/formulaire.service.ts index 681e6c405..194b0cb09 100644 --- a/src/app/services/formulaire/formulaire.service.ts +++ b/src/app/services/formulaire/formulaire.service.ts @@ -337,4 +337,38 @@ export class FormulaireService extends Observable { "form": f }); } + + private deserialiseForm(elements: {}) { + const props = elements["props"]; + const ct: CalculatorType = props["calcType"]; + this.createFormulaire(ct, elements); + } + + private deserialiseSessionElement(element: {}) { + const keys = Object.keys(element); + if (keys.length !== 1) + throw new Error(`session file : invalid session object '${element}'`); + + switch (keys[0]) { + case "form": + this.deserialiseForm(element[keys[0]]); + break; + + default: + throw new Error(`session file : invalid key '${keys[0]}' in session object`); + } + } + + private deserialiseSession(elements: {}) { + for (const ks in elements) + switch (ks) { + case "elements": + for (const e of elements[ks]) + this.deserialiseSessionElement(e); + break; + + default: + throw new Error(`session file : invalid key '${ks}' in session object`); + } + } } -- GitLab From 7d86fb31b8d845e189eb302b53f0e3a14efe1bd3 Mon Sep 17 00:00:00 2001 From: "francois.grand" <francois.grand@irstea.fr> Date: Fri, 18 May 2018 16:39:05 +0200 Subject: [PATCH 10/20] =?UTF-8?q?=20#45=20impl=C3=A9mentation=20du=20charg?= =?UTF-8?q?ement=20de=20la=20session?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/app.component.ts | 18 ++++-- src/app/formulaire/fieldset-container.ts | 14 ++++- .../services/formulaire/formulaire.service.ts | 58 ++++++++++++++++++- 3 files changed, 81 insertions(+), 9 deletions(-) diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 9cd3266d5..a1024c868 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -201,11 +201,6 @@ export class AppComponent implements OnInit, OnDestroy, Observer { this._calculators[formIndex]["title"] = title; } - private loadSession() { - this.formulaireService.loadSession(); - this.closeNav(); - } - /** * sauvegarde du/des formulaires * @param form formulaire à sélectionner par défaut dans la liste @@ -336,6 +331,19 @@ export class AppComponent implements OnInit, OnDestroy, Observer { this.toList(); } + private loadSession() { + this.closeNav(); + + // création du dialogue de sélection des formulaires à sauver + const compRef: ComponentRef<LoadCalculatorComponent> = this.loadCalcDialogAnchor.createDialog(); + + const prom: Promise<any[]> = compRef.instance.run(); + prom.then(list => { + this.formulaireService.loadSession(compRef.instance.selectedFile); + compRef.destroy(); + }); + } + private params() { this.closeNav(); this.router.navigate(['/setup']); diff --git a/src/app/formulaire/fieldset-container.ts b/src/app/formulaire/fieldset-container.ts index 64aaee77a..1f384a140 100644 --- a/src/app/formulaire/fieldset-container.ts +++ b/src/app/formulaire/fieldset-container.ts @@ -28,6 +28,16 @@ export class FieldsetContainer extends FormulaireElement { return this._templates[index]; } + private getTemplateIndex(id: string): number { + let i = 0; + for (const t of this._templates) { + if (t.config["id"] == id) + return i; + i++; + } + throw new Error(`template ${id} non trouvé`); + } + public addFieldset(fs: FieldSet) { this.fieldsets.push(fs); } @@ -68,7 +78,7 @@ export class FieldsetContainer extends FormulaireElement { * @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) { + public addFromTemplate(templateIndex: number, after?: number): FieldSet { const templ: FieldsetTemplate = this._templates[templateIndex]; const inst: FieldSet = templ.instantiateTemplate(this, after); @@ -80,6 +90,8 @@ export class FieldsetContainer extends FormulaireElement { "action": "newFieldset", "fieldset": inst }, this); + + return inst; } public get fieldsets(): FieldSet[] { diff --git a/src/app/services/formulaire/formulaire.service.ts b/src/app/services/formulaire/formulaire.service.ts index 194b0cb09..c08bb630e 100644 --- a/src/app/services/formulaire/formulaire.service.ts +++ b/src/app/services/formulaire/formulaire.service.ts @@ -146,7 +146,7 @@ export class FormulaireService extends Observable { return this._httpService.httpGetRequest(undefined, undefined, undefined, f, processData); } - public createFormulaire(ct: CalculatorType): Promise<FormulaireDefinition> { + private newFormulaire(ct: CalculatorType, jsonState?: {}): FormulaireDefinition { let f: FormulaireDefinition; switch (ct) { case CalculatorType.ConduiteDistributrice: @@ -185,10 +185,31 @@ export class FormulaireService extends Observable { throw new Error(`FormulaireService.createFormulaire() : type de calculette ${ct} non pris en charge`) } - f.calculatorName = decode(this.getLocalisedTitleFromCalculatorType(ct) + " (" + f.uid + ")"); + if (jsonState !== undefined) { + const props = jsonState["props"]; + f.initSessionNub(props); + } + else + f.initSessionNub(); + + return f; + } + + /** + * crée un formulaire d'un type donné + * @param ct type de formulaire + * @param jsonState + */ + public createFormulaire(ct: CalculatorType, jsonState?: {}): Promise<FormulaireDefinition> { + const f: FormulaireDefinition = this.newFormulaire(ct, jsonState); + + if (jsonState === undefined) + f.calculatorName = decode(this.getLocalisedTitleFromCalculatorType(ct) + " (" + f.uid + ")"); this._formulaires.push(f); let prom: Promise<Response> = this.loadConfig(f, ct); return prom.then(_ => { + if (jsonState !== undefined) + f.deserialiseJSON(jsonState); return f; }).then(f => { this.loadUpdateFormulaireLocalisation(f); @@ -328,7 +349,38 @@ export class FormulaireService extends Observable { return false; } - public loadSession() { + private readSingleFile(file: File): Promise<any> { + return new Promise<any>((resolve, reject) => { + var fr = new FileReader(); + + fr.onload = () => { + resolve(fr.result); + }; + + fr.onerror = () => { + fr.abort(); + reject(new Error(`Erreur de lecture du fichier ${file.name}`)); + }; + + fr.readAsText(file); + }); + } + + public loadSession(f: File) { + this.readSingleFile(f).then(s => { + const session = JSON.parse(s); + for (const k in session) + switch (k) { + case "session": + this.deserialiseSession(session[k]); + break; + + default: + throw new Error(`session file : invalid key '${k}'`); + } + }).catch(err => { + throw err; + }); } public saveForm(f: FormulaireDefinition) { -- GitLab From de9dc0b633589b893e28d1712c988469c7dc183a Mon Sep 17 00:00:00 2001 From: "francois.grand" <francois.grand@irstea.fr> Date: Fri, 18 May 2018 16:40:47 +0200 Subject: [PATCH 11/20] =?UTF-8?q?=20#45=20=C3=A0=20l'ouverture=20de=20la?= =?UTF-8?q?=20calculette=20"ouvrages=20parall=C3=A8les",=20un=20nouvel=20o?= =?UTF-8?q?uvrage=20est=20cr=C3=A9=C3=A9=20automatiquement.=20L'impl=C3=A9?= =?UTF-8?q?mentation=20a=20=C3=A9t=C3=A9=20modifi=C3=A9e=20de=20fa=C3=A7on?= =?UTF-8?q?=20=C3=A0=20ne=20pas=20le=20faire=20dans=20le=20cas=20du=20char?= =?UTF-8?q?gement=20d'une=20session?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../calculator-list/calculator-list.component.ts | 11 +++++++++++ .../fieldset-container.component.ts | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/app/components/calculator-list/calculator-list.component.ts b/src/app/components/calculator-list/calculator-list.component.ts index 91b239baa..1a14c08d0 100644 --- a/src/app/components/calculator-list/calculator-list.component.ts +++ b/src/app/components/calculator-list/calculator-list.component.ts @@ -6,6 +6,8 @@ import { CalculatorType, EnumEx } from "jalhyd"; import { FormulaireDefinition } from "../../formulaire/definition/form-definition"; import { ServiceFactory } from "../../services/service-factory"; import { InternationalisationService } from '../../services/internationalisation/internationalisation.service'; +import { FormulaireParallelStructure } from "../../formulaire/definition/concrete/form-parallel-structures"; +import { FieldsetContainer } from "../../formulaire/fieldset-container"; class ListElement { private _label: string; @@ -41,6 +43,15 @@ export class CalculatorListComponent implements OnInit { const p: Promise<FormulaireDefinition> = ServiceFactory.instance.formulaireService.createFormulaire(t); p.then(f => { this.router.navigate(['/calculator', f.uid]); + return f; + }).then(f => { + // on ajoute un ouvrage après l'ouverture de la calculette "ouvrages parallèles" + if (f instanceof FormulaireParallelStructure) + for (const e of f.allFormElements) + if (e instanceof FieldsetContainer) { + e.addFromTemplate(0); + break; + } }); } diff --git a/src/app/components/fieldset-container/fieldset-container.component.ts b/src/app/components/fieldset-container/fieldset-container.component.ts index baa3ce418..240f408b9 100644 --- a/src/app/components/fieldset-container/fieldset-container.component.ts +++ b/src/app/components/fieldset-container/fieldset-container.component.ts @@ -73,8 +73,8 @@ export class FieldsetContainerComponent implements DoCheck, AfterViewInit { } public ngAfterViewInit() { + this.onFielsetListChange(); this._fieldsetComponents.changes.subscribe(_ => this.onFielsetListChange()); - this.addStructure(); } /* -- GitLab From e05aaa0594c56955c46297807a36d6ba83c56d30 Mon Sep 17 00:00:00 2001 From: "francois.grand" <francois.grand@irstea.fr> Date: Fri, 18 May 2018 16:48:07 +0200 Subject: [PATCH 12/20] =?UTF-8?q?=20#45=20fichier=20de=20conf=20des=20calc?= =?UTF-8?q?ulettes=20:=20suppression=20du=20champ=20"defaultNodeType"=20da?= =?UTF-8?q?ns=20les=20fieldsets=20-=20FormulaireDefinition=20:=20remplacem?= =?UTF-8?q?ent=20du=20membre=20=5FcalcType=20par=20des=20propri=C3=A9t?= =?UTF-8?q?=C3=A9s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../regime-uniforme.config.json | 4 --- src/app/calculators/remous/remous.config.json | 4 --- .../section-param/section-param.config.json | 4 --- .../definition/concrete/form-cond-distri.ts | 6 ++++- .../definition/concrete/form-courbe-remous.ts | 6 ++++- .../concrete/form-lechapt-calmon.ts | 6 ++++- .../concrete/form-parallel-structures.ts | 11 ++++++-- .../concrete/form-passe-bassin-dim.ts | 6 ++++- .../concrete/form-passe-bassin-puissance.ts | 6 ++++- .../concrete/form-regime-uniforme.ts | 6 ++++- .../concrete/form-section-parametree.ts | 6 ++++- .../formulaire/definition/form-definition.ts | 25 ++++++++++--------- src/app/formulaire/fieldset.ts | 15 +++-------- 13 files changed, 60 insertions(+), 45 deletions(-) diff --git a/src/app/calculators/regime-uniforme/regime-uniforme.config.json b/src/app/calculators/regime-uniforme/regime-uniforme.config.json index 5710ce3e1..7286a71d8 100644 --- a/src/app/calculators/regime-uniforme/regime-uniforme.config.json +++ b/src/app/calculators/regime-uniforme/regime-uniforme.config.json @@ -2,7 +2,6 @@ { "id": "fs_section", "type": "fieldset", - "defaultNodeType": "SectionTrapeze", "option": "cal", "fields": [ { @@ -104,7 +103,6 @@ { "id": "fs_bief", "type": "fieldset", - "defaultNodeType": "SectionTrapeze", "option": "cal", "fields": [ { @@ -127,7 +125,6 @@ { "id": "fs_hydraulique", "type": "fieldset", - "defaultNodeType": "SectionTrapeze", "option": "cal", "fields": [ { @@ -145,7 +142,6 @@ { "id": "fs_param_calc", "type": "fieldset", - "defaultNodeType": "SectionTrapeze", "option": "fix", "fields": [ { diff --git a/src/app/calculators/remous/remous.config.json b/src/app/calculators/remous/remous.config.json index f530722a3..289a274e1 100644 --- a/src/app/calculators/remous/remous.config.json +++ b/src/app/calculators/remous/remous.config.json @@ -2,7 +2,6 @@ { "id": "fs_section", "type": "fieldset", - "defaultNodeType": "SectionTrapeze", "option": "fix", "fields": [ { @@ -104,7 +103,6 @@ { "id": "fs_bief", "type": "fieldset", - "defaultNodeType": "SectionTrapeze", "option": "fix", "fields": [ { @@ -132,7 +130,6 @@ { "id": "fs_condlim", "type": "fieldset", - "defaultNodeType": "SectionTrapeze", "option": "fix", "fields": [ { @@ -155,7 +152,6 @@ { "id": "fs_param_calc", "type": "fieldset", - "defaultNodeType": "SectionTrapeze", "option": "fix", "fields": [ { diff --git a/src/app/calculators/section-param/section-param.config.json b/src/app/calculators/section-param/section-param.config.json index 88aac4d94..56ea1dd3c 100644 --- a/src/app/calculators/section-param/section-param.config.json +++ b/src/app/calculators/section-param/section-param.config.json @@ -2,7 +2,6 @@ { "id": "fs_section", "type": "fieldset", - "defaultNodeType": "SectionTrapeze", "option": "var", "fields": [ { @@ -104,7 +103,6 @@ { "id": "fs_bief", "type": "fieldset", - "defaultNodeType": "SectionTrapeze", "option": "var", "fields": [ { @@ -127,7 +125,6 @@ { "id": "fs_hydraulique", "type": "fieldset", - "defaultNodeType": "SectionTrapeze", "option": "var", "fields": [ { @@ -145,7 +142,6 @@ { "id": "fs_param_calc", "type": "fieldset", - "defaultNodeType": "SectionTrapeze", "option": "fix", "fields": [ { diff --git a/src/app/formulaire/definition/concrete/form-cond-distri.ts b/src/app/formulaire/definition/concrete/form-cond-distri.ts index b79c5d50c..c9e70be83 100644 --- a/src/app/formulaire/definition/concrete/form-cond-distri.ts +++ b/src/app/formulaire/definition/concrete/form-cond-distri.ts @@ -16,13 +16,17 @@ export class FormulaireConduiteDistributrice extends FormulaireDefinition { private _formResult: FormResultFixedVar; constructor() { - super(CalculatorType.ConduiteDistributrice); + super(); this._formFixedVar = new FormDefFixedVar(this); this._formParamCalc = new FormDefParamToCalculate(this); this._formResult = new FormResultFixedVar(this, false); this._formCompute = new FormComputeFixedVar(this, this._formResult); } + protected get defaultProperties(): {} { + return { "calcType": CalculatorType.ConduiteDistributrice, "nodeType": ComputeNodeType.None }; + } + protected initParse() { this._formParamCalc.initParse(); } diff --git a/src/app/formulaire/definition/concrete/form-courbe-remous.ts b/src/app/formulaire/definition/concrete/form-courbe-remous.ts index 0f60d8a59..d67e9bf24 100644 --- a/src/app/formulaire/definition/concrete/form-courbe-remous.ts +++ b/src/app/formulaire/definition/concrete/form-courbe-remous.ts @@ -21,12 +21,16 @@ export class FormulaireCourbeRemous extends FormulaireDefinition { private _resolveMethSelectId: string; constructor() { - super(CalculatorType.CourbeRemous) + super(); this._formSection = new FormDefSection(this); this._formResult = new FormResultRemous(this); this._formCompute = new FormComputeCourbeRemous(this, this._formSection, this._formResult); } + protected get defaultProperties(): {} { + return { "calcType": CalculatorType.CourbeRemous, "nodeType": ComputeNodeType.SectionPuissance }; + } + protected parseOptions(json: {}) { this._formSection.parseOptions(json); diff --git a/src/app/formulaire/definition/concrete/form-lechapt-calmon.ts b/src/app/formulaire/definition/concrete/form-lechapt-calmon.ts index baf385278..96d6fad59 100644 --- a/src/app/formulaire/definition/concrete/form-lechapt-calmon.ts +++ b/src/app/formulaire/definition/concrete/form-lechapt-calmon.ts @@ -18,13 +18,17 @@ export class FormulaireLechaptCalmon extends FormulaireDefinition implements Obs private _formResult: FormResultFixedVar; constructor() { - super(CalculatorType.LechaptCalmon) + super(); this._formFixedVar = new FormDefFixedVar(this); this._formParamCalc = new FormDefParamToCalculate(this); this._formResult = new FormResultFixedVar(this, false); this._formCompute = new FormComputeFixedVar(this, this._formResult); } + protected get defaultProperties(): {} { + return { "calcType": CalculatorType.LechaptCalmon, "nodeType": ComputeNodeType.None }; + } + protected initParse() { this._formParamCalc.initParse(); } diff --git a/src/app/formulaire/definition/concrete/form-parallel-structures.ts b/src/app/formulaire/definition/concrete/form-parallel-structures.ts index 66838edba..d06971f41 100644 --- a/src/app/formulaire/definition/concrete/form-parallel-structures.ts +++ b/src/app/formulaire/definition/concrete/form-parallel-structures.ts @@ -1,4 +1,4 @@ -import { CalculatorType, ComputeNodeType, Structure, ParallelStructure, SessionNub } from "jalhyd"; +import { CalculatorType, ComputeNodeType, Structure, ParallelStructure, SessionNub, StructureType, LoiDebit } from "jalhyd"; import { FormulaireDefinition } from "../form-definition"; import { CalculatorResults } from "../../../results/calculator-results"; @@ -33,7 +33,7 @@ export class FormulaireParallelStructure extends FormulaireDefinition { private __ouvrageSelectId: string; constructor() { - super(CalculatorType.ParallelStructure) + super(); this._formFixedVar = new FormDefFixedVar(this); this._formParamCalc = new FormDefParamToCalculate(this); this._formResult = new FormResultFixedVar(this, false); @@ -41,6 +41,13 @@ export class FormulaireParallelStructure extends FormulaireDefinition { this._formCompute = new FormComputeParallelStructures(this, this._formParallelStruct, this._formResult); } + protected get defaultProperties(): {} { + return { + "calcType": CalculatorType.ParallelStructure, "nodeType": ComputeNodeType.None, + "structureType": StructureType.SeuilRectangulaire, "loiDebit": LoiDebit.Cem88v + }; + } + private createStructNub(templ: FieldsetTemplate): SessionNub { const paramService: ParamService = ServiceFactory.instance.paramService; diff --git a/src/app/formulaire/definition/concrete/form-passe-bassin-dim.ts b/src/app/formulaire/definition/concrete/form-passe-bassin-dim.ts index bc8d202d1..64a5141cd 100644 --- a/src/app/formulaire/definition/concrete/form-passe-bassin-dim.ts +++ b/src/app/formulaire/definition/concrete/form-passe-bassin-dim.ts @@ -17,13 +17,17 @@ export class FormulairePasseBassinDimensions extends FormulaireDefinition { private _formResult: FormResultFixedVar; constructor() { - super(CalculatorType.PabDimensions); + super(); this._formFixedVar = new FormDefFixedVar(this); this._formParamCalc = new FormDefParamToCalculate(this); this._formResult = new FormResultFixedVar(this, false); this._formCompute = new FormComputeFixedVar(this, this._formResult); } + protected get defaultProperties(): {} { + return { "calcType": CalculatorType.PabDimensions, "nodeType": ComputeNodeType.None }; + } + protected initParse() { this._formParamCalc.initParse(); } diff --git a/src/app/formulaire/definition/concrete/form-passe-bassin-puissance.ts b/src/app/formulaire/definition/concrete/form-passe-bassin-puissance.ts index 02ed7376a..31d2a8639 100644 --- a/src/app/formulaire/definition/concrete/form-passe-bassin-puissance.ts +++ b/src/app/formulaire/definition/concrete/form-passe-bassin-puissance.ts @@ -17,13 +17,17 @@ export class FormulairePasseBassinPuissance extends FormulaireDefinition { private _formResult: FormResultFixedVar; constructor() { - super(CalculatorType.PabPuissance); + super(); this._formFixedVar = new FormDefFixedVar(this); this._formParamCalc = new FormDefParamToCalculate(this); this._formResult = new FormResultFixedVar(this, false); this._formCompute = new FormComputeFixedVar(this, this._formResult); } + protected get defaultProperties(): {} { + return { "calcType": CalculatorType.PabPuissance, "nodeType": ComputeNodeType.None }; + } + protected initParse() { this._formParamCalc.initParse(); } diff --git a/src/app/formulaire/definition/concrete/form-regime-uniforme.ts b/src/app/formulaire/definition/concrete/form-regime-uniforme.ts index b4f322431..50e7aeff7 100644 --- a/src/app/formulaire/definition/concrete/form-regime-uniforme.ts +++ b/src/app/formulaire/definition/concrete/form-regime-uniforme.ts @@ -20,7 +20,7 @@ export class FormulaireRegimeUniforme extends FormulaireDefinition implements Ob private _formResult: FormResultFixedVar; constructor() { - super(CalculatorType.RegimeUniforme) + super(); this._formFixedVar = new FormDefFixedVar(this); this._formParamCalc = new FormDefParamToCalculate(this); this._formSection = new FormDefSection(this); @@ -28,6 +28,10 @@ export class FormulaireRegimeUniforme extends FormulaireDefinition implements Ob this._formCompute = new FormComputeFixedVar(this, this._formResult); } + protected get defaultProperties(): {} { + return { "calcType": CalculatorType.RegimeUniforme, "nodeType": ComputeNodeType.SectionCercle }; + } + protected initParse() { this._formParamCalc.initParse(); } diff --git a/src/app/formulaire/definition/concrete/form-section-parametree.ts b/src/app/formulaire/definition/concrete/form-section-parametree.ts index 63f636138..1f14c0f66 100644 --- a/src/app/formulaire/definition/concrete/form-section-parametree.ts +++ b/src/app/formulaire/definition/concrete/form-section-parametree.ts @@ -22,13 +22,17 @@ export class FormulaireSectionParametree extends FormulaireDefinition { private _formSectionResult: FormResultSection; constructor() { - super(CalculatorType.SectionParametree); + super(); this._formFixedVar = new FormDefFixedVar(this); this._formSection = new FormDefSection(this); this._formSectionResult = new FormResultSection(this, this._formSection); this._formCompute = new FormComputeSectionParametree(this, this._formSection, this._formSectionResult); } + protected get defaultProperties(): {} { + return { "calcType": CalculatorType.SectionParametree, "nodeType": ComputeNodeType.SectionCercle }; + } + protected parseOptions(json: {}) { this._formSection.parseOptions(json); } diff --git a/src/app/formulaire/definition/form-definition.ts b/src/app/formulaire/definition/form-definition.ts index c596e5f4e..7d577b03d 100644 --- a/src/app/formulaire/definition/form-definition.ts +++ b/src/app/formulaire/definition/form-definition.ts @@ -20,11 +20,6 @@ import { FieldsetTemplate } from "../fieldset-template"; * classe de base pour tous les formulaires */ export abstract class FormulaireDefinition extends FormulaireNode implements Observer { - /** - * type de calculette - */ - private _calcType: CalculatorType; - /** * nom de la calculette */ @@ -47,15 +42,19 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs protected _paramService: ParamService; - constructor(calcType: CalculatorType) { + constructor() { super(undefined); - this._calcType = calcType; this._paramService = ServiceFactory.instance.paramService; - this.initSessionNub(); } public get calculatorType(): CalculatorType { - return this._calcType; + const props = this._currentSessionNub === undefined ? this.defaultProperties : this._currentSessionNub.properties.props; + return props["calcType"]; + } + + public get nodeType(): ComputeNodeType { + const props = this._currentSessionNub === undefined ? this.defaultProperties : this._currentSessionNub.properties.props; + return props["nodeType"]; } public get calculatorName() { @@ -70,15 +69,17 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs return this._jsonConfig; } - protected initSessionNub() { - this._currentSessionNub = this.createSessionNub({ "calcType": this._calcType, "nodeType": ComputeNodeType.None }); + protected abstract get defaultProperties(): {}; + + public initSessionNub(props?: {}) { + this._currentSessionNub = this.createSessionNub(props === undefined ? this.defaultProperties : props); } public get currentSessionNub(): SessionNub { return this._currentSessionNub; } - protected findNub(params: Props | {}) { + private findNub(params: Props | {}) { return this._paramService.findSessionNub(params); } diff --git a/src/app/formulaire/fieldset.ts b/src/app/formulaire/fieldset.ts index 967d8388b..1a35a58bb 100644 --- a/src/app/formulaire/fieldset.ts +++ b/src/app/formulaire/fieldset.ts @@ -112,7 +112,7 @@ export class FieldSet extends FormulaireElement implements Observer { return this._props; } - public getPropValue(key: string): any { + private getPropValue(key: string): any { return this._props.getPropValue(key); } @@ -296,18 +296,9 @@ export class FieldSet extends FormulaireElement implements Observer { const calc_type: CalculatorType = ct == undefined ? this.parentForm.calculatorType : CalculatorType[ct]; this.setPropValue("calcType", calc_type); - const nt: string = json["nodeType"]; - const node_type: ComputeNodeType = nt == undefined ? ComputeNodeType.None : ComputeNodeType[nt]; - const dnt: string = json["defaultNodeType"]; - const default_node_type: ComputeNodeType = dnt == undefined ? ComputeNodeType.None : ComputeNodeType[dnt]; - - if (nt !== undefined && dnt !== undefined) - throw new Error("les champs 'nodeType' et 'defaultNodeType' ne doivent pas être définis en même temps") - - const ntype = dnt !== undefined ? default_node_type : node_type; - - this.setPropValue("nodeType", ntype); + const node_type: ComputeNodeType = dnt == undefined ? this.parentForm.nodeType : ComputeNodeType[dnt]; + this.setPropValue("nodeType", node_type); const st: string = json["defaultStructType"]; if (st) -- GitLab From 4453d496d5edd7154f5e2b9576bcc60794a257a8 Mon Sep 17 00:00:00 2001 From: "francois.grand" <francois.grand@irstea.fr> Date: Tue, 22 May 2018 09:57:08 +0200 Subject: [PATCH 13/20] =?UTF-8?q?=20#45=20remous=20:=20correction=20d'un?= =?UTF-8?q?=20bug=20d'affichage=20quand=20il=20n'y=20a=20pas=20de=20r?= =?UTF-8?q?=C3=A9sultat=20vari=C3=A9s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/components/remous-results/remous-results.component.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/app/components/remous-results/remous-results.component.ts b/src/app/components/remous-results/remous-results.component.ts index 5f6f261c0..07bbca115 100644 --- a/src/app/components/remous-results/remous-results.component.ts +++ b/src/app/components/remous-results/remous-results.component.ts @@ -225,7 +225,8 @@ export class RemousResultsComponent { // le dernier dataset de la liste datasets est dessiné en 1er this._remousResults.update(); - this.varResultsComponent.results = this._remousResults.varResults; + if (this.varResultsComponent) + this.varResultsComponent.results = this._remousResults.varResults; const penteFond: number = this._remousResults.penteFond; -- GitLab From 7340ffad1f7f0b704a3c6dd1b80b452713f072a1 Mon Sep 17 00:00:00 2001 From: "francois.grand" <francois.grand@irstea.fr> Date: Tue, 22 May 2018 12:24:17 +0200 Subject: [PATCH 14/20] =?UTF-8?q?=20#45=20classe=20FieldSet=20:=20modif=20?= =?UTF-8?q?update()=20pour=20=C3=A9viter=20un=20crash=20quand=20la=20nouve?= =?UTF-8?q?lle=20valeur=20est=20undefined?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/formulaire/fieldset.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/app/formulaire/fieldset.ts b/src/app/formulaire/fieldset.ts index 1a35a58bb..9d89536e2 100644 --- a/src/app/formulaire/fieldset.ts +++ b/src/app/formulaire/fieldset.ts @@ -378,17 +378,17 @@ export class FieldSet extends FormulaireElement implements Observer { if (data.action) switch (data.action) { case "select": - if (data.value.id.indexOf("select_section_") != -1) // sections paramétrées + if (sender.id === "select_section") // sections paramétrées this.setPropValue("nodeType", data.value.value); - if (data.value.id.indexOf("select_ouvrage") != -1) // ouvrages parallèles + if (sender.id === "select_ouvrage") // ouvrages parallèles this.setPropValue("structureType", data.value.value); - else if (data.value.id.indexOf("select_loidebit1") != -1) // ouvrages parallèles + else if (sender.id === "select_loidebit1") // ouvrages parallèles this.setPropValue("loiDebit", data.value.value); - else if (data.value.id.indexOf("select_loidebit2") != -1) // ouvrages parallèles + else if (sender.id === "select_loidebit2") // ouvrages parallèles this.setPropValue("loiDebit", data.value.value); - else if (data.value.id.indexOf("select_resolution") != -1) // courbes de remous, méthode de résolution + else if (sender.id === "select_resolution") // courbes de remous, méthode de résolution this.setPropValue("methodeResolution", data.value.value); - else if (data.value.id.indexOf("select_target") != -1) // courbes de remous, variable à calculer + else if (sender.id === "select_target") // courbes de remous, variable à calculer this.setPropValue("varCalc", data.value.value); break; } -- GitLab From 07c584c62f4bbdb1380d06622d9be0994f0a9b43 Mon Sep 17 00:00:00 2001 From: "francois.grand" <francois.grand@irstea.fr> Date: Tue, 22 May 2018 12:26:09 +0200 Subject: [PATCH 15/20] =?UTF-8?q?=20#45=20d=C3=A9placement=20(FieldSet=20-?= =?UTF-8?q?>=20FormulaireParallelStructure)=20de=20la=20v=C3=A9rification?= =?UTF-8?q?=20de=20la=20coh=C3=A9rence=20des=20valeurs=20de=20type=20de=20?= =?UTF-8?q?structure/loi=20de=20d=C3=A9bit=20(cf.=20m=C3=A9thode=20Formula?= =?UTF-8?q?ireParallelStructure.adjustProperties())?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../concrete/form-parallel-structures.ts | 28 +++++++++++++++++-- src/app/formulaire/fieldset.ts | 17 +++-------- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/src/app/formulaire/definition/concrete/form-parallel-structures.ts b/src/app/formulaire/definition/concrete/form-parallel-structures.ts index d06971f41..358fa6e66 100644 --- a/src/app/formulaire/definition/concrete/form-parallel-structures.ts +++ b/src/app/formulaire/definition/concrete/form-parallel-structures.ts @@ -1,4 +1,4 @@ -import { CalculatorType, ComputeNodeType, Structure, ParallelStructure, SessionNub, StructureType, LoiDebit } from "jalhyd"; +import { CalculatorType, ComputeNodeType, Structure, ParallelStructure, SessionNub, StructureType, LoiDebit, StructureProperties, Props } from "jalhyd"; import { FormulaireDefinition } from "../form-definition"; import { CalculatorResults } from "../../../results/calculator-results"; @@ -199,6 +199,28 @@ export class FormulaireParallelStructure extends FormulaireDefinition { return n as FieldsetContainer; } + /** + * après une modification, détermine si les propriétés sont compatibles entre elles et les ajuste au besoin + * @param props propriétés à vérifier + * @param name nom de la propriété qui vient de changer + * @param val nouvelle valeur de la propriété + */ + private adjustProperties(props: Props, name: string, val: any) { + const res: Props = props.clone(); + + // si prop=type d'ouvrage, on prend une loi de débit compatible avec (spécifique aux ouvrages //) comme valeur par défaut + if (name === "structureType") { + if (!StructureProperties.isCompatibleValues(val, res.getPropValue("loiDebit"))) + res.setPropValue("loiDebit", StructureProperties.findCompatibleLoiDebit(val)); + } + // si prop=loi débit, on prend un type d'ouvrage compatible + else if (name === "loiDebit") + if (!StructureProperties.isCompatibleValues(res.getPropValue("structureType"), val)) + res.setPropValue("structureType", StructureProperties.findCompatibleStructure(val)); + + return res; + } + /** * abonnement en tant qu'observateur du FieldsetContainer */ @@ -236,8 +258,8 @@ export class FormulaireParallelStructure extends FormulaireDefinition { else if (sender instanceof FieldSet && data.action == "propertyChange") { switch (sender.id) { case "fs_ouvrage": - // this.replaceCurrentSessionNub(sender.properties); - const newNub = this.replaceSessionNub(sender.sessionNub, sender.properties); + const props = this.adjustProperties(sender.properties, data["name"], data["value"]); + const newNub = this.replaceSessionNub(sender.sessionNub, props); sender.setSessionNub(newNub); this.reset(); break; diff --git a/src/app/formulaire/fieldset.ts b/src/app/formulaire/fieldset.ts index 9d89536e2..fefcb06c4 100644 --- a/src/app/formulaire/fieldset.ts +++ b/src/app/formulaire/fieldset.ts @@ -1,4 +1,4 @@ -import { CalculatorType, ComputeNodeType, ParamDefinition, LoiDebit, StructureType, Props, SessionNub, StructureProperties, Observer } from "jalhyd"; +import { CalculatorType, ComputeNodeType, ParamDefinition, LoiDebit, StructureType, Props, SessionNub, Observer } from "jalhyd"; import { FormulaireElement } from "./formulaire-element"; import { Dependency } from "./dependency/dependency"; @@ -56,6 +56,7 @@ export class FieldSet extends FormulaireElement implements Observer { public setSessionNub(sn: SessionNub, update: boolean = true) { this._sessionNub = sn; + this._props.setProps(sn.properties, this); if (update) this.updateFields(); } @@ -116,18 +117,8 @@ export class FieldSet extends FormulaireElement implements Observer { return this._props.getPropValue(key); } - public setPropValue(key: string, val: any) { - if (this._props.setPropValue(key, val, this)) { - // si prop=type d'ouvrage, on prend une loi de débit compatible avec (spécifique aux ouvrages //) comme valeur par défaut - if (key === "structureType") { - if (!StructureProperties.isCompatibleValues(val, this.getPropValue("loiDebit"))) - this.setPropValue("loiDebit", StructureProperties.findCompatibleLoiDebit(val)); - } - // si prop=loi débit, on prend un type d'ouvrage compatible - else if (key === "loiDebit") - if (!StructureProperties.isCompatibleValues(this.getPropValue("structureType"), val)) - this.setPropValue("structureType", StructureProperties.findCompatibleStructure(val)); - } + public setPropValue(key: string, val: any): boolean { + return this._props.setPropValue(key, val, this); } /** -- GitLab From 08a267cee2f9f10d19590dedffa09692b333051a Mon Sep 17 00:00:00 2001 From: "francois.grand" <francois.grand@irstea.fr> Date: Wed, 23 May 2018 10:04:26 +0200 Subject: [PATCH 16/20] =?UTF-8?q?=20#45=20ouvrages=20:=20correction=20d'un?= =?UTF-8?q?=20bug=20r=C3=A9cr=C3=A9ant=20un=20Nub=20non=20n=C3=A9cessaire?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../definition/concrete/form-parallel-structures.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/app/formulaire/definition/concrete/form-parallel-structures.ts b/src/app/formulaire/definition/concrete/form-parallel-structures.ts index 358fa6e66..a9afe9717 100644 --- a/src/app/formulaire/definition/concrete/form-parallel-structures.ts +++ b/src/app/formulaire/definition/concrete/form-parallel-structures.ts @@ -69,11 +69,7 @@ export class FormulaireParallelStructure extends FormulaireDefinition { } private get parallelStructureNub(): ParallelStructure { - const params = { - "calcType": CalculatorType.ParallelStructure, - "nodeType": ComputeNodeType.None - }; - return this.getSessionNub(params).nub as ParallelStructure; + return this.currentSessionNub.nub as ParallelStructure; } public createFieldset(parent: FormulaireNode, json: {}, data?: {}): FieldSet { -- GitLab From 3a2f4683278dfea6612070017b2cb1a4f1686d48 Mon Sep 17 00:00:00 2001 From: "francois.grand" <francois.grand@irstea.fr> Date: Wed, 23 May 2018 10:23:34 +0200 Subject: [PATCH 17/20] #45 FormulaireParallelStructure.createStructNub() : modif purement formelle --- .../definition/concrete/form-parallel-structures.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/app/formulaire/definition/concrete/form-parallel-structures.ts b/src/app/formulaire/definition/concrete/form-parallel-structures.ts index a9afe9717..64b83a279 100644 --- a/src/app/formulaire/definition/concrete/form-parallel-structures.ts +++ b/src/app/formulaire/definition/concrete/form-parallel-structures.ts @@ -2,8 +2,6 @@ import { CalculatorType, ComputeNodeType, Structure, ParallelStructure, SessionN import { FormulaireDefinition } from "../form-definition"; import { CalculatorResults } from "../../../results/calculator-results"; -import { ServiceFactory } from "../../../services/service-factory"; -import { ParamService } from "../../../services/param/param.service"; import { FormDefParamToCalculate } from "../form-def-paramcalc"; import { FormDefFixedVar } from "../form-def-fixedvar"; import { FormDefParallelStructures } from "../form-def-parallel-structures"; @@ -49,14 +47,12 @@ export class FormulaireParallelStructure extends FormulaireDefinition { } private createStructNub(templ: FieldsetTemplate): SessionNub { - const paramService: ParamService = ServiceFactory.instance.paramService; - // valeurs par défaut de CalculatorType, ComputeNodeType, StructureType, LoiDebit // !!! attention !!! pour l'instant, il doit y avoir cohérence entre ces valeurs et celles du fichier de conf // cad valeur par défaut du 1er select (type d'ouvrage), du 2ème (loi de débit). // A terme, il faudrait analyser le fichier de conf (dépendances d'existence) pour déterminer automatiquement ces valeurs const params = FieldSet.makeDefaultProps(templ.calcTypeFromConfig, templ.defaultNodeTypeFromConfig); - return paramService.createSessionNub(params); + return this.createSessionNub(params); } /** -- GitLab From bfd239d44644d7075a8655132e98afdfa9778e7b Mon Sep 17 00:00:00 2001 From: "francois.grand" <francois.grand@irstea.fr> Date: Wed, 23 May 2018 16:11:50 +0200 Subject: [PATCH 18/20] =?UTF-8?q?=20#45=20modif=20composant=20LoadCalculat?= =?UTF-8?q?orComponent=20pour=20afficher=20et=20permettre=20de=20s=C3=A9le?= =?UTF-8?q?ctionner=20les=20calculettes=20trouv=C3=A9es=20dans=20le=20fich?= =?UTF-8?q?ier=20session=20-=20ajout=20du=20champ=20"uid"=20pour=20les=20"?= =?UTF-8?q?form"=20dans=20les=20fichiers=20session?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/app.component.ts | 7 ++- .../load-calculator.component.html | 2 + .../load-calculator.component.ts | 63 ++++++++++++++++--- .../save-calculator.component.ts | 6 ++ .../formulaire/definition/form-definition.ts | 2 + .../services/formulaire/formulaire.service.ts | 51 +++++++++++++-- 6 files changed, 114 insertions(+), 17 deletions(-) diff --git a/src/app/app.component.ts b/src/app/app.component.ts index a1024c868..2f6879d8a 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -30,6 +30,11 @@ import { SaveCalculatorComponent } from './components/save-calculator/save-calcu export class AppComponent implements OnInit, OnDestroy, Observer { private _displayErrorDialog: boolean = false; + /** + * liste des calculettes. Forme des objets : + * "title": nom de la calculette + * "uid": id unique du formulaire + */ private _calculators: any[] = []; /** @@ -339,7 +344,7 @@ export class AppComponent implements OnInit, OnDestroy, Observer { const prom: Promise<any[]> = compRef.instance.run(); prom.then(list => { - this.formulaireService.loadSession(compRef.instance.selectedFile); + this.formulaireService.loadSession(compRef.instance.selectedFile, compRef.instance.calculators); compRef.destroy(); }); } diff --git a/src/app/components/load-calculator/load-calculator.component.html b/src/app/components/load-calculator/load-calculator.component.html index d6ee5866c..b596cadbf 100644 --- a/src/app/components/load-calculator/load-calculator.component.html +++ b/src/app/components/load-calculator/load-calculator.component.html @@ -16,6 +16,8 @@ </div> <div class="modal-footer"> <button type="button" class="btn btn-danger relative waves-light" (click)="loadDialog.hide();cancelLoad()" mdbRippleRadius>{{uitextCancel}}</button> + <button type="button" class="btn btn-success waves-light" [disabled]="disableLoadButton" (click)="loadDialog.hide();confirmLoad()" + mdbRippleRadius>{{uitextLoad}}</button> </div> </div> </div> diff --git a/src/app/components/load-calculator/load-calculator.component.ts b/src/app/components/load-calculator/load-calculator.component.ts index f07ecb22a..c1a3f8b71 100644 --- a/src/app/components/load-calculator/load-calculator.component.ts +++ b/src/app/components/load-calculator/load-calculator.component.ts @@ -12,6 +12,11 @@ export class LoadCalculatorComponent { private _selectFile: File; + /** + * liste des calculettes affichées. Forme des objets : + * "title": nom de la calculette + * "selected": flag de sélection pour la sauvegarde + */ private _calculators: any[]; /** @@ -36,6 +41,11 @@ export class LoadCalculatorComponent { return "Annuler"; } + private get uitextLoad() { + // return this.intlService.localizeText("INFO_OPTION_NO"); + return "Charger"; + } + private get uitextSelectAll() { return "Toutes"; } @@ -44,6 +54,24 @@ export class LoadCalculatorComponent { return "Aucune"; } + /** + * calcule l'état du bouton charger + */ + private get disableLoadButton() { + // pas de fichier sélectionné -> bouton grisé + if (this._selectFile === undefined) + return true; + + // au moins une calculette sélectionnée -> dégrisé + if (this._calculators !== undefined) + for (const c of this._calculators) + if (c.selected) + return false; + + // grisé sinon + return true; + } + public run(): Promise<any[]> { // promise de gestion de la confirmation/annulation de la sauvegarde return new Promise((resolve, reject) => { @@ -61,29 +89,44 @@ export class LoadCalculatorComponent { return this._calculators && this._calculators.length != 0; } - private onFileSelect() { + private getSelectedFile(): File { const files: { [key: string]: File } = this.fileSelector.nativeElement.files; - for (let key in files) { - if (!isNaN(parseInt(key))) { - this._selectFile = files[key]; - this.confirmLoad(); - break; - } - } + for (const key in files) + if (!isNaN(parseInt(key))) + return files[key]; + return undefined; + } + + private onFileSelect() { + const formService = ServiceFactory.instance.formulaireService; + this._selectFile = this.getSelectedFile(); + if (this._selectFile !== undefined) + formService.calculatorInfosFromSessionFile(this._selectFile).then( + calcInfos => { + this._calculators = calcInfos; + for (const n of this._calculators) + n["selected"] = true; + }); } public get selectedFile(): File { return this._selectFile; } + public get calculators(): any[] { + return this._calculators; + } + private isSelected(c: any) { return c.selected ? "checked" : undefined; } private onCheckCalc(event: any) { for (const c of this._calculators) - if (c.uid == +event.target.value) + if (c.uid == +event.target.value) { c.selected = event.target.checked; + break; + } } private selectAll() { @@ -110,7 +153,7 @@ export class LoadCalculatorComponent { } /** - * appelé quand on clique sur sauver + * appelé quand on clique sur charger */ private confirmLoad() { this.confirmed = true; diff --git a/src/app/components/save-calculator/save-calculator.component.ts b/src/app/components/save-calculator/save-calculator.component.ts index 99babe24c..f00fd173e 100644 --- a/src/app/components/save-calculator/save-calculator.component.ts +++ b/src/app/components/save-calculator/save-calculator.component.ts @@ -7,6 +7,12 @@ import { InternationalisationService } from "../../services/internationalisation templateUrl: "./save-calculator.component.html" }) export class SaveCalculatorComponent { + /** + * liste des calculettes affichées. Forme des objets : + * "title": nom de la calculette + * "selected": flag de sélection pour la sauvegarde + * "uid": id unique du formulaire + */ private _calculators: any[]; /** diff --git a/src/app/formulaire/definition/form-definition.ts b/src/app/formulaire/definition/form-definition.ts index 7d577b03d..1a4340300 100644 --- a/src/app/formulaire/definition/form-definition.ts +++ b/src/app/formulaire/definition/form-definition.ts @@ -442,6 +442,7 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs public JSONserialise(): {} { let res = {}; res["id"] = this.calculatorName; + res["uid"] = this.uid; res["props"] = this._currentSessionNub.properties.props; res["elements"] = this.serialiseKids(); return { "form": res }; @@ -488,6 +489,7 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs this._calculatorName = elements[k]; break; + case "uid": case "props": break; diff --git a/src/app/services/formulaire/formulaire.service.ts b/src/app/services/formulaire/formulaire.service.ts index c08bb630e..b89e1baaa 100644 --- a/src/app/services/formulaire/formulaire.service.ts +++ b/src/app/services/formulaire/formulaire.service.ts @@ -366,13 +366,18 @@ export class FormulaireService extends Observable { }); } - public loadSession(f: File) { + /** + * charge une session en tenant compte des calculettes sélectionnées + * @param f fichier session + * @param formInfos infos sur les calculettes @see LoadCalculatorComponent._calculators + */ + public loadSession(f: File, formInfos: any[]) { this.readSingleFile(f).then(s => { const session = JSON.parse(s); for (const k in session) switch (k) { case "session": - this.deserialiseSession(session[k]); + this.deserialiseSession(session[k], formInfos); break; default: @@ -383,6 +388,36 @@ export class FormulaireService extends Observable { }); } + /** + * obtient des infos (nom, uid des calculettes) d'un fichier session + * @param f fichier session + */ + public calculatorInfosFromSessionFile(f: File): Promise<any[]> { + return this.readSingleFile(f).then(s => { + const res: any[] = []; + const session = JSON.parse(s); + + // liste des noms de calculettes + for (const k in session) + switch (k) { + case "session": + const sess = session[k]; + const elems = sess["elements"]; + for (const e of elems) + for (const k in e) + if (k === "form") { + const form = e[k]; + res.push({ "uid": form["uid"], "title": form["id"] }); + } + break; + + default: + throw new Error(`session file : invalid key '${k}'`); + } + return res; + }); + } + public saveForm(f: FormulaireDefinition) { this.notifyObservers({ "action": "saveForm", @@ -396,14 +431,18 @@ export class FormulaireService extends Observable { this.createFormulaire(ct, elements); } - private deserialiseSessionElement(element: {}) { + private deserialiseSessionElement(element: {}, formInfos: any[]) { const keys = Object.keys(element); if (keys.length !== 1) throw new Error(`session file : invalid session object '${element}'`); switch (keys[0]) { case "form": - this.deserialiseForm(element[keys[0]]); + const form = element[keys[0]]; + + for (const i of formInfos) + if (i["uid"] == form["uid"] && i["selected"]) + this.deserialiseForm(form); break; default: @@ -411,12 +450,12 @@ export class FormulaireService extends Observable { } } - private deserialiseSession(elements: {}) { + private deserialiseSession(elements: {}, formInfos: any[]) { for (const ks in elements) switch (ks) { case "elements": for (const e of elements[ks]) - this.deserialiseSessionElement(e); + this.deserialiseSessionElement(e, formInfos); break; default: -- GitLab From d9a0000bb37edaf3f5f123fcc2bc0ebf38baec84 Mon Sep 17 00:00:00 2001 From: "francois.grand" <francois.grand@irstea.fr> Date: Mon, 28 May 2018 15:50:21 +0200 Subject: [PATCH 19/20] =?UTF-8?q?=20#45=20ajout=20de=20l'=C3=A9criture=20d?= =?UTF-8?q?e=20la=20session=20dans=20un=20fichier=20(utilise=20la=20lib=20?= =?UTF-8?q?FileSaver)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 ++ src/app/app.component.ts | 3 +-- src/app/services/formulaire/formulaire.service.ts | 6 ++++++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 4f2602358..f612aaad6 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "angular-bootstrap-md": "^5.0.5", "angular2-chartjs": "^0.4.1", "core-js": "^2.4.1", + "file-saver": "^1.3.8", "he": "^1.1.1", "jalhyd": "file:../jalhyd/jalhyd-1.0.0.tgz", "ngx-md": "^3.1.1", @@ -36,6 +37,7 @@ "@angular/cli": "1.5.4", "@angular/compiler-cli": "^5.0.0", "@angular/language-service": "^5.0.0", + "@types/file-saver": "^1.3.0", "@types/jasmine": "~2.5.53", "@types/jasminewd2": "~2.0.2", "@types/node": "~6.0.60", diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 2f6879d8a..ed45462d1 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -241,8 +241,7 @@ export class AppComponent implements OnInit, OnDestroy, Observer { elems.push(form.JSONserialise()); } let session = { "session": { "elements": elems } }; - console.log("---"); - console.log(JSON.stringify(session)); + this.formulaireService.saveSession(session); } private closeCalculator(form: FormulaireDefinition) { diff --git a/src/app/services/formulaire/formulaire.service.ts b/src/app/services/formulaire/formulaire.service.ts index b89e1baaa..ccf34e328 100644 --- a/src/app/services/formulaire/formulaire.service.ts +++ b/src/app/services/formulaire/formulaire.service.ts @@ -3,6 +3,7 @@ import { Response } from "@angular/http"; import { Observable as rxObservable } from "rxjs/Observable"; import "rxjs/add/operator/toPromise"; import { decode } from "he"; +import { saveAs } from "file-saver" import { CalculatorType, EnumEx, Observable } from "jalhyd"; @@ -388,6 +389,11 @@ export class FormulaireService extends Observable { }); } + public saveSession(session: {}) { + const blob = new Blob([JSON.stringify(session)], { type: "text/plain;charset=utf-8" }); + saveAs(blob); + } + /** * obtient des infos (nom, uid des calculettes) d'un fichier session * @param f fichier session -- GitLab From 957e38eb5c94f563750d119069df4ac3d47a25d3 Mon Sep 17 00:00:00 2001 From: "francois.grand" <francois.grand@irstea.fr> Date: Mon, 28 May 2018 16:50:18 +0200 Subject: [PATCH 20/20] =?UTF-8?q?=20#45=20sauvegarde=20de=20la=20session?= =?UTF-8?q?=20:=20possibilit=C3=A9=20de=20saisir=20le=20nom=20de=20fichier?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/app.component.ts | 14 +++++++++++--- .../save-calculator/save-calculator.component.html | 14 +++++++++++++- .../save-calculator/save-calculator.component.ts | 11 +++++++++++ src/app/services/formulaire/formulaire.service.ts | 4 ++-- 4 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/app/app.component.ts b/src/app/app.component.ts index ed45462d1..95e286053 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -228,11 +228,19 @@ export class AppComponent implements OnInit, OnDestroy, Observer { // passage de la liste, récupération d'une Promise pour traiter le résultat const prom: Promise<any[]> = compRef.instance.run(list); prom.then(list => { - this.saveSession(list) + let name = compRef.instance.filename; + + // ajout extension ".json" + const re = /.+\.json/; + const match = re.exec(name.toLowerCase()); + if (match === null) + name = name + ".json"; + + this.saveSession(list, name) }); } - private saveSession(calcList: any[]) { + private saveSession(calcList: any[], filename) { let elems = []; for (const c of calcList) if (c.selected) { @@ -241,7 +249,7 @@ export class AppComponent implements OnInit, OnDestroy, Observer { elems.push(form.JSONserialise()); } let session = { "session": { "elements": elems } }; - this.formulaireService.saveSession(session); + this.formulaireService.saveSession(session, filename); } private closeCalculator(form: FormulaireDefinition) { diff --git a/src/app/components/save-calculator/save-calculator.component.html b/src/app/components/save-calculator/save-calculator.component.html index 3ead22063..cab54103e 100644 --- a/src/app/components/save-calculator/save-calculator.component.html +++ b/src/app/components/save-calculator/save-calculator.component.html @@ -5,11 +5,23 @@ <h4 class="modal-title w-100" id="myModalLabel">{{uitextDialogTitle}}</h4> </div> <div class="modal-body"> + <!-- liste de calculettes avec check --> <div *ngFor="let c of _calculators"> <input type="checkbox" value={{c.uid}} checked={{isSelected(c)}} (change)="onCheckCalc($event)">{{c.title}} </div> + + <!-- bouton "tout sélectionnner" --> <button type="button" class="btn btn-mdb-color waves-light" (click)="selectAll()" mdbRippleRadius>{{uitextSelectAll}}</button> - <button type="button" class="btn btn-mdb-color waves-light" (click)="deselectAll()" mdbRippleRadius>{{uitextDeselectAll}}</button> + + <!-- bouton "tout désélectionnner" --> + <button type="button" class="btn btn-mdb-color waves-light py-10" (click)="deselectAll()" mdbRippleRadius>{{uitextDeselectAll}}</button> + + <!-- nom du fichier --> + <div class="md-form form-sm mt-4"> + <input mdbActive type="text" id="form1" class="form-control" [(ngModel)]="_filename"> + <!-- on utilise [innerHTML] pour que les codes HTML comme soient interprétés correctement --> + <label for="form1" [innerHTML]="_filenameTitle"></label> + </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-danger relative waves-light" (click)="saveDialog.hide();cancelSave()" mdbRippleRadius>{{uitextCloseDialogNo}}</button> diff --git a/src/app/components/save-calculator/save-calculator.component.ts b/src/app/components/save-calculator/save-calculator.component.ts index f00fd173e..6e30cd2db 100644 --- a/src/app/components/save-calculator/save-calculator.component.ts +++ b/src/app/components/save-calculator/save-calculator.component.ts @@ -15,6 +15,13 @@ export class SaveCalculatorComponent { */ private _calculators: any[]; + /** + * nom du fichier + */ + private _filename: string = "session"; + + private _filenameTitle = "Nom de fichier"; + /** * événement émis lors du clic sur "annuler"/"enregister" * utilisé par la promise de gestion de la confirmation/annulation de la sauvegarde @@ -50,6 +57,10 @@ export class SaveCalculatorComponent { return "Aucune"; } + public get filename(): string { + return this._filename; + } + public run(calcList: any[]): Promise<any[]> { this._calculators = calcList; diff --git a/src/app/services/formulaire/formulaire.service.ts b/src/app/services/formulaire/formulaire.service.ts index ccf34e328..5984c3f9d 100644 --- a/src/app/services/formulaire/formulaire.service.ts +++ b/src/app/services/formulaire/formulaire.service.ts @@ -389,9 +389,9 @@ export class FormulaireService extends Observable { }); } - public saveSession(session: {}) { + public saveSession(session: {}, filename?: string) { const blob = new Blob([JSON.stringify(session)], { type: "text/plain;charset=utf-8" }); - saveAs(blob); + saveAs(blob, filename); } /** -- GitLab