diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 3dc37b5aee1e9dda60cf51ed700506360eafccf0..6c36ede63b3c31276206d3fbde2f054e8a09cdd7 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -107,6 +107,7 @@ import { DialogLoadPredefinedEspeceComponent } from "./components/dialog-load-pr import { DialogLoadSessionComponent } from "./components/dialog-load-session/dialog-load-session.component"; import { DialogLogEntriesDetailsComponent } from "./components/dialog-log-entries-details/dialog-log-entries-details.component"; import { DialogSaveSessionComponent } from "./components/dialog-save-session/dialog-save-session.component"; +import { DialogNewPbCloisonComponent } from "./components/dialog-new-pb-cloison/dialog-new-pb-cloison.component"; import { JalhydAsyncModelValidationDirective } from "./directives/jalhyd-async-model-validation.directive"; import { @@ -147,122 +148,125 @@ const appRoutes: Routes = [ } } }), - MatBadgeModule, - MatButtonModule, - MatButtonToggleModule, - MatCardModule, - MatCheckboxModule, - MatDialogModule, - MaterialFileInputModule, - MatFormFieldModule, - MatIconModule, - MatInputModule, - MatListModule, - MatMenuModule, - MatProgressBarModule, - MatRadioModule, - MatSelectModule, - MatSidenavModule, - MatSnackBarModule, - MatTableModule, - MatTabsModule, - MatToolbarModule, - MatTooltipModule, - MatomoModule, - RouterModule.forRoot( - appRoutes, - { - useHash: true, // prevents reloading whole app when typing url in browser's navigation bar - enableTracing: false // debugging purposes only - } - ), - StorageServiceModule, - TableModule, - // KonamiModule - ], - declarations: [ // composants, pipes et directives - AppComponent, - ApplicationSetupComponent, - BaseParamInputComponent, - CalcCanvasComponent, - CalculatorListComponent, - CalculatorNameComponent, - CalculatorResultsComponent, - DialogConfirmCloseCalcComponent, - DialogConfirmEmptySessionComponent, - DialogEditPabComponent, - DialogEditParamComputedComponent, - DialogEditParamValuesComponent, - DialogGeneratePABComponent, - DialogGeneratePARSimulationComponent, - DialogLoadSessionComponent, - DialogLogEntriesDetailsComponent, - DialogSaveSessionComponent, - FieldSetComponent, - FieldsetContainerComponent, - FixedResultsComponent, - FixedVarResultsComponent, - FlexGtXxsShowHideDirective, - FlexLtXsShowHideDirective, - FlexXxsShowHideDirective, - GenericCalculatorComponent, - ChartTypeSelectComponent, - JalhydAsyncModelValidationDirective, - JalhydModelValidationDirective, - JalhydModelValidationMinDirective, - JalhydModelValidationMaxDirective, - JalhydModelValidationStepDirective, - JetResultsComponent, - JetTrajectoryChartComponent, - LogComponent, - LogEntryComponent, - ModulesDiagramComponent, - NgParamInputComponent, - PabProfileChartComponent, - PabResultsComponent, - PabResultsTableComponent, - PabTableComponent, - VariableResultsSelectorComponent, - MacrorugoCompoundResultsComponent, - MacrorugoCompoundResultsTableComponent, - ParamComputedComponent, - ParamFieldLineComponent, - ParamLinkComponent, - ParamValuesComponent, - QuicknavComponent, - RemousResultsComponent, - ResultsChartComponent, - SectionCanvasComponent, - SectionResultsComponent, - SelectFieldLineComponent, - SelectModelFieldLineComponent, - SessionPropertiesComponent, - VarResultsComponent - ], - entryComponents: [ - DialogConfirmCloseCalcComponent, - DialogConfirmEmptySessionComponent, - DialogEditPabComponent, - DialogEditParamComputedComponent, - DialogEditParamValuesComponent, - DialogGeneratePABComponent, - DialogGeneratePARSimulationComponent, - DialogSaveSessionComponent, - DialogLoadSessionComponent, - DialogLogEntriesDetailsComponent - ], - providers: [ // services - ApplicationSetupService, - CustomBreakPointsProvider, - FormulaireService, - HttpService, - I18nService, - NotificationsService, - { - provide: ErrorStateMatcher, - useClass: ImmediateErrorStateMatcher - } - ], + MatBadgeModule, + MatButtonModule, + MatButtonToggleModule, + MatCardModule, + MatCheckboxModule, + MatDialogModule, + MaterialFileInputModule, + MatFormFieldModule, + MatIconModule, + MatInputModule, + MatListModule, + MatMenuModule, + MatProgressBarModule, + MatRadioModule, + MatSelectModule, + MatSidenavModule, + MatSnackBarModule, + MatTableModule, + MatTabsModule, + MatToolbarModule, + MatTooltipModule, + MatomoModule, + RouterModule.forRoot( + appRoutes, + { + useHash: true, // prevents reloading whole app when typing url in browser's navigation bar + enableTracing: false // debugging purposes only + } + ), + StorageServiceModule, + TableModule, + KonamiModule + ], + declarations: [ // composants, pipes et directives + AppComponent, + ApplicationSetupComponent, + BaseParamInputComponent, + CalcCanvasComponent, + CalculatorListComponent, + CalculatorNameComponent, + CalculatorResultsComponent, + DialogConfirmCloseCalcComponent, + DialogConfirmEmptySessionComponent, + DialogEditPabComponent, + DialogEditParamComputedComponent, + DialogEditParamValuesComponent, + DialogGeneratePABComponent, + DialogGeneratePARSimulationComponent, + DialogLoadSessionComponent, + DialogLogEntriesDetailsComponent, + DialogSaveSessionComponent, + DialogNewPbCloisonComponent, + FieldSetComponent, + FieldsetContainerComponent, + FixedResultsComponent, + FixedVarResultsComponent, + FlexGtXxsShowHideDirective, + FlexLtXsShowHideDirective, + FlexXxsShowHideDirective, + GenericCalculatorComponent, + ChartTypeSelectComponent, + JalhydAsyncModelValidationDirective, + JalhydModelValidationDirective, + JalhydModelValidationMinDirective, + JalhydModelValidationMaxDirective, + JalhydModelValidationStepDirective, + JetResultsComponent, + JetTrajectoryChartComponent, + LogComponent, + LogEntryComponent, + ModulesDiagramComponent, + NgParamInputComponent, + PabProfileChartComponent, + PabResultsComponent, + PabResultsTableComponent, + PabTableComponent, + PbSchemaComponent, + VariableResultsSelectorComponent, + MacrorugoCompoundResultsComponent, + MacrorugoCompoundResultsTableComponent, + ParamComputedComponent, + ParamFieldLineComponent, + ParamLinkComponent, + ParamValuesComponent, + QuicknavComponent, + RemousResultsComponent, + ResultsChartComponent, + SectionCanvasComponent, + SectionResultsComponent, + SelectFieldLineComponent, + SelectModelFieldLineComponent, + SessionPropertiesComponent, + VarResultsComponent + ], + entryComponents: [ + DialogConfirmCloseCalcComponent, + DialogConfirmEmptySessionComponent, + DialogEditPabComponent, + DialogEditParamComputedComponent, + DialogEditParamValuesComponent, + DialogGeneratePABComponent, + DialogGeneratePARSimulationComponent, + DialogSaveSessionComponent, + DialogNewPbCloisonComponent, + DialogLoadSessionComponent, + DialogLogEntriesDetailsComponent + ], + providers: [ // services + ApplicationSetupService, + CustomBreakPointsProvider, + FormulaireService, + HttpService, + I18nService, + NotificationsService, + { + provide: ErrorStateMatcher, + useClass: ImmediateErrorStateMatcher + } + ], schemas: [ NO_ERRORS_SCHEMA ], bootstrap: [ AppComponent ] }) diff --git a/src/app/components/dialog-new-pb-cloison/dialog-new-pb-cloison.component.html b/src/app/components/dialog-new-pb-cloison/dialog-new-pb-cloison.component.html new file mode 100644 index 0000000000000000000000000000000000000000..aa12a43084c645c56379cd303cc0083aea50721c --- /dev/null +++ b/src/app/components/dialog-new-pb-cloison/dialog-new-pb-cloison.component.html @@ -0,0 +1,28 @@ +<h1 mat-dialog-title>{{ uitextSelectBasins }}</h1> + +<form> + <mat-form-field> + <mat-select [placeholder]="uiTextUpstreambasin" [(value)]="upstreamIndex" required> + <mat-option *ngFor="let b of availableIndexes" [value]="b"> + {{ basinDescription(b, uitextRiverUpstream) }} + </mat-option> + </mat-select> + </mat-form-field> + + <mat-form-field> + <mat-select [placeholder]="uiTextDownstreambasin" [(value)]="downstreamIndex" required> + <mat-option *ngFor="let b of availableIndexes" [value]="b"> + {{ basinDescription(b, uitextRiverDownstream) }} + </mat-option> + </mat-select> + </mat-form-field> + + <div mat-dialog-actions [attr.align]="'end'"> + <button mat-raised-button color="primary" [mat-dialog-close]="true" cdkFocusInitial> + {{ uitextCancel }} + </button> + <button mat-raised-button color="warn" (click)="onValidate()" [disabled]="! enableValidate"> + {{ uitextValidate }} + </button> + </div> +</form> diff --git a/src/app/components/dialog-new-pb-cloison/dialog-new-pb-cloison.component.scss b/src/app/components/dialog-new-pb-cloison/dialog-new-pb-cloison.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..fc080522ee974e20200905fc9ed90970fd2c1fee --- /dev/null +++ b/src/app/components/dialog-new-pb-cloison/dialog-new-pb-cloison.component.scss @@ -0,0 +1,4 @@ +mat-form-field { + display: block; + margin-top: 0.5em; +} diff --git a/src/app/components/dialog-new-pb-cloison/dialog-new-pb-cloison.component.ts b/src/app/components/dialog-new-pb-cloison/dialog-new-pb-cloison.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..f5513751b8f24e50f2bba4f9f12386f090ff6a1c --- /dev/null +++ b/src/app/components/dialog-new-pb-cloison/dialog-new-pb-cloison.component.ts @@ -0,0 +1,96 @@ +import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material/dialog"; +import { Inject, Component, OnInit } from "@angular/core"; + +import { I18nService } from "../../services/internationalisation.service"; + +import { PbBassin } from "jalhyd"; + +@Component({ + selector: "dialog-new-pb-cloison", + templateUrl: "dialog-new-pb-cloison.component.html", + styleUrls: ["dialog-new-pb-cloison.component.scss"] +}) +export class DialogNewPbCloisonComponent implements OnInit { + + /** the selected upstream basin */ + public upstreamIndex: number; + + /** the selected downstream basin */ + public downstreamIndex: number; + + /** list of connectable basins, plus reiver upstream / downstrem */ + protected availableBasins: PbBassin[]; + + constructor( + public dialogRef: MatDialogRef<DialogNewPbCloisonComponent>, + private i18nService: I18nService, + @Inject(MAT_DIALOG_DATA) public data: any + ) { + this.availableBasins = data.basins; + this.upstreamIndex = 0; + this.downstreamIndex = 1; + } + + public get availableIndexes(): number[] { + // add river upstream as "0" + let ab: number[] = [ 0 ]; + for (let i = 0; i < this.availableBasins.length; i++) { + ab.push(i + 1); + } + return ab; + } + + public basinDescription(i: number, fallback: string): string { + if (i === 0) { + return fallback; + } else { + return this.i18nService.localizeText("INFO_PB_BASSIN_N") + i; + } + } + + public get enableValidate(): boolean { + return (this.upstreamIndex !== this.downstreamIndex); + } + + public onValidate(close = true) { + if (close) { + this.dialogRef.close({ + up: this.upstreamIndex, + down: this.downstreamIndex, + }); + } + return true; + } + + public ngOnInit() { + // this.initVariableValues(); + } + + public get uitextSelectBasins(): string { + return this.i18nService.localizeText("INFO_PB_NEW_WALL_SELECT_BASINS"); + } + + public get uiTextUpstreambasin(): string { + return this.i18nService.localizeText("INFO_PB_NEW_WALL_UP_BASIN"); + } + + public get uiTextDownstreambasin(): string { + return this.i18nService.localizeText("INFO_PB_NEW_WALL_DOWN_BASIN"); + } + + public get uitextRiverUpstream(): string { + return this.i18nService.localizeText("INFO_LIB_AMONT"); + } + + public get uitextRiverDownstream(): string { + return this.i18nService.localizeText("INFO_LIB_AVAL"); + } + + public get uitextValidate() { + return this.i18nService.localizeText("INFO_OPTION_VALIDATE"); + } + + public get uitextCancel() { + return this.i18nService.localizeText("INFO_OPTION_CANCEL"); + } +} diff --git a/src/app/components/pb-schema/pb-schema.component.html b/src/app/components/pb-schema/pb-schema.component.html index d87b406bc687360e1e4c87bdeebee77030ca807d..42f056be83d6baf9160d4e9770ca7bfc5a60c20f 100644 --- a/src/app/components/pb-schema/pb-schema.component.html +++ b/src/app/components/pb-schema/pb-schema.component.html @@ -12,6 +12,10 @@ {{ uitextAddBasin }} </button> + <button type="button" id="add-wall" mat-raised-button color="accent" (click)="onAddWallClick()" [disabled]="! enableAddWallButton"> + {{ uitextAddWall }} + </button> + <div class="hyd-window-btns"> <span class="related-entity-title"> {{ prefixedItemDescription }} @@ -20,11 +24,11 @@ <mat-option *ngFor="let i of addManyOptionsList" [value]="i"> {{ i }} </mat-option> - </mat-select> - <button type="button" mat-icon-button color="primary" [disabled]="! enableAddButton" (click)="onAddClick()" - [title]="uitextAdd"> - <mat-icon>add_box</mat-icon> - </button> --> + </mat-select> --> + <button type="button" mat-icon-button color="primary" [disabled]="! enableCopyButton" (click)="onCopyClick()" + [title]="uitextCopy"> + <mat-icon>content_copy</mat-icon> + </button> <button type="button" mat-icon-button color="primary" [disabled]="! enableRemoveButton" (click)="onRemoveClick()" [title]="uitextRemove"> <mat-icon>delete</mat-icon> diff --git a/src/app/components/pb-schema/pb-schema.component.scss b/src/app/components/pb-schema/pb-schema.component.scss index 7c3c8cb0bec3dffac0c0d1c00b1e9d9fd8fc28e0..f7b1167f4ad16883e0203ecacbeb6f5820da3a46 100644 --- a/src/app/components/pb-schema/pb-schema.component.scss +++ b/src/app/components/pb-schema/pb-schema.component.scss @@ -26,6 +26,10 @@ mat-card-content { #add-basin { float: left; } + #add-wall { + float: left; + margin-left: .5em; + } .related-entity-title { vertical-align: middle; font-weight: bold; diff --git a/src/app/components/pb-schema/pb-schema.component.ts b/src/app/components/pb-schema/pb-schema.component.ts index 7b4a8af0c797f353a832262dad5fa612c7288bf0..7f3f21e816f6c24e9da70af5c513cbff61c90e32 100644 --- a/src/app/components/pb-schema/pb-schema.component.ts +++ b/src/app/components/pb-schema/pb-schema.component.ts @@ -1,7 +1,8 @@ import { Component, Input, Output, EventEmitter, OnInit, AfterViewInit, ViewChild } from "@angular/core"; +import { MatDialog } from '@angular/material/dialog'; import { - PreBarrage, PbBassin, PbBassinParams, PbCloison, CalculatorType + PreBarrage, PbBassin, PbBassinParams, PbCloison } from "jalhyd"; import * as mermaid from "mermaid"; @@ -10,6 +11,7 @@ import { I18nService } from "../../services/internationalisation.service"; import { ApplicationSetupService } from "../../services/app-setup.service"; import { NotificationsService } from "../../services/notifications.service"; import { PbSchema } from "../../formulaire/elements/pb-schema"; +import { DialogNewPbCloisonComponent } from "../dialog-new-pb-cloison/dialog-new-pb-cloison.component"; /** * The interactive schema for calculator type "PreBarrage" (component) @@ -61,6 +63,7 @@ export class PbSchemaComponent implements AfterViewInit, OnInit { public constructor( private i18nService: I18nService, + private newPbCloisonDialog: MatDialog, private appSetupService: ApplicationSetupService, private notifService: NotificationsService ) { } @@ -132,8 +135,8 @@ export class PbSchemaComponent implements AfterViewInit, OnInit { // styles def.push("classDef wall fill:#e8e8e8,stroke-width:0;"); - def.push("classDef node-highlighted fill:orange;"); - // def.push("classDef basin fill:black;"); + def.push("classDef basin fill:#e0f3fb,stroke:#003A80;"); // irstea-ocean 50 / 500 + def.push("classDef node-highlighted fill:#4DBBE9;"); // irstea-ocean (material "accent"), 300 // debug if (this.model.children.length === 0) { @@ -150,7 +153,7 @@ export class PbSchemaComponent implements AfterViewInit, OnInit { for (const c of this.model.children) { if (c instanceof PbBassin) { def.push(`${c.uid}("${this.itemDesription(c)}")`); // rounded edges - // def.push(`class ${c.uid} basin;`); + def.push(`class ${c.uid} basin;`); } else if (c instanceof PbCloison) { const upstreamBasinId = c.bassinAmont === undefined ? this.upstreamId : c.bassinAmont.uid; const downstreamBasinId = c.bassinAval === undefined ? this.downstreamId : c.bassinAval.uid; @@ -182,7 +185,6 @@ export class PbSchemaComponent implements AfterViewInit, OnInit { item.classList.add("node-highlighted"); // find what was clicked if ([ this.upstreamId, this.downstreamId ].includes(item.id)) { - console.log("YOU CLICKED EITHER UPSTREAM OR DOWNSTREAM", item.id); this._selectedItem = undefined; } else { for (const b of this.model.children) { @@ -190,11 +192,6 @@ export class PbSchemaComponent implements AfterViewInit, OnInit { this._selectedItem = b; } } - if (this._selectedItem !== undefined) { - console.log(`${this._selectedItem.calcType === CalculatorType.PbBassin ? "BASIN" : "WALL"} FOUND !`, this._selectedItem); - } else { - console.log("watt ze fyook ?"); - } } } @@ -287,6 +284,23 @@ export class PbSchemaComponent implements AfterViewInit, OnInit { return this.i18nService.localizeText("INFO_FIELDSET_REMOVE"); } + public get enableCopyButton() { + return (this._selectedItem !== undefined && this._selectedItem instanceof PbCloison); + } + + /** Copies a wall */ + public onCopyClick() { + const wall = this._selectedItem as PbCloison + const wallCopy = new PbCloison(wall.bassinAmont, wall.bassinAval); + this.model.addChild(wallCopy); + this.unselect(); + this.refresh(); + } + + public get uitextCopy() { + return this.i18nService.localizeText("INFO_FIELDSET_COPY"); + } + /** Adds a new lone basin */ public onAddBasinClick() { this.model.addChild(new PbBassin(new PbBassinParams(20, 99))); @@ -298,6 +312,41 @@ export class PbSchemaComponent implements AfterViewInit, OnInit { return this.i18nService.localizeText("INFO_PB_ADD_BASIN"); } + public get enableAddWallButton(): boolean { + return (this.model.bassins.length > 0); + } + + /** Adds a new lone wall, opening a modal to choose connected basins */ + public onAddWallClick() { + // open dialog + const dialogRef = this.newPbCloisonDialog.open( + DialogNewPbCloisonComponent, + { + data: { + basins: this.model.bassins + }, + disableClose: true + } + ); + // apply modifications + dialogRef.afterClosed().subscribe(result => { + if (result.up !== undefined && result.down !== undefined) { + const wall = new PbCloison( + result.up === 0 ? undefined : this.model.bassins[result.up - 1], + result.down === 0 ? undefined : this.model.bassins[result.down - 1] + ); + this.model.addChild(wall); + this.unselect(); + this.refresh(); + } + }); + } + + + public get uitextAddWall() { + return this.i18nService.localizeText("INFO_PB_ADD_WALL"); + } + /** * Computes the global Pab validity : validity of every cell of every row */ @@ -310,7 +359,6 @@ export class PbSchemaComponent implements AfterViewInit, OnInit { private clearHighlightedItems() { this.nativeElement.querySelectorAll("g.node").forEach(item => { - console.log("found an item !"); item.classList.remove("node-highlighted"); }); } diff --git a/src/app/formulaire/elements/pb-schema.ts b/src/app/formulaire/elements/pb-schema.ts index 0d424378155a0a2977d501eea2a5282916c709c9..5be43f62f4db6d3d752be4141f580196c03dfe32 100644 --- a/src/app/formulaire/elements/pb-schema.ts +++ b/src/app/formulaire/elements/pb-schema.ts @@ -14,13 +14,6 @@ export class PbSchema extends FormulaireElement { this._confId = json["id"]; } - /** - * Returns the parent FormulairePab - */ - /* public get form(): FormulairePab { - return this.parentForm as FormulairePab; - } */ - /** * Returns the Prebarrage model associated to the parent form */ diff --git a/src/locale/messages.en.json b/src/locale/messages.en.json index 57397c48de90b1358e0b4bfd158db69b58e02f49..b5004bf82c16a54406cd0ffb903fcca113ce1129 100644 --- a/src/locale/messages.en.json +++ b/src/locale/messages.en.json @@ -517,8 +517,12 @@ "INFO_PARAMMODE_LIST": "Values list", "INFO_PARAMMODE_MINMAX": "Min/max", "INFO_PB_ADD_BASIN": "Add new basin", + "INFO_PB_ADD_WALL": "Add new wall", "INFO_PB_BASSIN_N": "Basin #", "INFO_PB_CLOISON": "Wall", + "INFO_PB_NEW_WALL_SELECT_BASINS": "Select basins to connect", + "INFO_PB_NEW_WALL_UP_BASIN": "upstream basin", + "INFO_PB_NEW_WALL_DOWN_BASIN": "Downstream basin", "INFO_PB_SCHEMA": "Basins layout", "INFO_PREBARRAGE_TITRE": "Pre-dams", "INFO_PREBARRAGE_TITRE_COURT": "Pre-dams", diff --git a/src/locale/messages.fr.json b/src/locale/messages.fr.json index 3ff3a647d635f80893c04f4d25e902783ac3fcc9..1f2e4117ca2ac0ad89c0cbce6870fcdf55c62b09 100644 --- a/src/locale/messages.fr.json +++ b/src/locale/messages.fr.json @@ -518,8 +518,12 @@ "INFO_PARAMMODE_LIST": "Liste de valeurs", "INFO_PARAMMODE_MINMAX": "Min/max", "INFO_PB_ADD_BASIN": "Ajouter un bassin", + "INFO_PB_ADD_WALL": "Ajouter une cloison", "INFO_PB_BASSIN_N": "Bassin n°", "INFO_PB_CLOISON": "Cloison", + "INFO_PB_NEW_WALL_SELECT_BASINS": "Choisir les bassins à connecter", + "INFO_PB_NEW_WALL_UP_BASIN": "Bassin amont", + "INFO_PB_NEW_WALL_DOWN_BASIN": "Bassin aval", "INFO_PB_SCHEMA": "Organisation des bassins", "INFO_PREBARRAGE_TITRE": "Prébarrages", "INFO_PREBARRAGE_TITRE_COURT": "Prébarrages",