4 * Copyright 2016 RIFT.IO Inc
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
21 import _
from 'lodash'
22 import cc
from 'change-case'
23 import React
from 'react'
24 import PureRenderMixin
from 'react-addons-pure-render-mixin'
25 import utils
from '../libraries/utils'
26 import messages
from './messages'
27 import DescriptorModelFactory
from '../libraries/model/DescriptorModelFactory'
28 import CatalogItemCanvasEditor
from './CatalogItemCanvasEditor'
29 import CatalogItemsActions
from '../actions/CatalogItemsActions'
30 import CanvasEditorActions
from '../actions/CanvasEditorActions'
31 import ComposerAppActions
from '../actions/ComposerAppActions'
32 import CanvasZoom
from './CanvasZoom'
33 import CanvasPanelTray
from './CanvasPanelTray'
34 import EditForwardingGraphPaths
from './EditorForwardingGraph/EditForwardingGraphPaths'
35 import SelectionManager
from '../libraries/SelectionManager'
36 import DescriptorModelIconFactory
from '../libraries/model/IconFactory'
38 import '../styles/CanvasPanel.scss'
40 const CanvasPanel
= React
.createClass({
41 mixins
: [PureRenderMixin
],
56 componentWillMount() {
60 componentDidUpdate() {
61 SelectionManager
.refreshOutline();
63 componentWillUnmount() {
67 left
: this.props
.layout
.left
69 var req
= require
.context("../", true, /^\.\/.*\.svg$/);
70 const hasItem
= this.props
.containers
.length
!== 0;
71 const isEditingNSD
= DescriptorModelFactory
.isNetworkService(this.props
.containers
[0]);
72 const hasNoCatalogs
= this.props
.hasNoCatalogs
;
73 const bodyComponent
= hasItem
? <CatalogItemCanvasEditor zoom
={this.props
.zoom
} isShowingMoreInfo
={this.props
.showMore
} containers
={this.props
.containers
}/> : messages
.canvasWelcome();
75 <div id
="canvasPanelDiv" className
="CanvasPanel" style
={style
} onDragOver
={this.onDragOver
} onDrop
={this.onDrop
}>
76 <div onDoubleClick
={this.onDblClickOpenFullScreen
} className
="CanvasPanelHeader panel-header" data
-resizable
="limit_bottom">
78 {hasItem
? <img src
={req('./' + DescriptorModelIconFactory
.getUrlForType(this.props
.containers
[0].type
, 'black'))} width
="20px" /> : null}
79 <span className
="model-name">{this.props
.title
}</span
>
82 <div className
="CanvasPanelBody panel-body" style
={{marginRight
: this.props
.layout
.right
, bottom
: this.props
.layout
.bottom
}} >
83 {hasNoCatalogs
? null : bodyComponent
}
85 <CanvasZoom zoom
={this.props
.zoom
} style
={{bottom
: this.props
.layout
.bottom
+ 20}}/>
86 <CanvasPanelTray layout
={this.props
.layout
} show
={isEditingNSD
}>
87 <EditForwardingGraphPaths containers
={this.props
.containers
} />
93 const isDraggingFiles
= _
.contains(event
.dataTransfer
.types
, 'Files');
94 if (!isDraggingFiles
) {
95 event
.preventDefault();
96 event
.dataTransfer
.dropEffect
= 'copy';
100 // given a drop event determine which action to take in the canvas:
101 // open item or add item to an existing, already opened nsd
102 // note: nsd is the only editable container
103 const data
= utils
.parseJSONIgnoreErrors(event
.dataTransfer
.getData('text'));
104 if (data
.type
=== 'catalog-item') {
105 this.handleDropCatalogItem(event
, data
);
106 } else if (data
.type
=== 'action') {
107 this.handleDropCanvasAction(event
, data
);
110 handleDropCanvasAction(event
, data
) {
111 const action
= cc
.camel('on-' + data
.action
);
112 if (typeof this[action
] === 'function') {
113 if (this[action
]({clientX
: event
.clientX
, clientY
: event
.clientY
})) {
114 event
.preventDefault();
117 console
.warn(`no action defined for drop event ${data.action}. Did you forget to add CanvasPanel.${action}() event handler?`);
120 handleDropCatalogItem(event
, data
) {
122 const currentItem
= this.props
.containers
[0];
123 if (data
.item
.uiState
.type
=== 'nsd') {
124 // if item is an nsd then open the descriptor in the canvas
125 openItem
= data
.item
;
126 // if item is a vnfd or pnfd then check if the current item is an nsd
127 } else if (DescriptorModelFactory
.isNetworkService(currentItem
)) {
128 // so add the item to the nsd and re-render the canvas
129 switch (data
.item
.uiState
.type
) {
131 this.onAddVnfd(data
.item
, {clientX
: event
.clientX
, clientY
: event
.clientY
});
134 this.onAddPnfd(data
.item
, {clientX
: event
.clientX
, clientY
: event
.clientY
});
137 console
.warn(`Unknown catalog-item type. Expect type "nsd", "vnfd" or "pnfd" but got ${data.item.uiState.type}.`);
140 // otherwise the default action is to open the item
141 openItem
= data
.item
;
144 event
.preventDefault();
145 CatalogItemsActions
.editCatalogItem(openItem
);
148 onAddVdu(dropCoordinates
) {
149 const currentItem
= this.props
.containers
[0];
150 if (DescriptorModelFactory
.isVirtualNetworkFunction(currentItem
)) {
151 const vdu
= currentItem
.createVdu();
152 vdu
.uiState
.dropCoordinates
= dropCoordinates
;
153 CatalogItemsActions
.catalogItemDescriptorChanged(currentItem
);
156 onAddVld(dropCoordinates
) {
157 const currentItem
= this.props
.containers
[0];
158 if (DescriptorModelFactory
.isNetworkService(currentItem
) || DescriptorModelFactory
.isVirtualNetworkFunction(currentItem
)) {
159 const vld
= currentItem
.createVld();
160 vld
.uiState
.dropCoordinates
= dropCoordinates
;
161 CatalogItemsActions
.catalogItemDescriptorChanged(currentItem
);
164 onAddVnffgd(dropCoordinates
) {
165 const currentItem
= this.props
.containers
[0];
166 if (DescriptorModelFactory
.isNetworkService(currentItem
)) {
167 const vld
= currentItem
.createVnffgd();
168 vld
.uiState
.dropCoordinates
= dropCoordinates
;
169 CatalogItemsActions
.catalogItemDescriptorChanged(currentItem
);
172 onAddVnfd(model
, dropCoordinates
) {
173 const currentItem
= this.props
.containers
[0];
174 if (DescriptorModelFactory
.isNetworkService(currentItem
) || DescriptorModelFactory
.isVirtualNetworkFunction(currentItem
)) {
175 const vnfd
= DescriptorModelFactory
.newVirtualNetworkFunction(model
);
176 const cvnfd
= currentItem
.createConstituentVnfdForVnfd(vnfd
);
177 cvnfd
.uiState
.dropCoordinates
= dropCoordinates
;
178 CatalogItemsActions
.catalogItemDescriptorChanged(currentItem
);
181 onAddPnfd(model
, dropCoordinates
) {
182 const currentItem
= this.props
.containers
[0];
183 if (DescriptorModelFactory
.isNetworkService(currentItem
)) {
184 const pnfd
= DescriptorModelFactory
.newPhysicalNetworkFunction(model
);
185 pnfd
.uiState
.dropCoordinates
= dropCoordinates
;
186 currentItem
.createPnfd(pnfd
);
187 CatalogItemsActions
.catalogItemDescriptorChanged(currentItem
);
190 onDblClickOpenFullScreen(event
) {
191 event
.stopPropagation();
192 ComposerAppActions
.enterFullScreenMode();
196 export default CanvasPanel
;