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
}>
84 <button className
={!isDescriptorView
? '-selected' : ''} onClick
={ComposerAppActions
.showAssets
}>
90 //CanvasPanelTray panel to display
91 let displayedPanel
= null;
92 switch (this.props
.displayedPanel
) {
93 case 'forwarding' : displayedPanel
= (<EditForwardingGraphPaths containers
={this.props
.containers
} />); break;
94 case 'parameter' : displayedPanel
= (<ConfigPrimitiveParameters containers
={this.props
.containers
} />); break;
95 default: displayedPanel
= (<div
><p className
="welcome-message">Please select a tab
</p></div>); break;
98 <div id
="canvasPanelDiv" className
="CanvasPanel" style
={style
} onDragOver
={this.onDragOver
} onDrop
={this.onDrop
}>
99 <div onDoubleClick
={this.onDblClickOpenFullScreen
} className
="CanvasPanelHeader panel-header" data
-resizable
="limit_bottom">
101 {hasItem
? <img src
={req('./' + DescriptorModelIconFactory
.getUrlForType(this.props
.containers
[0].type
, 'black'))} width
="20px" /> : null}
102 <span className
="model-name">{this.props
.title
}</span
>
106 <div className
="CanvasPanelBody panel-body" style
={{marginRight
: this.props
.layout
.right
, bottom
: this.props
.layout
.bottom
}} >
107 {hasNoCatalogs
? null : viewFiles
? <FileManager files
={this.props
.files
} type
={this.props
.type
} item
={this.props
.item
} filesState
={this.props
.filesState
} /> : bodyComponent
}
111 <CanvasZoom zoom
={this.props
.zoom
} style
={{bottom
: this.props
.layout
.bottom
+ 20}}/>
114 <CanvasPanelTray layout
={this.props
.layout
} displayedPanel
={this.props
.displayedPanel
} show
={isEditingNSD
&& isDescriptorView
}>
121 const isDraggingFiles
= _
.includes(event
.dataTransfer
.types
, 'Files');
122 if (!isDraggingFiles
) {
123 event
.preventDefault();
124 event
.dataTransfer
.dropEffect
= 'copy';
128 // given a drop event determine which action to take in the canvas:
129 // open item or add item to an existing, already opened nsd
130 // note: nsd is the only editable container
131 const data
= utils
.parseJSONIgnoreErrors(event
.dataTransfer
.getData('text'));
132 if (data
.type
=== 'catalog-item') {
133 this.handleDropCatalogItem(event
, data
);
134 } else if (data
.type
=== 'action') {
135 this.handleDropCanvasAction(event
, data
);
138 handleDropCanvasAction(event
, data
) {
139 const action
= cc
.camel('on-' + data
.action
);
140 if (typeof this[action
] === 'function') {
141 if (this[action
]({clientX
: event
.clientX
, clientY
: event
.clientY
})) {
142 event
.preventDefault();
145 console
.warn(`no action defined for drop event ${data.action}. Did you forget to add CanvasPanel.${action}() event handler?`);
148 handleDropCatalogItem(event
, data
) {
150 const currentItem
= this.props
.containers
[0];
151 if (data
.item
.uiState
.type
=== 'nsd') {
152 // if item is an nsd then open the descriptor in the canvas
153 openItem
= data
.item
;
154 // if item is a vnfd or pnfd then check if the current item is an nsd
155 } else if (DescriptorModelFactory
.isNetworkService(currentItem
)) {
156 // so add the item to the nsd and re-render the canvas
157 switch (data
.item
.uiState
.type
) {
159 this.onAddVnfd(data
.item
, {clientX
: event
.clientX
, clientY
: event
.clientY
});
162 this.onAddPnfd(data
.item
, {clientX
: event
.clientX
, clientY
: event
.clientY
});
165 console
.warn(`Unknown catalog-item type. Expect type "nsd", "vnfd" or "pnfd" but got ${data.item.uiState.type}.`);
168 // otherwise the default action is to open the item
169 openItem
= data
.item
;
172 event
.preventDefault();
173 CatalogItemsActions
.editCatalogItem(openItem
);
176 onAddVdu(dropCoordinates
) {
177 const currentItem
= this.props
.containers
[0];
178 if (DescriptorModelFactory
.isVirtualNetworkFunction(currentItem
)) {
179 const vdu
= currentItem
.createVdu();
180 vdu
.uiState
.dropCoordinates
= dropCoordinates
;
181 CatalogItemsActions
.catalogItemDescriptorChanged(currentItem
);
184 onAddVld(dropCoordinates
) {
185 const currentItem
= this.props
.containers
[0];
186 if (DescriptorModelFactory
.isNetworkService(currentItem
) || DescriptorModelFactory
.isVirtualNetworkFunction(currentItem
)) {
187 const vld
= currentItem
.createVld();
188 vld
.uiState
.dropCoordinates
= dropCoordinates
;
189 CatalogItemsActions
.catalogItemDescriptorChanged(currentItem
);
192 onAddVnffgd(dropCoordinates
) {
193 const currentItem
= this.props
.containers
[0];
194 if (DescriptorModelFactory
.isNetworkService(currentItem
)) {
195 const vld
= currentItem
.createVnffgd();
196 vld
.uiState
.dropCoordinates
= dropCoordinates
;
197 CatalogItemsActions
.catalogItemDescriptorChanged(currentItem
);
200 onAddVnfd(model
, dropCoordinates
) {
201 const currentItem
= this.props
.containers
[0];
202 if (DescriptorModelFactory
.isNetworkService(currentItem
) || DescriptorModelFactory
.isVirtualNetworkFunction(currentItem
)) {
203 const vnfd
= DescriptorModelFactory
.newVirtualNetworkFunction(model
);
204 const cvnfd
= currentItem
.createConstituentVnfdForVnfd(vnfd
);
205 cvnfd
.uiState
.dropCoordinates
= dropCoordinates
;
206 CatalogItemsActions
.catalogItemDescriptorChanged(currentItem
);
209 onAddPnfd(model
, dropCoordinates
) {
210 const currentItem
= this.props
.containers
[0];
211 if (DescriptorModelFactory
.isNetworkService(currentItem
)) {
212 const pnfd
= DescriptorModelFactory
.newPhysicalNetworkFunction(model
);
213 pnfd
.uiState
.dropCoordinates
= dropCoordinates
;
214 currentItem
.createPnfd(pnfd
);
215 CatalogItemsActions
.catalogItemDescriptorChanged(currentItem
);
218 onDblClickOpenFullScreen(event
) {
219 event
.stopPropagation();
220 ComposerAppActions
.enterFullScreenMode();
224 export default CanvasPanel
;