16a0abc5fd6f9b0de0f4aba449fa31628e138a51
[sdc.git] / openecomp-ui / src / nfvo-components / input / validation / Input.jsx
1 /*
2  * Copyright © 2016-2018 European Support Limited
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 or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 import React from 'react';
17 import ReactDOM from 'react-dom';
18 import classNames from 'classnames';
19 import Checkbox from 'react-bootstrap/lib/Checkbox.js';
20 import { Radio } from 'onap-ui-react';
21 import FormGroup from 'react-bootstrap/lib/FormGroup.js';
22 import FormControl from 'react-bootstrap/lib/FormControl.js';
23 import Overlay from 'react-bootstrap/lib/Overlay.js';
24 import Tooltip from 'react-bootstrap/lib/Tooltip.js';
25 import Datepicker from 'nfvo-components/datepicker/Datepicker.jsx';
26
27 class Input extends React.Component {
28     state = {
29         value: this.props.value,
30         checked: this.props.checked,
31         selectedValues: []
32     };
33
34     render() {
35         /* eslint-disable no-unused-vars */
36         const {
37             label,
38             isReadOnlyMode,
39             value,
40             onBlur,
41             onKeyDown,
42             type,
43             disabled,
44             checked,
45             name
46         } = this.props;
47         const {
48             groupClassName,
49             isValid = true,
50             errorText,
51             isRequired,
52             overlayPos,
53             ...inputProps
54         } = this.props;
55         const {
56             dateFormat,
57             startDate,
58             endDate,
59             selectsStart,
60             selectsEnd
61         } = this.props; // Date Props
62         /* eslint-enable no-unused-vars */
63         let wrapperClassName =
64             type !== 'radio'
65                 ? 'validation-input-wrapper'
66                 : 'validation-radio-wrapper';
67         if (disabled) {
68             wrapperClassName += ' disabled';
69         }
70         return (
71             <div className={wrapperClassName}>
72                 <FormGroup
73                     className={classNames('form-group', [groupClassName], {
74                         required: isRequired,
75                         'has-error': !isValid
76                     })}>
77                     {label &&
78                         (type !== 'checkbox' && type !== 'radio') && (
79                             <label className="control-label">{label}</label>
80                         )}
81                     {type === 'text' && (
82                         <FormControl
83                             bsClass={'form-control input-options-other'}
84                             onChange={e => this.onChange(e)}
85                             disabled={isReadOnlyMode || Boolean(disabled)}
86                             onBlur={onBlur}
87                             onKeyDown={onKeyDown}
88                             value={value || ''}
89                             inputRef={input => (this.input = input)}
90                             type={type}
91                             data-test-id={this.props['data-test-id']}
92                             placeholder={this.props.placeholder || ''}
93                         />
94                     )}
95                     {type === 'number' && (
96                         <FormControl
97                             bsClass={'form-control input-options-other'}
98                             onChange={e => this.onChange(e)}
99                             disabled={isReadOnlyMode || Boolean(disabled)}
100                             onBlur={onBlur}
101                             onKeyDown={onKeyDown}
102                             value={value !== undefined ? value : ''}
103                             inputRef={input => (this.input = input)}
104                             type={type}
105                             data-test-id={this.props['data-test-id']}
106                         />
107                     )}
108
109                     {type === 'textarea' && (
110                         <FormControl
111                             className="form-control input-options-other"
112                             disabled={isReadOnlyMode || Boolean(disabled)}
113                             value={value || ''}
114                             onBlur={onBlur}
115                             onKeyDown={onKeyDown}
116                             componentClass={type}
117                             onChange={e => this.onChange(e)}
118                             inputRef={input => (this.input = input)}
119                             data-test-id={this.props['data-test-id']}
120                         />
121                     )}
122
123                     {type === 'checkbox' && (
124                         <Checkbox
125                             className={classNames({
126                                 required: isRequired,
127                                 'has-error': !isValid
128                             })}
129                             onChange={e => this.onChangeCheckBox(e)}
130                             disabled={isReadOnlyMode || Boolean(disabled)}
131                             checked={checked}
132                             data-test-id={this.props['data-test-id']}>
133                             {label}
134                         </Checkbox>
135                     )}
136
137                     {type === 'radio' && (
138                         <Radio
139                             name={name}
140                             checked={checked}
141                             disabled={isReadOnlyMode || Boolean(disabled)}
142                             value={value}
143                             onChange={isChecked =>
144                                 this.onChangeRadio(isChecked)
145                             }
146                             inputRef={input => (this.input = input)}
147                             label={label}
148                             data-test-id={this.props['data-test-id']}
149                         />
150                     )}
151                     {type === 'select' && (
152                         <FormControl
153                             onClick={e => this.optionSelect(e)}
154                             className="custom-select"
155                             componentClass={type}
156                             inputRef={input => (this.input = input)}
157                             name={name}
158                             {...inputProps}
159                             data-test-id={this.props['data-test-id']}
160                         />
161                     )}
162                     {type === 'date' && (
163                         <Datepicker
164                             date={value}
165                             format={dateFormat}
166                             startDate={startDate}
167                             endDate={endDate}
168                             inputRef={input => (this.input = input)}
169                             onChange={this.props.onChange}
170                             disabled={isReadOnlyMode || Boolean(disabled)}
171                             data-test-id={this.props['data-test-id']}
172                             selectsStart={selectsStart}
173                             selectsEnd={selectsEnd}
174                         />
175                     )}
176                 </FormGroup>
177                 {this.renderErrorOverlay()}
178             </div>
179         );
180     }
181
182     getValue() {
183         return this.props.type !== 'select'
184             ? this.state.value
185             : this.state.selectedValues;
186     }
187
188     getChecked() {
189         return this.state.checked;
190     }
191
192     optionSelect(e) {
193         let selectedValues = [];
194         if (e.target.value) {
195             selectedValues.push(e.target.value);
196         }
197         this.setState({
198             selectedValues
199         });
200     }
201
202     static getDerivedStateFromProps(props, state) {
203         if (state.value === props.value) {
204             return null;
205         } else {
206             return { value: props.value, ...state };
207         }
208     }
209
210     onChange(e) {
211         const { onChange, type } = this.props;
212         let value = e.target.value;
213         if (type === 'number') {
214             if (value === '') {
215                 value = undefined;
216             } else {
217                 value = Number(value);
218             }
219         }
220         onChange(value);
221     }
222
223     onChangeCheckBox(e) {
224         let { onChange } = this.props;
225         let checked = e.target.checked;
226         this.setState({
227             checked
228         });
229         onChange(checked);
230     }
231
232     onChangeRadio(isChecked) {
233         let { onChange } = this.props;
234         this.setState({
235             checked: isChecked
236         });
237         onChange(this.state.value);
238     }
239
240     focus() {
241         ReactDOM.findDOMNode(this.input).focus();
242     }
243
244     renderErrorOverlay() {
245         let position = 'right';
246         const { errorText = '', isValid = true, type, overlayPos } = this.props;
247
248         if (overlayPos) {
249             position = overlayPos;
250         } else if (
251             type === 'text' ||
252             type === 'email' ||
253             type === 'number' ||
254             type === 'radio' ||
255             type === 'password' ||
256             type === 'date'
257         ) {
258             position = 'bottom';
259         }
260
261         return (
262             <Overlay
263                 show={!isValid}
264                 placement={position}
265                 target={() => {
266                     let target = ReactDOM.findDOMNode(this.input);
267                     return target.offsetParent ? target : undefined;
268                 }}
269                 container={this}>
270                 <Tooltip
271                     id={`error-${errorText.replace(' ', '-')}`}
272                     className="validation-error-message">
273                     {errorText}
274                 </Tooltip>
275             </Overlay>
276         );
277     }
278 }
279 export default Input;