import { ApplicationRef, Injectable, NgZone } from '@angular/core'; import { FormGroup } from '@angular/forms'; import { DatasetProfileDefinitionModel } from '../../../../core/model/dataset-profile-definition/dataset-profile-definition'; import { Rule } from '../../../../core/model/dataset-profile-definition/rule'; import { VisibilityRule } from './models/visibility-rule'; import { VisibilityRulesContext } from './models/visibility-rules-context'; @Injectable() export class VisibilityRulesService { public formGroup: FormGroup; private visibilityRuleContext: VisibilityRulesContext; private fieldsPathMemory: any = {}; private elementVisibilityMap = new Map(); private initialModel: DatasetProfileDefinitionModel; private currentModel: DatasetProfileDefinitionModel; constructor( public applicationReference: ApplicationRef, public ngZone: NgZone ) { } public setModel(model: DatasetProfileDefinitionModel) { this.initialModel = model; this.currentModel = model; //this.visibilityRuleContext.rules.forEach(item => this.evaluateVisibility(item)) } public triggerVisibilityEvaluation() { this.visibilityRuleContext.rules.forEach(item => this.evaluateVisibility(item)); } public getFormGroup(id: string): FormGroup { const pathKeyArray = this.search('pages', this.initialModel.pages, id).split('.'); pathKeyArray.pop(); const pathKey = pathKeyArray.join('.'); if (!this.fieldsPathMemory[id] && pathKey) { this.fieldsPathMemory[id] = pathKey; } return (this.formGroup.get(pathKey)); } public checkElementVisibility(id: string): boolean { return !this.elementVisibilityMap.has(id) || this.elementVisibilityMap.get(id); } public buildVisibilityRules(item: Array) { this.visibilityRuleContext = new VisibilityRulesContext(); this.visibilityRuleContext.buildVisibilityRuleContext(item || []); } public updateValueAndVisibility(id: string) { const visibilityRules = this.visibilityRuleContext.rules.filter(item => item.sourceVisibilityRules.filter(source => source.sourceControlId === id).length > 0); visibilityRules.forEach(item => this.evaluateVisibility(item)); } private evaluateVisibility(visibilityRule: VisibilityRule) { for (let i = 0; i < visibilityRule.sourceVisibilityRules.length; i++) { const pathKey = this.fieldsPathMemory[visibilityRule.sourceVisibilityRules[i].sourceControlId]; if (this.formGroup.get(pathKey + '.value') && (this.parseValue(this.formGroup.get(pathKey + '.value').value) !== this.parseValue(visibilityRule.sourceVisibilityRules[i].sourceControlValue))) { if (this.formGroup.get(pathKey).parent.get('id')) { if (!this.checkElementVisibility(this.formGroup.get(pathKey).parent.get('id').value)) { const targetPathKey = this.fieldsPathMemory[visibilityRule.targetControlId]; this.getObject(this.currentModel, 'id', visibilityRule.targetControlId, this.currentModel, true); this.elementVisibilityMap.set(visibilityRule.targetControlId, false); this.clearValues(targetPathKey); return; } } else { const targetPathKey = this.fieldsPathMemory[visibilityRule.targetControlId]; this.getObject(this.currentModel, 'id', visibilityRule.targetControlId, this.currentModel, true); this.elementVisibilityMap.set(visibilityRule.targetControlId, false); this.clearValues(targetPathKey); return; } } } const obj = this.getObject(this.initialModel, 'id', visibilityRule.targetControlId, this.initialModel); const targetObjPathKey = this.fieldsPathMemory[visibilityRule.targetControlId] ? this.fieldsPathMemory[visibilityRule.targetControlId] : this.search('pages', this.initialModel.pages, obj); this.updateValue(this.currentModel, obj, targetObjPathKey); this.elementVisibilityMap.set(visibilityRule.targetControlId, true); } private clearValues(pathKey) { if (pathKey && this.formGroup.get(pathKey + '.value')) { this.formGroup.get(pathKey + '.value').patchValue(null); } if (pathKey && this.formGroup.get(pathKey)['controls'].fields) { for (let i = 0; i < this.formGroup.get(pathKey)['controls'].fields.length; i++) { this.clearValues(pathKey + '.fields.' + i); } } } parseValue(value: any) { if (typeof value === 'string') { if (value === 'true') { return true; } else if (value === 'false') { return false; } else { return this.translate(value); } } else { return value; } } updateValue(obj, value, path) { let i; path = path.split('.'); for (i = 0; i < path.length - 1; i++) { obj = obj[path[i]]; } for (let propIndex = 0; propIndex < obj.length; propIndex++) { if (obj[propIndex] && obj[propIndex]['id'] === value['id']) { return; } } obj[path[i]] = 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; } } } } return false; } private getObject(obj, key, val, parent, deleteObj = false) { for (const i in obj) { if (!obj.hasOwnProperty(i)) { continue; } if (typeof obj[i] === 'object') { const returnObj = this.getObject(obj[i], key, val, obj, deleteObj); if (returnObj) { return returnObj; } } else if (i === key && obj[key] === val) { //console.log(obj[key]) if (deleteObj) { parent[parent.indexOf(obj)] = null; } return obj; } } } private translate(item: any) { try { return JSON.parse(item).value; } catch (error) { return item; } } }