blob: b27ba1db3be5298089300513139a83e416ca5f0e [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']}
Vodafone804ec682019-03-18 15:46:53 +053092 placeholder={this.props.placeholder || ''}
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +020093 />
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 )}
AviZi280f8012017-06-09 02:39:56 +0300108
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200109 {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 )}
AviZi280f8012017-06-09 02:39:56 +0300122
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200123 {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 )}
AviZi280f8012017-06-09 02:39:56 +0300136
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200137 {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 }
AviZi280f8012017-06-09 02:39:56 +0300181
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200182 getValue() {
183 return this.props.type !== 'select'
184 ? this.state.value
185 : this.state.selectedValues;
186 }
AviZi280f8012017-06-09 02:39:56 +0300187
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200188 getChecked() {
189 return this.state.checked;
190 }
AviZi280f8012017-06-09 02:39:56 +0300191
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200192 optionSelect(e) {
193 let selectedValues = [];
194 if (e.target.value) {
195 selectedValues.push(e.target.value);
196 }
197 this.setState({
198 selectedValues
199 });
200 }
Einav Weiss Keidar1801b242018-08-13 16:19:46 +0300201
202 static getDerivedStateFromProps(props, state) {
203 if (state.value === props.value) {
204 return null;
205 } else {
206 return { value: props.value, ...state };
207 }
svishnevb72a4b42018-05-24 15:52:14 +0300208 }
Einav Weiss Keidar1801b242018-08-13 16:19:46 +0300209
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200210 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 }
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200220 onChange(value);
221 }
AviZi280f8012017-06-09 02:39:56 +0300222
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200223 onChangeCheckBox(e) {
224 let { onChange } = this.props;
225 let checked = e.target.checked;
226 this.setState({
227 checked
228 });
229 onChange(checked);
230 }
AviZi280f8012017-06-09 02:39:56 +0300231
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200232 onChangeRadio(isChecked) {
233 let { onChange } = this.props;
234 this.setState({
235 checked: isChecked
236 });
237 onChange(this.state.value);
238 }
AviZi280f8012017-06-09 02:39:56 +0300239
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200240 focus() {
241 ReactDOM.findDOMNode(this.input).focus();
242 }
AviZi280f8012017-06-09 02:39:56 +0300243
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200244 renderErrorOverlay() {
245 let position = 'right';
246 const { errorText = '', isValid = true, type, overlayPos } = this.props;
AviZi280f8012017-06-09 02:39:56 +0300247
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200248 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 }
AviZi280f8012017-06-09 02:39:56 +0300260
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200261 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 }
AviZi280f8012017-06-09 02:39:56 +0300278}
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200279export default Input;