argos/dmp-frontend/src/app/utilities/visibility-rules/visibility-rules.service.ts

149 lines
5.5 KiB
TypeScript

import { VisibilityRule } from './models/VisibilityRule';
import { VisibilityRulesContext } from './models/VisibilityRulesContext';
import { FormGroup } from '@angular/forms';
import { Injectable, ApplicationRef, NgZone } from '@angular/core';
import { Rule } from '../../models/Rule';
import { DatasetProfileDefinitionModel } from '../../models/DatasetProfileDefinitionModel';
import { JsonSerializer } from '../JsonSerializer';
@Injectable()
export class VisibilityRulesService {
public formGroup: FormGroup;
public visibilityRuleContext: VisibilityRulesContext;
public fieldsPathMemory: any = {};
private elementVisibilityMap = new Map<String, boolean>();
private initialModel: DatasetProfileDefinitionModel;
private currentModel: DatasetProfileDefinitionModel;
constructor(public applicationReference: ApplicationRef, public ngZone: NgZone) {
}
public setModel(model: DatasetProfileDefinitionModel) {
this.initialModel = JsonSerializer.fromJSONObject(model, DatasetProfileDefinitionModel);
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 (<FormGroup>this.formGroup.get(pathKey));
}
public checkElementVisibility(id: string): boolean {
return !this.elementVisibilityMap.has(id) || this.elementVisibilityMap.get(id);
}
public buildVisibilityRules(item: Array<Rule>) {
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;
}
}
}