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