[SDC-29] rebase continue work to align source
[sdc.git] / catalog-ui / src / app / ng2 / pages / properties-assignment / properties-assignment.page.component.ts
index 299615b..98fdc73 100644 (file)
@@ -1,18 +1,23 @@
 import {Component, ViewChild, ElementRef, Renderer, Inject} from "@angular/core";
 import {PostsService} from "../../services/posts.service";
-import {PropertiesService, SimpleFlatProperty} from "../../services/properties.service";
+import { PropertiesService } from "../../services/properties.service";
+import { HierarchyNavService } from "../../services/hierarchy-nav.service";
 import { PropertiesUtils } from './properties.utils';
 import { PropertyFEModel, InstanceFePropertiesMap, InstanceBePropertiesMap, InstancePropertiesAPIMap, Component as ComponentData, FilterPropertiesAssignmentData } from "app/models";
 import { PROPERTY_TYPES, ResourceType } from "app/utils";
 import property = require("lodash/property");
 import {ComponentServiceNg2} from "../../services/component-services/component.service";
 import {ComponentInstanceServiceNg2} from "../../services/component-instance-services/component-instance.service"
-import {InputFEModel, ComponentInstance, PropertyBEModel, DerivedFEProperty, ResourceInstance} from "app/models";
+import { InputFEModel, ComponentInstance, PropertyBEModel, DerivedPropertyType, DerivedFEProperty, ResourceInstance, SimpleFlatProperty } from "app/models";
 import {HierarchyDisplayOptions} from "../../components/hierarchy-navigtion/hierarchy-display-options"
 import {PropertyRowSelectedEvent} from "./../../components/properties-table/properties-table.component";
 import { KeysPipe } from 'app/ng2/pipes/keys.pipe';
 import {FilterPropertiesAssignmentComponent} from "../../components/filter-properties-assignment/filter-properties-assignment.component";
-
+import { ComponentModeService } from "app/ng2/services/component-mode.service"
+import {WorkspaceMode, EVENTS} from "../../../utils/constants";
+import {ComponentInstanceProperty, InputBEModel} from "app/models"
+import {ComponentInstanceInput} from "../../../models/properties-inputs/input-be-model";
+import {EventListenerService} from "app/services/event-listener-service"
 @Component({
     templateUrl: './properties-assignment.page.component.html',
     styleUrls: ['./properties-assignment.page.component.less']
@@ -29,39 +34,60 @@ export class PropertiesAssignmentComponent {
     inputs: Array<InputFEModel> = [];
     instances: Array<ComponentInstance> = [];
     searchQuery: string;
-    propertyStructureHeader: string
+    propertyStructureHeader: string;
 
     selectedFlatProperty: SimpleFlatProperty = new SimpleFlatProperty();
     selectedInstanceType: string;
     selectedInstanceData: ComponentInstance = new ComponentInstance();
     checkedPropertiesCount: number = 0;
 
-    hierarchyPropertiesDisplayOptions:HierarchyDisplayOptions = new HierarchyDisplayOptions('uniqueId', 'name', 'childrens');
+    hierarchyPropertiesDisplayOptions:HierarchyDisplayOptions = new HierarchyDisplayOptions('path', 'name', 'childrens');
     hierarchyInstancesDisplayOptions:HierarchyDisplayOptions = new HierarchyDisplayOptions('uniqueId', 'name');
     displayClearSearch = false;
     searchPropertyName:string;
-    hideAdvanceSearch:boolean;
+    isInpusTabSelected:boolean;
+    isReadonly:boolean;
+    loadingInstances:boolean = false;
+    loadingInputs:boolean = false;
+    loadingProperties:boolean = false;
 
     @ViewChild('hierarchyNavTabs') hierarchyNavTabs: ElementRef;
     @ViewChild('propertyInputTabs') propertyInputTabs: ElementRef;
     @ViewChild('advanceSearch') advanceSearch: FilterPropertiesAssignmentComponent;
 
-    constructor(private propertiesService:PropertiesService,
+    constructor(private propertiesService: PropertiesService,
+                private hierarchyNavService: HierarchyNavService,
                 private propertiesUtils:PropertiesUtils,
                 private componentServiceNg2:ComponentServiceNg2,
                 private componentInstanceServiceNg2:ComponentInstanceServiceNg2,
                 @Inject("$stateParams") _stateParams,
-                private renderer: Renderer) {
+                private renderer: Renderer,
+                private componentModeService:ComponentModeService,
+                private EventListenerService:EventListenerService) {
 
         this.instanceFePropertiesMap = new InstanceFePropertiesMap();
 
         /* This is the way you can access the component data, please do not use any data except metadata, all other data should be received from the new api calls on the first time
         than if the data is already exist, no need to call the api again - Ask orit if you have any questions*/
         this.component = _stateParams.component;
+        this.EventListenerService.registerObserverCallback(EVENTS.ON_CHECKOUT, this.onCheckout);
+        this.updateViewMode();
     }
 
     ngOnInit() {
         console.log("==>" + this.constructor.name + ": ngOnInit");
+        this.loadingInputs = true;
+        this.loadingInstances = true;
+        this.loadingProperties = true;
+        this.componentServiceNg2
+            .getComponentInputs(this.component)
+            .subscribe(response => {
+                _.forEach(response.inputs, (input: InputBEModel) => {
+                    this.inputs.push(new InputFEModel(input));
+                });
+                this.loadingInputs = false;
+
+            });
         this.componentServiceNg2
             .getComponentResourceInstances(this.component)
             .subscribe(response => {
@@ -70,95 +96,33 @@ export class PropertiesAssignmentComponent {
                 _.forEach(this.instances, (instance) => {
                     this.instancesNavigationData.push(instance);
                 });
-
+                this.loadingInstances = false;
+                if (this.instancesNavigationData[0] == undefined) {
+                    this.loadingProperties = false;
+                }
                 this.selectFirstInstanceByDefault();
             });
+    };
 
-        this.componentServiceNg2
-            .getComponentInputs(this.component)
-            .subscribe(response => {
-                _.forEach(response.inputs, (input: PropertyBEModel) => {
-                    this.inputs.push(new InputFEModel(input));
-                });
-            })
+    ngOnDestroy() {
+        this.EventListenerService.unRegisterObserver(EVENTS.ON_CHECKOUT);
     }
 
     selectFirstInstanceByDefault = () => {
         if (this.instancesNavigationData[0] !== undefined) {
             this.onInstanceSelectedUpdate(this.instancesNavigationData[0]);
         }
-    }
-
-    propertyValueChanged = (event) => {
-        console.log("==>" + this.constructor.name + ": propertyValueChanged " + event);
-
-        if(this.selectedInstanceData.originType === ResourceType.VF) {
-            console.log("I want to update input value on the resource instance");
-            let inputToUpdate = new PropertyBEModel(event);
-            this.componentInstanceServiceNg2
-                .updateInstanceInput(this.component, this.selectedInstanceData.uniqueId, inputToUpdate)
-                .subscribe(response => {
-                    console.log("update resource instance input and got this response: ",response);
-                })
-        }
-        else {
-            // Copying the actual value from the object ref into the value if it's from a complex type
-            if(event.isDataType) {
-                event.value = JSON.stringify(event.valueObjectRef);
-            }
-            let propertyBe = new PropertyBEModel(event);
-            this.componentInstanceServiceNg2
-                .updateInstanceProperty(this.component, this.selectedInstanceData.uniqueId, propertyBe)
-                .subscribe(response => {
-                    console.log("updated resource instance property and got this response: ",response);
-                });
-            console.log(event);
-        }
-
-    };
-
-    inputValueChanged = (event) => {
-        console.log("==>" + this.constructor.name + ": inputValueChanged");
-        let inputToUpdate = new PropertyBEModel(event);
-
-        this.componentServiceNg2
-            .updateComponentInput(this.component, inputToUpdate)
-            .subscribe(response => {
-                console.log("updated the component input and got this response: ", response);
-            })
     };
 
-    declareProperties = ():void => {
-        console.log("==>" + this.constructor.name + ": declareProperties");
-
-        let selectedProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
-
-        let instancesNames = new KeysPipe().transform(this.instanceFePropertiesMap,[]);
-        angular.forEach(instancesNames, (instanceName:string):void=>{
-            selectedProperties[instanceName] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceName]);
-            //selectedProperties[this.selectedInstanceData.uniqueId] = this.propertiesService.getCheckedProperties(this.properties);
-        });
+    updateViewMode = () => {
+        this.isReadonly = this.componentModeService.getComponentMode(this.component) === WorkspaceMode.VIEW;
+    }
 
-        let inputsToCreate: InstancePropertiesAPIMap;
-        if (this.selectedInstanceType !== ResourceType.VF) {
-            inputsToCreate = new InstancePropertiesAPIMap(null, selectedProperties);
-        } else {
-            inputsToCreate = new InstancePropertiesAPIMap(selectedProperties, null);
-        }
-        this.componentServiceNg2
-            .createInput(this.component, inputsToCreate)
-            .subscribe(response => {
-                this.setInputTabIndication(response.length);
-                this.checkedPropertiesCount = 0;
-                _.forEach(response, (input: PropertyBEModel) => { this.inputs.push(new InputFEModel(input)); });
-                this.findAndDisableDeclaredProperties();
-            });
+    onCheckout = (component:ComponentData) => {
+        this.component = component;
+        this.updateViewMode();
     }
 
-    //TODO: Can remove? no one use it
-    // getSelectedFEProps = (): Array<PropertyFEModel> => {
-    //     return this.properties.filter(prop => prop.isSelected && !prop.isDeclared);
-    // }
 
     onInstanceSelectedUpdate = (resourceInstance: ResourceInstance) => {
         console.log("==>" + this.constructor.name + ": onInstanceSelectedUpdate");
@@ -166,12 +130,15 @@ export class PropertiesAssignmentComponent {
         this.selectedInstanceData = resourceInstance;
         this.selectedInstanceType = resourceInstance.originType;
 
+        this.loadingProperties = true;
         if(resourceInstance.originType === ResourceType.VF) {
             this.componentInstanceServiceNg2
                 .getComponentInstanceInputs(this.component, resourceInstance)
                 .subscribe(response => {
                     instanceBePropertiesMap[resourceInstance.uniqueId] = response;
                     this.processInstancePropertiesResponse(instanceBePropertiesMap);
+                    this.loadingProperties = false;
+
                 });
         } else {
             this.componentInstanceServiceNg2
@@ -179,23 +146,68 @@ export class PropertiesAssignmentComponent {
                 .subscribe(response => {
                     instanceBePropertiesMap[resourceInstance.uniqueId] = response;
                     this.processInstancePropertiesResponse(instanceBePropertiesMap);
+                    this.loadingProperties = false;
                 });
         }
 
         if( this.searchPropertyName ){
             this.clearSearch();
         }
+        //clear selected property from the navigation
+        this.selectedFlatProperty = new SimpleFlatProperty();
+        this.propertiesNavigationData = [];
     };
 
     /**
      * Entry point handling response from server
      */
     processInstancePropertiesResponse = (instanceBePropertiesMap:InstanceBePropertiesMap) => {
-        this.instanceFePropertiesMap = this.propertiesUtils.convertPropertiesMapToFEAndCreateChildren(instanceBePropertiesMap); //create flattened children
-        this.findAndDisableDeclaredProperties(); //disable properties or flattened children that are declared
+        this.instanceFePropertiesMap = this.propertiesUtils.convertPropertiesMapToFEAndCreateChildren(instanceBePropertiesMap, this.inputs); //create flattened children, disable declared props, and init values
         this.checkedPropertiesCount = 0;
     };
 
+
+    /*** VALUE CHANGE EVENTS ***/
+    propertyValueChanged = (event: PropertyFEModel) => {
+        console.log("==>" + this.constructor.name + ": propertyValueChanged " + event);
+        // Copying the actual value from the object ref into the value if it's from a complex type
+        event.value = event.getJSONValue();
+
+        if (this.selectedInstanceData.originType === ResourceType.VF) {
+            console.log("I want to update input value on the resource instance");
+            let inputToUpdate = new PropertyBEModel(event);
+            this.componentInstanceServiceNg2
+                .updateInstanceInput(this.component, this.selectedInstanceData.uniqueId, inputToUpdate)
+                .subscribe(response => {
+                    console.log("update resource instance input and got this response: ", response);
+                })
+        }
+        else {
+            let propertyBe = new PropertyBEModel(event);
+            this.componentInstanceServiceNg2
+                .updateInstanceProperty(this.component, this.selectedInstanceData.uniqueId, propertyBe)
+                .subscribe(response => {
+                    console.log("updated resource instance property and got this response: ", response);
+                });
+            console.log(event);
+        }
+
+    };
+
+    inputValueChanged = (event) => {
+        console.log("==>" + this.constructor.name + ": inputValueChanged");
+        let inputToUpdate = new PropertyBEModel(event);
+
+        this.componentServiceNg2
+            .updateComponentInput(this.component, inputToUpdate)
+            .subscribe(response => {
+                console.log("updated the component input and got this response: ", response);
+            })
+    };
+
+
+    /*** HEIRARCHY/NAV RELATED FUNCTIONS ***/
+
     /**
      * Handle select node in navigation area, and select the row in table
      */
@@ -219,13 +231,13 @@ export class PropertiesAssignmentComponent {
         if(this.selectedInstanceData.originType !== ResourceType.VF) {
             let simpleFlatProperty:Array<SimpleFlatProperty>;
             if (property instanceof PropertyFEModel) {
-                simpleFlatProperty = this.propertiesService.getSimplePropertiesTree(property, instanceName);
+                simpleFlatProperty = this.hierarchyNavService.getSimplePropertiesTree(property, instanceName);
             } else if (property instanceof DerivedFEProperty) {
                 // Need to find parent PropertyFEModel
                 let parentPropertyFEModel:PropertyFEModel = _.find(this.instanceFePropertiesMap[instanceName], (tmpFeProperty):boolean => {
                     return property.propertiesName.indexOf(tmpFeProperty.name)===0;
                 });
-                simpleFlatProperty = this.propertiesService.getSimplePropertiesTree(parentPropertyFEModel, instanceName);
+                simpleFlatProperty = this.hierarchyNavService.getSimplePropertiesTree(parentPropertyFEModel, instanceName);
             }
             this.propertiesNavigationData = simpleFlatProperty;
         }
@@ -236,20 +248,10 @@ export class PropertiesAssignmentComponent {
         }
 
         // Set selected property in table
-        this.selectedFlatProperty = new SimpleFlatProperty(property.uniqueId, null, property.name, null);
+        this.selectedFlatProperty = this.hierarchyNavService.createSimpleFlatProperty(property, instanceName);
         this.renderer.invokeElementMethod(this.hierarchyNavTabs, 'triggerTabChange', ['Property Structure']);
     };
 
-    //TODO: Can remove? no one use it
-    // findParentProperty = (childProp: DerivedFEProperty): PropertyFEModel => {
-    //     return this.properties.find(prop => prop.name == childProp.propertiesName.substring(0, childProp.propertiesName.indexOf("#")));
-    // }
-
-    //used for declare button, to keep count of newly checked properties (and ignore declared properties)
-    updateCheckedPropertyCount = (increment: boolean):void => {
-        this.checkedPropertiesCount += (increment) ? 1 : -1;
-        console.log("CheckedProperties count is now.... " + this.checkedPropertiesCount);
-    }
 
     selectInstanceRow = ($event) => {//get instance name
         this.selectedInstanceData =  _.find(this.instancesNavigationData, (instance:ComponentInstance) => {
@@ -257,15 +259,90 @@ export class PropertiesAssignmentComponent {
         });
         this.renderer.invokeElementMethod(
             this.hierarchyNavTabs, 'triggerTabChange', ['Composition']);
-    }
+    };
 
     tabChanged = (event) => {
         console.log("==>" + this.constructor.name + ": tabChanged " + event);
-        this.hideAdvanceSearch = event.title !== "Properties";
+        this.isInpusTabSelected = event.title === "Inputs";
+        this.propertyStructureHeader = null;
         this.searchQuery = '';
     };
 
-    deleteInput = (input:InputFEModel) => {
+
+
+    /*** DECLARE PROPERTIES/INPUTS ***/
+    declareProperties = (): void => {
+        console.log("==>" + this.constructor.name + ": declareProperties");
+
+        let selectedProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
+
+        let instancesNames = new KeysPipe().transform(this.instanceFePropertiesMap, []);
+        angular.forEach(instancesNames, (instanceName: string): void => {
+            selectedProperties[instanceName] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceName]);
+            //selectedProperties[this.selectedInstanceData.uniqueId] = this.propertiesService.getCheckedProperties(this.properties);
+        });
+
+        let inputsToCreate: InstancePropertiesAPIMap;
+        if (this.selectedInstanceType !== ResourceType.VF) {
+            inputsToCreate = new InstancePropertiesAPIMap(null, selectedProperties);
+        } else {
+            inputsToCreate = new InstancePropertiesAPIMap(selectedProperties, null);
+        }
+        this.componentServiceNg2
+            .createInput(this.component, inputsToCreate)
+            .subscribe(response => {
+                this.setInputTabIndication(response.length);
+                this.checkedPropertiesCount = 0;
+                _.forEach(response, (input: InputBEModel) => {
+                    this.inputs.push(new InputFEModel(input));
+                    this.updatePropertyValueAfterDeclare(input);
+                });
+            });
+    };
+
+    updatePropertyValueAfterDeclare = (input: InputBEModel) => {
+        _.forEach(input.properties, (property: ComponentInstanceProperty) => {
+            this.updatePropertyOrInputValueAfterDeclare(property, input);
+        });
+
+        _.forEach(input.inputs, (inputInstance: ComponentInstanceInput) => {
+            this.updatePropertyOrInputValueAfterDeclare(inputInstance, input);
+        });
+    }
+
+    updatePropertyOrInputValueAfterDeclare = (inputSource: ComponentInstanceProperty | ComponentInstanceInput, input: InputBEModel) => {
+        if (this.instanceFePropertiesMap[inputSource.componentInstanceId]) {
+            let propertyForUpdatindVal = _.find(this.instanceFePropertiesMap[inputSource.componentInstanceId], (feProperty: PropertyFEModel) => {
+                return feProperty.name == inputSource.name;
+            });
+
+            if (input.inputPath == propertyForUpdatindVal.name) input.inputPath = null; //Fix - if inputPath is sent for parent props, remove it
+
+            propertyForUpdatindVal.setAsDeclared(input.inputPath); //set prop as declared before assigning value
+            this.propertiesService.disableRelatedProperties(propertyForUpdatindVal, input.inputPath);
+            this.propertiesUtils.resetPropertyValue(propertyForUpdatindVal, inputSource.value, input.inputPath);
+            // if (input.inputPath) {
+            //     let childProp = _.find(propertyForUpdatindVal.flattenedChildren, (child: DerivedFEProperty) => {
+            //         return child.propertiesName == input.inputPath;
+            //     });
+            //     this.propertiesUtils.assignFlattenedChildrenValues(JSON.parse(inputSource.value), [childProp], inputSource.name);
+            // } else {
+            //     propertyForUpdatindVal.valueObj = inputSource.value;
+            // }
+        }
+    }
+
+    //used for declare button, to keep count of newly checked properties (and ignore declared properties)
+    updateCheckedPropertyCount = (increment: boolean): void => {
+        this.checkedPropertiesCount += (increment) ? 1 : -1;
+        console.log("CheckedProperties count is now.... " + this.checkedPropertiesCount);
+    };
+
+    setInputTabIndication = (numInputs: number): void => {
+        this.renderer.invokeElementMethod(this.propertyInputTabs, 'setTabIndication', ['Inputs', numInputs]);
+    };
+
+    deleteInput = (input: InputFEModel) => {
         console.log("==>" + this.constructor.name + ": deleteInput");
         let inputToDelete = new PropertyBEModel(input);
 
@@ -273,51 +350,45 @@ export class PropertiesAssignmentComponent {
             .deleteInput(this.component, inputToDelete)
             .subscribe(response => {
                 this.inputs = this.inputs.filter(input => input.uniqueId !== response.uniqueId);
-                let propToEnable: PropertyFEModel = this.instanceFePropertiesMap[input.instanceName].find(prop => prop.name == input.propertyName);
-                propToEnable.setNonDeclared(response.inputPath);
-                this.propertiesService.undoDisableRelatedProperties(propToEnable, response.inputPath);
-                //this.propertiesService.initValueObjectRef(propToEnable); //TODO:speak to BE about value returned by server
-            });
-    }
 
-    setInputTabIndication = (numInputs: number): void => {
-        this.renderer.invokeElementMethod( this.propertyInputTabs, 'setTabIndication', ['Inputs', numInputs]);
-    }
+                //Reload the whole instance for now - TODO: CHANGE THIS after the BE starts returning properties within the response, use commented code below instead!
+                this.onInstanceSelectedUpdate(this.selectedInstanceData);
+                // let instanceFeProperties = this.instanceFePropertiesMap[this.getInstanceUniqueId(input.instanceName)];
+
+                // if (instanceFeProperties) {
+                //     let propToEnable: PropertyFEModel = instanceFeProperties.find((prop) => {
+                //         return prop.name == input.propertyName;
+                //     });
+
+                //     if (propToEnable) {
+                //         if (propToEnable.name == response.inputPath) response.inputPath = null;
+                //         propToEnable.setNonDeclared(response.inputPath);
+                //         //this.propertiesUtils.resetPropertyValue(propToEnable, newValue, response.inputPath);
+                //         this.propertiesService.undoDisableRelatedProperties(propToEnable, response.inputPath);
+                //     }
+                // }
+            });
+    };
 
-    findAndDisableDeclaredProperties = () => {
-        this.inputs.filter(input => input.instanceName === this.selectedInstanceData.normalizedName).forEach(input => {
-            let prop: PropertyFEModel = this.instanceFePropertiesMap[this.selectedInstanceData.uniqueId].find(prop => prop.name === input.propertyName);
-            if (prop) {
-                prop.setAsDeclared(input.inputPath); //if a path was sent, its a child prop. this param is optional
-                this.propertiesService.disableRelatedProperties(prop, input.inputPath)
-                //this.propertiesService.initValueObjectRef(prop);
-            }
+    getInstanceUniqueId = (instanceName: string): string => {
+        let wantedInstance: ComponentInstance = this.instances.find((instance) => {
+            return instance.normalizedName === instanceName;
         });
+
+        return wantedInstance.uniqueId;
     };
 
+
+
+    /*** SEARCH RELATED FUNCTIONS ***/
     searchPropertiesInstances = (filterData:FilterPropertiesAssignmentData) => {
-        //let filteredProperties = this.componentServiceNg2.filterComponentInstanceProperties(this.component, filterData);
         let instanceBePropertiesMap:InstanceBePropertiesMap;
         this.componentServiceNg2
             .filterComponentInstanceProperties(this.component, filterData)
             .subscribe(response => {
-                //instanceBePropertiesMap=response;
-                //console.log("================filter results=============");
-                //console.table(instanceBePropertiesMap);
-                this.processInstancePropertiesResponse(response);
-
-
-                //this.properties = [];
-                // _.forEach(instanceBePropertiesMap, (InstanceProperties:Array<PropertyBEModel>, instanceName:string) => {
-                //     this.properties = this.properties.concat(this.propertiesService.convertPropertiesToFEAndCreateChildren(InstanceProperties, instanceName));
-                // });
-
-
-                // this.instancesNavigationData = _.filter(this.instancesNavigationData, (instance:ComponentInstance) => {
-                //     return instanceBePropertiesMap[instance.name];
-                // });
 
-                // this.hierarchyPropertiesDisplayOptions.searchText = filterData.propertyName;//mark results in tree
+                this.processInstancePropertiesResponse(response);
+                this.hierarchyPropertiesDisplayOptions.searchText = filterData.propertyName;//mark results in tree
                 this.searchPropertyName = filterData.propertyName;//mark in table
                 this.renderer.invokeElementMethod(this.hierarchyNavTabs, 'triggerTabChange', ['Composition']);
                 this.propertiesNavigationData = [];
@@ -332,13 +403,13 @@ export class PropertiesAssignmentComponent {
         this.hierarchyPropertiesDisplayOptions.searchText = "";
         this.displayClearSearch = false;
         this.advanceSearch.clearAll();
-    }
+    };
 
     clickOnClearSearch = () => {
         this.clearSearch();
         this.selectFirstInstanceByDefault();
         this.renderer.invokeElementMethod(
             this.hierarchyNavTabs, 'triggerTabChange', ['Composition']);
-    }
+    };
 
 }