Support list of map properties in composition 62/129262/2
authorandre.schmid <andre.schmid@est.tech>
Thu, 12 May 2022 16:37:43 +0000 (17:37 +0100)
committerMichael Morris <michael.morris@est.tech>
Tue, 17 May 2022 08:23:38 +0000 (08:23 +0000)
Supports editing list<map<string, string> properties in the
edit properties dialog in the composition screen.
Fixes entry schema of type map not being shown.

Change-Id: Iea1732f51148ae88dedd2242b3b19d19c4548eb4
Issue-ID: SDC-4001
Signed-off-by: andre.schmid <andre.schmid@est.tech>
catalog-ui/src/app/directives/property-types/type-list/type-list-directive.html
catalog-ui/src/app/directives/property-types/type-list/type-list-directive.less
catalog-ui/src/app/directives/property-types/type-list/type-list-directive.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/directives/select-property-types/select-type-list/select-type-list-directive.less
catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view.html
catalog-ui/src/assets/languages/en_US.json

index 661514f..48e4415 100644 (file)
@@ -17,7 +17,8 @@
  
 <div>
     <div data-ng-if="!isSchemaTypeDataType">
-        <div class="i-sdc-form-item list-new-item" data-ng-class="{error:(parentFormObj['listNewItem'+fieldsPrefixName].$dirty && parentFormObj['listNewItem'+fieldsPrefixName].$invalid)}">
+        <div class="i-sdc-form-item list-new-item" data-ng-class="{error:(parentFormObj['listNewItem'+fieldsPrefixName].$dirty && parentFormObj['listNewItem'+fieldsPrefixName].$invalid)}"
+             ng-if="schemaProperty.type !== 'map'">
             <input class="i-sdc-form-input"
                    data-tests-id="listNewItem{{fieldsPrefixName}}"
                    ng-if="!constraints && !((schemaProperty.simpleType||schemaProperty.type) == 'boolean')"
             </div>
         </div>
         <div class="add-btn add-list-item" data-tests-id="add-list-item{{fieldsPrefixName}}"
-             data-ng-class="{'disabled': readOnly || !schemaProperty.type || parentFormObj['listNewItem'+fieldsPrefixName].$invalid || !listNewItem.value}" data-ng-click="addListItem()">Add</div>
+             data-ng-class="{'disabled': readOnly || !schemaProperty.type || parentFormObj['listNewItem'+fieldsPrefixName].$invalid || (!listNewItem.value && schemaProperty.type !== 'map')}" data-ng-click="addListItem()">Add</div>
         <div class="list-value-items">
-                                    <span class="list-value-item" data-ng-repeat="value in valueObjRef track by $index">
-                                        {{value}}
-                                        <span ng-if="!readOnly" class="delete-list-item sprite-new small-x-button" data-ng-click="deleteListItem($index)"></span>
-                                    </span>
+            <span class="list-value-item" data-ng-repeat="value in valueObjRef track by $index">
+                <span ng-if="!readOnly" class="delete-list-item sprite-new small-x-button" data-ng-click="deleteListItem($index)"
+                      title="{{'PROPERTY_EDIT_LIST_DELETE_ITEM' | translate}}"></span>
+                <div ng-if="schemaProperty.type === 'map'">
+                    <type-map value-obj-ref="value"
+                              schema-property="stringSchema"
+                              parent-form-obj="parentFormObj"
+                              fields-prefix-name="fieldsPrefixName+''+$index"
+                              read-only="readOnly"
+                              default-value="{{undefined}}"
+                              max-length="maxLength"
+                              show-add-btn="true"
+                              constraints="constraints">
+                    </type-map>
+                </div>
+                <div ng-if="schemaProperty.type !== 'map'">
+                    {{value}}
+                </div>
+            </span>
         </div>
     </div>
     <div data-ng-if="isSchemaTypeDataType">
index 71263f2..99d8005 100644 (file)
@@ -21,7 +21,6 @@
         display: inline-block;
         background-color: @tlv_color_v;
         margin: 10px 0 0 10px;
-        padding: 0 8px;
         .delete-list-item{
             margin: 0 0 0 2px;
             .hand;
index 997e28d..7681004 100644 (file)
@@ -37,21 +37,29 @@ export interface ITypeListScope extends ng.IScope {
     listDefaultValue:any;
     listNewItem:any;
     maxLength:number;
-    
+    stringSchema: SchemaProperty;
+
     constraints:string[];
 
     getValidationPattern(type:string):RegExp;
     validateIntRange(value:string):boolean;
     addListItem():void;
-    deleteListItem(listItemIndex:number):void
+    deleteListItem(listItemIndex:number):void;
+    getStringSchemaProperty():SchemaProperty;
 }
 
 
 export class TypeListDirective implements ng.IDirective {
 
+    private readonly stringSchema: SchemaProperty;
+
     constructor(private DataTypesService:DataTypesService,
                 private PropertyNameValidationPattern:RegExp,
-                private ValidationUtils:ValidationUtils) {  
+                private ValidationUtils:ValidationUtils) {
+        this.stringSchema = new SchemaProperty();
+        this.stringSchema.type = PROPERTY_TYPES.STRING;
+        this.stringSchema.isSimpleType = true;
+        this.stringSchema.isDataType = false;
     }
 
     scope = {
@@ -73,6 +81,7 @@ export class TypeListDirective implements ng.IDirective {
 
     link = (scope:ITypeListScope, element:any, $attr:any) => {
         scope.propertyNameValidationPattern = this.PropertyNameValidationPattern;
+        scope.stringSchema = this.stringSchema;
 
         //reset valueObjRef when schema type is changed
         scope.$watchCollection('schemaProperty.type', (newData:any):void => {
@@ -103,17 +112,22 @@ export class TypeListDirective implements ng.IDirective {
 
         scope.addListItem = ():void => {
             scope.valueObjRef = scope.valueObjRef || [];
-            let newVal = ((scope.schemaProperty.simpleType || scope.schemaProperty.type) == PROPERTY_TYPES.STRING ? scope.listNewItem.value : JSON.parse(scope.listNewItem.value));
+            let newVal;
+            if (scope.schemaProperty.type === PROPERTY_TYPES.MAP) {
+                newVal = {"": ""};
+            } else if ((scope.schemaProperty.simpleType || scope.schemaProperty.type) == PROPERTY_TYPES.STRING) {
+                newVal = scope.listNewItem.value;
+            } else {
+                newVal = JSON.parse(scope.listNewItem.value);
+            }
             scope.valueObjRef.push(newVal);
             scope.listNewItem.value = "";
         };
 
-        scope.deleteListItem = (listItemIndex:number):void => {
+        scope.deleteListItem = (listItemIndex: number): void => {
             scope.valueObjRef.splice(listItemIndex, 1);
-            if (!scope.valueObjRef.length) {
-                if (scope.listDefaultValue) {
-                    angular.copy(scope.listDefaultValue, scope.valueObjRef);
-                }
+            if (!scope.valueObjRef.length && scope.listDefaultValue) {
+                angular.copy(scope.listDefaultValue, scope.valueObjRef);
             }
         };
     };
index 55a414e..139f1f4 100644 (file)
                               read-only="readOnly"
             ></fields-structure>
         </div>
-        <span ng-click="deleteMapItem($index)" class="delete-map-item" data-tests-id="delete-map-item{{fieldsPrefixName}}{{$index}}" data-ng-class="{'disabled': readOnly}"></span>
+        <span ng-click="deleteMapItem($index)" class="delete-map-item" data-tests-id="delete-map-item{{fieldsPrefixName}}{{$index}}"
+              data-ng-class="{'disabled': readOnly}" title="{{'PROPERTY_EDIT_MAP_DELETE_ITEM' | translate}}"></span>
     </div>
-    <div class="add-map-item" data-ng-class="{'schema-data-type':isSchemaTypeDataType}">
+    <div class="add-map-item" data-ng-class="{'schema-data-type':isSchemaTypeDataType}" data-ng-if="showAddBtn">
         <div class="add-btn" data-tests-id="add-map-item"
-             data-ng-class="{'disabled': readOnly || !schemaProperty.type || mapKeys.indexOf('')>-1 || !isMapKeysUnique}" data-ng-click="addMapItemFields()">Add</div>
+             data-ng-class="{'disabled': readOnly || !schemaProperty.type || mapKeys.indexOf('')>-1 || !isMapKeysUnique}"
+             data-ng-click="addMapItemFields()" title="{{'PROPERTY_EDIT_MAP_ADD_ITEM' | translate}}">Add</div>
     </div>
 </div>
 
index 080c13b..ceb2fa0 100644 (file)
@@ -40,6 +40,7 @@ export interface ITypeMapScope extends ng.IScope {
     mapDefaultValue:any;
     maxLength:number;
     constraints:string[];
+    showAddBtn: boolean;
 
     getValidationPattern(type:string):RegExp;
     validateIntRange(value:string):boolean;
@@ -67,17 +68,18 @@ export class TypeMapDirective implements ng.IDirective {
         readOnly: '=',//is form read only
         defaultValue: '@',//this map default value
         maxLength: '=',
-        constraints: '='
-        
+        constraints: '=',
+        showAddBtn: '=?'
     };
 
     restrict = 'E';
     replace = true;
-    template = ():string => {
+    template = (): string => {
         return require('./type-map-directive.html');
     };
 
     link = (scope:ITypeMapScope, element:any, $attr:any) => {
+        scope.showAddBtn = angular.isDefined(scope.showAddBtn) ? scope.showAddBtn : true;
         scope.MapKeyValidationPattern = this.MapKeyValidationPattern;
         scope.isMapKeysUnique = true;
 
@@ -91,6 +93,11 @@ export class TypeMapDirective implements ng.IDirective {
             }
         });
 
+        scope.$watchCollection('valueObjRef', (newData: any): void => {
+            scope.mapKeys = Object.keys(scope.valueObjRef);
+            scope.mapKeysStatic = Object.keys(scope.valueObjRef);
+        });
+
         //when user brows between properties in "edit property form"
         scope.$watchCollection('fieldsPrefixName', (newData:any):void => {
             if (!scope.valueObjRef) {
@@ -119,27 +126,29 @@ export class TypeMapDirective implements ng.IDirective {
         };
 
         scope.changeKeyOfMap = (newKey:string, index:number, fieldName:string):void => {
-            let oldKey = Object.keys(scope.valueObjRef)[index];
-            let existsKeyIndex = Object.keys(scope.valueObjRef).indexOf(newKey);
-            if (existsKeyIndex > -1 && existsKeyIndex != index) {
+            const currentKeySet = Object.keys(scope.valueObjRef);
+            const currentKey = currentKeySet[index];
+            const existingKeyIndex = currentKeySet.indexOf(newKey);
+            if (existingKeyIndex > -1 && existingKeyIndex != index) {
                 scope.parentFormObj[fieldName].$setValidity('keyExist', false);
                 scope.isMapKeysUnique = false;
-            } else {
-                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 = {};
-                    angular.copy(scope.valueObjRef , newObj);
-                    angular.forEach(newObj,function(value:any,key:string){
-                        delete scope.valueObjRef[key];
-                        if(key == oldKey){
-                            scope.valueObjRef[newKey] = value;
-                        }else{
-                            scope.valueObjRef[key] = value;
-                        }
-                    });
-                }
+                return;
+            }
+
+            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 = {};
+                angular.copy(scope.valueObjRef, newObj);
+                angular.forEach(newObj, function (value: any, key: string) {
+                    delete scope.valueObjRef[key];
+                    if (key == currentKey) {
+                        scope.valueObjRef[newKey] = value;
+                    } else {
+                        scope.valueObjRef[key] = value;
+                    }
+                });
             }
         };
 
index 71263f2..99d8005 100644 (file)
@@ -21,7 +21,6 @@
         display: inline-block;
         background-color: @tlv_color_v;
         margin: 10px 0 0 10px;
-        padding: 0 8px;
         .delete-list-item{
             margin: 0 0 0 2px;
             .hand;
index 7c29d98..49ff38b 100644 (file)
@@ -84,7 +84,7 @@
                             <div class="w-sdc-form-column" data-ng-if="showSchema()">
                                 <!-- Entry Schema -->
                                 <div class="i-sdc-form-item" data-ng-class="{error:(forms.editForm.schemaType.$dirty && forms.editForm.schemaType.$invalid)}">
-                                    <label class="i-sdc-form-label required">Entry Schema</label>
+                                    <label class="i-sdc-form-label required">{{'PROPERTY_ENTRY_SCHEMA' | translate}}</label>
                                     <select class="i-sdc-form-select"
                                             data-required
                                             data-tests-id="schema-type"
@@ -92,8 +92,8 @@
                                             name="schemaType"
                                             data-ng-change="onSchemaTypeChange()"
                                             data-ng-model="editPropertyModel.property.schema.property.type">
-                                        <option value="">Choose Schema Type</option>
-                                        <option data-ng-repeat="type in editPropertyModel.simpleTypes"
+                                        <option value="">{{'PROPERTY_ENTRY_SCHEMA_CHOOSE_OPTION' | translate}}</option>
+                                        <option data-ng-repeat="type in editPropertyModel.types"
                                                 value="{{type}}">{{type}}</option>
                                         <option data-ng-repeat="type in nonPrimitiveTypes"
                                                 value="{{type}}">{{type.replace("org.openecomp.datatypes.heat.","")}}</option>
index aa5e368..fe855c1 100644 (file)
   "PROPERTY_EDIT_LIST_GENERIC": "Invalid value. The correct value is X, Y",
   "PROPERTY_EDIT_MAP_GENERIC": "Invalid value. The correct value is \"Key\":value",
   "PROPERTY_EDIT_MAP_UNIQUE_KEYS": "Key must be unique.",
+  "PROPERTY_EDIT_LIST_DELETE_ITEM": "Delete list item",
+  "PROPERTY_EDIT_MAP_DELETE_ITEM": "Delete map item",
+  "PROPERTY_EDIT_MAP_ADD_ITEM": "Add map item",
+  "PROPERTY_ENTRY_SCHEMA": "Entry Schema",
+  "PROPERTY_ENTRY_SCHEMA_CHOOSE_OPTION": "Choose Schema Type",
   "=========== ATTRIBUTE VIEW ===========": "",
   "ATTRIBUTE_VIEW_DELETE_MODAL_TITLE": "Delete Attribute Confirmation",
   "ATTRIBUTE_DETAILS_MODAL_TITLE": "Attribute Details",