Forked from HYCAR-Hydro / airGR
Source project has a limited visibility.
app.component.ts 13.74 KiB
import { Component, ApplicationRef, OnInit, OnDestroy, HostListener, ViewChild, ComponentRef } from "@angular/core";
import { Router, Event, NavigationEnd, ActivationEnd } from "@angular/router";
import { MatSidenav, MatToolbar, MatDialog, MatIconRegistry } from "@angular/material";
import { DomSanitizer } from "@angular/platform-browser";
import { Observer, jalhydDateRev, jalhydVersion, CalculatorType, Session } from "jalhyd";
import { environment } from "../environments/environment";
import { I18nService } from "./services/internationalisation/internationalisation.service";
import { ErrorService } from "./services/error/error.service";
import { FormulaireService } from "./services/formulaire/formulaire.service";
import { FormulaireDefinition } from "./formulaire/definition/form-definition";
import { ServiceFactory } from "./services/service-factory";
import { HttpService } from "./services/http/http.service";
import { ApplicationSetupService } from "./services/app-setup/app-setup.service";
import { nghydDateRev, nghydVersion } from "../date_revision";
import { DialogConfirmEmptySessionComponent } from "./components/dialog-confirm-empty-session/dialog-confirm-empty-session.component";
import { DialogLoadSessionComponent } from "./components/dialog-load-session/dialog-load-session.component";
import { DialogSaveSessionComponent } from "./components/dialog-save-session/dialog-save-session.component";
import { NotificationsService } from "./services/notifications/notifications.service";
@Component({
  selector: "nghyd-app",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.scss"],
  providers: [ErrorService]
export class AppComponent implements OnInit, OnDestroy, Observer {
  @ViewChild("sidenav")
  public sidenav: MatSidenav;
  @ViewChild("navbar")
  public navbar: MatToolbar;
  /** current calculator, inferred from _currentFormId by setActiveCalc() (used for navbar menu) */
  public currentCalc: any;
  /**
   * liste des modules de calcul. Forme des objets :
   * "title": nom du module de calcul
   * "uid": id unique du formulaire
  private _calculators: any[] = [];
  /**
   * id du formulaire courant
   * on utilise pas directement FormulaireService.currentFormId pour éviter l'erreur
   * ExpressionChangedAfterItHasBeenCheckedError
  private _currentFormId: string;
  private _innerWidth: number;
  /**
   * composant actuellement affiché par l'élément <router-outlet>
  private _routerCurrentComponent: Component;
  constructor(
    private intlService: I18nService,
    private appSetupService: ApplicationSetupService,
    private appRef: ApplicationRef,
    private errorService: ErrorService,
    private router: Router,
    private formulaireService: FormulaireService,
    private httpService: HttpService,
    private notificationsService: NotificationsService,
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
private confirmEmptySessionDialog: MatDialog, private saveSessionDialog: MatDialog, private loadSessionDialog: MatDialog, private matIconRegistry: MatIconRegistry, private domSanitizer: DomSanitizer ) { ServiceFactory.instance.httpService = httpService; ServiceFactory.instance.applicationSetupService = appSetupService; ServiceFactory.instance.i18nService = intlService; ServiceFactory.instance.formulaireService = formulaireService; ServiceFactory.instance.notificationsService = notificationsService; this.router.events.subscribe((event: Event) => { // close side navigation when clicking a calculator tab if (event instanceof NavigationEnd) { this.sidenav.close(); window.scrollTo(0, 0); } // [de]activate calc tabs depending on loaded route if (event instanceof ActivationEnd) { const path = event.snapshot.url[0].path; if (path === "calculator") { const calcUid = event.snapshot.params.uid; if (this.calculatorExists(calcUid)) { this.setActiveCalc(calcUid); } else { // if required calculator does not exist, redirect to list page this.toList(); } } else { this.setActiveCalc(null); } } }); // icônes personnalisées this.matIconRegistry.addSvgIcon( "file_excel", this.domSanitizer.bypassSecurityTrustResourceUrl("../../assets/icons/file-excel.svg") ); } /** * Triggered at app startup. * Preferences are loaded by app setup service * @see ApplicationSetupService.construct() */ ngOnInit() { this.formulaireService.addObserver(this); this.subscribeErrorService(); this._innerWidth = window.innerWidth; } ngOnDestroy() { this.unsubscribeErrorService(); this.formulaireService.removeObserver(this); } @HostListener("window:resize", ["$event"]) onResize(event) { // keep track of window size for navbar tabs arrangement this._innerWidth = window.innerWidth; } public get uitextSidenavNewCalc() { return this.intlService.localizeText("INFO_MENU_NOUVELLE_CALC"); } public get uitextSidenavParams() { return this.intlService.localizeText("INFO_SETUP_TITLE");
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
} public get uitextSidenavLoadSession() { return this.intlService.localizeText("INFO_MENU_LOAD_SESSION_TITLE"); } public get uitextSidenavSaveSession() { return this.intlService.localizeText("INFO_MENU_SAVE_SESSION_TITLE"); } public get uitextSidenavEmptySession() { return this.intlService.localizeText("INFO_MENU_EMPTY_SESSION_TITLE"); } public get uitextSidenavHelp() { return this.intlService.localizeText("INFO_MENU_HELP_TITLE"); } public get uitextSelectCalc() { return this.intlService.localizeText("INFO_MENU_SELECT_CALC"); } public getCalculatorLabel(t: CalculatorType) { return this.formulaireService.getLocalisedTitleFromCalculatorType(t); } public get calculators() { return this._calculators; } public get currentFormId() { return this._currentFormId; } public setActiveCalc(uid: string) { this._calculators.forEach((calc) => { calc.active = (calc.uid === uid); }); // mark current calc for navbar menu const index = this.getCalculatorIndexFromId(uid); this.currentCalc = this._calculators[index]; } /** * Returns true if sum of open calculator tabs witdh is lower than navbar * available space (ie. if navbar is not overflowing), false otherwise */ public get tabsFitInNavbar() { // manual breakpoints // @WARNING keep in sync with .calculator-buttons sizes in app.component.scss let tabsLimit = 0; if (this._innerWidth > 480) { tabsLimit = 3; } if (this._innerWidth > 640) { tabsLimit = 4; } if (this._innerWidth > 800) { tabsLimit = 6; } /*if (this._innerWidth > 1200) { tabsLimit = 8; }*/ const fits = this._calculators.length <= tabsLimit; return fits; } /** * abonnement au service d'erreurs
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
*/ private subscribeErrorService() { this.errorService.addObserver(this); } private unsubscribeErrorService() { this.errorService.removeObserver(this); } // interface Observer update(sender: any, data: any): void { if (sender instanceof FormulaireService) { switch (data["action"]) { case "createForm": // add newly created form to calculators list const f: FormulaireDefinition = data["form"]; this._calculators.push( { "title": f.calculatorName, "type": f.calculatorType, "uid": f.uid } ); // abonnement en tant qu'observateur du nouveau formulaire f.addObserver(this); break; case "invalidFormId": this.toList(); break; case "currentFormChanged": this._currentFormId = data["formId"]; break; case "saveForm": this.saveForm(data["form"]); break; case "closeForm": const form: FormulaireDefinition = data["form"]; this.closeCalculator(form); break; } } else if (sender instanceof FormulaireDefinition) { switch (data["action"]) { case "nameChanged": this.updateCalculatorTitle(sender, data["name"]); break; } } } /** * Returns true if a form having "formUid" as UID exists * @param formId UID to look for */ private calculatorExists(formId: string): boolean { return (this.getCalculatorIndexFromId(formId) > -1); } private getCalculatorIndexFromId(formId: string) { const index = this._calculators.reduce((resultIndex, calc, currIndex) => { if (resultIndex === -1 && calc["uid"] === formId) { resultIndex = currIndex; } return resultIndex; }, -1);
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
return index; } private updateCalculatorTitle(f: FormulaireDefinition, title: string) { const formIndex = this.getCalculatorIndexFromId(f.uid); this._calculators[formIndex]["title"] = title; } /** * Saves a JSON serialised session file, for one or more calc modules * @param calcList modules to save * @param filename */ private saveSession(calcList: any[], filename) { const elems = []; const serialiseOptions: { [key: string]: {} } = {}; for (const c of calcList) { if (c.selected) { serialiseOptions[c.uid] = { // GUI-dependent metadata to add to the session file title: c.title }; } } const session: string = Session.getInstance().serialise(serialiseOptions); this.formulaireService.downloadTextFile(session, filename); } /** * Supprime un module de calcul **de l'interface** * ATTENTION, ne supprime pas le module de calcul en mémoire ! * Pour cela, utiliser FormulaireService.requestCloseForm(form.uid); * @param form module de calcul à fermer */ private closeCalculator(form: FormulaireDefinition) { const formId: string = form.uid; // désabonnement en tant qu'observateur form.removeObserver(this); // recherche du module de calcul correspondant à formId const closedIndex = this.getCalculatorIndexFromId(formId); /* * détermination du nouveau module de calcul à afficher : * - celui après celui supprimé * - ou celui avant celui supprimé si on supprime le dernier */ let newId = null; const l = this._calculators.length; if (l > 1) { if (closedIndex === l - 1) { newId = this._calculators[closedIndex - 1]["uid"]; } else { newId = this._calculators[closedIndex + 1]["uid"]; } } // suppression this._calculators = this._calculators.filter(calc => { return formId !== calc["uid"]; }); // MAJ affichage if (newId === null) { this.toList(); this._currentFormId = null; } else { this.toCalc(newId);
351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
} } private toList() { this.router.navigate(["/list"]); } private toCalc(id: string) { this.router.navigate(["/calculator", id]); this.setActiveCalc(id); } /** * récupération du composant affiché par le routeur */ public onRouterOutletActivated(a) { this._routerCurrentComponent = a; } /** * restarts a fresh session by closing all calculators */ public emptySession() { const dialogRef = this.confirmEmptySessionDialog.open( DialogConfirmEmptySessionComponent, { disableClose: true } ); dialogRef.afterClosed().subscribe(result => { if (result) { this.doEmptySession(); } }); } public doEmptySession() { for (const c of this._calculators) { const form = this.formulaireService.getFormulaireFromId(c.uid); this.formulaireService.requestCloseForm(form.uid); } // just to be sure, get rid of any Nub possibly stuck in session without any form attached Session.getInstance().clear(); } public loadSession() { // création du dialogue de sélection des formulaires à sauver const dialogRef = this.loadSessionDialog.open( DialogLoadSessionComponent, { disableClose: true } ); dialogRef.afterClosed().subscribe(result => { if (result) { if (result.emptySession) { this.doEmptySession(); } this.formulaireService.loadSession(result.file, result.calculators); } }); } public get revisionInfo(): any { return { jalhyd: { date: jalhydDateRev, version: jalhydVersion, }, nghyd: { date: nghydDateRev, version: nghydVersion } };
421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
} /** * sauvegarde du/des formulaires * @param form formulaire à sélectionner par défaut dans la liste */ public saveForm(form?: FormulaireDefinition) { // liste des formulaires const list = []; for (const c of this._calculators) { const uid = c["uid"]; list.push({ "selected": form ? (uid === form.uid) : true, "title": c["title"], "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; // ajout extension ".json" const re = /.+\.json/; const match = re.exec(name.toLowerCase()); if (match === null) { name = name + ".json"; } this.saveSession(result.calculators, name); } }); } /** * détection de la fermeture de la page/navigateur et demande de confirmation */ @HostListener("window:beforeunload", ["$event"]) confirmExit($event) { if (environment.production) { // affecter une valeur différente de null provoque l'affichage d'un dialogue de confirmation, mais le texte n'est pas affiché $event.returnValue = "Your data will be lost !"; } } }