[SDC] Onboarding 1710 rebase.
[sdc.git] / openecomp-ui / src / sdc-app / onboarding / licenseModel / entitlementPools / EntitlementPoolsEditorView.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
18 import i18n from 'nfvo-utils/i18n/i18n.js';
19 import Validator from 'nfvo-utils/Validator.js';
20
21 import Input from 'nfvo-components/input/validation/Input.jsx';
22 import InputOptions from 'nfvo-components/input/validation/InputOptions.jsx';
23 import Form from 'nfvo-components/input/validation/Form.jsx';
24 import GridSection from 'nfvo-components/grid/GridSection.jsx';
25 import GridItem from 'nfvo-components/grid/GridItem.jsx';
26 import {optionsInputValues as  EntitlementPoolsOptionsInputValues, thresholdUnitType, SP_ENTITLEMENT_POOL_FORM, EP_TIME_FORMAT}  from  './EntitlementPoolsConstants.js';
27 import {other as optionInputOther} from 'nfvo-components/input/inputOptions/InputOptions.jsx';
28
29 const EntitlementPoolPropType = React.PropTypes.shape({
30         id: React.PropTypes.string,
31         name: React.PropTypes.string,
32         description: React.PropTypes.string,
33         manufacturerReferenceNumber: React.PropTypes.string,
34         operationalScope: React.PropTypes.shape({
35                 choices: React.PropTypes.array,
36                 other: React.PropTypes.string
37         }),
38         aggregationFunction: React.PropTypes.shape({
39                 choice: React.PropTypes.string,
40                 other: React.PropTypes.string
41         }),
42         increments: React.PropTypes.string,
43         time: React.PropTypes.shape({
44                 choice: React.PropTypes.string,
45                 other: React.PropTypes.string
46         }),
47         entitlementMetric: React.PropTypes.shape({
48                 choice: React.PropTypes.string,
49                 other: React.PropTypes.string
50         })
51 });
52
53 const EntitlementPoolsFormContent = ({data, genericFieldInfo, onDataChanged, validateName, validateChoiceWithOther, validateTimeOtherValue,
54          thresholdValueValidation, validateStartDate}) => {
55         let {
56                 name, description, manufacturerReferenceNumber, operationalScope , aggregationFunction,  thresholdUnits, thresholdValue,
57                 increments, time, entitlementMetric, startDate, expiryDate} = data;
58
59         return (
60                 <GridSection>
61                         <GridItem colSpan={2}>
62                                 <Input
63                                         onChange={name => onDataChanged({name}, SP_ENTITLEMENT_POOL_FORM, {name: validateName})}
64                                         isValid={genericFieldInfo.name.isValid}
65                                         isRequired={true}
66                                         errorText={genericFieldInfo.name.errorText}
67                                         label={i18n('Name')}
68                                         value={name}
69                                         data-test-id='create-ep-name'
70                                         type='text'/>
71                         </GridItem>
72                         <GridItem colSpan={2}>
73                                 <InputOptions
74                                         onInputChange={()=>{}}
75                                         isMultiSelect={true}
76
77                                         isRequired={true}
78                                         onEnumChange={operationalScope => onDataChanged({operationalScope:{choices: operationalScope, other: ''}},
79                                                 SP_ENTITLEMENT_POOL_FORM, {operationalScope: validateChoiceWithOther})}
80                                         onOtherChange={operationalScope => onDataChanged({operationalScope:{choices: [optionInputOther.OTHER],
81                                                 other: operationalScope}}, SP_ENTITLEMENT_POOL_FORM, {operationalScope: validateChoiceWithOther})}
82                                         label={i18n('Operational Scope')}
83                                         data-test-id='create-ep-operational-scope'
84                                         type='select'
85                                         multiSelectedEnum={operationalScope && operationalScope.choices}
86                                         otherValue={operationalScope && operationalScope.other}
87                                         values={EntitlementPoolsOptionsInputValues.OPERATIONAL_SCOPE}
88                                         isValid={genericFieldInfo.operationalScope.isValid}
89                                         errorText={genericFieldInfo.operationalScope.errorText} />
90                         </GridItem>
91                         <GridItem colSpan={2} stretch>
92                                 <Input
93                                         onChange={description => onDataChanged({description}, SP_ENTITLEMENT_POOL_FORM)}
94                                         isValid={genericFieldInfo.description.isValid}
95                                         errorText={genericFieldInfo.description.errorText}
96                                         label={i18n('Description')}
97                                         value={description}
98                                         isRequired={true}
99                                         data-test-id='create-ep-description'
100                                         type='textarea'/>
101                         </GridItem>
102                         <GridItem colSpan={2}>
103                                 <div className='threshold-section'>
104                                         <Input
105                                                 isRequired={true}
106                                                 onChange={e => {
107                                                         // setting the unit to the correct value
108                                                         const selectedIndex = e.target.selectedIndex;
109                                                         const val = e.target.options[selectedIndex].value;
110                                                         onDataChanged({thresholdUnits: val}, SP_ENTITLEMENT_POOL_FORM);
111                                                         // TODO make sure that the value is valid too
112                                                         onDataChanged({thresholdValue: thresholdValue}, SP_ENTITLEMENT_POOL_FORM,{thresholdValue : thresholdValueValidation});}
113
114                                                 }
115                                                 value={thresholdUnits}
116                                                 label={i18n('Threshold Units')}
117                                                 data-test-id='create-ep-threshold-units'
118                                                 isValid={genericFieldInfo.thresholdUnits.isValid}
119                                                 errorText={genericFieldInfo.thresholdUnits.errorText}
120                                                 groupClassName='bootstrap-input-options'
121                                                 className='input-options-select'
122                                                 type='select' >
123                                                 {EntitlementPoolsOptionsInputValues.THRESHOLD_UNITS.map(mtype =>
124                                                         <option key={mtype.enum} value={mtype.enum}>{`${mtype.title}`}</option>)}
125                                         </Input>
126
127                                         <Input
128                                                 className='entitlement-pools-form-row-threshold-value'
129                                                 onChange={thresholdValue => onDataChanged({thresholdValue}, SP_ENTITLEMENT_POOL_FORM,
130                                                         {thresholdValue : thresholdValueValidation})}
131                                                 label={i18n('Threshold Value')}
132                                                 isValid={genericFieldInfo.thresholdValue.isValid}
133                                                 errorText={genericFieldInfo.thresholdValue.errorText}
134                                                 data-test-id='create-ep-threshold-value'
135                                                 value={thresholdValue}
136                                                 isRequired={true}
137                                                 type='text'/>
138                                 </div>
139                                 <InputOptions
140                                         onInputChange={()=>{}}
141                                         isMultiSelect={false}
142                                         isRequired={true}
143                                         onEnumChange={entitlementMetric => onDataChanged({entitlementMetric:{choice: entitlementMetric, other: ''}},
144                                                 SP_ENTITLEMENT_POOL_FORM, {entitlementMetric: validateChoiceWithOther})}
145                                         onOtherChange={entitlementMetric => onDataChanged({entitlementMetric:{choice: optionInputOther.OTHER,
146                                                 other: entitlementMetric}}, SP_ENTITLEMENT_POOL_FORM, {entitlementMetric: validateChoiceWithOther})}
147                                         label={i18n('Entitlement Metric')}
148                                         data-test-id='create-ep-entitlement-metric'
149                                         type='select'
150                                         required={true}
151                                         selectedEnum={entitlementMetric && entitlementMetric.choice}
152                                         otherValue={entitlementMetric && entitlementMetric.other}
153                                         values={EntitlementPoolsOptionsInputValues.ENTITLEMENT_METRIC}
154                                         isValid={genericFieldInfo.entitlementMetric.isValid}
155                                         errorText={genericFieldInfo.entitlementMetric.errorText} />
156                                 <InputOptions
157                                         onInputChange={()=>{}}
158                                         isMultiSelect={false}
159                                         isRequired={true}
160                                         onEnumChange={aggregationFunction => onDataChanged({aggregationFunction:{choice: aggregationFunction, other: ''}},
161                                                 SP_ENTITLEMENT_POOL_FORM, {aggregationFunction: validateChoiceWithOther})}
162                                         onOtherChange={aggregationFunction => onDataChanged({aggregationFunction:{choice: optionInputOther.OTHER,
163                                                 other: aggregationFunction}}, SP_ENTITLEMENT_POOL_FORM, {aggregationFunction: validateChoiceWithOther})}
164                                         label={i18n('Aggregate Function')}
165                                         data-test-id='create-ep-aggregate-function'
166                                         type='select'
167                                         required={true}
168                                         selectedEnum={aggregationFunction && aggregationFunction.choice}
169                                         otherValue={aggregationFunction && aggregationFunction.other}
170                                         values={EntitlementPoolsOptionsInputValues.AGGREGATE_FUNCTION}
171                                         isValid={genericFieldInfo.aggregationFunction.isValid}
172                                         errorText={genericFieldInfo.aggregationFunction.errorText} />
173                         </GridItem>
174                         <GridItem colSpan={2}>
175                                 <Input
176                                         onChange={manufacturerReferenceNumber => onDataChanged({manufacturerReferenceNumber}, SP_ENTITLEMENT_POOL_FORM)}
177                                         label={i18n('Manufacturer Reference Number')}
178                                         value={manufacturerReferenceNumber}
179                                         isValid={genericFieldInfo.manufacturerReferenceNumber.isValid}
180                                         errorText={genericFieldInfo.manufacturerReferenceNumber.errorText}
181                                         isRequired={true}
182                                         data-test-id='create-ep-reference-number'
183                                         type='text'/>
184                         </GridItem>
185                         <GridItem colSpan={2}>
186                                 <InputOptions
187                                         onInputChange={()=>{}}
188                                         isMultiSelect={false}
189                                         isRequired={true}
190                                         onEnumChange={time => onDataChanged({time:{choice: time, other: ''}},
191                                                 SP_ENTITLEMENT_POOL_FORM, {time: validateChoiceWithOther})}
192                                         onOtherChange={time => onDataChanged({time:{choice: optionInputOther.OTHER,
193                                                 other: time}}, SP_ENTITLEMENT_POOL_FORM, {time: validateTimeOtherValue})}
194                                         label={i18n('Time')}
195                                         data-test-id='create-ep-time'
196                                         type='select'
197                                         required={true}
198                                         selectedEnum={time && time.choice}
199                                         otherValue={time && time.other}
200                                         values={EntitlementPoolsOptionsInputValues.TIME}
201                                         isValid={genericFieldInfo.time.isValid}
202                                         errorText={genericFieldInfo.time.errorText} />
203                         </GridItem>
204                         <GridItem colSpan={2}>
205                                 <Input
206                                         onChange={increments => onDataChanged({increments}, SP_ENTITLEMENT_POOL_FORM)}
207                                         label={i18n('Increments')}
208                                         value={increments}
209                                         data-test-id='create-ep-increments'
210                                         type='text'/>
211                         </GridItem>
212                         <GridItem colSpan={2} />
213                         <GridItem colSpan={2}>
214                                 <Input
215                                         type='date'
216                                         label={i18n('Start Date')} 
217                                         value={startDate}
218                                         dateFormat={EP_TIME_FORMAT}
219                                         startDate={startDate}
220                                         endDate={expiryDate}
221                                         onChange={startDate => onDataChanged(
222                                                 {startDate: startDate ? startDate.format(EP_TIME_FORMAT) : ''}, 
223                                                 SP_ENTITLEMENT_POOL_FORM,
224                                                 {startDate: validateStartDate}
225                                         )}
226                                         isValid={genericFieldInfo.startDate.isValid}
227                                         errorText={genericFieldInfo.startDate.errorText}
228                                         selectsStart/>
229                         </GridItem>
230                         <GridItem colSpan={2}>
231                                 <Input
232                                         type='date' 
233                                         label={i18n('Expiry Date')} 
234                                         value={expiryDate}
235                                         dateFormat={EP_TIME_FORMAT}
236                                         startDate={startDate}
237                                         endDate={expiryDate}
238                                         onChange={expiryDate => {
239                                                 onDataChanged({expiryDate: expiryDate ? expiryDate.format(EP_TIME_FORMAT) : ''}, SP_ENTITLEMENT_POOL_FORM);
240                                                 onDataChanged({startDate}, SP_ENTITLEMENT_POOL_FORM, {startDate: validateStartDate});
241                                         }}
242                                         isValid={genericFieldInfo.expiryDate.isValid}
243                                         errorText={genericFieldInfo.expiryDate.errorText}
244                                         selectsEnd/>
245                         </GridItem>
246                 </GridSection>
247         );
248 };
249
250 class EntitlementPoolsEditorView extends React.Component {
251
252         static propTypes = {
253                 data: EntitlementPoolPropType,
254                 previousData: EntitlementPoolPropType,
255                 EPNames: React.PropTypes.object,
256                 isReadOnlyMode: React.PropTypes.bool,
257                 onDataChanged: React.PropTypes.func.isRequired,
258                 onSubmit: React.PropTypes.func.isRequired,
259                 onCancel: React.PropTypes.func.isRequired
260         };
261
262         static defaultProps = {
263                 data: {}
264         };
265
266         render() {
267                 let {data = {}, onDataChanged, isReadOnlyMode, genericFieldInfo} = this.props;
268
269
270                 return (
271                         <div>
272                                 {
273                                         genericFieldInfo && <Form
274                                                 ref='validationForm'
275                                                 hasButtons={true}
276                                                 onSubmit={ () => this.submit() }
277                                                 onReset={ () => this.props.onCancel() }
278                                                 labledButtons={true}
279                                                 isReadOnlyMode={isReadOnlyMode}
280                                                 isValid={this.props.isFormValid}
281                                                 formReady={this.props.formReady}
282                                                 onValidateForm={() => this.props.onValidateForm(SP_ENTITLEMENT_POOL_FORM) }
283                                                 className='entitlement-pools-form'>
284                                                 <EntitlementPoolsFormContent
285                                                         data={data}
286                                                         genericFieldInfo={genericFieldInfo}
287                                                         onDataChanged={onDataChanged}
288                                                         validateName={(value)=> this.validateName(value)}
289                                                         validateTimeOtherValue ={(value)=> this.validateTimeOtherValue(value)}
290                                                         validateChoiceWithOther={(value)=> this.validateChoiceWithOther(value)}
291                                                         validateStartDate={(value, state)=> this.validateStartDate(value, state)}
292                                                         thresholdValueValidation={(value, state)=> this.thresholdValueValidation(value, state)}/>
293                                         </Form>
294                                 }
295                         </div>
296                 );
297         }
298
299         submit() {
300                 const {data: entitlementPool, previousData: previousEntitlementPool} = this.props;
301                 this.props.onSubmit({entitlementPool, previousEntitlementPool});
302         }
303
304         validateName(value) {
305                 const {data: {id}, EPNames} = this.props;
306                 const isExists = Validator.isItemNameAlreadyExistsInList({itemId: id, itemName: value, list: EPNames});
307
308                 return !isExists ?  {isValid: true, errorText: ''} :
309                 {isValid: false, errorText: i18n('Entitlement pool by the name \'' + value + '\' already exists. Entitlement pool name must be unique')};
310         }
311
312         validateStartDate(value, state) {
313                 if (state.data.expiryDate) {
314                         if (!value) {
315                                 return {isValid: false, errorText: i18n('Start date has to be specified if expiry date is specified')};
316                         }
317                 }
318                 return {isValid: true, errorText: ''};
319         }
320
321         validateTimeOtherValue(value) {
322                 return Validator.validate('time', value.other, [{type: 'required', data: true}, {type: 'numeric', data: true}]);
323         }
324
325         validateChoiceWithOther(value) {
326                 let chosen = value.choice;
327                 // if we have an empty multiple select we have a problem since it's required
328                 if (value.choices) {
329                         if (value.choices.length === 0) {
330                                 return  Validator.validate('field', '', [{type: 'required', data: true}]);
331                         } else {
332                                 // continuing validation with the first chosen value in case we have the 'Other' field
333                                 chosen = value.choices[0];
334                         }
335                 }
336                 if (chosen !== optionInputOther.OTHER) {
337                         return  Validator.validate('field', chosen, [{type: 'required', data: true}]);
338                 } else { // when 'Other' was chosen, validate other value
339                         return  Validator.validate('field', value.other, [{type: 'required', data: true}]);
340                 }
341         }
342
343         thresholdValueValidation(value, state) {
344
345                 let  unit = state.data.thresholdUnits;
346                 if (unit === thresholdUnitType.PERCENTAGE) {
347                         return Validator.validate('thresholdValue', value, [
348                                 {type: 'required', data: true},
349                                 {type: 'numeric', data: true},
350                                 {type: 'maximum', data: 100},
351                                 {type: 'minimum', data: 0}]);
352                 } else {
353                         return Validator.validate('thresholdValue', value, [
354                                 {type: 'numeric', data: true},
355                                 {type: 'required', data: true}]);
356                 }
357         }
358
359 }
360
361 export default EntitlementPoolsEditorView;