diff --git a/src/app/app.component.html b/src/app/app.component.html index a2dd2cf0e9b4c2f6ef118cbdeb36d9753db05e23..7c85695482c9d855809836ebe2a097d4a5bc61ee 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1,6 +1,8 @@ <header> <!--Navbar--> <mdb-navbar SideClass="navbar navbar-expand-sm navbar-dark indigo"> + <!-- Ouverture du sidenav --> + <span style="font-size:30px;cursor:pointer;color:white" (click)="openNav()">☰</span> <!-- Navbar brand --> <logo> @@ -12,61 +14,9 @@ <!-- Links --> <ul class="navbar-nav mr-auto"> - <!-- <li class="nav-item active"> - <a class="nav-link waves-light" mdbRippleRadius>Home - <span class="sr-only">(current)</span> - </a> + <li class="nav-item" *ngFor="let c of _calculators"> + <a class="nav-link waves-light" mdbRippleRadius [routerLink]="['/calculator/',c.uid]">{{c.title}}</a> </li> - <li class="nav-item"> - <a class="nav-link waves-light" mdbRippleRadius>Features</a> - </li> - <li class="nav-item"> - <a class="nav-link waves-light" mdbRippleRadius>Pricing</a> - </li> --> - - <!-- menu calculettes --> - <li class="nav-item"> - <div class="btn-group" dropdown> - <button dropdownToggle mdbRippleRadius type="button" class="btn btn-primary dropdown-toggle"> - Calculettes - <span class="caret"></span> - </button> - <ul *dropdownMenu class="dropdown-menu" role="menu"> - <li role="menuitem"> - <a class="dropdown-item" (click)="setDisplayCondDistri()">Conduite distributrice</a> - </li> - <li role="menuitem"> - <a class="dropdown-item" (click)="setDisplayLechaptCalmon()">Lechapt-Calmon</a> - </li> - <li role="menuitem"> - <a class="dropdown-item" (click)="setDisplayRegimeUnif()">Régime uniforme</a> - </li> - <!-- <li class="divider dropdown-divider"></li> --> - <li role="menuitem"> - <a class="dropdown-item" (click)="setDisplaySectionParam()">Sections paramétrées</a> - </li> - <li role="menuitem"> - <a class="dropdown-item" (click)="setDisplayCourbeRemous()">Courbes de remous</a> - </li> - </ul> - </div> - </li> - - <!-- menu langues --> - <li class="nav-item"> - <div class="btn-group" dropdown> - <button dropdownToggle mdbRippleRadius type="button" class="btn btn-primary dropdown-toggle"> - Langue - <span class="caret"></span> - </button> - <ul *dropdownMenu class="dropdown-menu" role="menu"> - <li role="menuitem" *ngFor="let l of intlService.languages"> - <a class="dropdown-item" (click)="selectLang(l.code)">{{l.label}}</a> - </li> - </ul> - </div> - </li> - </ul> <!-- Links --> @@ -77,14 +27,26 @@ <!--/.Navbar--> </header> - <main> - <div class="container-fluid"> - <hydrocalc type="ConduiteDistributrice" *ngIf="isDisplayCondDistri()"></hydrocalc> - <hydrocalc type="LechaptCalmon" *ngIf="isDisplayLechaptCalmon()"></hydrocalc> - <hydrocalc type="RegimeUniforme" *ngIf="isDisplayRegimeUnif()"></hydrocalc> - <hydrocalc type="SectionParametree" *ngIf="isDisplaySectionParam()"></hydrocalc> - <hydrocalc type="CourbeRemous" *ngIf="isDisplayCourbeRemous()"></hydrocalc> + <!-- <sidenav></sidenav> --> + <!-- sidenav --> + <div class="container"> + <div class="row"> + <div id="mySidenav" class="sidenav"> + <!-- ATTENTION ! pas de href="#" sous peine de rechargement de la page et réinitialisation de l'appli --> + <a class="closebtn" (click)="closeNav()">×</a> + <a (click)="newCalc()">Nouvelle calculette</a> + <a (click)="params()">Paramètres</a> + </div> + </div> + </div> + + <div class="container"> + <div class="row"> + <div class="col 12"> + <router-outlet></router-outlet> + </div> + </div> </div> </main> diff --git a/src/app/app.component.scss b/src/app/app.component.scss index 6cb7ce297266821d837497d81c1a328a2cadc4e5..839bbcf420c21d9be40af50730cf32f52d104627 100644 --- a/src/app/app.component.scss +++ b/src/app/app.component.scss @@ -1,4 +1,49 @@ .dropdown-menu > li > a:hover { background-color: rgb(172, 172, 172); background-image: none; -} \ No newline at end of file +} + +// sidenav +body { + font-family: "Lato", sans-serif; +} + +.sidenav { + height: 100%; + width: 0; + position: fixed; + z-index: 1; + top: 0; + left: 0; + background-color: #111; + overflow-x: hidden; + transition: 0.5s; + padding-top: 60px; +} + +.sidenav a { + padding: 8px 8px 8px 32px; + text-decoration: none; + font-size: 25px; + color: #818181; + display: block; + transition: 0.3s; +} + +.sidenav a:hover { + color: #f1f1f1; +} + +.sidenav .closebtn { + position: absolute; + top: 0; + right: 25px; + font-size: 36px; + margin-left: 50px; +} + +@media screen and (max-height: 450px) { + .sidenav {padding-top: 15px;} + .sidenav a {font-size: 18px;} +} +// sidenav \ No newline at end of file diff --git a/src/app/app.component.ts b/src/app/app.component.ts index ef162d122b1860eef984044eca6d78a3a91708dc..8c93ded303c7c8a605614f0bdd9826303aa1ee58 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,6 +1,7 @@ import { Component, ApplicationRef } from '@angular/core'; //import { Component, ChangeDetectorRef, ApplicationRef, AfterViewChecked } from '@angular/core'; //import { MdDialog } from '@angular/material'; +import { Router } from '@angular/router'; import { ComputeNodeType, ComputeNode } from 'jalhyd'; @@ -11,26 +12,42 @@ import { Observer } from './services/observer'; import { ErrorService } from './services/error/error.service'; // import { AlertDialog } from './components/alert-dialog/alert-dialog.component'; import { FormulaireService } from './services/formulaire/formulaire.service'; +import { FormulaireElement } from './formulaire/formulaire-element'; +import { FormulaireDefinition, CalculatorType } from './formulaire/formulaire-definition'; @Component({ selector: 'nghyd-app', templateUrl: './app.component.html', - styleUrls: ['./app.component.scss'], - providers: [ParamService, InternationalisationService, HttpService, FormulaireService] + styleUrls: ['./app.component.scss'] }) export class AppComponent implements Observer { private _currentLanguage: LanguageCode; private _displayErrorDialog: boolean = false; + private _calculators: any[] = []; + // constructor(private intlService: InternationalisationService, private appRef: ApplicationRef, private dialog: MdDialog, private errorService: ErrorService) { } - constructor(private intlService: InternationalisationService, private appRef: ApplicationRef, private errorService: ErrorService) { } + constructor(private intlService: InternationalisationService, + private appRef: ApplicationRef, + private errorService: ErrorService, + private router: Router, + private formulaireService: FormulaireService + ) { + this.formulaireService.addObserver(this); + } private initLocale() { let docLocale: string = document['locale'] as string; this.intlService.setLocale(docLocale); this._currentLanguage = this.intlService.currentLanguage.code; + + // process.on('unhandledRejection', (reason, p) => { + // console.log('Unhandled Rejection at: Promise', p, 'reason:', reason); + // // Stack Trace + // console.log(reason.stack); + // }); } ngOnInit() { @@ -40,46 +57,6 @@ export class AppComponent implements Observer { private _displayedCalc: ComputeNodeType; - private isDisplayCondDistri(): boolean { - return this._displayedCalc == ComputeNodeType.CondDistri; - } - - private setDisplayCondDistri() { - this._displayedCalc = ComputeNodeType.CondDistri; - } - - private isDisplayLechaptCalmon(): boolean { - return this._displayedCalc == ComputeNodeType.LechaptCalmon; - } - - private setDisplayLechaptCalmon() { - this._displayedCalc = ComputeNodeType.LechaptCalmon; - } - - private isDisplayRegimeUnif(): boolean { - return this._displayedCalc == ComputeNodeType.RegimeUniforme; - } - - private setDisplayRegimeUnif() { - this._displayedCalc = ComputeNodeType.RegimeUniforme; - } - - private isDisplaySectionParam(): boolean { - return this._displayedCalc == ComputeNodeType.SectionParametree; - } - - private setDisplaySectionParam() { - this._displayedCalc = ComputeNodeType.SectionParametree; - } - - private isDisplayCourbeRemous(): boolean { - return this._displayedCalc == ComputeNodeType.CourbeRemous; - } - - private setDisplayCourbeRemous() { - this._displayedCalc = ComputeNodeType.CourbeRemous; - } - /** * abonnement au service d'erreurs */ @@ -103,14 +80,42 @@ export class AppComponent implements Observer { // interface Observer - update(data: any): void { - // on ouvre un dialogue avec le message d'erreur reçu - // if (this._displayErrorDialog) { - // let dialogRef = this.dialog.open(AlertDialog); - // let ad: AlertDialog = dialogRef.componentInstance; - // ad.text = String(data); - // } - // else - console.log(data); + update(sender: any, data: any): void { + if (sender instanceof ErrorService) { + // on ouvre un dialogue avec le message d'erreur reçu + // if (this._displayErrorDialog) { + // let dialogRef = this.dialog.open(AlertDialog); + // let ad: AlertDialog = dialogRef.componentInstance; + // ad.text = String(data); + // } + // else + console.log(data); + } + else if (sender instanceof FormulaireService) { + const f: FormulaireDefinition = data; + this._calculators.push( + { + "title": CalculatorType[f.calculatorType] + String(f.uid), + "uid": String(f.uid) + } + ); + } } + + // sidenav + + private openNav() { + document.getElementById("mySidenav").style.width = "300px"; + } + + private closeNav() { + document.getElementById("mySidenav").style.width = "0"; + } + + private newCalc() { + this.closeNav(); + this.router.navigate(['/list']); + } + + // sidenav } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 4f3a51f91e8d1bb8e76977e08884537dd0e2ebdd..b2ff7e6d137109e9587eec351472f5afb4a6be4b 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -6,7 +6,12 @@ import { HttpModule } from '@angular/http'; import { FormsModule } from '@angular/forms'; // <-- NgModel lives here //import { MdInputModule, MdDialogModule } from '@angular/material'; import { ChartModule } from 'angular2-chartjs'; +import { RouterModule, Routes } from '@angular/router'; +import { FormulaireService } from "./services/formulaire/formulaire.service"; +import { ParamService } from "./services/param/param.service"; +import { InternationalisationService } from "./services/internationalisation/internationalisation.service"; +import { HttpService } from "./services/http/http.service"; import { AppComponent } from './app.component'; import { ParamInputComponent } from './components/param-input/param-input.component'; import { FieldSetComponent } from './components/field-set/field-set.component'; @@ -22,9 +27,20 @@ import { CalcCanvasComponent } from './components/canvas/canvas.component'; import { SectionCanvasComponent } from './components/section-canvas/section-canvas.component'; import { RemousResultsComponent } from './components/remous-results/remous-results.component'; import { LogComponent } from './components/log/log.component'; +import { CalculatorListComponent } from './components/calculator-list/calculator-list.component'; + +const appRoutes: Routes = [ + { path: 'list', component: CalculatorListComponent }, + { path: 'calculator/:uid', component: GenericCalculatorComponent }, + { path: '**', component: CalculatorListComponent } +]; @NgModule({ imports: [ + RouterModule.forRoot( + appRoutes, + { enableTracing: true } // <-- debugging purposes only + ), BrowserModule, BrowserAnimationsModule, MDBBootstrapModule.forRoot(), @@ -35,20 +51,23 @@ import { LogComponent } from './components/log/log.component'; ChartModule, AppErrorModule ], - declarations: [ + declarations: [ // composants, pipes et directives AppComponent, ParamInputComponent, FieldSetComponent, ParamFieldLineComponent, SelectFieldLineComponent, CheckFieldLineComponent, LogComponent, + CalculatorListComponent, GenericCalculatorComponent, // AlertDialog, CalculatorResultsComponent, SectionResultsComponent, RemousResultsComponent, CalcCanvasComponent, SectionCanvasComponent ], // entryComponents: [AlertDialog], - providers: [], - schemas: [ NO_ERRORS_SCHEMA ], + providers: [ // services + ParamService, InternationalisationService, HttpService, FormulaireService + ], + schemas: [NO_ERRORS_SCHEMA], bootstrap: [AppComponent] }) export class AppModule { } diff --git a/src/app/calculators/generic/calculator.component.ts b/src/app/calculators/generic/calculator.component.ts index 48dddaea7b12d278fbc9cbc779c2dabf7e8bc97d..60f409ef56eb5d7a08cbe4d93f99b40ab38b1349 100644 --- a/src/app/calculators/generic/calculator.component.ts +++ b/src/app/calculators/generic/calculator.component.ts @@ -1,7 +1,5 @@ -import { Component, OnInit, DoCheck, ViewChild, Input } from "@angular/core"; -import { Response } from "@angular/http"; -import { Observable } from "rxjs/Observable"; -import "rxjs/add/operator/toPromise"; +import { Component, Inject, OnInit, DoCheck, ViewChild, Input } from "@angular/core"; +import { ActivatedRoute, ParamMap } from '@angular/router'; import { ComputeNode, ComputeNodeType, ParamsEquation, Nub, acSection, RegimeUniforme, MethodeResolution, CourbeRemousParams, CourbeRemous, cLog, Result } from "jalhyd"; @@ -22,6 +20,7 @@ import { CalculatorResultsComponent } from "../../components/calculator-results/ import { SectionResultsComponent } from "../../components/section-results/section-results.component"; import { RemousResultsComponent } from "../../components/remous-results/remous-results.component"; import { Observer } from "../../services/observer"; +import { Subscription } from "rxjs/Subscription"; @Component({ selector: 'hydrocalc', @@ -35,16 +34,6 @@ import { Observer } from "../../services/observer"; ] }) export class GenericCalculatorComponent implements OnInit, DoCheck, Observer { - /** - * Calculator type input attribute - */ - private _calculatorType: CalculatorType; - - @Input() - private set type(s: string) { - this._calculatorType = CalculatorType[s]; - } - /** * type de noeud de calcul actuel (utilisé pour les sections, à sortir de ce composant générique) */ @@ -69,10 +58,8 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, Observer { private remousResultsComponent: RemousResultsComponent; /** - * objet JSON chargé depuis le fichier de traduction + * formulaire affiché */ - private _localisation = {}; - private _formulaire: FormulaireDefinition; /** @@ -90,7 +77,11 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, Observer { */ private _showResultsRemous: boolean = false; - constructor(private paramService: ParamService, private httpService: HttpService, private intlService: InternationalisationService, private formulaireService: FormulaireService) { + constructor(private paramService: ParamService, + private httpService: HttpService, + private intlService: InternationalisationService, + private formulaireService: FormulaireService, + private route: ActivatedRoute) { this.intlService.addObserver(this); } @@ -101,7 +92,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, Observer { } private get uitextTitre() { - switch (this._calculatorType) { + switch (this._formulaire.calculatorType) { case CalculatorType.ConduiteDistributrice: return this.intlService.localizeText("INFO_CONDDISTRI_TITRE"); @@ -118,7 +109,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, Observer { return this.intlService.localizeText("INFO_REMOUS_TITRE") default: - return "Invalid calculator type " + this._calculatorType; + return "Invalid calculator type " + this._formulaire.calculatorType; } } @@ -126,110 +117,25 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, Observer { return this.intlService.localizeText("INFO_CALCULATOR_CALCULER"); } - private loadLocalisation(): Promise<string> { - let ths = this; - let processData = function (s: string) { - // fermeture nécessaire pour capturer la valeur de this (undefined sinon) - ths._localisation = JSON.parse(s); - ths.formulaireService.updateLocalisation(ths._formulaire.uid, ths._localisation); - } - - let f: string = this.formulaireService.getConfigPathPrefix(this._calculatorType) + this.intlService.currentLanguage.tag + ".json" - let resp: Observable<Response> = this.httpService.httpGetRequestResponse(undefined, undefined, undefined, f); - - let prom = resp.map(res => res.text()).toPromise(); - prom.then((res) => { - processData(res); - }) - - return prom; - } - - private loadFormulaire(): Promise<FormulaireDefinition> { - if (this._formulaire == undefined) { - let prom = this.formulaireService.loadFormulaire(this._calculatorType); - prom.then(res => { - this._formulaire = res; - }); - prom.then( - _ => this.loadLocalisation() - ); - // prom.then( - // _ => this.formulaireService.updateLocalisation(this._localisation) - // ); - - return prom; - } - return undefined; - } - - /* - private getHtmlElementFromId_helper(elm: HTMLElement, id: string): HTMLElement { - if (elm.hasAttribute('id')) - if (elm.getAttribute('id') === id) - return elm; - - let kids: NodeList = elm.childNodes; - for (let i = 0; i < kids.length; i++) { - let kid = kids[i]; - if (kid instanceof HTMLElement) { - let e = this.getHtmlElementFromId_helper(<HTMLElement>kid, id); - if (e != undefined) - return e; - } - } - - return undefined; - } - - private getHtmlElementFromId(id: string): HTMLElement { - let he: HTMLElement = this.elementRef.nativeElement; - return this.getHtmlElementFromId_helper(he, id); - } - - private getHtmlElementValue(e: HTMLElement): string { - if (e instanceof HTMLSelectElement) - return e.value; - return undefined; - } - private setHtmlElementValue(e: HTMLElement, val: string) { - if (e instanceof HTMLInputElement) - e.value = val; - } - */ private applyDependencies() { if (this._formulaire == undefined) return; this._formulaire.applyDependencies(); - - /* - for (let d of this._formulaire.dependencies) { - if (d instanceof ExistenceDependency) { - } - else if (d instanceof ValueDependency) { - let vd = <ValueDependency>d; - let master: HTMLElement = this.getHtmlElementFromId(d.masterElement.id); - if (this.getHtmlElementValue(master) == vd.masterValue) { - let slave: HTMLElement = this.getHtmlElementFromId(d.slaveElement.id); - this.setHtmlElementValue(slave, vd.slaveValue); - } - } - } - */ } + private _subscription: Subscription; + ngOnInit() { - let prom = this.loadFormulaire(); - prom.then( - _ => { - let ssf: SelectField = <SelectField>this._formulaire.getFormulaireElementById("select_section"); - if (ssf != undefined) - this.updateSectionType(ssf.getValue()); - - this.applyDependencies(); - } - ); + // récupération des paramètres passés avec la route (URL) + this._subscription = this.route.params.subscribe(params => { + const uid: number = +params['uid']; + + this._formulaire = this.formulaireService.getFormulaireFromId(uid); + let ssf: SelectField = <SelectField>this._formulaire.getFormulaireElementById("select_section"); + if (ssf != undefined) + this.updateSectionType(ssf.getValue()); + }); } ngDoCheck() { @@ -242,6 +148,10 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, Observer { // } } + ngOnDestroy() { + this._subscription.unsubscribe(); + } + /* * gestion des événements clic sur les radios : * envoi d'un message au composant parent @@ -372,10 +282,9 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, Observer { this.resultsComponent.setVariableParamHeaderFromParameter(varParam, false); this.resultsComponent.setVariableResultHeader(computedParam["label"]); - let ssf: SelectField = <SelectField>this._formulaire.getFormulaireElementById("select_section"); - let typeSect: ComputeNodeType = FormulaireDefinition.getComputeNodeTypeFromSection(ssf.getValue(), CalculatorType.SectionParametree); + let nodeType: ComputeNodeType = this.getNodeTypeFromSelectField("select_section", CalculatorType.SectionParametree); - var np: [acSection, ParamsEquation] = this.formulaireService.getSectionNubAndParameters(CalculatorType.SectionParametree, typeSect); + var np: [acSection, ParamsEquation] = this.formulaireService.getSectionNubAndParameters(this._formulaire, nodeType); let sect: acSection = np[0]; let prms: ParamsEquation = np[1]; @@ -409,9 +318,8 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, Observer { return; } - let ssf: SelectField = <SelectField>this._formulaire.getFormulaireElementById("select_section"); - let typeSect: ComputeNodeType = FormulaireDefinition.getComputeNodeTypeFromSection(ssf.getValue(), CalculatorType.SectionParametree); - var np: [acSection, ParamsEquation] = this.formulaireService.getSectionNubAndParameters(CalculatorType.SectionParametree, typeSect); + let nodeType: ComputeNodeType = this.getNodeTypeFromSelectField("select_section", CalculatorType.SectionParametree); + var np: [acSection, ParamsEquation] = this.formulaireService.getSectionNubAndParameters(this._formulaire, nodeType); let sect: acSection = np[0]; let prms: ParamsEquation = np[1]; @@ -503,9 +411,8 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, Observer { private doComputeRemous() { this.remousResultsComponent.reset(); - let ssf: SelectField = <SelectField>this._formulaire.getFormulaireElementById("select_section"); - let typeSect: ComputeNodeType = FormulaireDefinition.getComputeNodeTypeFromSection(ssf.getValue(), CalculatorType.CourbeRemous); - var np: [acSection, ParamsEquation] = this.formulaireService.getSectionNubAndParameters(CalculatorType.CourbeRemous, typeSect, false); + let nodeType: ComputeNodeType = this.getNodeTypeFromSelectField("select_section", CalculatorType.CourbeRemous); + var np: [acSection, ParamsEquation] = this.formulaireService.getSectionNubAndParameters(this._formulaire, nodeType, false); let sect: acSection = np[0]; let prmSect: ParamsEquation = np[1]; @@ -585,12 +492,12 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, Observer { this._showResultsSection = false; this._showResultsRemous = false; - if (this._calculatorType == CalculatorType.SectionParametree) { + if (this._formulaire.calculatorType == CalculatorType.SectionParametree) { this.doComputeSection(); return; } - if (this._calculatorType == CalculatorType.CourbeRemous) { + if (this._formulaire.calculatorType == CalculatorType.CourbeRemous) { this.doComputeRemous(); return; } @@ -598,14 +505,14 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, Observer { let np: [Nub, ParamsEquation]; let nub: Nub; let prms: ParamsEquation; - let rg: boolean = this._calculatorType == CalculatorType.RegimeUniforme; + let rg: boolean = this._formulaire.calculatorType == CalculatorType.RegimeUniforme; if (rg) { - let snp: [acSection, ParamsEquation] = this.formulaireService.getSectionNubAndParameters(CalculatorType.RegimeUniforme, this._nodeType); + let snp: [acSection, ParamsEquation] = this.formulaireService.getSectionNubAndParameters(this._formulaire, this._nodeType); nub = new RegimeUniforme(snp[0]); prms = snp[1]; } else { - np = this.formulaireService.getNubAndParameters(this._calculatorType); + np = this.formulaireService.getNubAndParameters(this._formulaire); nub = np[0]; prms = np[1]; } @@ -658,6 +565,67 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, Observer { this._showResultsFixVar = true; } + private getComputeNodeTypeFromSection(sect: string, calc: CalculatorType): ComputeNodeType { + switch (calc) { + case CalculatorType.SectionParametree: + switch (sect) { + case "trapez": + return ComputeNodeType.SectionTrapeze; + + case "rect": + return ComputeNodeType.SectionRectangle; + + case "circ": + return ComputeNodeType.SectionCercle; + + case "puiss": + return ComputeNodeType.SectionPuissance; + + default: + throw "getComputeNodeTypeFromSection() : section " + sect + " / type de calculette " + CalculatorType[calc] + " non pris en charge" + } + + case CalculatorType.RegimeUniforme: + switch (sect) { + case "trapez": + return ComputeNodeType.RegimeUniformeTrapeze; + + case "rect": + return ComputeNodeType.RegimeUniformeRectangle; + + case "circ": + return ComputeNodeType.RegimeUniformeCercle; + + case "puiss": + return ComputeNodeType.RegimeUniformePuissance; + + default: + throw "getComputeNodeTypeFromSection() : section " + sect + " / type de calculette " + CalculatorType[calc] + " non pris en charge" + } + + case CalculatorType.CourbeRemous: + switch (sect) { + case "trapez": + return ComputeNodeType.CourbeRemousTrapeze; + + case "rect": + return ComputeNodeType.CourbeRemousRectangle; + + case "circ": + return ComputeNodeType.CourbeRemousCercle; + + case "puiss": + return ComputeNodeType.CourbeRemousPuissance; + + default: + throw "getComputeNodeTypeFromSection() : section " + sect + " / type de calculette " + CalculatorType[calc] + " non pris en charge" + } + + default: + throw "getComputeNodeTypeFromSection() : section " + sect + " / type de calculette " + CalculatorType[calc] + " non pris en charge" + } + } + private getResultsStyleDisplay() { return this._showResultsFixVar ? "block" : "none"; } @@ -677,13 +645,10 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, Observer { // interface Observer - update(data: any): void { - // message de InternationalisationService - // const promise = this.loadLocalisation() - // .then(() => { - // this.formulaireService.updateLocalisation(this._localisation); - // }); - this.loadLocalisation(); + update(sender: any, data: any): void { + if (sender instanceof InternationalisationService) { + this.formulaireService.updateLocalisation(); + } } private removePrefix(s: string, prefix: string): string { @@ -698,72 +663,18 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, Observer { //TODO ici on fait un cas particulier, il faudra sortir ça let type: string = this.removePrefix(val, "select_section_"); - if (type != undefined) { - switch (this._calculatorType) { - case CalculatorType.SectionParametree: - switch (type) { - case "trapez": - this._nodeType = ComputeNodeType.SectionTrapeze; - break; - - case "rect": - this._nodeType = ComputeNodeType.SectionRectangle; - break; - - case "circ": - this._nodeType = ComputeNodeType.SectionCercle; - break; - - case "puiss": - this._nodeType = ComputeNodeType.SectionPuissance; - break; - } - break; - - case CalculatorType.RegimeUniforme: - switch (type) { - case "trapez": - this._nodeType = ComputeNodeType.RegimeUniformeTrapeze; - break; - - case "rect": - this._nodeType = ComputeNodeType.RegimeUniformeRectangle; - break; - - case "circ": - this._nodeType = ComputeNodeType.RegimeUniformeCercle; - break; - - case "puiss": - this._nodeType = ComputeNodeType.RegimeUniformePuissance; - break; - } - break; - - case CalculatorType.CourbeRemous: - switch (type) { - case "trapez": - this._nodeType = ComputeNodeType.CourbeRemousTrapeze; - break; - - case "rect": - this._nodeType = ComputeNodeType.CourbeRemousRectangle; - break; - - case "circ": - this._nodeType = ComputeNodeType.CourbeRemousCercle; - break; - - case "puiss": - this._nodeType = ComputeNodeType.CourbeRemousPuissance; - break; - } - break; - - default: - throw "GenericCalculatorComponent.updateSectionType() : section " + val + " / type de calculette " + CalculatorType[this._calculatorType] + " non pris en charge" - } - } + if (type != undefined) + this._nodeType = this.getComputeNodeTypeFromSection(type, this._formulaire.calculatorType); + } + + private getNodeTypeFromSelectField(selectFieldId: string, calcType: CalculatorType): ComputeNodeType { + let ssf: SelectField = <SelectField>this._formulaire.getFormulaireElementById(selectFieldId); + let val = ssf.getValue(); + let type: string = this.removePrefix(val, "select_section_"); + if (type != undefined) + return this.getComputeNodeTypeFromSection(type, calcType); + + return undefined; } /** diff --git a/src/app/components/calculator-list/calculator-list.component.css b/src/app/components/calculator-list/calculator-list.component.css new file mode 100644 index 0000000000000000000000000000000000000000..61c95428bd01c0e553f853c4053569dbfaf01a98 --- /dev/null +++ b/src/app/components/calculator-list/calculator-list.component.css @@ -0,0 +1,12 @@ +.full-page { + width: 100%; + height: 100%; + min-height: 100%; + background: red; + display: block; +} + +.full-height { + min-height: 100%; + height: 100%; +} diff --git a/src/app/components/calculator-list/calculator-list.component.html b/src/app/components/calculator-list/calculator-list.component.html new file mode 100644 index 0000000000000000000000000000000000000000..1b955aee56221d1e0b449c82215f014527561247 --- /dev/null +++ b/src/app/components/calculator-list/calculator-list.component.html @@ -0,0 +1,9 @@ +<div class="container-fluid"> + <div class="row"> + <div class="offset-4 col-4 mx-auto"> + <ul *ngFor="let l of _items" class="list-group"> + <button class="list-group-item" (click)="create(l.type)">{{l.label}}</button> + </ul> + </div> + </div> +</div> \ No newline at end of file diff --git a/src/app/components/calculator-list/calculator-list.component.ts b/src/app/components/calculator-list/calculator-list.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..d2db5a80b37a7e67982b4a9ea38c12c216cfecf1 --- /dev/null +++ b/src/app/components/calculator-list/calculator-list.component.ts @@ -0,0 +1,37 @@ +import { Component } from "@angular/core"; +import { Router } from '@angular/router'; + +import { CalculatorType, FormulaireDefinition } from "../../formulaire/formulaire-definition"; +import { FormulaireService } from "../../services/formulaire/formulaire.service"; + +class ListElement { + constructor(private _label: string, private _type: CalculatorType) { } + + public get label() { return this._label } + public get type() { return this._type } +} + +@Component({ + selector: "list", + templateUrl: "./calculator-list.component.html", + styleUrls: ["./calculator-list.component.css"] +}) +export class CalculatorListComponent { + private _items: ListElement[] = []; + + constructor(private formulaireService: FormulaireService, private router: Router) { + this._items.push(new ListElement("Conduite distributrice", CalculatorType.ConduiteDistributrice)); + this._items.push(new ListElement("Lechapt-Calmon", CalculatorType.LechaptCalmon)); + this._items.push(new ListElement("Regime uniforme", CalculatorType.RegimeUniforme)); + this._items.push(new ListElement("Sections paramétrées", CalculatorType.SectionParametree)); + this._items.push(new ListElement("Courbes remous", CalculatorType.CourbeRemous)); + } + + private create(t: CalculatorType) { + console.log("create", t); + const p: Promise<FormulaireDefinition> = this.formulaireService.createFormulaire(t); + p.then(f => { + this.router.navigate(['/calculator', f.uid]); + }); + } +} diff --git a/src/app/formulaire/formulaire-definition.ts b/src/app/formulaire/formulaire-definition.ts index caf1ad4eedfa511eeedeb470e0b132e70ecd5662..782a500a3ca834c8001a331151137c4dfb1b4ac8 100644 --- a/src/app/formulaire/formulaire-definition.ts +++ b/src/app/formulaire/formulaire-definition.ts @@ -40,12 +40,12 @@ export class FormulaireDefinition { */ private _defaultNodeType: ComputeNodeType; - constructor(private paramService: ParamService, private _type: CalculatorType) { + constructor(private paramService: ParamService, private _calcType: CalculatorType) { this._uid = FormulaireDefinition.uidGenerator(); } - public get type(): CalculatorType { - return this._type; + public get calculatorType(): CalculatorType { + return this._calcType; } /** @@ -435,35 +435,6 @@ export class FormulaireDefinition { console.log(d.toString()); } - public static getComputeNodeTypeFromSection(sect: string, calc: CalculatorType): ComputeNodeType { - switch (calc) { - case CalculatorType.SectionParametree: - if (sect === "select_section_trapez") - return ComputeNodeType.SectionTrapeze; - if (sect === "select_section_rect") - return ComputeNodeType.SectionRectangle; - if (sect === "select_section_circ") - return ComputeNodeType.SectionCercle; - if (sect === "select_section_puiss") - return ComputeNodeType.SectionPuissance; - throw "Formulaire.getSectionType() : type de section '" + sect + "' inconnu pour la calculette " + CalculatorType[calc]; - - case CalculatorType.CourbeRemous: - if (sect === "select_section_trapez") - return ComputeNodeType.CourbeRemousTrapeze; - if (sect === "select_section_rect") - return ComputeNodeType.CourbeRemousRectangle; - if (sect === "select_section_circ") - return ComputeNodeType.CourbeRemousCercle; - if (sect === "select_section_puiss") - return ComputeNodeType.CourbeRemousPuissance; - throw "Formulaire.getSectionType() : type de section '" + sect + "' inconnu pour la calculette " + CalculatorType[calc]; - - default: - throw "Formulaire.getSectionType() : type de calculette " + CalculatorType[calc] + " non pris en charge"; - } - } - public isDisplayed(id: string) { return this.getFormulaireElementById(id).isDisplayed; } diff --git a/src/app/services/formulaire/formulaire.service.ts b/src/app/services/formulaire/formulaire.service.ts index db9439187d6c32e0f46f7a09a95f477ea5a8b9f9..0c408308aa4992e8faa8a0f2460ebba9f48b62e5 100644 --- a/src/app/services/formulaire/formulaire.service.ts +++ b/src/app/services/formulaire/formulaire.service.ts @@ -1,5 +1,7 @@ import { Injectable } from "@angular/core"; import { Response } from "@angular/http"; +import { Observable as rxObservable } from "rxjs/Observable"; +import "rxjs/add/operator/toPromise"; import { ComputeNodeType, ParamsEquation, acSection, Nub, ConduiteDistrib, ConduiteDistribParams } from "jalhyd"; import { LechaptCalmon, LechaptCalmonParams, ParamsSectionTrapez, cSnTrapez } from "jalhyd"; @@ -12,15 +14,72 @@ import { FormulaireElement } from "../../formulaire/formulaire-element"; import { SelectField } from "../../formulaire/select-field"; import { CheckField } from "../../formulaire/check-field"; import { StringMap } from "../../stringmap"; +import { InternationalisationService } from "../../services/internationalisation/internationalisation.service"; +import { EnumEx } from "../../util"; +import { Observable } from "../observer"; @Injectable() -export class FormulaireService { +export class FormulaireService extends Observable { private _formulaires: FormulaireDefinition[]; - constructor(private paramService: ParamService, private httpService: HttpService) { + constructor(private paramService: ParamService, + private httpService: HttpService, + private intlService: InternationalisationService + ) { + super(); this._formulaires = []; } + public get formulaires(): FormulaireDefinition[] { + return this._formulaires; + } + + private loadLocalisation(calc: CalculatorType): Promise<any> { + let f: string = this.getConfigPathPrefix(calc) + this.intlService.currentLanguage.tag + ".json" + let resp: rxObservable<Response> = this.httpService.httpGetRequestResponse(undefined, undefined, undefined, f); + + let prom = resp.map(res => res.text()).toPromise(); + return prom.then((res) => { + let j = JSON.parse(res); + return j as StringMap; + }) + } + + /** + * met à jour la langue du formulaire + * @param formId id unique du formulaire + * @param localisation ensemble id-message traduit + */ + private updateFormulaireLocalisation(formId: number, localisation: StringMap) { + for (let loc_id in localisation) { + let fe = this.getFormulaireElementById(formId, loc_id); + if (fe != undefined) + fe.updateLocalisation(localisation); + } + } + + /** + * charge la localisation et met à jour la langue du formulaire + */ + private loadUpdateFormulaireLocalisation(f: FormulaireDefinition): Promise<any> { + return this.loadLocalisation(f.calculatorType) + .then(localisation => { + this.updateFormulaireLocalisation(f.uid, localisation); + }); + } + + public updateLocalisation() { + for (const c of EnumEx.getValues(CalculatorType)) { + const prom: Promise<StringMap> = this.loadLocalisation(c); + prom.then(loc => { + for (const f of this._formulaires) + if (f.calculatorType == c) + this.updateFormulaireLocalisation(f.uid, loc); + } + ); + } + } + private loadConfig(form: FormulaireDefinition, ct: CalculatorType): Promise<Response> { let processData = function (s: string) { form.parseConfig(JSON.parse(s)); @@ -30,28 +89,33 @@ export class FormulaireService { return this.httpService.httpGetRequest(undefined, undefined, undefined, f, processData); } - public loadFormulaire(ct: CalculatorType): Promise<FormulaireDefinition> { + public createFormulaire(ct: CalculatorType): Promise<FormulaireDefinition> { if (ct == undefined) - throw "FormulaireService.getFormulaire() : invalid undefined CalculatorType" + throw "FormulaireService.createFormulaire() : invalid undefined CalculatorType" let f = new FormulaireDefinition(this.paramService, ct); this._formulaires.push(f); - let pr: Promise<FormulaireDefinition> = this.loadConfig(f, ct) - .then(res => { - return f; - }); - return pr; + let prom: Promise<Response> = this.loadConfig(f, ct); + return prom.then(_ => { + return f; + }).then(f => { + this.loadUpdateFormulaireLocalisation(f); + return f; + }).then(f => { + f.applyDependencies(); + return f; + }).then(f => { + this.notifyObservers(f); + return f; + }); } - private getFormulaire(ct: CalculatorType): FormulaireDefinition { - if (ct == undefined) - throw "FormulaireService.getFormulaire() : invalid undefined CalculatorType" - + public getFormulaireFromId(uid: number): FormulaireDefinition { for (let f of this._formulaires) - if (f.type == ct) + if (f.uid == uid) return f; - throw "FormulaireService.getFormulaire() : type '" + ct + "' form is not loaded"; + throw "FormulaireService.getFormulaire() : unkown form id " + uid; } private getFormulaireElementById(formId: number, elemId: string): FormulaireElement { @@ -90,22 +154,8 @@ export class FormulaireService { return undefined; } - /** - * met à jour la langue du formulaire - * @param formId id unique du formulaire - * @param localisation ensemble id-message traduit - */ - public updateLocalisation(formId: number, localisation: StringMap) { - for (let loc_id in localisation) { - let fe = this.getFormulaireElementById(formId, loc_id); - if (fe != undefined) - fe.updateLocalisation(localisation); - } - } - - public getNubAndParameters(ct: CalculatorType): [Nub, ParamsEquation] { - let f = this.getFormulaire(ct); - switch (ct) { + public getNubAndParameters(f: FormulaireDefinition): [Nub, ParamsEquation] { + switch (f.calculatorType) { case CalculatorType.ConduiteDistributrice: { let Q: number = f.getParameterValue("Q"); // débit Q @@ -133,15 +183,13 @@ export class FormulaireService { } default: - throw "FormulaireService.getNubAndParameters() : valeur de CalculatorType " + ct + " non implémentée" + throw "FormulaireService.getNubAndParameters() : valeur de CalculatorType " + f.calculatorType + " non implémentée" } } - public getSectionNubAndParameters(ct: CalculatorType, nt: ComputeNodeType, getY: boolean = true): [acSection, ParamsEquation] { - let f: FormulaireDefinition = this.getFormulaire(ct); + public getSectionNubAndParameters(f: FormulaireDefinition, nt: ComputeNodeType, getY: boolean = true): [acSection, ParamsEquation] { // bief - // let Ks = f.getNodeParameterValue(nt, "Ks"); // Strickler let Ks = f.getParameterValue("Ks"); // Strickler let If: number = f.getParameterValue("If"); // Pente du fond let YB: number = f.getParameterValue("YB"); // Hauteur de berge @@ -208,7 +256,7 @@ export class FormulaireService { } } - public getConfigPathPrefix(ct: CalculatorType): string { + private getConfigPathPrefix(ct: CalculatorType): string { if (ct == undefined) throw "FormulaireService.getConfigPathPrefix() : invalid undefined CalculatorType" diff --git a/src/app/services/observer.ts b/src/app/services/observer.ts index b916f71b3bcad3a926d71dd508451309a2f34f42..8933a7c60f2430d9f4f56f15487d6c07f740a358 100644 --- a/src/app/services/observer.ts +++ b/src/app/services/observer.ts @@ -1,10 +1,8 @@ export interface Observer { - update(data: any): void; + update(sender: any, data: any): void; } -// class Observable<T> { export class Observable { - // private data: T; private _observers: Observer[]; @@ -18,7 +16,7 @@ export class Observable { public notifyObservers(data: any) { for (let o of this._observers) { - o.update(data); + o.update(this, data); } } } diff --git a/src/app/util.ts b/src/app/util.ts index b6777e733836be1e975f1cd23242b5bb7fbb3197..297bda30c95628265de4e338e22e363a23853612 100644 --- a/src/app/util.ts +++ b/src/app/util.ts @@ -4,4 +4,35 @@ export function logObject(obj: {}, m?: string) { console.log(JSON.stringify(obj)); else console.log(m + " " + JSON.stringify(obj)); +} + +/** + * classe d'itérateurs pour les enums + * cf. https://stackoverflow.com/questions/21293063/how-to-programmatically-enumerate-an-enum-type-in-typescript-0-9-5#21294925 + */ +export class EnumEx { + /** + * retourne les noms et les valeurs d'un enum + */ + static getNamesAndValues<T extends number>(e: any) { + return EnumEx.getNames(e).map(n => ({ name: n, value: e[n] as T })); + } + + /** + * retourne les noms d'un enum + */ + static getNames(e: any) { + return EnumEx.getObjValues(e).filter(v => typeof v === "string") as string[]; + } + + /** + * retourne les valeurs d'un enum + */ + static getValues<T extends number>(e: any) { + return EnumEx.getObjValues(e).filter(v => typeof v === "number") as T[]; + } + + private static getObjValues(e: any): (number | string)[] { + return Object.keys(e).map(k => e[k]); + } } \ No newline at end of file diff --git a/src/index.html b/src/index.html index 799c40343da9ac23d68c5079ded026142dd2a805..aa3fc3c95b653b683c8e0696eebb5339af57dbeb 100644 --- a/src/index.html +++ b/src/index.html @@ -2,9 +2,9 @@ <html lang="en"> <head> + <base href="/"> <meta charset="utf-8"> <title>ngHyd - Calculettes hydrauliques</title> - <base href="/"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- <link rel="icon" type="image/x-icon" href="favicon.ico"> -->