All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src.app.shared.components.dataset.forms-data-grid.forms-data-grid.component.ts Maven / Gradle / Ivy

The newest version!
/*
 * SPDX-FileCopyrightText: 2017-2024 Enedis
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 */

import { Component, forwardRef, Input } from '@angular/core';
import {
    AbstractControl,
    ControlValueAccessor,
    FormArray,
    FormBuilder,
    FormControl,
    FormGroup,
    NG_VALIDATORS,
    NG_VALUE_ACCESSOR,
    UntypedFormArray,
    ValidationErrors
} from '@angular/forms';
import { KeyValue } from '@model';
import { FileSaverService } from 'ngx-filesaver';

@Component({
    selector: 'chutney-forms-data-grid',
    templateUrl: './forms-data-grid.component.html',
    styleUrls: ['./forms-data-grid.component.scss'],
    providers: [
        {
            provide: NG_VALUE_ACCESSOR,
            useExisting: forwardRef(() => FormsDataGridComponent),
            multi: true
        },
        {
            provide: NG_VALIDATORS,
            useExisting: forwardRef(() => FormsDataGridComponent),
            multi: true
        }
    ]
})
export class FormsDataGridComponent implements ControlValueAccessor {

    dataGridForm: FormArray;
    headers: FormArray = this.fb.array([]);
    @Input() enableImportExport: boolean;

    constructor(private fb: FormBuilder,
                private fileSaverService: FileSaverService) {
        this.dataGridForm = this.fb.array([]);
    }

    // Columns

    updateHeader(col: number, newHeader: string) {
        const lines = this.dataGridForm.controls;
        lines.forEach((line: FormArray) => {
            let cell = line.controls[col];
            cell.patchValue(new KeyValue(newHeader, cell.value.value));
        });
    }

    addColumn() {
        if (this.thereIsNoLine()) {
            this.insertLine(this.createLine([]))
        }

        this.headers.push(this.fb.control(''));
        this.dataGridForm.controls.forEach((line: FormArray) => {
            line.push(this.createKeyValue('', ''));
            line.updateValueAndValidity();
        });
        this.dataGridForm.updateValueAndValidity();
    }

    private thereIsNoLine() {
        return this.dataGridForm.controls.length === 0;
    }

    removeColumn(col: number) {
        this.headers.removeAt(col);
        this.dataGridForm.controls.forEach((line: FormArray) => {
            line.removeAt(col);
        });

        if (this.isLastColumn()) {
            this.clearForm()
        }
    }

    private isLastColumn() {
        return !this.dataGridForm.value.some((element) => element.length > 0);
    }

    private clearForm() {
        this.headers.clear();
        while (this.dataGridForm.length !== 0) {
            this.dataGridForm.removeAt(0)
        }
    }

    // Lines

    addLine() {
        if (this.thereIsNoHeader()) {
            this.headers.push(this.fb.control(''));
        }

        let line: Array = this.headers.value.map(h => {
            return new KeyValue(h, '');
        });
        this.insertLine(this.createLine(line));
    }

    private thereIsNoHeader() {
        return this.headers.length === 0;
    }

    removeLine(i: number) {
        this.dataGridForm.removeAt(i);
    }

    // Import / Export

    exportMultiKeyValue() {
        const fileName = 'chutney_dataset_multi_keyvalues.csv';
        let fileContent = '';
        const delimiter = ';';

        fileContent = this.headerLine(delimiter);

        this.dataGridForm.value
            .map(line => {
                let lineContent = '\n';
                line.forEach(kv => {
                    lineContent += kv.value + delimiter;
                });
                return lineContent;
            })
            .forEach(line => fileContent += line  );

        this.fileSaverService.saveText(fileContent, fileName);
    }

    private headerLine(delimiter: string) {
        let headerLine = '';
        this.headers.value.forEach(header => {
            headerLine += header + delimiter;
        });
        return headerLine;
    }

    importMultiKeyValue(files: any) {
        const file = files.item(0);
        const fileReader = new FileReader();
        fileReader.onload = (e) => {
            this.clearForm();
            const content = '' + fileReader.result;
            const lines = content.split('\n');

            this.headers = this.fb.array(this.cleanLastSemicolon(lines.shift()).split(';')
                .map(header => this.fb.control(header)));

            lines.forEach(l => {
                const lineValues = this.cleanLastSemicolon(l).split(';');

                const kv = this.headers
                    .value
                    .map( (header, i) => [header, lineValues[i]])
                    .map( ([key, value]) => new KeyValue(key, value) );

                this.insertLine(this.createLine(kv));
            });

            this.dataGridForm.enable();
        };
        fileReader.readAsText(file);
    }

    private cleanLastSemicolon(value: string): string{
        if(value.length > 0 && value[value.length - 1] === ';') {
            value = value.slice(0, value.length - 1);
        }
        return value;
    }

    // CVA
    onChanged: any = () => {
    };

    onTouched: any = () => {
    };

    propagateChange: any = () => {
    };

    writeValue(val: Array>): void {
        this.clearForm();
        if (val != null && val.length > 0) {
            if (this.dataGridForm.length === 0) {
                val.map(l => this.createLine(l))
                   .forEach(l => this.insertLine(l));
            }

            this.headers = this.fb.array(this.getHeaders().map(header => this.fb.control(header)))
        }
    }

    private getHeaders(): Array {
        if (this.dataGridForm.length > 0) {
            return this.dataGridForm.controls[0].value.map(kv => kv.key);
        }
        return [];
    }

    private createLine(line: Array): FormArray {
        let lineArray = this.fb.array([]) as UntypedFormArray;
        line.map(kv => this.createKeyValue(kv.key, kv.value))
            .forEach(cell => {
                lineArray.push(cell);
            });
        return lineArray;
    }

    private createKeyValue(key?: string, value?: string): FormGroup {
        return this.fb.group({
            key: key ? key : '',
            value: value ? value : ''
        });
    }

    private insertLine(line: FormArray, i?: number) {
        if (i == null) {
            i = this.dataGridForm.length;
        }

        this.dataGridForm.insert(i, line);
    }

    registerOnChange(fn: any): void {
        this.propagateChange = fn;
        this.dataGridForm.valueChanges.subscribe(fn);
    }

    registerOnTouched(fn: any): void {
        this.onTouched = fn;
    }

    setDisabledState?(isDisabled: boolean): void {
        isDisabled ? this.dataGridForm.disable() : this.dataGridForm.enable();
    }

    validate(c: AbstractControl): ValidationErrors | null {
        return this.dataGridForm.valid ? null : {
            invalidForm: {
                valid: false,
                message: 'fields are invalid'
            }
        };
    }

    protected readonly FormControl = FormControl;
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy