[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;