|
|
|
@ -1,454 +1,577 @@
|
|
|
|
|
import { ApplicationRef, Injectable, NgZone } from '@angular/core';
|
|
|
|
|
import { AbstractControl, UntypedFormArray, UntypedFormGroup } from '@angular/forms';
|
|
|
|
|
import { isNumeric } from '@app/utilities/enhancers/utils';
|
|
|
|
|
import { Injectable } from '@angular/core';
|
|
|
|
|
import { AbstractControl } from '@angular/forms';
|
|
|
|
|
import { Observable, Subject } from 'rxjs';
|
|
|
|
|
import { VisibilityRule } from './models/visibility-rule';
|
|
|
|
|
import { VisibilityRuleSource } from './models/visibility-rule-source';
|
|
|
|
|
import { VisibilityRulesContext } from './models/visibility-rules-context';
|
|
|
|
|
import { DescriptionTemplate, DescriptionTemplatePage, DescriptionTemplateSection } from '@app/core/model/description-template/description-template';
|
|
|
|
|
import { Rule } from './models/rule';
|
|
|
|
|
import { DescriptionTemplateDefinition, DescriptionTemplateField, DescriptionTemplateFieldSet, DescriptionTemplatePage, DescriptionTemplateSection } from '@app/core/model/description-template/description-template';
|
|
|
|
|
import { RuleWithTarget } from './models/rule';
|
|
|
|
|
import { FormService } from '@common/forms/form-service';
|
|
|
|
|
import { DescriptionFieldPersist, DescriptionPropertyDefinitionFieldSetPersist, DescriptionPropertyDefinitionPersist } from '@app/core/model/description/description';
|
|
|
|
|
import { DescriptionTemplateFieldType } from '@app/core/common/enum/description-template-field-type';
|
|
|
|
|
|
|
|
|
|
@Injectable()
|
|
|
|
|
export class VisibilityRulesService {
|
|
|
|
|
|
|
|
|
|
private readonly VISIBILITY_RULE_LOGIC: 'OR' | 'AND' = 'OR';
|
|
|
|
|
private readonly DEFAULTVISIBILITY = false;
|
|
|
|
|
|
|
|
|
|
private visibilityRuleContext: VisibilityRulesContext;
|
|
|
|
|
private form: AbstractControl;
|
|
|
|
|
private definition: DescriptionTemplateDefinition;
|
|
|
|
|
private rulesBySources: Map<String, RuleWithTarget[]> ;
|
|
|
|
|
public isVisibleMap: { [key: string]: boolean } = null;
|
|
|
|
|
private _isVisibleMap: { [key: string]: boolean } = null;
|
|
|
|
|
|
|
|
|
|
public isVisibleMap: { [key: string]: boolean } = {};
|
|
|
|
|
|
|
|
|
|
private elementVisibilityMapSubject = new Subject<{ [key: string]: boolean }>();
|
|
|
|
|
private elementComputationalMap = new Map<String, Map<String, boolean>>(); /// keep saved the values of each form control validity value
|
|
|
|
|
private _changeMade$ = new Subject<void>();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// get isVisibleMap(): MapWithDefault {
|
|
|
|
|
// // console.log('isVisibleMap');
|
|
|
|
|
// return this.elementVisibilityMap;
|
|
|
|
|
|
|
|
|
|
// }; /// keep saved the values of each form control validity value
|
|
|
|
|
private allDescriptionTemplateFields: DescriptionTemplateField[] = null;
|
|
|
|
|
private allDescriptionTemplateFieldSets: DescriptionTemplateFieldSet[] = null;
|
|
|
|
|
|
|
|
|
|
constructor(
|
|
|
|
|
public applicationReference: ApplicationRef,
|
|
|
|
|
public ngZone: NgZone
|
|
|
|
|
protected formService: FormService
|
|
|
|
|
) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public setContext(definition: DescriptionTemplateDefinition, form: AbstractControl) {
|
|
|
|
|
this.definition = definition;
|
|
|
|
|
this.form = form;
|
|
|
|
|
this.allDescriptionTemplateFields = null;
|
|
|
|
|
this.allDescriptionTemplateFieldSets = null;
|
|
|
|
|
this.rulesBySources = null;
|
|
|
|
|
this._isVisibleMap = null;
|
|
|
|
|
this.calculateVisibility();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
getElementVisibilityMapObservable(): Observable<{ [key: string]: boolean }> {
|
|
|
|
|
// this.isVisibleMap
|
|
|
|
|
// console.log('getElementVisibilityMapObservable: ');
|
|
|
|
|
return this.elementVisibilityMapSubject.asObservable();
|
|
|
|
|
public buildVisibilityKey(id: string, ordinal: number | null): string {
|
|
|
|
|
if (ordinal == null) return id;
|
|
|
|
|
else return id + "_" + ordinal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public checkElementVisibility(id: string): boolean {
|
|
|
|
|
//console.log('checkElementVisibility: ' + id);
|
|
|
|
|
return true;
|
|
|
|
|
// if (this.visibilityRuleContext.rules.filter(item => item.targetControlId === id).length === 0) { return true; }
|
|
|
|
|
// console.log(this.elementVisibilityMap.has(id) ? this.elementVisibilityMap.get(id) : false);
|
|
|
|
|
// return this.elementVisibilityMap.has(id) ? this.elementVisibilityMap.get(id) : false;
|
|
|
|
|
public isVisible(id: string, ordinal: number | null): boolean {
|
|
|
|
|
this.calculateVisibility();
|
|
|
|
|
const fieldKey = this.buildVisibilityKey(id, ordinal);
|
|
|
|
|
return this.isVisibleMap[fieldKey] ?? false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public buildVisibilityRules(item: Array<Rule>, form: AbstractControl) {
|
|
|
|
|
this.visibilityRuleContext = new VisibilityRulesContext();
|
|
|
|
|
this.visibilityRuleContext.buildVisibilityRuleContext(item || []);
|
|
|
|
|
this.form = form;
|
|
|
|
|
this.resetVisibilityRules();
|
|
|
|
|
public getVisibilityStates(): { [key: string]: boolean } {
|
|
|
|
|
this.calculateVisibility();
|
|
|
|
|
return this.isVisibleMap;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public updateValueAndVisibility(id: string, value: any) {
|
|
|
|
|
//console.log('updateValueAndVisibility: ' + id + ' value: ' + value);
|
|
|
|
|
const visibilityRules = this.visibilityRuleContext.rules.filter(item => item.sourceVisibilityRules.filter(source => source.sourceControlId === id).length > 0);
|
|
|
|
|
if (visibilityRules.length > 0) {
|
|
|
|
|
visibilityRules.forEach(item => this.evaluateVisibility(item, value, id));
|
|
|
|
|
this.elementVisibilityMapSubject.next(this.isVisibleMap);
|
|
|
|
|
public updateVisibilityForSource(id: string) {
|
|
|
|
|
const visibilityRules = this.rulesBySources.has(id) ? this.rulesBySources.get(id) : null;
|
|
|
|
|
if (visibilityRules && visibilityRules.length > 0) {
|
|
|
|
|
this.reloadVisibility();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private evaluateVisibility(visibilityRule: VisibilityRule, value: any, sourceId: string) {// source controlId is the same
|
|
|
|
|
//console.log('evaluateVisibility: ' + visibilityRule + ' value: ' + value + ' sourceId: ' + sourceId);
|
|
|
|
|
|
|
|
|
|
const targetId = visibilityRule.targetControlId;
|
|
|
|
|
const visibilityMap = this.elementComputationalMap.get(targetId) ? this.elementComputationalMap.get(targetId) : new Map<String, boolean>();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (value instanceof Array) {
|
|
|
|
|
|
|
|
|
|
const parsedSourceControlValues = visibilityRule.sourceVisibilityRules.map(e => this.parseValue(e.sourceControlValue));
|
|
|
|
|
const parsedValues = value.map(e => this.parseValue(e));
|
|
|
|
|
|
|
|
|
|
const isVisible = parsedValues.map(v => parsedSourceControlValues.includes(v)).reduce((acc, current) => acc || current, false);
|
|
|
|
|
|
|
|
|
|
public reloadVisibility() {
|
|
|
|
|
this.rulesBySources = null;
|
|
|
|
|
this._isVisibleMap = null;
|
|
|
|
|
this.calculateVisibility();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if(isVisible){
|
|
|
|
|
// this._emitChangesIfNeeded(visibilityRule.targetControlId, true);
|
|
|
|
|
// this.elementVisibilityMap.set(visibilityRule.targetControlId, true);
|
|
|
|
|
// return;
|
|
|
|
|
// }
|
|
|
|
|
visibilityMap.set(sourceId, isVisible);
|
|
|
|
|
private calculateVisibility(){
|
|
|
|
|
if (this._isVisibleMap != null) return;
|
|
|
|
|
if (this.definition == null || this.form == null) return;
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
const visibilityDependencySource = visibilityRule.sourceVisibilityRules.filter(x => x.sourceControlId === sourceId);
|
|
|
|
|
this.initRules();
|
|
|
|
|
const propertyDefinition: DescriptionPropertyDefinitionPersist = this.formService.getValue(this.form.getRawValue()) as DescriptionPropertyDefinitionPersist;
|
|
|
|
|
|
|
|
|
|
const shouldBeVisible = visibilityDependencySource.reduce((isVisible, x) => {
|
|
|
|
|
this.buildTargetVisibility(propertyDefinition);
|
|
|
|
|
this.expandVisibilityToChildren(propertyDefinition);
|
|
|
|
|
this.setDefaultVisibilityForNotCaclucted(propertyDefinition);
|
|
|
|
|
this.hideParentIfAllChildrenAreHidden(propertyDefinition);
|
|
|
|
|
this.ensureFieldSetVisibility(propertyDefinition);
|
|
|
|
|
this.isVisibleMap = this._isVisibleMap;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const shouldBeHidden = value !== null && (this.parseValue(value) !== this.parseValue(x.sourceControlValue));
|
|
|
|
|
return this.VISIBILITY_RULE_LOGIC === 'OR' ? (isVisible || !shouldBeHidden) : (isVisible && !shouldBeHidden);
|
|
|
|
|
// if(value !== null && )
|
|
|
|
|
}, this.VISIBILITY_RULE_LOGIC === 'AND');
|
|
|
|
|
visibilityMap.set(sourceId, shouldBeVisible);
|
|
|
|
|
private initRules(){
|
|
|
|
|
if (this.definition == null || this.form == null) return;
|
|
|
|
|
if (this.rulesBySources != null) return;
|
|
|
|
|
this.rulesBySources = new Map();
|
|
|
|
|
|
|
|
|
|
const fields: DescriptionTemplateField[] = this.getAllDescriptionTemplateDefinitionFields(this.definition);
|
|
|
|
|
for (let i = 0; i < fields.length; i++) {
|
|
|
|
|
const fieldEntity = fields[i];
|
|
|
|
|
if (fieldEntity.visibilityRules != null && fieldEntity.visibilityRules.length > 0) {
|
|
|
|
|
for (let j = 0; j < fieldEntity.visibilityRules.length; j++) {
|
|
|
|
|
const rule = fieldEntity.visibilityRules[j];
|
|
|
|
|
if (!this.rulesBySources.has(fieldEntity.id)) this.rulesBySources.set(fieldEntity.id, []);
|
|
|
|
|
const ruleWithTarget: RuleWithTarget = new RuleWithTarget(fieldEntity.id, rule, fieldEntity);
|
|
|
|
|
this.rulesBySources.get(fieldEntity.id).push(ruleWithTarget);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private getDescriptionTemplateDefinitionFieldById(definition: DescriptionTemplateDefinition, fieldId: string): DescriptionTemplateField[] {
|
|
|
|
|
const fields: DescriptionTemplateField[] = this.getAllDescriptionTemplateDefinitionFields(definition);
|
|
|
|
|
return fields.filter(x=> x.id == fieldId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.elementComputationalMap.set(targetId, visibilityMap);// unnessecary
|
|
|
|
|
|
|
|
|
|
private getAllDescriptionTemplateDefinitionFields(definition: DescriptionTemplateDefinition): DescriptionTemplateField[] {
|
|
|
|
|
if (this.allDescriptionTemplateFields != null) return this.allDescriptionTemplateFields;
|
|
|
|
|
|
|
|
|
|
const isVisible = this._computeVisibility(targetId);
|
|
|
|
|
this._emitChangesIfNeeded(targetId, isVisible);
|
|
|
|
|
const previousVisibility = this.isVisibleMap[targetId];
|
|
|
|
|
this.isVisibleMap[targetId] = isVisible;
|
|
|
|
|
let fields: DescriptionTemplateField[] = [];
|
|
|
|
|
if (definition.pages == null) return fields;
|
|
|
|
|
for (let i = 0; i < definition.pages.length; i++) {
|
|
|
|
|
const item = definition.pages[i];
|
|
|
|
|
fields = [...fields, ...this.getAllDescriptionTemplatePageFields(item)];
|
|
|
|
|
}
|
|
|
|
|
this.allDescriptionTemplateFields = fields;
|
|
|
|
|
return this.allDescriptionTemplateFields;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!isVisible && previousVisibility !== isVisible) {
|
|
|
|
|
this.resetControlWithId(this.form, targetId);
|
|
|
|
|
private getAllDescriptionTemplatePageFields(definition: DescriptionTemplatePage): DescriptionTemplateField[] {
|
|
|
|
|
let fields: DescriptionTemplateField[] = [];
|
|
|
|
|
if (definition.sections == null) return fields;
|
|
|
|
|
for (let i = 0; i < definition.sections.length; i++) {
|
|
|
|
|
const item = definition.sections[i];
|
|
|
|
|
fields = [...fields, ...this.getAllDescriptionTemplateSectionFields(item)];
|
|
|
|
|
}
|
|
|
|
|
return fields;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private getAllDescriptionTemplateSectionFields(definition: DescriptionTemplateSection): DescriptionTemplateField[] {
|
|
|
|
|
let fields: DescriptionTemplateField[] = [];
|
|
|
|
|
if (definition.sections != null) {
|
|
|
|
|
for (let i = 0; i < definition.sections.length; i++) {
|
|
|
|
|
const item = definition.sections[i];
|
|
|
|
|
fields = [...fields, ...this.getAllDescriptionTemplateSectionFields(item)];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (definition.fieldSets != null) {
|
|
|
|
|
for (let i = 0; i < definition.fieldSets.length; i++) {
|
|
|
|
|
const item = definition.fieldSets[i];
|
|
|
|
|
fields = [...fields, ...this.getAllDescriptionTemplateFieldSetFields(item)];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return fields;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// for (let i = 0; i < visibilityRule.sourceVisibilityRules.length; i++) {
|
|
|
|
|
// if (value != null && (this.parseValue(value) !== this.parseValue(visibilityRule.sourceVisibilityRules[i].sourceControlValue))) {
|
|
|
|
|
// this._emitChangesIfNeeded(visibilityRule.targetControlId, false);
|
|
|
|
|
// this.elementVisibilityMap.set(visibilityRule.targetControlId, false);
|
|
|
|
|
// this.resetControlWithId(this.form, visibilityRule.targetControlId);
|
|
|
|
|
// //this.updateValueAndVisibility(visibilityRule.targetControlId, null);
|
|
|
|
|
// // this.clearValues(targetPathKey);
|
|
|
|
|
// return;
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
// this._emitChangesIfNeeded(visibilityRule.targetControlId, true);
|
|
|
|
|
// this.elementVisibilityMap.set(visibilityRule.targetControlId, true);
|
|
|
|
|
private getAllDescriptionTemplateFieldSetFields(definition: DescriptionTemplateFieldSet): DescriptionTemplateField[] {
|
|
|
|
|
return definition.fields == null ? [] : definition.fields;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// this.updateValueAndVisibility(visibilityRule.targetControlId, null);
|
|
|
|
|
private getDescriptionTemplateDefinitionFieldSetById(definition: DescriptionTemplateDefinition, fieldSetId: string): DescriptionTemplateFieldSet[] {
|
|
|
|
|
const fieldSets: DescriptionTemplateFieldSet[] = this.getAllDescriptionTemplateDefinitionFieldSets(definition);
|
|
|
|
|
return fieldSets.filter(x=> x.id == fieldSetId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private getAllDescriptionTemplateDefinitionFieldSets(definition: DescriptionTemplateDefinition): DescriptionTemplateFieldSet[] {
|
|
|
|
|
if (this.allDescriptionTemplateFieldSets != null) return this.allDescriptionTemplateFieldSets;
|
|
|
|
|
let fieldSets: DescriptionTemplateFieldSet[] = [];
|
|
|
|
|
if (definition.pages == null) return fieldSets;
|
|
|
|
|
for (let i = 0; i < definition.pages.length; i++) {
|
|
|
|
|
const item = definition.pages[i];
|
|
|
|
|
fieldSets = [...fieldSets, ...this.getAllDescriptionTemplatePageFieldSets(item)];
|
|
|
|
|
}
|
|
|
|
|
this.allDescriptionTemplateFieldSets = fieldSets;
|
|
|
|
|
return this.allDescriptionTemplateFieldSets;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private _computeVisibility(targetId: string): boolean {
|
|
|
|
|
//console.log('_computeVisibility: ' + targetId);
|
|
|
|
|
private getAllDescriptionTemplatePageFieldSets(definition: DescriptionTemplatePage): DescriptionTemplateFieldSet[] {
|
|
|
|
|
let fieldSets: DescriptionTemplateFieldSet[] = [];
|
|
|
|
|
if (definition.sections == null) return fieldSets;
|
|
|
|
|
for (let i = 0; i < definition.sections.length; i++) {
|
|
|
|
|
const item = definition.sections[i];
|
|
|
|
|
fieldSets = [...fieldSets, ...this.getAllDescriptionTemplateSectionFieldSets(item)];
|
|
|
|
|
}
|
|
|
|
|
return fieldSets;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const visibilityMap = this.elementComputationalMap.get(targetId);
|
|
|
|
|
const values = visibilityMap.values();
|
|
|
|
|
let currentVal = values.next();
|
|
|
|
|
let visibilityValues: boolean[] = [];
|
|
|
|
|
while (!currentVal.done) {
|
|
|
|
|
visibilityValues.push(currentVal.value);
|
|
|
|
|
currentVal = values.next();
|
|
|
|
|
private getAllDescriptionTemplateSectionFieldSets(definition: DescriptionTemplateSection): DescriptionTemplateFieldSet[] {
|
|
|
|
|
let fieldSets: DescriptionTemplateFieldSet[] = [];
|
|
|
|
|
if (definition.sections != null) {
|
|
|
|
|
for (let i = 0; i < definition.sections.length; i++) {
|
|
|
|
|
const item = definition.sections[i];
|
|
|
|
|
fieldSets = [...fieldSets, ...this.getAllDescriptionTemplateSectionFieldSets(item)];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (definition.fieldSets != null) {
|
|
|
|
|
for (let i = 0; i < definition.fieldSets.length; i++) {
|
|
|
|
|
const item = definition.fieldSets[i];
|
|
|
|
|
fieldSets = [...fieldSets, ...definition.fieldSets];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return fieldSets;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private buildTargetVisibility(propertyDefinition: DescriptionPropertyDefinitionPersist){
|
|
|
|
|
this._isVisibleMap = {};
|
|
|
|
|
this.rulesBySources.forEach((ruleForSource: RuleWithTarget[], ruleForSourceKey: string) => {
|
|
|
|
|
for (let i = 0; i < ruleForSource.length; i++) {
|
|
|
|
|
const rule = ruleForSource[i];
|
|
|
|
|
if (propertyDefinition.fieldSets != null) {
|
|
|
|
|
new Map(Object.entries(propertyDefinition.fieldSets)).forEach((propertyDefinitionFieldSet: DescriptionPropertyDefinitionFieldSetPersist, propertyDefinitionFieldSetKey: string) => {
|
|
|
|
|
if (propertyDefinitionFieldSet.items != null && propertyDefinitionFieldSet.items.length > 0) {
|
|
|
|
|
for (let j = 0; j < propertyDefinitionFieldSet.items.length; j++) {
|
|
|
|
|
const definitionFieldSetItem = propertyDefinitionFieldSet.items[j];
|
|
|
|
|
if (definitionFieldSetItem?.fields != null) {
|
|
|
|
|
const fieldsMap = new Map(Object.entries(definitionFieldSetItem.fields));
|
|
|
|
|
fieldsMap.forEach((field: DescriptionFieldPersist, key: string) => {
|
|
|
|
|
if (rule.source == key){
|
|
|
|
|
|
|
|
|
|
if (fieldsMap.has(rule.target)){ //Rule applies only for current multiple item
|
|
|
|
|
const fieldKey = this.buildVisibilityKey(rule.target, definitionFieldSetItem.ordinal);
|
|
|
|
|
const currentState = this._isVisibleMap[fieldKey] ?? false;
|
|
|
|
|
this._isVisibleMap[fieldKey] = currentState || this.ruleIsTrue(rule, field);
|
|
|
|
|
//console.log(fieldKey + " " + this._isVisibleMap[fieldKey] + " " + field.textListValue);
|
|
|
|
|
} else if (this.getDescriptionTemplateDefinitionFieldById(this.definition, rule.target).length > 0 || this.getDescriptionTemplateDefinitionFieldSetById(this.definition, rule.target).length > 0) { //Rule applies to different fieldset, so we apply for all multiple items
|
|
|
|
|
const ordinals: number[] = this.getKeyOrdinals(rule.target, propertyDefinition);
|
|
|
|
|
for (let k = 0; k < ordinals.length; k++) {
|
|
|
|
|
const ordinal = ordinals[j];
|
|
|
|
|
const fieldKey = this.buildVisibilityKey(rule.target, ordinal);
|
|
|
|
|
const currentState = this._isVisibleMap[fieldKey] ?? false;
|
|
|
|
|
this._isVisibleMap[fieldKey] = currentState || this.ruleIsTrue(rule, field);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
const fieldKey = this.buildVisibilityKey(rule.target, null); //Ordinal is null if target not on field
|
|
|
|
|
const currentState = this._isVisibleMap[fieldKey] ?? false;
|
|
|
|
|
this._isVisibleMap[fieldKey] = currentState || this.ruleIsTrue(rule, field);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (visibilityValues.length) {
|
|
|
|
|
return visibilityValues.reduce((r, c) => {
|
|
|
|
|
if (this.VISIBILITY_RULE_LOGIC === 'OR') {
|
|
|
|
|
return r || c;
|
|
|
|
|
} else {
|
|
|
|
|
return r && c;
|
|
|
|
|
private getKeyOrdinals(key: string, propertyDefinition: DescriptionPropertyDefinitionPersist): number[]{
|
|
|
|
|
let ordinals = [];
|
|
|
|
|
if (propertyDefinition.fieldSets != null) {
|
|
|
|
|
new Map(Object.entries(propertyDefinition.fieldSets)).forEach((propertyDefinitionFieldSet: DescriptionPropertyDefinitionFieldSetPersist, propertyDefinitionFieldSetKey: string) => {
|
|
|
|
|
if (propertyDefinitionFieldSetKey == key) {
|
|
|
|
|
ordinals = propertyDefinitionFieldSet.items?.map(x => x.ordinal) ?? [];
|
|
|
|
|
return ordinals;
|
|
|
|
|
}
|
|
|
|
|
}, visibilityValues[0]);
|
|
|
|
|
if (propertyDefinitionFieldSet.items != null && propertyDefinitionFieldSet.items.length > 0) {
|
|
|
|
|
for (let i = 0; i < propertyDefinitionFieldSet.items.length; i++) {
|
|
|
|
|
const definitionFieldSetItem = propertyDefinitionFieldSet.items[i];
|
|
|
|
|
if (definitionFieldSetItem?.fields != null) {
|
|
|
|
|
new Map(Object.entries(definitionFieldSetItem.fields)).forEach((field: DescriptionFieldPersist, fieldKey: string) => {
|
|
|
|
|
if (fieldKey == key) ordinals = propertyDefinitionFieldSet.items?.map(x=> x.ordinal) ?? [];
|
|
|
|
|
});
|
|
|
|
|
if (ordinals != null && ordinals.length > 0) return ordinals;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return this.DEFAULTVISIBILITY;
|
|
|
|
|
return ordinals;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private resetVisibilityRules() {
|
|
|
|
|
//console.log('resetVisibilityRules: ');
|
|
|
|
|
|
|
|
|
|
this.isVisibleMap = {};
|
|
|
|
|
this.elementComputationalMap.clear();
|
|
|
|
|
this.elementComputationalMap = new Map<String, Map<String, boolean>>();
|
|
|
|
|
this._populateComputationMap(); /// !IMPORTANT FOR THE AND LOGIC
|
|
|
|
|
this._changeMade$.next();
|
|
|
|
|
private ruleIsTrue(rule: RuleWithTarget, field: DescriptionFieldPersist) :boolean{
|
|
|
|
|
if (field != null){
|
|
|
|
|
const fieldType: DescriptionTemplateFieldType = rule.field != null && rule.field.data != null ? rule.field.data.fieldType : DescriptionTemplateFieldType.FREE_TEXT;
|
|
|
|
|
if ([DescriptionTemplateFieldType.FREE_TEXT, DescriptionTemplateFieldType.CHECK_BOX, DescriptionTemplateFieldType.TEXT_AREA,
|
|
|
|
|
DescriptionTemplateFieldType.RICH_TEXT_AREA, DescriptionTemplateFieldType.UPLOAD, DescriptionTemplateFieldType.BOOLEAN_DECISION,
|
|
|
|
|
DescriptionTemplateFieldType.RADIO_BOX, DescriptionTemplateFieldType.CURRENCY, DescriptionTemplateFieldType.SELECT].includes(fieldType) && field.textValue != null && field.textValue.length > 0) {
|
|
|
|
|
if (DescriptionTemplateFieldType.UPLOAD == fieldType){
|
|
|
|
|
return false; //not apply visibility logic
|
|
|
|
|
} else {
|
|
|
|
|
return field.textValue == rule.textValue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if ([DescriptionTemplateFieldType.SELECT, DescriptionTemplateFieldType.TAGS, DescriptionTemplateFieldType.INTERNAL_ENTRIES_DMPS,
|
|
|
|
|
DescriptionTemplateFieldType.INTERNAL_ENTRIES_DESCRIPTIONS].includes(fieldType) && field.textListValue != null && field.textListValue.length > 0) {
|
|
|
|
|
return rule.textListValue != null &&
|
|
|
|
|
rule.textListValue.every(x=> field.textListValue.includes(x));
|
|
|
|
|
}
|
|
|
|
|
else if (DescriptionTemplateFieldType.REFERENCE_TYPES == fieldType) {
|
|
|
|
|
return false; //not implemented visibility logic
|
|
|
|
|
}
|
|
|
|
|
else if (DescriptionTemplateFieldType.DATE_PICKER == fieldType && field.dateValue != null) return field.dateValue == rule.dateValue;
|
|
|
|
|
else if ([DescriptionTemplateFieldType.VALIDATION, DescriptionTemplateFieldType.DATASET_IDENTIFIER].includes(fieldType) && field.externalIdentifier != null) {
|
|
|
|
|
return false; //not implemented visibility logic
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private _populateComputationMap(): void {
|
|
|
|
|
//console.log('_populateComputationMap: ');
|
|
|
|
|
// this.visibilityRuleContext.rules.forEach(rule => {
|
|
|
|
|
// const targetId = rule.targetControlId;
|
|
|
|
|
// const visibilityMap = this.elementComputationalMap.get(targetId) ? this.elementComputationalMap.get(targetId) : new Map<String, boolean>();
|
|
|
|
|
// rule.sourceVisibilityRules.forEach(vr => {
|
|
|
|
|
// visibilityMap.set(vr.sourceControlId, this.DEFAULTVISIBILITY);
|
|
|
|
|
// });
|
|
|
|
|
// this.elementComputationalMap.set(targetId, visibilityMap);
|
|
|
|
|
// });
|
|
|
|
|
private expandVisibilityToChildren(propertyDefinition: DescriptionPropertyDefinitionPersist){
|
|
|
|
|
if (this.definition?.pages == null) return;
|
|
|
|
|
for (let i = 0; i < this.definition?.pages.length; i++) {
|
|
|
|
|
const pageEntity = this.definition?.pages[i];
|
|
|
|
|
const fieldKey = this.buildVisibilityKey(pageEntity.id, null);
|
|
|
|
|
const currentValue: boolean | null = this._isVisibleMap[fieldKey] ?? null;
|
|
|
|
|
this.expandPageVisibility(pageEntity, propertyDefinition, currentValue);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
parseValue(value: any) {
|
|
|
|
|
if (typeof value === 'string') {
|
|
|
|
|
if (isNumeric(value)) { return value; }
|
|
|
|
|
else if (value === 'true') {
|
|
|
|
|
return true;
|
|
|
|
|
private expandPageVisibility(pageEntity : DescriptionTemplatePage, propertyDefinition: DescriptionPropertyDefinitionPersist, parentVisibility : boolean | null){
|
|
|
|
|
if (pageEntity.sections == null) return;
|
|
|
|
|
for (let i = 0; i < pageEntity.sections.length; i++) {
|
|
|
|
|
const sectionEntity = pageEntity.sections[i];
|
|
|
|
|
const fieldKey = this.buildVisibilityKey(sectionEntity.id, null);
|
|
|
|
|
const currentValue: boolean | null = this._isVisibleMap[fieldKey] ?? null;
|
|
|
|
|
if (currentValue != null){
|
|
|
|
|
if (parentVisibility != null && !parentVisibility) { //Parent is hidden so all childs should be hidden
|
|
|
|
|
this._isVisibleMap[fieldKey] = false;
|
|
|
|
|
this.expandSectionVisibility(sectionEntity, propertyDefinition, currentValue);
|
|
|
|
|
} else {
|
|
|
|
|
this.expandSectionVisibility(sectionEntity, propertyDefinition, currentValue);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (parentVisibility != null) this._isVisibleMap[fieldKey] = parentVisibility;
|
|
|
|
|
this.expandSectionVisibility(sectionEntity, propertyDefinition, parentVisibility);
|
|
|
|
|
}
|
|
|
|
|
else if (value === 'false') {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
private expandSectionVisibility(sectionEntity: DescriptionTemplateSection, propertyDefinition: DescriptionPropertyDefinitionPersist, parentVisibility : boolean | null){
|
|
|
|
|
if (sectionEntity.sections != null) {
|
|
|
|
|
for (let i = 0; i < sectionEntity.sections.length; i++) {
|
|
|
|
|
const subSectionEntity = sectionEntity.sections[i];
|
|
|
|
|
const fieldKey = this.buildVisibilityKey(subSectionEntity.id, null);
|
|
|
|
|
const currentValue: boolean | null = this._isVisibleMap[fieldKey] ?? null;
|
|
|
|
|
if (currentValue != null){
|
|
|
|
|
if (parentVisibility != null && !parentVisibility) { //Parent is hidden so all childs should be hidden
|
|
|
|
|
this._isVisibleMap[fieldKey] = false;
|
|
|
|
|
this.expandSectionVisibility(subSectionEntity, propertyDefinition, currentValue);
|
|
|
|
|
} else {
|
|
|
|
|
this.expandSectionVisibility(subSectionEntity, propertyDefinition, currentValue);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (parentVisibility != null) this._isVisibleMap[fieldKey] = parentVisibility;
|
|
|
|
|
this.expandSectionVisibility(subSectionEntity, propertyDefinition, parentVisibility);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else { return this.translate(value); }
|
|
|
|
|
} else { return value; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
search(path, obj, target) {
|
|
|
|
|
for (const k in obj) {
|
|
|
|
|
if (obj.hasOwnProperty(k)) {
|
|
|
|
|
if (obj[k] === target) {
|
|
|
|
|
return path + '.' + k;
|
|
|
|
|
} else if (typeof obj[k] === 'object') {
|
|
|
|
|
const result = this.search(path + '.' + k, obj[k], target);
|
|
|
|
|
if (result) {
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
if (sectionEntity.fieldSets != null) {
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < sectionEntity.fieldSets.length; i++) {
|
|
|
|
|
const fieldSetEntity = sectionEntity.fieldSets[i];
|
|
|
|
|
const fieldSetsMap = propertyDefinition.fieldSets != null ? new Map(Object.entries(propertyDefinition.fieldSets)) : null;
|
|
|
|
|
if (fieldSetsMap != null && fieldSetsMap.has(fieldSetEntity.id)) {
|
|
|
|
|
const propertyDefinitionFieldSet = fieldSetsMap.get(fieldSetEntity.id)
|
|
|
|
|
if (propertyDefinitionFieldSet.items != null && propertyDefinitionFieldSet.items.length > 0) {
|
|
|
|
|
for (let j = 0; j < propertyDefinitionFieldSet.items.length; j++) {
|
|
|
|
|
const definitionFieldSetItem = propertyDefinitionFieldSet.items[j];
|
|
|
|
|
const fieldKey = this.buildVisibilityKey(fieldSetEntity.id, definitionFieldSetItem.ordinal);
|
|
|
|
|
const currentValue: boolean | null = this._isVisibleMap[fieldKey] ?? null;
|
|
|
|
|
if (currentValue != null){
|
|
|
|
|
if (parentVisibility != null && !parentVisibility) { //Parent is hidden so all childs should be hidden
|
|
|
|
|
this._isVisibleMap[fieldKey] = false;
|
|
|
|
|
this.expandFieldSetVisibility(fieldSetEntity, currentValue, definitionFieldSetItem.ordinal);
|
|
|
|
|
} else {
|
|
|
|
|
this.expandFieldSetVisibility(fieldSetEntity, currentValue, definitionFieldSetItem.ordinal);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (parentVisibility != null) this._isVisibleMap[fieldKey] = parentVisibility;
|
|
|
|
|
this.expandFieldSetVisibility(fieldSetEntity, parentVisibility, definitionFieldSetItem.ordinal);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
scanIfChildsOfCompositeFieldHasVisibleItems(compositeFieldParent: UntypedFormGroup): boolean {
|
|
|
|
|
// console.log('scanIfChildsOfCompositeFieldHasVisibleItems: ' + compositeFieldParent);
|
|
|
|
|
private expandFieldSetVisibility(fieldSetEntity: DescriptionTemplateFieldSet, parentVisibility: boolean | null, ordinal: number){
|
|
|
|
|
if (fieldSetEntity.fields != null) {
|
|
|
|
|
for (let i = 0; i < fieldSetEntity.fields.length; i++) {
|
|
|
|
|
const fieldEntity = fieldSetEntity.fields[i];
|
|
|
|
|
const fieldKey = this.buildVisibilityKey(fieldEntity.id, ordinal);
|
|
|
|
|
const currentValue: boolean | null = this._isVisibleMap[fieldKey] ?? null;
|
|
|
|
|
if (currentValue != null){
|
|
|
|
|
if (parentVisibility != null && !parentVisibility) { //Parent is hidden so all childs should be hidden
|
|
|
|
|
this._isVisibleMap[fieldKey] = false;
|
|
|
|
|
}
|
|
|
|
|
} else if (parentVisibility != null){
|
|
|
|
|
this._isVisibleMap[fieldKey] = parentVisibility;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//TODO: implement this
|
|
|
|
|
return true;
|
|
|
|
|
// let isVisible = false;
|
|
|
|
|
// (<UntypedFormArray>(compositeFieldParent.get('fields'))).controls.forEach(element => {
|
|
|
|
|
// if (this.checkElementVisibility(element.get('id').value)) {
|
|
|
|
|
// isVisible = true;
|
|
|
|
|
// }
|
|
|
|
|
// });
|
|
|
|
|
// return isVisible;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private translate(item: any) {
|
|
|
|
|
try {
|
|
|
|
|
return JSON.parse(item).value;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
return item;
|
|
|
|
|
private setDefaultVisibilityForNotCaclucted(propertyDefinition: DescriptionPropertyDefinitionPersist) {
|
|
|
|
|
if (this.definition?.pages == null) return;
|
|
|
|
|
for (let i = 0; i < this.definition?.pages.length; i++) {
|
|
|
|
|
const pageEntity = this.definition?.pages[i];
|
|
|
|
|
const fieldKey = this.buildVisibilityKey(pageEntity.id, null);
|
|
|
|
|
const currentValue: boolean | null = this._isVisibleMap[fieldKey] ?? null;
|
|
|
|
|
if (currentValue == null) this._isVisibleMap[fieldKey] = true;
|
|
|
|
|
this.setDefaultPageVisibility(pageEntity, propertyDefinition);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private resetControlWithId(formControl: AbstractControl, id: string) {
|
|
|
|
|
//'resetControlWithId: ' + id);
|
|
|
|
|
//TODO: implement this
|
|
|
|
|
// if (formControl instanceof UntypedFormGroup) {
|
|
|
|
|
// if ((formControl as UntypedFormGroup).contains('id') && (formControl as UntypedFormGroup).contains('value') && (formControl as UntypedFormGroup).get('id').value === id) {
|
|
|
|
|
// this.resetFieldFormGroup(formControl);
|
|
|
|
|
// } if ((formControl as UntypedFormGroup).contains('id') && (formControl as UntypedFormGroup).contains('fields') && (formControl as UntypedFormGroup).get('id').value === id) {
|
|
|
|
|
// this.resetCompositeFieldFormGroup(formControl);
|
|
|
|
|
// } else {
|
|
|
|
|
// Object.keys(formControl.controls).forEach(item => {
|
|
|
|
|
// const control = formControl.get(item);
|
|
|
|
|
// this.resetControlWithId(control, id);
|
|
|
|
|
// });
|
|
|
|
|
// }
|
|
|
|
|
// } else if (formControl instanceof UntypedFormArray) {
|
|
|
|
|
// formControl.controls.forEach(item => {
|
|
|
|
|
// this.resetControlWithId(item, id);
|
|
|
|
|
// });
|
|
|
|
|
// }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private resetFieldFormGroup(formGroup: UntypedFormGroup) {
|
|
|
|
|
//console.log('resetFieldFormGroup: ' + formGroup);
|
|
|
|
|
//TODO: implement this
|
|
|
|
|
// const renderStyle = formGroup.getRawValue().viewStyle.renderStyle;
|
|
|
|
|
// if (renderStyle === DatasetProfileFieldViewStyle.Validation || renderStyle === DatasetProfileFieldViewStyle.DatasetIdentifier) {
|
|
|
|
|
// formGroup.get('value').setValue({ identifier: '', type: '' });
|
|
|
|
|
// } else {
|
|
|
|
|
// formGroup.get('value').setValue(formGroup.get('defaultValue').value ? this.parseValue(formGroup.get('defaultValue').value.value) : undefined);
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private resetCompositeFieldFormGroup(formGroup: UntypedFormGroup) {
|
|
|
|
|
//console.log('resetCompositeFieldFormGroup: ' + formGroup);
|
|
|
|
|
//TODO: implement this
|
|
|
|
|
// (formGroup.get('fields') as UntypedFormArray).controls.forEach((element: UntypedFormGroup) => {
|
|
|
|
|
// this.resetFieldFormGroup(element);
|
|
|
|
|
// });
|
|
|
|
|
// (formGroup.get('multiplicityItems') as UntypedFormArray).controls.splice(0);
|
|
|
|
|
}
|
|
|
|
|
private _emitChangesIfNeeded(id: string, valueToBeSet: boolean) {
|
|
|
|
|
if (this.isVisibleMap[id]) {
|
|
|
|
|
if (this.isVisibleMap[id] != valueToBeSet) {
|
|
|
|
|
this._changeMade$.next();
|
|
|
|
|
private setDefaultPageVisibility(pageEntity: DescriptionTemplatePage, propertyDefinition: DescriptionPropertyDefinitionPersist) {
|
|
|
|
|
if (pageEntity.sections == null) return;
|
|
|
|
|
for (let i = 0; i < pageEntity.sections.length; i++) {
|
|
|
|
|
const sectionEntity = pageEntity.sections[i];
|
|
|
|
|
const fieldKey = this.buildVisibilityKey(sectionEntity.id, null);
|
|
|
|
|
const currentValue: boolean | null = this._isVisibleMap[fieldKey] ?? null;
|
|
|
|
|
if (currentValue == null){
|
|
|
|
|
this._isVisibleMap[fieldKey] = true;
|
|
|
|
|
this.setDefaultSectionVisibility(sectionEntity, propertyDefinition);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
this._changeMade$.next();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
public get visibilityChange() {
|
|
|
|
|
return this._changeMade$.asObservable();
|
|
|
|
|
}
|
|
|
|
|
public getVisibilityDependency(targetId: string): VisibilityRuleSource[] | null {
|
|
|
|
|
//console.log('getVisibilityDependency: ' + targetId);
|
|
|
|
|
return this.visibilityRuleContext.rules.reduce((hasDependency, rule) => {
|
|
|
|
|
if (hasDependency) return hasDependency;
|
|
|
|
|
|
|
|
|
|
if (rule.targetControlId === targetId) {
|
|
|
|
|
return rule.sourceVisibilityRules;
|
|
|
|
|
private setDefaultSectionVisibility(sectionEntity: DescriptionTemplateSection, propertyDefinition: DescriptionPropertyDefinitionPersist) {
|
|
|
|
|
if (sectionEntity.sections != null) {
|
|
|
|
|
for (let i = 0; i < sectionEntity.sections.length; i++) {
|
|
|
|
|
const subSectionEntity = sectionEntity.sections[i];
|
|
|
|
|
const fieldKey = this.buildVisibilityKey(subSectionEntity.id, null);
|
|
|
|
|
const currentValue: boolean | null = this._isVisibleMap[fieldKey] ?? null;
|
|
|
|
|
if (currentValue == null){
|
|
|
|
|
this._isVisibleMap[fieldKey] = true;
|
|
|
|
|
this.setDefaultSectionVisibility(subSectionEntity, propertyDefinition);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}, null) as VisibilityRuleSource[];
|
|
|
|
|
}
|
|
|
|
|
if (sectionEntity.fieldSets != null) {
|
|
|
|
|
for (let i = 0; i < sectionEntity.fieldSets.length; i++) {
|
|
|
|
|
const fieldSetEntity = sectionEntity.fieldSets[i];
|
|
|
|
|
const fieldSetsMap = propertyDefinition.fieldSets != null ? new Map(Object.entries(propertyDefinition.fieldSets)) : null;
|
|
|
|
|
if (fieldSetsMap != null && fieldSetsMap.has(fieldSetEntity.id)) {
|
|
|
|
|
const propertyDefinitionFieldSet = fieldSetsMap.get(fieldSetEntity.id)
|
|
|
|
|
if (propertyDefinitionFieldSet.items != null && propertyDefinitionFieldSet.items.length > 0) {
|
|
|
|
|
for (let j = 0; j < propertyDefinitionFieldSet.items.length; j++) {
|
|
|
|
|
const definitionFieldSetItem = propertyDefinitionFieldSet.items[j];
|
|
|
|
|
const fieldKey = this.buildVisibilityKey(fieldSetEntity.id, definitionFieldSetItem.ordinal);
|
|
|
|
|
const currentValue: boolean | null = this._isVisibleMap[fieldKey] ?? null;
|
|
|
|
|
if (currentValue == null){
|
|
|
|
|
this._isVisibleMap[fieldKey] = true;
|
|
|
|
|
this.setDefaultFieldSetVisibility(fieldSetEntity, definitionFieldSetItem.ordinal);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public getVisibilityTargets(sourceId: string): string[] {
|
|
|
|
|
console.log('getVisibilityTargets: ' + sourceId);
|
|
|
|
|
return this.visibilityRuleContext.rules.filter(x => {
|
|
|
|
|
const result = x.sourceVisibilityRules.filter(y => y.sourceControlId === sourceId);
|
|
|
|
|
return result.length;
|
|
|
|
|
}).map(x => x.targetControlId);
|
|
|
|
|
private setDefaultFieldSetVisibility(fieldSetEntity: DescriptionTemplateFieldSet, ordinal: number){
|
|
|
|
|
if (fieldSetEntity.fields != null) {
|
|
|
|
|
for (let i = 0; i < fieldSetEntity.fields.length; i++) {
|
|
|
|
|
const fieldEntity = fieldSetEntity.fields[i];
|
|
|
|
|
const fieldKey = this.buildVisibilityKey(fieldEntity.id, ordinal);
|
|
|
|
|
const currentValue: boolean | null = this._isVisibleMap[fieldKey] ?? null;
|
|
|
|
|
if (currentValue == null){
|
|
|
|
|
this._isVisibleMap[fieldKey] = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// public appendVisibilityRule(rule: VisibilityRule): void{
|
|
|
|
|
|
|
|
|
|
// const existingTargetRule = this.visibilityRuleContext.rules.find( r => r.targetControlId === rule.targetControlId);
|
|
|
|
|
|
|
|
|
|
// if(existingTargetRule){
|
|
|
|
|
// rule.sourceVisibilityRules.forEach(svr =>{
|
|
|
|
|
// existingTargetRule.sourceVisibilityRules.push(svr);
|
|
|
|
|
// });
|
|
|
|
|
// }else{
|
|
|
|
|
// this.visibilityRuleContext.rules.push(rule);
|
|
|
|
|
// }
|
|
|
|
|
private hideParentIfAllChildrenAreHidden(propertyDefinition: DescriptionPropertyDefinitionPersist) {
|
|
|
|
|
if (this.definition?.pages == null) return;
|
|
|
|
|
for (let i = 0; i < this.definition?.pages.length; i++) {
|
|
|
|
|
const pageEntity = this.definition?.pages[i];
|
|
|
|
|
const fieldKey = this.buildVisibilityKey(pageEntity.id, null);
|
|
|
|
|
const isCurrentHidden = this.isHiddenPageVisibilityIfAllChildrenIsHidden(pageEntity, propertyDefinition);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//removes rule that has the specific id either as a source either as a target
|
|
|
|
|
public removeAllIdReferences(id: string): void {
|
|
|
|
|
//console.log('removeAllIdReferences: ' + id);
|
|
|
|
|
|
|
|
|
|
// * Remove from visibility rues and visibility rules context
|
|
|
|
|
|
|
|
|
|
//remove as a target
|
|
|
|
|
const temp = this.visibilityRuleContext.rules.map((x, i) => (x.targetControlId === id) ? i : null);
|
|
|
|
|
const indexes = temp.filter(x => x !== null);
|
|
|
|
|
indexes.reverse().forEach(index => this.visibilityRuleContext.rules.splice(index, 1));
|
|
|
|
|
this.isVisibleMap[id] = undefined;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//remove as a source
|
|
|
|
|
const tbd = this.visibilityRuleContext.rules.reduce((to_be_deleted, rule, ruleIdx) => {
|
|
|
|
|
const idxs = rule.sourceVisibilityRules.map((x, i) => (x.sourceControlId === id) ? i : null).filter(x => x !== null);
|
|
|
|
|
idxs.reverse().forEach(index => rule.sourceVisibilityRules.splice(index, 1));
|
|
|
|
|
|
|
|
|
|
if (!rule.sourceVisibilityRules.length) {
|
|
|
|
|
to_be_deleted.push(ruleIdx);
|
|
|
|
|
if (isCurrentHidden && (this._isVisibleMap[fieldKey] ?? true)) {
|
|
|
|
|
this._isVisibleMap[fieldKey] = false;
|
|
|
|
|
}
|
|
|
|
|
return to_be_deleted
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//clean up empty
|
|
|
|
|
tbd.reverse().forEach(index => {
|
|
|
|
|
this.visibilityRuleContext.rules.splice(index, 1);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// * Remove from computational map
|
|
|
|
|
|
|
|
|
|
// as a target
|
|
|
|
|
if (this.elementComputationalMap.get(id)) {
|
|
|
|
|
this.elementComputationalMap.delete(id);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// as a source
|
|
|
|
|
const keyIterator = this.elementComputationalMap.keys();
|
|
|
|
|
let currentKey = keyIterator.next();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while (!currentKey.done) {
|
|
|
|
|
const currentVals = this.elementComputationalMap.get(currentKey.value);
|
|
|
|
|
currentVals.delete(id);
|
|
|
|
|
currentKey = keyIterator.next();
|
|
|
|
|
private isHiddenPageVisibilityIfAllChildrenIsHidden(pageEntity: DescriptionTemplatePage, propertyDefinition: DescriptionPropertyDefinitionPersist): boolean{
|
|
|
|
|
let isHidden = true;
|
|
|
|
|
if (pageEntity?.sections == null) return;
|
|
|
|
|
for (let i = 0; i < pageEntity.sections.length; i++) {
|
|
|
|
|
const sectionEntity = pageEntity.sections[i];
|
|
|
|
|
const fieldKey = this.buildVisibilityKey(sectionEntity.id, null);
|
|
|
|
|
const isCurrentHidden = this.isHiddenSectionIfAllChildrenIsHidden(sectionEntity, propertyDefinition);
|
|
|
|
|
if (isCurrentHidden && (this._isVisibleMap[fieldKey] ?? true)) {
|
|
|
|
|
this._isVisibleMap[fieldKey] = false;
|
|
|
|
|
}
|
|
|
|
|
isHidden = isHidden && isCurrentHidden;
|
|
|
|
|
}
|
|
|
|
|
return isHidden;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public addNewRule(rule: Rule, currentVisibility = this.DEFAULTVISIBILITY): void {
|
|
|
|
|
//console.log('addNewRule: ' + rule + ' currentVisibility: ' + currentVisibility);
|
|
|
|
|
|
|
|
|
|
const targetId = rule.targetField;
|
|
|
|
|
const sourceId = rule.sourceField;
|
|
|
|
|
this.visibilityRuleContext.addToVisibilityRulesContext(rule);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let visibilityMap = this.elementComputationalMap.get(targetId);
|
|
|
|
|
|
|
|
|
|
if (!visibilityMap) {
|
|
|
|
|
visibilityMap = new Map<String, boolean>();
|
|
|
|
|
this.elementComputationalMap.set(targetId, visibilityMap);
|
|
|
|
|
private isHiddenSectionIfAllChildrenIsHidden(sectionEntity: DescriptionTemplateSection, propertyDefinition: DescriptionPropertyDefinitionPersist): boolean{
|
|
|
|
|
let isHidden = true;
|
|
|
|
|
if (sectionEntity.sections != null) {
|
|
|
|
|
for (let i = 0; i < sectionEntity.sections.length; i++) {
|
|
|
|
|
const subSectionEntity = sectionEntity.sections[i];
|
|
|
|
|
const fieldKey = this.buildVisibilityKey(subSectionEntity.id, null);
|
|
|
|
|
const isCurrentHidden = this.isHiddenSectionIfAllChildrenIsHidden(subSectionEntity, propertyDefinition);
|
|
|
|
|
if (isCurrentHidden && (this._isVisibleMap[fieldKey] ?? true)) {
|
|
|
|
|
this._isVisibleMap[fieldKey] = false;
|
|
|
|
|
}
|
|
|
|
|
isHidden = isHidden && isCurrentHidden;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
visibilityMap.set(sourceId, currentVisibility);
|
|
|
|
|
const isVisible = this._computeVisibility(targetId);
|
|
|
|
|
|
|
|
|
|
this._emitChangesIfNeeded(targetId, isVisible);
|
|
|
|
|
this.isVisibleMap[targetId] = isVisible;
|
|
|
|
|
this.elementVisibilityMapSubject.next(this.isVisibleMap);
|
|
|
|
|
if (sectionEntity.fieldSets != null) {
|
|
|
|
|
for (let i = 0; i < sectionEntity.fieldSets.length; i++) {
|
|
|
|
|
const fieldSetEntity = sectionEntity.fieldSets[i];
|
|
|
|
|
const fieldSetsMap = propertyDefinition.fieldSets != null ? new Map(Object.entries(propertyDefinition.fieldSets)) : null;
|
|
|
|
|
if (fieldSetsMap != null && fieldSetsMap.has(fieldSetEntity.id)) {
|
|
|
|
|
const propertyDefinitionFieldSet = fieldSetsMap.get(fieldSetEntity.id)
|
|
|
|
|
if (propertyDefinitionFieldSet.items != null && propertyDefinitionFieldSet.items.length > 0) {
|
|
|
|
|
for (let j = 0; j < propertyDefinitionFieldSet.items.length; j++) {
|
|
|
|
|
const definitionFieldSetItem = propertyDefinitionFieldSet.items[j];
|
|
|
|
|
const fieldKey = this.buildVisibilityKey(fieldSetEntity.id, definitionFieldSetItem.ordinal);
|
|
|
|
|
const isCurrentHidden = this.isHiddenFieldSetIfAllChildrenIsHidden(fieldSetEntity, definitionFieldSetItem.ordinal);
|
|
|
|
|
if (isCurrentHidden && (this._isVisibleMap[fieldKey] ?? true)) {
|
|
|
|
|
this._isVisibleMap[fieldKey] = false;
|
|
|
|
|
}
|
|
|
|
|
isHidden = isHidden && isCurrentHidden;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return isHidden;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Check what sourceId hides or shows the target field
|
|
|
|
|
* return true if no rule found
|
|
|
|
|
*/
|
|
|
|
|
public checkTargetVisibilityProvidedBySource(sourceId: string, targetId: string): boolean {
|
|
|
|
|
//console.log('checkTargetVisibilityProvidedBySource: ' + sourceId + ' targetId: ' + targetId);
|
|
|
|
|
|
|
|
|
|
const computationalMap = this.elementComputationalMap.get(targetId);
|
|
|
|
|
if (computationalMap) {
|
|
|
|
|
return !!computationalMap.get(sourceId);
|
|
|
|
|
private isHiddenFieldSetIfAllChildrenIsHidden(fieldSetEntity: DescriptionTemplateFieldSet, ordinal: number): boolean{
|
|
|
|
|
let isHidden = true;
|
|
|
|
|
if (fieldSetEntity.fields != null) {
|
|
|
|
|
for (let i = 0; i < fieldSetEntity.fields.length; i++) {
|
|
|
|
|
const fieldEntity = fieldSetEntity.fields[i];
|
|
|
|
|
const fieldKey = this.buildVisibilityKey(fieldEntity.id, ordinal);
|
|
|
|
|
const currentValue: boolean | null = (this._isVisibleMap[fieldKey] ?? true);
|
|
|
|
|
isHidden = isHidden && !currentValue;
|
|
|
|
|
}
|
|
|
|
|
return isHidden;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public getVisibilityRulesFromDescriptionTempalte(descriptionTemplate: DescriptionTemplate): Rule[] {
|
|
|
|
|
//console.log('getVisibilityRulesFromDescriptionTempalte: ' + descriptionTemplate);
|
|
|
|
|
const result: Rule[] = this.getVisibilityRulesFromDescriptionTempalteSections(descriptionTemplate?.definition?.pages);
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public getVisibilityRulesFromDescriptionTempalteSections(pages: DescriptionTemplatePage[]): Rule[] {
|
|
|
|
|
//console.log('getVisibilityRulesFromDescriptionTempalteSections: ' + sections);
|
|
|
|
|
const result: Rule[] = [];
|
|
|
|
|
pages.forEach(page => {
|
|
|
|
|
page?.sections?.forEach(section => {
|
|
|
|
|
if (section.sections != null) { result.push(...this.getVisibilityRulesFromDescriptionTempalteSections(section.sections)); };
|
|
|
|
|
section?.fieldSets?.forEach(fieldSet => {
|
|
|
|
|
fieldSet?.fields?.forEach(field => {
|
|
|
|
|
field.visibilityRules?.forEach(visibilityRule => {
|
|
|
|
|
result.push({
|
|
|
|
|
sourceField: field.id.toString(),
|
|
|
|
|
targetField: visibilityRule.target,
|
|
|
|
|
requiredValue: visibilityRule.value
|
|
|
|
|
})
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
return result;
|
|
|
|
|
private ensureFieldSetVisibility(propertyDefinition: DescriptionPropertyDefinitionPersist) {
|
|
|
|
|
if (this.definition?.pages == null) return;
|
|
|
|
|
for (let i = 0; i < this.definition?.pages.length; i++) {
|
|
|
|
|
const pageEntity = this.definition?.pages[i];
|
|
|
|
|
this.ensurePageFieldSetVisibility(pageEntity, propertyDefinition);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class MapWithDefault extends Map<string, boolean> {
|
|
|
|
|
get(key) {
|
|
|
|
|
//console.log('MapWithDefault');
|
|
|
|
|
if (!this.has(key)) {
|
|
|
|
|
this.set(key, true);
|
|
|
|
|
private ensurePageFieldSetVisibility(pageEntity: DescriptionTemplatePage, propertyDefinition: DescriptionPropertyDefinitionPersist){
|
|
|
|
|
if (pageEntity?.sections == null) return;
|
|
|
|
|
for (let i = 0; i < pageEntity.sections.length; i++) {
|
|
|
|
|
const sectionEntity = pageEntity.sections[i];
|
|
|
|
|
this.ensureSectionFieldSetVisibility(sectionEntity, propertyDefinition);
|
|
|
|
|
}
|
|
|
|
|
return super.get(key);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private ensureSectionFieldSetVisibility(sectionEntity: DescriptionTemplateSection, propertyDefinition: DescriptionPropertyDefinitionPersist){
|
|
|
|
|
if (sectionEntity.sections != null) {
|
|
|
|
|
for (let i = 0; i < sectionEntity.sections.length; i++) {
|
|
|
|
|
const subSectionEntity = sectionEntity.sections[i];
|
|
|
|
|
this.ensureSectionFieldSetVisibility(subSectionEntity, propertyDefinition);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (sectionEntity.fieldSets != null) {
|
|
|
|
|
for (let i = 0; i < sectionEntity.fieldSets.length; i++) {
|
|
|
|
|
const fieldSetEntity = sectionEntity.fieldSets[i];
|
|
|
|
|
let isHidden = true;
|
|
|
|
|
const fieldSetsMap = propertyDefinition.fieldSets != null ? new Map(Object.entries(propertyDefinition.fieldSets)) : null;
|
|
|
|
|
if (fieldSetsMap != null && fieldSetsMap.has(fieldSetEntity.id)) {
|
|
|
|
|
const propertyDefinitionFieldSet = fieldSetsMap.get(fieldSetEntity.id)
|
|
|
|
|
if (propertyDefinitionFieldSet.items != null && propertyDefinitionFieldSet.items.length > 0) {
|
|
|
|
|
for (let j = 0; j < propertyDefinitionFieldSet.items.length; j++) {
|
|
|
|
|
const definitionFieldSetItem = propertyDefinitionFieldSet.items[j];
|
|
|
|
|
const fieldKey = this.buildVisibilityKey(fieldSetEntity.id, definitionFieldSetItem.ordinal);
|
|
|
|
|
const isCurrentHidden = !this._isVisibleMap[fieldKey] ?? false;
|
|
|
|
|
isHidden = isHidden && isCurrentHidden;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
const globalFieldSetKey = this.buildVisibilityKey(fieldSetEntity.id, null);
|
|
|
|
|
this._isVisibleMap[globalFieldSetKey] = !isHidden;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|