From b3d4898d9e8452ea0b8d848c048e712d43b8d9a3 Mon Sep 17 00:00:00 2001 From: Michael Lando Date: Sun, 11 Jun 2017 14:22:02 +0300 Subject: [SDC-29] rebase continue work to align source Change-Id: I218f1c5ee23fb2c8314f1c70921d3ad8682c10f4 Signed-off-by: Michael Lando --- .../properties-assignment/properties.utils.ts | 168 +++++++++++++++------ 1 file changed, 122 insertions(+), 46 deletions(-) (limited to 'catalog-ui/src/app/ng2/pages/properties-assignment/properties.utils.ts') diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/properties.utils.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/properties.utils.ts index 79769e21b5..dfde2a40b2 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/properties.utils.ts +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/properties.utils.ts @@ -1,78 +1,154 @@ import { Injectable } from '@angular/core'; import { DataTypeModel, PropertyFEModel, PropertyBEModel, InstanceBePropertiesMap, InstanceFePropertiesMap, SchemaProperty, DerivedFEProperty, DerivedFEPropertyMap, DerivedPropertyType, InputFEModel} from "app/models"; import { DataTypeService } from "app/ng2/services/data-type.service"; +import { PropertiesService } from "app/ng2/services/properties.service"; import { PROPERTY_TYPES } from "app/utils"; import { UUID } from "angular2-uuid"; @Injectable() export class PropertiesUtils { - constructor(private dataTypeService:DataTypeService) {} + constructor(private dataTypeService:DataTypeService, private propertiesService: PropertiesService) {} /** * Entry point when getting properties from server - * Returning InstanceFePropertiesMap + * For each instance, loop through each property, and: + * 1. Create flattened children + * 2. Check against inputs to see if any props are declared and disable them + * 3. Initialize valueObj (which also creates any new list/map flattened children as needed) + * Returns InstanceFePropertiesMap */ - public convertPropertiesMapToFEAndCreateChildren = (instancePropertiesMap:InstanceBePropertiesMap): InstanceFePropertiesMap => { + public convertPropertiesMapToFEAndCreateChildren = (instancePropertiesMap:InstanceBePropertiesMap, inputs:Array): InstanceFePropertiesMap => { let instanceFePropertiesMap:InstanceFePropertiesMap = new InstanceFePropertiesMap(); angular.forEach(instancePropertiesMap, (properties:Array, instanceName:string) => { - instanceFePropertiesMap[instanceName] = this.convertPropertiesToFEAndCreateChildren(properties); + let instanceInputs: Array = inputs.filter(input => input.instanceName == instanceName.split('.').pop()); + let propertyFeArray: Array = []; + _.forEach(properties, (property: PropertyBEModel) => { + + if (!this.dataTypeService.getDataTypeByTypeName(property.type)) { // if type not exist in data types remove property from list + console.log("ERROR: missing type " + property.type + " in dataTypes , of property ", property); + } else { + + let newFEProp: PropertyFEModel = new PropertyFEModel(property); //Convert property to FE + + if (newFEProp.derivedDataType == DerivedPropertyType.COMPLEX) { //Create children if prop is not simple, list, or map. + newFEProp.flattenedChildren = this.createFlattenedChildren(newFEProp.type, newFEProp.name); + } + if (instanceInputs.length) { //if this prop (or any children) are declared, set isDeclared and disable checkbox on parents/children + instanceInputs.filter(input => input.propertyName == newFEProp.name).forEach((input) => { + newFEProp.setAsDeclared(input.inputPath); //if a path was sent, its a child prop. this param is optional + this.propertiesService.disableRelatedProperties(newFEProp, input.inputPath); + }); + } + this.initValueObjectRef(newFEProp); //initialize valueObj. + propertyFeArray.push(newFEProp); + newFEProp.updateExpandedChildPropertyId(newFEProp.name); //display only the first level of children + } + }); + instanceFePropertiesMap[instanceName] = propertyFeArray; + }); return instanceFePropertiesMap; } + private createListOrMapChildrenFromValueObj = (property: PropertyFEModel) => { + if ((property.derivedDataType == DerivedPropertyType.LIST || property.derivedDataType == DerivedPropertyType.MAP) + && Object.keys(property.valueObj).length) { - /** - * Convert the properties Array to Array - */ - private convertPropertiesToFEAndCreateChildren = (properties: Array): Array => { - let propertyFeArray: Array = []; - _.forEach(properties, (property: PropertyBEModel, index: number) => { - //console.log("=======" + property.name + "========"); - if(!this.dataTypeService.getDataTypeByTypeName(property.type)){ // if type not exist in data types remove property from list - console.log("ERROR: missing type " + property.type + " in dataTypes , of property ",property); - return; - } - let propertyFe:PropertyFEModel = new PropertyFEModel(property); - if (propertyFe.isDataType) { //prop is not simple, list, or map. Need to create children. - let tempProps: Array = []; - let dataTypeObj: DataTypeModel = this.dataTypeService.getDataTypeByTypeName(propertyFe.type); - this.dataTypeService.getDerivedDataTypeProperties(dataTypeObj, tempProps, propertyFe.name); - propertyFe.flattenedChildren = tempProps; - propertyFe.expandedChildPropertyId = propertyFe.name; - this.initValueObjectRef(propertyFe); - } - propertyFeArray.push(propertyFe); - + Object.keys(property.valueObj).forEach((key) => { + let newProps: Array = this.createListOrMapChildren(property, key, property.valueObj[key]); + property.flattenedChildren.push(...newProps); + }); + + } + } - }); - return propertyFeArray; + public createListOrMapChildren = (property:PropertyBEModel, key: string, valueObj: any): Array => { + let newProps: Array = []; + let parentProp = new DerivedFEProperty(property, property.propertiesName, true, key, valueObj); + newProps.push(parentProp); - //TODO: need to look at schema to create the nested properties for the following cases: - // 1 - when value is populated for a complex type (list or map) - // 2 - when adding new entries to a complex type (eg. adding a new entry to a list of AddressRequirements) + if (!property.schema.property.isSimpleType) { + let additionalChildren:Array = this.createFlattenedChildren(property.schema.property.type, parentProp.propertiesName); + this.assignFlattenedChildrenValues(parentProp.valueObj, additionalChildren, parentProp.propertiesName); + additionalChildren.forEach(prop => prop.canBeDeclared = false); + newProps.push(...additionalChildren); + } + return newProps; } + /** + * Creates derivedFEProperties of a specified type and returns them. + */ + private createFlattenedChildren = (type: string, parentName: string):Array => { + let tempProps: Array = []; + let dataTypeObj: DataTypeModel = this.dataTypeService.getDataTypeByTypeName(type); + this.dataTypeService.getDerivedDataTypeProperties(dataTypeObj, tempProps, parentName); + return tempProps; + } + + /* Sets the valueObj of parent property and its children. + * Note: This logic is different than assignflattenedchildrenvalues - here we merge values, there we pick either the parents value, props value, or default value - without merging. + */ public initValueObjectRef = (property: PropertyFEModel): void => { - //console.log("Property " + property.name + " has value: " + property.value); - if (!property.isDataType || property.isDeclared) { //if property is declared, it gets a simple input instead. List and map values and pseudo-children will be handled in property component - property.value = property.value || property.defaultValue; - } else if (property.value){ //we have a complex property with a value. Lets parse property.value and populate our flattened children with those values - this.assignValuesRecursively(JSON.parse(property.value), property.flattenedChildren, property.name); + if (property.derivedDataType == DerivedPropertyType.SIMPLE || property.isDeclared) { //if property is declared, it gets a simple input instead. List and map values and pseudo-children will be handled in property component + property.valueObj = property.value || property.defaultValue; + + if (property.isDeclared && typeof property.valueObj == 'object') property.valueObj = JSON.stringify(property.valueObj); + } else { + if (property.derivedDataType == DerivedPropertyType.LIST) { + property.valueObj = _.merge([], JSON.parse(property.defaultValue || '[]'), JSON.parse(property.value || '[]')); //value object should be merged value and default value. Value takes higher precendence. Set valueObj to empty obj if undefined. + } else { + property.valueObj = _.merge({}, JSON.parse(property.defaultValue || '{}'), JSON.parse(property.value || '{}')); //value object should be merged value and default value. Value takes higher precendence. Set valueObj to empty obj if undefined. + } + if (property.derivedDataType == DerivedPropertyType.COMPLEX) { + this.assignFlattenedChildrenValues(property.valueObj, property.flattenedChildren, property.name); + } else { + this.createListOrMapChildrenFromValueObj(property); + } } } - public assignValuesRecursively = (valueJSON: any, derivedPropArray: Array, propName: string) => { - if (valueJSON && Object.keys(valueJSON)) { - Object.keys(valueJSON).forEach(valueKey => { - let childProp: DerivedFEProperty = derivedPropArray.find(prop => prop.propertiesName == propName + "#" + valueKey); - if (!childProp) return; - if (childProp.isDeclared || (childProp.derivedDataType != DerivedPropertyType.COMPLEX && !_.isEmpty(valueJSON[valueKey]))) { - childProp.value = (typeof valueJSON[valueKey] === 'object')? JSON.stringify(valueJSON[valueKey]) : valueJSON[valueKey]; - } else { - this.assignValuesRecursively(valueJSON[valueKey], derivedPropArray, childProp.propertiesName) + /* + * Loops through flattened properties array and to assign values + * Then, convert any neccessary strings to objects, and vis-versa + * For list or map property, creates new children props if valueObj has values + */ + public assignFlattenedChildrenValues = (parentValueJSON: any, derivedPropArray: Array, parentName: string) => { + if (!derivedPropArray || !parentName) return; + derivedPropArray.forEach((prop, index) => { + + let propNameInObj = prop.propertiesName.substring(prop.propertiesName.indexOf(parentName) + parentName.length + 1).split('#').join('.'); //extract everything after parent name + prop.valueObj = _.get(parentValueJSON, propNameInObj, prop.value || prop.defaultValue); //assign value -first value of parent if exists. If not, prop.value if not, prop.defaultvalue + + if ((prop.derivedDataType == DerivedPropertyType.SIMPLE || prop.isDeclared) && typeof prop.valueObj == 'object') { //Stringify objects that should be strings + prop.valueObj = JSON.stringify(prop.valueObj); + } else { //parse strings that should be objects + if ((prop.derivedDataType == DerivedPropertyType.COMPLEX || prop.derivedDataType == DerivedPropertyType.MAP) && typeof prop.valueObj != 'object') { + prop.valueObj = JSON.parse(prop.valueObj || '{}'); + } else if (prop.derivedDataType == DerivedPropertyType.LIST && typeof prop.valueObj != 'object') { + prop.valueObj = JSON.parse(prop.valueObj || '[]'); } - }); + if ((prop.derivedDataType == DerivedPropertyType.LIST || prop.derivedDataType == DerivedPropertyType.MAP) && Object.keys(prop.valueObj).length) { + let newProps: Array = []; + Object.keys(prop.valueObj).forEach((key) => { + newProps.push(...this.createListOrMapChildren(prop, key, prop.valueObj[key]));//create new children, assign their values, and then add to array + }); + derivedPropArray.splice(index + 1, 0, ...newProps); + } + } + }); + } + + public resetPropertyValue = (property: PropertyFEModel, newValue: string, inputPath?: string): void => { + property.value = newValue; + if (inputPath) { + let newProp = property.flattenedChildren.find(prop => prop.propertiesName == inputPath); + newProp && this.assignFlattenedChildrenValues(JSON.parse(newValue), [newProp], property.name); + } else { + this.initValueObjectRef(property); } } + + } -- cgit 1.2.3-korg