Files
redash/client/app/components/QueryBasedParameterInput.jsx
Gabriel Dutra d8a0af1a95 Fix query based dropdown not adding quote marks correctly (#4186)
* Handle non-array in multi-value QueryBasedParameter

* Use state value in QueryBasedParameterInput

* Normalize array in parameter structure

* Add Multi-selection test

* Remove unnecessary not null check
2019-10-06 11:35:47 +03:00

113 lines
3.1 KiB
JavaScript

import { find, isArray, map, intersection, isEqual } from 'lodash';
import React from 'react';
import PropTypes from 'prop-types';
import { react2angular } from 'react2angular';
import Select from 'antd/lib/select';
const { Option } = Select;
export class QueryBasedParameterInput extends React.Component {
static propTypes = {
parameter: PropTypes.any, // eslint-disable-line react/forbid-prop-types
value: PropTypes.any, // eslint-disable-line react/forbid-prop-types
mode: PropTypes.oneOf(['default', 'multiple']),
queryId: PropTypes.number,
onSelect: PropTypes.func,
className: PropTypes.string,
};
static defaultProps = {
value: null,
mode: 'default',
parameter: null,
queryId: null,
onSelect: () => {},
className: '',
};
constructor(props) {
super(props);
this.state = {
options: [],
value: null,
loading: false,
};
}
componentDidMount() {
this._loadOptions(this.props.queryId);
}
componentDidUpdate(prevProps) {
if (this.props.queryId !== prevProps.queryId) {
this._loadOptions(this.props.queryId);
}
if (this.props.value !== prevProps.value) {
this.setValue(this.props.value);
}
}
setValue(value) {
const { options } = this.state;
if (this.props.mode === 'multiple') {
value = isArray(value) ? value : [value];
const optionValues = map(options, option => option.value);
const validValues = intersection(value, optionValues);
this.setState({ value: validValues });
return validValues;
}
const found = find(options, option => option.value === this.props.value) !== undefined;
value = found ? value : options[0].value;
this.setState({ value });
return value;
}
async _loadOptions(queryId) {
if (queryId && (queryId !== this.state.queryId)) {
this.setState({ loading: true });
const options = await this.props.parameter.loadDropdownValues();
// stale queryId check
if (this.props.queryId === queryId) {
this.setState({ options, loading: false }, () => {
const updatedValue = this.setValue(this.props.value);
if (!isEqual(updatedValue, this.props.value)) {
this.props.onSelect(updatedValue);
}
});
}
}
}
render() {
const { className, value, mode, onSelect, ...otherProps } = this.props;
const { loading, options } = this.state;
return (
<span>
<Select
className={className}
disabled={loading || (options.length === 0)}
loading={loading}
mode={mode}
value={this.state.value}
onChange={onSelect}
dropdownMatchSelectWidth={false}
optionFilterProp="children"
showSearch
showArrow
notFoundContent={null}
{...otherProps}
>
{options.map(option => (<Option value={option.value} key={option.value}>{option.name}</Option>))}
</Select>
</span>
);
}
}
export default function init(ngModule) {
ngModule.component('queryBasedParameterInput', react2angular(QueryBasedParameterInput));
}
init.init = true;