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 PropTypes from 'prop-types';
18 import i18n from 'nfvo-utils/i18n/i18n.js';
19 import Validator from 'nfvo-utils/Validator.js';
21 import Tabs from 'sdc-ui/lib/react/Tabs.js';
22 import Tab from 'sdc-ui/lib/react/Tab.js';
24 import Button from 'sdc-ui/lib/react/Button.js';
25 import Form from 'nfvo-components/input/validation/Form.jsx';
26 import Input from 'nfvo-components/input/validation/Input.jsx';
27 import GridSection from 'nfvo-components/grid/GridSection.jsx';
28 import GridItem from 'nfvo-components/grid/GridItem.jsx';
29 import {optionsInputValues as licenseKeyGroupOptionsInputValues, LKG_FORM_NAME, tabIds} from './LicenseKeyGroupsConstants.js';
30 import {optionsInputValues as LicenseModelOptionsInputValues} from '../LicenseModelConstants.js';
31 import {validateStartDate, thresholdValueValidation} from '../LicenseModelValidations.js';
32 import {other as optionInputOther} from 'nfvo-components/input/validation/InputOptions.jsx';
33 import InputOptions from 'nfvo-components/input/validation/InputOptions.jsx';
35 import {DATE_FORMAT} from 'sdc-app/onboarding/OnboardingConstants.js';
37 import LicenseKeyGroupsLimits from './LicenseKeyGroupsLimits.js';
38 import {limitType, NEW_LIMIT_TEMP_ID} from '../limits/LimitEditorConstants.js';
40 const LicenseKeyGroupPropType = PropTypes.shape({
42 name: PropTypes.string,
43 description: PropTypes.string,
44 increments: PropTypes.string,
45 operationalScope: PropTypes.shape({
46 choices: PropTypes.array,
47 other: PropTypes.string
49 type: PropTypes.string,
50 thresholdUnits: PropTypes.string,
51 thresholdValue: PropTypes.number,
52 startDate: PropTypes.string,
53 expiryDate: PropTypes.string
56 const LicenseKeyGroupFormContent = ({data, onDataChanged, genericFieldInfo, validateName, validateStartDate, thresholdValueValidation}) => {
57 let {name, description, increments, operationalScope, type, thresholdUnits, thresholdValue, startDate, expiryDate} = data;
59 <GridSection hasLostColSet>
60 <GridItem colSpan={2}>
62 onChange={name => onDataChanged({name}, LKG_FORM_NAME, {name: validateName})}
64 data-test-id='create-lkg-name'
66 isValid={genericFieldInfo.name.isValid}
67 errorText={genericFieldInfo.name.errorText}
71 <GridItem colSpan={2} lastColInRow>
73 onInputChange={()=>{}}
75 onEnumChange={operationalScope => onDataChanged({operationalScope:{choices: operationalScope, other: ''}},
77 onOtherChange={operationalScope => onDataChanged({operationalScope:{choices: [optionInputOther.OTHER],
78 other: operationalScope}}, LKG_FORM_NAME)}
79 label={i18n('Operational Scope')}
80 data-test-id='create-lkg-operational-scope'
82 multiSelectedEnum={operationalScope && operationalScope.choices}
83 otherValue={operationalScope && operationalScope.other}
84 values={licenseKeyGroupOptionsInputValues.OPERATIONAL_SCOPE}
85 isValid={genericFieldInfo.operationalScope.isValid}
86 errorText={genericFieldInfo.operationalScope.errorText} />
88 <GridItem colSpan={2}>
90 onChange={description => onDataChanged({description}, LKG_FORM_NAME)}
91 label={i18n('Description')}
92 data-test-id='create-lkg-description'
94 isValid={genericFieldInfo.description.isValid}
95 errorText={genericFieldInfo.description.errorText}
97 overlayPos='bottom' />
99 <GridItem colSpan={2} lastColInRow>
102 onChange={e => { const selectedIndex = e.target.selectedIndex;
103 const val = e.target.options[selectedIndex].value;
104 onDataChanged({type: val}, LKG_FORM_NAME);}}
107 data-test-id='create-lkg-type'
108 isValid={genericFieldInfo.type.isValid}
109 errorText={genericFieldInfo.type.errorText}
110 groupClassName='bootstrap-input-options'
111 className='input-options-select'
115 licenseKeyGroupOptionsInputValues.TYPE.map(type =>
116 (<option key={type.enum} value={type.enum}>{type.title}</option>))
123 // setting the unit to the correct value
124 const selectedIndex = e.target.selectedIndex;
125 const val = e.target.options[selectedIndex].value;
126 onDataChanged({thresholdUnits: val}, LKG_FORM_NAME);
127 // TODO make sure that the value is valid too
128 onDataChanged({thresholdValue: thresholdValue}, LKG_FORM_NAME,{thresholdValue : thresholdValueValidation});}
131 value={thresholdUnits}
132 label={i18n('Threshold Units')}
133 data-test-id='create-ep-threshold-units'
134 isValid={genericFieldInfo.thresholdUnits.isValid}
135 errorText={genericFieldInfo.thresholdUnits.errorText}
136 groupClassName='bootstrap-input-options'
137 className='input-options-select'
139 {LicenseModelOptionsInputValues.THRESHOLD_UNITS.map(mtype =>
140 <option key={mtype.enum} value={mtype.enum}>{`${mtype.title}`}</option>)}
145 className='entitlement-pools-form-row-threshold-value'
146 onChange={thresholdValue => onDataChanged({thresholdValue}, LKG_FORM_NAME,
147 {thresholdValue : thresholdValueValidation})}
148 label={i18n('Threshold Value')}
149 isValid={genericFieldInfo.thresholdValue.isValid}
150 errorText={genericFieldInfo.thresholdValue.errorText}
151 data-test-id='create-ep-threshold-value'
152 value={thresholdValue}
158 label={i18n('Start Date')}
160 dateFormat={DATE_FORMAT}
161 startDate={startDate}
163 onChange={startDate => onDataChanged(
164 {startDate: startDate ? startDate.format(DATE_FORMAT) : ''},
166 {startDate: validateStartDate}
168 isValid={genericFieldInfo.startDate.isValid}
169 errorText={genericFieldInfo.startDate.errorText}
172 <GridItem lastColInRow>
175 label={i18n('Expiry Date')}
177 dateFormat={DATE_FORMAT}
178 startDate={startDate}
180 onChange={expiryDate => {
181 onDataChanged({expiryDate: expiryDate ? expiryDate.format(DATE_FORMAT) : ''}, LKG_FORM_NAME);
182 onDataChanged({startDate}, LKG_FORM_NAME, {startDate: validateStartDate});
184 isValid={genericFieldInfo.expiryDate.isValid}
185 errorText={genericFieldInfo.expiryDate.errorText}
188 <GridItem colSpan={2}>
190 onChange={increments => onDataChanged({increments}, LKG_FORM_NAME)}
191 label={i18n('Increments')}
193 data-test-id='create-ep-increments'
200 class LicenseKeyGroupsEditorView extends React.Component {
202 data: LicenseKeyGroupPropType,
203 previousData: LicenseKeyGroupPropType,
204 LKGNames: PropTypes.object,
205 isReadOnlyMode: PropTypes.bool,
206 onDataChanged: PropTypes.func.isRequired,
207 onSubmit: PropTypes.func.isRequired,
208 onCancel: PropTypes.func.isRequired
211 static defaultProps = {
215 componentDidUpdate(prevProps) {
216 if (this.props.formReady && this.props.formReady !== prevProps.formReady) { // if form validation succeeded -> continue with submit
222 localFeatureGroupsListFilter: '',
223 selectedTab: tabIds.GENERAL,
228 let {data = {}, onDataChanged, isReadOnlyMode, onCloseLimitEditor, genericFieldInfo, limitsList = []} = this.props;
229 let {selectedTab} = this.state;
230 const isTabsDisabled = !data.id || !this.props.isFormValid;
232 <div className='license-keygroup-editor'>
235 activeTab={selectedTab}
236 onTabClick={(tabIndex)=>{
237 if (tabIndex === tabIds.ADD_LIMIT_BUTTON) {
240 this.setState({selectedTab: tabIndex});
241 onCloseLimitEditor();
242 this.setState({selectedLimit: ''});
246 <Tab tabId={tabIds.GENERAL} data-test-id='general-tab' title={i18n('General')}>
247 { genericFieldInfo &&
251 isValid={this.props.isFormValid}
252 formReady={this.props.formReady}
253 onValidateForm={() => this.props.onValidateForm(LKG_FORM_NAME) }
255 isReadOnlyMode={isReadOnlyMode}
256 className='license-model-form license-key-groups-form'>
257 <LicenseKeyGroupFormContent
259 onDataChanged={onDataChanged}
260 genericFieldInfo={genericFieldInfo}
261 validateName={(value)=> this.validateName(value)}
262 validateStartDate={(value, state)=> validateStartDate(value, state)}
263 thresholdValueValidation={(value, state) => thresholdValueValidation(value, state)}/>
267 <Tab tabId={tabIds.SP_LIMITS} disabled={isTabsDisabled} data-test-id='general-tab' title={i18n('SP Limits')}>
268 {selectedTab === tabIds.SP_LIMITS &&
269 <LicenseKeyGroupsLimits
270 limitType={limitType.SERVICE_PROVIDER}
271 limitsList={limitsList.filter(item => item.type === limitType.SERVICE_PROVIDER)}
272 selectedLimit={this.state.selectedLimit}
273 onCloseLimitEditor={() => this.onCloseLimitEditor()}
274 onSelectLimit={limit => this.onSelectLimit(limit)}
275 isReadOnlyMode={isReadOnlyMode} />}
277 <Tab tabId={tabIds.VENDOR_LIMITS} disabled={isTabsDisabled} data-test-id='general-tab' title={i18n('Vendor Limits')}>
278 {selectedTab === tabIds.VENDOR_LIMITS &&
279 <LicenseKeyGroupsLimits
280 limitType={limitType.VENDOR}
281 limitsList={limitsList.filter(item => item.type === limitType.VENDOR)}
282 selectedLimit={this.state.selectedLimit}
283 onCloseLimitEditor={() => this.onCloseLimitEditor()}
284 onSelectLimit={limit => this.onSelectLimit(limit)}
285 isReadOnlyMode={isReadOnlyMode} />}
287 {selectedTab !== tabIds.GENERAL ?
289 className='add-limit-button'
290 tabId={tabIds.ADD_LIMIT_BUTTON}
293 disabled={this.state.selectedLimit || isReadOnlyMode}>
297 <div></div> // Render empty div to not break tabs
301 <GridSection className='license-model-modal-buttons license-key-group-editor-buttons'>
302 {!this.state.selectedLimit &&
303 <Button btnType='default' disabled={!this.props.isFormValid || isReadOnlyMode} onClick={() => this.submit()} type='reset'>
307 <Button btnType={this.state.selectedLimit ? 'default' : 'outline'} onClick={() => this.props.onCancel()} type='reset'>
317 const {data: licenseKeyGroup, previousData: previousLicenseKeyGroup, formReady, onValidateForm, onSubmit} = this.props;
319 onValidateForm(LKG_FORM_NAME);
321 onSubmit({licenseKeyGroup, previousLicenseKeyGroup});
325 validateName(value) {
326 const {data: {id}, LKGNames} = this.props;
327 const isExists = Validator.isItemNameAlreadyExistsInList({itemId: id, itemName: value, list: LKGNames});
329 return !isExists ? {isValid: true, errorText: ''} :
330 {isValid: false, errorText: i18n('License key group by the name \'' + value + '\' already exists. License key group name must be unique')};
333 onSelectLimit(limit) {
334 if (limit.id === this.state.selectedLimit) {
335 this.setState({selectedLimit: ''});
338 this.setState({selectedLimit: limit.id});
339 this.props.onOpenLimitEditor(limit);
342 onCloseLimitEditor() {
343 this.setState({selectedLimit: ''});
344 this.props.onCloseLimitEditor();
348 this.setState({selectedLimit: NEW_LIMIT_TEMP_ID});
349 this.props.onOpenLimitEditor();
353 export default LicenseKeyGroupsEditorView;