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 i18n from 'nfvo-utils/i18n/i18n.js';
18 import Validator from 'nfvo-utils/Validator.js';
20 import Tabs from 'sdc-ui/lib/react/Tabs.js';
21 import Tab from 'sdc-ui/lib/react/Tab.js';
23 import Button from 'sdc-ui/lib/react/Button.js';
24 import Form from 'nfvo-components/input/validation/Form.jsx';
25 import Input from 'nfvo-components/input/validation/Input.jsx';
26 import GridSection from 'nfvo-components/grid/GridSection.jsx';
27 import GridItem from 'nfvo-components/grid/GridItem.jsx';
28 import {optionsInputValues as licenseKeyGroupOptionsInputValues, LKG_FORM_NAME, tabIds} from './LicenseKeyGroupsConstants.js';
29 import {optionsInputValues as LicenseModelOptionsInputValues} from '../LicenseModelConstants.js';
30 import {validateStartDate, thresholdValueValidation} from '../LicenseModelValidations.js';
31 import {other as optionInputOther} from 'nfvo-components/input/validation/InputOptions.jsx';
32 import InputOptions from 'nfvo-components/input/validation/InputOptions.jsx';
34 import {DATE_FORMAT} from 'sdc-app/onboarding/OnboardingConstants.js';
36 import LicenseKeyGroupsLimits from './LicenseKeyGroupsLimits.js';
37 import {limitType, NEW_LIMIT_TEMP_ID} from '../limits/LimitEditorConstants.js';
39 const LicenseKeyGroupPropType = React.PropTypes.shape({
40 id: React.PropTypes.string,
41 name: React.PropTypes.string,
42 description: React.PropTypes.string,
43 increments: React.PropTypes.string,
44 operationalScope: React.PropTypes.shape({
45 choices: React.PropTypes.array,
46 other: React.PropTypes.string
48 type: React.PropTypes.string,
49 thresholdUnits: React.PropTypes.string,
50 thresholdValue: React.PropTypes.number,
51 startDate: React.PropTypes.string,
52 expiryDate: React.PropTypes.string
55 const LicenseKeyGroupFormContent = ({data, onDataChanged, genericFieldInfo, validateName, validateStartDate, thresholdValueValidation}) => {
56 let {name, description, increments, operationalScope, type, thresholdUnits, thresholdValue, startDate, expiryDate} = data;
59 <GridItem colSpan={2}>
61 onChange={name => onDataChanged({name}, LKG_FORM_NAME, {name: validateName})}
63 data-test-id='create-lkg-name'
65 isValid={genericFieldInfo.name.isValid}
66 errorText={genericFieldInfo.name.errorText}
70 <GridItem colSpan={2}>
72 onInputChange={()=>{}}
74 onEnumChange={operationalScope => onDataChanged({operationalScope:{choices: operationalScope, other: ''}},
76 onOtherChange={operationalScope => onDataChanged({operationalScope:{choices: [optionInputOther.OTHER],
77 other: operationalScope}}, LKG_FORM_NAME)}
78 label={i18n('Operational Scope')}
79 data-test-id='create-lkg-operational-scope'
81 multiSelectedEnum={operationalScope && operationalScope.choices}
82 otherValue={operationalScope && operationalScope.other}
83 values={licenseKeyGroupOptionsInputValues.OPERATIONAL_SCOPE}
84 isValid={genericFieldInfo.operationalScope.isValid}
85 errorText={genericFieldInfo.operationalScope.errorText} />
87 <GridItem colSpan={2}>
89 onChange={description => onDataChanged({description}, LKG_FORM_NAME)}
90 label={i18n('Description')}
91 data-test-id='create-lkg-description'
93 isValid={genericFieldInfo.description.isValid}
94 errorText={genericFieldInfo.description.errorText}
96 overlayPos='bottom' />
98 <GridItem colSpan={2}>
101 onChange={e => { const selectedIndex = e.target.selectedIndex;
102 const val = e.target.options[selectedIndex].value;
103 onDataChanged({type: val}, LKG_FORM_NAME);}}
106 data-test-id='create-lkg-type'
107 isValid={genericFieldInfo.type.isValid}
108 errorText={genericFieldInfo.type.errorText}
109 groupClassName='bootstrap-input-options'
110 className='input-options-select'
113 licenseKeyGroupOptionsInputValues.TYPE.map(type =>
114 (<option key={type.enum} value={type.enum}>{type.title}</option>))
121 // setting the unit to the correct value
122 const selectedIndex = e.target.selectedIndex;
123 const val = e.target.options[selectedIndex].value;
124 onDataChanged({thresholdUnits: val}, LKG_FORM_NAME);
125 // TODO make sure that the value is valid too
126 onDataChanged({thresholdValue: thresholdValue}, LKG_FORM_NAME,{thresholdValue : thresholdValueValidation});}
129 value={thresholdUnits}
130 label={i18n('Threshold Units')}
131 data-test-id='create-ep-threshold-units'
132 isValid={genericFieldInfo.thresholdUnits.isValid}
133 errorText={genericFieldInfo.thresholdUnits.errorText}
134 groupClassName='bootstrap-input-options'
135 className='input-options-select'
137 {LicenseModelOptionsInputValues.THRESHOLD_UNITS.map(mtype =>
138 <option key={mtype.enum} value={mtype.enum}>{`${mtype.title}`}</option>)}
143 className='entitlement-pools-form-row-threshold-value'
144 onChange={thresholdValue => onDataChanged({thresholdValue}, LKG_FORM_NAME,
145 {thresholdValue : thresholdValueValidation})}
146 label={i18n('Threshold Value')}
147 isValid={genericFieldInfo.thresholdValue.isValid}
148 errorText={genericFieldInfo.thresholdValue.errorText}
149 data-test-id='create-ep-threshold-value'
150 value={thresholdValue}
156 label={i18n('Start Date')}
158 dateFormat={DATE_FORMAT}
159 startDate={startDate}
161 onChange={startDate => onDataChanged(
162 {startDate: startDate ? startDate.format(DATE_FORMAT) : ''},
164 {startDate: validateStartDate}
166 isValid={genericFieldInfo.startDate.isValid}
167 errorText={genericFieldInfo.startDate.errorText}
173 label={i18n('Expiry Date')}
175 dateFormat={DATE_FORMAT}
176 startDate={startDate}
178 onChange={expiryDate => {
179 onDataChanged({expiryDate: expiryDate ? expiryDate.format(DATE_FORMAT) : ''}, LKG_FORM_NAME);
180 onDataChanged({startDate}, LKG_FORM_NAME, {startDate: validateStartDate});
182 isValid={genericFieldInfo.expiryDate.isValid}
183 errorText={genericFieldInfo.expiryDate.errorText}
186 <GridItem colSpan={2}>
188 onChange={increments => onDataChanged({increments}, LKG_FORM_NAME)}
189 label={i18n('Increments')}
191 data-test-id='create-ep-increments'
198 class LicenseKeyGroupsEditorView extends React.Component {
200 data: LicenseKeyGroupPropType,
201 previousData: LicenseKeyGroupPropType,
202 LKGNames: React.PropTypes.object,
203 isReadOnlyMode: React.PropTypes.bool,
204 onDataChanged: React.PropTypes.func.isRequired,
205 onSubmit: React.PropTypes.func.isRequired,
206 onCancel: React.PropTypes.func.isRequired
209 static defaultProps = {
213 componentDidUpdate(prevProps) {
214 if (this.props.formReady && this.props.formReady !== prevProps.formReady) { // if form validation succeeded -> continue with submit
220 localFeatureGroupsListFilter: '',
221 selectedTab: tabIds.GENERAL,
226 let {data = {}, onDataChanged, isReadOnlyMode, onCloseLimitEditor, genericFieldInfo, limitsList = []} = this.props;
227 let {selectedTab} = this.state;
228 const isTabsDisabled = !data.id || !this.props.isFormValid;
230 <div className='license-keygroup-editor'>
233 activeTab={selectedTab}
234 onTabClick={(tabIndex)=>{
235 if (tabIndex === tabIds.ADD_LIMIT_BUTTON) {
238 this.setState({selectedTab: tabIndex});
239 onCloseLimitEditor();
240 this.setState({selectedLimit: ''});
244 <Tab tabId={tabIds.GENERAL} data-test-id='general-tab' title={i18n('General')}>
245 { genericFieldInfo &&
249 isValid={this.props.isFormValid}
250 formReady={this.props.formReady}
251 onValidateForm={() => this.props.onValidateForm(LKG_FORM_NAME) }
253 isReadOnlyMode={isReadOnlyMode}
254 className='license-model-form license-key-groups-form'>
255 <LicenseKeyGroupFormContent
257 onDataChanged={onDataChanged}
258 genericFieldInfo={genericFieldInfo}
259 validateName={(value)=> this.validateName(value)}
260 validateStartDate={(value, state)=> validateStartDate(value, state)}
261 thresholdValueValidation={(value, state) => thresholdValueValidation(value, state)}/>
265 <Tab tabId={tabIds.SP_LIMITS} disabled={isTabsDisabled} data-test-id='general-tab' title={i18n('SP Limits')}>
266 {selectedTab === tabIds.SP_LIMITS &&
267 <LicenseKeyGroupsLimits
268 limitType={limitType.SERVICE_PROVIDER}
269 limitsList={limitsList.filter(item => item.type === limitType.SERVICE_PROVIDER)}
270 selectedLimit={this.state.selectedLimit}
271 onCloseLimitEditor={() => this.onCloseLimitEditor()}
272 onSelectLimit={limit => this.onSelectLimit(limit)}
273 isReadOnlyMode={isReadOnlyMode} />}
275 <Tab tabId={tabIds.VENDOR_LIMITS} disabled={isTabsDisabled} data-test-id='general-tab' title={i18n('Vendor Limits')}>
276 {selectedTab === tabIds.VENDOR_LIMITS &&
277 <LicenseKeyGroupsLimits
278 limitType={limitType.VENDOR}
279 limitsList={limitsList.filter(item => item.type === limitType.VENDOR)}
280 selectedLimit={this.state.selectedLimit}
281 onCloseLimitEditor={() => this.onCloseLimitEditor()}
282 onSelectLimit={limit => this.onSelectLimit(limit)}
283 isReadOnlyMode={isReadOnlyMode} />}
285 {selectedTab !== tabIds.GENERAL ?
287 className='add-limit-button'
288 tabId={tabIds.ADD_LIMIT_BUTTON}
291 disabled={this.state.selectedLimit || isReadOnlyMode}>
295 <div></div> // Render empty div to not break tabs
299 <GridSection className='license-model-modal-buttons license-key-group-editor-buttons'>
300 {!this.state.selectedLimit &&
301 <Button btnType='default' disabled={!this.props.isFormValid || isReadOnlyMode} onClick={() => this.submit()} type='reset'>
305 <Button btnType={this.state.selectedLimit ? 'default' : 'outline'} onClick={() => this.props.onCancel()} type='reset'>
315 const {data: licenseKeyGroup, previousData: previousLicenseKeyGroup, formReady, onValidateForm, onSubmit} = this.props;
317 onValidateForm(LKG_FORM_NAME);
319 onSubmit({licenseKeyGroup, previousLicenseKeyGroup});
323 validateName(value) {
324 const {data: {id}, LKGNames} = this.props;
325 const isExists = Validator.isItemNameAlreadyExistsInList({itemId: id, itemName: value, list: LKGNames});
327 return !isExists ? {isValid: true, errorText: ''} :
328 {isValid: false, errorText: i18n('License key group by the name \'' + value + '\' already exists. License key group name must be unique')};
331 onSelectLimit(limit) {
332 if (limit.id === this.state.selectedLimit) {
333 this.setState({selectedLimit: ''});
336 this.setState({selectedLimit: limit.id});
337 this.props.onOpenLimitEditor(limit);
340 onCloseLimitEditor() {
341 this.setState({selectedLimit: ''});
342 this.props.onCloseLimitEditor();
346 this.setState({selectedLimit: NEW_LIMIT_TEMP_ID});
347 this.props.onOpenLimitEditor();
351 export default LicenseKeyGroupsEditorView;