Skip to content
Snippets Groups Projects
field-set.component.ts 12.6 KiB
Newer Older
import { Component, Input, Output, EventEmitter, ViewChildren, QueryList, DoCheck } from "@angular/core";
import { ParamRadioConfig } from "../../formulaire/elements/ngparam";
import { FieldSet } from "../../formulaire/elements/fieldset";
import { ParamFieldLineComponent } from "../param-field-line/param-field-line.component";
import { Field } from "../../formulaire/elements/field";
import { InputField } from "../../formulaire/elements/input-field";
import { SelectField } from "../../formulaire/elements/select/select-field";
import { FormulairePab } from "../../formulaire/definition/form-pab";
import { SelectFieldLineComponent } from "../select-field-line/select-field-line.component";
import { FieldsetContainer } from "../../formulaire/elements/fieldset-container";
import { NotificationsService } from "../../services/notifications.service";
import { ApplicationSetupService } from "../../services/app-setup.service";
import { I18nService } from "../../services/internationalisation.service";
mathias.chouet's avatar
mathias.chouet committed

import { sprintf } from "sprintf-js";
import { DefinedBoolean } from "../../util/definedvalue/definedboolean";
@Component({
    selector: "field-set",
    templateUrl: "./field-set.component.html",
    styleUrls: ["./field-set.component.scss"]
export class FieldSetComponent implements DoCheck {
mathias.chouet's avatar
mathias.chouet committed
    /** number of children to add when clicking "add" or "clone" button */
    public childrenToAdd = 1;

    /** flag to show/hide "add" button (and "how many children" select */
    public showAddChildren: boolean = true;

    /** flag to show/hide "move up" and "move down" buttons */
    public showMoveArrows: boolean = true;

    public set fieldSet(fs: FieldSet) {
    public get fields() {
mathias.chouet's avatar
mathias.chouet committed
        return this._fieldSet.kids;
    }

mathias.chouet's avatar
mathias.chouet committed
    public get addManyOptionsList() {
        return Array(20).fill(0).map((value, index) => index + 1);
    }
mathias.chouet's avatar
mathias.chouet committed

    public get title(): string {
mathias.chouet's avatar
mathias.chouet committed
            return "fs undefined";
        }
        if (! this._fieldSet.label) {
mathias.chouet's avatar
mathias.chouet committed
            return "label undefined";
        }
        return this._fieldSet.label;
    }

    public get isValid() {
        return this._isValid.value;
mathias.chouet's avatar
mathias.chouet committed
    }

    /** flag d'affichage des boutons ajouter, supprimer, monter, descendre */
    public get showButtons() {
        return (this._fieldSet.parent instanceof FieldsetContainer);
    }

    /** flag d'activation du bouton monter */
    public get enableUpButton() {
        if (this._fieldSet.parent instanceof FieldsetContainer) {
            return this._fieldSet.parent.getFieldsetPosition(this._fieldSet) !== 0;
        }
        return false;
    }

    /** flag d'activation du bouton descendre */
    public get enableDownButton() {
        if (this._fieldSet.parent instanceof FieldsetContainer) {
            return this._fieldSet.parent.getFieldsetPosition(this._fieldSet) < this._fieldSet.parent.fieldsets.length - 1;
        }
        return false;
    }

    /** flag d'activation du bouton supprimer */
    public get enableRemoveButton() {
        if (this._fieldSet.parent instanceof FieldsetContainer) {
            return this._fieldSet.parent.fieldsets.length > 1;
mathias.chouet's avatar
mathias.chouet committed
    /**
    * field set attribute
    */
    private _fieldSet: FieldSet;

    @ViewChildren(ParamFieldLineComponent)
    private _paramComponents: QueryList<ParamFieldLineComponent>;

    @ViewChildren(SelectFieldLineComponent)
    private _selectModelComponents: QueryList<SelectFieldLineComponent>;
     * événement de changement de valeur d'un input
     */
    @Output()
    private inputChange = new EventEmitter();

     * événement de demande d'ajout d'un fieldset (FieldSet dans un FieldsetContainer)
    /**
     * événement de demande de remontée d'un fieldset dans la liste (FieldSet dans un FieldsetContainer)
     */
    @Output()
    private moveFieldsetUp = new EventEmitter();

    /**
     * événement de demande de descente d'un fieldset dans la liste (FieldSet dans un FieldsetContainer)
     */
    @Output()
    private moveFieldsetDown = new EventEmitter();

    /**
     * événement de demande de suppression d'un fieldset (FieldSet dans un FieldsetContainer)
     */
    @Output()
    private removeFieldset = new EventEmitter();

    /**
     * flag de validité de la saisie
     */
    private _isValid: DefinedBoolean;
mathias.chouet's avatar
mathias.chouet committed
    /**
     * événement de changement d'état d'un radio
     */
    @Output()
    private radio = new EventEmitter<any>();
    /** événement signalant un appui sur TAB ou SHIFT+TAB */
    @Output()
    protected tabPressed = new EventEmitter<any>();

    /**
     * nombre d'appels à DoCheck
     */
    private _DoCheckCount: number = 0;

mathias.chouet's avatar
mathias.chouet committed
    public constructor(
        private notifService: NotificationsService,
        private i18nService: I18nService,
        private appSetupService: ApplicationSetupService
    ) {
        this._isValid = new DefinedBoolean();
    }
mathias.chouet's avatar
mathias.chouet committed

    /**
     * détermine si un Field est du type InputField
     */
    public isInputField(f: Field): boolean {
        return f instanceof InputField && f.isDisplayed;
    }

    /**
     * détermine si un Field est du type SelectField
     */
    public isSelectField(f: Field): boolean {
        return (
            f instanceof SelectField
            && ! (f.parentForm instanceof FormulairePab)
            && f.isDisplayed
        );
    }

     * gestion des événements clic sur les radios :
     * réception d'un message du composant enfant (param-field)
     * cf. https://angular.io/guide/component-interaction#parent-listens-for-child-event
     */
    public onRadioClick(info: any) {
     * calcul de la validité de tous les ParamFieldLineComponent et tous les
     * SelectFieldLineComponent de la vue
    private computeValidity(): boolean {
        let paramsAreValid = true;
        let selectAreValid = true;
mathias.chouet's avatar
mathias.chouet committed
            paramsAreValid = this._paramComponents.reduce<boolean>(
                // callback
                (
                    // accumulator (valeur précédente du résultat)
                    acc,
                    // currentValue (élément courant dans le tableau)
mathias.chouet's avatar
mathias.chouet committed
                    param
mathias.chouet's avatar
mathias.chouet committed
                ): boolean => {
                    return acc && param.isValid;
                }
                // valeur initiale
                , true);
mathias.chouet's avatar
mathias.chouet committed
        }
        if (this._selectModelComponents) {
            selectAreValid = false;
mathias.chouet's avatar
mathias.chouet committed
            selectAreValid = this._selectModelComponents.reduce<boolean>(
                // callback
                (
                    // accumulator (valeur précédente du résultat)
                    acc,
                    // currentValue (élément courant dans le tableau)
mathias.chouet's avatar
mathias.chouet committed
                    select
mathias.chouet's avatar
mathias.chouet committed
                ): boolean => {
                    return acc && select.isValid;
                }
                // valeur initiale
                , true);
        }

        // global validity
        return (paramsAreValid && selectAreValid);
    }

    private updateValidity(forceEmit: boolean = false) {
        this._isValid.value = this.computeValidity();
            this.validChange.emit();
        }
    /**
     * Renvoie l'événement au composant du dessus
     */
    public onTabPressed(event) {
        this.tabPressed.emit(event);
    }

        this._DoCheckCount++;
        // à priori, DoCheck n'est plus utile après quelques cycles de détection de changement
        // puisque la validité du fieldset est déterminée par les saisies dans les inputs
        if (this._DoCheckCount < 3) {
            this.updateValidity(true);
        }
    }

    /**
     * réception d'un événement de validité de ParamFieldLineComponent
     */
    public onParamLineValid(event: boolean) {
    /**
     * réception d'un événement de validité de SelectFieldLineComponent
     */
    public onSelectLineChanged(value:any) {
        this.updateValidity(true);
    }
    

    /**
    * réception d'un événement de changement de valeur d'un input
    */
   public onInputChange($event) {
        this.inputChange.emit($event);
    /**
     * met à jour les paramètres liés
     */
    public updateLinkedParameters() {
        this._paramComponents.forEach(fsc => fsc.updateLinkedParameter());
    }

    public get uitextAddStructure(): string {
        return this.i18nService.localizeText("INFO_FIELDSET_ADD");
    }

    public get uitextCopyStructure(): string {
        return this.i18nService.localizeText("INFO_FIELDSET_COPY");
    }

    public get uitextRemoveStructure(): string {
        return this.i18nService.localizeText("INFO_FIELDSET_REMOVE");
    }

    public get uitextMoveStructureUp(): string {
        return this.i18nService.localizeText("INFO_FIELDSET_MOVE_UP");
    }

    public get uitextMoveStructureDown(): string {
        return this.i18nService.localizeText("INFO_FIELDSET_MOVE_DOWN");
    }

    public onAddClick() {
mathias.chouet's avatar
mathias.chouet committed
        for (let i = 0; i < this.childrenToAdd; i++) {
            this.addFieldset.emit({
                fs: this._fieldSet,
                clone: false
            });
        }
mathias.chouet's avatar
mathias.chouet committed
        let msg: string;
        if (this.childrenToAdd === 1) {
            const cns = this.i18nService.childName(this._fieldSet.nub);
            msg = sprintf(this.i18nService.localizeText("INFO_STUFF_ADDED"), cns);
mathias.chouet's avatar
mathias.chouet committed
        } else {
            const cnp = this.i18nService.childName(this._fieldSet.nub, true);
            msg = sprintf(this.i18nService.localizeText("INFO_STUFF_ADDED_N_TIMES"), this.childrenToAdd, cnp);
mathias.chouet's avatar
mathias.chouet committed
        }
        this.notifService.notify(msg);
mathias.chouet's avatar
mathias.chouet committed
        this.childrenToAdd = 1; // reinit to avoid confusion
    }

    /**
     * clic sur le bouton copier
     */
    public onCopyClick() {
mathias.chouet's avatar
mathias.chouet committed
        for (let i = 0; i < this.childrenToAdd; i++) {
            this.addFieldset.emit({
                fs: this._fieldSet,
                clone: true
            });
        }
mathias.chouet's avatar
mathias.chouet committed
        const pos = (this._fieldSet.parent as FieldsetContainer).getFieldsetPosition(this._fieldSet) + 1;
        let msg: string;
        const cns = capitalize(this.i18nService.childName(this._fieldSet.nub));
mathias.chouet's avatar
mathias.chouet committed
        if (this.childrenToAdd === 1) {
            msg = sprintf(this.i18nService.localizeText("INFO_STUFF_COPIED"), cns, pos);
mathias.chouet's avatar
mathias.chouet committed
        } else {
            msg = sprintf(this.i18nService.localizeText("INFO_STUFF_COPIED_N_TIMES"), cns, pos, this.childrenToAdd);
mathias.chouet's avatar
mathias.chouet committed
        }
        this.notifService.notify(msg);
mathias.chouet's avatar
mathias.chouet committed
        this.childrenToAdd = 1; // reinit to avoid confusion
    public onRemoveClick() {
mathias.chouet's avatar
mathias.chouet committed
        const pos = (this._fieldSet.parent as FieldsetContainer).getFieldsetPosition(this._fieldSet) + 1;
        this.removeFieldset.emit(this._fieldSet);
        const cns = capitalize(this.i18nService.childName(this._fieldSet.nub));
mathias.chouet's avatar
mathias.chouet committed
        this.notifService.notify(
            sprintf(this.i18nService.localizeText("INFO_STUFF_REMOVED"), cns, pos)
mathias.chouet's avatar
mathias.chouet committed
        );
    public onMoveUpClick() {
mathias.chouet's avatar
mathias.chouet committed
        const pos = (this._fieldSet.parent as FieldsetContainer).getFieldsetPosition(this._fieldSet) + 1;
        this.moveFieldsetUp.emit(this._fieldSet);
        const cns = capitalize(this.i18nService.childName(this._fieldSet.nub));
mathias.chouet's avatar
mathias.chouet committed
        this.notifService.notify(
            sprintf(this.i18nService.localizeText("INFO_STUFF_MOVED"), cns, pos)
mathias.chouet's avatar
mathias.chouet committed
        );
    public onMoveDownClick() {
mathias.chouet's avatar
mathias.chouet committed
        const pos = (this._fieldSet.parent as FieldsetContainer).getFieldsetPosition(this._fieldSet) + 1;
        this.moveFieldsetDown.emit(this._fieldSet);
        const cns = capitalize(this.i18nService.childName(this._fieldSet.nub));
mathias.chouet's avatar
mathias.chouet committed
        this.notifService.notify(
            sprintf(this.i18nService.localizeText("INFO_STUFF_MOVED"), cns, pos)
mathias.chouet's avatar
mathias.chouet committed
        );
        window.open("assets/docs/" + this.appSetupService.language + "/calculators/" + this._fieldSet.helpLink, "_blank");
    }

    public get enableHelpButton() {
        return this._fieldSet && this._fieldSet.helpLink;
    }

    public get uitextOpenHelp() {
        return this.i18nService.localizeText("INFO_CALCULATOR_OPEN_HELP");
    }