Commit 622246d5 by Hugo Häggmark Committed by GitHub

Templating: fixes so Textbox variables get value from url (#24623)

parent f97d021c
...@@ -2,13 +2,14 @@ import { variableAdapters } from '../adapters'; ...@@ -2,13 +2,14 @@ import { variableAdapters } from '../adapters';
import { createTextBoxVariableAdapter } from './adapter'; import { createTextBoxVariableAdapter } from './adapter';
import { reduxTester } from '../../../../test/core/redux/reduxTester'; import { reduxTester } from '../../../../test/core/redux/reduxTester';
import { TemplatingState } from 'app/features/variables/state/reducers'; import { TemplatingState } from 'app/features/variables/state/reducers';
import { updateTextBoxVariableOptions } from './actions'; import { setTextBoxVariableOptionsFromUrl, updateTextBoxVariableOptions } from './actions';
import { getRootReducer } from '../state/helpers'; import { getRootReducer } from '../state/helpers';
import { TextBoxVariableModel, VariableHide, VariableOption } from '../../templating/types'; import { VariableOption } from '../../templating/types';
import { toVariablePayload } from '../state/types'; import { toVariablePayload } from '../state/types';
import { createTextBoxOptions } from './reducer'; import { createTextBoxOptions } from './reducer';
import { setCurrentVariableValue, addVariable } from '../state/sharedReducer'; import { addVariable, changeVariableProp, setCurrentVariableValue } from '../state/sharedReducer';
import { updateLocation } from 'app/core/actions'; import { updateLocation } from 'app/core/actions';
import { textboxBuilder } from '../shared/testing/builders';
describe('textbox actions', () => { describe('textbox actions', () => {
variableAdapters.setInit(() => [createTextBoxVariableAdapter()]); variableAdapters.setInit(() => [createTextBoxVariableAdapter()]);
...@@ -21,39 +22,45 @@ describe('textbox actions', () => { ...@@ -21,39 +22,45 @@ describe('textbox actions', () => {
selected: false, selected: false,
}; };
const variable: TextBoxVariableModel = { const variable = textboxBuilder()
type: 'textbox', .withId('textbox')
id: '0', .withName('textbox')
global: false, .withCurrent('A')
current: { .withQuery('A')
value: '', .build();
text: '',
selected: false,
},
options: [],
query: 'A',
name: 'textbox',
label: '',
hide: VariableHide.dontHide,
skipUrlSync: false,
index: 0,
};
const tester = await reduxTester<{ templating: TemplatingState }>() const tester = await reduxTester<{ templating: TemplatingState }>()
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenActionIsDispatched(addVariable(toVariablePayload(variable, { global: false, index: 0, model: variable }))) .whenActionIsDispatched(addVariable(toVariablePayload(variable, { global: false, index: 0, model: variable })))
.whenAsyncActionIsDispatched(updateTextBoxVariableOptions(toVariablePayload(variable)), true); .whenAsyncActionIsDispatched(updateTextBoxVariableOptions(toVariablePayload(variable)), true);
tester.thenDispatchedActionsPredicateShouldEqual(actions => { tester.thenDispatchedActionsShouldEqual(
const [createAction, setCurrentAction, locationAction] = actions; createTextBoxOptions(toVariablePayload(variable)),
const expectedNumberOfActions = 3; setCurrentVariableValue(toVariablePayload(variable, { option })),
updateLocation({ query: { 'var-textbox': 'A' } })
);
});
});
describe('when setTextBoxVariableOptionsFromUrl is dispatched', () => {
it('then correct actions are dispatched', async () => {
const urlValue = 'bB';
const variable = textboxBuilder()
.withId('textbox')
.withName('textbox')
.withCurrent('A')
.withQuery('A')
.build();
expect(createAction).toEqual(createTextBoxOptions(toVariablePayload(variable))); const tester = await reduxTester<{ templating: TemplatingState }>()
expect(setCurrentAction).toEqual(setCurrentVariableValue(toVariablePayload(variable, { option }))); .givenRootReducer(getRootReducer())
expect(locationAction).toEqual(updateLocation({ query: { 'var-textbox': 'A' } })); .whenActionIsDispatched(addVariable(toVariablePayload(variable, { global: false, index: 0, model: variable })))
.whenAsyncActionIsDispatched(setTextBoxVariableOptionsFromUrl(toVariablePayload(variable), urlValue), true);
return actions.length === expectedNumberOfActions; tester.thenDispatchedActionsShouldEqual(
}); changeVariableProp(toVariablePayload(variable, { propName: 'query', propValue: 'bB' })),
setCurrentVariableValue(toVariablePayload(variable, { option: { text: 'bB', value: 'bB', selected: false } }))
);
}); });
}); });
}); });
...@@ -3,12 +3,27 @@ import { ThunkResult } from '../../../types'; ...@@ -3,12 +3,27 @@ import { ThunkResult } from '../../../types';
import { getVariable } from '../state/selectors'; import { getVariable } from '../state/selectors';
import { variableAdapters } from '../adapters'; import { variableAdapters } from '../adapters';
import { createTextBoxOptions } from './reducer'; import { createTextBoxOptions } from './reducer';
import { toVariablePayload, VariableIdentifier } from '../state/types'; import { toVariableIdentifier, toVariablePayload, VariableIdentifier } from '../state/types';
import { setOptionFromUrl } from '../state/actions';
import { UrlQueryValue } from '@grafana/data';
import { changeVariableProp } from '../state/sharedReducer';
export const updateTextBoxVariableOptions = (identifier: VariableIdentifier): ThunkResult<void> => { export const updateTextBoxVariableOptions = (identifier: VariableIdentifier): ThunkResult<void> => {
return async (dispatch, getState) => { return async (dispatch, getState) => {
await dispatch(createTextBoxOptions(toVariablePayload(identifier))); await dispatch(createTextBoxOptions(toVariablePayload(identifier)));
const variableInState = getVariable<TextBoxVariableModel>(identifier.id!, getState()); const variableInState = getVariable<TextBoxVariableModel>(identifier.id!, getState());
await variableAdapters.get(identifier.type).setValue(variableInState, variableInState.options[0], true); await variableAdapters.get(identifier.type).setValue(variableInState, variableInState.options[0], true);
}; };
}; };
export const setTextBoxVariableOptionsFromUrl = (
identifier: VariableIdentifier,
urlValue: UrlQueryValue
): ThunkResult<void> => async (dispatch, getState) => {
const variableInState = getVariable<TextBoxVariableModel>(identifier.id!, getState());
dispatch(changeVariableProp(toVariablePayload(variableInState, { propName: 'query', propValue: urlValue })));
await dispatch(setOptionFromUrl(toVariableIdentifier(variableInState), urlValue));
};
...@@ -3,11 +3,11 @@ import cloneDeep from 'lodash/cloneDeep'; ...@@ -3,11 +3,11 @@ import cloneDeep from 'lodash/cloneDeep';
import { TextBoxVariableModel } from '../../templating/types'; import { TextBoxVariableModel } from '../../templating/types';
import { initialTextBoxVariableModelState, textBoxVariableReducer } from './reducer'; import { initialTextBoxVariableModelState, textBoxVariableReducer } from './reducer';
import { dispatch } from '../../../store/store'; import { dispatch } from '../../../store/store';
import { setOptionAsCurrent, setOptionFromUrl } from '../state/actions'; import { setOptionAsCurrent } from '../state/actions';
import { VariableAdapter } from '../adapters'; import { VariableAdapter } from '../adapters';
import { TextBoxVariablePicker } from './TextBoxVariablePicker'; import { TextBoxVariablePicker } from './TextBoxVariablePicker';
import { TextBoxVariableEditor } from './TextBoxVariableEditor'; import { TextBoxVariableEditor } from './TextBoxVariableEditor';
import { updateTextBoxVariableOptions } from './actions'; import { setTextBoxVariableOptionsFromUrl, updateTextBoxVariableOptions } from './actions';
import { toVariableIdentifier } from '../state/types'; import { toVariableIdentifier } from '../state/types';
export const createTextBoxVariableAdapter = (): VariableAdapter<TextBoxVariableModel> => { export const createTextBoxVariableAdapter = (): VariableAdapter<TextBoxVariableModel> => {
...@@ -26,7 +26,7 @@ export const createTextBoxVariableAdapter = (): VariableAdapter<TextBoxVariableM ...@@ -26,7 +26,7 @@ export const createTextBoxVariableAdapter = (): VariableAdapter<TextBoxVariableM
await dispatch(setOptionAsCurrent(toVariableIdentifier(variable), option, emitChanges)); await dispatch(setOptionAsCurrent(toVariableIdentifier(variable), option, emitChanges));
}, },
setValueFromUrl: async (variable, urlValue) => { setValueFromUrl: async (variable, urlValue) => {
await dispatch(setOptionFromUrl(toVariableIdentifier(variable), urlValue)); await dispatch(setTextBoxVariableOptionsFromUrl(toVariableIdentifier(variable), urlValue));
}, },
updateOptions: async variable => { updateOptions: async variable => {
await dispatch(updateTextBoxVariableOptions(toVariableIdentifier(variable))); await dispatch(updateTextBoxVariableOptions(toVariableIdentifier(variable)));
......
...@@ -25,10 +25,9 @@ export const textBoxVariableSlice = createSlice({ ...@@ -25,10 +25,9 @@ export const textBoxVariableSlice = createSlice({
reducers: { reducers: {
createTextBoxOptions: (state: VariablesState, action: PayloadAction<VariablePayload>) => { createTextBoxOptions: (state: VariablesState, action: PayloadAction<VariablePayload>) => {
const instanceState = getInstanceState<TextBoxVariableModel>(state, action.payload.id!); const instanceState = getInstanceState<TextBoxVariableModel>(state, action.payload.id!);
instanceState.options = [ const option = { text: instanceState.query.trim(), value: instanceState.query.trim(), selected: false };
{ text: instanceState.query.trim(), value: instanceState.query.trim(), selected: false }, instanceState.options = [option];
]; instanceState.current = option;
instanceState.current = instanceState.options[0];
}, },
}, },
}); });
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment