MetricSelect.tsx 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. import React from 'react';
  2. import _ from 'lodash';
  3. import { Select, SelectOptionItem } from '@grafana/ui';
  4. import { Variable } from 'app/types/templates';
  5. export interface Props {
  6. onChange: (value: string) => void;
  7. options: SelectOptionItem[];
  8. isSearchable: boolean;
  9. value: string;
  10. placeholder?: string;
  11. className?: string;
  12. variables?: Variable[];
  13. }
  14. interface State {
  15. options: any[];
  16. }
  17. export class MetricSelect extends React.Component<Props, State> {
  18. static defaultProps = {
  19. variables: [],
  20. options: [],
  21. isSearchable: true,
  22. };
  23. constructor(props) {
  24. super(props);
  25. this.state = { options: [] };
  26. }
  27. componentDidMount() {
  28. this.setState({ options: this.buildOptions(this.props) });
  29. }
  30. componentWillReceiveProps(nextProps: Props) {
  31. if (nextProps.options.length > 0 || nextProps.variables.length) {
  32. this.setState({ options: this.buildOptions(nextProps) });
  33. }
  34. }
  35. shouldComponentUpdate(nextProps: Props) {
  36. const nextOptions = this.buildOptions(nextProps);
  37. return nextProps.value !== this.props.value || !_.isEqual(nextOptions, this.state.options);
  38. }
  39. buildOptions({ variables = [], options }) {
  40. return variables.length > 0 ? [this.getVariablesGroup(), ...options] : options;
  41. }
  42. getVariablesGroup() {
  43. return {
  44. label: 'Template Variables',
  45. options: this.props.variables.map(v => ({
  46. label: `$${v.name}`,
  47. value: `$${v.name}`,
  48. })),
  49. };
  50. }
  51. getSelectedOption() {
  52. const { options } = this.state;
  53. const allOptions = options.every(o => o.options) ? _.flatten(options.map(o => o.options)) : options;
  54. return allOptions.find(option => option.value === this.props.value);
  55. }
  56. render() {
  57. const { placeholder, className, isSearchable, onChange } = this.props;
  58. const { options } = this.state;
  59. const selectedOption = this.getSelectedOption();
  60. return (
  61. <Select
  62. className={className}
  63. isMulti={false}
  64. isClearable={false}
  65. backspaceRemovesValue={false}
  66. onChange={item => onChange(item.value)}
  67. options={options}
  68. isSearchable={isSearchable}
  69. maxMenuHeight={500}
  70. placeholder={placeholder}
  71. noOptionsMessage={() => 'No options found'}
  72. value={selectedOption}
  73. />
  74. );
  75. }
  76. }