From 0d8b5cac651a575f132aa7666ae0b34e2b7fdeec Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Thu, 18 Jul 2019 16:32:00 +0200 Subject: [PATCH 1/2] Fix #237 --- src/app/app.module.ts | 2 + .../calculator.component.html | 24 ++++--- .../calculator.component.scss | 6 ++ .../calculator.component.ts | 10 ++- .../pab-results-table.component.scss | 1 + .../pab-results/pab-results.component.html | 3 + .../quicknav/quicknav.component.html | 7 ++ .../quicknav/quicknav.component.scss | 67 +++++++++++++++++++ .../components/quicknav/quicknav.component.ts | 67 +++++++++++++++++++ src/locale/messages.en.json | 3 + src/locale/messages.fr.json | 3 + src/theme.scss | 12 ++++ 12 files changed, 196 insertions(+), 9 deletions(-) create mode 100644 src/app/components/quicknav/quicknav.component.html create mode 100644 src/app/components/quicknav/quicknav.component.scss create mode 100644 src/app/components/quicknav/quicknav.component.ts diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 19cc15e1e..9deea03e4 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -83,6 +83,7 @@ import { SelectModelFieldLineComponent } from "./components/select-model-field-l import { PabProfileGraphComponent } from "./components/pab-profile-graph/pab-profile-graph.component"; import { PabTableComponent } from "./components/pab-table/pab-table.component"; import { PabVariableResultsSelectorComponent } from "./components/pab-results/pab-variable-results-selector.component"; +import { QuicknavComponent } from "./components/quicknav/quicknav.component"; import { DialogConfirmEmptySessionComponent } from "./components/dialog-confirm-empty-session/dialog-confirm-empty-session.component"; import { DialogConfirmCloseCalcComponent } from "./components/dialog-confirm-close-calc/dialog-confirm-close-calc.component"; @@ -195,6 +196,7 @@ const appRoutes: Routes = [ ParamFieldLineComponent, ParamLinkComponent, ParamValuesComponent, + QuicknavComponent, RemousResultsComponent, ResultsGraphComponent, SectionCanvasComponent, diff --git a/src/app/components/generic-calculator/calculator.component.html b/src/app/components/generic-calculator/calculator.component.html index 08366714a..87c73d874 100644 --- a/src/app/components/generic-calculator/calculator.component.html +++ b/src/app/components/generic-calculator/calculator.component.html @@ -29,6 +29,8 @@ </mat-card-header> + <quicknav [fxHide.gt-sm]="! isPAB" [items]="quicknavItems" [currentItem]="'input'" [align]="'left'"></quicknav> + <form> <mat-card-content> @@ -43,7 +45,8 @@ <!-- chapitres --> <mat-card id="calc-card-field-sets" [class.pab-field-sets]="isPAB" - [fxFlex.gt-xs]="isPAB ? '1 0 auto' : '1 0 400px'" + [fxFlex.gt-sm]="isPAB ? '1 0 auto' : '1 0 400px'" + [fxFlex.lt-md]="isPAB ? '1 0 auto' : '1 0 500px'" [fxFlex.lt-sm]="isPAB ? '1 0 auto' : '1 0 300px'"> <ng-template ngFor let-fe [ngForOf]="formElements"> @@ -73,20 +76,25 @@ <!-- résultats --> <mat-card id="calc-card-results" [class.pab-results]="isPAB" - [fxFlex.gt-xs]="isPAB ? '1 0 auto' : '1 0 400px'" + [fxFlex.gt-sm]="isPAB ? '1 0 auto' : '1 0 400px'" + [fxFlex.lt-md]="isPAB ? '1 0 auto' : '1 0 500px'" [fxFlex.lt-sm]="isPAB ? '1 0 auto' : '1 0 300px'"> <div id="fake-results-anchor"></div> - <mat-card-header> + + <quicknav [ngClass.lt-xs]="'extraSmall'" [fxHide.gt-sm]="! isPAB" [items]="quicknavItems" [currentItem]="'results'" [align]="'left'"></quicknav> + + <mat-card-header *ngIf="! isPAB" [fxHide.lt-md]="! isPAB"> <mat-card-title> <h1 [innerHTML]="uitextResultsTitle"></h1> </mat-card-title> - <div fxFlex></div> - <button mat-raised-button color="accent" id="generate-pab" *ngIf="isPABCloisons" (click)="generatePAB()" - [disabled]="! generatePABEnabled" [title]="uitextGeneratePabTitle"> - {{ uitextGeneratePAB }} - </button> </mat-card-header> + + <button mat-raised-button color="accent" id="generate-pab" *ngIf="isPABCloisons" (click)="generatePAB()" + [disabled]="! generatePABEnabled" [title]="uitextGeneratePabTitle"> + {{ uitextGeneratePAB }} + </button> + <mat-card-content> <calc-results id="resultsComp" (afterViewChecked)="onCalcResultsViewChecked()"></calc-results> </mat-card-content> diff --git a/src/app/components/generic-calculator/calculator.component.scss b/src/app/components/generic-calculator/calculator.component.scss index e1e07ee87..86ee92752 100644 --- a/src/app/components/generic-calculator/calculator.component.scss +++ b/src/app/components/generic-calculator/calculator.component.scss @@ -81,4 +81,10 @@ mat-card { margin-bottom: 8px; } } + + mat-card-content { + > calc-name { + margin-top: 1.5em; + } + } } diff --git a/src/app/components/generic-calculator/calculator.component.ts b/src/app/components/generic-calculator/calculator.component.ts index faec11c44..c72a3f203 100644 --- a/src/app/components/generic-calculator/calculator.component.ts +++ b/src/app/components/generic-calculator/calculator.component.ts @@ -194,6 +194,14 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit, return this.intlService.localizeText("INFO_CALCULATOR_CLOSE"); } + public get quicknavItems() { + const elts = [ "input", "results" ]; + if (this.isPAB) { + elts.push("charts"); + } + return elts; + } + /** * Triggered at calculator instanciation */ @@ -279,7 +287,7 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit, } private scrollToResults() { - const element = document.getElementById("fake-results-anchor"); + const element = document.getElementById ("fake-results-anchor"); if (element) { element.scrollIntoView(); } diff --git a/src/app/components/pab-results/pab-results-table.component.scss b/src/app/components/pab-results/pab-results-table.component.scss index ea1d83f80..efbe2b6ea 100644 --- a/src/app/components/pab-results/pab-results-table.component.scss +++ b/src/app/components/pab-results/pab-results-table.component.scss @@ -1,5 +1,6 @@ :host { display: block; + margin-bottom: 1.5em; } .pab-results-table-container { diff --git a/src/app/components/pab-results/pab-results.component.html b/src/app/components/pab-results/pab-results.component.html index fbb8e9c23..2e31dc126 100644 --- a/src/app/components/pab-results/pab-results.component.html +++ b/src/app/components/pab-results/pab-results.component.html @@ -12,6 +12,9 @@ <pab-results-table *ngIf="hasDisplayableResults" [results]="pabResults"></pab-results-table> </div> + <quicknav *ngIf="hasDisplayableResults" [items]="[ 'input', 'results', 'charts' ]" + [currentItem]="'charts'" [align]="'left'"></quicknav> + <div id="pab-graphs-container" class="container" fxLayout="row wrap" fxLayoutAlign="space-around start"> <pab-profile-graph *ngIf="hasDisplayableResults" fxFlex.gt-xs="1 0 400px" fxFlex.lt-sm="1 0 300px"> </pab-profile-graph> diff --git a/src/app/components/quicknav/quicknav.component.html b/src/app/components/quicknav/quicknav.component.html new file mode 100644 index 000000000..31f1db00b --- /dev/null +++ b/src/app/components/quicknav/quicknav.component.html @@ -0,0 +1,7 @@ +<div class="quicknav-row" [ngStyle]="alignStyle" *ngIf="hasItems" [id]="id" + [class.autoPadLeft]="align === 'left'" [class.autoPadRight]="align === 'right'"> + + <div class="quicknav-item" *ngFor="let i of items" [class.current]="isCurrent(i)" [ngStyle]="paddingStyle"> + <a (click)="scrollTo(i)">{{ label(i) }}</a> + </div> +</div> diff --git a/src/app/components/quicknav/quicknav.component.scss b/src/app/components/quicknav/quicknav.component.scss new file mode 100644 index 000000000..62391f1ae --- /dev/null +++ b/src/app/components/quicknav/quicknav.component.scss @@ -0,0 +1,67 @@ +:host { + display: block; + margin-bottom: .5em; + width: 100%; + + &.extraSmall { + + .quicknav-item { + font-size: 12px; + + &.current { + font-size: 18px; + } + } + } +} + +@import "../../../theme.scss"; + +.quicknav-row { + width: 100%; + padding-bottom: 3px; + border-bottom: solid #dddddd 1px; +} + +.quicknav-item { + display: inline; + padding: 0 .5em 3px .5em; + text-transform: uppercase; + font-size: 18px; + font-weight: normal; + + &.current { + @extend .border-accent; + border-bottom-width: 2px; + border-bottom-style: solid; + font-size: 24px; + + a { + // font-weight: bold; + @extend .color-accent; + } + } + + a { + cursor: pointer; + color: #cbcbcb; + &:focus { + outline: none; + } + &:hover { + color: #707070; + } + } +} + +.autoPadLeft { + .quicknav-item:first-of-type { + padding-left: 0; + } +} + +.autoPadRight { + .quicknav-item:last-of-type { + padding-right: 0; + } +} diff --git a/src/app/components/quicknav/quicknav.component.ts b/src/app/components/quicknav/quicknav.component.ts new file mode 100644 index 000000000..17e442ef9 --- /dev/null +++ b/src/app/components/quicknav/quicknav.component.ts @@ -0,0 +1,67 @@ +import { Component, Input } from "@angular/core"; + +import { I18nService } from "../../services/internationalisation/internationalisation.service"; + +@Component({ + selector: "quicknav", + templateUrl: "./quicknav.component.html", + styleUrls: [ + "./quicknav.component.scss" + ] +}) +export class QuicknavComponent { + + @Input() + public items: string[]; + + @Input() + public currentItem: string; + + @Input() + public align: string; + + private prefix = "qn_"; + + public constructor( + private i18nService: I18nService + ) { + this.items = []; + this.currentItem = ""; + this.align = "center"; + } + + public get id() { + return this.prefix + this.currentItem; + } + + public get hasItems() { + return this.items.length > 0; + } + + public get alignStyle() { + return { + "text-align": this.align + }; + } + + public label(item: string = "") { + return this.i18nService.localizeText("INFO_QUICKNAV_" + item.toUpperCase()); + } + + public isCurrent(item: string) { + return item === this.currentItem; + } + + public scrollTo(item: string) { + // https://stackoverflow.com/a/56391657/5986614 + const element = document.getElementById(this.prefix + item); + if (element) { + const yCoordinate = element.getBoundingClientRect().top + window.pageYOffset; + // element.scrollIntoView({behavior: "smooth", block: "start", inline: "nearest"}); + window.scrollTo({ + top: yCoordinate - 60, // substract a little more than navbar height + behavior: "smooth" + }); + } + } +} diff --git a/src/locale/messages.en.json b/src/locale/messages.en.json index c83ba6b83..b1f8ab601 100644 --- a/src/locale/messages.en.json +++ b/src/locale/messages.en.json @@ -317,6 +317,9 @@ "INFO_PARAMFIELD_VARIATED": "Variated", "INFO_PARAMMODE_LIST": "Values list", "INFO_PARAMMODE_MINMAX": "Min/max", + "INFO_QUICKNAV_CHARTS": "charts", + "INFO_QUICKNAV_INPUT": "input", + "INFO_QUICKNAV_RESULTS": "results", "WARNING_PROBLEMS_ENCOUNTERED": "Problems occurred during calculation (info: %info%, warning: %warning%, error: %error%)", "INFO_REGIMEUNIFORME_TITRE_COURT": "Uniform flow", "INFO_REGIMEUNIFORME_TITRE": "Uniform flow calculation", diff --git a/src/locale/messages.fr.json b/src/locale/messages.fr.json index 86203c1bc..5d4dca279 100644 --- a/src/locale/messages.fr.json +++ b/src/locale/messages.fr.json @@ -317,6 +317,9 @@ "INFO_PARAMFIELD_VARIATED": "Varié", "INFO_PARAMMODE_LIST": "Liste de valeurs", "INFO_PARAMMODE_MINMAX": "Min/max", + "INFO_QUICKNAV_CHARTS": "graphiques", + "INFO_QUICKNAV_INPUT": "données", + "INFO_QUICKNAV_RESULTS": "résultats", "WARNING_PROBLEMS_ENCOUNTERED": "Des problèmes sont survenus durant le calcul (info: %info%, avertissement: %warning%, erreur: %error%)", "INFO_REGIMEUNIFORME_TITRE_COURT": "R. uniforme", "INFO_REGIMEUNIFORME_TITRE": "Régime uniforme", diff --git a/src/theme.scss b/src/theme.scss index 951487e70..982a741bb 100644 --- a/src/theme.scss +++ b/src/theme.scss @@ -204,6 +204,9 @@ $warn: map-get($nghyd-theme, warn); .bg-primary-extralight { background-color: mat-color($primary, 50); } +.border-primary { + border-color: mat-color($primary); +} .color-accent { color: mat-color($accent); @@ -223,6 +226,9 @@ $warn: map-get($nghyd-theme, warn); .bg-accent-extralight { background-color: mat-color($accent, 50); } +.border-accent { + border-color: mat-color($accent); +} .color-warn { color: mat-color($warn); @@ -242,6 +248,9 @@ $warn: map-get($nghyd-theme, warn); .bg-warn-extralight { background-color: mat-color($warn, 50); } +.border-warn { + border-color: mat-color($warn); +} .color-error { color: mat-color($nghyd-error); @@ -249,6 +258,9 @@ $warn: map-get($nghyd-theme, warn); .bg-error { background-color: mat-color($nghyd-error); } +.border-error { + border-color: mat-color($nghyd-error); +} .mat-button-toggle-checked { background-color: mat-color($accent); -- GitLab From 59b61ba6875b26f842ad150ca5e2ba1317d92894 Mon Sep 17 00:00:00 2001 From: "mathias.chouet" <mathias.chouet@irstea.fr> Date: Mon, 22 Jul 2019 12:31:12 +0200 Subject: [PATCH 2/2] Quicknav : show "charts" entry only if PAB has results --- src/app/components/generic-calculator/calculator.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/components/generic-calculator/calculator.component.ts b/src/app/components/generic-calculator/calculator.component.ts index c72a3f203..623091c90 100644 --- a/src/app/components/generic-calculator/calculator.component.ts +++ b/src/app/components/generic-calculator/calculator.component.ts @@ -196,7 +196,7 @@ export class GenericCalculatorComponent extends BaseComponent implements OnInit, public get quicknavItems() { const elts = [ "input", "results" ]; - if (this.isPAB) { + if (this.isPAB && this.hasResults) { elts.push("charts"); } return elts; -- GitLab