blob: c54d4b660fd4a2643d56be226ccf8b9bf89a8d5b [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
svishnevb72a4b42018-05-24 15:52:14 +03007 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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 }
svishnevb72a4b42018-05-24 15:52:14 +0300200 componentWillReceiveProps(nextProps) {
201 this.setState({
202 value: nextProps.value
203 });
204 }
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200205 onChange(e) {
206 const { onChange, type } = this.props;
207 let value = e.target.value;
208 if (type === 'number') {
209 if (value === '') {
210 value = undefined;
211 } else {
212 value = Number(value);
213 }
214 }
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200215 onChange(value);
216 }
AviZi280f8012017-06-09 02:39:56 +0300217
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200218 onChangeCheckBox(e) {
219 let { onChange } = this.props;
220 let checked = e.target.checked;
221 this.setState({
222 checked
223 });
224 onChange(checked);
225 }
AviZi280f8012017-06-09 02:39:56 +0300226
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200227 onChangeRadio(isChecked) {
228 let { onChange } = this.props;
229 this.setState({
230 checked: isChecked
231 });
232 onChange(this.state.value);
233 }
AviZi280f8012017-06-09 02:39:56 +0300234
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200235 focus() {
236 ReactDOM.findDOMNode(this.input).focus();
237 }
AviZi280f8012017-06-09 02:39:56 +0300238
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200239 renderErrorOverlay() {
240 let position = 'right';
241 const { errorText = '', isValid = true, type, overlayPos } = this.props;
AviZi280f8012017-06-09 02:39:56 +0300242
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200243 if (overlayPos) {
244 position = overlayPos;
245 } else if (
246 type === 'text' ||
247 type === 'email' ||
248 type === 'number' ||
249 type === 'radio' ||
250 type === 'password' ||
251 type === 'date'
252 ) {
253 position = 'bottom';
254 }
AviZi280f8012017-06-09 02:39:56 +0300255
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200256 return (
257 <Overlay
258 show={!isValid}
259 placement={position}
260 target={() => {
261 let target = ReactDOM.findDOMNode(this.input);
262 return target.offsetParent ? target : undefined;
263 }}
264 container={this}>
265 <Tooltip
266 id={`error-${errorText.replace(' ', '-')}`}
267 className="validation-error-message">
268 {errorText}
269 </Tooltip>
270 </Overlay>
271 );
272 }
AviZi280f8012017-06-09 02:39:56 +0300273}
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200274export default Input;