2 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
13 * or implied. See the License for the specific language governing
14 * permissions and limitations under the License.
16 import React from 'react';
17 import classnames from 'classnames';
18 import Dropzone from 'react-dropzone';
21 import i18n from 'nfvo-utils/i18n/i18n.js';
24 import SVGIcon from 'sdc-ui/lib/react/SVGIcon.js';
25 import SoftwareProductComponentsList from '../components/SoftwareProductComponentsList.js';
27 const SoftwareProductPropType = React.PropTypes.shape({
28 name: React.PropTypes.string,
29 description: React.PropTypes.string,
30 version: React.PropTypes.object,
31 id: React.PropTypes.string,
32 categoryId: React.PropTypes.string,
33 vendorId: React.PropTypes.string,
34 status: React.PropTypes.string,
35 licensingData: React.PropTypes.object,
36 validationData: React.PropTypes.object
39 const ComponentPropType = React.PropTypes.shape({
40 id: React.PropTypes.string,
41 name: React.PropTypes.string,
42 displayName: React.PropTypes.string,
43 description: React.PropTypes.string
46 class SoftwareProductLandingPageView extends React.Component {
56 currentSoftwareProduct: SoftwareProductPropType,
57 isReadOnlyMode: React.PropTypes.bool,
58 componentsList: React.PropTypes.arrayOf(ComponentPropType),
59 onDetailsSelect: React.PropTypes.func,
60 onAttachmentsSelect: React.PropTypes.func,
61 onUpload: React.PropTypes.func,
62 onUploadConfirmation: React.PropTypes.func,
63 onInvalidFileSizeUpload: React.PropTypes.func,
64 onComponentSelect: React.PropTypes.func,
65 onAddComponent: React.PropTypes.func
69 let {currentSoftwareProduct, isReadOnlyMode, isManual, onDetailsSelect, componentsList} = this.props;
71 <div className='software-product-landing-wrapper'>
73 className={classnames('software-product-landing-view', {'active-dragging': this.state.dragging})}
74 onDrop={files => this.handleImportSubmit(files, isReadOnlyMode, isManual)}
75 onDragEnter={() => this.handleOnDragEnter(isReadOnlyMode, isManual)}
76 onDragLeave={() => this.setState({dragging:false})}
83 <div className='draggable-wrapper'>
84 <div className='software-product-landing-view-top'>
86 <ProductSummary currentSoftwareProduct={currentSoftwareProduct} onDetailsSelect={onDetailsSelect} />
88 <div className='details-panel'/>
89 : this.renderProductDetails(currentSoftwareProduct, isReadOnlyMode)}
94 <SoftwareProductComponentsList
95 isReadOnlyMode={isReadOnlyMode}
96 componentsList={componentsList}
98 currentSoftwareProduct={currentSoftwareProduct}/>
103 handleOnDragEnter(isReadOnlyMode, isManual) {
104 if (!isReadOnlyMode && !isManual) {
105 this.setState({dragging: true});
109 renderProductDetails(currentSoftwareProduct, isReadOnlyMode) {
110 let {validationData} = currentSoftwareProduct;
111 let {onAttachmentsSelect} = this.props;
113 heatTemplates: validationData ? '1' : '0',
119 <div className='details-panel'>
120 <div className='software-product-landing-view-heading-title'>{i18n('Software Product Attachments')}</div>
121 <div className='software-product-landing-view-top-block'>
123 className='software-product-landing-view-top-block-col'
124 onClick={() => onAttachmentsSelect(currentSoftwareProduct)}>
126 <div className='attachment-details'>{i18n('HEAT Templates')} (<span
127 className='attachment-details-count'>{details.heatTemplates}</span>)
132 className={classnames('software-product-landing-view-top-block-col-upl', {'disabled': isReadOnlyMode})}>
133 <div className='drag-text'>{i18n('Drag & drop for upload')}</div>
134 <div className='or-text'>{i18n('or')}</div>
135 <div data-test-id='upload-btn' className='upload-btn primary-btn' onClick={() => this.refs.fileInput.open()}>
136 <span className='primary-btn-text'>{i18n('Select file')}</span>
144 handleImportSubmit(files, isReadOnlyMode, isManual) {
145 if (isReadOnlyMode || isManual) {
148 if (files[0] && files[0].size) {
150 fileName: files[0].name,
154 this.startUploading(files);
160 this.props.onInvalidFileSizeUpload();
165 startUploading(files) {
166 let {onUpload, currentSoftwareProduct, onUploadConfirmation} = this.props;
168 let {validationData} = currentSoftwareProduct;
170 if (!(files && files.length)) {
174 let formData = new FormData();
175 formData.append('upload', file);
176 this.refs.fileInput.value = '';
178 if (validationData) {
179 onUploadConfirmation(currentSoftwareProduct.id, formData);
181 onUpload(currentSoftwareProduct.id, formData);
187 const ProductSummary = ({currentSoftwareProduct, onDetailsSelect}) => {
188 let {name = '', description = '', vendorName = '', fullCategoryDisplayName = '', licenseAgreementName = ''} = currentSoftwareProduct;
190 <div className='details-panel'>
191 <div className='software-product-landing-view-heading-title'>{i18n('Software Product Details')}</div>
193 className='software-product-landing-view-top-block clickable'
194 onClick={() => onDetailsSelect(currentSoftwareProduct)}>
195 <div className='details-container'>
196 <div className='single-detail-section title-section'>
197 <div className='single-detail-section title-text'>
201 <div className='details-section'>
202 <div className='multiple-details-section'>
203 <div className='detail-col' >
204 <div className='title'>{i18n('Vendor')}</div>
205 <div className='description'>{vendorName}</div>
207 <div className='detail-col'>
208 <div className='title'>{i18n('Category')}</div>
209 <div className='description'>{fullCategoryDisplayName}</div>
211 <div className='detail-col'>
212 <div className='title extra-large'>{i18n('License Agreement')}</div>
213 <div className='description'>
214 <LicenseAgreement licenseAgreementName={licenseAgreementName}/>
218 <div className='single-detail-section'>
219 <div className='title'>{i18n('Description')}</div>
220 <div className='description'>{description}</div>
230 const LicenseAgreement = ({licenseAgreementName}) => {
231 if (!licenseAgreementName) {
232 return (<div className='missing-license'><SVGIcon name='exclamationTriangleFull'/><div className='warning-text'>{i18n('Missing')}</div></div>);
234 return <div>{licenseAgreementName}</div>;
237 export default SoftwareProductLandingPageView;