Fix handling of default values for VFC properties 82/133182/7
authoreschcam <cameron.scholes@est.tech>
Tue, 7 Feb 2023 17:27:13 +0000 (17:27 +0000)
committerMichael Morris <michael.morris@est.tech>
Fri, 24 Feb 2023 14:23:26 +0000 (14:23 +0000)
Issue-ID: SDC-4375
Signed-off-by: eschcam <cameron.scholes@est.tech>
Change-Id: Icb3c1dbbf52266c2021c50f491a7e48efdfb9e55

catalog-ui/src/app/directives/property-types/data-type-fields-structure/data-type-fields-structure.ts
catalog-ui/src/app/directives/property-types/type-map/type-map-directive.html
catalog-ui/src/app/directives/property-types/type-map/type-map-directive.ts
catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view-model.ts
catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view.html
catalog-ui/src/app/view-models/workspace/tabs/properties/properties-view-model.ts

index cb16ffa..419ad2d 100644 (file)
@@ -7,9 +7,9 @@
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *      http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * Created by obarda on 1/27/2016.
  */
 'use strict';
-import * as _ from "lodash";
-import {DataTypesService} from "app/services";
-import { ValidationUtils } from "app/utils";
-import { DataTypePropertyModel } from "app/models/data-type-properties";
-import { DataTypesMap} from "app/models";
+import { DataTypesMap } from 'app/models';
+import { DataTypePropertyModel } from 'app/models/data-type-properties';
+import { DataTypesService } from 'app/services';
+import { ValidationUtils } from 'app/utils';
+import * as _ from 'lodash';
 
 export interface IDataTypeFieldsStructureScope extends ng.IScope {
-    parentFormObj:ng.IFormController;
-    dataTypeProperties:Array<DataTypePropertyModel>;
-    typeName:string;
-    valueObjRef:any;
-    propertyNameValidationPattern:RegExp;
-    fieldsPrefixName:string;
-    readOnly:boolean;
-    currentTypeDefaultValue:any;
-    types:DataTypesMap;
-    expandByDefault:boolean;
-    expand:boolean;
-    expanded:boolean;
-    dataTypesService:DataTypesService;
-    constraints:string[];
-
-    expandAndCollapse():void;
-    getValidationPattern(type:string):RegExp;
-    validateIntRange(value:string):boolean;
-    onValueChange(propertyName:string, type:string):void
-    inputOnValueChange(property:any):void;
-}
+    parentFormObj: ng.IFormController;
+    dataTypeProperties: DataTypePropertyModel[];
+    typeName: string;
+    valueObjRef: any;
+    propertyNameValidationPattern: RegExp;
+    fieldsPrefixName: string;
+    readOnly: boolean;
+    currentTypeDefaultValue: any;
+    types: DataTypesMap;
+    expandByDefault: boolean;
+    expand: boolean;
+    expanded: boolean;
+    dataTypesService: DataTypesService;
+    constraints: string[];
 
+    expandAndCollapse(): void;
+    getValidationPattern(type: string): RegExp;
+    validateIntRange(value: string): boolean;
+    onValueChange(propertyName: string, type: string): void;
+    inputOnValueChange(property: any): void;
+}
 
 export class DataTypeFieldsStructureDirective implements ng.IDirective {
 
-    
-
-    constructor(private DataTypesService:DataTypesService,
-                private PropertyNameValidationPattern:RegExp,
-                private ValidationUtils:ValidationUtils) {
-    }
-
     constraints: string[];
 
     scope = {
@@ -71,35 +63,87 @@ export class DataTypeFieldsStructureDirective implements ng.IDirective {
         readOnly: '=',
         defaultValue: '@',
         types: '=',
-        expandByDefault: '='        
+        expandByDefault: '='
     };
 
     restrict = 'E';
     replace = true;
-    template = ():string => {
+
+    constructor(private DataTypesService: DataTypesService,
+                private PropertyNameValidationPattern: RegExp,
+                private ValidationUtils: ValidationUtils) {
+    }
+
+    public static factory = (DataTypesService: DataTypesService,
+                             PropertyNameValidationPattern: RegExp,
+                             ValidationUtils: ValidationUtils) => {
+        return new DataTypeFieldsStructureDirective(DataTypesService, PropertyNameValidationPattern, ValidationUtils);
+    }
+    template = (): string => {
         return require('./data-type-fields-structure.html');
-    };
-    //public types=Utils.Constants.PROPERTY_DATA.TYPES;
+    }
+
+    link = (scope: IDataTypeFieldsStructureScope, element: any, $attr: any) => {
+        scope.propertyNameValidationPattern = this.PropertyNameValidationPattern;
+
+        scope.$watchCollection('[typeName,fieldsPrefixName]', (newData: any): void => {
+            this.rerender(scope);
+        });
+
+        scope.expandAndCollapse = (): void => {
+            if (!scope.expanded) {
+                this.initDataOnScope(scope, $attr);
+                scope.expanded = true;
+            }
+            scope.expand = !scope.expand;
+        };
+
+        scope.getValidationPattern = (type: string): RegExp => {
+            return this.ValidationUtils.getValidationPattern(type);
+        };
+
+        scope.validateIntRange = (value: string): boolean => {
+            return !value || this.ValidationUtils.validateIntRange(value);
+        };
+
+        scope.onValueChange = (propertyName: string, type: string, ): void => {
+            scope.valueObjRef[propertyName] = !angular.isUndefined(scope.valueObjRef[propertyName]) ? scope.valueObjRef[propertyName] : scope.currentTypeDefaultValue[propertyName];
+            if (scope.valueObjRef[propertyName] && type != 'string') {
+                scope.valueObjRef[propertyName] = JSON.parse(scope.valueObjRef[propertyName]);
+            }
+        };
+
+        scope.inputOnValueChange = (property: any) => {
+            if (property.constraints) {
+                // this.constraints = property.constraints[0].validValues;
+            }
+
+            const value = !scope.parentFormObj[scope.fieldsPrefixName + property.name].$error.pattern
+                && ('integer' == property.type && scope.parentFormObj[scope.fieldsPrefixName + property.name].$setValidity('pattern', scope.validateIntRange(scope.valueObjRef[property.name]))
+                || scope.onValueChange(property.name, (property.simpleType || property.type)));
+            return value;
+        };
+    }
+    // public types=Utils.Constants.PROPERTY_DATA.TYPES;
 
-    //get data type properties array and return object with the properties and their default value
-    //(for example: get: [{name:"prop1",defaultValue:1 ...},{name:"prop2", defaultValue:"bla bla" ...}]
+    // get data type properties array and return object with the properties and their default value
+    // (for example: get: [{name:"prop1",defaultValue:1 ...},{name:"prop2", defaultValue:"bla bla" ...}]
     //              return: {prop1: 1, prop2: "bla bla"}
-    private getDefaultValue = (dataTypeProperties:Array<DataTypePropertyModel>):any => {
-        let defaultValue = {};
-        for (let i = 0; i < dataTypeProperties.length; i++) {
-            if (dataTypeProperties[i].type != 'string') {
-                if (!angular.isUndefined(dataTypeProperties[i].defaultValue)) {
-                    defaultValue[dataTypeProperties[i].name] = JSON.parse(dataTypeProperties[i].defaultValue);
+    private getDefaultValue = (dataTypeProperties: DataTypePropertyModel[]): any => {
+        const defaultValue = {};
+        for (const element of dataTypeProperties) {
+            if (element.type != 'string') {
+                if (!angular.isUndefined(element.defaultValue)) {
+                    defaultValue[element.name] = JSON.parse(element.defaultValue);
                 }
             } else {
-                defaultValue[dataTypeProperties[i].name] = dataTypeProperties[i].defaultValue;
+                defaultValue[element.name] = element.defaultValue;
             }
         }
         return defaultValue;
-    };
-
+    }
 
-    private initDataOnScope = (scope:any, $attr:any):void => {
+    private initDataOnScope = (scope: any, $attr: any): void => {
         scope.dataTypesService = this.DataTypesService;
         scope.dataTypeProperties = this.getDataTypeProperties(scope.typeName, scope.types);
         if ($attr.defaultValue) {
@@ -112,7 +156,7 @@ export class DataTypeFieldsStructureDirective implements ng.IDirective {
             scope.valueObjRef = {};
         }
 
-        _.forEach(scope.currentTypeDefaultValue, (value, key)=> {
+        _.forEach(scope.currentTypeDefaultValue, (value, key) => {
             if (angular.isUndefined(scope.valueObjRef[key])) {
                 if (typeof scope.currentTypeDefaultValue[key] == 'object') {
                     angular.copy(scope.currentTypeDefaultValue[key], scope.valueObjRef[key]);
@@ -121,72 +165,23 @@ export class DataTypeFieldsStructureDirective implements ng.IDirective {
                 }
             }
         });
-    };
-    
-    private getDataTypeProperties = (dataTypeName:string, typesInModel:DataTypesMap):Array<DataTypePropertyModel> => {
+    }
+
+    private getDataTypeProperties = (dataTypeName: string, typesInModel: DataTypesMap): DataTypePropertyModel[] => {
         let properties = typesInModel[dataTypeName].properties || [];
-        if (typesInModel[dataTypeName].derivedFromName != "tosca.datatypes.Root") {
+        if (typesInModel[dataTypeName].derivedFromName != 'tosca.datatypes.Root') {
             properties = this.getDataTypeProperties(typesInModel[dataTypeName].derivedFromName, typesInModel).concat(properties);
         }
         return properties;
-    };
+    }
 
-    private rerender = (scope:any):void => {
+    private rerender = (scope: any): void => {
         scope.expanded = false;
         scope.expand = false;
         if (scope.expandByDefault) {
             scope.expandAndCollapse();
         }
-    };
-
-    link = (scope:IDataTypeFieldsStructureScope, element:any, $attr:any) => {
-        scope.propertyNameValidationPattern = this.PropertyNameValidationPattern;
-
-        scope.$watchCollection('[typeName,fieldsPrefixName]', (newData:any):void => {
-            this.rerender(scope);
-        });
-
-
-        scope.expandAndCollapse = ():void => {
-            if (!scope.expanded) {
-                this.initDataOnScope(scope, $attr);
-                scope.expanded = true;
-            }
-            scope.expand = !scope.expand;
-        };
-
-        scope.getValidationPattern = (type:string):RegExp => {
-            return this.ValidationUtils.getValidationPattern(type);
-        };
-
-        scope.validateIntRange = (value:string):boolean => {
-            return !value || this.ValidationUtils.validateIntRange(value);
-        };
-
-        scope.onValueChange = (propertyName:string, type:string,):void => {
-            scope.valueObjRef[propertyName] = !angular.isUndefined(scope.valueObjRef[propertyName]) ? scope.valueObjRef[propertyName] : scope.currentTypeDefaultValue[propertyName];
-            if (scope.valueObjRef[propertyName] && type != 'string') {
-                scope.valueObjRef[propertyName] = JSON.parse(scope.valueObjRef[propertyName]);
-            }
-        };
-
-        scope.inputOnValueChange = (property:any) => {
-            if (property.constraints){
-                // this.constraints = property.constraints[0].validValues;
-            }
-            
-            let value = !scope.parentFormObj[scope.fieldsPrefixName + property.name].$error.pattern
-                && ('integer' == property.type && scope.parentFormObj[scope.fieldsPrefixName + property.name].$setValidity('pattern', scope.validateIntRange(scope.valueObjRef[property.name]))
-                || scope.onValueChange(property.name, (property.simpleType || property.type)));
-            return value;
-        }
-    };
-
-    public static factory = (DataTypesService:DataTypesService,
-                             PropertyNameValidationPattern:RegExp,
-                             ValidationUtils:ValidationUtils)=> {
-        return new DataTypeFieldsStructureDirective(DataTypesService, PropertyNameValidationPattern, ValidationUtils);
-    };
+    }
 }
 
 DataTypeFieldsStructureDirective.factory.$inject = ['Sdc.Services.DataTypesService', 'PropertyNameValidationPattern', 'ValidationUtils'];
index b4ac6aa..a2b7424 100644 (file)
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
+
+
 <div class="type-map">
-    <div data-ng-repeat="i in getNumber(mapKeys.length) track by $index" class="map-item" data-ng-class="{'primitive-value-map':!isSchemaTypeDataType}">
+    <div  ng-if="mapKeys.length > 0" data-ng-repeat="i in getNumber(mapKeys.length) track by $index" class="map-item" data-ng-class="{'primitive-value-map':!isSchemaTypeDataType}">
         <div class="i-sdc-form-item map-item-field" data-ng-class="{error:(parentFormObj['mapKey'+fieldsPrefixName+$index].$dirty && parentFormObj['mapKey'+fieldsPrefixName+$index].$invalid)}">
             <label class="i-sdc-form-label required">Key</label>
             <input class="i-sdc-form-input"
@@ -42,9 +42,9 @@
         <div data-ng-if="!isSchemaTypeDataType" class="i-sdc-form-item map-item-field" data-ng-class="{error:(parentFormObj['mapValue'+fieldsPrefixName+$index].$dirty && parentFormObj['mapValue'+fieldsPrefixName+$index].$invalid)}">
             <label class="i-sdc-form-label required">Value</label>
             <form class="temp-form">
-                <input type="radio" name="hasToscaFunction-{{fieldsPrefixName}}-{{$index}}" data-ng-checked="{{showToscaFunction[$index] == false}}" data-ng-click="onEnableTosca(false,$index)"/> 
+                <input type="radio" name="hasToscaFunction-{{fieldsPrefixName}}-{{$index}}" data-ng-checked="{{showToscaFunction[$index] == false}}" data-ng-click="onEnableTosca(false,$index)"/>
                 Value
-                <input type="radio" name="hasToscaFunction-{{fieldsPrefixName}}-{{$index}}" data-ng-checked="{{showToscaFunction[$index]}}" data-ng-click="onEnableTosca(true,$index)" ng-disabled="mapKeys[$index] == '' || mapKeys[$index] == null"/> 
+                <input type="radio" name="hasToscaFunction-{{fieldsPrefixName}}-{{$index}}" data-ng-checked="{{showToscaFunction[$index]}}" data-ng-click="onEnableTosca(true,$index)" ng-disabled="mapKeys[$index] == '' || mapKeys[$index] == null"/>
                 {{'TOSCA_FUNCTION_LABEL' | translate}}
             </form>
             <input class="i-sdc-form-input"
                 <!-- Get the saved value for the relevant key -->
                 <option ng-if = "valueObjRef[mapKeys[$index]]" value = "{{valueObjRef[mapKeys[$index]]}}" name = "{{valueObjRef[mapKeys[$index]]}}" hidden selected>
                         {{valueObjRef[mapKeys[$index]]}}
-                </option> 
+                </option>
                 <!-- add all constratint to Select list -->
                 <option ng-repeat='value in constraints' value="{{value}}" name="{{value}}">
                     {{value}}
-                </option> 
+                </option>
             </select>
 
             <div class="input-error" data-ng-show="parentFormObj['mapValue'+fieldsPrefixName+$index].$dirty && parentFormObj['mapValue'+fieldsPrefixName+$index].$invalid">
index 20470be..456c66a 100644 (file)
@@ -7,9 +7,9 @@
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *      http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * Created by rcohen on 9/15/2016.
  */
 'use strict';
-import {ValidationUtils, PROPERTY_TYPES, PROPERTY_DATA} from "app/utils";
-import {DataTypesService} from "app/services";
-import {SchemaProperty, PropertyModel, DataTypesMap} from "app/models";
-import {InstanceFeDetails} from "app/models/instance-fe-details";
-import {ToscaGetFunction} from "app/models/tosca-get-function";
-import {SubPropertyToscaFunction} from "app/models/sub-property-tosca-function";
+import { DataTypesMap, PropertyModel, SchemaProperty } from 'app/models';
+import { InstanceFeDetails } from 'app/models/instance-fe-details';
+import { SubPropertyToscaFunction } from 'app/models/sub-property-tosca-function';
+import { ToscaGetFunction } from 'app/models/tosca-get-function';
+import { DataTypesService } from 'app/services';
+import { PROPERTY_DATA, PROPERTY_TYPES, ValidationUtils } from 'app/utils';
 
 export interface ITypeMapScope extends ng.IScope {
-    parentFormObj:ng.IFormController;
-    schemaProperty:SchemaProperty;
-    parentProperty:PropertyModel;
+    parentFormObj: ng.IFormController;
+    schemaProperty: SchemaProperty;
+    parentProperty: PropertyModel;
     componentInstanceMap: Map<string, InstanceFeDetails>;
-    isMapKeysUnique:boolean;
-    isSchemaTypeDataType:boolean;
-    valueObjRef:any;
-    mapKeys:Array<string>;//array of map keys
-    mapKeysStatic:Array<string>;
-    MapKeyValidationPattern:RegExp;
-    fieldsPrefixName:string;
-    readOnly:boolean;
-    mapDefaultValue:any;
-    maxLength:number;
-    constraints:string[];
+    isMapKeysUnique: boolean;
+    isSchemaTypeDataType: boolean;
+    valueObjRef: any;
+    mapKeys: string[]; // array of map keys
+    mapKeysStatic: string[];
+    MapKeyValidationPattern: RegExp;
+    fieldsPrefixName: string;
+    readOnly: boolean;
+    mapDefaultValue: any;
+    maxLength: number;
+    constraints: string[];
     showAddBtn: boolean;
-    showToscaFunction: Array<boolean>;
-    types:DataTypesMap;
+    showToscaFunction: boolean[];
+    types: DataTypesMap;
 
-    getValidationPattern(type:string):RegExp;
-    validateIntRange(value:string):boolean;
-    changeKeyOfMap(newKey:string, index:number, fieldName:string):void;
-    deleteMapItem(index:number):void;
-    addMapItemFields():void;
-    parseToCorrectType(objectOfValues:any, locationInObj:string, type:string):void;
-    getNumber(num:number):Array<any>;
-    validateSubToscaFunction(key:string):boolean;
-    onEnableTosca(toscaFlag:boolean,index:number);
-    onGetToscaFunction(toscaGetFunction: ToscaGetFunction, key:string);
+    getValidationPattern(type: string): RegExp;
+    validateIntRange(value: string): boolean;
+    changeKeyOfMap(newKey: string, index: number, fieldName: string): void;
+    deleteMapItem(index: number): void;
+    addMapItemFields(): void;
+    parseToCorrectType(objectOfValues: any, locationInObj: string, type: string): void;
+    getNumber(num: number): any[];
+    validateSubToscaFunction(key: string): boolean;
+    onEnableTosca(toscaFlag: boolean, index: number);
+    onGetToscaFunction(toscaGetFunction: ToscaGetFunction, key: string);
 }
 
-
 export class TypeMapDirective implements ng.IDirective {
 
-    constructor(private DataTypesService:DataTypesService,
-                private MapKeyValidationPattern:RegExp,
-                private ValidationUtils:ValidationUtils,
-                private $timeout:ng.ITimeoutService) {
-    }
-
     scope = {
-        valueObjRef: '=',//ref to map object in the parent value object
+        valueObjRef: '=', // ref to map object in the parent value object
         componentInstanceMap: '=',
-        schemaProperty: '=',//get the schema.property object
-        parentFormObj: '=',//ref to parent form (get angular form object)
-        fieldsPrefixName: '=',//prefix for form fields names
-        readOnly: '=',//is form read only
-        defaultValue: '@',//this map default value
+        schemaProperty: '=', // get the schema.property object
+        parentFormObj: '=', // ref to parent form (get angular form object)
+        fieldsPrefixName: '=', // prefix for form fields names
+        readOnly: '=', // is form read only
+        defaultValue: '@', // this map default value
         maxLength: '=',
         constraints: '=',
         showAddBtn: '=?',
@@ -87,98 +80,102 @@ export class TypeMapDirective implements ng.IDirective {
 
     restrict = 'E';
     replace = true;
+
+    constructor(private DataTypesService: DataTypesService,
+                private MapKeyValidationPattern: RegExp,
+                private ValidationUtils: ValidationUtils,
+                private $timeout: ng.ITimeoutService) {
+    }
+
+    public static factory = (DataTypesService: DataTypesService,
+                             MapKeyValidationPattern: RegExp,
+                             ValidationUtils: ValidationUtils,
+                             $timeout: ng.ITimeoutService) => {
+        return new TypeMapDirective(DataTypesService, MapKeyValidationPattern, ValidationUtils, $timeout);
+    }
     template = (): string => {
         return require('./type-map-directive.html');
-    };
-    
-    private isDataTypeForSchemaType = (property:SchemaProperty, types:DataTypesMap):boolean=> {
-        property.simpleType = "";
-        if (property.type && PROPERTY_DATA.TYPES.indexOf(property.type) > -1) {
-            return false;
-        }
-        let simpleType = this.getTypeForDataTypeDerivedFromSimple(property.type, types);
-        if (simpleType) {
-            property.simpleType = simpleType;
-            return false;
-        }
-        return true;
-    };
-    
-    private getTypeForDataTypeDerivedFromSimple = (dataTypeName:string, types:DataTypesMap):string => {
-        if (!types[dataTypeName]) {
-            return 'string';
-        }
-        if (types[dataTypeName].derivedFromName == "tosca.datatypes.Root" || types[dataTypeName].properties) {
-            return null;
-        }
-        if (PROPERTY_DATA.SIMPLE_TYPES.indexOf(types[dataTypeName].derivedFromName) > -1) {
-            return types[dataTypeName].derivedFromName
-        }
-        return this.getTypeForDataTypeDerivedFromSimple(types[dataTypeName].derivedFromName, types);
-    };
+    }
 
-    link = (scope:ITypeMapScope, element:any, $attr:any) => {
+    link = (scope: ITypeMapScope, element: any, $attr: any) => {
         scope.showAddBtn = angular.isDefined(scope.showAddBtn) ? scope.showAddBtn : true;
         scope.MapKeyValidationPattern = this.MapKeyValidationPattern;
         scope.isMapKeysUnique = true;
+
         if (scope.mapKeys === undefined) {
-            scope.mapKeys = Object.keys(scope.valueObjRef);
-        }
-        scope.showToscaFunction = new Array(scope.mapKeys.length);
-        scope.mapKeys.forEach((key, index) => {
-            scope.showToscaFunction[index] = false;
-            if (scope.parentProperty.subPropertyToscaFunctions != null) {
-                scope.parentProperty.subPropertyToscaFunctions.forEach(SubPropertyToscaFunction => {
-                    if (SubPropertyToscaFunction.subPropertyPath.indexOf(key) != -1) {
-                        scope.showToscaFunction[index] = true;
-                    }
-                });
+            if (scope.valueObjRef) {
+                scope.mapKeys = Object.keys(scope.valueObjRef);
+            } else if (scope.defaultValue) {
+                const defaultValue = JSON.parse(scope.defaultValue);
+                scope.valueObjRef = defaultValue;
+                scope.mapKeys = Object.keys(defaultValue);
+            } else {
+                console.warn('Missing value keys');
             }
-        });
+        }
+
+        if (scope.mapKeys) {
+            scope.showToscaFunction = new Array(scope.mapKeys.length);
+            scope.mapKeys.forEach((key, index) => {
+                scope.showToscaFunction[index] = false;
+                if (scope.parentProperty && scope.parentProperty.subPropertyToscaFunctions != null) {
+                    scope.parentProperty.subPropertyToscaFunctions.forEach((SubPropertyToscaFunction) => {
+                        if (SubPropertyToscaFunction.subPropertyPath.indexOf(key) != -1) {
+                            scope.showToscaFunction[index] = true;
+                        }
+                    });
+                }
+            });
+        } else {
+            console.warn('Missing map keys');
+        }
 
-        //reset valueObjRef and mapKeys when schema type is changed
-        scope.$watchCollection('schemaProperty.type', (newData:any):void => {
+        // reset valueObjRef and mapKeys when schema type is changed
+        scope.$watchCollection('schemaProperty.type', (newData: any): void => {
             scope.isSchemaTypeDataType = this.isDataTypeForSchemaType(scope.schemaProperty, scope.types);
             if (scope.valueObjRef) {
                 scope.mapKeys = Object.keys(scope.valueObjRef);
-                //keeping another copy of the keys, as the mapKeys gets overridden sometimes
+                // keeping another copy of the keys, as the mapKeys gets overridden sometimes
                 scope.mapKeysStatic = Object.keys(scope.valueObjRef);
             }
         });
 
         scope.$watchCollection('valueObjRef', (newData: any): void => {
-            scope.mapKeys = Object.keys(scope.valueObjRef);
-            scope.mapKeysStatic = Object.keys(scope.valueObjRef);
+            if (scope.valueObjRef) {
+                scope.mapKeys = Object.keys(scope.valueObjRef);
+                scope.mapKeysStatic = Object.keys(scope.valueObjRef);
+            } else {
+                console.warn('valueObjRef missing', scope.valueObjRef);
+            }
         });
 
-        //when user brows between properties in "edit property form"
-        scope.$watchCollection('fieldsPrefixName', (newData:any):void => {
-            if (!scope.valueObjRef) {
-                scope.valueObjRef = {};
+        // when user brows between properties in "edit property form"
+        scope.$watchCollection('fieldsPrefixName', (newData: any): void => {
+            if (scope.valueObjRef) {
+                scope.mapKeys = Object.keys(scope.valueObjRef);
+                // keeping another copy of the keys, as the mapKeys gets overridden sometimes
+                scope.mapKeysStatic = Object.keys(scope.valueObjRef);
             }
-            scope.mapKeys = Object.keys(scope.valueObjRef);
-            //keeping another copy of the keys, as the mapKeys gets overridden sometimes
-            scope.mapKeysStatic = Object.keys(scope.valueObjRef);
 
             if ($attr.defaultValue) {
                 scope.mapDefaultValue = JSON.parse($attr.defaultValue);
             }
         });
 
-        //return dummy array in order to prevent rendering map-keys ng-repeat again when a map key is changed
-        scope.getNumber = (num:number):Array<any> => {
+        // return dummy array in order to prevent rendering map-keys ng-repeat again when a map key is changed
+        scope.getNumber = (num: number): any[] => {
             return new Array(num);
         };
 
-        scope.getValidationPattern = (type:string):RegExp => {
+        scope.getValidationPattern = (type: string): RegExp => {
             return this.ValidationUtils.getValidationPattern(type);
         };
 
-        scope.validateIntRange = (value:string):boolean => {
+        scope.validateIntRange = (value: string): boolean => {
             return !value || this.ValidationUtils.validateIntRange(value);
         };
 
-        scope.changeKeyOfMap = (newKey:string, index:number, fieldName:string):void => {
+        scope.changeKeyOfMap = (newKey: string, index: number, fieldName: string): void => {
             const currentKeySet = Object.keys(scope.valueObjRef);
             const currentKey = currentKeySet[index];
             const existingKeyIndex = currentKeySet.indexOf(newKey);
@@ -191,10 +188,10 @@ export class TypeMapDirective implements ng.IDirective {
             scope.parentFormObj[fieldName].$setValidity('keyExist', true);
             scope.isMapKeysUnique = true;
             if (!scope.parentFormObj[fieldName].$invalid) {
-                //To preserve the order of the keys, delete each one and recreate
-                let newObj = {};
+                // To preserve the order of the keys, delete each one and recreate
+                const newObj = {};
                 angular.copy(scope.valueObjRef, newObj);
-                angular.forEach(newObj, function (value: any, key: string) {
+                angular.forEach(newObj, function(value: any, key: string) {
                     delete scope.valueObjRef[key];
                     if (key == currentKey) {
                         scope.valueObjRef[newKey] = value;
@@ -205,13 +202,13 @@ export class TypeMapDirective implements ng.IDirective {
             }
         };
 
-        scope.deleteMapItem = (index:number):void=> {
+        scope.deleteMapItem = (index: number): void => {
             const keyToChange = scope.mapKeys[index];
             delete scope.valueObjRef[scope.mapKeys[index]];
             scope.mapKeys.splice(index, 1);
             scope.showToscaFunction.splice(index, 1);
-            if (scope.parentProperty.subPropertyToscaFunctions != null) {
-                let subToscaFunctionList : Array<SubPropertyToscaFunction> = [];
+            if (scope.parentProperty && scope.parentProperty.subPropertyToscaFunctions != null) {
+                const subToscaFunctionList: SubPropertyToscaFunction[] = [];
                 scope.parentProperty.subPropertyToscaFunctions.forEach((SubPropertyToscaFunction, index) => {
                     if (SubPropertyToscaFunction.subPropertyPath.indexOf(keyToChange) == -1) {
                         subToscaFunctionList.push(SubPropertyToscaFunction);
@@ -219,7 +216,7 @@ export class TypeMapDirective implements ng.IDirective {
                 });
                 scope.parentProperty.subPropertyToscaFunctions = subToscaFunctionList;
             }
-            if (!scope.mapKeys.length) {//only when user removes all pairs of key-value fields - put the default
+            if (!scope.mapKeys.length) {// only when user removes all pairs of key-value fields - put the default
                 if (scope.mapDefaultValue) {
                     angular.copy(scope.mapDefaultValue, scope.valueObjRef);
                     scope.mapKeys = Object.keys(scope.valueObjRef);
@@ -227,12 +224,12 @@ export class TypeMapDirective implements ng.IDirective {
             }
         };
 
-        scope.onEnableTosca = (toscaFlag:boolean,flagIndex:number):void => {
+        scope.onEnableTosca = (toscaFlag: boolean, flagIndex: number): void => {
             scope.showToscaFunction[flagIndex] = toscaFlag;
             scope.valueObjRef[scope.mapKeys[flagIndex]] = null;
             if (!toscaFlag) {
                 if (scope.parentProperty.subPropertyToscaFunctions != null) {
-                    let subToscaFunctionList : Array<SubPropertyToscaFunction> = [];
+                    const subToscaFunctionList: SubPropertyToscaFunction[] = [];
                     scope.parentProperty.subPropertyToscaFunctions.forEach((SubPropertyToscaFunction, index) => {
                         if (SubPropertyToscaFunction.subPropertyPath.indexOf(scope.mapKeys[flagIndex]) == -1) {
                             subToscaFunctionList.push(SubPropertyToscaFunction);
@@ -243,9 +240,9 @@ export class TypeMapDirective implements ng.IDirective {
             }
         };
 
-        scope.onGetToscaFunction = (toscaGetFunction: ToscaGetFunction, key:string): void => {
+        scope.onGetToscaFunction = (toscaGetFunction: ToscaGetFunction, key: string): void => {
             if (scope.parentProperty.subPropertyToscaFunctions != null) {
-                scope.parentProperty.subPropertyToscaFunctions.forEach(SubPropertyToscaFunction => {
+                scope.parentProperty.subPropertyToscaFunctions.forEach((SubPropertyToscaFunction) => {
                     if (SubPropertyToscaFunction.subPropertyPath.indexOf(key) != -1) {
                         SubPropertyToscaFunction.toscaFunction = toscaGetFunction;
                         return;
@@ -253,45 +250,69 @@ export class TypeMapDirective implements ng.IDirective {
                 });
 
             }
-            if (scope.parentProperty.subPropertyToscaFunctions == null){
+            if (scope.parentProperty.subPropertyToscaFunctions == null) {
                 scope.parentProperty.subPropertyToscaFunctions = [];
             }
-            let subPropertyToscaFunction = new SubPropertyToscaFunction();
+            const subPropertyToscaFunction = new SubPropertyToscaFunction();
             subPropertyToscaFunction.toscaFunction = toscaGetFunction;
             subPropertyToscaFunction.subPropertyPath = [key];
             scope.parentProperty.subPropertyToscaFunctions.push(subPropertyToscaFunction);
-        }
+        };
+
+        scope.addMapItemFields = (): void => {
+            if (!scope.valueObjRef) {
+                scope.valueObjRef = {};
+                scope.showToscaFunction = [];
+            }
 
-        scope.addMapItemFields = ():void => {
             scope.valueObjRef[''] = null;
             scope.mapKeys = Object.keys(scope.valueObjRef);
             scope.showToscaFunction.push(false);
         };
 
-        scope.parseToCorrectType = (objectOfValues:any, locationInObj:string, type:string):void => {
+        scope.parseToCorrectType = (objectOfValues: any, locationInObj: string, type: string): void => {
             if (objectOfValues[locationInObj] && type != PROPERTY_TYPES.STRING) {
                 objectOfValues[locationInObj] = JSON.parse(objectOfValues[locationInObj]);
             }
-        }
+        };
 
-        scope.validateSubToscaFunction = (key:string):boolean => {
+        scope.validateSubToscaFunction = (key: string): boolean => {
             if (scope.parentProperty.subPropertyToscaFunctions != null) {
-                scope.parentProperty.subPropertyToscaFunctions.forEach(SubPropertyToscaFunction => {
+                scope.parentProperty.subPropertyToscaFunctions.forEach((SubPropertyToscaFunction) => {
                     if (SubPropertyToscaFunction.subPropertyPath.indexOf(key) != -1) {
                         return true;
                     }
                 });
             }
             return false;
+        };
+    }
+
+    private isDataTypeForSchemaType = (property: SchemaProperty, types: DataTypesMap): boolean => {
+        property.simpleType = '';
+        if (property.type && PROPERTY_DATA.TYPES.indexOf(property.type) > -1) {
+            return false;
         }
-    };
+        const simpleType = this.getTypeForDataTypeDerivedFromSimple(property.type, types);
+        if (simpleType) {
+            property.simpleType = simpleType;
+            return false;
+        }
+        return true;
+    }
 
-    public static factory = (DataTypesService:DataTypesService,
-                             MapKeyValidationPattern:RegExp,
-                             ValidationUtils:ValidationUtils,
-                             $timeout:ng.ITimeoutService)=> {
-        return new TypeMapDirective(DataTypesService, MapKeyValidationPattern, ValidationUtils, $timeout);
-    };
+    private getTypeForDataTypeDerivedFromSimple = (dataTypeName: string, types: DataTypesMap): string => {
+        if (!types[dataTypeName]) {
+            return 'string';
+        }
+        if (types[dataTypeName].derivedFromName == 'tosca.datatypes.Root' || types[dataTypeName].properties) {
+            return null;
+        }
+        if (PROPERTY_DATA.SIMPLE_TYPES.indexOf(types[dataTypeName].derivedFromName) > -1) {
+            return types[dataTypeName].derivedFromName;
+        }
+        return this.getTypeForDataTypeDerivedFromSimple(types[dataTypeName].derivedFromName, types);
+    }
 }
 
 TypeMapDirective.factory.$inject = ['Sdc.Services.DataTypesService', 'MapKeyValidationPattern', 'ValidationUtils', '$timeout'];
index c20d9fc..05045c1 100644 (file)
@@ -7,9 +7,9 @@
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *      http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -77,7 +77,6 @@ interface IPropertyFormViewModelScope extends ng.IScope {
     getValidationPattern(type:string):RegExp;
     validateIntRange(value:string):boolean;
     close():void;
-    onValueChange():void;
     onSchemaTypeChange():void;
     onTypeChange(resetSchema:boolean):void;
     showSchema():boolean;
@@ -150,6 +149,7 @@ export class PropertyFormViewModel {
     private initResource = ():void => {
         this.$scope.editPropertyModel.property = new PropertyModel(this.property);
         this.$scope.editPropertyModel.property.type = this.property.type ? this.property.type : null;
+        this.$scope.editPropertyModel.property.value = this.property.value ? this.property.value : this.property.defaultValue;
         this.$scope.constraints = this.property.constraints && this.property.constraints[0] ? this.property.constraints[0]["validValues"] : null;
         this.initToscaGetFunction();
         this.setMaxLength();
@@ -159,7 +159,7 @@ export class PropertyFormViewModel {
         this.$scope.editPropertyModel.hasGetFunctionValue = this.$scope.editPropertyModel.property.isToscaFunction();
         this.$scope.editPropertyModel.isGetFunctionValid = true;
     }
-    
+
     private isDataTypeForPropertyType = (property:PropertyModel):boolean=> {
         property.simpleType = "";
         if (property.type && PROPERTY_DATA.TYPES.indexOf(property.type) > -1) {
@@ -172,7 +172,7 @@ export class PropertyFormViewModel {
         }
         return true;
     };
-    
+
     private getTypeForDataTypeDerivedFromSimple = (dataTypeName:string):string => {
         if (!this.$scope.dataTypes[dataTypeName]) {
             return 'string';
@@ -438,15 +438,6 @@ export class PropertyFormViewModel {
             this.$uibModalInstance.close();
         };
 
-        // put default value when instance value is empty
-        this.$scope.onValueChange = ():void => {
-            if (!this.$scope.editPropertyModel.property.value) {
-                if (this.$scope.isPropertyValueOwner) {
-                    this.$scope.editPropertyModel.property.value = this.$scope.editPropertyModel.property.defaultValue;
-                }
-            }
-        };
-
         // Add the done button at the footer.
         this.$scope.footerButtons = [
             {'name': 'Save', 'css': 'blue', 'callback': this.$scope.save},
index bfe7f49..2840e86 100644 (file)
                                            data-ng-pattern="getValidationPattern((editPropertyModel.property.simpleType||editPropertyModel.property.type))"
                                            data-ng-model-options="{ debounce: 200 }"
                                            data-ng-change="('json'==editPropertyModel.property.type && forms.editForm.value.$setValidity('pattern', validateJson(editPropertyModel.property.value)))
-                                                        ||(!forms.editForm.value.$error.pattern && ('integer'==editPropertyModel.property.type && forms.editForm.value.$setValidity('pattern', validateIntRange(editPropertyModel.property.value)) || onValueChange()))"
+                                                        ||(!forms.editForm.value.$error.pattern && ('integer'==editPropertyModel.property.type && forms.editForm.value.$setValidity('pattern', validateIntRange(editPropertyModel.property.value))))"
                                            autofocus/>
                                     <!-- Boolean -->
                                     <select class="i-sdc-form-select"
                                             ng-if="(editPropertyModel.property.simpleType||editPropertyModel.property.type) == 'boolean'"
                                             data-ng-disabled="editPropertyModel.property.readonly && !isPropertyValueOwner"
                                             name="value"
-                                            data-ng-change="onValueChange()"
                                             data-ng-model="editPropertyModel.property.value">
                                         <option value="true">true</option>
                                         <option value="false">false</option>
index 6d108d7..1d57355 100644 (file)
@@ -7,9 +7,9 @@
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *      http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.