blob: f3279b0b6db94f5cfdf47055bfb7c7b47759785b [file] [log] [blame]
svishnevb72a4b42018-05-24 15:52:14 +03001/*
2 * Copyright © 2016-2018 European Support Limited
AviZi280f8012017-06-09 02:39:56 +03003 *
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
Einav Weiss Keidar1801b242018-08-13 16:19:46 +03007 *
svishnevb72a4b42018-05-24 15:52:14 +03008 * http://www.apache.org/licenses/LICENSE-2.0
Einav Weiss Keidar1801b242018-08-13 16:19:46 +03009 *
AviZi280f8012017-06-09 02:39:56 +030010 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
svishnevb72a4b42018-05-24 15:52:14 +030012 * 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.
AviZi280f8012017-06-09 02:39:56 +030015 */
16import React from 'react';
17import ReactDOM from 'react-dom';
18import classNames from 'classnames';
19import Checkbox from 'react-bootstrap/lib/Checkbox.js';
talig8e9c0652017-12-20 14:30:43 +020020import Radio from 'sdc-ui/lib/react/Radio.js';
AviZi280f8012017-06-09 02:39:56 +030021import FormGroup from 'react-bootstrap/lib/FormGroup.js';
22import FormControl from 'react-bootstrap/lib/FormControl.js';
23import Overlay from 'react-bootstrap/lib/Overlay.js';
24import Tooltip from 'react-bootstrap/lib/Tooltip.js';
Avi Zivb8e2faf2017-07-18 19:45:38 +030025import Datepicker from 'nfvo-components/datepicker/Datepicker.jsx';
AviZi280f8012017-06-09 02:39:56 +030026
27class Input extends React.Component {
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +020028 state = {
29 value: this.props.value,
30 checked: this.props.checked,
31 selectedValues: []
32 };
AviZi280f8012017-06-09 02:39:56 +030033
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +020034 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 />
93 )}
94 {type === 'number' && (
95 <FormControl
96 bsClass={'form-control input-options-other'}
97 onChange={e => this.onChange(e)}
98 disabled={isReadOnlyMode || Boolean(disabled)}
99 onBlur={onBlur}
100 onKeyDown={onKeyDown}
101 value={value !== undefined ? value : ''}
102 inputRef={input => (this.input = input)}
103 type={type}
104 data-test-id={this.props['data-test-id']}
105 />
106 )}
AviZi280f8012017-06-09 02:39:56 +0300107
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200108 {type === 'textarea' && (
109 <FormControl
110 className="form-control input-options-other"
111 disabled={isReadOnlyMode || Boolean(disabled)}
112 value={value || ''}
113 onBlur={onBlur}
114 onKeyDown={onKeyDown}
115 componentClass={type}
116 onChange={e => this.onChange(e)}
117 inputRef={input => (this.input = input)}
118 data-test-id={this.props['data-test-id']}
119 />
120 )}
AviZi280f8012017-06-09 02:39:56 +0300121
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200122 {type === 'checkbox' && (
123 <Checkbox
124 className={classNames({
125 required: isRequired,
126 'has-error': !isValid
127 })}
128 onChange={e => this.onChangeCheckBox(e)}
129 disabled={isReadOnlyMode || Boolean(disabled)}
130 checked={checked}
131 data-test-id={this.props['data-test-id']}>
132 {label}
133 </Checkbox>
134 )}
AviZi280f8012017-06-09 02:39:56 +0300135
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200136 {type === 'radio' && (
137 <Radio
138 name={name}
139 checked={checked}
140 disabled={isReadOnlyMode || Boolean(disabled)}
141 value={value}
142 onChange={isChecked =>
143 this.onChangeRadio(isChecked)
144 }
145 inputRef={input => (this.input = input)}
146 label={label}
147 data-test-id={this.props['data-test-id']}
148 />
149 )}
150 {type === 'select' && (
151 <FormControl
152 onClick={e => this.optionSelect(e)}
153 className="custom-select"
154 componentClass={type}
155 inputRef={input => (this.input = input)}
156 name={name}
157 {...inputProps}
158 data-test-id={this.props['data-test-id']}
159 />
160 )}
161 {type === 'date' && (
162 <Datepicker
163 date={value}
164 format={dateFormat}
165 startDate={startDate}
166 endDate={endDate}
167 inputRef={input => (this.input = input)}
168 onChange={this.props.onChange}
169 disabled={isReadOnlyMode || Boolean(disabled)}
170 data-test-id={this.props['data-test-id']}
171 selectsStart={selectsStart}
172 selectsEnd={selectsEnd}
173 />
174 )}
175 </FormGroup>
176 {this.renderErrorOverlay()}
177 </div>
178 );
179 }
AviZi280f8012017-06-09 02:39:56 +0300180
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200181 getValue() {
182 return this.props.type !== 'select'
183 ? this.state.value
184 : this.state.selectedValues;
185 }
AviZi280f8012017-06-09 02:39:56 +0300186
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200187 getChecked() {
188 return this.state.checked;
189 }
AviZi280f8012017-06-09 02:39:56 +0300190
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200191 optionSelect(e) {
192 let selectedValues = [];
193 if (e.target.value) {
194 selectedValues.push(e.target.value);
195 }
196 this.setState({
197 selectedValues
198 });
199 }
Einav Weiss Keidar1801b242018-08-13 16:19:46 +0300200
201 static getDerivedStateFromProps(props, state) {
202 if (state.value === props.value) {
203 return null;
204 } else {
205 return { value: props.value, ...state };
206 }
svishnevb72a4b42018-05-24 15:52:14 +0300207 }
Einav Weiss Keidar1801b242018-08-13 16:19:46 +0300208
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200209 onChange(e) {
210 const { onChange, type } = this.props;
211 let value = e.target.value;
212 if (type === 'number') {
213 if (value === '') {
214 value = undefined;
215 } else {
216 value = Number(value);
217 }
218 }
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200219 onChange(value);
220 }
AviZi280f8012017-06-09 02:39:56 +0300221
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200222 onChangeCheckBox(e) {
223 let { onChange } = this.props;
224 let checked = e.target.checked;
225 this.setState({
226 checked
227 });
228 onChange(checked);
229 }
AviZi280f8012017-06-09 02:39:56 +0300230
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200231 onChangeRadio(isChecked) {
232 let { onChange } = this.props;
233 this.setState({
234 checked: isChecked
235 });
236 onChange(this.state.value);
237 }
AviZi280f8012017-06-09 02:39:56 +0300238
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200239 focus() {
240 ReactDOM.findDOMNode(this.input).focus();
241 }
AviZi280f8012017-06-09 02:39:56 +0300242
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200243 renderErrorOverlay() {
244 let position = 'right';
245 const { errorText = '', isValid = true, type, overlayPos } = this.props;
AviZi280f8012017-06-09 02:39:56 +0300246
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200247 if (overlayPos) {
248 position = overlayPos;
249 } else if (
250 type === 'text' ||
251 type === 'email' ||
252 type === 'number' ||
253 type === 'radio' ||
254 type === 'password' ||
255 type === 'date'
256 ) {
257 position = 'bottom';
258 }
AviZi280f8012017-06-09 02:39:56 +0300259
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200260 return (
261 <Overlay
262 show={!isValid}
263 placement={position}
264 target={() => {
265 let target = ReactDOM.findDOMNode(this.input);
266 return target.offsetParent ? target : undefined;
267 }}
268 container={this}>
269 <Tooltip
270 id={`error-${errorText.replace(' ', '-')}`}
271 className="validation-error-message">
272 {errorText}
273 </Tooltip>
274 </Overlay>
275 );
276 }
AviZi280f8012017-06-09 02:39:56 +0300277}
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200278export default Input;