import React, { ComponentType, PureComponent } from 'react'; import { connect, ConnectedProps } from 'react-redux'; import { bindActionCreators } from 'redux'; import { LoadingState } from '@grafana/data'; import { ClickOutsideWrapper } from '@grafana/ui'; import { StoreState, ThunkDispatch } from 'app/types'; import { isMulti } from '../../guard'; import { getVariableQueryRunner } from '../../query/VariableQueryRunner'; import { formatVariableLabel } from '../../shared/formatVariable'; import { toKeyedAction } from '../../state/keyedVariablesReducer'; import { getVariablesState } from '../../state/selectors'; import { KeyedVariableIdentifier } from '../../state/types'; import { VariableOption, VariableWithMultiSupport, VariableWithOptions } from '../../types'; import { toKeyedVariableIdentifier } from '../../utils'; import { VariableInput } from '../shared/VariableInput'; import { VariableLink } from '../shared/VariableLink'; import { VariableOptions } from '../shared/VariableOptions'; import { NavigationKey, VariablePickerProps } from '../types'; import { commitChangesToVariable, filterOrSearchOptions, navigateOptions, openOptions } from './actions'; import { initialOptionPickerState, OptionsPickerState, toggleAllOptions, toggleOption } from './reducer'; export const optionPickerFactory = (): ComponentType< VariablePickerProps > => { const mapDispatchToProps = (dispatch: ThunkDispatch) => { return { ...bindActionCreators({ openOptions, commitChangesToVariable, navigateOptions }, dispatch), filterOrSearchOptions: (identifier: KeyedVariableIdentifier, filter = '') => { dispatch(filterOrSearchOptions(identifier, filter)); }, toggleAllOptions: (identifier: KeyedVariableIdentifier) => dispatch(toKeyedAction(identifier.rootStateKey, toggleAllOptions())), toggleOption: ( identifier: KeyedVariableIdentifier, option: VariableOption, clearOthers: boolean, forceSelect: boolean ) => dispatch(toKeyedAction(identifier.rootStateKey, toggleOption({ option, clearOthers, forceSelect }))), }; }; const mapStateToProps = (state: StoreState, ownProps: OwnProps) => { const { rootStateKey } = ownProps.variable; if (!rootStateKey) { console.error('OptionPickerFactory: variable has no rootStateKey'); return { picker: initialOptionPickerState, }; } return { picker: getVariablesState(rootStateKey, state).optionsPicker, }; }; const connector = connect(mapStateToProps, mapDispatchToProps); interface OwnProps extends VariablePickerProps {} type Props = OwnProps & ConnectedProps; class OptionsPickerUnconnected extends PureComponent { onShowOptions = () => this.props.openOptions(toKeyedVariableIdentifier(this.props.variable), this.props.onVariableChange); onHideOptions = () => { if (!this.props.variable.rootStateKey) { console.error('Variable has no rootStateKey'); return; } this.props.commitChangesToVariable(this.props.variable.rootStateKey, this.props.onVariableChange); }; onToggleOption = (option: VariableOption, clearOthers: boolean) => { const toggleFunc = isMulti(this.props.variable) && this.props.variable.multi ? this.onToggleMultiValueVariable : this.onToggleSingleValueVariable; toggleFunc(option, clearOthers); }; onToggleSingleValueVariable = (option: VariableOption, clearOthers: boolean) => { this.props.toggleOption(toKeyedVariableIdentifier(this.props.variable), option, clearOthers, false); this.onHideOptions(); }; onToggleMultiValueVariable = (option: VariableOption, clearOthers: boolean) => { this.props.toggleOption(toKeyedVariableIdentifier(this.props.variable), option, clearOthers, false); }; onToggleAllOptions = () => { this.props.toggleAllOptions(toKeyedVariableIdentifier(this.props.variable)); }; onFilterOrSearchOptions = (filter: string) => { this.props.filterOrSearchOptions(toKeyedVariableIdentifier(this.props.variable), filter); }; onNavigate = (key: NavigationKey, clearOthers: boolean) => { if (!this.props.variable.rootStateKey) { console.error('Variable has no rootStateKey'); return; } this.props.navigateOptions(this.props.variable.rootStateKey, key, clearOthers); }; render() { const { variable, picker } = this.props; const showOptions = picker.id === variable.id; return (
{showOptions ? this.renderOptions(picker) : this.renderLink(variable)}
); } renderLink(variable: VariableWithOptions) { const linkText = formatVariableLabel(variable); const loading = variable.state === LoadingState.Loading; return ( ); } onCancel = () => { getVariableQueryRunner().cancelRequest(toKeyedVariableIdentifier(this.props.variable)); }; renderOptions(picker: OptionsPickerState) { const { id } = this.props.variable; return ( ); } } const OptionsPicker = connector(OptionsPickerUnconnected); OptionsPicker.displayName = 'OptionsPicker'; return OptionsPicker; };