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 UID
from '../libraries/UniqueId'
22 import React
from 'react'
23 import messages
from './messages'
24 import ClassNames
from 'classnames'
25 import PureRenderMixin
from 'react-addons-pure-render-mixin'
26 import CatalogDataStore
from '../stores/CatalogDataStore'
27 import CatalogItemsActions
from '../actions/CatalogItemsActions'
28 import ComposerAppActions
from '../actions/ComposerAppActions'
29 import SelectionManager
from '../libraries/SelectionManager'
31 import '../styles/CatalogItems.scss'
32 import imgFile
from 'file!../images/vendor-riftio.png'
34 const DEFAULT_NSD_ICON
= require('style/img/catalog-nsd-default.svg');
35 const DEFAULT_VNFD_ICON
= require('style/img/catalog-vnfd-default.svg');
36 const DEFAULT_ICON
= require('style/img/catalog-default.svg');
38 function renderVersion (version
) {
40 return (<span className
='version'>{version
}</span
>);
41 } // else return null by default
43 function getImageErrorHandler (type
) {
44 return type
=== 'nsd' ? handleNsdImageError
: type
=== 'vnfd' ? handleVnfdImageError
: handleImageError
;
46 function handleImageError (e
, image
) {
47 console
.log('Bad logo path, using default');
48 e
.target
.src
= image
|| DEFAULT_ICON
;
50 function handleNsdImageError (e
) {
51 handleImageError(e
, DEFAULT_NSD_ICON
);
53 function handleVnfdImageError (e
) {
54 handleImageError(e
, DEFAULT_VNFD_ICON
);
57 const CatalogItems
= React
.createClass({
58 mixins
: [PureRenderMixin
],
60 return CatalogDataStore
.getState();
67 componentWillMount() {
68 CatalogDataStore
.listen(this.onChange
);
71 // async actions creator will dispatch loadCatalogsSuccess and loadCatalogsError messages
72 CatalogDataStore
.loadCatalogs().catch(e
=> console
.warn('unable to load catalogs', e
));
74 componentWillUnmount() {
75 CatalogDataStore
.unlisten(this.onChange
);
81 const onDragStart = function(event
) {
82 const data
= {type
: 'catalog-item', item
: this};
83 event
.dataTransfer
.effectAllowed
= 'copy';
84 event
.dataTransfer
.setData('text', JSON
.stringify(data
));
85 ComposerAppActions
.setDragState(data
);
87 const onDblClickCatalogItem = function () {
88 CatalogItemsActions
.editCatalogItem(this);
90 const onClickCatalogItem = function () {
91 // single clicking an item is handled by ComposerApp::onClick handler
92 //CatalogItemsActions.selectCatalogItem(this);
94 const cleanDataURI = function (imageString
, type
, id
) {
95 if (/\bbase64\b/g.test(imageString
)) {
97 } else if (/<\?xml\b/g.test(imageString
)) {
98 const imgStr
= imageString
.substring(imageString
.indexOf('<?xml'));
99 return 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(imgStr
);
100 } else if (/\.(svg|png|gif|jpeg|jpg)$/.test(imageString
)) {
101 return 'assets/logos/' + type
+ '/' + id
+ '/' + imageString
;
102 // return require('../images/logos/' + imageString);
104 return type
=== 'nsd' ? DEFAULT_NSD_ICON
: type
=== 'vnfd' ? DEFAULT_VNFD_ICON
: DEFAULT_ICON
;
106 const items
= this.getCatalogItems().map(function (d
) {
107 const isNSD
= d
.uiState
.type
=== 'nsd';
108 const isVNFD
= d
.uiState
.type
=== 'vnfd';
109 const isDeleted
= d
.uiState
.deleted
;
110 const isModified
= d
.uiState
.modified
;
111 const isSelected
= SelectionManager
.isSelected(d
);
112 const isOpenForEdit
= d
.uiState
.isOpenForEdit
;
113 const spanClassNames
= ClassNames({'-is-selected': isSelected
, '-is-open-for-edit': isOpenForEdit
});
114 const sectionClassNames
= ClassNames('catalog-item', {'-is-modified': isModified
, '-is-deleted': isDeleted
});
123 <li key
={d
.id
} data
-uid
={UID
.from(d
)} onClick
={onClickCatalogItem
.bind(d
)} onDoubleClick
={onDblClickCatalogItem
.bind(d
)}>
124 <div className
={spanClassNames
+ ' ' + type
}>
125 <div className
={sectionClassNames
} id
={d
.id
} draggable
="true" onDragStart
={onDragStart
.bind(d
)}>
126 {isModified
? <div className
="-is-modified-indicator" title
="This descriptor has changes."></div
> : null}
127 <div className
="type-header">{type
}</div
>
129 <dt className
="name">{d
.name
}</dt
>
130 <dd className
="logo">
131 <img className
="logo" src
={cleanDataURI(d
['logo'], type
, d
.id
)} draggable
="false" onError
={getImageErrorHandler(type
)} />
133 <dd className
="short-name" title
={d
.name
}>{d
['short-name']}</dd
>
134 <dd className
="description">{d
.description
}</dd
>
135 <dd className
="vendor">{d
.vendor
|| d
.provider
} {renderVersion(d
.version
)}</dd
>
139 {isOpenForEdit
? <div className
="-is-open-for-edit-indicator" title
="This descriptor is open in the canvas."></div
> : null}
144 <div className
="CatalogItems">
145 <ul data
-offset
-parent
="true">
146 {items
.length
? items
: messages
.catalogWelcome
}
152 const catalogFilter
= (d
) => {return d
.type
=== this.props
.filterByType
};
153 return this.state
.catalogs
.filter(catalogFilter
).reduce((result
, catalog
) => {
154 return result
.concat(catalog
.descriptors
);
159 export default CatalogItems
;