grafana/public/app/core/components/Select/MetricSelect.tsx

91 lines
2.4 KiB
TypeScript
Raw Normal View History

2018-12-18 04:25:13 -06:00
import React from 'react';
import _ from 'lodash';
2018-12-19 14:34:13 -06:00
import { LegacyForms } from '@grafana/ui';
import { SelectableValue } from '@grafana/data';
2018-12-19 14:34:13 -06:00
import { Variable } from 'app/types/templates';
const { Select } = LegacyForms;
2018-12-18 04:25:13 -06:00
export interface Props {
onChange: (value: string) => void;
options: Array<SelectableValue<string>>;
2018-12-19 14:14:55 -06:00
isSearchable: boolean;
2018-12-19 14:19:43 -06:00
value: string;
2018-12-18 04:25:13 -06:00
placeholder?: string;
className?: string;
2018-12-19 14:34:13 -06:00
variables?: Variable[];
2018-12-18 04:25:13 -06:00
}
interface State {
options: Array<SelectableValue<string>>;
}
export class MetricSelect extends React.Component<Props, State> {
static defaultProps: Partial<Props> = {
2018-12-19 14:23:05 -06:00
variables: [],
options: [],
2019-01-02 05:18:15 -06:00
isSearchable: true,
};
constructor(props: Props) {
2018-12-18 04:25:13 -06:00
super(props);
this.state = { options: [] };
2018-12-18 04:25:13 -06:00
}
componentDidMount() {
this.setState({ options: this.buildOptions(this.props) });
2018-12-18 04:25:13 -06:00
}
UNSAFE_componentWillReceiveProps(nextProps: Props) {
2018-12-19 14:23:05 -06:00
if (nextProps.options.length > 0 || nextProps.variables.length) {
this.setState({ options: this.buildOptions(nextProps) });
}
}
2018-12-18 09:09:32 -06:00
shouldComponentUpdate(nextProps: Props) {
2018-12-18 09:56:16 -06:00
const nextOptions = this.buildOptions(nextProps);
2018-12-19 14:19:43 -06:00
return nextProps.value !== this.props.value || !_.isEqual(nextOptions, this.state.options);
}
buildOptions({ variables = [], options }: Props) {
2019-01-02 05:21:30 -06:00
return variables.length > 0 ? [this.getVariablesGroup(), ...options] : options;
}
2018-12-19 14:23:05 -06:00
getVariablesGroup() {
return {
label: 'Template Variables',
2018-12-19 14:23:05 -06:00
options: this.props.variables.map(v => ({
label: `$${v.name}`,
value: `$${v.name}`,
})),
};
}
getSelectedOption() {
const { options } = this.state;
const allOptions = options.every(o => o.options) ? _.flatten(options.map(o => o.options)) : options;
2018-12-19 14:19:43 -06:00
return allOptions.find(option => option.value === this.props.value);
}
2018-12-18 04:25:13 -06:00
render() {
2018-12-19 14:14:55 -06:00
const { placeholder, className, isSearchable, onChange } = this.props;
const { options } = this.state;
const selectedOption = this.getSelectedOption();
2018-12-18 04:25:13 -06:00
return (
<Select
className={className}
isMulti={false}
isClearable={false}
backspaceRemovesValue={false}
onChange={item => onChange(item.value)}
2018-12-18 04:25:13 -06:00
options={options}
2018-12-19 14:14:55 -06:00
isSearchable={isSearchable}
2018-12-18 04:25:13 -06:00
maxMenuHeight={500}
placeholder={placeholder}
noOptionsMessage={() => 'No options found'}
value={selectedOption}
/>
);
}
}