argos/dmp-frontend/src/app/ui/admin/description-template/editor/components/visibility-rule/description-template-editor...

254 lines
7.5 KiB
TypeScript

import { Component, Input, OnInit } from '@angular/core';
import { AbstractControl, FormArray, UntypedFormArray, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
import { DescriptionTemplateFieldType } from '@app/core/common/enum/description-template-field-type';
import { DescriptionTemplateRule } from '@app/core/model/description-template/description-template';
import { TranslateService } from '@ngx-translate/core';
import { ToCEntryType } from '../../table-of-contents/description-template-table-of-contents-entry';
import { DescriptionTemplateRuleEditorModel } from '../../description-template-editor.model';
import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model';
@Component({
selector: 'app-description-template-editor-visibility-rule-component',
templateUrl: './description-template-editor-visibility-rule.component.html',
styleUrls: ['./description-template-editor-visibility-rule.component.scss']
})
export class DescriptionTemplateEditorRuleComponent implements OnInit {
@Input() form: UntypedFormArray;
@Input() fieldTypeForCheck: DescriptionTemplateFieldType;
@Input() formArrayOptionsForCheck: UntypedFormArray;
@Input() viewOnly: boolean;
@Input() validationErrorModel: ValidationErrorModel;
@Input() validationRootPath: string;
options: OptionItem[];
sectionOptions: OptionItem[];
fieldSetOptions: OptionItem[];
fieldOptions: OptionItem[];
parentIds: string[] = [];
hiddenBy: string[] = [];
rootForm: AbstractControl = null;
constructor(private language: TranslateService) {
}
isTextType(type: DescriptionTemplateFieldType){
return type == DescriptionTemplateFieldType.FREE_TEXT || type == DescriptionTemplateFieldType.CHECK_BOX ||
type == DescriptionTemplateFieldType.TEXT_AREA || type == DescriptionTemplateFieldType.RICH_TEXT_AREA ||
type == DescriptionTemplateFieldType.BOOLEAN_DECISION || type == DescriptionTemplateFieldType.RADIO_BOX ||
type == DescriptionTemplateFieldType.CURRENCY || type == DescriptionTemplateFieldType.SELECT;
}
isTextListType(type: DescriptionTemplateFieldType){
return type == DescriptionTemplateFieldType.TAGS || type == DescriptionTemplateFieldType.INTERNAL_ENTRIES_DMPS ||
type == DescriptionTemplateFieldType.INTERNAL_ENTRIES_DESCRIPTIONS;
}
isDateType(type: DescriptionTemplateFieldType){
return type == DescriptionTemplateFieldType.DATE_PICKER;
}
isReferenceType(type: DescriptionTemplateFieldType){
return type == DescriptionTemplateFieldType.REFERENCE_TYPES;
}
isExternalIdentifierType(type: DescriptionTemplateFieldType){
return type == DescriptionTemplateFieldType.VALIDATION || type == DescriptionTemplateFieldType.DATASET_IDENTIFIER;;
}
targetValidation() {
//TODO
}
deleteRule(index) {
this.form.removeAt(index);
this.form.controls?.forEach(
(control, index) => DescriptionTemplateRuleEditorModel.reapplyValidators({
formGroup: control as UntypedFormGroup,
rootPath: `${this.validationRootPath}visibilityRules[${index}].`,
validationErrorModel: this.validationErrorModel
})
);
this.form.markAsDirty();//deactivate guard
}
ngOnInit(): void {
this.rootForm = this.findRootForm();
this._computeOptions();
}
private _computeOptions() {
this.options = this.getOptions();
this.sectionOptions = [];
this.fieldOptions = [];
this.fieldSetOptions = [];
this.options.forEach(option => {
switch (option.type) {
case ToCEntryType.Field:
this.fieldOptions.push(option);
break;
case ToCEntryType.FieldSet:
this.fieldSetOptions.push(option);
break;
case ToCEntryType.Section:
this.sectionOptions.push(option);
break;
default:
break;
}
});
//remove options to hide if given fieldset is already hidden by option
this.fieldOptions.forEach(e => this._buildHiddenBy(e));
this.fieldSetOptions.forEach(e => this._buildHiddenBy(e));
this.parentIds = this.computeParentIds();
this.hiddenBy = this.computeHiddenBy();
}
computeOptions(isOpened: boolean) {
if (isOpened) {
this._computeOptions();
}
}
private _buildHiddenBy(fo: OptionItem) {
try {
this.fieldOptions.forEach(foption => {
const rules = (foption.form.get('visibilityRules') as UntypedFormArray).controls.map(c => (c as UntypedFormGroup).getRawValue()) as DescriptionTemplateRule[]
const targets = rules.map(rule => rule.target);
targets.forEach(target => {
if (fo.parentsIds.includes(target) && !fo.hiddenBy.includes(foption.id)) {
fo.hiddenBy.push(...foption.parentsIds);
}
})
});
} catch {
console.log('error');
}
}
findRootForm() {
let currentForm: AbstractControl = this.form;
while (currentForm.parent != null){
currentForm = currentForm.parent;
}
return currentForm;
}
getOptions(): OptionItem[] {
if (this.rootForm) {
const result: OptionItem[] = [];
(this.rootForm.get('definition').get('pages') as UntypedFormArray).controls.forEach(pageForm => {
const sections = pageForm.get('sections') as UntypedFormArray;
if (sections) {
sections.controls.forEach(section => {
const subResult = this.buildOptions(section as UntypedFormGroup, ToCEntryType.Section, []);
result.push(...subResult);
});
}
});
return result;
}
//nothing found
return [];
}
private buildOptions(form: UntypedFormGroup, type: ToCEntryType, parentIds: string[]): OptionItem[] {
const sections = form.get('sections') as UntypedFormArray;
const fieldSets = form.get('fieldSets') as UntypedFormArray;
const fields = form.get('fields') as UntypedFormArray;
const result: OptionItem[] = [];
// parentIds.push(form.get('id').value);
const currentOptionItem: OptionItem = {
id: form.get('id').value,
type: type,
label: type === ToCEntryType.Field ? form.get('data').get('label').value : form.get('title').value,
// parentsIds: [form.get('id').value]
parentsIds: [...parentIds, form.get('id').value],
form: form,
hiddenBy: []
}
result.push(currentOptionItem);
if (sections) {
sections.controls.forEach(section => {
result.push(...this.buildOptions(section as UntypedFormGroup, ToCEntryType.Section, currentOptionItem.parentsIds));
});
}
if (fieldSets) {
fieldSets.controls.forEach(fieldset => {
result.push(...this.buildOptions(fieldset as UntypedFormGroup, ToCEntryType.FieldSet, currentOptionItem.parentsIds));
});
}
if (fields) {
fields.controls.forEach(field => {
result.push(...this.buildOptions(field as UntypedFormGroup, ToCEntryType.Field, currentOptionItem.parentsIds)); //TODO NA TO DOUME
});
}
return result;
}
computeParentIds(): string[] {
if (!this.rootForm.get('id')) return [];
const current = this.options.find(opt => opt.id === this.rootForm.get('id').value);
if (current) {
return current.parentsIds;
}
return [];
}
computeHiddenBy(): string[] {
if (!this.rootForm.get('id')) return [];
const current = this.options.find(opt => opt.id === this.rootForm.get('id').value);
if (current) {
return current.hiddenBy;
}
return [];
}
getToolTipMessage(id: string) {
if (this.parentIds.includes(id)) {
// return 'Cannot hide element that contain the field';
return this.language.instant('DESCRIPTION-TEMPLATE-EDITOR.STEPS.FORM.RULE.HINTS.ELEMENT-CHILD-OF-TARGET');
} else if (this.hiddenBy.includes(id)) {
return this.language.instant('DESCRIPTION-TEMPLATE-EDITOR.STEPS.FORM.RULE.HINTS.ELEMENT-HIDDEN-FROM-ELEMENT');
}
return '';
}
}
interface OptionItem {
id: string,
label: string,
type: ToCEntryType,
parentsIds: string[],
form: UntypedFormGroup,
hiddenBy: string[]
}