From 6f1a38cbe2030e7a11369bb42afd833f32fd3b2e Mon Sep 17 00:00:00 2001 From: Alex Khomenko Date: Fri, 12 Feb 2021 16:00:12 +0200 Subject: [PATCH] Variables: Extend option pickers to accept custom onChange callback (#30913) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Rename DashboardPicker props * Extend variable option pickers to allow providing custom onchage callback * Update public/app/features/variables/pickers/OptionsPicker/actions.ts Co-authored-by: Hugo Häggmark * Update public/app/features/variables/pickers/OptionsPicker/actions.ts Co-authored-by: Hugo Häggmark * Update public/app/features/variables/pickers/OptionsPicker/actions.ts Co-authored-by: Hugo Häggmark * Update public/app/features/variables/textbox/TextBoxVariablePicker.tsx Co-authored-by: Hugo Häggmark * Codeformat Co-authored-by: Hugo Häggmark --- .../core/components/Select/DashboardPicker.tsx | 17 +++++------------ .../pickers/OptionsPicker/OptionsPicker.tsx | 2 +- .../variables/pickers/OptionsPicker/actions.ts | 18 +++++++++++++----- public/app/features/variables/pickers/types.ts | 1 + .../textbox/TextBoxVariablePicker.tsx | 11 ++++++++++- 5 files changed, 30 insertions(+), 19 deletions(-) diff --git a/public/app/core/components/Select/DashboardPicker.tsx b/public/app/core/components/Select/DashboardPicker.tsx index f8735d78e9f..451e45e842a 100644 --- a/public/app/core/components/Select/DashboardPicker.tsx +++ b/public/app/core/components/Select/DashboardPicker.tsx @@ -7,8 +7,8 @@ import { DashboardSearchHit } from 'app/features/search/types'; import { DashboardDTO } from 'app/types'; export interface Props { - onSelected: (dashboard: DashboardDTO) => void; - currentDashboard?: SelectableValue; + onChange: (dashboard: DashboardDTO) => void; + value?: SelectableValue; width?: number; isClearable?: boolean; invalid?: boolean; @@ -26,14 +26,7 @@ const getDashboards = (query = '') => { }); }; -export const DashboardPicker: FC = ({ - onSelected, - currentDashboard, - width, - isClearable = false, - invalid, - disabled, -}) => { +export const DashboardPicker: FC = ({ onChange, value, width, isClearable = false, invalid, disabled }) => { const debouncedSearch = debounce(getDashboards, 300); return ( @@ -42,10 +35,10 @@ export const DashboardPicker: FC = ({ isClearable={isClearable} defaultOptions={true} loadOptions={debouncedSearch} - onChange={onSelected} + onChange={onChange} placeholder="Select dashboard" noOptionsMessage="No dashboards found" - value={currentDashboard} + value={value} invalid={invalid} disabled={disabled} /> diff --git a/public/app/features/variables/pickers/OptionsPicker/OptionsPicker.tsx b/public/app/features/variables/pickers/OptionsPicker/OptionsPicker.tsx index f27a7ca8cf3..1c8297088b2 100644 --- a/public/app/features/variables/pickers/OptionsPicker/OptionsPicker.tsx +++ b/public/app/features/variables/pickers/OptionsPicker/OptionsPicker.tsx @@ -36,7 +36,7 @@ type Props = OwnProps & ConnectedProps & DispatchProps; export class OptionsPickerUnconnected extends PureComponent { onShowOptions = () => this.props.showOptions(this.props.variable); - onHideOptions = () => this.props.commitChangesToVariable(); + onHideOptions = () => this.props.commitChangesToVariable(this.props.onVariableChange); onToggleOption = (option: VariableOption, clearOthers: boolean) => { const toggleFunc = this.props.variable.multi ? this.onToggleMultiValueVariable : this.onToggleSingleValueVariable; diff --git a/public/app/features/variables/pickers/OptionsPicker/actions.ts b/public/app/features/variables/pickers/OptionsPicker/actions.ts index 9a4c471d197..1bc98126ed3 100644 --- a/public/app/features/variables/pickers/OptionsPicker/actions.ts +++ b/public/app/features/variables/pickers/OptionsPicker/actions.ts @@ -72,7 +72,13 @@ export const filterOrSearchOptions = (searchQuery = ''): ThunkResult => { }; }; -export const commitChangesToVariable = (): ThunkResult => { +const setVariable = async (updated: VariableWithMultiSupport) => { + const adapter = variableAdapters.get(updated.type); + await adapter.setValue(updated, updated.current, true); + return; +}; + +export const commitChangesToVariable = (callback?: (updated: VariableWithMultiSupport) => void): ThunkResult => { return async (dispatch, getState) => { const picker = getState().templating.optionsPicker; const existing = getVariable(picker.id, getState()); @@ -88,9 +94,11 @@ export const commitChangesToVariable = (): ThunkResult => { return; } - const adapter = variableAdapters.get(updated.type); - await adapter.setValue(updated, updated.current, true); - return; + if (callback) { + return callback(updated); + } + + return setVariable(updated); }; }; @@ -159,7 +167,7 @@ const searchForOptions = async (dispatch: ThunkDispatch, getState: () => StoreSt const searchForOptionsWithDebounce = debounce(searchForOptions, 500); -function mapToCurrent(picker: OptionsPickerState): VariableOption | undefined { +export function mapToCurrent(picker: OptionsPickerState): VariableOption | undefined { const { options, selectedValues, queryValue: searchQuery, multi } = picker; if (options.length === 0 && searchQuery && searchQuery.length > 0) { diff --git a/public/app/features/variables/pickers/types.ts b/public/app/features/variables/pickers/types.ts index 6a8ef8e9695..b992f303b9e 100644 --- a/public/app/features/variables/pickers/types.ts +++ b/public/app/features/variables/pickers/types.ts @@ -2,6 +2,7 @@ import { VariableModel } from '../types'; export interface VariablePickerProps { variable: Model; + onVariableChange?: (variable: Model) => void; } export enum NavigationKey { diff --git a/public/app/features/variables/textbox/TextBoxVariablePicker.tsx b/public/app/features/variables/textbox/TextBoxVariablePicker.tsx index b5f3e4a1570..efb3b907268 100644 --- a/public/app/features/variables/textbox/TextBoxVariablePicker.tsx +++ b/public/app/features/variables/textbox/TextBoxVariablePicker.tsx @@ -10,7 +10,7 @@ import { useDispatch } from 'react-redux'; export interface Props extends VariablePickerProps {} -export function TextBoxVariablePicker({ variable }: Props): ReactElement { +export function TextBoxVariablePicker({ variable, onVariableChange }: Props): ReactElement { const dispatch = useDispatch(); const [updatedValue, setUpdatedValue] = useState(variable.current.value); useEffect(() => { @@ -27,6 +27,15 @@ export function TextBoxVariablePicker({ variable }: Props): ReactElement { toVariablePayload({ id: variable.id, type: variable.type }, { propName: 'query', propValue: updatedValue }) ) ); + + if (onVariableChange) { + onVariableChange({ + ...variable, + current: { ...variable.current, value: updatedValue }, + }); + return; + } + variableAdapters.get(variable.type).updateOptions(variable); }, [dispatch, variable, updatedValue]);