From c9000b0fec77312e9faff3218f4e06d01615a3e3 Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Thu, 11 Apr 2019 11:04:41 +0200 Subject: [PATCH 1/5] =?UTF-8?q?Fix=20#188=20Utiliser=20la=20touche=20TAB?= =?UTF-8?q?=20pour=20passer=20d'un=20champ=20=C3=A0=20l'autre?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../field-set/field-set.component.html | 3 +- .../field-set/field-set.component.ts | 11 ++++ .../fieldset-container.component.html | 3 +- .../fieldset-container.component.ts | 11 ++++ .../calculator.component.html | 10 +++- .../calculator.component.ts | 55 +++++++++++++++++-- .../generic-input.component.html | 1 + .../generic-input/generic-input.component.ts | 14 +++++ .../param-field-line.component.html | 3 +- .../param-field-line.component.ts | 11 ++++ 10 files changed, 112 insertions(+), 10 deletions(-) diff --git a/src/app/components/field-set/field-set.component.html b/src/app/components/field-set/field-set.component.html index b87bbe724..0dea7034b 100644 --- a/src/app/components/field-set/field-set.component.html +++ b/src/app/components/field-set/field-set.component.html @@ -20,7 +20,8 @@ <mat-card-content> <ng-template ngFor let-p [ngForOf]="fields"> - <param-field-line *ngIf="isInputField(p)" [param]=p (radio)=onRadioClick($event) (valid)=onParamLineValid() (inputChange)=onInputChange()> + <param-field-line *ngIf="isInputField(p)" [param]=p (radio)=onRadioClick($event) (valid)=onParamLineValid() + (inputChange)=onInputChange() (tabPressed)="onTabPressed($event)"> </param-field-line> <select-field-line *ngIf="isSelectField(p)" [_select]=p> diff --git a/src/app/components/field-set/field-set.component.ts b/src/app/components/field-set/field-set.component.ts index 1541cba64..bb3c51de8 100644 --- a/src/app/components/field-set/field-set.component.ts +++ b/src/app/components/field-set/field-set.component.ts @@ -117,6 +117,10 @@ export class FieldSetComponent implements DoCheck { @Output() private radio = new EventEmitter<any>(); + /** événement signalant un appui sur TAB ou SHIFT+TAB */ + @Output() + protected tabPressed = new EventEmitter<any>(); + private hasRadioFix(): boolean { if (this._fieldSet.hasInputs) { switch (this._fieldSet.getInput(0).radioConfig) { @@ -209,6 +213,13 @@ export class FieldSetComponent implements DoCheck { this.validChange.emit(); } + /** + * Renvoie l'événement au composant du dessus + */ + public onTabPressed(event) { + this.tabPressed.emit(event); + } + public ngDoCheck() { this.updateValidity(); } diff --git a/src/app/components/fieldset-container/fieldset-container.component.html b/src/app/components/fieldset-container/fieldset-container.component.html index 3bb2f5d4c..c2f75e4f1 100644 --- a/src/app/components/fieldset-container/fieldset-container.component.html +++ b/src/app/components/fieldset-container/fieldset-container.component.html @@ -8,6 +8,7 @@ <field-set *ngFor="let fs of fieldsets" class="fieldset-inner" [fieldSet]=fs (radio)=onRadioClick($event) (validChange)=onFieldsetValid() (inputChange)=onInputChange() (addFieldset)=onAddFieldset($event) (removeFieldset)=onRemoveFieldset($event) - (moveFieldsetDown)=onMoveFieldsetDown($event) (moveFieldsetUp)=onMoveFieldsetUp($event)> + (moveFieldsetDown)=onMoveFieldsetDown($event) (moveFieldsetUp)=onMoveFieldsetUp($event) + (tabPressed)="onTabPressed($event)"> </field-set> </mat-card-content> diff --git a/src/app/components/fieldset-container/fieldset-container.component.ts b/src/app/components/fieldset-container/fieldset-container.component.ts index 15ca4d3e3..b5e7be12e 100644 --- a/src/app/components/fieldset-container/fieldset-container.component.ts +++ b/src/app/components/fieldset-container/fieldset-container.component.ts @@ -60,6 +60,10 @@ export class FieldsetContainerComponent implements DoCheck, AfterViewInit { @Output() private inputChange = new EventEmitter(); + /** événement signalant un appui sur TAB ou SHIFT+TAB */ + @Output() + protected tabPressed = new EventEmitter<any>(); + private addStructure(after?: FieldSet) { if (after) { this._container.addFromTemplate(0, after.indexAsKid()); @@ -204,4 +208,11 @@ export class FieldsetContainerComponent implements DoCheck, AfterViewInit { const form = this._container.parent as FormulaireDefinition; form.moveFieldsetDown(fs); } + + /** + * Renvoie l'événement au composant du dessus + */ + public onTabPressed(event) { + this.tabPressed.emit(event); + } } diff --git a/src/app/components/generic-calculator/calculator.component.html b/src/app/components/generic-calculator/calculator.component.html index a714e0be4..27eb0116b 100644 --- a/src/app/components/generic-calculator/calculator.component.html +++ b/src/app/components/generic-calculator/calculator.component.html @@ -32,10 +32,14 @@ <!-- chapitres --> <mat-card id="calc-card-field-sets" fxFlex.gt-xs="1 0 400px" fxFlex.lt-sm="1 0 300px"> <ng-template ngFor let-fe [ngForOf]="formElements"> - <field-set *ngIf="isFieldset(fe)" [style.display]="getFieldsetStyleDisplay(fe.id)" [fieldSet]=fe (radio)=onRadioClick($event) - (validChange)=OnFieldsetValid() (inputChange)=onInputChange()></field-set> + <field-set *ngIf="isFieldset(fe)" [style.display]="getFieldsetStyleDisplay(fe.id)" [fieldSet]=fe + (radio)=onRadioClick($event) (validChange)=OnFieldsetValid() (inputChange)=onInputChange() + (tabPressed)="onTabPressed($event)"> + </field-set> - <fieldset-container *ngIf="isFieldsetContainer(fe)" [_container]=fe (radio)=onRadioClick($event) (validChange)=onFieldsetContainerValid()></fieldset-container> + <fieldset-container *ngIf="isFieldsetContainer(fe)" [_container]=fe (radio)=onRadioClick($event) + (validChange)=onFieldsetContainerValid() (tabPressed)="onTabPressed($event)"> + </fieldset-container> </ng-template> <mat-card-actions> diff --git a/src/app/components/generic-calculator/calculator.component.ts b/src/app/components/generic-calculator/calculator.component.ts index 31842b969..d7a267bb7 100644 --- a/src/app/components/generic-calculator/calculator.component.ts +++ b/src/app/components/generic-calculator/calculator.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit, DoCheck, OnDestroy, ViewChild, ViewChildren, QueryList, AfterViewChecked } from "@angular/core"; +import { Component, OnInit, DoCheck, OnDestroy, ViewChild, ViewChildren, QueryList, AfterViewChecked, ElementRef, Renderer2 } from "@angular/core"; import { ActivatedRoute, Router } from "@angular/router"; import { Observer, Session, ParamValueMode } from "jalhyd"; @@ -98,7 +98,9 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit, constructor( private route: ActivatedRoute, private router: Router, - private confirmCloseCalcDialog: MatDialog + private confirmCloseCalcDialog: MatDialog, + private _elementRef: ElementRef, + private renderer: Renderer2 ) { super(); this.intlService = ServiceFactory.instance.i18nService; @@ -308,7 +310,11 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit, // accumulator (valeur précédente du résultat) acc, // currentValue (élément courant dans le tableau) - fieldset + fieldset, + // currentIndex (indice courant dans le tableau) + currIndex, + // array (tableau parcouru) + array ) => { return acc && fieldset.isValid; } @@ -322,7 +328,11 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit, // accumulator (valeur précédente du résultat) acc, // currentValue (élément courant dans le tableau) - fieldsetContainer + fieldsetContainer, + // currentIndex (indice courant dans le tableau) + currIndex, + // array (tableau parcouru) + array ) => { return acc && fieldsetContainer.isValid; } @@ -357,6 +367,43 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit, this._formulaire.resetResults([]); } + /** + * Passe d'un champ de saisie à l'autre lors de l'appui sur + * TAB, sans passer par les autres éléments d'interface + */ + public onTabPressed(event: any) { + // event source input id + const srcId = event.originalEvent.target.id; + + // find all available inputs + const qs = "ngparam-input input.form-control"; + let inputs: Node[] = Array.from(this._elementRef.nativeElement.querySelectorAll(qs)); + + // find calculated symbol if any, to exclude it from inputs list + let calcSymbol = ""; + if (this._formulaire.currentNub.calculatedParam) { + calcSymbol = this._formulaire.currentNub.calculatedParam.symbol; + } + inputs = inputs.filter((i: any) => { + return i.id !== calcSymbol; + }); + + // find position among inputs list + const currentIndex = inputs.findIndex((i: any) => { + return i.id === srcId; + }); + + // focus previous / next input + let newIndex = currentIndex; + if (event.shift) { + newIndex = (newIndex === 0) ? (inputs.length - 1) : (newIndex - 1); + } else { + newIndex = (newIndex + 1) % inputs.length; + } + const elt = (inputs[newIndex] as HTMLElement); + elt.focus(); + } + public openHelp() { window.open("assets/docs-fr/calculators/" + this._formulaire.helpLink + "/", "_blank"); } diff --git a/src/app/components/generic-input/generic-input.component.html b/src/app/components/generic-input/generic-input.component.html index f6ca6506f..c60194a79 100644 --- a/src/app/components/generic-input/generic-input.component.html +++ b/src/app/components/generic-input/generic-input.component.html @@ -1,6 +1,7 @@ <mat-form-field> <input matInput #inputControl="ngModel" class="form-control" type="text" inputmode="numeric" [id]="inputId" [name]="inputId" [disabled]="isDisabled" [(ngModel)]="uiValue" [placeholder]="title" + (keydown.Tab)="onTabPressed($event, false)" (keydown.shift.Tab)="onTabPressed($event, true)" pattern="^-?([0-9]*\.)?([0-9]+[Ee]-?)?[0-9]+$" required> <mat-error>{{ errorMessage }}</mat-error> diff --git a/src/app/components/generic-input/generic-input.component.ts b/src/app/components/generic-input/generic-input.component.ts index 1bac27018..0b8b3f09b 100644 --- a/src/app/components/generic-input/generic-input.component.ts +++ b/src/app/components/generic-input/generic-input.component.ts @@ -59,6 +59,12 @@ export abstract class GenericInputComponent extends BaseComponent implements OnC @Output() protected change = new EventEmitter<any>(); + /** + * événement signalant un appui sur TAB ou SHIFT+TAB + */ + @Output() + protected tabPressed = new EventEmitter<any>(); + /** * valeur saisie. * Cette variable n'est modifiée que lorsqu'on affecte le modèle ou que l'utilisateur fait une saisie @@ -231,6 +237,14 @@ export abstract class GenericInputComponent extends BaseComponent implements OnC } } + /** + * Renvoie l'événement au composant du dessus + */ + public onTabPressed(event, shift: boolean) { + this.tabPressed.emit({ originalEvent: event, shift: shift }); + return false; // stops event propagation + } + private updateAll() { this.updateAndValidateUI(); this.validateModel(); diff --git a/src/app/components/param-field-line/param-field-line.component.html b/src/app/components/param-field-line/param-field-line.component.html index acea333d2..1c71eb5b9 100644 --- a/src/app/components/param-field-line/param-field-line.component.html +++ b/src/app/components/param-field-line/param-field-line.component.html @@ -4,7 +4,8 @@ <!-- input de saisie de la valeur --> <div fxFlex="1 0 120px"> <!-- composant pour gérer le cas général (valeur numérique à saisir) --> - <ngparam-input [title]="param.title" [hidden]="! isRadioFixChecked" (change)="onInputChange($event)"></ngparam-input> + <ngparam-input [title]="param.title" [hidden]="! isRadioFixChecked" + (change)="onInputChange($event)" (tabPressed)="onTabPressed($event)"></ngparam-input> <!-- composant pour gérer le cas "paramètre calculé" --> <param-computed *ngIf="isRadioCalChecked" [title]="title" [param]="param"></param-computed> diff --git a/src/app/components/param-field-line/param-field-line.component.ts b/src/app/components/param-field-line/param-field-line.component.ts index 06a78419f..59b38594a 100644 --- a/src/app/components/param-field-line/param-field-line.component.ts +++ b/src/app/components/param-field-line/param-field-line.component.ts @@ -127,6 +127,10 @@ export class ParamFieldLineComponent implements OnChanges { @Output() private inputChange: EventEmitter<void>; + /** événement signalant un appui sur TAB ou SHIFT+TAB */ + @Output() + protected tabPressed = new EventEmitter<any>(); + /** true si la valeur saisie est valide */ private _isInputValid = false; @@ -266,6 +270,13 @@ export class ParamFieldLineComponent implements OnChanges { this.emitValidity(); } + /** + * Renvoie l'événement au composant du dessus + */ + public onTabPressed(event) { + this.tabPressed.emit(event); + } + /** * émission d'un événement de validité */ -- GitLab From cdfb93668abfa08a2c0aefad6d86f55679cb2047 Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Thu, 11 Apr 2019 11:19:14 +0200 Subject: [PATCH 2/5] =?UTF-8?q?Fix=20#173=20-=20pr=C3=A9fixage=20des=20ID?= =?UTF-8?q?=20des=20input=20de=20structures=20par=20la=20position=20de=20l?= =?UTF-8?q?a=20structure?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../generic-input/generic-input.component.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/app/components/generic-input/generic-input.component.ts b/src/app/components/generic-input/generic-input.component.ts index 0b8b3f09b..e75f2ed18 100644 --- a/src/app/components/generic-input/generic-input.component.ts +++ b/src/app/components/generic-input/generic-input.component.ts @@ -1,7 +1,7 @@ import { Input, Output, EventEmitter, ChangeDetectorRef, OnChanges, ViewChild } from "@angular/core"; import { NgModel } from "@angular/forms"; import { BaseComponent } from "../base/base.component"; -import { isNumeric } from "jalhyd"; +import { isNumeric, Structure } from "jalhyd"; import { FormulaireDefinition } from "../../formulaire/definition/form-definition"; import { NgParameter } from "../../formulaire/ngparam"; import { I18nService } from "../../services/internationalisation/internationalisation.service"; @@ -37,11 +37,18 @@ export abstract class GenericInputComponent extends BaseComponent implements OnC * id de l'input, utilisé notamment pour les tests */ public get inputId() { - let id = "input-1"; + let id = "error-in-inputId"; if (this._model) { // unique input id based on parameter symbol if (this._model instanceof NgParameter) { - id = (this._model as NgParameter).symbol; + const param = this._model as NgParameter; + id = param.symbol; + // if inside a nested Structure, prefix with Structure position + // to disambiguate + const nub = param.paramDefinition.parentNub; + if (nub && nub instanceof Structure) { + id = nub.findPositionInParent() + "_" + id; + } } } return id; -- GitLab From 76d20400165519737231b06c85d9e4afe116a90f Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Thu, 11 Apr 2019 11:20:33 +0200 Subject: [PATCH 3/5] update jalhyd_branch --- jalhyd_branch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jalhyd_branch b/jalhyd_branch index 6ba102133..1f7391f92 100644 --- a/jalhyd_branch +++ b/jalhyd_branch @@ -1 +1 @@ -54-ameliorer-le-filtre-de-choix-des-parametres-pouvant-etre-lies +master -- GitLab From 7e9ebdf6367310dec0fed60012df57aa10ec859f Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Thu, 11 Apr 2019 13:44:35 +0200 Subject: [PATCH 4/5] =?UTF-8?q?Fix=20#158=20ajout=20des=20tags=20de=20vers?= =?UTF-8?q?ion=20dans=20le=20panneau=20lat=C3=A9ral?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- preprocessors.js | 9 ++++++--- src/app/app.component.html | 14 ++++++++++++-- src/app/app.component.scss | 16 ++++++++++++++++ src/app/app.component.ts | 18 +++++++++++++----- 4 files changed, 47 insertions(+), 10 deletions(-) diff --git a/preprocessors.js b/preprocessors.js index ecc995383..e95d481c3 100755 --- a/preprocessors.js +++ b/preprocessors.js @@ -7,13 +7,16 @@ var fs = require('fs'); date_last_commit = require('child_process') .execSync('git log -1 --format=%cd --date=short') .toString().trim() +version = require('child_process') + .execSync('git describe') + .toString().trim() var sFileName = "src/date_revision.ts"; -fs.writeFile(sFileName, `export const nghydDateRev = "${date_last_commit}";\n`, function(err) { +fs.writeFile(sFileName, `export const nghydDateRev = "${date_last_commit}";\nexport const nghydVersion = "${version}";\n`, function(err) { if(err) { return console.log(err); } - console.log(`File ${sFileName} saved with date ${date_last_commit}`); -}); \ No newline at end of file + console.log(`File ${sFileName} saved with date ${date_last_commit}, version ${version}`); +}); diff --git a/src/app/app.component.html b/src/app/app.component.html index 4ce195dc9..aa14cd73d 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -96,8 +96,18 @@ </a> <div class="hyd_version"> - JaLHyd version: {{ getDateRevision()[0] }}<br/> - ngHyd version: {{ getDateRevision()[1] }} + <div class="jalhyd-version"> + <span class="version"> + JaLHyd: <span class="value">{{ revisionInfo.jalhyd.version }}</span> + </span> + <span class="date">updated {{ revisionInfo.jalhyd.date }}</span> + </div> + <div class="nghyd-version"> + <span class="version"> + ngHyd: <span class="value">{{ revisionInfo.nghyd.version }}</span> + </span> + <span class="date">updated {{ revisionInfo.nghyd.date }}</span> + </div> </div> </div> </mat-sidenav> diff --git a/src/app/app.component.scss b/src/app/app.component.scss index 98e0c6c01..6cf6170ef 100644 --- a/src/app/app.component.scss +++ b/src/app/app.component.scss @@ -216,6 +216,22 @@ button:focus { color: #888888; padding: 0 2em 1em 0; text-align: right; + + .jalhyd-version { + margin-bottom: 0.6em; + } + + .version { + display: block; + + > .value { + font-weight: bold; + } + } + + .date { + font-size: 0.8em; + } } .closebtn { diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 43e8c0f2c..e61b8c3b8 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -3,7 +3,7 @@ import { Router, Event, NavigationEnd, ActivationEnd } from "@angular/router"; import { MatSidenav, MatToolbar, MatDialog, MatIconRegistry } from "@angular/material"; import { DomSanitizer } from "@angular/platform-browser"; -import { Observer, jalhydDateRev, CalculatorType, Session } from "jalhyd"; +import { Observer, jalhydDateRev, jalhydVersion, CalculatorType, Session } from "jalhyd"; import { environment } from "../environments/environment"; import { I18nService } from "./services/internationalisation/internationalisation.service"; @@ -13,7 +13,7 @@ import { FormulaireDefinition } from "./formulaire/definition/form-definition"; import { ServiceFactory } from "./services/service-factory"; import { HttpService } from "./services/http/http.service"; import { ApplicationSetupService } from "./services/app-setup/app-setup.service"; -import { nghydDateRev } from "../date_revision"; +import { nghydDateRev, nghydVersion } from "../date_revision"; import { DialogConfirmEmptySessionComponent } from "./components/dialog-confirm-empty-session/dialog-confirm-empty-session.component"; import { DialogLoadSessionComponent } from "./components/dialog-load-session/dialog-load-session.component"; @@ -407,9 +407,17 @@ export class AppComponent implements OnInit, OnDestroy, Observer { }); } - public getDateRevision(): string[] { - const dr: string[] = [jalhydDateRev, nghydDateRev]; - return dr; + public get revisionInfo(): any { + return { + jalhyd: { + date: jalhydDateRev, + version: jalhydVersion, + }, + nghyd: { + date: nghydDateRev, + version: nghydVersion + } + }; } /** -- GitLab From 21462af44a393d7540f647b223fd2653f03e185f Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Thu, 11 Apr 2019 13:55:08 +0200 Subject: [PATCH 5/5] =?UTF-8?q?Le=20bouton=20"+"=20dispara=C3=AEt=20lorsqu?= =?UTF-8?q?'on=20est=20sur=20la=20page=20d'accueil?= 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 | 4 ++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/app/app.component.html b/src/app/app.component.html index aa14cd73d..50dad1690 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -53,8 +53,7 @@ </div> <button mat-icon-button id="new-calculator" routerLink="/list" (click)="sidenav.close()"> - <mat-icon *ngIf="calculators.length > 0">add_box</mat-icon> - <mat-icon *ngIf="calculators.length === 0">home</mat-icon> + <mat-icon *ngIf="currentRoute != '/list'">add_box</mat-icon> </button> <div id="toolbar-bottom-spacer"></div> diff --git a/src/app/app.component.ts b/src/app/app.component.ts index e61b8c3b8..9f7ad4caf 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -172,6 +172,10 @@ export class AppComponent implements OnInit, OnDestroy, Observer { return this._currentFormId; } + public get currentRoute(): string { + return this.router.url; + } + public setActiveCalc(uid: string) { this._calculators.forEach((calc) => { calc.active = (calc.uid === uid); -- GitLab