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, {Component, PropTypes} from 'react';
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';
28 class GeneralSection extends React.Component {
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
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);
48 onSelectSubCategory(e) {
49 const selectedIndex = e.target.selectedIndex;
50 const subCategory = e.target.options[selectedIndex].value;
51 this.props.onSelectSubCategory(subCategory);
55 let {genericFieldInfo} = this.props;
58 {genericFieldInfo && <GridSection title={i18n('General')}>
61 data-test-id='vsp-name'
64 value={this.props.name}
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)}/>
70 data-test-id='vsp-vendor-name'
71 label={i18n('Vendor')}
73 value={this.props.vendorId}
74 onChange={e => this.onVendorParamChanged(e)}>
75 {sortByStringProperty(
76 this.props.finalizedLicenseModelList,
78 ).map(lm => <option key={lm.id} value={lm.id}>{lm.vendorName}</option>)
82 data-test-id='vsp-category-name'
83 label={i18n('Category')}
85 value={this.props.subCategory}
86 onChange={e => this.onSelectSubCategory(e)}>
88 this.props.softwareProductCategories.map(category =>
89 category.subcategories &&
92 label={category.name}>{category.subcategories.map(sub =>
95 value={sub.uniqueId}>{`${sub.name} (${category.name})`}</option>)}
101 <GridItem colSpan={2} stretch>
103 data-test-id='vsp-description'
104 label={i18n('Description')}
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)}/>
116 class LicensesSection extends React.Component {
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
126 onFeatureGroupsChanged: PropTypes.func.isRequired,
127 onLicensingDataChanged: PropTypes.func.isRequired,
128 featureGroupsList: PropTypes.array,
129 licenseAgreementList: PropTypes.array
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);
138 onLicensingDataChanged(e) {
139 const selectedIndex = e.target.selectedIndex;
140 const licenseAgreement = e.target.options[selectedIndex].value;
141 this.props.onLicensingDataChanged({licenseAgreement, featureGroups: []});
146 <GridSection title={i18n('Licenses')}>
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')}
154 {this.props.licensingVersionsList.map(version =>
157 value={version.enum}>{version.title}
164 data-test-id='vsp-license-agreement'
165 label={i18n('License Agreement')}
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>)}
174 {this.props.licensingData.licenseAgreement && (
176 data-test-id='vsp-feature-group'
179 onInputChange={()=>{}}
180 onEnumChange={featureGroups => this.props.onFeatureGroupsChanged({featureGroups})}
181 multiSelectedEnum={this.props.licensingData.featureGroups}
182 name='feature-groups'
183 label={i18n('Feature Groups')}
185 values={this.props.featureGroupsList}/>)
192 const AvailabilitySection = (props) => (
193 <GridSection title={i18n('Availability')}>
194 <GridItem colSpan={2}>
196 data-test-id='vsp-use-availability-zone'
197 label={i18n('Use Availability Zones for High Availability')}
199 value={props.dataMap['general/availability/useAvailabilityZonesForHighAvailability']}
200 onChange={(aZone) => props.onQDataChanged({'general/availability/useAvailabilityZonesForHighAvailability' : aZone})} />
204 const RegionsSection = (props) => (
205 <GridSection title={i18n('Regions')}>
208 data-test-id='vsp-regions'
211 onInputChange={()=>{}}
212 onEnumChange={(regions) => props.onQDataChanged({'general/regionsData/regions' : regions})}
213 multiSelectedEnum={props.dataMap['general/regionsData/regions']}
216 values={props.genericFieldInfo['general/regionsData/regions'].enum} />
220 const StorageDataReplicationSection = (props) => (
221 <GridSection title={i18n('Storage Data Replication')}>
224 data-test-id='vsp-storage-rep-size'
225 label={i18n('Storage Replication Size (GB)')}
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})} />
234 data-test-id='vsp-storage-rep-source'
235 label={i18n('Storage Replication Source')}
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})} />
244 data-test-id='vsp-storage-rep-freq'
245 label={i18n('Storage Replication Freq. (min)')}
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})} />
254 data-test-id='vsp-storage-rep-dest'
255 label={i18n('Storage Replication Destination')}
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})} />
265 class SoftwareProductDetails extends Component {
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
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
296 licensingVersionsList: []
299 prepareDataForGeneralSection(){
300 let {softwareProductCategories, finalizedLicenseModelList, onDataChanged, currentSoftwareProduct, genericFieldInfo} = this.props;
301 let {name, description, vendorId, subCategory} = currentSoftwareProduct;
307 softwareProductCategories,
308 finalizedLicenseModelList,
310 onVendorParamChanged: args => this.onVendorParamChanged(args),
311 onSelectSubCategory: args => this.onSelectSubCategory(args),
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);
322 onVendorParamChanged: args => this.onVendorParamChanged(args),
325 licensingVersionsList,
327 onFeatureGroupsChanged: args => this.onFeatureGroupsChanged(args),
328 onLicensingDataChanged: args => this.onLicensingDataChanged(args),
330 licenseAgreementList,
336 let {currentSoftwareProduct} = this.props;
337 let {qdata, onQDataChanged, dataMap, qGenericFieldInfo} = this.props;
338 let {isReadOnlyMode} = this.props;
341 <div className='vsp-details-page'>
343 ref={(validationForm) => this.validationForm = validationForm}
344 className='vsp-general-tab'
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} />
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 : '';
367 let vendorName = finalizedLicenseModelList.find(licenseModelItem => licenseModelItem.id === vendorId).vendorName || '';
375 onVendorParamChanged(deltaData, forms.VENDOR_SOFTWARE_PRODUCT_DETAILS);
379 refreshVendorVersionsList(vendorId) {
384 let {finalVersions} = this.props.finalizedLicenseModelList.find(vendor => vendor.id === vendorId);
386 let licensingVersionsList = [{
388 title: i18n('Select...')
391 finalVersions.forEach(version => licensingVersionsList.push({
397 return licensingVersionsList;
400 onFeatureGroupsChanged({featureGroups}) {
401 this.onLicensingDataChanged({featureGroups});
404 onLicensingDataChanged(deltaData) {
405 this.props.onDataChanged({
407 ...this.props.currentSoftwareProduct.licensingData,
410 }, forms.VENDOR_SOFTWARE_PRODUCT_DETAILS);
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);
420 return this.validationForm.handleFormSubmit(new Event('dummy'));
424 export default SoftwareProductDetails;