Provide tosca function to map values 09/132209/6
authorimamSidero <imam.hussain@est.tech>
Tue, 15 Nov 2022 10:18:16 +0000 (10:18 +0000)
committerMichael Morris <michael.morris@est.tech>
Mon, 5 Dec 2022 10:25:39 +0000 (10:25 +0000)
Providing the capability to add tosca function as the map values against it's key

Issue-ID: SDC-4264
Signed-off-by: Imam hussain <imam.hussain@est.tech>
Change-Id: Ieaa49f9ac18b848bfd3996e9c6e08f9b4a32b999

catalog-ui/src/app/models/properties-inputs/derived-fe-property.ts
catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.html
catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.less
catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.ts
catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.html
catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.ts
catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.html
catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts
catalog-ui/src/app/ng2/pages/properties-assignment/services/properties.utils.ts
catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.component.ts
catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-get-function/tosca-get-function.component.ts

index 2d406e2..7d832c5 100644 (file)
@@ -21,6 +21,8 @@
 import * as _ from "lodash";
 import { SchemaPropertyGroupModel, SchemaProperty } from '../schema-property';
 import { DerivedPropertyType, PropertyBEModel, PropertyFEModel } from '../../models';
+import {SubPropertyToscaFunction} from "../sub-property-tosca-function";
+import {ToscaFunction} from "../tosca-function";
 import { PROPERTY_TYPES } from 'app/utils';
 import { UUID } from "angular2-uuid";
 
@@ -30,9 +32,11 @@ export class DerivedFEProperty extends PropertyBEModel {
     valueObjIsValid: boolean;
     valueObjOrig: any;
     valueObjIsChanged: boolean;
+    value: any
     parentName: string;
     propertiesName: string; //"network_assignments#ipv4_subnet#use_ipv4 =  parentPath + name
     derivedDataType: DerivedPropertyType;
+    toscaFunction: ToscaFunction;
     isDeclared: boolean;
     isSelected: boolean;
     isDisabled: boolean;
@@ -51,6 +55,13 @@ export class DerivedFEProperty extends PropertyBEModel {
             this.canBeDeclared = true; //defaults to true
         } else { //creating a direct child of list or map (ie. Item that can be deleted, with UUID instead of name)
             super(null);
+            if(property.type === PROPERTY_TYPES.MAP && property.subPropertyToscaFunctions != null){
+                property.subPropertyToscaFunctions.forEach((item : SubPropertyToscaFunction) => {
+                    if(item.subPropertyPath[0] === key){
+                        this.toscaFunction = item.toscaFunction;
+                    }
+                });
+            }
             this.isChildOfListOrMap = true;
             this.canBeDeclared = false;
             this.name = UUID.UUID();
@@ -88,6 +99,9 @@ export class DerivedFEProperty extends PropertyBEModel {
        
             }
             this.valueObj = (this.type == PROPERTY_TYPES.JSON && typeof value == 'object') ? JSON.stringify(value) : value;
+            if (value != null) {
+                this.value = typeof value == 'object' ? JSON.stringify(value) : value;
+            }
             this.updateValueObjOrig();
         }
         // this.constraints = property ? property.constraints : null;
index 4553bcb..2431a70 100644 (file)
     <!-- RIGHT CELL OR FULL WIDTH CELL-->
     <ng-container *ngIf="propType == derivedPropertyTypes.SIMPLE || property.isDeclared || property.isToscaFunction() || (property.isChildOfListOrMap && propType == derivedPropertyTypes.MAP && property.schema.property.isSimpleType)">
         <div class="table-cell">
+            <checkbox class="inline-checkBox" *ngIf="(nestedLevel == 1 && property.isChildOfListOrMap && propType == derivedPropertyTypes.MAP && property.schema.property.isSimpleType)" [(checked)]="property.isSelected" [disabled]="property.isDisabled || readonly || property.mapKey == ''" (checkedChange)="toggleTosca.emit(property)" ></checkbox>
             <dynamic-element class="value-input"
                 pattern="validationUtils.getValidationPattern(property.type)"
-                [value]="property.isDeclared || property.isToscaFunction() ? property.value : property.valueObj"
+                [value]="(property.isDeclared || property.isToscaFunction()) ? property.value : property.valueObj"
                 [type]="property.isDeclared || property.isToscaFunction() ? 'string' : property.type"
                 [name]="property.name"
                 [path]="property.propertiesName"
@@ -65,7 +66,7 @@
         <div class="table-cell empty"></div>
     </ng-container>
     <!-- ICONS: add, delete, and expand -->
-    <ng-container *ngIf="!property.isDeclared && !property.isToscaFunction()">
+    <ng-container *ngIf="(!property.isDeclared && !property.isToscaFunction()) || (property.isToscaFunction() && property.isChildOfListOrMap && propType == derivedPropertyTypes.MAP && property.schema.property.isSimpleType)">
             <a *ngIf="(propType == derivedPropertyTypes.LIST) && (!property.isChildOfListOrMap || property.mapInlist)" class="property-icon add-item" (click)="createNewChildProperty();" [ngClass]="{'disabled':readonly || preventInsertItem(property)}" [attr.data-tests-id]="'add-to-list-' + propertyTestsId">Add value to list</a>
             <a *ngIf="(propType == derivedPropertyTypes.MAP) && (!property.isChildOfListOrMap || property.mapInlist)" class="property-icon add-item" (click)="createNewChildProperty();" [ngClass]="{'disabled':readonly || preventInsertItem(property)}" [attr.data-tests-id]="'add-to-list-' + propertyTestsId">Add value to map</a>
             <span *ngIf="property.isChildOfListOrMap" (click)="deleteItem.emit(property);" class="property-icon sprite-new delete-item-icon" [ngClass]="{'disabled':readonly}" [attr.data-tests-id]="'delete-from-list-' + propertyTestsId"></span>
@@ -93,6 +94,7 @@
             (clickOnPropertyRow)="onClickPropertyRow($event)"
             (checkProperty)="checkedChange($event)"
             (addChildPropsToParent)="addChildProps($event, prop.propertiesName)"
+            (toggleTosca)="toggleToscaFunction($event)"
             >
         </dynamic-property>
     </ng-container>
index 6b018c1..360cfac 100644 (file)
@@ -27,6 +27,7 @@ import { trigger, state, style, transition, animate } from '@angular/animations'
 import {PropertiesUtils} from "../../../../pages/properties-assignment/services/properties.utils";
 import {IUiElementChangeEvent} from "../../../ui/form-components/ui-element-base.component";
 import {DynamicElementComponent} from "../../../ui/dynamic-element/dynamic-element.component";
+import {SubPropertyToscaFunction} from "app/models/sub-property-tosca-function";
 
 @Component({
     selector: 'dynamic-property',
@@ -57,6 +58,7 @@ export class DynamicPropertyComponent {
     @Output('propertyChanged') emitter: EventEmitter<void> = new EventEmitter<void>();
     @Output() expandChild: EventEmitter<string> = new EventEmitter<string>();
     @Output() checkProperty: EventEmitter<string> = new EventEmitter<string>();
+    @Output() toggleTosca: EventEmitter<DerivedFEProperty> = new EventEmitter<DerivedFEProperty>();
     @Output() deleteItem: EventEmitter<string> = new EventEmitter<string>();
     @Output() clickOnPropertyRow: EventEmitter<PropertyFEModel | DerivedFEProperty> = new EventEmitter<PropertyFEModel | DerivedFEProperty>();
     @Output() mapKeyChanged: EventEmitter<string> = new EventEmitter<string>();
@@ -131,6 +133,10 @@ export class DynamicPropertyComponent {
         this.checkProperty.emit(propName);
     }
 
+    toggleToscaFunction = (prop: DerivedFEProperty) => {
+        this.toggleTosca.emit(prop);
+    }
+
     getHasChildren = (property:DerivedFEProperty): boolean => {// enter to this function only from base property (PropertyFEModel) and check for child property if it has children
         return _.filter((<PropertyFEModel>this.property).flattenedChildren,(prop:DerivedFEProperty)=>{
             return _.startsWith(prop.propertiesName + '#', property.propertiesName);
@@ -222,6 +228,15 @@ export class DynamicPropertyComponent {
                     delete itemParent.valueObjValidation[oldKey];
                     itemParent.valueObjIsValid = itemParent.calculateValueObjIsValid();
                 }
+                if (this.property.subPropertyToscaFunctions !== null) {
+                    let tempSubToscaFunction: SubPropertyToscaFunction[] = [];
+                    this.property.subPropertyToscaFunctions.forEach((item : SubPropertyToscaFunction, index) => {
+                        if(item.subPropertyPath[0] != oldKey){
+                            tempSubToscaFunction.push(item);
+                        }
+                    });
+                    this.property.subPropertyToscaFunctions = tempSubToscaFunction;
+                }
                 this.property.childPropMapKeyUpdated(item, null);  // remove map key
             } else {
                 const itemIndex: number = this.property.flattenedChildren.filter(prop => prop.parentName == item.parentName).map(prop => prop.propertiesName).indexOf(item.propertiesName);
@@ -241,7 +256,15 @@ export class DynamicPropertyComponent {
 
     updateChildKeyInParent(childProp: DerivedFEProperty, newMapKey: string) {
         if (this.property instanceof PropertyFEModel) {
+            let oldKey = childProp.getActualMapKey();
             this.property.childPropMapKeyUpdated(childProp, newMapKey);
+            if (this.property.subPropertyToscaFunctions != null) {
+                this.property.subPropertyToscaFunctions.forEach((item : SubPropertyToscaFunction) => {
+                    if(item.subPropertyPath[0] === oldKey){
+                        item.subPropertyPath = [newMapKey];
+                    }
+                });
+            }
             this.emitter.emit();
         }
     }
index 2d8fa77..6e4eddd 100644 (file)
@@ -89,7 +89,7 @@
                         (expandChild)="property.updateExpandedChildPropertyId($event)"
                         (clickOnPropertyRow)="onClickPropertyInnerRow($event, instanceId)"
                         (checkProperty)="propertyChecked(property, $event)"
-
+                        (toggleTosca)="toggleToscaFunction($event)"
                         >
                         
                     </dynamic-property>
index f787286..a0b4013 100644 (file)
@@ -47,6 +47,7 @@ export class PropertiesTableComponent implements OnChanges {
     @Output() selectPropertyRow: EventEmitter<PropertyRowSelectedEvent> = new EventEmitter<PropertyRowSelectedEvent>();
     @Output() updateCheckedPropertyCount: EventEmitter<boolean> = new EventEmitter<boolean>(); // only for hasDeclareOption
     @Output() updateCheckedChildPropertyCount: EventEmitter<boolean> = new EventEmitter<boolean>();//only for hasDeclareListOption
+    @Output() togggleToscaBtn: EventEmitter<boolean> = new EventEmitter<boolean>();
     @Output() deleteProperty: EventEmitter<PropertyFEModel> = new EventEmitter<PropertyFEModel>();
     private selectedPropertyToDelete: PropertyFEModel;
 
@@ -108,6 +109,10 @@ export class PropertiesTableComponent implements OnChanges {
         }
     }
 
+    toggleToscaFunction = (prop: DerivedFEProperty) => {
+        this.togggleToscaBtn.emit(prop.isSelected);
+    };
+
     onDeleteProperty = () => {
         this.deleteProperty.emit(this.selectedPropertyToDelete);
         this.modalService.closeCurrentModal();
index c01cf95..1be3495 100644 (file)
@@ -36,6 +36,7 @@
                             (selectChildProperty)="selectChildProperty($event)"
                             (updateCheckedPropertyCount)="updateCheckedPropertyCount($event)"
                             (updateCheckedChildPropertyCount)="updateCheckedChildPropertyCount($event)"
+                            (togggleToscaBtn)="togggleToscaBtn($event)"
                             (selectInstanceRow)="selectInstanceRow($event)"
                             (deleteProperty)="deleteProperty($event)">
                         </properties-table>
@@ -77,7 +78,7 @@
                 </div>
                 <button (click)="selectToscaFunctionAndValues()"
                         *ngIf="isPropertiesTabSelected && !isSelf()"
-                        [disabled]="checkedPropertiesCount != 1 || isReadonly || hasChangedData"
+                        [disabled]="(checkedPropertiesCount != 1 || isReadonly || hasChangedData) && !enableToscaFunction"
                         class="tlv-btn blue declare-button"
                         data-tests-id="declare-button select-tosca-function">{{'TOSCA_FUNCTION_LABEL' | translate}}</button>
                 <button class="tlv-btn blue declare-button" [disabled]="!checkedPropertiesCount || isReadonly || hasChangedData" (click)="declareProperties()" data-tests-id="declare-button declare-input">Declare Input</button>
index c3babc1..767acb4 100644 (file)
@@ -96,6 +96,8 @@ export class PropertiesAssignmentComponent {
     selectedInstanceData: ComponentInstance | GroupInstance | PolicyInstance = null;
     checkedPropertiesCount: number = 0;
     checkedChildPropertiesCount: number = 0;
+    enableToscaFunction: boolean = false;
+    checkedToscaCount: number = 0;
 
     hierarchyPropertiesDisplayOptions: HierarchyDisplayOptions = new HierarchyDisplayOptions('path', 'name', 'childrens');
     hierarchyInstancesDisplayOptions: HierarchyDisplayOptions = new HierarchyDisplayOptions('uniqueId', 'name', 'archived', null, 'iconClass');
@@ -578,16 +580,23 @@ export class PropertiesAssignmentComponent {
 
     private clearCheckedInstancePropertyValue() {
         const checkedInstanceProperty: PropertyBEModel = this.buildCheckedInstanceProperty();
+        let currentValue = checkedInstanceProperty.value;
         checkedInstanceProperty.getInputValues = null;
         checkedInstanceProperty.value = null;
         checkedInstanceProperty.toscaFunction = null;
         if (checkedInstanceProperty instanceof PropertyDeclareAPIModel && (<PropertyDeclareAPIModel>checkedInstanceProperty).propertiesName){
             const propertiesNameArray = (<PropertyDeclareAPIModel>checkedInstanceProperty).propertiesName;
             const parts = propertiesNameArray.split("#");
+            const currentKey = checkedInstanceProperty.type === PROPERTY_TYPES.MAP ? (<DerivedFEProperty>checkedInstanceProperty.input).mapKey : null;
             if (propertiesNameArray.length > 1){
-                const index = checkedInstanceProperty.subPropertyToscaFunctions.findIndex(existingSubPropertyToscaFunction => this.areEqual(existingSubPropertyToscaFunction.subPropertyPath, parts.slice(1)));
+                const index = checkedInstanceProperty.subPropertyToscaFunctions.findIndex(existingSubPropertyToscaFunction => this.areEqual(existingSubPropertyToscaFunction.subPropertyPath, currentKey != null ? [currentKey] : parts.slice(1)));
                 checkedInstanceProperty.subPropertyToscaFunctions.splice(index, 1);
             }
+            if(currentValue !== null && currentKey !== null){
+                let valueJson = JSON.parse(currentValue);
+                delete valueJson[currentKey];
+                checkedInstanceProperty.value = JSON.stringify(valueJson);
+            }
         }
         if (this.selectedInstanceData instanceof ComponentInstance) {
             this.updateInstanceProperty(checkedInstanceProperty);
@@ -603,18 +612,18 @@ export class PropertiesAssignmentComponent {
         if (checkedProperty instanceof PropertyDeclareAPIModel && (<PropertyDeclareAPIModel>checkedProperty).propertiesName){
             const propertiesName = (<PropertyDeclareAPIModel>checkedProperty).propertiesName;
             const parts = propertiesName.split("#");
-
+            const currentKey = checkedProperty.type === PROPERTY_TYPES.MAP ? (<DerivedFEProperty>checkedProperty.input).mapKey : null;
             if (checkedProperty.subPropertyToscaFunctions == null){
                 checkedProperty.subPropertyToscaFunctions = [];
             }
-            let subPropertyToscaFunction = checkedProperty.subPropertyToscaFunctions.find(existingSubPropertyToscaFunction => this.areEqual(existingSubPropertyToscaFunction.subPropertyPath, parts.slice(1)));
+            let subPropertyToscaFunction = checkedProperty.subPropertyToscaFunctions.find(existingSubPropertyToscaFunction => this.areEqual(existingSubPropertyToscaFunction.subPropertyPath, currentKey != null ? [currentKey] : parts.slice(1)));
             if (!subPropertyToscaFunction){
                  subPropertyToscaFunction = new SubPropertyToscaFunction();
                  checkedProperty.subPropertyToscaFunctions.push(subPropertyToscaFunction);
             }
             subPropertyToscaFunction.toscaFunction = toscaFunction;
-            subPropertyToscaFunction.subPropertyPath = parts.slice(1);
-
+            subPropertyToscaFunction.subPropertyPath = currentKey != null ? [currentKey] : parts.slice(1);
+   
         } else {
             checkedProperty.subPropertyToscaFunctions = null;
             checkedProperty.toscaFunction = toscaFunction;
@@ -634,6 +643,8 @@ export class PropertiesAssignmentComponent {
 
     updateInstanceProperty(instanceProperty: PropertyBEModel) {
         this.loadingProperties = true;
+        this.enableToscaFunction = false;
+        this.checkedToscaCount = 0;
         this.componentInstanceServiceNg2.updateInstanceProperties(this.component.componentType, this.component.uniqueId,
             this.selectedInstanceData.uniqueId, [instanceProperty])
         .subscribe(() => {
@@ -1154,6 +1165,15 @@ export class PropertiesAssignmentComponent {
         this.checkedChildPropertiesCount += (increment) ? 1 : -1;
     };
 
+    togggleToscaBtn = (toscaFlag: boolean) : void => {
+        this.checkedToscaCount += toscaFlag ? 1 : -1;
+        if(this.checkedToscaCount == 1){
+            this.enableToscaFunction = true;
+        }else{
+            this.enableToscaFunction = false;
+        }
+    };
+
     setInputTabIndication = (numInputs: number): void => {
         this.propertyInputTabs.setTabIndication('Inputs', numInputs);
     };
index 747de7c..876fc8e 100644 (file)
@@ -202,7 +202,7 @@ export class PropertiesUtils {
                 } else if (prop.derivedDataType == DerivedPropertyType.LIST) {
                     prop.valueObj = (prop.valueObj === null || typeof prop.valueObj != 'object') ? JSON.parse(prop.valueObj || '[]') : prop.valueObj;
                 } else if (prop.derivedDataType == DerivedPropertyType.MAP) {
-                    if (!prop.isChildOfListOrMap || !prop.schema.property.isSimpleType) {
+                    if (!prop.isChildOfListOrMap) {
                         prop.valueObj = (prop.valueObj === null || typeof prop.valueObj != 'object') ? JSON.parse(prop.valueObj || '{}') : prop.valueObj;
                     }
                 }
index e40a4d6..bc73796 100644 (file)
@@ -18,7 +18,7 @@
  */
 
 import {Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges} from '@angular/core';
-import {ComponentMetadata, PropertyBEModel, PropertyDeclareAPIModel} from 'app/models';
+import {ComponentMetadata, PropertyBEModel, PropertyDeclareAPIModel, DerivedFEProperty} from 'app/models';
 import {TopologyTemplateService} from "../../../services/component-services/topology-template.service";
 import {WorkspaceService} from "../../workspace/workspace.service";
 import {ToscaGetFunctionType} from "../../../../models/tosca-get-function-type";
@@ -101,8 +101,8 @@ export class ToscaFunctionComponent implements OnInit, OnChanges {
            if (this.property instanceof PropertyDeclareAPIModel && this.property.subPropertyToscaFunctions && (<PropertyDeclareAPIModel> this.property).propertiesName){
                let propertiesPath = (<PropertyDeclareAPIModel> this.property).propertiesName.split("#");
             if (propertiesPath.length > 1){
-                   propertiesPath = propertiesPath.slice(1);
-                let subPropertyToscaFunction = this.property.subPropertyToscaFunctions.find(subPropertyToscaFunction => this.areEqual(subPropertyToscaFunction.subPropertyPath, propertiesPath));
+                   let keyToFind = this.property.type === PROPERTY_TYPES.MAP ? [(<DerivedFEProperty>this.property.input).mapKey] : propertiesPath.slice(1);
+                let subPropertyToscaFunction = this.property.subPropertyToscaFunctions.find(subPropertyToscaFunction => this.areEqual(subPropertyToscaFunction.subPropertyPath, keyToFind !== null ? keyToFind : propertiesPath.slice(1)));
 
                 if (subPropertyToscaFunction){
                        this.toscaFunction = subPropertyToscaFunction.toscaFunction;
index a32a4d0..0757e3d 100644 (file)
@@ -18,7 +18,7 @@
  */
 
 import {Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges} from '@angular/core';
-import {AttributeBEModel, ComponentMetadata, DataTypeModel, PropertyBEModel, PropertyModel, PropertyDeclareAPIModel} from 'app/models';
+import {AttributeBEModel, ComponentMetadata, DataTypeModel, PropertyBEModel, PropertyModel, PropertyDeclareAPIModel, DerivedFEProperty} from 'app/models';
 import {TopologyTemplateService} from "../../../../services/component-services/topology-template.service";
 import {WorkspaceService} from "../../../workspace/workspace.service";
 import {PropertiesService} from "../../../../services/properties.service";
@@ -261,7 +261,7 @@ export class ToscaGetFunctionComponent implements OnInit, OnChanges {
     }
 
     private propertyTypeToString() {
-           if (this.isSubProperty()){
+           if (this.isSubProperty() && this.property.type != PROPERTY_TYPES.MAP){
                return this.getType((<PropertyDeclareAPIModel>this.property).propertiesName.split("#").slice(1),  this.property.type);
         }
         if (this.property.schemaType) {
@@ -367,6 +367,9 @@ export class ToscaGetFunctionComponent implements OnInit, OnChanges {
 
     private hasSameType(property: PropertyBEModel | AttributeBEModel): boolean {
         if (this.typeHasSchema(this.property.type)) {
+            if(this.property.type === PROPERTY_TYPES.MAP && this.property instanceof PropertyDeclareAPIModel && (<PropertyDeclareAPIModel> this.property).input instanceof DerivedFEProperty){
+                return property.type === this.property.schema.property.type;
+            }
             if (!property.schema || !property.schema.property) {
                 return false;
             }