From c9ec952e635c72f12ec6a5fe42b23088660dd1dc Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Thu, 13 Jun 2019 17:39:26 +0200 Subject: [PATCH] Pab: validity check --- .../calculator.component.ts | 12 +++ .../pab-table/pab-table.component.html | 4 +- .../pab-table/pab-table.component.scss | 6 ++ .../pab-table/pab-table.component.ts | 76 +++++++++++-------- src/theme.scss | 9 +++ 5 files changed, 73 insertions(+), 34 deletions(-) diff --git a/src/app/components/generic-calculator/calculator.component.ts b/src/app/components/generic-calculator/calculator.component.ts index 3b65cc69b..0392ec276 100644 --- a/src/app/components/generic-calculator/calculator.component.ts +++ b/src/app/components/generic-calculator/calculator.component.ts @@ -16,6 +16,7 @@ import { CalculatorNameComponent } from "./calc-name.component"; import { FormulaireElement } from "../../formulaire/formulaire-element"; import { FieldsetContainer } from "../../formulaire/fieldset-container"; import { FieldsetContainerComponent } from "../fieldset-container/fieldset-container.component"; +import { PabTableComponent } from "../pab-table/pab-table.component"; import { ServiceFactory } from "../../services/service-factory"; import { MatDialog } from "@angular/material"; import { DialogConfirmCloseCalcComponent } from "../dialog-confirm-close-calc/dialog-confirm-close-calc.component"; @@ -41,6 +42,12 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit, @ViewChildren(FieldsetContainerComponent) private _fieldsetContainerComponents: QueryList<FieldsetContainerComponent>; + /** + * PabTableComponent if any + */ + @ViewChild(PabTableComponent) + private _pabTableComponent: PabTableComponent; + /** * composant d'affichage des résultats */ @@ -336,6 +343,7 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit, // valeur initiale , this._fieldsetComponents.length > 0); } + if (this._fieldsetContainerComponents !== undefined) { this._isUIValid = this._isUIValid && this._fieldsetContainerComponents.reduce( // callback @@ -354,6 +362,10 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit, // valeur initiale , true); } + + if (this._pabTableComponent !== undefined) { + this._isUIValid = this._isUIValid && this._pabTableComponent.isValid; + } } public getFieldsetStyleDisplay(id: string) { diff --git a/src/app/components/pab-table/pab-table.component.html b/src/app/components/pab-table/pab-table.component.html index bdd4f919b..ea7863833 100644 --- a/src/app/components/pab-table/pab-table.component.html +++ b/src/app/components/pab-table/pab-table.component.html @@ -74,10 +74,12 @@ [ngClass]="cell.class" [class.editable-cell]="hasModel(cell)" [class.readonly-cell]="! hasModel(cell)" [class.selectable-cell]="isSelectable(cell)" [class.selected-cell]="isSelected(cell) && ! isSelected(row)" + [class.invalid-cell]="isInvalid(cell)" [attr.rowspan]="rowSpan(cell)" [attr.colspan]="colSpan(cell)" [title]="cellTitle(cell)"> - <input matInput *ngIf="isNumberInput(cell)" type="number" [(ngModel)]="cell.model.singleValue"> + <input matInput *ngIf="isNumberInput(cell)" step="0.00000000000001" type="number" + [(ngModel)]="cell.model.singleValue" (input)="inputValueChanged($event, cell)"> <mat-select *ngIf="isSelect(cell)" [value]="cell.modelValue" (selectionChange)="loiDebitSelected($event, cell)"> diff --git a/src/app/components/pab-table/pab-table.component.scss b/src/app/components/pab-table/pab-table.component.scss index d09c4cad0..d8beccf90 100644 --- a/src/app/components/pab-table/pab-table.component.scss +++ b/src/app/components/pab-table/pab-table.component.scss @@ -42,6 +42,9 @@ mat-card-content { .selected-editable-cell-bg { @extend .bg-accent-verylight; } +.invalid-cell-bg { + @extend .bg-error; +} #pab-table-toolbar { #edit-pab-table { @@ -117,6 +120,9 @@ mat-card-content { @extend .selected-editable-cell-bg; } } + &.invalid-cell { + @extend .invalid-cell-bg; + } &.basin_number { text-align: center; font-weight: bold; diff --git a/src/app/components/pab-table/pab-table.component.ts b/src/app/components/pab-table/pab-table.component.ts index 6ba74e562..ad5d0c01e 100644 --- a/src/app/components/pab-table/pab-table.component.ts +++ b/src/app/components/pab-table/pab-table.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, Output, EventEmitter, OnInit } from "@angular/core"; +import { Component, Input, Output, EventEmitter, OnInit, AfterViewInit } from "@angular/core"; import { MatDialog } from "@angular/material"; @@ -11,7 +11,7 @@ import { Nub, Structure, ParallelStructure, - LoiDebit + ParamDefinition } from "jalhyd"; import { sprintf } from "sprintf-js"; @@ -33,7 +33,7 @@ import { DialogEditPabComponent } from "../dialog-edit-pab/dialog-edit-pab.compo "./pab-table.component.scss" ] }) -export class PabTableComponent implements /* DoCheck, AfterViewInit, */ OnInit { +export class PabTableComponent implements AfterViewInit, OnInit { @Input() private pabTable: PabTable; @@ -84,6 +84,7 @@ export class PabTableComponent implements /* DoCheck, AfterViewInit, */ OnInit { return this.i18nService.localizeText("INFO_PAB_TABLE"); } + /** Global Pab validity */ public get isValid() { return this._isValid; } @@ -139,6 +140,34 @@ export class PabTableComponent implements /* DoCheck, AfterViewInit, */ OnInit { return undefined; } + /** + * Checks that input value is a valid number, according to input[type="number"] algorithm, + * and stores it in cell.uiValidity, so that the <td> element can access it and get angry + * if input is invalid + */ + public inputValueChanged($event, cell) { + // console.log("input value changed", $event.target.validity.valid, $event.target.validity); + if ($event && $event.target && $event.target.validity) { + cell.uiValidity = $event.target.validity.valid; + } + this.updateValidity(); + } + + /** + * Returns true if current cell is bound to a model that says its input value is + * no valid, or if characters typed in the input field are not a valid number + * (read from cell.uiValidity, see inputValueChanged() above) + */ + public isInvalid(cell: any): boolean { + let valid = true; + if (this.hasModel(cell) && cell.model instanceof ParamDefinition) { + valid = valid && cell.model.isValid; + } + if (cell.uiValidity !== undefined) { + valid = valid && cell.uiValidity; + } + return ! valid; + } /** returns true if the cell / row has a selectable item */ public isSelectable(cellOrRow: any): boolean { @@ -377,7 +406,6 @@ export class PabTableComponent implements /* DoCheck, AfterViewInit, */ OnInit { }); // as much rows as the greatest number of parameters among its devices const maxNbParams = this.findMaxNumberOfDeviceParameters(cloison); - // console.log(">>> max nb params: ", maxNbParams); for (let i = 0; i < maxNbParams; i++) { // build device params row const deviceParamRow = { selectable: cloison, cells: [] }; @@ -585,6 +613,8 @@ export class PabTableComponent implements /* DoCheck, AfterViewInit, */ OnInit { // done ! this.rows.push(deviceParamRowDW); } + + this.updateValidity(); } private findMaxNumberOfDevices(): number { @@ -1026,40 +1056,20 @@ export class PabTableComponent implements /* DoCheck, AfterViewInit, */ OnInit { } } - /* public ngAfterViewInit() { - this.onFieldsetListChange(); - this._fieldsetComponents.changes.subscribe(_ => this.onFieldsetListChange()); - } - - public ngDoCheck() { + public ngAfterViewInit() { this.updateValidity(); - } */ + } /** - * @TODO Calcul de la validité de la Pab + * Computes the global Pab validity : validity of every cell of every row */ private updateValidity() { - this._isValid = false; - - /* if (this._fieldsetComponents !== undefined) { - this._isValid = this._fieldsetComponents.reduce( - // callback - ( - // accumulator (valeur précédente du résultat) - acc, - // currentValue (élément courant dans le tableau) - fieldset, - // currentIndex (indice courant dans le tableau) - currIndex, - // array (tableau parcouru) - array - ) => { - return acc && fieldset.isValid; - } - // valeur initiale - , this._fieldsetComponents.length > 0); - } */ - + this._isValid = true; + for (const r of this.rows) { + for (const c of r.cells) { + this._isValid = this._isValid && ! this.isInvalid(c); + } + } this.validChange.emit(); } diff --git a/src/theme.scss b/src/theme.scss index f45053954..951487e70 100644 --- a/src/theme.scss +++ b/src/theme.scss @@ -171,6 +171,7 @@ $mat-irstea-rouille: ( $nghyd-primary: mat-palette($mat-irstea-marine); $nghyd-accent: mat-palette($mat-irstea-ocean); $nghyd-warn: mat-palette($mat-irstea-prune); +$nghyd-error: mat-palette($mat-irstea-rouille); // $nghyd-warn: mat-palette($mat-irstea-rouille); $nghyd-theme: mat-light-theme($nghyd-primary, $nghyd-accent, $nghyd-warn); @@ -181,6 +182,7 @@ $nghyd-theme: mat-light-theme($nghyd-primary, $nghyd-accent, $nghyd-warn); $primary: map-get($nghyd-theme, primary); $accent: map-get($nghyd-theme, accent); $warn: map-get($nghyd-theme, warn); +// $error: map-get($nghyd-error); // convenience classes (functions mat-* cannot be used outside of this file) @@ -241,6 +243,13 @@ $warn: map-get($nghyd-theme, warn); background-color: mat-color($warn, 50); } +.color-error { + color: mat-color($nghyd-error); +} +.bg-error { + background-color: mat-color($nghyd-error); +} + .mat-button-toggle-checked { background-color: mat-color($accent); color: mat-color($accent, default-contrast) !important; -- GitLab