/*! * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing * permissions and limitations under the License. */ import React from 'react'; import PropTypes from 'prop-types'; import ReactDOM from 'react-dom'; import i18n from 'nfvo-utils/i18n/i18n.js'; import classNames from 'classnames'; import Select from 'nfvo-components/input/SelectInput.jsx'; import Overlay from 'react-bootstrap/lib/Overlay.js'; import Tooltip from 'react-bootstrap/lib/Tooltip.js'; export const other = {OTHER: 'Other'}; class InputOptions extends React.Component { static propTypes = { values: PropTypes.arrayOf(PropTypes.shape({ enum: PropTypes.string, title: PropTypes.string })), isEnabledOther: PropTypes.bool, label: PropTypes.string, selectedValue: PropTypes.string, multiSelectedEnum: PropTypes.oneOfType([ PropTypes.string, PropTypes.array ]), selectedEnum: PropTypes.string, otherValue: PropTypes.string, overlayPos: PropTypes.string, onEnumChange: PropTypes.func, onOtherChange: PropTypes.func, onBlur: PropTypes.func, isRequired: PropTypes.bool, isMultiSelect: PropTypes.bool, isValid: PropTypes.bool, disabled: PropTypes.bool }; state = { otherInputDisabled: !this.props.otherValue }; oldProps = { selectedEnum: '', otherValue: '', multiSelectedEnum: [] }; render() { let {label, isRequired, values, otherValue, onOtherChange, isMultiSelect, onBlur, multiSelectedEnum, selectedEnum, isValid, children, isReadOnlyMode} = this.props; const dataTestId = this.props['data-test-id'] ? {'data-test-id': this.props['data-test-id']} : {}; let currentMultiSelectedEnum = []; let currentSelectedEnum = ''; let otherInputDisabled = (isMultiSelect && (multiSelectedEnum === undefined || multiSelectedEnum.length === 0 || multiSelectedEnum[0] !== other.OTHER)) || (!isMultiSelect && (selectedEnum === undefined || selectedEnum !== other.OTHER)); if (isMultiSelect) { currentMultiSelectedEnum = multiSelectedEnum; if(!otherInputDisabled) { currentSelectedEnum = multiSelectedEnum ? multiSelectedEnum.toString() : undefined; } } else if(selectedEnum){ currentSelectedEnum = selectedEnum; } if (!onBlur) { onBlur = () => {}; } return(
{label && } {isMultiSelect && otherInputDisabled ? this.input = input} label={label} className='form-control input-options-select' value={currentSelectedEnum} style={{'width' : otherInputDisabled ? '100%' : '100px'}} onBlur={() => onBlur()} disabled={isReadOnlyMode || Boolean(this.props.disabled)} onChange={ value => this.enumChanged(value)} type='select'> {children || (values && values.length && values.map((val, index) => this.renderOptions(val, index)))} {onOtherChange && } {!otherInputDisabled &&
} this.otherValue = otherValue} style={{'display' : otherInputDisabled ? 'none' : 'block'}} disabled={isReadOnlyMode || Boolean(this.props.disabled)} value={otherValue || ''} onBlur={() => onBlur()} onChange={() => this.changedOtherInput()}/>
}
{ this.renderErrorOverlay() }
); } renderOptions(val, index){ return ( ); } renderMultiSelectOptions(values) { let {onOtherChange} = this.props; let optionsList = []; if (onOtherChange) { optionsList = values.map(option => { return { label: option.title, value: option.enum, }; }).concat([{ label: i18n(other.OTHER), value: i18n(other.OTHER), }]); } else { optionsList = values.map(option => { return { label: option.title, value: option.enum, }; }); } if (optionsList.length > 0 && optionsList[0].value === '') { optionsList.shift(); } return optionsList; } renderErrorOverlay() { let position = 'right'; const {errorText = '', isValid = true, type, overlayPos} = this.props; if (overlayPos) { position = overlayPos; } else if (type === 'text' || type === 'email' || type === 'number' || type === 'password') { position = 'bottom'; } return ( { let {otherInputDisabled} = this.state; let target = otherInputDisabled ? ReactDOM.findDOMNode(this.input) : ReactDOM.findDOMNode(this.otherValue); return target.offsetParent ? target : undefined; }} container={this}> {errorText} ); } getValue() { let res = ''; let {isMultiSelect} = this.props; let {otherInputDisabled} = this.state; if (otherInputDisabled) { res = isMultiSelect ? this.input.getValue() : this.input.value; } else { res = this.otherValue.value; } return res; } enumChanged() { let enumValue = this.input.value; let {onEnumChange, onOtherChange, isMultiSelect, onChange} = this.props; this.setState({ otherInputDisabled: !Boolean(onOtherChange) || enumValue !== other.OTHER }); let value = isMultiSelect ? [enumValue] : enumValue; if (onEnumChange) { onEnumChange(value); } if (onChange) { onChange(value); } } multiSelectEnumChanged(enumValue) { let {onEnumChange, onOtherChange} = this.props; let selectedValues = enumValue.map(enumVal => { return enumVal.value; }); if (this.state.otherInputDisabled === false) { selectedValues.shift(); } else if (selectedValues.includes(i18n(other.OTHER))) { selectedValues = [i18n(other.OTHER)]; } this.setState({ otherInputDisabled: !Boolean(onOtherChange) || !selectedValues.includes(i18n(other.OTHER)) }); onEnumChange(selectedValues); } changedOtherInput() { let {onOtherChange} = this.props; onOtherChange(this.otherValue.value); } componentDidUpdate() { let {otherValue, selectedEnum, onInputChange, multiSelectedEnum} = this.props; if (this.oldProps.otherValue !== otherValue || this.oldProps.selectedEnum !== selectedEnum || this.oldProps.multiSelectedEnum !== multiSelectedEnum) { this.oldProps = { otherValue, selectedEnum, multiSelectedEnum }; onInputChange(); } } static getTitleByName(values, name) { for (let key of Object.keys(values)) { let option = values[key].find(option => option.enum === name); if (option) { return option.title; } } return name; } } export default InputOptions;