MetricSelect.tsx 2.3 KB

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