import {ChangeDetectorRef, Component, ElementRef, Input, OnChanges, OnInit, SimpleChanges} from '@angular/core'; import { AbstractControl, FormArray, FormControl, FormGroup } from '@angular/forms'; import { VisibilityRulesService } from '@app/ui/misc/dataset-description-form/visibility-rules/visibility-rules.service'; import { BaseComponent } from '@common/base/base.component'; import { takeUntil } from 'rxjs/operators'; @Component({ selector: 'app-form-progress-indication', templateUrl: './form-progress-indication.component.html', styleUrls: ['./form-progress-indication.component.scss'] }) export class FormProgressIndicationComponent extends BaseComponent implements OnInit, OnChanges { @Input() formGroup: FormGroup; @Input() isDmpEditor: boolean; @Input() isDatasetEditor: boolean; @Input() public progressValueAccuracy = 2; determinateProgressValue: number; progressSoFar: number; total: number; percent: number; constructor(private visibilityRulesService: VisibilityRulesService) { super(); } public value = 0; ngOnInit() { this.init(); } ngOnChanges(changes: SimpleChanges) { if(changes.formGroup) { this.init(); } } init() { setTimeout(() => {this.calculateValueForProgressbar();}); this.formGroup .valueChanges .pipe(takeUntil(this._destroyed)) .subscribe(control => { setTimeout(() => {this.calculateValueForProgressbar();}); }); } calculateValueForProgressbar() { if (this.isDmpEditor) { this.progressSoFar = this.countFormControlsValidForProgress(this.formGroup); this.total = this.countFormControlsRequiredFieldsForTotal(this.formGroup); } else if (this.isDatasetEditor) { this.progressSoFar = this.countFormControlsValidForProgress(this.formGroup) + this.countFormControlsWithValueForProgress(this.formGroup); this.total = this.countFormControlsRequiredFieldsForTotal(this.formGroup) + this.CountFormControlDepthLengthFotTotal(this.formGroup); } else { this.progressSoFar = this.countFormControlsWithValueForProgress(this.formGroup); this.total = this.CountFormControlDepthLengthFotTotal(this.formGroup); } this.percent = (this.progressSoFar / this.total) * 100; this.value = Number.parseFloat(this.percent.toPrecision(this.progressValueAccuracy)); } countFormControlsWithValueForProgress(formControl: AbstractControl): number { let valueCurent = 0; if (formControl instanceof FormGroup) { if (this.checkFormsIfIsFieldsAndVisible(formControl) && this.checkIfIsRequired((formControl as FormGroup))) { if (this.hasValue(formControl)) valueCurent++; } if (this.chechFieldIfIsFieldSetAndVisible((formControl as FormGroup)) && this.checkIfIsRequired((formControl as FormGroup))) { valueCurent = valueCurent + this.compositeFieldsGetChildsForProgress(formControl); } else { Object.keys(formControl.controls).forEach(item => { const control = formControl.get(item); valueCurent = valueCurent + this.countFormControlsWithValueForProgress(control); }); } } else if (formControl instanceof FormArray) { formControl.controls.forEach(item => { valueCurent = valueCurent + this.countFormControlsWithValueForProgress(item); }); } return valueCurent; } private hasValue(formGroup: FormGroup): boolean { return formGroup.get('value').valid && formGroup.get('value').value != null && formGroup.get('value').value !== '' && this.visibilityRulesService.checkElementVisibility(formGroup.get('id').value); } private compositeFieldsGetChildsForProgress(formGroup: FormGroup): number { let valueCurent = 0; if (this.visibilityRulesService.checkElementVisibility(formGroup.get('id').value)) { (formGroup.get('fields') as FormArray).controls.forEach((element: FormGroup) => { valueCurent = valueCurent + this.countFormControlsWithValueForProgress(element); }); (formGroup.get('multiplicityItems') as FormArray).controls.forEach((element: FormGroup) => { valueCurent = valueCurent + this.countFormControlsWithValueForProgress(element); }); } return valueCurent; } private checkIfIsRequired(formControl: FormGroup): boolean { return !!(formControl.get('validationRequired') && formControl.get('validationRequired').value); } private checkFormsIfIsFieldsAndVisible(formControl: FormGroup): boolean { if (formControl.contains('id') && formControl.contains('value')) { return true; } return false; } private chechFieldIfIsFieldSetAndVisible(formControl: FormGroup): boolean { if (formControl.contains('id') && formControl.contains('fields')) { return true; } return false; } CountFormControlDepthLengthFotTotal(formControl: AbstractControl): number { let valueCurent = 0; if (formControl instanceof FormArray) { formControl.controls.forEach(item => { valueCurent = valueCurent + this.CountFormControlDepthLengthFotTotal(item); }); } else if (formControl instanceof FormGroup) { if ((formControl as FormGroup).contains('id') && (formControl as FormGroup).contains('value') && (this.visibilityRulesService.checkElementVisibility((formControl as FormGroup).get('id').value)) && this.checkIfIsRequired((formControl as FormGroup))) { valueCurent++; } else if ((formControl as FormGroup).contains('id') && (formControl as FormGroup).contains('fields')) { valueCurent = valueCurent + this.compositeFieldsGetChildsForTotal(formControl); } else { Object.keys(formControl.controls).forEach(item => { const control = formControl.get(item); valueCurent = valueCurent + this.CountFormControlDepthLengthFotTotal(control); }); } } return valueCurent; } private compositeFieldsGetChildsForTotal(formGroup: FormGroup): number { let valueCurent = 0; if (this.visibilityRulesService.checkElementVisibility(formGroup.get('id').value)) { (formGroup.get('fields') as FormArray).controls.forEach((element: FormGroup) => { valueCurent = valueCurent + this.CountFormControlDepthLengthFotTotal(element); }); (formGroup.get('multiplicityItems') as FormArray).controls.forEach((element: FormGroup) => { valueCurent = valueCurent + this.CountFormControlDepthLengthFotTotal(element); }); } return valueCurent; } countFormControlsValidForProgress(formControl: AbstractControl): number { let valueCurrent = 0; if (formControl instanceof FormControl) { if (this.controlRequired(formControl) && this.controlEnabled(formControl) && formControl.valid) { valueCurrent++; } } else if (formControl instanceof FormGroup) { Object.keys(formControl.controls).forEach(item => { const control = formControl.get(item); valueCurrent = valueCurrent + this.countFormControlsValidForProgress(control); }); } else if (formControl instanceof FormArray) { formControl.controls.forEach(item => { valueCurrent = valueCurrent + this.countFormControlsValidForProgress(item); }); } return valueCurrent; } countFormControlsRequiredFieldsForTotal(formControl: AbstractControl): number { let valueCurrent = 0; if (formControl instanceof FormControl) { if (this.controlRequired(formControl) && this.controlEnabled(formControl)) { valueCurrent++; } } else if (formControl instanceof FormGroup) { Object.keys(formControl.controls).forEach(item => { const control = formControl.get(item); valueCurrent = valueCurrent + this.countFormControlsRequiredFieldsForTotal(control); }); } else if (formControl instanceof FormArray) { formControl.controls.forEach(item => { valueCurrent = valueCurrent + this.countFormControlsRequiredFieldsForTotal(item); }); } return valueCurrent; } controlRequired(formControl: AbstractControl) { if (formControl.validator) { const validator = formControl.validator({} as AbstractControl); if (validator && validator.required) { return true; } } else { return false } } controlEnabled(formControl: AbstractControl) { if (formControl.enabled) { return true; } else { return false } } isEditor(): boolean { return this.isDmpEditor || this.isDatasetEditor; } }