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'
37 import FileManager
from './filemanager/FileManager.jsx';
39 import ConfigPrimitiveParameters
from './ConfigPrimitiveParameters/ConfigPrimitiveParameters'
40 import '../styles/CanvasPanel.scss'
42 const CanvasPanel
= React
.createClass({
43 mixins
: [PureRenderMixin
],
58 componentWillMount() {
62 componentDidUpdate() {
63 SelectionManager
.refreshOutline();
65 componentWillUnmount() {
69 left
: this.props
.layout
.left
71 var req
= require
.context("../", true, /^\.\/.*\.svg$/);
72 const hasItem
= this.props
.containers
.length
!== 0;
73 const isEditingNSD
= DescriptorModelFactory
.isNetworkService(this.props
.containers
[0]);
74 const isDescriptorView
= (this.props
.panelTabShown
== 'descriptor');
75 const hasNoCatalogs
= this.props
.hasNoCatalogs
;
76 const bodyComponent
= hasItem
? <CatalogItemCanvasEditor zoom
={this.props
.zoom
} isShowingMoreInfo
={this.props
.showMore
} containers
={this.props
.containers
}/> : messages
.canvasWelcome();
77 const viewFiles
= this.props
.panelTabShown
== 'assets';
78 const viewButtonTabs
= !hasItem
? null : (
79 <div className
="CanvasPanelTabs">
80 <div className
="CatalogFilter">
81 <button className
={isDescriptorView
? '-selected' : ''} onClick
={ComposerAppActions
.showDescriptor
}>
86 <button className
={!isDescriptorView
? '-selected' : ''} onClick
={ComposerAppActions
.showAssets
}>
94 //CanvasPanelTray panel to display
95 let displayedPanel
= null;
96 switch (this.props
.displayedPanel
) {
97 case 'forwarding' : displayedPanel
= (<EditForwardingGraphPaths containers
={this.props
.containers
} />); break;
98 case 'parameter' : displayedPanel
= (<ConfigPrimitiveParameters containers
={this.props
.containers
} />); break;
99 default: displayedPanel
= (<div
><p className
="welcome-message">Please select a tab
</p></div>); break;
102 <div id
="canvasPanelDiv" className
="CanvasPanel" style
={style
} onDragOver
={this.onDragOver
} onDrop
={this.onDrop
}>
103 <div onDoubleClick
={this.onDblClickOpenFullScreen
} className
="CanvasPanelHeader panel-header" data
-resizable
="limit_bottom">
105 {hasItem
? <img src
={req('./' + DescriptorModelIconFactory
.getUrlForType(this.props
.containers
[0].type
, 'black'))} width
="20px" /> : null}
106 <span className
="model-name">{this.props
.title
}</span
>
110 <div className
="CanvasPanelBody panel-body" style
={{marginRight
: this.props
.layout
.right
, bottom
: this.props
.layout
.bottom
}} >
111 {hasNoCatalogs
? null : viewFiles
? <FileManager files
={this.props
.files
} type
={this.props
.type
} item
={this.props
.item
} filesState
={this.props
.filesState
} newPathName
={this.props
.newPathName
} /> : bodyComponent
}
115 <CanvasZoom zoom
={this.props
.zoom
} style
={{bottom
: this.props
.layout
.bottom
+ 20}}/>
118 <CanvasPanelTray layout
={this.props
.layout
} displayedPanel
={this.props
.displayedPanel
} show
={isEditingNSD
&& isDescriptorView
}>
125 const isDraggingFiles
= _
.includes(event
.dataTransfer
.types
, 'Files');
126 if (!isDraggingFiles
) {
127 event
.preventDefault();
128 event
.dataTransfer
.dropEffect
= 'copy';
132 // given a drop event determine which action to take in the canvas:
133 // open item or add item to an existing, already opened nsd
134 // note: nsd is the only editable container
135 const data
= utils
.parseJSONIgnoreErrors(event
.dataTransfer
.getData('text'));
136 if (data
.type
=== 'catalog-item') {
137 this.handleDropCatalogItem(event
, data
);
138 } else if (data
.type
=== 'action') {
139 this.handleDropCanvasAction(event
, data
);
142 handleDropCanvasAction(event
, data
) {
143 const action
= cc
.camel('on-' + data
.action
);
144 if (typeof this[action
] === 'function') {
145 if (this[action
]({clientX
: event
.clientX
, clientY
: event
.clientY
})) {
146 event
.preventDefault();
149 console
.warn(`no action defined for drop event ${data.action}. Did you forget to add CanvasPanel.${action}() event handler?`);
152 handleDropCatalogItem(event
, data
) {
154 const currentItem
= this.props
.containers
[0];
155 if (data
.item
.uiState
.type
=== 'nsd') {
156 // if item is an nsd then open the descriptor in the canvas
157 openItem
= data
.item
;
158 // if item is a vnfd or pnfd then check if the current item is an nsd
159 } else if (DescriptorModelFactory
.isNetworkService(currentItem
)) {
160 // so add the item to the nsd and re-render the canvas
161 switch (data
.item
.uiState
.type
) {
163 this.onAddVnfd(data
.item
, {clientX
: event
.clientX
, clientY
: event
.clientY
});
166 this.onAddPnfd(data
.item
, {clientX
: event
.clientX
, clientY
: event
.clientY
});
169 console
.warn(`Unknown catalog-item type. Expect type "nsd", "vnfd" or "pnfd" but got ${data.item.uiState.type}.`);
172 // otherwise the default action is to open the item
173 openItem
= data
.item
;
176 event
.preventDefault();
177 CatalogItemsActions
.editCatalogItem(openItem
);
180 onAddVdu(dropCoordinates
) {
181 const currentItem
= this.props
.containers
[0];
182 if (DescriptorModelFactory
.isVirtualNetworkFunction(currentItem
)) {
183 const vdu
= currentItem
.createVdu();
184 vdu
.uiState
.dropCoordinates
= dropCoordinates
;
185 CatalogItemsActions
.catalogItemDescriptorChanged(currentItem
);
188 onAddVld(dropCoordinates
) {
189 const currentItem
= this.props
.containers
[0];
190 if (DescriptorModelFactory
.isNetworkService(currentItem
) || DescriptorModelFactory
.isVirtualNetworkFunction(currentItem
)) {
191 const vld
= currentItem
.createVld();
192 vld
.uiState
.dropCoordinates
= dropCoordinates
;
193 CatalogItemsActions
.catalogItemDescriptorChanged(currentItem
);
196 onAddVnffgd(dropCoordinates
) {
197 const currentItem
= this.props
.containers
[0];
198 if (DescriptorModelFactory
.isNetworkService(currentItem
)) {
199 const vld
= currentItem
.createVnffgd();
200 vld
.uiState
.dropCoordinates
= dropCoordinates
;
201 CatalogItemsActions
.catalogItemDescriptorChanged(currentItem
);
204 onAddVnfd(model
, dropCoordinates
) {
205 const currentItem
= this.props
.containers
[0];
206 if (DescriptorModelFactory
.isNetworkService(currentItem
) || DescriptorModelFactory
.isVirtualNetworkFunction(currentItem
)) {
207 const vnfd
= DescriptorModelFactory
.newVirtualNetworkFunction(model
);
208 const cvnfd
= currentItem
.createConstituentVnfdForVnfd(vnfd
);
209 cvnfd
.uiState
.dropCoordinates
= dropCoordinates
;
210 CatalogItemsActions
.catalogItemDescriptorChanged(currentItem
);
213 onAddPnfd(model
, dropCoordinates
) {
214 const currentItem
= this.props
.containers
[0];
215 if (DescriptorModelFactory
.isNetworkService(currentItem
)) {
216 const pnfd
= DescriptorModelFactory
.newPhysicalNetworkFunction(model
);
217 pnfd
.uiState
.dropCoordinates
= dropCoordinates
;
218 currentItem
.createPnfd(pnfd
);
219 CatalogItemsActions
.catalogItemDescriptorChanged(currentItem
);
222 onDblClickOpenFullScreen(event
) {
223 event
.stopPropagation();
224 ComposerAppActions
.enterFullScreenMode();
228 export default CanvasPanel
;