[sdc] update code of sdc
[sdc.git] / openecomp-ui / src / sdc-app / onboarding / softwareProduct / details / SoftwareProductDetailsView.jsx
1 /*!
2  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
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
13  * or implied. See the License for the specific language governing
14  * permissions and limitations under the License.
15  */
16 import React, {Component, PropTypes} from 'react';
17
18 import i18n from 'nfvo-utils/i18n/i18n.js';
19 import sortByStringProperty from 'nfvo-utils/sortByStringProperty.js';
20 import Form from 'nfvo-components/input/validation/Form.jsx';
21 import Input from 'nfvo-components/input/validation/Input.jsx';
22 import InputOptions from 'nfvo-components/input/inputOptions/InputOptions.jsx';
23 import GridSection from 'nfvo-components/grid/GridSection.jsx';
24 import GridItem from 'nfvo-components/grid/GridItem.jsx';
25 import SoftwareProductCategoriesHelper from 'sdc-app/onboarding/softwareProduct/SoftwareProductCategoriesHelper.js';
26 import {forms} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
27
28 class GeneralSection extends React.Component {
29         static propTypes = {
30                 vendorId: PropTypes.string,
31                 name: PropTypes.string,
32                 description: PropTypes.string,
33                 subCategory: PropTypes.string,
34                 softwareProductCategories: PropTypes.array,
35                 finalizedLicenseModelList: PropTypes.array,
36                 onDataChanged: PropTypes.func.isRequired,
37                 onVendorParamChanged: PropTypes.func.isRequired,
38                 onSelectSubCategory: PropTypes.func.isRequired
39         };
40
41         onVendorParamChanged(e) {
42                 const selectedIndex = e.target.selectedIndex;
43                 const vendorId = e.target.options[selectedIndex].value;
44                 this.props.onVendorParamChanged({vendorId}, forms.VENDOR_SOFTWARE_PRODUCT_DETAILS);
45
46         }
47
48         onSelectSubCategory(e) {
49                 const selectedIndex = e.target.selectedIndex;
50                 const subCategory = e.target.options[selectedIndex].value;
51                 this.props.onSelectSubCategory(subCategory);
52         }
53
54         render (){
55                 let {genericFieldInfo} = this.props;
56                 return (
57                         <div>
58                         {genericFieldInfo && <GridSection title={i18n('General')}>
59                         <GridItem>
60                                 <Input
61                                         data-test-id='vsp-name'
62                                         label={i18n('Name')}
63                                         type='text'
64                                         value={this.props.name}
65                                         isRequired={true}
66                                         errorText={genericFieldInfo.name.errorText}
67                                         isValid={genericFieldInfo.name.isValid}
68                                         onChange={name => name.length <= 25 && this.props.onDataChanged({name}, forms.VENDOR_SOFTWARE_PRODUCT_DETAILS)}/>
69                                 <Input
70                                         data-test-id='vsp-vendor-name'
71                                         label={i18n('Vendor')}
72                                         type='select'
73                                         value={this.props.vendorId}
74                                         onChange={e => this.onVendorParamChanged(e)}>
75                                         {sortByStringProperty(
76                                                 this.props.finalizedLicenseModelList,
77                                                 'vendorName'
78                                         ).map(lm => <option key={lm.id} value={lm.id}>{lm.vendorName}</option>)
79                                         }
80                                 </Input>
81                                 <Input
82                                         data-test-id='vsp-category-name'
83                                         label={i18n('Category')}
84                                         type='select'
85                                         value={this.props.subCategory}
86                                         onChange={e => this.onSelectSubCategory(e)}>
87                                         {
88                                                 this.props.softwareProductCategories.map(category =>
89                                                         category.subcategories &&
90                                                         <optgroup
91                                                                 key={category.name}
92                                                                 label={category.name}>{category.subcategories.map(sub =>
93                                                                 <option
94                                                                         key={sub.uniqueId}
95                                                                         value={sub.uniqueId}>{`${sub.name} (${category.name})`}</option>)}
96                                                         </optgroup>
97                                                 )
98                                         }
99                                 </Input>
100                         </GridItem>
101                         <GridItem colSpan={2} stretch>
102                                 <Input
103                                         data-test-id='vsp-description'
104                                         label={i18n('Description')}
105                                         type='textarea'
106                                         isRequired={true}
107                                         isValid={genericFieldInfo.description.isValid}
108                                         errorText={genericFieldInfo.description.errorText}
109                                         value={this.props.description}
110                                         onChange={description => this.props.onDataChanged({description}, forms.VENDOR_SOFTWARE_PRODUCT_DETAILS)}/>
111                         </GridItem>
112                 </GridSection>}
113                 </div>);
114         }
115 }
116 class LicensesSection extends React.Component {
117         static propTypes = {
118                 onVendorParamChanged: PropTypes.func.isRequired,
119                 vendorId: PropTypes.string,
120                 licensingVersion: PropTypes.object,
121                 licensingVersionsList: PropTypes.array,
122                 licensingData: PropTypes.shape({
123                         licenceAgreement: PropTypes.string,
124                         featureGroups: PropTypes.array
125                 }),
126                 onFeatureGroupsChanged: PropTypes.func.isRequired,
127                 onLicensingDataChanged: PropTypes.func.isRequired,
128                 featureGroupsList: PropTypes.array,
129                 licenseAgreementList: PropTypes.array
130         };
131
132         onVendorParamChanged(e) {
133                 const selectedIndex = e.target.selectedIndex;
134                 const licensingVersion = e.target.options[selectedIndex].value;
135                 this.props.onVendorParamChanged({vendorId: this.props.vendorId, licensingVersion:{id:licensingVersion, label: licensingVersion}}, forms.VENDOR_SOFTWARE_PRODUCT_DETAILS);
136         }
137
138         onLicensingDataChanged(e) {
139                 const selectedIndex = e.target.selectedIndex;
140                 const licenseAgreement = e.target.options[selectedIndex].value;
141                 this.props.onLicensingDataChanged({licenseAgreement, featureGroups: []});
142         }
143
144         render(){
145                 return (
146                         <GridSection title={i18n('Licenses')}>
147                                 <GridItem>
148                                         <Input
149                                                 data-test-id='vsp-licensing-version'
150                                                 onChange={e => this.onVendorParamChanged(e)}
151                                                 value={this.props.licensingVersion ? this.props.licensingVersion.id : ''}
152                                                 label={i18n('Licensing Version')}
153                                                 type='select'>
154                                                 {this.props.licensingVersionsList.map(version =>
155                                                         <option
156                                                                 key={version.enum}
157                                                                 value={version.enum}>{version.title}
158                                                         </option>
159                                                 )}
160                                         </Input>
161                                 </GridItem>
162                                 <GridItem>
163                                         <Input
164                                                 data-test-id='vsp-license-agreement'
165                                                 label={i18n('License Agreement')}
166                                                 type='select'
167                                                 value={this.props.licensingData.licenseAgreement ? this.props.licensingData.licenseAgreement : '' }
168                                                 onChange={(e) => this.onLicensingDataChanged(e)}>
169                                                 <option key='placeholder' value=''>{i18n('Select...')}</option>
170                                                 {this.props.licenseAgreementList.map(la => <option value={la.id} key={la.id}>{la.name}</option>)}
171                                         </Input>
172                                 </GridItem>
173                                 <GridItem>
174                                         {this.props.licensingData.licenseAgreement && (
175                                                 <InputOptions
176                                                         data-test-id='vsp-feature-group'
177                                                         type='select'
178                                                         isMultiSelect={true}
179                                                         onInputChange={()=>{}}
180                                                         onEnumChange={featureGroups => this.props.onFeatureGroupsChanged({featureGroups})}
181                                                         multiSelectedEnum={this.props.licensingData.featureGroups}
182                                                         name='feature-groups'
183                                                         label={i18n('Feature Groups')}
184                                                         clearable={false}
185                                                         values={this.props.featureGroupsList}/>)
186                                         }
187                                 </GridItem>
188                         </GridSection>
189                 );
190         }
191 }
192 const AvailabilitySection = (props) => (
193         <GridSection title={i18n('Availability')}>
194                 <GridItem colSpan={2}>
195                         <Input
196                                 data-test-id='vsp-use-availability-zone'
197                                 label={i18n('Use Availability Zones for High Availability')}
198                                 type='checkbox'
199                                 value={props.dataMap['general/availability/useAvailabilityZonesForHighAvailability']}
200                                 onChange={(aZone) => props.onQDataChanged({'general/availability/useAvailabilityZonesForHighAvailability' : aZone})} />
201                 </GridItem>
202         </GridSection>
203 );
204 const RegionsSection = (props) => (
205         <GridSection title={i18n('Regions')}>
206                 <GridItem>
207                         <InputOptions
208                                 data-test-id='vsp-regions'
209                                 type='select'
210                                 isMultiSelect={true}
211                                 onInputChange={()=>{}}
212                                 onEnumChange={(regions) => props.onQDataChanged({'general/regionsData/regions' : regions})}
213                                 multiSelectedEnum={props.dataMap['general/regionsData/regions']}
214                                 name='vsp-regions'
215                                 clearable={false}
216                                 values={props.genericFieldInfo['general/regionsData/regions'].enum} />
217                 </GridItem>
218         </GridSection>
219 );
220 const StorageDataReplicationSection = (props) => (
221         <GridSection title={i18n('Storage Data Replication')}>
222                 <GridItem>
223                         <Input
224                                 data-test-id='vsp-storage-rep-size'
225                                 label={i18n('Storage Replication Size (GB)')}
226                                 type='number'
227                                 isValid={props.genericFieldInfo['general/storageDataReplication/storageReplicationSize'].isValid}
228                                 errorText={props.genericFieldInfo['general/storageDataReplication/storageReplicationSize'].errorText}
229                                 value={props.dataMap['general/storageDataReplication/storageReplicationSize']}
230                                 onChange={(sRep) => props.onQDataChanged({'general/storageDataReplication/storageReplicationSize' : sRep})} />
231                 </GridItem>
232                 <GridItem>
233                         <Input
234                                 data-test-id='vsp-storage-rep-source'
235                                 label={i18n('Storage Replication Source')}
236                                 type='text'
237                                 isValid={props.genericFieldInfo['general/storageDataReplication/storageReplicationSource'].isValid}
238                                 errorText={props.genericFieldInfo['general/storageDataReplication/storageReplicationSource'].errorText}
239                                 value={props.dataMap['general/storageDataReplication/storageReplicationSource']}
240                                 onChange={(sRepSource) => props.onQDataChanged({'general/storageDataReplication/storageReplicationSource' : sRepSource})} />
241                 </GridItem>
242                 <GridItem>
243                         <Input
244                                 data-test-id='vsp-storage-rep-freq'
245                                 label={i18n('Storage Replication Freq. (min)')}
246                                 type='number'
247                                 isValid={props.genericFieldInfo['general/storageDataReplication/storageReplicationFrequency'].isValid}
248                                 errorText={props.genericFieldInfo['general/storageDataReplication/storageReplicationFrequency'].errorText}
249                                 value={props.dataMap['general/storageDataReplication/storageReplicationFrequency']}
250                                 onChange={(sRepFreq) => props.onQDataChanged({'general/storageDataReplication/storageReplicationFrequency' : sRepFreq})} />
251                 </GridItem>
252                 <GridItem>
253                         <Input
254                                 data-test-id='vsp-storage-rep-dest'
255                                 label={i18n('Storage Replication Destination')}
256                                 type='text'
257                                 isValid={props.genericFieldInfo['general/storageDataReplication/storageReplicationDestination'].isValid}
258                                 errorText={props.genericFieldInfo['general/storageDataReplication/storageReplicationDestination'].errorText}
259                                 value={props.dataMap['general/storageDataReplication/storageReplicationDestination']}
260                                 onChange={(sRepDest) => props.onQDataChanged({'general/storageDataReplication/storageReplicationDestination' : sRepDest})} />
261                 </GridItem>
262         </GridSection>
263 );
264
265 class SoftwareProductDetails extends Component {
266
267         static propTypes = {
268                 vendorName: PropTypes.string,
269                 currentSoftwareProduct: PropTypes.shape({
270                         id: PropTypes.string,
271                         name: PropTypes.string,
272                         description: PropTypes.string,
273                         category: PropTypes.string,
274                         subCategory: PropTypes.string,
275                         vendorId: PropTypes.string,
276                         vendorName: PropTypes.string,
277                         licensingVersion: PropTypes.object,
278                         licensingData: PropTypes.shape({
279                                 licenceAgreement: PropTypes.string,
280                                 featureGroups: PropTypes.array
281                         })
282                 }),
283                 softwareProductCategories: PropTypes.array,
284                 finalizedLicenseModelList: PropTypes.array,
285                 licenseAgreementList: PropTypes.array,
286                 featureGroupsList: PropTypes.array,
287                 onSubmit: PropTypes.func.isRequired,
288                 onDataChanged: PropTypes.func.isRequired,
289                 onValidityChanged: PropTypes.func.isRequired,
290                 qdata: PropTypes.object.isRequired,
291                 onQDataChanged: PropTypes.func.isRequired,
292                 onVendorParamChanged: PropTypes.func.isRequired
293         };
294
295         state = {
296                 licensingVersionsList: []
297         };
298
299         prepareDataForGeneralSection(){
300                 let {softwareProductCategories, finalizedLicenseModelList, onDataChanged, currentSoftwareProduct, genericFieldInfo} = this.props;
301                 let {name, description, vendorId, subCategory} = currentSoftwareProduct;
302                 return {
303                         name,
304                         description,
305                         vendorId,
306                         subCategory,
307                         softwareProductCategories,
308                         finalizedLicenseModelList,
309                         onDataChanged,
310                         onVendorParamChanged: args => this.onVendorParamChanged(args),
311                         onSelectSubCategory: args => this.onSelectSubCategory(args),
312                         genericFieldInfo
313                 };
314
315         }
316
317         prepareDataForLicensesSection(){
318                 let { featureGroupsList, licenseAgreementList, currentSoftwareProduct } = this.props;
319                 let {vendorId, licensingVersion, licensingData = {}} = currentSoftwareProduct;
320                 let licensingVersionsList = this.state.licensingVersionsList.length > 0 ? this.state.licensingVersionsList : this.refreshVendorVersionsList(vendorId);
321                 return {
322                         onVendorParamChanged: args => this.onVendorParamChanged(args),
323                         vendorId,
324                         licensingVersion,
325                         licensingVersionsList,
326                         licensingData,
327                         onFeatureGroupsChanged: args => this.onFeatureGroupsChanged(args),
328                         onLicensingDataChanged: args => this.onLicensingDataChanged(args),
329                         featureGroupsList,
330                         licenseAgreementList,
331                 };
332
333         }
334
335         render() {
336                 let {currentSoftwareProduct} = this.props;
337                 let {qdata, onQDataChanged, dataMap, qGenericFieldInfo} = this.props;
338                 let {isReadOnlyMode} = this.props;
339
340                 return (
341                 <div className='vsp-details-page'>
342                                 <Form
343                                         ref={(validationForm) => this.validationForm = validationForm}
344                                         className='vsp-general-tab'
345                                         hasButtons={false}
346                                         formReady={null}
347                                         isValid={this.props.isFormValid}
348                                         onSubmit={() => this.props.onSubmit(currentSoftwareProduct, qdata)}
349                                         onValidityChanged={(isValidityData) => this.props.onValidityChanged(isValidityData)}
350                                         isReadOnlyMode={isReadOnlyMode}>
351                                         <GeneralSection {...this.prepareDataForGeneralSection()}/>
352                                         <LicensesSection {...this.prepareDataForLicensesSection()}/>
353                                         <AvailabilitySection onQDataChanged={onQDataChanged} dataMap={dataMap} />
354                                         <RegionsSection onQDataChanged={onQDataChanged} dataMap={dataMap} genericFieldInfo={qGenericFieldInfo} />
355                                         <StorageDataReplicationSection onQDataChanged={onQDataChanged} dataMap={dataMap} genericFieldInfo={qGenericFieldInfo} />
356                                 </Form>
357                         </div>
358                 );
359         }
360
361         onVendorParamChanged({vendorId, licensingVersion}) {
362                 let {finalizedLicenseModelList, onVendorParamChanged} = this.props;
363                 if(!licensingVersion) {
364                         const licensingVersionsList = this.refreshVendorVersionsList(vendorId);
365                         licensingVersion = licensingVersionsList.length > 0 ? licensingVersionsList[0].enum : '';
366                 }
367                 let vendorName = finalizedLicenseModelList.find(licenseModelItem => licenseModelItem.id === vendorId).vendorName || '';
368                 let deltaData = {
369                         vendorId,
370                         vendorName,
371                         licensingVersion,
372                         licensingData: {}
373                 };
374
375                 onVendorParamChanged(deltaData, forms.VENDOR_SOFTWARE_PRODUCT_DETAILS);
376
377         }
378
379         refreshVendorVersionsList(vendorId) {
380                 if(!vendorId) {
381                         return [];
382                 }
383
384                 let {finalVersions} = this.props.finalizedLicenseModelList.find(vendor => vendor.id === vendorId);
385
386                 let licensingVersionsList = [{
387                         enum: '',
388                         title: i18n('Select...')
389                 }];
390                 if(finalVersions) {
391                         finalVersions.forEach(version => licensingVersionsList.push({
392                                 enum: version.id,
393                                 title: version.label
394                         }));
395                 }
396
397                 return licensingVersionsList;
398         }
399
400         onFeatureGroupsChanged({featureGroups}) {
401                 this.onLicensingDataChanged({featureGroups});
402         }
403
404         onLicensingDataChanged(deltaData) {
405                 this.props.onDataChanged({
406                         licensingData: {
407                                 ...this.props.currentSoftwareProduct.licensingData,
408                                 ...deltaData
409                         }
410                 }, forms.VENDOR_SOFTWARE_PRODUCT_DETAILS);
411         }
412
413         onSelectSubCategory(subCategory) {
414                 let {softwareProductCategories, onDataChanged} = this.props;
415                 let category = SoftwareProductCategoriesHelper.getCurrentCategoryOfSubCategory(subCategory, softwareProductCategories);
416                 onDataChanged({category, subCategory}, forms.VENDOR_SOFTWARE_PRODUCT_DETAILS);
417         }
418
419         save(){
420                 return this.validationForm.handleFormSubmit(new Event('dummy'));
421         }
422 }
423
424 export default SoftwareProductDetails;