[SDC-29] Amdocs OnBoard 1707 initial commit.
[sdc.git] / openecomp-ui / src / nfvo-components / input / inputOptions / InputOptions.jsx
1 /*!
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  */
16 import React from 'react';
17 import i18n from 'nfvo-utils/i18n/i18n.js';
18 import classNames from 'classnames';
19 import Select from 'nfvo-components/input/SelectInput.jsx';
20
21 export const other = {OTHER: 'Other'};
22
23 class InputOptions extends React.Component {
24
25         static propTypes = {
26                 values: React.PropTypes.arrayOf(React.PropTypes.shape({
27                         enum: React.PropTypes.string,
28                         title: React.PropTypes.string
29                 })),
30                 isEnabledOther: React.PropTypes.bool,
31                 label: React.PropTypes.string,
32                 selectedValue: React.PropTypes.string,
33                 multiSelectedEnum: React.PropTypes.oneOfType([
34                         React.PropTypes.string,
35                         React.PropTypes.array
36                 ]),
37                 selectedEnum: React.PropTypes.string,
38                 otherValue: React.PropTypes.string,
39                 onEnumChange: React.PropTypes.func,
40                 onOtherChange: React.PropTypes.func,
41                 onBlur: React.PropTypes.func,
42                 isRequired: React.PropTypes.bool,
43                 isMultiSelect: React.PropTypes.bool,
44                 hasError: React.PropTypes.bool,
45                 disabled: React.PropTypes.bool
46         };
47
48
49         static contextTypes = {
50                 isReadOnlyMode: React.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                 const dataTestId = this.props['data-test-id'] ? {'data-test-id': this.props['data-test-id']} : {};
66                 let currentMultiSelectedEnum = [];
67                 let currentSelectedEnum = '';
68                 let {otherInputDisabled} = this.state;
69                 if (isMultiSelect) {
70                         currentMultiSelectedEnum = multiSelectedEnum;
71                         if(!otherInputDisabled) {
72                                 currentSelectedEnum = multiSelectedEnum ? multiSelectedEnum.toString() : undefined;
73                         }
74                 }
75                 else if(selectedEnum){
76                         currentSelectedEnum = selectedEnum;
77                 }
78                 if (!onBlur) {
79                         onBlur = () => {};
80                 }
81
82                 let isReadOnlyMode = this.context.isReadOnlyMode;
83
84                 return(
85                         <div className={classNames('form-group', {'required' : (validations && validations.required) || isRequired, 'has-error' : hasError})}>
86                                 {label && <label className='control-label'>{label}</label>}
87                                 {isMultiSelect && otherInputDisabled ?
88                                         <Select
89                                                 {...dataTestId}
90                                                 ref='_myInput'
91                                                 value={currentMultiSelectedEnum}
92                                                 className='options-input'
93                                                 clearable={false}
94                                                 required={isRequired}
95                                                 disabled={isReadOnlyMode || Boolean(this.props.disabled)}
96                                                 onBlur={() => onBlur()}
97                                                 onMultiSelectChanged={value => this.multiSelectEnumChanged(value)}
98                                                 options={this.renderMultiSelectOptions(values)}
99                                                 multi/> :
100                                         <div className={classNames('input-options',{'has-error' : hasError})}>
101                                                 <select
102                                                         {...dataTestId}
103                                                         ref={'_myInput'}
104                                                         label={label}
105                                                         className='form-control input-options-select'
106                                                         value={currentSelectedEnum}
107                                                         style={{'width' : otherInputDisabled ? '100%' : '100px'}}
108                                                         onBlur={() => onBlur()}
109                                                         disabled={isReadOnlyMode || Boolean(this.props.disabled)}
110                                                         onChange={ value => this.enumChanged(value)}
111                                                         type='select'>
112                                                         {children || (values && values.length && values.map((val, index) => this.renderOptions(val, index)))}
113                                                         {onOtherChange && <option key='other' value={other.OTHER}>{i18n(other.OTHER)}</option>}
114                                                 </select>
115
116                                                 {!otherInputDisabled && <div className='input-options-separator'/>}
117                                                 <input
118                                                         className='form-control input-options-other'
119                                                         placeholder={i18n('other')}
120                                                         ref='_otherValue'
121                                                         style={{'display' : otherInputDisabled ? 'none' : 'block'}}
122                                                         disabled={isReadOnlyMode || Boolean(this.props.disabled)}
123                                                         value={otherValue || ''}
124                                                         onBlur={() => onBlur()}
125                                                         onChange={() => this.changedOtherInput()}/>
126                                         </div>
127                                 }
128                         </div>
129                 );
130         }
131
132         renderOptions(val, index){
133                 return (
134                         <option key={index} value={val.enum}>{val.title}</option>
135                 );
136         }
137
138
139         renderMultiSelectOptions(values) {
140                 let {onOtherChange} = this.props;
141                 let optionsList = [];
142                 if (onOtherChange) {
143                         optionsList = values.map(option => {
144                                 return {
145                                         label: option.title,
146                                         value: option.enum,
147                                 };
148                         }).concat([{
149                                 label: i18n(other.OTHER),
150                                 value: i18n(other.OTHER),
151                         }]);
152                 }
153                 else {
154                         optionsList = values.map(option => {
155                                 return {
156                                         label: option.title,
157                                         value: option.enum,
158                                 };
159                         });
160                 }
161                 if (optionsList.length > 0 && optionsList[0].value === '') {
162                         optionsList.shift();
163                 }
164                 return optionsList;
165         }
166
167         getValue() {
168                 let res = '';
169                 let {isMultiSelect} = this.props;
170                 let {otherInputDisabled} = this.state;
171
172                 if (otherInputDisabled) {
173                         res = isMultiSelect ? this.refs._myInput.getValue() : this.refs._myInput.value;
174                 } else {
175                         res = this.refs._otherValue.value;
176                 }
177                 return res;
178         }
179
180         enumChanged() {
181                 let enumValue = this.refs._myInput.value;
182                 let {onEnumChange, onOtherChange, isMultiSelect, onChange} = this.props;
183                 this.setState({
184                         otherInputDisabled: !Boolean(onOtherChange) || enumValue !== other.OTHER
185                 });
186
187                 let value = isMultiSelect ? [enumValue] : enumValue;
188                 if (onEnumChange) {
189                         onEnumChange(value);
190                 }
191                 if (onChange) {
192                         onChange(value);
193                 }
194         }
195
196         multiSelectEnumChanged(enumValue) {
197                 let {onEnumChange, onOtherChange} = this.props;
198                 let selectedValues = enumValue.map(enumVal => {
199                         return enumVal.value;
200                 });
201
202                 if (this.state.otherInputDisabled === false) {
203                         selectedValues.shift();
204                 }
205                 else if (selectedValues.includes(i18n(other.OTHER))) {
206                         selectedValues = [i18n(other.OTHER)];
207                 }
208
209                 this.setState({
210                         otherInputDisabled: !Boolean(onOtherChange) || !selectedValues.includes(i18n(other.OTHER))
211                 });
212                 onEnumChange(selectedValues);
213         }
214
215         changedOtherInput() {
216                 let {onOtherChange} = this.props;
217                 onOtherChange(this.refs._otherValue.value);
218         }
219
220         componentDidUpdate() {
221                 let {otherValue, selectedEnum, onInputChange, multiSelectedEnum} = this.props;
222                 if (this.oldProps.otherValue !== otherValue
223                         || this.oldProps.selectedEnum !== selectedEnum
224                         || this.oldProps.multiSelectedEnum !== multiSelectedEnum) {
225                         this.oldProps = {
226                                 otherValue,
227                                 selectedEnum,
228                                 multiSelectedEnum
229                         };
230                         onInputChange();
231                 }
232         }
233
234         static getTitleByName(values, name) {
235                 for (let key of Object.keys(values)) {
236                         let option = values[key].find(option => option.enum === name);
237                         if (option) {
238                                 return option.title;
239                         }
240                 }
241                 return name;
242         }
243
244 }
245
246 export default InputOptions;