Fix type issue
[sdc.git] / openecomp-ui / src / sdc-app / onboarding / softwareProduct / landingPage / SoftwareProductLandingPageView.jsx
1 /*
2  * Copyright © 2016-2018 European Support Limited
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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 or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 import React from 'react';
17 import PropTypes from 'prop-types';
18 import classnames from 'classnames';
19 import Dropzone from 'react-dropzone';
20
21 import i18n from 'nfvo-utils/i18n/i18n.js';
22 import Configuration from 'sdc-app/config/Configuration.js';
23 import DraggableUploadFileBox from 'nfvo-components/fileupload/DraggableUploadFileBox.jsx';
24 import VnfRepositorySearchBox from 'nfvo-components/vnfMarketPlace/VnfRepositorySearchBox.jsx';
25
26 import { SVGIcon } from 'onap-ui-react';
27 import SoftwareProductComponentsList from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponents.js';
28
29 const SoftwareProductPropType = PropTypes.shape({
30     name: PropTypes.string,
31     description: PropTypes.string,
32     version: PropTypes.string,
33     id: PropTypes.string,
34     categoryId: PropTypes.string,
35     vendorId: PropTypes.string,
36     licenseType: PropTypes.string,
37     status: PropTypes.string,
38     licensingData: PropTypes.object,
39     validationData: PropTypes.object
40 });
41
42 const ComponentPropType = PropTypes.shape({
43     id: PropTypes.string,
44     name: PropTypes.string,
45     displayName: PropTypes.string,
46     description: PropTypes.string
47 });
48
49 class SoftwareProductLandingPageView extends React.Component {
50     state = {
51         fileName: '',
52         dragging: false,
53         files: []
54     };
55
56     constructor(props) {
57         super(props);
58         this.getExternalLicenceFeatureState = this.getExternalLicenceFeatureState.bind(
59             this
60         );
61     }
62
63     static propTypes = {
64         currentSoftwareProduct: SoftwareProductPropType,
65         isReadOnlyMode: PropTypes.bool,
66         componentsList: PropTypes.arrayOf(ComponentPropType),
67         version: PropTypes.object,
68         onLicenseChange: PropTypes.func,
69         onUpload: PropTypes.func,
70         onUploadConfirmation: PropTypes.func,
71         onInvalidFileSizeUpload: PropTypes.func,
72         onComponentSelect: PropTypes.func,
73         onAddComponent: PropTypes.func
74     };
75     componentDidMount() {
76         const {
77             onCandidateInProcess,
78             currentSoftwareProduct,
79             isCertified
80         } = this.props;
81         if (currentSoftwareProduct.candidateOnboardingOrigin && !isCertified) {
82             onCandidateInProcess(currentSoftwareProduct.id);
83         }
84     }
85
86     licenceChange = (e, currentSoftwareProduct, onLicenseChange) => {
87         currentSoftwareProduct.licenseType = e.target.value
88             ? e.target.value
89             : 'INTERNAL';
90         onLicenseChange(currentSoftwareProduct);
91     };
92
93     getExternalLicenceFeatureState() {
94         var licenseFeature = this.props.features.find(
95             feature => feature.name === 'EXTERNAL_LICENSE'
96         );
97         return licenseFeature ? licenseFeature.active : true;
98     }
99
100     render() {
101         let {
102             currentSoftwareProduct,
103             isReadOnlyMode,
104             isManual,
105             onLicenseChange
106         } = this.props;
107         let licenceChange = this.licenceChange;
108         return (
109             <div className="software-product-landing-wrapper">
110                 <Dropzone
111                     className={classnames('software-product-landing-view', {
112                         'active-dragging': this.state.dragging
113                     })}
114                     onDrop={files =>
115                         this.handleImportSubmit(files, isReadOnlyMode, isManual)
116                     }
117                     onDragEnter={() =>
118                         this.handleOnDragEnter(isReadOnlyMode, isManual)
119                     }
120                     onDragLeave={() => this.setState({ dragging: false })}
121                     multiple={false}
122                     disableClick={true}
123                     ref="fileInput"
124                     name="fileInput"
125                     accept=".zip, .csar">
126                     <div className="draggable-wrapper">
127                         <div className="software-product-landing-view-top">
128                             <div className="row">
129                                 <ProductSummary
130                                     currentSoftwareProduct={
131                                         currentSoftwareProduct
132                                     }
133                                     licenceChange={licenceChange}
134                                     onLicenseChange={onLicenseChange}
135                                     externalLicenceEnabled={this.getExternalLicenceFeatureState()}
136                                 />
137                                 {this.renderProductDetails(
138                                     isManual,
139                                     isReadOnlyMode
140                                 )}
141                             </div>
142                         </div>
143                     </div>
144                 </Dropzone>
145                 <SoftwareProductComponentsList />
146             </div>
147         );
148     }
149
150     handleOnDragEnter(isReadOnlyMode, isManual) {
151         if (!isReadOnlyMode && !isManual) {
152             this.setState({ dragging: true });
153         }
154     }
155
156     renderProductDetails(isManual, isReadOnlyMode) {
157         let { onBrowseVNF, currentSoftwareProduct } = this.props;
158
159         if (Configuration.get('showBrowseVNF')) {
160             return (
161                 <div className="details-panel">
162                     {!isManual && (
163                         <div>
164                             <div className="software-product-landing-view-heading-title">
165                                 {i18n('Software Product Attachments')}
166                             </div>
167                             <VnfRepositorySearchBox
168                                 dataTestId="upload-btn"
169                                 isReadOnlyMode={isReadOnlyMode}
170                                 className={classnames(
171                                     'software-product-landing-view-top-block-col-upl showVnf',
172                                     { disabled: isReadOnlyMode }
173                                 )}
174                                 onClick={() => this.refs.fileInput.open()}
175                                 onBrowseVNF={() =>
176                                     onBrowseVNF(currentSoftwareProduct)
177                                 }
178                             />
179                         </div>
180                     )}
181                 </div>
182             );
183         } else {
184             return (
185                 <div className="details-panel">
186                     {!isManual && (
187                         <div>
188                             <div className="software-product-landing-view-heading-title">
189                                 {i18n('Software Product Attachments')}
190                             </div>
191                             <DraggableUploadFileBox
192                                 dataTestId="upload-btn"
193                                 isReadOnlyMode={isReadOnlyMode}
194                                 className={classnames(
195                                     'software-product-landing-view-top-block-col-upl',
196                                     { disabled: isReadOnlyMode }
197                                 )}
198                                 onClick={() => this.refs.fileInput.open()}
199                                 onBrowseVNF={() => onBrowseVNF()}
200                             />
201                         </div>
202                     )}
203                 </div>
204             );
205         }
206     }
207
208     handleImportSubmit(files, isReadOnlyMode, isManual) {
209         if (isReadOnlyMode || isManual) {
210             return;
211         }
212         if (files[0] && files[0].size) {
213             this.setState({
214                 fileName: files[0].name,
215                 dragging: false,
216                 complete: '0'
217             });
218             this.startUploading(files);
219         } else {
220             this.setState({
221                 dragging: false
222             });
223             this.props.onInvalidFileSizeUpload();
224         }
225     }
226
227     startUploading(files) {
228         let {
229             onUpload,
230             currentSoftwareProduct,
231             onUploadConfirmation
232         } = this.props;
233
234         let { validationData } = currentSoftwareProduct;
235
236         if (!(files && files.length)) {
237             return;
238         }
239         let file = files[0];
240         let formData = new FormData();
241         formData.append('upload', file);
242         this.refs.fileInput.value = '';
243
244         if (validationData) {
245             onUploadConfirmation(currentSoftwareProduct.id, formData);
246         } else {
247             onUpload(currentSoftwareProduct.id, formData);
248         }
249     }
250 }
251
252 const ProductSummary = ({
253     currentSoftwareProduct,
254     licenceChange,
255     onLicenseChange,
256     externalLicenceEnabled
257 }) => {
258     let {
259         name = '',
260         description = '',
261         vendorName = '',
262         fullCategoryDisplayName = ''
263     } = currentSoftwareProduct;
264     return (
265         <div className="details-panel">
266             <div className="software-product-landing-view-heading-title">
267                 {i18n('Software Product Details')}
268             </div>
269             <div className="software-product-landing-view-top-block">
270                 <div className="details-container">
271                     <div className="single-detail-section title-section">
272                         <div className="single-detail-section title-text">
273                             {name}
274                         </div>
275                     </div>
276                     <div className="details-section">
277                         <div className="multiple-details-section">
278                             <div className="detail-col">
279                                 <div className="title">{i18n('Vendor')}</div>
280                                 <div className="description">{vendorName}</div>
281                             </div>
282                             <div className="detail-col">
283                                 <div className="title">{i18n('Category')}</div>
284                                 <div className="description">
285                                     {fullCategoryDisplayName}
286                                 </div>
287                             </div>
288                             <div className="detail-col">
289                                 <div className="title extra-large">
290                                     {i18n('License Agreement')}
291                                 </div>
292                                 <div className="description">
293                                     <LicenseAgreement
294                                         licenceChange={licenceChange}
295                                         currentSoftwareProduct={
296                                             currentSoftwareProduct
297                                         }
298                                         onLicenseChange={onLicenseChange}
299                                         externalLicenceEnabled={
300                                             externalLicenceEnabled
301                                         }
302                                     />
303                                 </div>
304                             </div>
305                         </div>
306                         <div className="single-detail-section">
307                             <div className="title">{i18n('Description')}</div>
308                             <div className="description">{description}</div>
309                         </div>
310                     </div>
311                 </div>
312             </div>
313         </div>
314     );
315 };
316
317 const LicenseAgreementWithExternal = ({
318     licenceChange,
319     currentSoftwareProduct,
320     onLicenseChange
321 }) => {
322     return (
323         <div className="missing-license">
324             <form>
325                 <input
326                     type="radio"
327                     value="INTERNAL"
328                     id="INTERNAL"
329                     onChange={event =>
330                         licenceChange(
331                             event,
332                             currentSoftwareProduct,
333                             onLicenseChange
334                         )
335                     }
336                     checked={currentSoftwareProduct.licenseType === 'INTERNAL'}
337                     name="license"
338                 />
339                 <div className="description licenceLabel">
340                     {i18n('Internal license')}
341                 </div>
342                 <br />
343                 <input
344                     type="radio"
345                     value="EXTERNAL"
346                     id="EXTERNAL"
347                     onChange={event =>
348                         licenceChange(
349                             event,
350                             currentSoftwareProduct,
351                             onLicenseChange
352                         )
353                     }
354                     checked={currentSoftwareProduct.licenseType === 'EXTERNAL'}
355                     name="license"
356                 />
357                 <div className="description licenceLabel">
358                     {i18n('External license')}
359                 </div>
360             </form>
361         </div>
362     );
363 };
364
365 const LicenseAgreementWithoutExternal = ({
366     licenceChange,
367     currentSoftwareProduct,
368     onLicenseChange
369 }) => {
370     if (!currentSoftwareProduct.licenseAgreementName) {
371         return (
372             <div
373                 className="missing-license clickable"
374                 onClick={event =>
375                     licenceChange(
376                         event,
377                         currentSoftwareProduct,
378                         onLicenseChange
379                     )
380                 }>
381                 <SVGIcon color="warning" name="exclamationTriangleFull" />
382                 <div className="warning-text">{i18n('Missing')}</div>
383             </div>
384         );
385     }
386     return <div>{currentSoftwareProduct.licenseAgreementName}</div>;
387 };
388
389 const LicenseAgreement = ({
390     licenceChange,
391     currentSoftwareProduct,
392     onLicenseChange,
393     externalLicenceEnabled
394 }) => {
395     if (externalLicenceEnabled) {
396         return (
397             <LicenseAgreementWithExternal
398                 licenceChange={licenceChange}
399                 currentSoftwareProduct={currentSoftwareProduct}
400                 onLicenseChange={onLicenseChange}
401             />
402         );
403     } else {
404         return (
405             <LicenseAgreementWithoutExternal
406                 licenceChange={licenceChange}
407                 currentSoftwareProduct={currentSoftwareProduct}
408                 onLicenseChange={onLicenseChange}
409             />
410         );
411     }
412 };
413
414 export default SoftwareProductLandingPageView;