Adding missing packege
[aai/sparky-fe.git] / src / generic-components / input / inputOptions / InputOptions.jsx
1 /*
2  * ============LICENSE_START=======================================================
3  * org.onap.aai
4  * ================================================================================
5  * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
6  * Copyright © 2017-2018 Amdocs
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *       http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21 import React from 'react';
22 import { PropTypes } from 'prop-types';
23 import i18n from 'utils/i18n/i18n.js';
24 import classNames from 'classnames';
25 import Select from 'generic-components/input/SelectInput.jsx';
26
27 export const other = {OTHER: 'Other'};
28
29 class InputOptions extends React.Component {
30
31   static propTypes = {
32     values: PropTypes.arrayOf(PropTypes.shape({
33       enum: PropTypes.string,
34       title: PropTypes.string
35     })),
36     isEnabledOther: PropTypes.bool,
37     title: PropTypes.string,
38     selectedValue: PropTypes.string,
39     multiSelectedEnum: PropTypes.array,
40     selectedEnum: PropTypes.string,
41     otherValue: PropTypes.string,
42     onEnumChange: PropTypes.func,
43     onOtherChange: PropTypes.func,
44     isRequired: PropTypes.bool,
45     isMultiSelect: PropTypes.bool
46   };
47
48
49   static contextTypes = {
50     isReadOnlyMode: PropTypes.bool
51   };
52
53   state = {
54     otherInputDisabled: !this.props.otherValue
55   };
56
57   oldProps = {
58     selectedEnum: '',
59     otherValue: '',
60     multiSelectedEnum: []
61   };
62
63   render() {
64     let {label, isRequired, values, otherValue, onOtherChange, isMultiSelect, onBlur, multiSelectedEnum, selectedEnum, hasError, validations, children} = this.props;
65
66     let currentMultiSelectedEnum = [];
67     let currentSelectedEnum = '';
68     let {otherInputDisabled} = this.state;
69     if (isMultiSelect) {
70       currentMultiSelectedEnum = multiSelectedEnum;
71       if (!otherInputDisabled) {
72         currentSelectedEnum =
73           multiSelectedEnum ? multiSelectedEnum.toString() : undefined;
74       }
75     }
76     else {
77       currentSelectedEnum = selectedEnum;
78     }
79
80     let isReadOnlyMode = this.context.isReadOnlyMode;
81
82     return (
83       <div
84         className={classNames('form-group', {'required' : validations.required , 'has-error' : hasError})}>
85         <label className='control-label'>{label}</label>
86         {isMultiSelect && otherInputDisabled ?
87           <Select
88             ref='_myInput'
89             value={currentMultiSelectedEnum}
90             className='options-input'
91             clearable={false}
92             required={isRequired}
93             disabled={isReadOnlyMode || Boolean(this.props.disabled)}
94             onBlur={() => onBlur()}
95             onMultiSelectChanged={value => this.multiSelectEnumChanged(value)}
96             options={this.renderMultiSelectOptions(values)}
97             multi/> :
98           <div className={classNames('input-options',{'has-error' : hasError})}>
99             <select
100               ref={'_myInput'}
101               label={label}
102               className='form-control input-options-select'
103               value={currentSelectedEnum}
104               style={{'width' : otherInputDisabled ? '100%' : '95px'}}
105               onBlur={() => onBlur()}
106               disabled={isReadOnlyMode || Boolean(this.props.disabled)}
107               onChange={ value => this.enumChanged(value)}
108               type='select'>
109               {values &&
110               values.length &&
111               values.map(val => this.renderOptions(val))}
112               {onOtherChange && <option key='other'
113                                         value={other.OTHER}>{i18n(
114                 other.OTHER)}</option>}
115               {children}
116             </select>
117
118             {!otherInputDisabled && <div className='input-options-separator'/>}
119             <input
120               className='form-control input-options-other'
121               placeholder={i18n('other')}
122               ref='_otherValue'
123               style={{'display' : otherInputDisabled ? 'none' : 'block'}}
124               disabled={isReadOnlyMode || Boolean(this.props.disabled)}
125               value={otherValue || ''}
126               onBlur={() => onBlur()}
127               onChange={() => this.changedOtherInput()}/>
128           </div>
129         }
130       </div>
131     );
132   }
133
134   renderOptions(val) {
135     return (
136       <option key={val.enum} value={val.enum}>{val.title}</option>
137     );
138   }
139
140
141   renderMultiSelectOptions(values) {
142     let {onOtherChange} = this.props;
143     let optionsList = [];
144     if (onOtherChange) {
145       optionsList = values.map(option => {
146         return {
147           label: option.title,
148           value: option.enum,
149         };
150       }).concat([{
151         label: i18n(other.OTHER),
152         value: i18n(other.OTHER),
153       }]);
154     }
155     else {
156       optionsList = values.map(option => {
157         return {
158           label: option.title,
159           value: option.enum,
160         };
161       });
162     }
163     if (optionsList.length > 0 && optionsList[0].value === '') {
164       optionsList.shift();
165     }
166     return optionsList;
167   }
168
169   getValue() {
170     let res = '';
171     let {isMultiSelect} = this.props;
172     let {otherInputDisabled} = this.state;
173
174     if (otherInputDisabled) {
175       res =
176         isMultiSelect
177           ? this.refs._myInput.getValue()
178           : this.refs._myInput.value;
179     } else {
180       res = this.refs._otherValue.value;
181     }
182     return res;
183   }
184
185   enumChanged() {
186     let enumValue = this.refs._myInput.value;
187     let {onEnumChange, isMultiSelect, onChange} = this.props;
188     this.setState({
189       otherInputDisabled: enumValue !== other.OTHER
190     });
191     if (onEnumChange) {
192       onEnumChange(isMultiSelect ? [enumValue] : enumValue);
193     }
194
195     if (onChange) {
196       onChange(enumValue);
197     }
198
199   }
200
201   multiSelectEnumChanged(enumValue) {
202     let {onEnumChange} = this.props;
203     let selectedValues = enumValue.map(enumVal => {
204       return enumVal.value;
205     });
206
207     if (this.state.otherInputDisabled === false) {
208       selectedValues.shift();
209     }
210     else if (selectedValues.includes(i18n(other.OTHER))) {
211       selectedValues = [i18n(other.OTHER)];
212     }
213
214     this.setState({
215       otherInputDisabled: !selectedValues.includes(i18n(other.OTHER))
216     });
217     onEnumChange(selectedValues);
218   }
219
220   changedOtherInput() {
221     let {onOtherChange} = this.props;
222     onOtherChange(this.refs._otherValue.value);
223   }
224
225   componentDidUpdate() {
226     let {otherValue, selectedEnum, onInputChange, multiSelectedEnum} = this.props;
227     if (this.oldProps.otherValue !== otherValue
228       || this.oldProps.selectedEnum !== selectedEnum
229       || this.oldProps.multiSelectedEnum !== multiSelectedEnum) {
230       this.oldProps = {
231         otherValue,
232         selectedEnum,
233         multiSelectedEnum
234       };
235       onInputChange();
236     }
237   }
238
239 }
240
241 export default InputOptions;