Merge "VLM overview - refactor of edit description input"
[sdc.git] / openecomp-ui / src / sdc-app / onboarding / licenseModel / licenseKeyGroups / LicenseKeyGroupsEditorView.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 from 'react';
17 import i18n from 'nfvo-utils/i18n/i18n.js';
18 import Validator from 'nfvo-utils/Validator.js';
19
20 import Tabs from 'sdc-ui/lib/react/Tabs.js';
21 import Tab from 'sdc-ui/lib/react/Tab.js';
22
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';
33
34 import {DATE_FORMAT} from 'sdc-app/onboarding/OnboardingConstants.js';
35
36 import LicenseKeyGroupsLimits from './LicenseKeyGroupsLimits.js';
37 import {limitType, NEW_LIMIT_TEMP_ID} from '../limits/LimitEditorConstants.js';
38
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
47         }),
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
53 });
54
55 const LicenseKeyGroupFormContent = ({data, onDataChanged, genericFieldInfo, validateName, validateStartDate, thresholdValueValidation}) => {
56         let {name, description, increments, operationalScope, type, thresholdUnits, thresholdValue, startDate, expiryDate} = data;
57         return (
58                 <GridSection>
59                         <GridItem colSpan={2}>
60                                 <Input
61                                         onChange={name => onDataChanged({name}, LKG_FORM_NAME, {name: validateName})}
62                                         label={i18n('Name')}
63                                         data-test-id='create-lkg-name'
64                                         value={name}
65                                         isValid={genericFieldInfo.name.isValid}
66                                         errorText={genericFieldInfo.name.errorText}
67                                         isRequired={true}
68                                         type='text'/>
69                         </GridItem>
70                         <GridItem colSpan={2}>
71                                 <InputOptions
72                                         onInputChange={()=>{}}
73                                         isMultiSelect={true}
74                                         onEnumChange={operationalScope => onDataChanged({operationalScope:{choices: operationalScope, other: ''}},
75                                                 LKG_FORM_NAME)}
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'
80                                         type='select'
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} />
86                         </GridItem>
87                         <GridItem colSpan={2}>
88                                 <Input
89                                         onChange={description => onDataChanged({description}, LKG_FORM_NAME)}
90                                         label={i18n('Description')}
91                                         data-test-id='create-lkg-description'
92                                         value={description}
93                                         isValid={genericFieldInfo.description.isValid}
94                                         errorText={genericFieldInfo.description.errorText}
95                                         type='textarea'
96                                         overlayPos='bottom' />
97                         </GridItem>
98                         <GridItem colSpan={2}>
99                                 <Input
100                                         isRequired={true}
101                                         onChange={e => { const selectedIndex = e.target.selectedIndex;
102                                                 const val = e.target.options[selectedIndex].value;
103                                                 onDataChanged({type: val}, LKG_FORM_NAME);}}
104                                         value={type}
105                                         label={i18n('Type')}
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'
111                                         type='select' >
112                                         {
113                                                 licenseKeyGroupOptionsInputValues.TYPE.map(type =>
114                                                 (<option key={type.enum} value={type.enum}>{type.title}</option>))
115                                         }
116                                 </Input>
117                         </GridItem>
118                         <GridItem>
119                                 <Input
120                                         onChange={e => {
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});}
127
128                                         }
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'
136                                         type='select' >
137                                         {LicenseModelOptionsInputValues.THRESHOLD_UNITS.map(mtype =>
138                                                 <option key={mtype.enum} value={mtype.enum}>{`${mtype.title}`}</option>)}
139                                 </Input>
140                         </GridItem>
141                         <GridItem>
142                                 <Input
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}
151                                         type='text'/>
152                         </GridItem>
153                                 <GridItem>
154                                 <Input
155                                         type='date'
156                                         label={i18n('Start Date')}
157                                         value={startDate}
158                                         dateFormat={DATE_FORMAT}
159                                         startDate={startDate}
160                                         endDate={expiryDate}
161                                         onChange={startDate => onDataChanged(
162                                                 {startDate: startDate ? startDate.format(DATE_FORMAT) : ''},
163                                                 LKG_FORM_NAME,
164                                                 {startDate: validateStartDate}
165                                         )}
166                                         isValid={genericFieldInfo.startDate.isValid}
167                                         errorText={genericFieldInfo.startDate.errorText}
168                                         selectsStart/>
169                         </GridItem>
170                         <GridItem>
171                                 <Input
172                                         type='date'
173                                         label={i18n('Expiry Date')}
174                                         value={expiryDate}
175                                         dateFormat={DATE_FORMAT}
176                                         startDate={startDate}
177                                         endDate={expiryDate}
178                                         onChange={expiryDate => {
179                                                 onDataChanged({expiryDate: expiryDate ? expiryDate.format(DATE_FORMAT) : ''}, LKG_FORM_NAME);
180                                                 onDataChanged({startDate}, LKG_FORM_NAME, {startDate: validateStartDate});
181                                         }}
182                                         isValid={genericFieldInfo.expiryDate.isValid}
183                                         errorText={genericFieldInfo.expiryDate.errorText}
184                                         selectsEnd/>
185                         </GridItem>
186                         <GridItem colSpan={2}>
187                                 <Input
188                                         onChange={increments => onDataChanged({increments}, LKG_FORM_NAME)}
189                                         label={i18n('Increments')}
190                                         value={increments}
191                                         data-test-id='create-ep-increments'
192                                         type='text'/>
193                         </GridItem>
194                 </GridSection>
195         );
196 };
197
198 class LicenseKeyGroupsEditorView extends React.Component {
199         static propTypes = {
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
207         };
208
209         static defaultProps = {
210                 data: {}
211         };
212
213         componentDidUpdate(prevProps) {                         
214                 if (this.props.formReady && this.props.formReady !== prevProps.formReady) { // if form validation succeeded -> continue with submit
215                         this.submit();
216                 }
217         }
218
219         state = {
220                 localFeatureGroupsListFilter: '',
221                 selectedTab: tabIds.GENERAL,
222                 selectedLimit: ''
223         };
224
225         render() {
226                 let {data = {}, onDataChanged, isReadOnlyMode, onCloseLimitEditor, genericFieldInfo, limitsList = []} = this.props;
227                 let {selectedTab} = this.state;
228                 const isTabsDisabled = !data.id || !this.props.isFormValid;
229                 return (
230                         <div className='license-keygroup-editor'>
231                                 <Tabs
232                                         type='menu' 
233                                         activeTab={selectedTab} 
234                                         onTabClick={(tabIndex)=>{
235                                                 if (tabIndex === tabIds.ADD_LIMIT_BUTTON)  {
236                                                         this.onAddLimit();
237                                                 } else {
238                                                         this.setState({selectedTab: tabIndex});
239                                                         onCloseLimitEditor();
240                                                         this.setState({selectedLimit: ''});
241                                                 }
242                                         }} 
243                                         invalidTabs={[]}>
244                                         <Tab tabId={tabIds.GENERAL} data-test-id='general-tab' title={i18n('General')}>
245                                                 { genericFieldInfo &&
246                                                         <Form
247                                                                 ref='validationForm'
248                                                                 hasButtons={false}
249                                                                 isValid={this.props.isFormValid}
250                                                                 formReady={this.props.formReady}
251                                                                 onValidateForm={() => this.props.onValidateForm(LKG_FORM_NAME) }
252                                                                 labledButtons={true}
253                                                                 isReadOnlyMode={isReadOnlyMode}
254                                                                 className='license-model-form license-key-groups-form'>
255                                                                         <LicenseKeyGroupFormContent
256                                                                                 data={data}
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)}/>
262                                                         </Form>}
263
264                                         </Tab>
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} />}
274                                         </Tab>
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} />}
284                                         </Tab>
285                                         {selectedTab !== tabIds.GENERAL ? 
286                                                         <Button
287                                                                 className='add-limit-button'
288                                                                 tabId={tabIds.ADD_LIMIT_BUTTON}
289                                                                 btnType='link'
290                                                                 iconName='plus'
291                                                                 disabled={this.state.selectedLimit || isReadOnlyMode}>
292                                                                 {i18n('Add Limit')}
293                                                         </Button>
294                                                 :
295                                                 <div></div> // Render empty div to not break tabs
296                                         }
297                                 </Tabs>
298                                 
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'>
302                                                         {i18n('Save')}
303                                                 </Button>
304                                         }
305                                         <Button btnType={this.state.selectedLimit ? 'default' : 'outline'} onClick={() => this.props.onCancel()} type='reset'>
306                                                 {i18n('Cancel')}
307                                         </Button>
308                                 </GridSection>
309                         </div>
310
311                 );
312         }
313
314         submit() {
315                 const {data: licenseKeyGroup, previousData: previousLicenseKeyGroup, formReady, onValidateForm, onSubmit} = this.props;
316                 if (!formReady) {
317                         onValidateForm(LKG_FORM_NAME);
318                 } else {
319                         onSubmit({licenseKeyGroup, previousLicenseKeyGroup});
320                 }
321         }
322
323         validateName(value) {
324                 const {data: {id}, LKGNames} = this.props;
325                 const isExists = Validator.isItemNameAlreadyExistsInList({itemId: id, itemName: value, list: LKGNames});
326
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')};
329         }
330
331         onSelectLimit(limit) {
332                 if (limit.id === this.state.selectedLimit) {
333                         this.setState({selectedLimit: ''});
334                         return;
335                 }
336                 this.setState({selectedLimit: limit.id});
337                 this.props.onOpenLimitEditor(limit);
338         }
339
340         onCloseLimitEditor() {
341                 this.setState({selectedLimit: ''});
342                 this.props.onCloseLimitEditor();
343         }
344
345         onAddLimit() {
346                 this.setState({selectedLimit: NEW_LIMIT_TEMP_ID});
347                 this.props.onOpenLimitEditor();
348         }
349 }
350
351 export default LicenseKeyGroupsEditorView;