2 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 import React from 'react';
17 import ReactDOM from 'react-dom';
18 import i18n from 'nfvo-utils/i18n/i18n.js';
19 import classNames from 'classnames';
20 import Select from 'nfvo-components/input/SelectInput.jsx';
21 import Overlay from 'react-bootstrap/lib/Overlay.js';
22 import Tooltip from 'react-bootstrap/lib/Tooltip.js';
24 export const other = {OTHER: 'Other'};
26 class InputOptions extends React.Component {
29 values: React.PropTypes.arrayOf(React.PropTypes.shape({
30 enum: React.PropTypes.string,
31 title: React.PropTypes.string
33 isEnabledOther: React.PropTypes.bool,
34 label: React.PropTypes.string,
35 selectedValue: React.PropTypes.string,
36 multiSelectedEnum: React.PropTypes.oneOfType([
37 React.PropTypes.string,
40 selectedEnum: React.PropTypes.string,
41 otherValue: React.PropTypes.string,
42 overlayPos: React.PropTypes.string,
43 onEnumChange: React.PropTypes.func,
44 onOtherChange: React.PropTypes.func,
45 onBlur: React.PropTypes.func,
46 isRequired: React.PropTypes.bool,
47 isMultiSelect: React.PropTypes.bool,
48 isValid: React.PropTypes.bool,
49 disabled: React.PropTypes.bool
53 otherInputDisabled: !this.props.otherValue
63 let {label, isRequired, values, otherValue, onOtherChange, isMultiSelect, onBlur, multiSelectedEnum, selectedEnum, isValid, children, isReadOnlyMode} = this.props;
64 const dataTestId = this.props['data-test-id'] ? {'data-test-id': this.props['data-test-id']} : {};
65 let currentMultiSelectedEnum = [];
66 let currentSelectedEnum = '';
67 let {otherInputDisabled} = this.state;
69 currentMultiSelectedEnum = multiSelectedEnum;
70 if(!otherInputDisabled) {
71 currentSelectedEnum = multiSelectedEnum ? multiSelectedEnum.toString() : undefined;
74 else if(selectedEnum){
75 currentSelectedEnum = selectedEnum;
82 <div className='validation-input-wrapper' >
83 <div className={classNames('form-group', {'required' : isRequired, 'has-error' : !isValid})} >
84 {label && <label className='control-label'>{label}</label>}
85 {isMultiSelect && otherInputDisabled ?
88 ref={(input) => this.input = input}
89 value={currentMultiSelectedEnum}
90 className='options-input'
93 disabled={isReadOnlyMode || Boolean(this.props.disabled)}
94 onBlur={() => onBlur()}
95 onMultiSelectChanged={value => this.multiSelectEnumChanged(value)}
96 options={this.renderMultiSelectOptions(values)}
98 <div className={classNames('input-options',{'has-error' : !isValid})} >
101 ref={(input) => this.input = input}
103 className='form-control input-options-select'
104 value={currentSelectedEnum}
105 style={{'width' : otherInputDisabled ? '100%' : '100px'}}
106 onBlur={() => onBlur()}
107 disabled={isReadOnlyMode || Boolean(this.props.disabled)}
108 onChange={ value => this.enumChanged(value)}
110 {children || (values && values.length && values.map((val, index) => this.renderOptions(val, index)))}
111 {onOtherChange && <option key='other' value={other.OTHER}>{i18n(other.OTHER)}</option>}
114 {!otherInputDisabled && <div className='input-options-separator'/>}
116 className='form-control input-options-other'
117 placeholder={i18n('other')}
118 ref={(otherValue) => this.otherValue = otherValue}
119 style={{'display' : otherInputDisabled ? 'none' : 'block'}}
120 disabled={isReadOnlyMode || Boolean(this.props.disabled)}
121 value={otherValue || ''}
122 onBlur={() => onBlur()}
123 onChange={() => this.changedOtherInput()}/>
127 { this.renderErrorOverlay() }
132 renderOptions(val, index){
134 <option key={index} value={val.enum}>{val.title}</option>
139 renderMultiSelectOptions(values) {
140 let {onOtherChange} = this.props;
141 let optionsList = [];
143 optionsList = values.map(option => {
149 label: i18n(other.OTHER),
150 value: i18n(other.OTHER),
154 optionsList = values.map(option => {
161 if (optionsList.length > 0 && optionsList[0].value === '') {
167 renderErrorOverlay() {
168 let position = 'right';
169 const {errorText = '', isValid = true, type, overlayPos} = this.props;
172 position = overlayPos;
174 else if (type === 'text'
177 || type === 'password') {
186 let {otherInputDisabled} = this.state;
187 let target = otherInputDisabled ? ReactDOM.findDOMNode(this.input) : ReactDOM.findDOMNode(this.otherValue);
188 return target.offsetParent ? target : undefined;
192 id={`error-${errorText.replace(' ', '-')}`}
193 className='validation-error-message'>
202 let {isMultiSelect} = this.props;
203 let {otherInputDisabled} = this.state;
205 if (otherInputDisabled) {
206 res = isMultiSelect ? this.input.getValue() : this.input.value;
208 res = this.otherValue.value;
214 let enumValue = this.input.value;
215 let {onEnumChange, onOtherChange, isMultiSelect, onChange} = this.props;
217 otherInputDisabled: !Boolean(onOtherChange) || enumValue !== other.OTHER
220 let value = isMultiSelect ? [enumValue] : enumValue;
229 multiSelectEnumChanged(enumValue) {
230 let {onEnumChange, onOtherChange} = this.props;
231 let selectedValues = enumValue.map(enumVal => {
232 return enumVal.value;
235 if (this.state.otherInputDisabled === false) {
236 selectedValues.shift();
238 else if (selectedValues.includes(i18n(other.OTHER))) {
239 selectedValues = [i18n(other.OTHER)];
243 otherInputDisabled: !Boolean(onOtherChange) || !selectedValues.includes(i18n(other.OTHER))
245 onEnumChange(selectedValues);
248 changedOtherInput() {
249 let {onOtherChange} = this.props;
250 onOtherChange(this.otherValue.value);
253 componentDidUpdate() {
254 let {otherValue, selectedEnum, onInputChange, multiSelectedEnum} = this.props;
255 if (this.oldProps.otherValue !== otherValue
256 || this.oldProps.selectedEnum !== selectedEnum
257 || this.oldProps.multiSelectedEnum !== multiSelectedEnum) {
267 static getTitleByName(values, name) {
268 for (let key of Object.keys(values)) {
269 let option = values[key].find(option => option.enum === name);
279 export default InputOptions;