Skip to content
Snippets Groups Projects
param-field-line.component.ts 10.2 KiB
Newer Older
import { Component, ViewChild, Input, Output, EventEmitter, OnChanges } from "@angular/core";
import { I18nService } from "../../services/internationalisation.service";
import { NgParameter, ParamRadioConfig } from "../../formulaire/elements/ngparam";
import { NgParamInputComponent } from "../ngparam-input/ngparam-input.component";
import { ServiceFactory } from "../../services/service-factory";
import { ParamValueMode, ParallelStructure, ParamCalculability } from "jalhyd";
import { FormulaireService } from "../../services/formulaire.service";
import { ParamLinkComponent } from "../param-link/param-link.component";
mathias.chouet's avatar
mathias.chouet committed
import { ParamValuesComponent } from "../param-values/param-values.component";
/**
 * Sélecteur de mode pour chaque paramètre: fixé, varier, calculer, lié
 */
@Component({
    selector: "param-field-line",
    styleUrls: [
        "./param-field-line.component.scss"
export class ParamFieldLineComponent implements OnChanges {
        this.intlService = ServiceFactory.i18nService;
        this._formService = ServiceFactory.formulaireService;
        this.inputChange = new EventEmitter();
    public get uitextParamFixe() {
        return this.intlService.localizeText("INFO_PARAMFIELD_PARAMFIXE");
    }

    public get uitextParamVarier() {
        return this.intlService.localizeText("INFO_PARAMFIELD_PARAMVARIER");
    }

    public get uitextParamCalculer() {
        return this.intlService.localizeText("INFO_PARAMFIELD_PARAMCALCULER");
    }

    public get uitextParamLie() {
        return this.intlService.localizeText("INFO_PARAMFIELD_PARAMLIE");
    }

    // états booléens des boutons

    public get isRadioFixChecked(): boolean {
        return this.param.radioState === ParamRadioConfig.FIX;
    public get isRadioVarChecked(): boolean {
        return this.param.radioState === ParamRadioConfig.VAR;
    public get isRadioCalChecked(): boolean {
        return this.param.radioState === ParamRadioConfig.CAL;
    }
    public get isRadioLinkChecked(): boolean {
        return this.param.radioState === ParamRadioConfig.LINK;
    /**
     * validité des saisies du composant
     */
    public get isValid(): boolean {
            case ParamRadioConfig.FIX:
mathias.chouet's avatar
mathias.chouet committed
                return this._isInputValid;

            case ParamRadioConfig.VAR:
                return this._isRangeValid;

            case ParamRadioConfig.LINK:
                // at first this._paramLinkComponent is undefined until view is refreshed
                return this._paramLinkComponent ? this._paramLinkComponent.isValid : true;

    public get formHasResults(): boolean {
        return ServiceFactory.formulaireService.currentFormHasResults;
mathias.chouet's avatar
mathias.chouet committed
    }
    public param: NgParameter;
mathias.chouet's avatar
mathias.chouet committed

mathias.chouet's avatar
mathias.chouet committed
    @ViewChild(NgParamInputComponent, { static: true })
mathias.chouet's avatar
mathias.chouet committed
    private _ngParamInputComponent: NgParamInputComponent;

    @ViewChild(ParamValuesComponent)
mathias.chouet's avatar
mathias.chouet committed
    private _paramValuesComponent: ParamValuesComponent;
    @ViewChild(ParamLinkComponent)
mathias.chouet's avatar
mathias.chouet committed
    private _paramLinkComponent: ParamLinkComponent;

    @Output()
    private valid: EventEmitter<void>;
mathias.chouet's avatar
mathias.chouet committed

    @Output()
    private inputChange: EventEmitter<void>;

    /** événement signalant un appui sur TAB ou SHIFT+TAB */
    @Output()
    protected tabPressed = new EventEmitter<any>();

    /** true si la valeur saisie est valide */
mathias.chouet's avatar
mathias.chouet committed
    private _isInputValid = false;

    /** true si le min-max/liste est valide */
mathias.chouet's avatar
mathias.chouet committed
    private _isRangeValid = true;

    private intlService: I18nService;
mathias.chouet's avatar
mathias.chouet committed

    private _formService: FormulaireService;

    /*
     * gestion des événements clic sur les radios :
     * envoi d'un message au composant parent
     * cf. https://angular.io/guide/component-interaction#parent-listens-for-child-event
     */
    @Output()
    private radio = new EventEmitter<any>();
mathias.chouet's avatar
mathias.chouet committed

    /**
     * calcule la présence du radio "paramètre fixé"
     */
    public hasRadioFix(): boolean {
mathias.chouet's avatar
mathias.chouet committed
            case ParamRadioConfig.FIX:
                return this.hasRadioLink(); // gné ?
mathias.chouet's avatar
mathias.chouet committed

            default:
                return true;
        }
    }

    /**
     * calcule la présence du radio "paramètre à varier"
     */
    public hasRadioVar(): boolean {
mathias.chouet's avatar
mathias.chouet committed
            case ParamRadioConfig.VAR:
            case ParamRadioConfig.CAL:
                return true;

            default:
                return false;
        }
    }

    /**
    * calcule la présence du radio "paramètre à calculer"
    */
mathias.chouet's avatar
mathias.chouet committed
    public hasRadioCal(): boolean {
mathias.chouet's avatar
mathias.chouet committed
            case ParamRadioConfig.CAL:
                return true;

            default:
                return false;
        }
    }

    /**
    * calcule la présence du radio "paramètre lié" (importé d'un autre module de calcul)
mathias.chouet's avatar
mathias.chouet committed
    */
mathias.chouet's avatar
mathias.chouet committed
    public hasRadioLink(): boolean {
mathias.chouet's avatar
mathias.chouet committed
        if (this._formService.formulaires.length > 0) {
            // au moins 2 modules de calcul ouverts
mathias.chouet's avatar
mathias.chouet committed
            if (this._formService.formulaires.length > 1) {
                return this._formService.getLinkableValues(this.param).length > 0;
mathias.chouet's avatar
mathias.chouet committed
            }

            // ou un seul module de calcul "ouvrages parallèles"
mathias.chouet's avatar
mathias.chouet committed
            if (this._formService.formulaires[0].currentNub instanceof ParallelStructure) {
                const ps: ParallelStructure = this._formService.formulaires[0].currentNub;
mathias.chouet's avatar
mathias.chouet committed
                if (ps.structures.length > 1) {
                    return this._formService.getLinkableValues(this.param).length > 0;
mathias.chouet's avatar
mathias.chouet committed
    /**
     * Returns true if the current parameter is in CALC mode but no SINGLE
     * parameter is available to take its place
     */
    public canExitCalcMode() {
        let ret = true;
        if (this.param.paramDefinition.isCalculated) {
            const nub = this.param.paramDefinition.parentNub;
            const p = nub.findFirstCalculableParameter(this.param.paramDefinition);
mathias.chouet's avatar
mathias.chouet committed
            ret = (p !== undefined);
        }
        return ret;
    }

    /**
     * Returns true if setting this parameter to Calc mode leads to a links loop
     */
    public get isRadioCalDisabled(): boolean {
        // find all Nubs that have to be calculated for this one to run
        const nub = this.param.paramDefinition.originNub;
        const requiredNubs = nub.getRequiredNubsDeep();
        // if one of those Nubs depends on the parameter we're about to set
        // to Calc mode, then we shouldn't do so
        for (const r of requiredNubs) {
            if (r.dependsOnParameter(this.param.paramDefinition)) {
                return true;
            }
        }
        return false;
    }

    public get radioCalTitle(): string {
        if (this.isRadioCalDisabled) {
            return this.intlService.localizeText("INFO_PARAMFIELD_CANNOT_CALC_LINKS_LOOP");
        }
        return "";
    }

mathias.chouet's avatar
mathias.chouet committed
    public onRadioClick(option: string) {
        const oldValue = this.param.valueMode;
mathias.chouet's avatar
mathias.chouet committed
        switch (option) {
            case "fix":
                this.param.valueMode = ParamValueMode.SINGLE;
mathias.chouet's avatar
mathias.chouet committed
                break;

            case "var":
                // prevent setting LISTE mode back to MINMAX if someone clicks "variable" again
                // after setting variable mode to LISTE
                if (oldValue !== ParamValueMode.MINMAX && oldValue !== ParamValueMode.LISTE) {
                    this.param.valueMode = ParamValueMode.MINMAX; // min/max par défaut
                }
mathias.chouet's avatar
mathias.chouet committed
                if (this._paramValuesComponent) {
                    // re-open modal when clicking the "var" mode button again (PoLS)
                    this._paramValuesComponent.openDialog();
                }
mathias.chouet's avatar
mathias.chouet committed
                break;

            case "cal":
mathias.chouet's avatar
mathias.chouet committed
                this.param.setCalculated(); // sets mode to CALCUL and more
                // did some nasty rascal tick the "create module with empty fields" evil option,
                // then chose to set a DICHO param to CALC mode without setting a value first ?
                if (
                    this.param.paramDefinition.calculability === ParamCalculability.DICHO
                    && this.param.paramDefinition.singleValue === undefined
                ) {
                    // restore dedicated initValue
                    this.param.paramDefinition.singleValue = this.param.paramDefinition.initValue;
                }
mathias.chouet's avatar
mathias.chouet committed
                break;

            case "link":
                this.param.valueMode = ParamValueMode.LINK;
mathias.chouet's avatar
mathias.chouet committed
                break;
        }
mathias.chouet's avatar
mathias.chouet committed
            "oldValueMode": oldValue
        });
        // MAJ validité
        this.emitValidity();
    }

    /**
     * Renvoie l'événement au composant du dessus
     */
    public onTabPressed(event) {
        this.tabPressed.emit(event);
    }

    /**
     * émission d'un événement de validité
     */
    private emitValidity() {
    }

    /**
     * réception d'un événement de NgParamInputComponent
     */
    public onInputChange(event: any) {
        switch (event.action) {
            case "valid":
                this._isInputValid = event.value;
                this.emitValidity();
                break;

            case "model":
        }
    }

    /**
     * réception d'un événement de validité de ParamValuesComponent
     */
mathias.chouet's avatar
mathias.chouet committed
    public onParamValuesValid(event: boolean) {
        this._isRangeValid = event;
mathias.chouet's avatar
mathias.chouet committed
        this.emitValidity();
        this._ngParamInputComponent.model = this.param;
        this._ngParamInputComponent.showError = this.isRadioFixChecked;
    }
francois.grand's avatar
francois.grand committed

    /**
     * relit la valeur dans l'interface et met à jour le NgParameter
     */
    public updateParameterFromUI() {
        this._ngParamInputComponent.updateModelFromUI();
    }

    /**
     * met à jour les paramètres liés
     */
    public updateLinkedParameter() {
mathias.chouet's avatar
mathias.chouet committed
        if (this._paramLinkComponent !== undefined) {
            this._paramLinkComponent.updateParamList();
mathias.chouet's avatar
mathias.chouet committed
        }