blob: 33cea933b52e6c4e7418ede76f1fd85a64cdead4 [file] [log] [blame]
AviZi280f8012017-06-09 02:39:56 +03001/*!
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 */
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 {
28
29 state = {
30 value: this.props.value,
31 checked: this.props.checked,
32 selectedValues: []
Avi Zivb8e2faf2017-07-18 19:45:38 +030033 };
AviZi280f8012017-06-09 02:39:56 +030034
35 render() {
36 const {label, isReadOnlyMode, value, onBlur, onKeyDown, type, disabled, checked, name} = this.props;
37 // eslint-disable-next-line no-unused-vars
Avi Zivb8e2faf2017-07-18 19:45:38 +030038 const {groupClassName, isValid = true, errorText, isRequired, overlayPos, ...inputProps} = this.props;
39 const {dateFormat, startDate, endDate, selectsStart, selectsEnd} = this.props; // Date Props
40 let wrapperClassName = (type !== 'radio') ? 'validation-input-wrapper' : 'validation-radio-wrapper';
AviZi280f8012017-06-09 02:39:56 +030041 if (disabled) {
42 wrapperClassName += ' disabled';
43 }
44 return(
45 <div className={wrapperClassName}>
46 <FormGroup className={classNames('form-group', [groupClassName], {'required' : isRequired , 'has-error' : !isValid})} >
47 {(label && (type !== 'checkbox' && type !== 'radio')) && <label className='control-label'>{label}</label>}
Avi Zivb8e2faf2017-07-18 19:45:38 +030048 {type === 'text' &&
AviZi280f8012017-06-09 02:39:56 +030049 <FormControl
50 bsClass={'form-control input-options-other'}
51 onChange={(e) => this.onChange(e)}
52 disabled={isReadOnlyMode || Boolean(disabled)}
53 onBlur={onBlur}
54 onKeyDown={onKeyDown}
55 value={value || ''}
56 inputRef={(input) => this.input = input}
57 type={type}
58 data-test-id={this.props['data-test-id']}/>}
Avi Zivb8e2faf2017-07-18 19:45:38 +030059 {type === 'number' &&
60 <FormControl
61 bsClass={'form-control input-options-other'}
62 onChange={(e) => this.onChange(e)}
63 disabled={isReadOnlyMode || Boolean(disabled)}
64 onBlur={onBlur}
65 onKeyDown={onKeyDown}
66 value={(value !== undefined) ? value : ''}
67 inputRef={(input) => this.input = input}
68 type={type}
69 data-test-id={this.props['data-test-id']}/>}
AviZi280f8012017-06-09 02:39:56 +030070
71 {type === 'textarea' &&
72 <FormControl
73 className='form-control input-options-other'
74 disabled={isReadOnlyMode || Boolean(disabled)}
75 value={value || ''}
76 onBlur={onBlur}
77 onKeyDown={onKeyDown}
78 componentClass={type}
79 onChange={(e) => this.onChange(e)}
80 inputRef={(input) => this.input = input}
81 data-test-id={this.props['data-test-id']}/>}
82
83 {type === 'checkbox' &&
84 <Checkbox
85 className={classNames({'required' : isRequired , 'has-error' : !isValid})}
86 onChange={(e)=>this.onChangeCheckBox(e)}
87 disabled={isReadOnlyMode || Boolean(disabled)}
talig8e9c0652017-12-20 14:30:43 +020088 checked={checked}
AviZi280f8012017-06-09 02:39:56 +030089 data-test-id={this.props['data-test-id']}>{label}</Checkbox>}
90
91 {type === 'radio' &&
92 <Radio name={name}
93 checked={checked}
94 disabled={isReadOnlyMode || Boolean(disabled)}
95 value={value}
talig8e9c0652017-12-20 14:30:43 +020096 onChange={(isChecked)=>this.onChangeRadio(isChecked)}
Avi Zivb8e2faf2017-07-18 19:45:38 +030097 inputRef={(input) => this.input = input}
talig8e9c0652017-12-20 14:30:43 +020098 label={label}
99 data-test-id={this.props['data-test-id']} />}
AviZi280f8012017-06-09 02:39:56 +0300100 {type === 'select' &&
101 <FormControl onClick={ (e) => this.optionSelect(e) }
svishnevd105b362018-01-15 18:04:38 +0200102 className='custom-select'
AviZi280f8012017-06-09 02:39:56 +0300103 componentClass={type}
104 inputRef={(input) => this.input = input}
105 name={name} {...inputProps}
106 data-test-id={this.props['data-test-id']}/>}
Avi Zivb8e2faf2017-07-18 19:45:38 +0300107 {type === 'date' &&
108 <Datepicker
109 date={value}
110 format={dateFormat}
111 startDate={startDate}
112 endDate={endDate}
113 inputRef={(input) => this.input = input}
114 onChange={this.props.onChange}
115 disabled={isReadOnlyMode || Boolean(disabled)}
116 data-test-id={this.props['data-test-id']}
117 selectsStart={selectsStart}
118 selectsEnd={selectsEnd} />}
AviZi280f8012017-06-09 02:39:56 +0300119 </FormGroup>
120 { this.renderErrorOverlay() }
121 </div>
122 );
123 }
124
125 getValue() {
126 return this.props.type !== 'select' ? this.state.value : this.state.selectedValues;
127 }
128
129 getChecked() {
130 return this.state.checked;
131 }
132
133 optionSelect(e) {
134 let selectedValues = [];
135 if (e.target.value) {
136 selectedValues.push(e.target.value);
137 }
138 this.setState({
139 selectedValues
140 });
141 }
142
143 onChange(e) {
144 const {onChange, type} = this.props;
145 let value = e.target.value;
146 if (type === 'number') {
Avi Zivb8e2faf2017-07-18 19:45:38 +0300147 if (value === '') {
148 value = undefined;
149 } else {
150 value = Number(value);
151 }
AviZi280f8012017-06-09 02:39:56 +0300152 }
153 this.setState({
154 value
155 });
156 onChange(value);
157 }
158
159 onChangeCheckBox(e) {
160 let {onChange} = this.props;
talig8e9c0652017-12-20 14:30:43 +0200161 let checked = e.target.checked;
AviZi280f8012017-06-09 02:39:56 +0300162 this.setState({
talig8e9c0652017-12-20 14:30:43 +0200163 checked
AviZi280f8012017-06-09 02:39:56 +0300164 });
talig8e9c0652017-12-20 14:30:43 +0200165 onChange(checked);
AviZi280f8012017-06-09 02:39:56 +0300166 }
167
talig8e9c0652017-12-20 14:30:43 +0200168 onChangeRadio(isChecked) {
AviZi280f8012017-06-09 02:39:56 +0300169 let {onChange} = this.props;
170 this.setState({
talig8e9c0652017-12-20 14:30:43 +0200171 checked: isChecked
AviZi280f8012017-06-09 02:39:56 +0300172 });
173 onChange(this.state.value);
174 }
175
176 focus() {
177 ReactDOM.findDOMNode(this.input).focus();
178 }
179
180 renderErrorOverlay() {
181 let position = 'right';
182 const {errorText = '', isValid = true, type, overlayPos} = this.props;
183
184 if (overlayPos) {
185 position = overlayPos;
186 }
187 else if (type === 'text'
188 || type === 'email'
189 || type === 'number'
Avi Zivb8e2faf2017-07-18 19:45:38 +0300190 || type === 'radio'
191 || type === 'password'
192 || type === 'date') {
AviZi280f8012017-06-09 02:39:56 +0300193 position = 'bottom';
194 }
195
196 return (
197 <Overlay
198 show={!isValid}
199 placement={position}
200 target={() => {
201 let target = ReactDOM.findDOMNode(this.input);
202 return target.offsetParent ? target : undefined;
203 }}
204 container={this}>
205 <Tooltip
206 id={`error-${errorText.replace(' ', '-')}`}
207 className='validation-error-message'>
208 {errorText}
209 </Tooltip>
210 </Overlay>
211 );
212 }
213
214}
215export default Input;