-
David Dorchies authored
Refs #635
David Dorchies authoredRefs #635
calculator-list.component.ts 12.87 KiB
import { Component, OnInit, Inject, forwardRef, ElementRef, ViewChild } from "@angular/core";
import { Router, ActivatedRoute } from "@angular/router";
import { CalculatorType, EnumEx, Session } from "jalhyd";
import { FormulaireDefinition } from "../../formulaire/definition/form-definition";
import { ServiceFactory } from "../../services/service-factory";
import { I18nService } from "../../services/internationalisation.service";
import { FormulaireParallelStructure } from "../../formulaire/definition/form-parallel-structures";
import { FieldsetContainer } from "../../formulaire/elements/fieldset-container";
import { FormulairePab } from "../../formulaire/definition/form-pab";
import { HttpService } from "../../services/http.service";
import { AppComponent } from "../../app.component";
import { FormulaireMacrorugoCompound } from "../../formulaire/definition/form-macrorugo-compound";
import { FormulaireSPP } from "../../formulaire/definition/form-spp";
import { ApplicationSetupService } from "../../services/app-setup.service";
@Component({
selector: "list",
templateUrl: "./calculator-list.component.html",
styleUrls: ["./calculator-list.component.scss"]
})
export class CalculatorListComponent implements OnInit {
private _items: any[];
public filteredItems: any[];
/** enable search only if /list/search route was called */
public enableSearch = false;
/** what is typed into the search field in the nav bar */
public searchTerms: string;
@ViewChild("searchField")
private searchField: ElementRef;
constructor(
@Inject(forwardRef(() => AppComponent)) private appComponent: AppComponent,
private router: Router,
private httpService: HttpService,
private intlService: I18nService,
private appSetupService: ApplicationSetupService,
public route: ActivatedRoute
) {
ServiceFactory.i18nService.addObserver(this);
ServiceFactory.applicationSetupService.addObserver(this);
this.searchTerms = "";
this.route.url.subscribe(params => {
if (params.length > 1 && params[1].path === "search") {
this.enableSearch = true;
// focus the new Field
setTimeout(() => {
this.searchField.nativeElement.focus();
}, 0);
}
});
}
/** triggered on init */
private loadCalculatorsThemes() {
this._items = [];
const unusedCalculators = EnumEx.getValues(CalculatorType);
const themes = ServiceFactory.applicationSetupService.themes;
if (themes) {
// group by themes
for (const theme of themes) {
if (theme.name) {
// get theme details from config
const themeTitleKey = "INFO_THEME_" + theme.name + "_TITRE";
const themeDescriptionKey = "INFO_THEME_" + theme.name + "_DESCRIPTION";
const credits = ServiceFactory.i18nService.localizeText("INFO_THEME_CREDITS");
const item = {
title: ServiceFactory.i18nService.localizeText(themeTitleKey),
description: ServiceFactory.i18nService.localizeText(themeDescriptionKey),
image: {
path: "assets/images/themes/" + theme.image.path,
credits: credits + " : " + theme.image.credits
},
calculators: []
};
// get calculators for this theme
for (const calcType of theme.calculators) {
item.calculators.push({
type: calcType,
label: ServiceFactory.formulaireService.getLocalisedTitleFromCalculatorType(calcType),
shortLabel: ServiceFactory.formulaireService.getLocalisedShortTitleFromCalculatorType(calcType),
description: ServiceFactory.formulaireService.getLocalisedDescriptionFromCalculatorType(calcType),
buttonId: "create-calc-" + calcType
});
// mark as used
const index = unusedCalculators.indexOf(calcType);
if (index > -1) {
unusedCalculators.splice(index, 1);
}
}
this._items.push(item);
}
// else special theme for unused calculators
}
// extra card for unused calculators
if (unusedCalculators.length > 0) {
const unusedThemeConfig = themes.find(i => i.name === undefined);
const unusedTheme: any = {};
unusedTheme.calculators = [];
unusedTheme.title = ServiceFactory.i18nService.localizeText("INFO_THEME_MODULES_INUTILISES_TITRE");
unusedTheme.description = ServiceFactory.i18nService.localizeText("INFO_THEME_MODULES_INUTILISES_DESCRIPTION");
unusedTheme.image = {
path: "assets/images/themes/" + unusedThemeConfig.image.path
};
for (const t of unusedCalculators) {
if ( // those sub-Nub types cannot be built outside a parent
! [
CalculatorType.Structure,
CalculatorType.Section,
CalculatorType.CloisonAval,
CalculatorType.YAXN,
CalculatorType.PbBassin,
CalculatorType.PbCloison,
CalculatorType.LechaptCalmon,
CalculatorType.PressureLossLaw
].includes(t)
) {
unusedTheme.calculators.push({
type: t,
label: ServiceFactory.formulaireService.getLocalisedTitleFromCalculatorType(t),
shortLabel: ServiceFactory.formulaireService.getLocalisedShortTitleFromCalculatorType(t),
description: ServiceFactory.formulaireService.getLocalisedDescriptionFromCalculatorType(t),
buttonId: "create-calc-" + t
});
}
}
if (unusedTheme.calculators.length > 0) {
this._items.push(unusedTheme);
} // else the only remaining calculator was "Structure", the one we don't want
}
}
// at first there is no filter, initialize anyway
this.filterItems();
}
public async create(t: CalculatorType) {
const f: FormulaireDefinition = await ServiceFactory.formulaireService.createFormulaire(t);
await this.router.navigate(["/calculator", f.uid]);
// on ajoute un ouvrage après l'ouverture du module de calcul "ouvrages parallèles"
if (f instanceof FormulaireParallelStructure) {
for (const e of f.allFormElements) {
if (e instanceof FieldsetContainer) {
e.addFromTemplate();
break;
}
}
}
// on ajoute un ouvrage après l'ouverture du module de calcul "passe à bassins"
if (f instanceof FormulairePab) {
for (const e of f.allFormElements) {
if (e instanceof FieldsetContainer) {
e.addFromTemplate();
break;
}
}
}
// adding GUI for default apron, in MacroRugoCompound
if (f instanceof FormulaireMacrorugoCompound) {
for (const e of f.allFormElements) {
if (e instanceof FieldsetContainer) {
e.addFromTemplate(0, f.currentNub.getChildren()[0]);
break;
}
}
}
// on ajoute un YAXN après l'ouverture du module de calcul "somme / produit de puissances"
if (f instanceof FormulaireSPP) {
for (const e of f.allFormElements) {
if (e instanceof FieldsetContainer) {
e.addFromTemplate();
break;
}
}
}
}
public get nbOpenCalculators() {
return Session.getInstance().getNumberOfNubs();
}
public resetSearch() {
this.searchTerms = "";
this.filterItems();
}
/**
* Returns calculators grouped by themes, filtered by the search
* terms entered in the navbar's search field in AppComponent
*/
public filterItems() {
if (this.searchTerms === "") {
this.filteredItems = this._items;
} else {
this.filteredItems = JSON.parse(JSON.stringify(this._items));
// filter items based on parent component's search field
for (const i of this.filteredItems) {
i.calculators = i.calculators.filter((c) => {
return this.searchMatches(c.label) || this.searchMatches(c.shortLabel) || this.searchMatches(c.description);
});
}
this.filteredItems = this.filteredItems.filter((i) => {
return (i.calculators.length > 0);
});
}
}
/**
* Returns true if given str matches this.searchTerms: all terms (separated
* by " ") must match, in any order
*/
private searchMatches(str: string): boolean {
let ok = false;
let terms = this.searchTerms.split(" ");
terms = terms.filter(
(item, index) => item !== "" && terms.indexOf(item) === index // deduplicate and remove ""
);
if (terms.length > 1) {
// all terms must match
ok = terms.every((t) => {
return str.toLowerCase().includes(t.toLowerCase());
});
} else if (terms.length > 0) {
ok = (str.toLowerCase().includes(terms[0].toLowerCase()));
} else {
ok = true;
}
return ok;
}
/**
* IMPORTANT: keep in sync with app/examples folder contents
*/
public get exampleFiles() {
return [
{
label: this.intlService.localizeText("INFO_EXAMPLE_LABEL_PAB_COMPLETE"),
path: "pab-complete-chain.json"
},
{
label: this.intlService.localizeText("INFO_EXAMPLE_LABEL_CHANNEL_FLOW"),
path: "solveur-channel-flow.json"
},
{
label: this.intlService.localizeText("INFO_EXAMPLE_LABEL_WEIR_JET_LENGTH"),
path: "weir-jet-length.json"
},
{
label: this.intlService.localizeText("INFO_EXAMPLE_LABEL_PENTE_CRITIQUE_CANAL"),
path: "pente-critique-canal.json"
},
{
label: this.intlService.localizeText("INFO_EXAMPLE_LABEL_PAB_ECH_TRIANG"),
path: "pab-ech-triang.json"
},
{
label: this.intlService.localizeText("INFO_EXAMPLE_LABEL_PERR"),
path: "perr.json"
},
{
label: this.intlService.localizeText("INFO_EXAMPLE_LABEL_PB"),
path: "prebarrage.json"
},
{
label: this.intlService.localizeText("INFO_EXAMPLE_LABEL_RANGEES_PERIOD"),
path: "passe_rangees_periodiques.json"
}
];
}
public async loadExample(path: string) {
const realPath = "app/examples/" + path;
try {
const d = await this.httpService.httpGetBlobRequestPromise(realPath);
const f: any = new Blob([d], { type: "application/json" });
this.appComponent.loadSessionFile(f);
} catch (e) {
console.error("could not load session file", e);
}
}
public get uitextWelcomeTitle() {
return "Cassiopée";
}
public get uitextWelcomeSubtitle() {
return ServiceFactory.i18nService.localizeText("INFO_WELCOME_SUBTITLE");
}
public get uitextWelcomeContent() {
return ServiceFactory.i18nService.localizeText("INFO_WELCOME_CONTENT");
}
public get uitextExamplesTitle() {
return ServiceFactory.i18nService.localizeText("INFO_EXAMPLES_TITLE");
}
public get uitextExamplesSubtitle() {
return ServiceFactory.i18nService.localizeText("INFO_EXAMPLES_SUBTITLE");
}
public get uitextSearchNoResult() {
return ServiceFactory.i18nService.localizeText("INFO_SEARCH_NO_RESULT");
}
// interface Observer
public update(sender: any, data: any): void {
if (sender instanceof I18nService) {
// reload themes if language changed
this.loadCalculatorsThemes();
}
}
public ngOnInit() {
this.loadCalculatorsThemes();
}
}