diff --git a/e2e/navbar.po.ts b/e2e/navbar.po.ts index 2335b6baad6e403e7bcfa9671fc1c7dca4533a94..2112ceecf8ae3666311cee6fe7627b09dc433b9a 100644 --- a/e2e/navbar.po.ts +++ b/e2e/navbar.po.ts @@ -21,7 +21,6 @@ export class Navbar { async clickRandomCalculatorTab(n: number) { const tabs = this.getAllCalculatorTabs(); const l = await tabs.count(); - console.log("NOMBRE DE TABS", l); const r = Math.min((Math.floor(Math.random() * l)), (l - 1)); await tabs.get(r).click(); } diff --git a/src/app/app.component.ts b/src/app/app.component.ts index a6607adc619e2667e7e66047bf841fea291def20..c5f1bc1368915b888a1cf67f6c40d22df311d053 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -14,12 +14,11 @@ import { ApplicationSetupService } from "./services/app-setup/app-setup.service" import { HttpService } from "./services/http/http.service"; 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"; import { nghydDateRev } from "../date_revision"; import { MatSidenav, MatToolbar, MatDialog } from "@angular/material"; import { DialogConfirmEmptySessionComponent } from "./components/dialog-confirm-empty-session/dialog-confirm-empty-session.component"; +import { DialogSaveSessionComponent } from './components/dialog-save-session/dialog-save-session.component'; @Component({ @@ -58,9 +57,6 @@ export class AppComponent implements OnInit, OnDestroy, Observer { @ViewChild(LoadCalcDialogAnchorDirective) private appLoadCalcDialogAnchor: LoadCalcDialogAnchorDirective; - @ViewChild(SaveCalcDialogAnchorDirective) - private appSaveCalcDialogAnchor: SaveCalcDialogAnchorDirective; - /** * composant actuellement affiché par l'élément <router-outlet> */ @@ -75,7 +71,8 @@ export class AppComponent implements OnInit, OnDestroy, Observer { private router: Router, private formulaireService: FormulaireService, private httpService: HttpService, - private confirmEmptySessionDialog: MatDialog + private confirmEmptySessionDialog: MatDialog, + private saveSessionDialog: MatDialog ) { ServiceFactory.instance.applicationSetupService = appSetupService; ServiceFactory.instance.paramService = paramService; @@ -393,10 +390,7 @@ export class AppComponent implements OnInit, OnDestroy, Observer { * @param form formulaire à sélectionner par défaut dans la liste */ public saveForm(form?: FormulaireDefinition) { - // création du dialogue de sélection des formulaires à sauver - const compRef: ComponentRef<SaveCalculatorComponent> = this.appSaveCalcDialogAnchor.createDialog(); - - // création de la liste des formulaires + // liste des formulaires const list = []; for (const c of this._calculators) { const uid = c["uid"]; @@ -406,21 +400,30 @@ export class AppComponent implements OnInit, OnDestroy, Observer { "uid": uid }); } + // dialogue de sélection des formulaires à sauver + const dialogRef = this.saveSessionDialog.open( + DialogSaveSessionComponent, + { + data: { + calculators: list + }, + disableClose: true + } + ); + dialogRef.afterClosed().subscribe(result => { + if (result) { + let name = result.filename; - // 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(innerList => { - let name = compRef.instance.filename; + // ajout extension ".json" + const re = /.+\.json/; + const match = re.exec(name.toLowerCase()); + if (match === null) { + name = name + ".json"; + } - // ajout extension ".json" - const re = /.+\.json/; - const match = re.exec(name.toLowerCase()); - if (match === null) { - name = name + ".json"; + this.saveSession(result.calculators, name); } - - this.saveSession(innerList, name); - }).catch(err => { }); + }); } /** diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 5be5350c105f04d125528af65fc6507dc1ee34ec..fc0d5b75a41979f8171ed19c7fcd94a54b7b6afa 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -2,7 +2,7 @@ import { BrowserModule } from "@angular/platform-browser"; import { BrowserAnimationsModule } from "@angular/platform-browser/animations"; import { NgModule, NO_ERRORS_SCHEMA } from "@angular/core"; import { MatButtonModule, MatCheckboxModule, MatIconModule, MatSelectModule, MatTabsModule, MatSidenavModule, - MatToolbarModule, MatMenuModule, MatDialogModule } from "@angular/material"; + MatToolbarModule, MatMenuModule, MatDialogModule, MatFormFieldModule, MatInputModule, MatListModule } from "@angular/material"; import { FlexLayoutModule } from "@angular/flex-layout"; import { MDBBootstrapModule } from "angular-bootstrap-md"; import { HttpClientModule } from "@angular/common/http"; @@ -51,12 +51,12 @@ import { VerticalResultElementComponent } from "./components/result-element/vert import { LogEntryComponent } from "./components/log-entry/log-entry.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"; import { ParamLinkComponent } from "./components/param-link/param-link.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"; +// import { DialogLoadSessionComponent } from "./components/dialog-load-session/dialog-load-session.component"; +import { DialogSaveSessionComponent } from "./components/dialog-save-session/dialog-save-session.component"; const appRoutes: Routes = [ { path: "list", component: CalculatorListComponent }, @@ -76,7 +76,10 @@ const appRoutes: Routes = [ MatButtonModule, MatCheckboxModule, MatDialogModule, + MatFormFieldModule, MatIconModule, + MatInputModule, + MatListModule, MatMenuModule, MatSelectModule, MatSidenavModule, @@ -103,6 +106,8 @@ const appRoutes: Routes = [ CheckFieldLineComponent, DialogConfirmCloseCalcComponent, DialogConfirmEmptySessionComponent, + // DialogLoadSessionComponent, + DialogSaveSessionComponent, FieldSetComponent, FieldsetContainerComponent, FixedResultsComponent, @@ -124,8 +129,6 @@ const appRoutes: Routes = [ RemousResultsComponent, ResultElementBaseComponent, ResultsGraphComponent, - SaveCalcDialogAnchorDirective, - SaveCalculatorComponent, SectionCanvasComponent, SectionResultsComponent, SelectFieldLineComponent, @@ -136,8 +139,9 @@ const appRoutes: Routes = [ entryComponents: [ DialogConfirmCloseCalcComponent, DialogConfirmEmptySessionComponent, - LoadCalculatorComponent, - SaveCalculatorComponent + DialogSaveSessionComponent, + // DialogLoadSessionComponent, + LoadCalculatorComponent ], providers: [ // services ApplicationSetupService, diff --git a/src/app/components/dialog-save-session/dialog-save-session.component.html b/src/app/components/dialog-save-session/dialog-save-session.component.html new file mode 100644 index 0000000000000000000000000000000000000000..5c19a5bc6c607f1367d8cc2f3a6363ddc7625bc3 --- /dev/null +++ b/src/app/components/dialog-save-session/dialog-save-session.component.html @@ -0,0 +1,34 @@ +<h1 mat-dialog-title [innerHTML]="uitextSaveSessionTitle"></h1> + +<form> + + <div mat-dialog-content> + <div class="cb-container"> + <mat-checkbox [name]="c.uid" *ngFor="let c of calculators" [(ngModel)]="c.selected"> + {{ c.title }} + </mat-checkbox> + </div> + + <div class="btn-container"> + <button mat-raised-button (click)="selectAll()">{{ uitextAll }}</button> + <button mat-raised-button (click)="selectNone()">{{ uitextNone }}</button> + </div> + + <mat-form-field> + <input matInput required [placeholder]="uitextFilenameInput" [(ngModel)]="fileName" + name="filename" #filename="ngModel"> + </mat-form-field> + </div> + + <div mat-dialog-actions> + <button mat-raised-button color="primary" [mat-dialog-close]="false" cdkFocusInitial> + {{ uitextCancel }} + </button> + <button mat-raised-button type="submit" color="warn" (click)="saveSession()" + [disabled]="(! filename.valid) || (! atLeastOneCheckboxSelected)"> + + {{ uitextSave }} + </button> + </div> + +</form> diff --git a/src/app/components/dialog-save-session/dialog-save-session.component.scss b/src/app/components/dialog-save-session/dialog-save-session.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..e612ad2cf5490552d96d024c1122ef4cd1bbfc1f --- /dev/null +++ b/src/app/components/dialog-save-session/dialog-save-session.component.scss @@ -0,0 +1,19 @@ +mat-form-field { + width: 100%; +} + +.cb-container { + margin-bottom: 5px; + + mat-checkbox { + display: block; + } +} + +.btn-container { + margin-bottom: 20px; + + button { + margin-right: 5px; + } +} diff --git a/src/app/components/dialog-save-session/dialog-save-session.component.ts b/src/app/components/dialog-save-session/dialog-save-session.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..e33183c22e61ec3a8019a5e73e1ce0811ff26d8d --- /dev/null +++ b/src/app/components/dialog-save-session/dialog-save-session.component.ts @@ -0,0 +1,74 @@ +import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material"; +import { Inject, Component } from "@angular/core"; +import { InternationalisationService } from "../../services/internationalisation/internationalisation.service"; + +@Component({ + selector: "dialog-save-session", + templateUrl: "dialog-save-session.component.html", + styleUrls: ["dialog-save-session.component.scss"] +}) +export class DialogSaveSessionComponent { + + public calculators: any[]; + + public fileName = "session"; + + constructor( + public dialogRef: MatDialogRef<DialogSaveSessionComponent>, + private intlService: InternationalisationService, + @Inject(MAT_DIALOG_DATA) public data: any + ) { + this.calculators = data.calculators; + } + + public selectAll() { + for (const c of this.calculators) { + c.selected = true; + } + } + + public selectNone() { + for (const c of this.calculators) { + c.selected = false; + } + } + + public saveSession() { + this.dialogRef.close({ + calculators: this.calculators, + filename: this.fileName + }); + } + + public get atLeastOneCheckboxSelected() { + let ok = false; + for (const c of this.calculators) { + ok = (ok || c.selected); + } + return ok; + } + + public get uitextSave() { + return this.intlService.localizeText("INFO_OPTION_SAVE"); + } + + public get uitextCancel() { + return this.intlService.localizeText("INFO_OPTION_CANCEL"); + } + + public get uitextAll() { + return this.intlService.localizeText("INFO_OPTION_ALL"); + } + + public get uitextNone() { + return this.intlService.localizeText("INFO_OPTION_NONE"); + } + + public get uitextSaveSessionTitle() { + return this.intlService.localizeText("INFO_DIALOG_SAVE_SESSION_TITLE"); + } + + public get uitextFilenameInput() { + return this.intlService.localizeText("INFO_DIALOG_SAVE_SESSION_FILENAME"); + } +} diff --git a/src/app/components/save-calculator/save-calculator-anchor.directive.ts b/src/app/components/save-calculator/save-calculator-anchor.directive.ts deleted file mode 100644 index fa2d02f81584d9e9c2f5c32c6f0d3408f35bfa1e..0000000000000000000000000000000000000000 --- a/src/app/components/save-calculator/save-calculator-anchor.directive.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Directive, ComponentFactoryResolver, ComponentFactory, ComponentRef } from "@angular/core"; - -import { ViewContainerRef } from "@angular/core"; -import { SaveCalculatorComponent } from "./save-calculator.component"; - -@Directive({ - selector: "[appSaveCalcDialogAnchor]" -}) -export class SaveCalcDialogAnchorDirective { - constructor( - private viewContainer: ViewContainerRef, - private componentFactoryResolver: ComponentFactoryResolver - ) { } - - public createDialog(): ComponentRef<SaveCalculatorComponent> { - this.viewContainer.clear(); - - const compFactory: ComponentFactory<SaveCalculatorComponent> - = this.componentFactoryResolver.resolveComponentFactory(SaveCalculatorComponent); - const 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 deleted file mode 100644 index 1c48d43c7dfd4aed16531596fc430da7bfb6536f..0000000000000000000000000000000000000000 --- a/src/app/components/save-calculator/save-calculator.component.html +++ /dev/null @@ -1,32 +0,0 @@ -<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"> - <!-- 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> - - <!-- 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 mdbInputDirective [mdbValidate]="false" 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> - <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 deleted file mode 100644 index 653e76c4bffce16c3a14360ffa357c5ac5987810..0000000000000000000000000000000000000000 --- a/src/app/components/save-calculator/save-calculator.component.ts +++ /dev/null @@ -1,135 +0,0 @@ -import { Component, EventEmitter } 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 { - /** - * 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[]; - - /** - * nom du fichier - */ - private _filename = "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 - */ - private confirmResult = new EventEmitter(); - - // services - private intlService: InternationalisationService; - - constructor() { - this.intlService = ServiceFactory.instance.internationalisationService; - } - - public get uitextDialogTitle() { - return "Enregister les calculettes"; - } - - public get uitextCloseDialogYes() { - // return this.intlService.localizeText("INFO_OPTION_YES"); - return "Sauver"; - } - - public get uitextCloseDialogNo() { - // return this.intlService.localizeText("INFO_OPTION_NO"); - return "Annuler"; - } - - public get uitextSelectAll() { - return "Toutes"; - } - - public get uitextDeselectAll() { - return "Aucune"; - } - - public get filename(): string { - return this._filename; - } - - public set filename(f: string) { - this._filename = f; - } - - public get filenameTitle(): string { - return this._filenameTitle; - } - - - 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) { - 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; - } - } - } - - public selectAll() { - for (const c of this._calculators) { - c.selected = true; - } - } - - public deselectAll() { - for (const c of this._calculators) { - c.selected = false; - } - } - - private set confirmed(b: boolean) { - setTimeout(() => { - this.confirmResult.next(b); - }, 0); - } - - public get calculators() { - return this._calculators; - } - - /** - * appelé quand on clique sur annuler - */ - public cancelSave() { - this.confirmed = false; - } - - /** - * appelé quand on clique sur sauver - */ - public confirmSave() { - this.confirmed = true; - } -} diff --git a/src/locale/messages.en.json b/src/locale/messages.en.json index 7b28cd7c10d90bc9ab8268a4549ca7020accf885..1e219d12470f55f737592f79bfcefd926b414b05 100644 --- a/src/locale/messages.en.json +++ b/src/locale/messages.en.json @@ -38,7 +38,6 @@ "INFO_CONDUITEDISTRIBUTRICE_TITRE": "Distributor pipe", "INFO_COURBEREMOUS_TITRE": "Backwater curves", "INFO_DEVER_TITRE": "Free flow weir stage-discharge laws", -<<<<<<< 81116b3ae675b90a82d894f617c9a85f2f95782f "INFO_EXTRARES_ENUM_MACRORUGOFLOWTYPE_0": "Emergent", "INFO_EXTRARES_ENUM_MACRORUGOFLOWTYPE_1": "Quasi-emergent", "INFO_EXTRARES_ENUM_MACRORUGOFLOWTYPE_2": "Submerged", @@ -49,7 +48,8 @@ "INFO_EXTRARES_ENUM_STRUCTUREFLOWREGIME_1": "Partially submerged", "INFO_EXTRARES_ENUM_STRUCTUREFLOWREGIME_2": "Submerged", "INFO_EXTRARES_ENUM_STRUCTUREFLOWREGIME_3": "Zero flow", -======= + "INFO_DIALOG_SAVE_SESSION_FILENAME": "File name", + "INFO_DIALOG_SAVE_SESSION_TITLE": "Save calculator modules", "INFO_EMPTY_SESSION_DIALOGUE_TEXT": "Warning ! All open calculators will be lost. Continue ?", "INFO_EMPTY_SESSION_DIALOGUE_TITRE": "New session", "INFO_EXTRARES_ENUM_OUVRAGE_Q_MODE_0": "Weir", @@ -59,7 +59,6 @@ "INFO_EXTRARES_ENUM_OUVRAGE_Q_REGIME_1": "Partially submerged", "INFO_EXTRARES_ENUM_OUVRAGE_Q_REGIME_2": "Submerged", "INFO_EXTRARES_ENUM_OUVRAGE_Q_REGIME_3": "Zero flow", ->>>>>>> Fix #103 bouton pour vider la session "INFO_EXTRARES_LIB_B": "Surface width (m)", "INFO_EXTRARES_LIB_CV": "Cv: Velocity coefficient", "INFO_EXTRARES_LIB_CVQT": "CV.QT: Corrected discharge (m³/s)", @@ -119,6 +118,12 @@ "INFO_MENU_EMPTY_SESSION_TITLE": "New session", "INFO_OPTION_NO": "No", "INFO_OPTION_YES": "Yes", + "INFO_OPTION_CANCEL": "Cancel", + "INFO_OPTION_SAVE": "Save", + "INFO_OPTION_ALL": "All", + "INFO_OPTION_ALL_F": "All", + "INFO_OPTION_NONE": "None", + "INFO_OPTION_NONE_F": "None", "INFO_OUVRAGE": "Structure", "INFO_PABDIMENSIONS_TITRE": "Fish ladder: dimensions", "INFO_PABPUISSANCE_TITRE": "Fish ladder: dissipated power", diff --git a/src/locale/messages.fr.json b/src/locale/messages.fr.json index 5327b55ce08b7c6292827a258f3332d379c94d64..274d78b9cf699c97f70cd56773a6b699066d7b58 100644 --- a/src/locale/messages.fr.json +++ b/src/locale/messages.fr.json @@ -48,6 +48,8 @@ "INFO_EXTRARES_ENUM_STRUCTUREFLOWREGIME_1": "Partiellement noyé", "INFO_EXTRARES_ENUM_STRUCTUREFLOWREGIME_2": "Noyé", "INFO_EXTRARES_ENUM_STRUCTUREFLOWREGIME_3": "Débit nul", + "INFO_DIALOG_SAVE_SESSION_FILENAME": "Nom de fichier", + "INFO_DIALOG_SAVE_SESSION_TITLE": "Enregistrer les modules de calcul", "INFO_EMPTY_SESSION_DIALOGUE_TEXT": "Attention ! Toutes les calculettes ouvertes seront perdues. Continuer ?", "INFO_EMPTY_SESSION_DIALOGUE_TITRE": "Démarrer une nouvelle session", "INFO_EXTRARES_ENUM_OUVRAGE_Q_MODE_0": "Surface libre", @@ -116,6 +118,12 @@ "INFO_MACRORUGO_TITRE": "Passe à macro-rugosité", "INFO_OPTION_NO": "Non", "INFO_OPTION_YES": "Oui", + "INFO_OPTION_CANCEL": "Annuler", + "INFO_OPTION_SAVE": "Enregistrer", + "INFO_OPTION_ALL": "Tous", + "INFO_OPTION_ALL_F": "Toutes", + "INFO_OPTION_NONE": "Aucun", + "INFO_OPTION_NONE_F": "Aucune", "INFO_OUVRAGE": "Ouvrage", "INFO_PABDIMENSIONS_TITRE": "Passe à bassin : dimensions", "INFO_PABPUISSANCE_TITRE": "Passe à bassin : puissance dissipée", diff --git a/src/styles.scss b/src/styles.scss index aafdbe2dbcd6e961a9969bb96d0043b14f6cafb1..a5a4bad2cba2d4e2cd8fefcaf6509d1401986763 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -1,4 +1,21 @@ /* You can add global styles to this file, and also import other style files */ @import "~@angular/material/prebuilt-themes/indigo-pink.css"; +// @import "~@angular/material/prebuilt-themes/deeppurple-amber.css"; +// @import "~@angular/material/prebuilt-themes/pink-bluegrey.css"; +// @import "~@angular/material/prebuilt-themes/purple-green.css"; + html, body { height: 100%; } + body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; } + +button { + &:focus { + outline: 0; + } +} + +mat-dialog-container { + .mat-dialog-actions { + margin-bottom: -5px; + } +}