fix policy and group drag and drop bug
[sdc.git] / catalog-ui / src / app / ng2 / pages / composition / graph / utils / composition-graph-palette-utils.ts
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 import {Component, Injectable} from "@angular/core";
22 import {CompositionGraphGeneralUtils, RequirementAndCapabilities} from "./composition-graph-general-utils";
23 import {CommonGraphUtils} from "../common/common-graph-utils";
24 import {EventListenerService} from "../../../../../services/event-listener-service";
25 import {ResourceNamePipe} from "app/ng2/pipes/resource-name.pipe";
26 import {ComponentInstanceFactory} from "app/utils/component-instance-factory";
27 import {GRAPH_EVENTS, GraphUIObjects} from "app/utils/constants";
28 import {TopologyTemplateService} from "app/ng2/services/component-services/topology-template.service";
29 import {DndDropEvent} from "ngx-drag-drop/ngx-drag-drop";
30 import {SdcUiServices} from "onap-ui-angular"
31 import { Component as TopologyTemplate, NodesFactory, CapabilitiesGroup, RequirementsGroup,
32      CompositionCiNodeBase, ComponentInstance, LeftPaletteComponent, Point } from "app/models";
33 import {CompositionService} from "../../composition.service";
34 import {WorkspaceService} from "app/ng2/pages/workspace/workspace.service";
35 import { QueueServiceUtils } from "app/ng2/utils/queue-service-utils";
36 import {ComponentGenericResponse} from "../../../../services/responses/component-generic-response";
37 import {MatchCapabilitiesRequirementsUtils} from "./match-capability-requirement-utils";
38 import {CompositionGraphNodesUtils} from "./index";
39
40 @Injectable()
41 export class CompositionGraphPaletteUtils {
42
43     constructor(private generalGraphUtils:CompositionGraphGeneralUtils,
44                 private nodesFactory:NodesFactory,
45                 private commonGraphUtils:CommonGraphUtils,
46                 private queueServiceUtils:QueueServiceUtils,
47                 private eventListenerService:EventListenerService,
48                 private topologyTemplateService: TopologyTemplateService,
49                 private loaderService: SdcUiServices.LoaderService,
50                 private compositionService: CompositionService,
51                 private workspaceService: WorkspaceService,
52                 private matchCapabilitiesRequirementsUtils: MatchCapabilitiesRequirementsUtils,
53                 private nodesGraphUtils: CompositionGraphNodesUtils) {
54     }
55
56     /**
57      * Calculate the dragged element (html element) position on canvas
58      * @param cy
59      * @param event
60      * @param position
61      * @returns {Cy.BoundingBox}
62      * @private
63      */
64     private _getNodeBBox(cy:Cy.Instance, event:DragEvent, position?:Cy.Position, eventPosition?: Point) {
65         let bbox = <Cy.BoundingBox>{};
66         if (!position) {
67             position = event ? this.commonGraphUtils.getCytoscapeNodePosition(cy, event) : eventPosition;
68         }
69         let cushionWidth:number = 40;
70         let cushionHeight:number = 40;
71
72         bbox.x1 = position.x - cushionWidth / 2;
73         bbox.y1 = position.y - cushionHeight / 2;
74         bbox.x2 = position.x + cushionWidth / 2;
75         bbox.y2 = position.y + cushionHeight / 2;
76         return bbox;
77     }
78
79     /**
80      * Create the component instance, update data from parent component in the left palette and notify on_insert_to_ucpe if component was dragg into ucpe
81      * @param cy
82      * @param fullComponent
83      * @param event
84      * @param component
85      */
86     private _createComponentInstanceOnGraphFromPaletteComponent(cy:Cy.Instance, fullComponent:LeftPaletteComponent, event:DragEvent) {
87         let componentInstanceToCreate:ComponentInstance = ComponentInstanceFactory.createComponentInstanceFromComponent(fullComponent, this.workspaceService.metadata.categories[0].useServiceSubstitutionForNestedServices); 
88         let cytoscapePosition:Cy.Position = this.commonGraphUtils.getCytoscapeNodePosition(cy, event);
89         componentInstanceToCreate.posX = cytoscapePosition.x;
90         componentInstanceToCreate.posY = cytoscapePosition.y;
91
92         let onFailedCreatingInstance:(error:any) => void = (error:any) => {
93             this.loaderService.deactivate();
94         };
95
96         //on success - update node data
97         let onSuccessCreatingInstance = (createInstance:ComponentInstance):void => {
98
99             this.loaderService.deactivate();
100             this.compositionService.addComponentInstance(createInstance);
101             createInstance.name = ResourceNamePipe.getDisplayName(createInstance.name);
102             createInstance.requirements = new RequirementsGroup(createInstance.requirements);
103             createInstance.capabilities = new CapabilitiesGroup(createInstance.capabilities);
104             createInstance.componentVersion = fullComponent.version;
105             createInstance.icon = fullComponent.icon;
106             createInstance.setInstanceRC();
107
108             let newNode:CompositionCiNodeBase = this.nodesFactory.createNode(createInstance);
109             this.commonGraphUtils.addComponentInstanceNodeToGraph(cy, newNode);
110             this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_CREATE_COMPONENT_INSTANCE);
111         };
112
113         this.queueServiceUtils.addBlockingUIAction(() => {
114             let uniqueId = this.workspaceService.metadata.uniqueId;
115             let componentType = this.workspaceService.metadata.componentType;
116             this.topologyTemplateService.createComponentInstance(componentType, uniqueId, componentInstanceToCreate).subscribe(onSuccessCreatingInstance, onFailedCreatingInstance);
117
118         });
119     }
120     //
121     // /**
122     //  * Thid function applay red/green background when component dragged from palette
123     //  * @param cy
124     //  * @param event
125     //  * @param dragElement
126     //  * @param dragComponent
127     //  */
128     // public onComponentDrag(cy:Cy.Instance, event) {
129     //     let draggedElement = document.getElementById("draggable_element");
130     //     // event.dataTransfer.setDragImage(draggableElement, 0, 0);
131     //     if (event.clientX < GraphUIObjects.DIAGRAM_PALETTE_WIDTH_OFFSET || event.clientY < GraphUIObjects.DIAGRAM_HEADER_OFFSET) { //hovering over palette. Dont bother computing validity of drop
132     //         draggedElement.className = 'invalid-drag';
133     //         event.dataTransfer.setDragImage(draggedElement.cloneNode(true), 0, 0);
134     //         return;
135     //     }
136     //
137     //     let offsetPosition = {
138     //         x: event.clientX - GraphUIObjects.DIAGRAM_PALETTE_WIDTH_OFFSET,
139     //         y: event.clientY - GraphUIObjects.DIAGRAM_HEADER_OFFSET
140     //     };
141     //     let bbox = this._getNodeBBox(cy, event, offsetPosition);
142     //
143     //     if (this.generalGraphUtils.isPaletteDropValid(cy, bbox)) {
144     //         draggedElement.className = 'valid-drag';
145     //         event.dataTransfer.setDragImage(draggedElement.cloneNode(true), 0, 0);
146     //         // event.dataTransfer.setDragImage(draggedElement, 0, 0);
147     //         // event.dataTransfer.setDragImage(draggedElement, 0, 0);
148     //
149     //     } else {
150     //         draggedElement.className = 'invalid-drag';
151     //         event.dataTransfer.setDragImage(draggedElement.cloneNode(true), 0, 0);
152     //     }
153     // }
154
155     public isDragValid(cy:Cy.Instance, position: Point):boolean {
156         if (position.x < GraphUIObjects.DIAGRAM_PALETTE_WIDTH_OFFSET || position.y < GraphUIObjects.DIAGRAM_HEADER_OFFSET) { //hovering over palette. Dont bother computing validity of drop
157             return false;
158         }
159         
160         let offsetPosition = {
161             x: position.x - GraphUIObjects.DIAGRAM_PALETTE_WIDTH_OFFSET,
162             y: position.y - GraphUIObjects.DIAGRAM_HEADER_OFFSET
163         };
164         let bbox = this._getNodeBBox(cy, null, offsetPosition, position);
165
166         if (this.generalGraphUtils.isPaletteDropValid(cy, bbox)) {
167             return true;
168         } else {
169             return false;
170         }
171     } 
172     /**
173      *  This function is called when after dropping node on canvas
174      *  Check if the capability & requirements fulfilled and if not get from server
175      * @param cy
176      * @param dragEvent
177      * @param component
178      */
179     public addNodeFromPalette(cy:Cy.Instance, dragEvent:DndDropEvent) {
180         this.loaderService.activate();
181
182         let draggedComponent:LeftPaletteComponent = dragEvent.data;
183
184         if (this.generalGraphUtils.componentRequirementsAndCapabilitiesCaching.containsKey(draggedComponent.uniqueId)) {
185             let fullComponent = this.generalGraphUtils.componentRequirementsAndCapabilitiesCaching.getValue(draggedComponent.uniqueId);
186             draggedComponent.capabilities = fullComponent.capabilities;
187             draggedComponent.requirements = fullComponent.requirements;
188             this._createComponentInstanceOnGraphFromPaletteComponent(cy, draggedComponent, dragEvent.event);
189
190         } else {
191
192             this.topologyTemplateService.getFullComponent(draggedComponent.componentType, draggedComponent.uniqueId).subscribe((topologyTemplate:TopologyTemplate) => {
193                 draggedComponent.capabilities = topologyTemplate.capabilities;
194                 draggedComponent.requirements = topologyTemplate.requirements;
195                 this._createComponentInstanceOnGraphFromPaletteComponent(cy, draggedComponent, dragEvent.event);
196             });
197         }
198     }
199
200     addPolicyOrGroupFromPalette(dndEvent: DndDropEvent) {
201         let draggedComponent:LeftPaletteComponent = dndEvent.data;
202         let dropPosition:Point = dndEvent.event;
203         let component:Component = dndEvent.data;
204         this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_ADD_ZONE_INSTANCE_FROM_PALETTE, draggedComponent, component, dropPosition);
205     }
206 }
207