[SDC] rebase 1710

Change-Id: I07fced02f40a57700d9d35ed3ba498bca351fb13
Signed-off-by: Michael Lando <ml636r@att.com>
diff --git a/catalog-ui/src/app/app.ts b/catalog-ui/src/app/app.ts
index 707d7e4..805e5f0 100644
--- a/catalog-ui/src/app/app.ts
+++ b/catalog-ui/src/app/app.ts
@@ -53,6 +53,7 @@
 
 import {AppModule} from './ng2/app.module';
 import {PropertiesAssignmentComponent} from "./ng2/pages/properties-assignment/properties-assignment.page.component";
+import { SearchWithAutoCompleteComponent } from "./ng2/shared/search-with-autocomplete/search-with-autocomplete.component";
 import {Component} from "./models/components/component";
 import {ComponentServiceNg2} from "./ng2/services/component-services/component.service";
 import {ComponentMetadata} from "./models/component-metadata";
@@ -145,6 +146,13 @@
 
 export const ng1appModule:ng.IModule = angular.module(moduleName, dependentModules);
 angular.module('sdcApp').directive('propertiesAssignment', downgradeComponent({component: PropertiesAssignmentComponent}) as angular.IDirectiveFactory);
+angular.module('sdcApp').directive('ng2SearchWithAutocomplete',
+    downgradeComponent({
+        component: SearchWithAutoCompleteComponent,
+        inputs: ['searchPlaceholder', 'searchBarClass', 'autoCompleteValues'],
+        outputs: ['searchChanged', 'searchButtonClicked']
+    }) as angular.IDirectiveFactory);
+
 
 ng1appModule.config([
     '$stateProvider',
@@ -161,7 +169,7 @@
      NotificationProvider:any):void => {
 
         NotificationProvider.setOptions({
-            delay: 10000,
+            delay: 5000,
             startTop: 10,
             startRight: 10,
             closeOnClick: true,
@@ -170,6 +178,7 @@
             positionX: 'right',
             positionY: 'top'
         });
+        NotificationProvider.options.templateUrl = 'notification-custom-template.html';
 
         $translateProvider.useStaticFilesLoader({
             prefix: pathPrefix + 'assets/languages/',
@@ -617,6 +626,7 @@
     'LeftPaletteLoaderService',
     'Sdc.Services.DataTypesService',
     'AngularJSBridge',
+    '$templateCache',
     ($http:ng.IHttpService,
      cacheService:CacheService,
      cookieService:CookieService,
@@ -632,8 +642,9 @@
      ecompHeaderService:EcompHeaderService,
      LeftPaletteLoaderService:LeftPaletteLoaderService,
      DataTypesService:DataTypesService,
-     AngularJSBridge):void => {
-
+     AngularJSBridge,
+     $templateCache:ng.ITemplateCacheService):void => {
+        $templateCache.put('notification-custom-template.html', require('./view-models/shared/notification-custom-template.html'));
         //handle cache data - version
         let initAsdcVersion:Function = ():void => {
 
diff --git a/catalog-ui/src/app/directives/graphs-v2/common/style/component-instances-nodes-style.ts b/catalog-ui/src/app/directives/graphs-v2/common/style/component-instances-nodes-style.ts
index 0dcc93d..6419759 100644
--- a/catalog-ui/src/app/directives/graphs-v2/common/style/component-instances-nodes-style.ts
+++ b/catalog-ui/src/app/directives/graphs-v2/common/style/component-instances-nodes-style.ts
@@ -231,7 +231,7 @@
 
     public static getBasicNodeHanlde = () => {
         return {
-            positionX: "center",
+            positionX: "right",
             positionY: "top",
             offsetX: 15,
             offsetY: -20,
@@ -248,7 +248,7 @@
 
     public static getBasicSmallNodeHandle = () => {
         return {
-            positionX: "center",
+            positionX: "right",
             positionY: "top",
             offsetX: 3,
             offsetY: -25,
diff --git a/catalog-ui/src/app/directives/graphs-v2/composition-graph/composition-graph.directive.ts b/catalog-ui/src/app/directives/graphs-v2/composition-graph/composition-graph.directive.ts
index 651a428..9aa7941 100644
--- a/catalog-ui/src/app/directives/graphs-v2/composition-graph/composition-graph.directive.ts
+++ b/catalog-ui/src/app/directives/graphs-v2/composition-graph/composition-graph.directive.ts
@@ -47,7 +47,8 @@
 
     component:Component;
     isLoading: boolean;
-    isViewOnly:boolean;
+    isViewOnly: boolean;
+    withSidebar: boolean;
     // Link menu - create link menu
     relationMenuDirectiveObj:RelationMenuDirectiveObj;
     isLinkMenuOpen:boolean;
@@ -65,6 +66,14 @@
     //Links menus
     deleteRelation(link:Cy.CollectionEdges):void;
     hideRelationMenu();
+
+    //search,zoom in/out/all
+    componentInstanceNames: Array<string>; //id, name
+    zoom(zoomIn: boolean): void;
+    zoomAll(nodes?:Cy.CollectionNodes): void;
+    getAutoCompleteValues(searchTerm: string):void;
+    highlightSearchMatches(searchTerm: string): void;
+    
     /*//asset popover menu
     assetPopoverObj:AssetPopoverObj;
     assetPopoverOpen:boolean;
@@ -101,7 +110,8 @@
     template = require('./composition-graph.html');
     scope = {
         component: '=',
-        isViewOnly: '='
+        isViewOnly: '=',
+        withSidebar: '='
     };
 
     link = (scope:ICompositionGraphScope, el:JQuery) => {
@@ -147,7 +157,11 @@
         this._cy = cytoscape({
             container: graphEl,
             style: ComponentInstanceNodesStyle.getCompositionGraphStyle(),
-            zoomingEnabled: false,
+            zoomingEnabled: true,
+            maxZoom: 2.5,
+            minZoom: .1,
+            userZoomingEnabled: false,
+            userPanningEnabled: true,
             selectionType: 'single',
             boxSelectionEnabled: true,
             autolock: isViewOnly,
@@ -270,6 +284,40 @@
             this.loadGraphData(scope);
         });
 
+        scope.zoom = (zoomIn: boolean):void => {
+            let currentZoom: number = this._cy.zoom();
+            if (zoomIn) {
+                this.GeneralGraphUtils.zoomGraphTo(this._cy, currentZoom + .1);
+            } else {
+                this.GeneralGraphUtils.zoomGraphTo(this._cy, currentZoom - .1);
+            }
+        }
+
+        //Zooms to fit all of the nodes in the collection passed in. If no nodes are passed in, will zoom to fit all nodes on graph
+        scope.zoomAll = (nodes?:Cy.CollectionNodes) => {
+            scope.withSidebar = false;
+            this._cy.animate({
+                fit: { eles: nodes, padding: 20 },
+                center: { eles: nodes }
+            }, { duration: 400 });
+        };
+
+        scope.getAutoCompleteValues = (searchTerm: string) => {
+            if (searchTerm.length > 1) { //US requirement: only display search results after 2nd letter typed.
+                let nodes: Cy.CollectionNodes = this.NodesGraphUtils.getMatchingNodesByName(this._cy, searchTerm);
+                scope.componentInstanceNames = _.map(nodes, node => node.data('name'));
+            } else {
+                scope.componentInstanceNames = [];
+            }
+        };
+
+        scope.highlightSearchMatches = (searchTerm: string) => {
+            if (searchTerm === undefined) return; //dont zoom & highlight if click on Search initially (searchTerm will be undefined). However, allow highlights to be cleared after subsequent search (searchTerm will be "")
+            
+            this.NodesGraphUtils.highlightMatchingNodesByName(this._cy, searchTerm);
+            let matchingNodes: Cy.CollectionNodes = this.NodesGraphUtils.getMatchingNodesByName(this._cy, searchTerm);
+            scope.zoomAll(matchingNodes);
+        };
 
         scope.createLinkFromMenu = (chosenMatch:MatchBase):void => {
             scope.isLinkMenuOpen = false;
@@ -367,7 +415,7 @@
         });*/
         this._cy.on('handlemouseover', (event, payload) => {
 
-            if (payload.node.grabbed() /* || this._cy.scratch('_edge_editation_highlights') === true*/) { //no need to add opacity while we are dragging and hovering othe nodes- or if opacity was already calculated for these nodes
+            if (payload.node.grabbed() || this._cy.scratch('_edge_editation_highlights') === true) { //no need to add opacity while we are dragging and hovering othe nodes- or if opacity was already calculated for these nodes
                 return;
             }
             let nodesData = this.NodesGraphUtils.getAllNodesData(this._cy.nodes());
@@ -377,9 +425,9 @@
             let filteredNodesData = this.matchCapabilitiesRequirementsUtils.findByMatchingCapabilitiesToRequirements(payload.node.data().componentInstance, linkableNodes, nodesLinks);
             this.matchCapabilitiesRequirementsUtils.highlightMatchingComponents(filteredNodesData, this._cy);
             this.matchCapabilitiesRequirementsUtils.fadeNonMachingComponents(filteredNodesData, nodesData, this._cy, payload.node.data());
-            /*
+            
             this._cy.scratch()._edge_editation_highlights = true;
-            scope.hideAssetPopover();*/
+            /*scope.hideAssetPopover();*/
         });
 
         this._cy.on('handlemouseout', () => {
diff --git a/catalog-ui/src/app/directives/graphs-v2/composition-graph/composition-graph.html b/catalog-ui/src/app/directives/graphs-v2/composition-graph/composition-graph.html
index 1e69d33..248f19f 100644
--- a/catalog-ui/src/app/directives/graphs-v2/composition-graph/composition-graph.html
+++ b/catalog-ui/src/app/directives/graphs-v2/composition-graph/composition-graph.html
@@ -20,4 +20,11 @@
 
 </div>
 
+    <div class="w-sdc-search-menu" data-ng-class="{'with-sidebar': withSidebar}">
+        <ng2-search-with-autocomplete [search-placeholder]="'Type to search'" [auto-complete-values]="componentInstanceNames" (search-changed)="getAutoCompleteValues($event)" (search-button-clicked)="highlightSearchMatches($event)"
+            [search-bar-class]="'composition-search'"></ng2-search-with-autocomplete>
+        <div class="zoom-icons sprite-new canvas-fit-all" data-ng-click="zoomAll()"></div>
+        <div class="zoom-icons sprite-new zoom-plus" data-ng-click="zoom(true)"></div>
+        <div class="zoom-icons sprite-new zoom-minus" data-ng-click="zoom(false)"></div>
+    </div>
 <!--<asset-popover ng-if="assetPopoverOpen" asset-popover-obj="assetPopoverObj" delete-asset="deleteNode(assetPopoverObj.nodeId)"></asset-popover>-->
diff --git a/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-general-utils.ts b/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-general-utils.ts
index 6080314..0ea38af 100644
--- a/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-general-utils.ts
+++ b/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-general-utils.ts
@@ -64,6 +64,14 @@
     };
 
 
+    public zoomGraphTo = (cy:Cy.Instance, zoomLevel: number):void => {
+        let zy = cy.height() / 2;
+        let zx = cy.width() / 2;
+        cy.zoom({
+            level: zoomLevel,
+            renderedPosition: { x: zx, y: zy }
+        });
+    }
     /**
      * will return true/false if two nodes overlapping
      *
diff --git a/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-nodes-utils.ts b/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-nodes-utils.ts
index feb6ac9..449d551 100644
--- a/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-nodes-utils.ts
+++ b/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-nodes-utils.ts
@@ -48,6 +48,21 @@
         })
     };
 
+
+    public highlightMatchingNodesByName = (cy: Cy.Instance, nameToMatch: string) => {
+
+        cy.batch(() => {
+            cy.nodes("[name !@^= '" + nameToMatch + "']").style({ 'background-image-opacity': 0.4 });
+            cy.nodes("[name @^= '" + nameToMatch + "']").style({ 'background-image-opacity': 1 });
+        })
+        
+    }
+
+    //Returns all nodes whose name starts with searchTerm
+    public getMatchingNodesByName = (cy: Cy.Instance, nameToMatch: string): Cy.CollectionNodes => {
+        return cy.nodes("[name @^= '" + nameToMatch + "']");
+    };
+
     /**
      * Deletes component instances on server and then removes it from the graph as well
      * @param cy
diff --git a/catalog-ui/src/app/models/components/component.ts b/catalog-ui/src/app/models/components/component.ts
index 9b2c942..53e8f05 100644
--- a/catalog-ui/src/app/models/components/component.ts
+++ b/catalog-ui/src/app/models/components/component.ts
@@ -923,16 +923,17 @@
     }
 
     public toJSON = ():any => {
-        this.componentService = undefined;
-        this.filterTerm = undefined;
-        this.iconSprite = undefined;
-        this.mainCategory = undefined;
-        this.subCategory = undefined;
-        this.selectedInstance = undefined;
-        this.showMenu = undefined;
-        this.$q = undefined;
-        this.selectedCategory = undefined;
-        return this;
+        let temp = angular.copy(this);
+        temp.componentService = undefined;
+        temp.filterTerm = undefined;
+        temp.iconSprite = undefined;
+        temp.mainCategory = undefined;
+        temp.subCategory = undefined;
+        temp.selectedInstance = undefined;
+        temp.showMenu = undefined;
+        temp.$q = undefined;
+        temp.selectedCategory = undefined;
+        return temp;
     };
 }
 
diff --git a/catalog-ui/src/app/models/components/resource.ts b/catalog-ui/src/app/models/components/resource.ts
index 138b413..cd83978 100644
--- a/catalog-ui/src/app/models/components/resource.ts
+++ b/catalog-ui/src/app/models/components/resource.ts
@@ -163,17 +163,18 @@
     };
 
     public toJSON = ():any => {
-        this.componentService = undefined;
-        this.filterTerm = undefined;
-        this.iconSprite = undefined;
-        this.mainCategory = undefined;
-        this.subCategory = undefined;
-        this.selectedInstance = undefined;
-        this.showMenu = undefined;
-        this.$q = undefined;
-        this.selectedCategory = undefined;
-        this.importedFile = undefined;
-        return this;
+        let temp = angular.copy(this);
+        temp.componentService = undefined;
+        temp.filterTerm = undefined;
+        temp.iconSprite = undefined;
+        temp.mainCategory = undefined;
+        temp.subCategory = undefined;
+        temp.selectedInstance = undefined;
+        temp.showMenu = undefined;
+        temp.$q = undefined;
+        temp.selectedCategory = undefined;
+        temp.importedFile = undefined;
+        return temp;
     };
 }
 
diff --git a/catalog-ui/src/app/ng2/app.module.ts b/catalog-ui/src/app/ng2/app.module.ts
index 09b40e9..57adb8f 100644
--- a/catalog-ui/src/app/ng2/app.module.ts
+++ b/catalog-ui/src/app/ng2/app.module.ts
@@ -40,6 +40,8 @@
 import { InterceptorService } from 'ng2-interceptors';
 import { XHRBackend, RequestOptions } from '@angular/http';
 import {HttpInterceptor} from "./services/http.interceptor.service";
+import { SearchBarComponent } from './shared/search-bar/search-bar.component';
+import { SearchWithAutoCompleteComponent } from './shared/search-with-autocomplete/search-with-autocomplete.component';
 
 export const upgradeAdapter = new UpgradeAdapter(forwardRef(() => AppModule));
 
@@ -60,7 +62,9 @@
 
 @NgModule({
     declarations: [
-        AppComponent
+        AppComponent,
+        SearchBarComponent,
+        SearchWithAutoCompleteComponent
     ],
     imports: [
         BrowserModule,
@@ -70,7 +74,7 @@
         PropertiesAssignmentModule
     ],
     exports: [],
-    entryComponents: [],
+    entryComponents: [SearchWithAutoCompleteComponent],
     providers: [
         DataTypesServiceProvider,
         SharingServiceProvider,
diff --git a/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.less b/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.less
index 05378f0..89c7287 100644
--- a/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.less
+++ b/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.less
@@ -85,7 +85,7 @@
             border-right:#d2d2d2 solid 1px;
         }
         &.col1 {
-            flex: 0 0 300px;
+            flex: 1 0 200px;
             max-width:300px;
             display: flex;
             justify-content: space-between;
diff --git a/catalog-ui/src/app/ng2/components/properties-table/properties-table.component.less b/catalog-ui/src/app/ng2/components/properties-table/properties-table.component.less
index 3eb7e96..9ede84f 100644
--- a/catalog-ui/src/app/ng2/components/properties-table/properties-table.component.less
+++ b/catalog-ui/src/app/ng2/components/properties-table/properties-table.component.less
@@ -91,7 +91,7 @@
             border-right:#d2d2d2 solid 1px;
         }
         &.col1 {
-            flex: 0 0 300px;
+            flex: 1 0 210px;
             max-width:300px;
             display: flex;
             justify-content: space-between;
@@ -100,7 +100,7 @@
             .property-name {
                 flex: 1;
                 display: flex;
-                max-width: 270px;
+                max-width: 90%;
             }
 
             .property-description-icon {
@@ -123,7 +123,7 @@
         }
 
         &.valueCol {
-            flex: 1 0 350px;
+            flex: 2 0 300px;
             display: flex;
             @media @smaller-screen { flex: 1 0 40%;}
         }
diff --git a/catalog-ui/src/app/ng2/shared/search-bar/search-bar.component.html b/catalog-ui/src/app/ng2/shared/search-bar/search-bar.component.html
new file mode 100644
index 0000000..3662959
--- /dev/null
+++ b/catalog-ui/src/app/ng2/shared/search-bar/search-bar.component.html
@@ -0,0 +1,5 @@
+<div class="search-bar-container {{class}}">
+    <input class="search-bar-input" type="text" [placeholder]="placeholder" [(ngModel)]="searchQuery" (ngModelChange)="searchQueryChange($event)"/>
+    <span class="clear-search-x" *ngIf="searchQuery" (click)="clearSearchQuery()">x</span>
+    <button class="search-bar-button" (click)="searchButtonClick()"></button>
+</div>
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/shared/search-bar/search-bar.component.less b/catalog-ui/src/app/ng2/shared/search-bar/search-bar.component.less
new file mode 100644
index 0000000..cfeb8d3
--- /dev/null
+++ b/catalog-ui/src/app/ng2/shared/search-bar/search-bar.component.less
@@ -0,0 +1,58 @@
+.search-bar-container {
+    display:flex;
+    border-radius: 4px;
+    box-shadow: 0px 2px 3.88px 0.12px rgba(0, 0, 0, 0.29);
+
+    .search-bar-input {
+        border: 1px solid #cdcdcd;
+        border-radius: 4px;
+        border-right:none;
+        border-top-right-radius: 0;
+        border-bottom-right-radius: 0;
+        outline:none;
+        padding:2px 50px 2px 10px;
+        color:  #5a5a5a;
+        font-size: 1em;
+        font-style: italic;
+    }
+
+    .clear-search-x {
+        position:absolute;
+        right:40px;
+        top:5px;
+        padding: 0 5px;
+        
+        &:hover {
+            border-radius:2px;
+            background-color: #ebebeb;
+            cursor:pointer;
+        }
+    }
+
+    .search-bar-button {
+        //background: url('../../../../assets/styles/svg/source/search-magnify.svg') no-repeat 50%;
+        background: url('../../../../assets/styles/images/sprites/sprite-global.png') no-repeat -206px -1275px;
+        background-color:  rgba(234, 234, 234, 0.88);
+        width: 30px;
+        height: 30px;
+        padding: 0;
+        cursor:pointer;
+        border:solid 1px #cdcdcd;
+        border-top-right-radius: 4px;
+        border-bottom-right-radius: 4px;
+
+        &:hover {
+            background-position:-126px -1275px;
+        }
+
+        &:active {
+            background-color:  rgba(31, 171, 223, 0.88);
+            background-position:-45px -1275px;
+            border-left:none;
+        }
+        &:focus {
+            outline:none;
+        }
+
+    }
+}
diff --git a/catalog-ui/src/app/ng2/shared/search-bar/search-bar.component.ts b/catalog-ui/src/app/ng2/shared/search-bar/search-bar.component.ts
new file mode 100644
index 0000000..2835d20
--- /dev/null
+++ b/catalog-ui/src/app/ng2/shared/search-bar/search-bar.component.ts
@@ -0,0 +1,30 @@
+import { Component, Input, Output, EventEmitter, ViewEncapsulation } from '@angular/core';
+
+@Component({
+    selector: 'search-bar',
+    templateUrl: './search-bar.component.html',
+    styleUrls: ['./search-bar.component.less'],
+    encapsulation: ViewEncapsulation.None
+})
+export class SearchBarComponent {
+
+    @Input() placeholder: string;
+    @Input() class: string;
+    @Input() searchQuery: string;
+    @Output() searchChanged: EventEmitter<any> = new EventEmitter<any>();
+    @Output() searchButtonClicked: EventEmitter<string> = new EventEmitter<string>();
+
+    searchButtonClick = (): void => {
+        this.searchButtonClicked.emit(this.searchQuery);
+    }
+
+    searchQueryChange = ($event): void => {
+        this.searchChanged.emit($event);
+    }
+
+    private clearSearchQuery = (): void => {
+        this.searchQuery = "";
+        this.searchButtonClick();
+    }
+}
+
diff --git a/catalog-ui/src/app/ng2/shared/search-with-autocomplete/search-with-autocomplete.component.html b/catalog-ui/src/app/ng2/shared/search-with-autocomplete/search-with-autocomplete.component.html
new file mode 100644
index 0000000..c9769ba
--- /dev/null
+++ b/catalog-ui/src/app/ng2/shared/search-with-autocomplete/search-with-autocomplete.component.html
@@ -0,0 +1,6 @@
+<div class="search-with-autocomplete-container {{searchBarClass}}" [class.autocomplete-visible]="autoCompleteValues && autoCompleteValues.length" [class.active]="searchQuery && searchQuery.length">
+    <search-bar [placeholder]="searchPlaceholder" [searchQuery]="searchQuery" (searchButtonClicked)="updateSearch($event)" (searchChanged)="searchChange($event)"></search-bar>
+    <div class="autocomplete-results">
+        <div *ngFor="let item of autoCompleteValues" class="autocomplete-result-item" (click)="updateSearch(item)">{{item}}</div>
+    </div>
+</div>
\ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/shared/search-with-autocomplete/search-with-autocomplete.component.less b/catalog-ui/src/app/ng2/shared/search-with-autocomplete/search-with-autocomplete.component.less
new file mode 100644
index 0000000..92b054c
--- /dev/null
+++ b/catalog-ui/src/app/ng2/shared/search-with-autocomplete/search-with-autocomplete.component.less
@@ -0,0 +1,35 @@
+
+.search-with-autocomplete-container{  
+    &.autocomplete-visible {
+
+        .search-bar-input {
+            border-bottom-left-radius: 0;
+        }
+        .search-bar-button {
+            border-bottom-right-radius: 0;
+        }
+        .autocomplete-results {
+            border: solid 1px #d2d2d2;
+            border-top:none;
+            border-bottom-left-radius: 4px;
+            border-bottom-right-radius: 4px;
+            background-color: #fff;
+            padding: 10px 20px;
+            width:100%;
+            position:absolute;
+            max-height: 200px;
+            overflow-y: scroll;
+        }
+
+        .autocomplete-result-item {
+            color:#5a5a5a;
+            padding: 5px 0;
+            cursor:pointer;
+
+            &:hover {
+                color: #999;
+            }
+        }
+    }
+}
+
diff --git a/catalog-ui/src/app/ng2/shared/search-with-autocomplete/search-with-autocomplete.component.ts b/catalog-ui/src/app/ng2/shared/search-with-autocomplete/search-with-autocomplete.component.ts
new file mode 100644
index 0000000..ced056d
--- /dev/null
+++ b/catalog-ui/src/app/ng2/shared/search-with-autocomplete/search-with-autocomplete.component.ts
@@ -0,0 +1,30 @@
+import { Component, Input, Output, EventEmitter, ViewEncapsulation } from '@angular/core';
+import { SearchBarComponent } from '../search-bar/search-bar.component';
+
+@Component({
+    selector: 'search-with-autocomplete',
+    templateUrl: './search-with-autocomplete.component.html',
+    styleUrls: ['./search-with-autocomplete.component.less'],
+    encapsulation: ViewEncapsulation.None
+})
+export class SearchWithAutoCompleteComponent {
+
+    @Input() searchPlaceholder: string;
+    @Input() searchBarClass: string;
+    @Input() searchQuery: string;
+    @Input() autoCompleteValues: Array<string>;
+    @Output() searchChanged: EventEmitter<any> = new EventEmitter<any>();
+    @Output() searchButtonClicked: EventEmitter<string> = new EventEmitter<string>();
+
+    searchChange = (searchTerm: string) => {
+        this.searchQuery = searchTerm;
+        this.searchChanged.emit(searchTerm);
+    }
+
+    updateSearch = (searchTerm: string) => {
+        this.searchQuery = searchTerm;
+        this.searchButtonClicked.emit(searchTerm);
+        this.autoCompleteValues = [];
+    }
+}
+
diff --git a/catalog-ui/src/app/view-models/shared/notification-custom-template.html b/catalog-ui/src/app/view-models/shared/notification-custom-template.html
new file mode 100644
index 0000000..d8fdf13
--- /dev/null
+++ b/catalog-ui/src/app/view-models/shared/notification-custom-template.html
@@ -0,0 +1,14 @@
+<div class="ui-notification">
+    <div class="notification-container">
+        <div class="icon-container">
+            <div class="icon-circle">
+                <div class="icon sprite-new">
+                </div>
+            </div>
+        </div>
+        <div class="msg-content">
+            <h3 ng-show="title" ng-bind-html="title"></h3>
+            <div class="message" ng-bind-html="message"></div>
+        </div>
+    </div>
+</div>
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/composition-view-model.ts b/catalog-ui/src/app/view-models/workspace/tabs/composition/composition-view-model.ts
index fbd32cc..0e5a5fc 100644
--- a/catalog-ui/src/app/view-models/workspace/tabs/composition/composition-view-model.ts
+++ b/catalog-ui/src/app/view-models/workspace/tabs/composition/composition-view-model.ts
@@ -30,7 +30,8 @@
 export interface ICompositionViewModelScope extends IWorkspaceViewModelScope {
 
     currentComponent:Component;
-    selectedComponent:Component;
+    selectedComponent: Component;
+    componentInstanceNames: Array<string>;
     isLoading:boolean;
     graphApi:any;
     sharingService:SharingService;
@@ -130,7 +131,6 @@
     private openUpdateComponentInstanceNameModal = ():void => {
         this.ModalsHandler.openUpdateComponentInstanceNameModal(this.$scope.currentComponent).then(()=> {
             this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_COMPONENT_INSTANCE_NAME_CHANGED, this.$scope.currentComponent.selectedInstance);
-
         });
     };
 
@@ -225,7 +225,7 @@
         this.$scope.openUpdateModal = ():void => {
             this.openUpdateComponentInstanceNameModal();
         };
-
+    
         this.$scope.deleteSelectedComponentInstance = ():void => {
             let state = "deleteInstance";
             let onOk = ():void => {
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/composition-view.html b/catalog-ui/src/app/view-models/workspace/tabs/composition/composition-view.html
index cef942e..e05574e 100644
--- a/catalog-ui/src/app/view-models/workspace/tabs/composition/composition-view.html
+++ b/catalog-ui/src/app/view-models/workspace/tabs/composition/composition-view.html
@@ -6,7 +6,7 @@
                  is-loading="isLoading"></palette>
 
         <composition-graph component="currentComponent" data-tests-id="canvas"
-                           is-view-only="isViewOnly"></composition-graph>
+                           is-view-only="isViewOnly" with-sidebar="displayDesignerRightSidebar"></composition-graph>
     </div>
 
     <div class="w-sdc-designer-sidebar-toggle" data-ng-class="{'active': displayDesignerRightSidebar}"
@@ -21,7 +21,7 @@
             <div class="w-sdc-designer-sidebar-logo-ph">
                 <div class="large {{selectedComponent.iconSprite}} {{selectedComponent.icon}}">
                     <div ng-if="isComponentInstanceSelected()"
-                         data-ng-class="{'non-certified':'CERTIFIED' !== selectedComponent.lifecycleState, 'smaller-icon': selectedComponent.icon==='vl' || selectedComponent.icon==='cp'}"
+                         data-ng-class="{'non-certified':'CERTIFIED' !== selectedComponent.lifecycleState}"
                          tooltips tooltip-side="top" tooltip-content="Not certified"></div>
                 </div>
             </div>
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/composition.less b/catalog-ui/src/app/view-models/workspace/tabs/composition/composition.less
index 7a775bd..262dfd9 100644
--- a/catalog-ui/src/app/view-models/workspace/tabs/composition/composition.less
+++ b/catalog-ui/src/app/view-models/workspace/tabs/composition/composition.less
@@ -781,6 +781,71 @@
         line-height: 18px;
     }
 
+    //Canvas search menu
+    .w-sdc-search-menu {
+        position:absolute;
+        right: 18px;
+        top:53px;
+        transition: right 0.2s;
+        display: flex;
+        flex-direction: column;
+        align-items: flex-end;
+        margin-right:10px;
+
+        &.with-sidebar {
+            right:320px;
+        }
+
+        .search-with-autocomplete-container.composition-search {
+            margin-top: 12px;
+
+            .search-bar-input {
+                width: 250px;
+                padding:2px 50px 2px 10px;
+                transition:all 0.4s;
+            }
+            .clear-search-x {
+                top: 17px
+            }
+
+            &:not(:hover):not(.autocomplete-visible):not(.active){
+                border-radius: 0;
+                box-shadow:none;
+
+                .search-bar-input:not(:focus){
+                    width: 0px;
+                    padding:0;
+                    border:none;
+                }
+                .clear-search-x {
+                    display:none;
+                }
+                .search-bar-input:not(:focus) ~ .search-bar-button {
+                    border-radius: 2px;
+                    border:solid 1px #fff;
+                }
+            } 
+        }
+
+        .zoom-icons {
+            border:solid 1px #fff;
+            border-radius: 2px;
+            box-shadow: 0px 2px 3.88px 0.12px rgba(0, 0, 0, 0.29);
+            background-color:  rgba(234, 234, 234, 0.88);
+            background-repeat: no-repeat;
+            margin-top: 10px;
+
+            &:hover {
+                cursor:pointer;
+            }
+
+            &:active {
+                border:none;
+                background-color:  rgba(31, 171, 223, 0.88);
+            }
+        }
+    }
+
     // ---------------------------------------------------------------------------------------------------
     // Canvas inline menu
     // ---------------------------------------------------------------------------------------------------
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/artifacts/artifacts-view-model.ts b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/artifacts/artifacts-view-model.ts
index 83e4653..c4c63fa 100644
--- a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/artifacts/artifacts-view-model.ts
+++ b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/artifacts/artifacts-view-model.ts
@@ -33,13 +33,14 @@
 import {ArtifactsUtils, ModalsHandler, ArtifactGroupType} from "app/utils";
 import {GRAPH_EVENTS} from "app/utils/constants";
 import {EventListenerService} from "app/services/event-listener-service";
+import {Dictionary} from "../../../../../../utils/dictionary/dictionary";
 
 export interface IArtifactsViewModelScope extends ICompositionViewModelScope {
     artifacts:Array<ArtifactModel>;
     artifactType:string;
     downloadFile:IFileDownload;
     isLoading:boolean;
-
+    displayDeleteButtonMap:Dictionary<string, boolean>;
     getTitle():string;
     addOrUpdate(artifact:ArtifactModel):void;
     delete(artifact:ArtifactModel):void;
@@ -125,6 +126,10 @@
             }
         }
         this.$scope.artifacts = artifacts;
+        this.$scope.displayDeleteButtonMap = new Dictionary<string, boolean>();
+        _.forEach(this.$scope.artifacts, (artifact:ArtifactModel)=>{
+            this.$scope.displayDeleteButtonMap[artifact.artifactLabel] = this.displayDeleteButton(artifact);
+        });
         this.$scope.isLoading = false;
     };
 
@@ -229,6 +234,17 @@
         });
     };
 
+    private displayDeleteButton = (artifact:ArtifactModel):boolean => {
+    if(!this.$scope.isViewMode() && artifact.esId){
+        if(this.$scope.isComponentInstanceSelected()){//is artifact of instance
+            return !this.$scope.selectedComponent.deploymentArtifacts || !this.$scope.selectedComponent.deploymentArtifacts[artifact.artifactLabel];//if the artifact is not from instance parent
+        }else{//is artifact of main component
+            return (!artifact.isHEAT() && !artifact.isThirdParty() && !this.$scope.isLicenseArtifact(artifact));
+        }
+    }
+    return false;
+};
+
     private initScope = ():void => {
 
         this.$scope.isLoading = false;
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/artifacts/artifacts-view.html b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/artifacts/artifacts-view.html
index 8221c67..dfbd639 100644
--- a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/artifacts/artifacts-view.html
+++ b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/artifacts/artifacts-view.html
@@ -36,7 +36,7 @@
                             <span class="i-sdc-designer-sidebar-section-content-item-artifact-details-desc-label" data-ng-show="artifact.description">Description:</span>{{artifact.description}}
                         </div>
                     </div>
-                    <button ng-if="!isViewMode() && artifact.esId && !isComponentInstanceSelected() && !artifact.isHEAT() && !artifact.isThirdParty() && !isLicenseArtifact(artifact)" class="i-sdc-designer-sidebar-section-content-item-button delete sprite e-sdc-small-icon-delete"
+                    <button ng-if="displayDeleteButtonMap[artifact.artifactLabel]" class="i-sdc-designer-sidebar-section-content-item-button delete sprite e-sdc-small-icon-delete"
                             data-tests-id="delete_{{artifact.artifactDisplayName}}" data-ng-click="delete(artifact)" type="button"></button>
                     <button ng-if="!isViewMode()  && artifact.isHEAT() && isComponentInstanceSelected() && artifact.heatParameters.length"
                             class="i-sdc-designer-sidebar-section-content-item-button attach sprite e-sdc-small-icon-pad"
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/details/details-view.html b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/details/details-view.html
index 8607d65..0418515 100644
--- a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/details/details-view.html
+++ b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/details/details-view.html
@@ -23,9 +23,9 @@
 
                 <span class="i-sdc-designer-sidebar-section-content-item-label">Version:</span>
                 <span class="i-sdc-designer-sidebar-section-content-item-value"
-                      data-ng-if="!isComponentInstanceSelected() || selectedComponent.isVl()"  data-tests-id="rightTab_version" data-ng-bind="selectedComponent.version"></span>
+                      data-ng-if="!isComponentInstanceSelected()"  data-tests-id="rightTab_version" data-ng-bind="selectedComponent.version"></span>
 
-                <ng-form name="editForm" data-ng-if="isComponentInstanceSelected() && !selectedComponent.isVl()">
+                <ng-form name="editForm" data-ng-if="isComponentInstanceSelected()">
                     <select data-ng-model="editResourceVersion.changeVersion" name="changeVersion" data-tests-id="changeVersion" data-ng-disabled="$parent.isViewOnly"
                             class="i-sdc-designer-sidebar-section-content-item-value i-sdc-form-select"
                             data-ng-class="{'minor': (editResourceVersion.changeVersion)%1}"
diff --git a/catalog-ui/src/app/view-models/workspace/workspace.less b/catalog-ui/src/app/view-models/workspace/workspace.less
index b7331b5..d0799f4 100644
--- a/catalog-ui/src/app/view-models/workspace/workspace.less
+++ b/catalog-ui/src/app/view-models/workspace/workspace.less
@@ -170,6 +170,9 @@
             line-height: 110px;
             .f-type ._28;
         }
+        &.composition .w-sdc-main-container-body-content {
+            height: calc(~'100% - @{action_nav_height}'); //composition is the only tab without a tab title. need to exclude from calculation.
+        }
         .w-sdc-main-container-body-content {
             height:calc(~'100% - @{action_nav_height} - @{tab_title}');
             align-items: center;
diff --git a/catalog-ui/src/assets/styles/app.less b/catalog-ui/src/assets/styles/app.less
index 13d88a3..fde4cc8 100644
--- a/catalog-ui/src/assets/styles/app.less
+++ b/catalog-ui/src/assets/styles/app.less
@@ -34,6 +34,7 @@
 @import 'welcome-sprite.less';
 @import 'welcome-style.less';
 @import 'sdc-ui.css';
+@import 'notification-template.less';
 
 // Less insides specific files.
 @import '../../app/directives/ecomp-footer/ecomp-footer.less';
diff --git a/catalog-ui/src/assets/styles/images/sprites/sprite-global.png b/catalog-ui/src/assets/styles/images/sprites/sprite-global.png
index 962478f..87e5d43 100644
--- a/catalog-ui/src/assets/styles/images/sprites/sprite-global.png
+++ b/catalog-ui/src/assets/styles/images/sprites/sprite-global.png
Binary files differ
diff --git a/catalog-ui/src/assets/styles/notification-template.less b/catalog-ui/src/assets/styles/notification-template.less
new file mode 100644
index 0000000..5baf10d
--- /dev/null
+++ b/catalog-ui/src/assets/styles/notification-template.less
@@ -0,0 +1,53 @@
+.notification-container{
+    display: flex;
+    padding: 15px 11px;
+    float: left;
+    .icon-container{
+        flex-grow: 1;
+        margin-right: 20px;
+        .icon-circle{
+            background-color: black;
+            height: 40px;
+            width: 40px;
+            border-radius: 50%;
+            display: flex;
+            align-items: center;
+            margin-right: 0;
+            background-color: rgba(255, 255, 255, 0.3);
+            .icon{
+                margin: 0 auto;
+                display: block;
+            }
+        }
+    }
+    .msg-content{
+        flex-grow: 3;
+        h3{
+            border-bottom: none;
+            font-weight: 400;
+            .f-type._18_m;
+        }
+        .message{
+            font-weight: 300;
+            .f-type._14_m;
+        }
+    }
+}
+.ui-notification.success{
+    background-color: @main_color_d;
+    .icon{
+        .notification-success-icon;
+    }
+}
+.ui-notification.error{
+    background-color: @func_color_q;
+    .icon{
+        .notification-error-icon;
+    }
+}
+.ui-notification.info{
+    background-color: @main_color_a;
+    .icon{
+        .notification-process-icon;
+    }
+}
diff --git a/catalog-ui/src/assets/styles/sprite.less b/catalog-ui/src/assets/styles/sprite.less
index 2076744..3f82e48 100644
--- a/catalog-ui/src/assets/styles/sprite.less
+++ b/catalog-ui/src/assets/styles/sprite.less
@@ -238,8 +238,12 @@
 .round-expand-icon:hover       { background-position: -100px -1188px;  width: 15px;  height: 15px; }
 .round-expand-icon.open        { background-position: -50px -1216px;  width: 15px;  height: 15px; }
 .round-expand-icon.open:hover  { background-position: -100px -1216px;  width: 15px;  height: 15px; }
-.update-component-icon {    background-position: -140px -1183px;  width: 20px;  height: 20px;}
-.update-component-icon:hover {    background-position: -170px -1183px;  width: 20px;  height: 20px;}
+.update-component-icon {    background-position: -140px -1213px;  width: 20px;  height: 20px;}
+.update-component-icon:hover {    background-position: -169px -1213px;  width: 20px;  height: 20px;}
+.notification-user-icon{	background-position: -206px -1211px;  width: 18px;  height: 22px;}
+.notification-error-icon{ background-position: -244px -1216px;  width: 17px;  height: 17px;}
+.notification-success-icon{ background-position: -281px -1215px;  width: 21px;  height: 19px;}
+.notification-process-icon{ background-position: -322px -1206px;  width: 28px;  height: 28px;}
 /*
 .sprite-new.expand-asset-icon {  background-position: -740px -590px;  width: 40px;  height: 40px; }
 .sprite-new.view-info-icon {  background-position: -739px -621px;  width: 40px;  height: 40px; }
@@ -259,3 +263,20 @@
 .sprite-new.vl-icon:active, .sprite-new.vl-icon.disabled-icon {  background-position: -820px -682px; }
 .sprite-new.trash-icon:active, .sprite-new.trash-icon.disabled-icon {  background-position: -820px -712px; }
 */
+
+
+.sprite-new.magnify-search {   background-position: -206px -1276px;  width: 30px;  height: 30px; }
+.sprite-new.magnify-search:hover {   background-position: -125px -1276px; }
+.sprite-new.magnify-search:active {   background-position: -46px -1275px; }
+
+.sprite-new.zoom-plus {   background-position: -208px -1380px;  width: 30px;  height: 30px; }
+.sprite-new.zoom-plus:hover {   background-position: -128px -1380px; }
+.sprite-new.zoom-plus:active {   background-position: -47px -1379px; }
+
+.sprite-new.zoom-minus {    background-position: -208px -1433px;  width: 30px;  height: 30px; }
+.sprite-new.zoom-minus:hover {    background-position: -128px -1433px; }
+.sprite-new.zoom-minus:active {    background-position: -47px -1432px; }
+
+.sprite-new.canvas-fit-all {    background-position: -208px -1326px;  width: 30px;  height: 30px;}
+.sprite-new.canvas-fit-all:hover {    background-position: -128px -1326px;  }
+.sprite-new.canvas-fit-all:active {    background-position: -47px -1325px;}
diff --git a/catalog-ui/src/assets/styles/svg/source/fit-all.svg b/catalog-ui/src/assets/styles/svg/source/fit-all.svg
new file mode 100644
index 0000000..dbea909
--- /dev/null
+++ b/catalog-ui/src/assets/styles/svg/source/fit-all.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+	xmlns:xlink="http://www.w3.org/1999/xlink"
+	width="18px" height="19px" viewBox="0 0 18 19">
+<path fillRule="evenodd" d="M 17.94 18.86C 17.77 18.92 17.63 19 17.4 18.94 16.03 18.93 12.86 19 12.86 19 12.5 19 11.92 18.85 12 18 12.08 17.07 12.5 17 12.86 17 12.86 17 14.79 17 14.79 17 14.79 17 10.44 11.98 10.44 11.98 10.44 11.98 11.77 10.51 11.77 10.51 11.77 10.51 16.33 15.76 16.33 15.76 16.33 15.76 16.33 12.99 16.33 12.99 16.23 12.09 17.03 11.99 17.4 11.99 17.77 11.99 18.01 12.27 18.01 12.69 18.01 12.69 18.01 18.23 18.01 18.23 18.01 17.81 18 18.55 17.94 18.86ZM 17.33 7.36C 16.92 7.36 16.04 7.25 16.15 6.31 16.15 6.31 16.15 3.62 16.15 3.62 16.15 3.62 11.37 9 11.37 9 11.37 9 10.01 7.53 10.01 7.53 10.01 7.53 14.82 2.1 14.82 2.1 14.82 2.1 12.33 2.1 12.33 2.1 11.92 2.1 11.47 2.02 11.37 1.05 11.29 0.16 11.92-0 12.33-0 12.33-0 15.82 0.07 17.33 0.06 17.59 0 17.74 0.08 17.93 0.15 17.99 0.47 18 1.25 18 0.8 18 0.8 18 6.62 18 6.62 18 7.06 17.73 7.36 17.33 7.36ZM 5.67 16.9C 6.08 16.9 6.53 16.98 6.63 17.95 6.71 18.84 6.08 19 5.67 19 5.67 19 2.18 18.93 0.67 18.94 0.41 19 0.26 18.92 0.07 18.85 0.01 18.53-0 17.75-0 18.2-0 18.2-0 12.38-0 12.38-0 11.94 0.27 11.64 0.67 11.64 1.08 11.64 1.96 11.75 1.85 12.69 1.85 12.69 1.85 15.38 1.85 15.38 1.85 15.38 6.63 10 6.63 10 6.63 10 7.99 11.47 7.99 11.47 7.99 11.47 3.18 16.9 3.18 16.9 3.18 16.9 5.67 16.9 5.67 16.9ZM 6.63 9C 6.63 9 1.85 3.62 1.85 3.62 1.85 3.62 1.85 6.31 1.85 6.31 1.96 7.25 1.08 7.36 0.67 7.36 0.27 7.36-0 7.06-0 6.62-0 6.62-0 0.8-0 0.8-0 1.25 0.01 0.47 0.07 0.15 0.26 0.08 0.41 0 0.67 0.06 2.18 0.07 5.67-0 5.67-0 6.08-0 6.71 0.16 6.63 1.05 6.53 2.02 6.08 2.1 5.67 2.1 5.67 2.1 3.18 2.1 3.18 2.1 3.18 2.1 7.99 7.53 7.99 7.53 7.99 7.53 6.63 9 6.63 9Z" fill="rgb(89,89,89)"/></svg>
\ No newline at end of file
diff --git a/catalog-ui/src/assets/styles/svg/source/minus.svg b/catalog-ui/src/assets/styles/svg/source/minus.svg
new file mode 100644
index 0000000..4ced110
--- /dev/null
+++ b/catalog-ui/src/assets/styles/svg/source/minus.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+	xmlns:xlink="http://www.w3.org/1999/xlink"
+	width="16px" height="2px" viewBox="0 0 16 2">
+<path fillRule="evenodd" d="M 1-0C 1-0 15-0 15-0 15.55-0 16 0.45 16 1 16 1.55 15.55 2 15 2 15 2 1 2 1 2 0.45 2 0 1.55 0 1 0 0.45 0.45-0 1-0Z" fill="rgb(99,99,99)"/></svg>
\ No newline at end of file
diff --git a/catalog-ui/src/assets/styles/svg/source/plus.svg b/catalog-ui/src/assets/styles/svg/source/plus.svg
new file mode 100644
index 0000000..dff172c
--- /dev/null
+++ b/catalog-ui/src/assets/styles/svg/source/plus.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+	xmlns:xlink="http://www.w3.org/1999/xlink"
+	width="18px" height="18px" viewBox="0 0 18 18">
+<path fillRule="evenodd" d="M 17 10C 17 10 10 10 10 10 10 10 10 17 10 17 10 17.55 9.55 18 9 18 8.45 18 8 17.55 8 17 8 17 8 10 8 10 8 10 1 10 1 10 0.45 10 0 9.55 0 9 0 8.45 0.45 8 1 8 1 8 8 8 8 8 8 8 8 1 8 1 8 0.45 8.45 0 9 0 9.55 0 10 0.45 10 1 10 1 10 8 10 8 10 8 17 8 17 8 17.55 8 18 8.45 18 9 18 9.55 17.55 10 17 10Z" fill="rgb(99,99,99)"/></svg>
\ No newline at end of file
diff --git a/catalog-ui/src/assets/styles/svg/source/search-magnify.svg b/catalog-ui/src/assets/styles/svg/source/search-magnify.svg
new file mode 100644
index 0000000..279c13f
--- /dev/null
+++ b/catalog-ui/src/assets/styles/svg/source/search-magnify.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+	xmlns:xlink="http://www.w3.org/1999/xlink"
+	width="23px" height="26px" viewBox="0 0 23 26">
+<path fillRule="evenodd" d="M 17.53 4.53C 14.5 0.28 8.55-0.71 4.3 2.32 0.05 5.36-0.94 11.31 2.09 15.56 3.56 17.63 5.74 18.99 8.25 19.41 10.42 19.77 12.58 19.38 14.48 18.32 14.48 18.32 20.28 25.23 20.28 25.23 20.44 25.47 20.7 25.61 20.93 25.65 21.16 25.69 21.45 25.64 21.68 25.47 22.15 25.13 22.26 24.5 21.92 24.06 21.92 24.06 16.11 17.15 16.11 17.15 17.73 15.7 18.81 13.79 19.17 11.61 19.58 9.14 19.01 6.6 17.53 4.53ZM 3.76 14.4C 1.37 11.04 2.14 6.4 5.5 4 7.18 2.8 9.16 2.41 11.07 2.73 12.97 3.05 14.73 4.07 15.92 5.74 17.09 7.38 17.52 9.34 17.19 11.32 16.86 13.29 15.79 15 14.18 16.17 12.58 17.35 10.58 17.77 8.61 17.44 6.65 17.08 4.9 16.03 3.76 14.4Z" fill="rgb(99,99,99)"/></svg>
\ No newline at end of file
diff --git a/catalog-ui/src/third-party/cytoscape.js-edge-editation/CytoscapeEdgeEditation.js b/catalog-ui/src/third-party/cytoscape.js-edge-editation/CytoscapeEdgeEditation.js
index 2da6f78..9be07f2 100644
--- a/catalog-ui/src/third-party/cytoscape.js-edge-editation/CytoscapeEdgeEditation.js
+++ b/catalog-ui/src/third-party/cytoscape.js-edge-editation/CytoscapeEdgeEditation.js
@@ -250,13 +250,14 @@
         _drawHandle: function (handle, target) {
 
             var position = this._getHandlePosition(handle, target);
-
+            var handleSize = target.renderedWidth() / 4;
+            
             this._ctx.beginPath();
 
             if (handle.imageUrl) {
                 var base_image = new Image();
                 base_image.src = handle.imageUrl;
-                this._ctx.drawImage(base_image, position.x, position.y, this.HANDLE_SIZE, this.HANDLE_SIZE);
+                this._ctx.drawImage(base_image, position.x, position.y, handleSize, handleSize);
             } else {
                 this._ctx.arc(position.x, position.y, this.HANDLE_SIZE, 0, 2 * Math.PI, false);
                 this._ctx.fillStyle = handle.color;
@@ -461,17 +462,17 @@
         },
         _getHandlePosition: function (handle, target) {
             var position = target.renderedPosition();
-            var width = target.renderedOuterWidth();
-            var height = target.renderedOuterHeight();
+            var width = target.renderedWidth();
+            var height = target.renderedHeight();
             var xpos = null;
             var ypos = null;
 
             switch (handle.positionX) {
                 case "left":
-                    xpos = position.x - width / 2 + this.HANDLE_SIZE;
+                    xpos = position.x - width / 4;
                     break;
                 case "right":
-                    xpos = position.x + width / 2 - this.HANDLE_SIZE;
+                    xpos = position.x + width / 4;
                     break;
                 case "center":
                     xpos = position.x;
@@ -480,18 +481,18 @@
 
             switch (handle.positionY) {
                 case "top":
-                    ypos = position.y - height / 2 + this.HANDLE_SIZE;
+                    ypos = position.y - width / 2;
                     break;
                 case "center":
                     ypos = position.y;
                     break;
                 case "bottom":
-                    ypos = position.y + height / 2 - this.HANDLE_SIZE;
+                    ypos = position.y + width / 2;
                     break;
             }
 
-            var offsetX = handle.offsetX ? handle.offsetX : 0;
-            var offsetY = handle.offsetY ? handle.offsetY : 0;
+            var offsetX =  0;
+            var offsetY =  0;
             return {x: xpos + offsetX, y: ypos + offsetY};
         },
         _getEdgeCSSByHandle: function (handle) {