Commit 3c1f27b0 by Hugo Häggmark Committed by GitHub

Chore: reduce strict errors for variables (#31241)

* Chore: reduces a lot of variable errors

* Chore: reduces variable Editor errors

* Chore: reduces variable Picker errors

* Chore: reduce error count

* Chore: reduces errors for ChangeEvent instead of FormEvent

* Chore: reduces errors with CombinedState

* Chore: reduces ComponentType errors

* Chore: reduce errors in reducers

* Chore: reduces misc errors

* Chore: reduce AdhocPicker errors

* Chore: reduce error limit

* Update public/app/features/variables/adhoc/picker/AdHocFilterValue.tsx

Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>

* Chore: updates after PR comments

* Chore: small refactor

Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>
parent 6c4be296
...@@ -2,17 +2,7 @@ import { ComponentType } from 'react'; ...@@ -2,17 +2,7 @@ import { ComponentType } from 'react';
import { Reducer } from 'redux'; import { Reducer } from 'redux';
import { Registry, UrlQueryValue, VariableType } from '@grafana/data'; import { Registry, UrlQueryValue, VariableType } from '@grafana/data';
import { import { VariableModel, VariableOption } from './types';
AdHocVariableModel,
ConstantVariableModel,
CustomVariableModel,
DataSourceVariableModel,
IntervalVariableModel,
QueryVariableModel,
TextBoxVariableModel,
VariableModel,
VariableOption,
} from './types';
import { VariableEditorProps } from './editor/types'; import { VariableEditorProps } from './editor/types';
import { VariablesState } from './state/variablesReducer'; import { VariablesState } from './state/variablesReducer';
import { VariablePickerProps } from './pickers/types'; import { VariablePickerProps } from './pickers/types';
...@@ -36,22 +26,12 @@ export interface VariableAdapter<Model extends VariableModel> { ...@@ -36,22 +26,12 @@ export interface VariableAdapter<Model extends VariableModel> {
updateOptions: (variable: Model, searchFilter?: string) => Promise<void>; updateOptions: (variable: Model, searchFilter?: string) => Promise<void>;
getSaveModel: (variable: Model, saveCurrentAsDefault?: boolean) => Partial<Model>; getSaveModel: (variable: Model, saveCurrentAsDefault?: boolean) => Partial<Model>;
getValueForUrl: (variable: Model) => string | string[]; getValueForUrl: (variable: Model) => string | string[];
picker: ComponentType<VariablePickerProps>; picker: ComponentType<VariablePickerProps<Model>>;
editor: ComponentType<VariableEditorProps>; editor: ComponentType<VariableEditorProps<Model>>;
reducer: Reducer<VariablesState>; reducer: Reducer<VariablesState>;
beforeAdding?: (model: any) => any; beforeAdding?: (model: any) => any;
} }
export type VariableModels =
| QueryVariableModel
| CustomVariableModel
| TextBoxVariableModel
| ConstantVariableModel
| DataSourceVariableModel
| IntervalVariableModel
| AdHocVariableModel;
export type VariableTypeRegistry<Model extends VariableModel = VariableModel> = Registry<VariableAdapter<Model>>;
export const getDefaultVariableAdapters = () => [ export const getDefaultVariableAdapters = () => [
createQueryVariableAdapter(), createQueryVariableAdapter(),
createCustomVariableAdapter(), createCustomVariableAdapter(),
...@@ -63,4 +43,4 @@ export const getDefaultVariableAdapters = () => [ ...@@ -63,4 +43,4 @@ export const getDefaultVariableAdapters = () => [
createSystemVariableAdapter(), createSystemVariableAdapter(),
]; ];
export const variableAdapters: VariableTypeRegistry = new Registry<VariableAdapter<VariableModels>>(); export const variableAdapters = new Registry<VariableAdapter<any>>();
...@@ -3,8 +3,7 @@ import { DataSourcePluginMeta, DataSourceSelectItem } from '@grafana/data'; ...@@ -3,8 +3,7 @@ import { DataSourcePluginMeta, DataSourceSelectItem } from '@grafana/data';
import { variableAdapters } from '../adapters'; import { variableAdapters } from '../adapters';
import { createAdHocVariableAdapter } from './adapter'; import { createAdHocVariableAdapter } 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 { getRootReducer, RootReducerType } from '../state/helpers';
import { getRootReducer } from '../state/helpers';
import { toVariableIdentifier, toVariablePayload } from '../state/types'; import { toVariableIdentifier, toVariablePayload } from '../state/types';
import { import {
addFilter, addFilter,
...@@ -19,7 +18,6 @@ import { ...@@ -19,7 +18,6 @@ import {
import { filterAdded, filterRemoved, filtersRestored, filterUpdated } from './reducer'; import { filterAdded, filterRemoved, filtersRestored, filterUpdated } from './reducer';
import { addVariable, changeVariableProp } from '../state/sharedReducer'; import { addVariable, changeVariableProp } from '../state/sharedReducer';
import { updateLocation } from 'app/core/actions'; import { updateLocation } from 'app/core/actions';
import { DashboardState, LocationState } from 'app/types';
import { VariableModel } from 'app/features/variables/types'; import { VariableModel } from 'app/features/variables/types';
import { changeVariableEditorExtended, setIdInEditor } from '../editor/reducer'; import { changeVariableEditorExtended, setIdInEditor } from '../editor/reducer';
import { adHocBuilder } from '../shared/testing/builders'; import { adHocBuilder } from '../shared/testing/builders';
...@@ -34,12 +32,6 @@ jest.mock('app/features/plugins/datasource_srv', () => ({ ...@@ -34,12 +32,6 @@ jest.mock('app/features/plugins/datasource_srv', () => ({
})), })),
})); }));
type ReducersUsedInContext = {
templating: TemplatingState;
dashboard: DashboardState;
location: LocationState;
};
variableAdapters.setInit(() => [createAdHocVariableAdapter()]); variableAdapters.setInit(() => [createAdHocVariableAdapter()]);
describe('adhoc actions', () => { describe('adhoc actions', () => {
...@@ -66,7 +58,7 @@ describe('adhoc actions', () => { ...@@ -66,7 +58,7 @@ describe('adhoc actions', () => {
.withDatasource(options.datasource) .withDatasource(options.datasource)
.build(); .build();
const tester = await reduxTester<ReducersUsedInContext>() const tester = await reduxTester<RootReducerType>()
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenActionIsDispatched(createAddVariableAction(variable)) .whenActionIsDispatched(createAddVariableAction(variable))
.whenAsyncActionIsDispatched(applyFilterFromTable(options), true); .whenAsyncActionIsDispatched(applyFilterFromTable(options), true);
...@@ -90,7 +82,7 @@ describe('adhoc actions', () => { ...@@ -90,7 +82,7 @@ describe('adhoc actions', () => {
operator: '=', operator: '=',
}; };
const tester = await reduxTester<ReducersUsedInContext>() const tester = await reduxTester<RootReducerType>()
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenAsyncActionIsDispatched(applyFilterFromTable(options), true); .whenAsyncActionIsDispatched(applyFilterFromTable(options), true);
...@@ -123,7 +115,7 @@ describe('adhoc actions', () => { ...@@ -123,7 +115,7 @@ describe('adhoc actions', () => {
.withDatasource(options.datasource) .withDatasource(options.datasource)
.build(); .build();
const tester = await reduxTester<ReducersUsedInContext>() const tester = await reduxTester<RootReducerType>()
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenActionIsDispatched(createAddVariableAction(variable)) .whenActionIsDispatched(createAddVariableAction(variable))
.whenAsyncActionIsDispatched(applyFilterFromTable(options), true); .whenAsyncActionIsDispatched(applyFilterFromTable(options), true);
...@@ -155,7 +147,7 @@ describe('adhoc actions', () => { ...@@ -155,7 +147,7 @@ describe('adhoc actions', () => {
const variable = adHocBuilder().withId('Filters').withName('Filters').withDatasource(options.datasource).build(); const variable = adHocBuilder().withId('Filters').withName('Filters').withDatasource(options.datasource).build();
const tester = await reduxTester<ReducersUsedInContext>() const tester = await reduxTester<RootReducerType>()
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenActionIsDispatched(createAddVariableAction(existing)) .whenActionIsDispatched(createAddVariableAction(existing))
.whenAsyncActionIsDispatched(applyFilterFromTable(options), true); .whenAsyncActionIsDispatched(applyFilterFromTable(options), true);
...@@ -194,7 +186,7 @@ describe('adhoc actions', () => { ...@@ -194,7 +186,7 @@ describe('adhoc actions', () => {
const update = { index: 0, filter: updated }; const update = { index: 0, filter: updated };
const tester = await reduxTester<ReducersUsedInContext>() const tester = await reduxTester<RootReducerType>()
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenActionIsDispatched(createAddVariableAction(variable)) .whenActionIsDispatched(createAddVariableAction(variable))
.whenAsyncActionIsDispatched(changeFilter('elastic-filter', update), true); .whenAsyncActionIsDispatched(changeFilter('elastic-filter', update), true);
...@@ -230,7 +222,7 @@ describe('adhoc actions', () => { ...@@ -230,7 +222,7 @@ describe('adhoc actions', () => {
.withDatasource('elasticsearch') .withDatasource('elasticsearch')
.build(); .build();
const tester = await reduxTester<ReducersUsedInContext>() const tester = await reduxTester<RootReducerType>()
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenActionIsDispatched(createAddVariableAction(variable)) .whenActionIsDispatched(createAddVariableAction(variable))
.whenAsyncActionIsDispatched(addFilter('elastic-filter', adding), true); .whenAsyncActionIsDispatched(addFilter('elastic-filter', adding), true);
...@@ -261,7 +253,7 @@ describe('adhoc actions', () => { ...@@ -261,7 +253,7 @@ describe('adhoc actions', () => {
.withDatasource('elasticsearch') .withDatasource('elasticsearch')
.build(); .build();
const tester = await reduxTester<ReducersUsedInContext>() const tester = await reduxTester<RootReducerType>()
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenActionIsDispatched(createAddVariableAction(variable)) .whenActionIsDispatched(createAddVariableAction(variable))
.whenAsyncActionIsDispatched(addFilter('elastic-filter', adding), true); .whenAsyncActionIsDispatched(addFilter('elastic-filter', adding), true);
...@@ -284,7 +276,7 @@ describe('adhoc actions', () => { ...@@ -284,7 +276,7 @@ describe('adhoc actions', () => {
.withDatasource('elasticsearch') .withDatasource('elasticsearch')
.build(); .build();
const tester = await reduxTester<ReducersUsedInContext>() const tester = await reduxTester<RootReducerType>()
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenActionIsDispatched(createAddVariableAction(variable)) .whenActionIsDispatched(createAddVariableAction(variable))
.whenAsyncActionIsDispatched(removeFilter('elastic-filter', 0), true); .whenAsyncActionIsDispatched(removeFilter('elastic-filter', 0), true);
...@@ -314,7 +306,7 @@ describe('adhoc actions', () => { ...@@ -314,7 +306,7 @@ describe('adhoc actions', () => {
.withDatasource('elasticsearch') .withDatasource('elasticsearch')
.build(); .build();
const tester = await reduxTester<ReducersUsedInContext>() const tester = await reduxTester<RootReducerType>()
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenActionIsDispatched(createAddVariableAction(variable)) .whenActionIsDispatched(createAddVariableAction(variable))
.whenAsyncActionIsDispatched(removeFilter('elastic-filter', 0), true); .whenAsyncActionIsDispatched(removeFilter('elastic-filter', 0), true);
...@@ -349,7 +341,7 @@ describe('adhoc actions', () => { ...@@ -349,7 +341,7 @@ describe('adhoc actions', () => {
{ ...existing, name: 'value-2' }, { ...existing, name: 'value-2' },
]; ];
const tester = await reduxTester<ReducersUsedInContext>() const tester = await reduxTester<RootReducerType>()
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenActionIsDispatched(createAddVariableAction(variable)) .whenActionIsDispatched(createAddVariableAction(variable))
.whenAsyncActionIsDispatched(setFiltersFromUrl('elastic-filter', fromUrl), true); .whenAsyncActionIsDispatched(setFiltersFromUrl('elastic-filter', fromUrl), true);
...@@ -380,7 +372,7 @@ describe('adhoc actions', () => { ...@@ -380,7 +372,7 @@ describe('adhoc actions', () => {
getMetricSources.mockRestore(); getMetricSources.mockRestore();
getMetricSources.mockReturnValue(datasources); getMetricSources.mockReturnValue(datasources);
const tester = reduxTester<ReducersUsedInContext>() const tester = reduxTester<RootReducerType>()
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenActionIsDispatched(initAdHocVariableEditor()); .whenActionIsDispatched(initAdHocVariableEditor());
...@@ -406,7 +398,7 @@ describe('adhoc actions', () => { ...@@ -406,7 +398,7 @@ describe('adhoc actions', () => {
getDatasource.mockRestore(); getDatasource.mockRestore();
getDatasource.mockResolvedValue(null); getDatasource.mockResolvedValue(null);
const tester = await reduxTester<ReducersUsedInContext>() const tester = await reduxTester<RootReducerType>()
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenActionIsDispatched(createAddVariableAction(variable)) .whenActionIsDispatched(createAddVariableAction(variable))
.whenActionIsDispatched(setIdInEditor({ id: variable.id })) .whenActionIsDispatched(setIdInEditor({ id: variable.id }))
...@@ -434,7 +426,7 @@ describe('adhoc actions', () => { ...@@ -434,7 +426,7 @@ describe('adhoc actions', () => {
getTagKeys: () => {}, getTagKeys: () => {},
}); });
const tester = await reduxTester<ReducersUsedInContext>() const tester = await reduxTester<RootReducerType>()
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenActionIsDispatched(createAddVariableAction(variable)) .whenActionIsDispatched(createAddVariableAction(variable))
.whenActionIsDispatched(setIdInEditor({ id: variable.id })) .whenActionIsDispatched(setIdInEditor({ id: variable.id }))
......
...@@ -6,7 +6,7 @@ import { MetricFindValue, SelectableValue } from '@grafana/data'; ...@@ -6,7 +6,7 @@ import { MetricFindValue, SelectableValue } from '@grafana/data';
interface Props { interface Props {
datasource: string; datasource: string;
filterKey: string; filterKey: string;
filterValue: string | null; filterValue?: string;
onChange: (item: SelectableValue<string>) => void; onChange: (item: SelectableValue<string>) => void;
placeHolder?: string; placeHolder?: string;
} }
......
import React, { PureComponent, ReactNode } from 'react'; import React, { PureComponent, ReactNode } from 'react';
import { connect, MapDispatchToProps, MapStateToProps } from 'react-redux'; import { connect, ConnectedProps } from 'react-redux';
import { StoreState } from 'app/types';
import { AdHocVariableFilter, AdHocVariableModel } from 'app/features/variables/types'; import { AdHocVariableFilter, AdHocVariableModel } from 'app/features/variables/types';
import { VariablePickerProps } from '../../pickers/types'; import { VariablePickerProps } from '../../pickers/types';
import { SelectableValue } from '@grafana/data'; import { SelectableValue } from '@grafana/data';
...@@ -10,20 +9,20 @@ import { addFilter, changeFilter, removeFilter } from '../actions'; ...@@ -10,20 +9,20 @@ import { addFilter, changeFilter, removeFilter } from '../actions';
import { REMOVE_FILTER_KEY } from './AdHocFilterKey'; import { REMOVE_FILTER_KEY } from './AdHocFilterKey';
import { AdHocFilterRenderer } from './AdHocFilterRenderer'; import { AdHocFilterRenderer } from './AdHocFilterRenderer';
interface OwnProps extends VariablePickerProps<AdHocVariableModel> {} const mapDispatchToProps = {
addFilter,
removeFilter,
changeFilter,
};
interface ConnectedProps {} const connector = connect(null, mapDispatchToProps);
interface DispatchProps { interface OwnProps extends VariablePickerProps<AdHocVariableModel> {}
addFilter: typeof addFilter;
removeFilter: typeof removeFilter;
changeFilter: typeof changeFilter;
}
type Props = OwnProps & ConnectedProps & DispatchProps; type Props = OwnProps & ConnectedProps<typeof connector>;
export class AdHocPickerUnconnected extends PureComponent<Props> { export class AdHocPickerUnconnected extends PureComponent<Props> {
onChange = (index: number, prop: string) => (key: SelectableValue<string>) => { onChange = (index: number, prop: string) => (key: SelectableValue<string | null>) => {
const { id, filters } = this.props.variable; const { id, filters } = this.props.variable;
const { value } = key; const { value } = key;
...@@ -85,13 +84,5 @@ export class AdHocPickerUnconnected extends PureComponent<Props> { ...@@ -85,13 +84,5 @@ export class AdHocPickerUnconnected extends PureComponent<Props> {
} }
} }
const mapDispatchToProps: MapDispatchToProps<DispatchProps, OwnProps> = { export const AdHocPicker = connector(AdHocPickerUnconnected);
addFilter,
removeFilter,
changeFilter,
};
const mapStateToProps: MapStateToProps<ConnectedProps, OwnProps, StoreState> = (state) => ({});
export const AdHocPicker = connect(mapStateToProps, mapDispatchToProps)(AdHocPickerUnconnected);
AdHocPicker.displayName = 'AdHocPicker'; AdHocPicker.displayName = 'AdHocPicker';
import React, { ChangeEvent, FocusEvent, PureComponent } from 'react'; import React, { FormEvent, PureComponent } from 'react';
import { selectors } from '@grafana/e2e-selectors'; import { selectors } from '@grafana/e2e-selectors';
import { VerticalGroup } from '@grafana/ui'; import { VerticalGroup } from '@grafana/ui';
...@@ -10,17 +10,17 @@ import { VariableTextField } from '../editor/VariableTextField'; ...@@ -10,17 +10,17 @@ import { VariableTextField } from '../editor/VariableTextField';
export interface Props extends VariableEditorProps<ConstantVariableModel> {} export interface Props extends VariableEditorProps<ConstantVariableModel> {}
export class ConstantVariableEditor extends PureComponent<Props> { export class ConstantVariableEditor extends PureComponent<Props> {
onChange = (event: ChangeEvent<HTMLInputElement>) => { onChange = (event: FormEvent<HTMLInputElement>) => {
this.props.onPropChange({ this.props.onPropChange({
propName: 'query', propName: 'query',
propValue: event.target.value, propValue: event.currentTarget.value,
}); });
}; };
onBlur = (event: FocusEvent<HTMLInputElement>) => { onBlur = (event: FormEvent<HTMLInputElement>) => {
this.props.onPropChange({ this.props.onPropChange({
propName: 'query', propName: 'query',
propValue: event.target.value, propValue: event.currentTarget.value,
updateOptions: true, updateOptions: true,
}); });
}; };
......
import { variableAdapters } from '../adapters'; import { variableAdapters } from '../adapters';
import { createConstantVariableAdapter } from './adapter'; import { createConstantVariableAdapter } 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 { updateConstantVariableOptions } from './actions'; import { updateConstantVariableOptions } from './actions';
import { getRootReducer } from '../state/helpers'; import { getRootReducer, RootReducerType } from '../state/helpers';
import { ConstantVariableModel, initialVariableModelState, VariableOption } from '../types'; import { ConstantVariableModel, initialVariableModelState, VariableOption } from '../types';
import { toVariablePayload } from '../state/types'; import { toVariablePayload } from '../state/types';
import { createConstantOptionsFromQuery } from './reducer'; import { createConstantOptionsFromQuery } from './reducer';
...@@ -35,19 +34,15 @@ describe('constant actions', () => { ...@@ -35,19 +34,15 @@ describe('constant actions', () => {
query: 'A', query: 'A',
}; };
const tester = await reduxTester<{ templating: TemplatingState }>() const tester = await reduxTester<RootReducerType>()
.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(updateConstantVariableOptions(toVariablePayload(variable)), true); .whenAsyncActionIsDispatched(updateConstantVariableOptions(toVariablePayload(variable)), true);
tester.thenDispatchedActionsPredicateShouldEqual((actions) => { tester.thenDispatchedActionsShouldEqual(
const [createAction, setCurrentAction] = actions; createConstantOptionsFromQuery(toVariablePayload(variable)),
const expectedNumberOfActions = 2; setCurrentVariableValue(toVariablePayload(variable, { option }))
);
expect(createAction).toEqual(createConstantOptionsFromQuery(toVariablePayload(variable)));
expect(setCurrentAction).toEqual(setCurrentVariableValue(toVariablePayload(variable, { option })));
return actions.length === expectedNumberOfActions;
});
}); });
}); });
}); });
...@@ -4,10 +4,10 @@ import { dispatch } from '../../../store/store'; ...@@ -4,10 +4,10 @@ import { dispatch } from '../../../store/store';
import { setOptionAsCurrent, setOptionFromUrl } from '../state/actions'; import { setOptionAsCurrent, setOptionFromUrl } from '../state/actions';
import { VariableAdapter } from '../adapters'; import { VariableAdapter } from '../adapters';
import { constantVariableReducer, initialConstantVariableModelState } from './reducer'; import { constantVariableReducer, initialConstantVariableModelState } from './reducer';
import { OptionsPicker } from '../pickers';
import { ConstantVariableEditor } from './ConstantVariableEditor'; import { ConstantVariableEditor } from './ConstantVariableEditor';
import { updateConstantVariableOptions } from './actions'; import { updateConstantVariableOptions } from './actions';
import { toVariableIdentifier } from '../state/types'; import { toVariableIdentifier } from '../state/types';
import { optionPickerFactory } from '../pickers';
export const createConstantVariableAdapter = (): VariableAdapter<ConstantVariableModel> => { export const createConstantVariableAdapter = (): VariableAdapter<ConstantVariableModel> => {
return { return {
...@@ -16,7 +16,7 @@ export const createConstantVariableAdapter = (): VariableAdapter<ConstantVariabl ...@@ -16,7 +16,7 @@ export const createConstantVariableAdapter = (): VariableAdapter<ConstantVariabl
name: 'Constant', name: 'Constant',
initialState: initialConstantVariableModelState, initialState: initialConstantVariableModelState,
reducer: constantVariableReducer, reducer: constantVariableReducer,
picker: OptionsPicker, picker: optionPickerFactory<ConstantVariableModel>(),
editor: ConstantVariableEditor, editor: ConstantVariableEditor,
dependsOn: () => { dependsOn: () => {
return false; return false;
......
import React, { ChangeEvent, FocusEvent, PureComponent } from 'react'; import React, { FormEvent, PureComponent } from 'react';
import { CustomVariableModel, VariableWithMultiSupport } from '../types'; import { CustomVariableModel, VariableWithMultiSupport } from '../types';
import { SelectionOptionsEditor } from '../editor/SelectionOptionsEditor'; import { SelectionOptionsEditor } from '../editor/SelectionOptionsEditor';
import { OnPropChangeArguments, VariableEditorProps } from '../editor/types'; import { OnPropChangeArguments, VariableEditorProps } from '../editor/types';
...@@ -21,10 +21,10 @@ interface DispatchProps { ...@@ -21,10 +21,10 @@ interface DispatchProps {
export type Props = OwnProps & ConnectedProps & DispatchProps; export type Props = OwnProps & ConnectedProps & DispatchProps;
class CustomVariableEditorUnconnected extends PureComponent<Props> { class CustomVariableEditorUnconnected extends PureComponent<Props> {
onChange = (event: ChangeEvent<HTMLTextAreaElement>) => { onChange = (event: FormEvent<HTMLTextAreaElement>) => {
this.props.onPropChange({ this.props.onPropChange({
propName: 'query', propName: 'query',
propValue: event.target.value, propValue: event.currentTarget.value,
}); });
}; };
...@@ -32,10 +32,10 @@ class CustomVariableEditorUnconnected extends PureComponent<Props> { ...@@ -32,10 +32,10 @@ class CustomVariableEditorUnconnected extends PureComponent<Props> {
this.props.onPropChange({ propName, propValue, updateOptions: true }); this.props.onPropChange({ propName, propValue, updateOptions: true });
}; };
onBlur = (event: FocusEvent<HTMLTextAreaElement>) => { onBlur = (event: FormEvent<HTMLTextAreaElement>) => {
this.props.onPropChange({ this.props.onPropChange({
propName: 'query', propName: 'query',
propValue: event.target.value, propValue: event.currentTarget.value,
updateOptions: true, updateOptions: true,
}); });
}; };
......
...@@ -2,11 +2,10 @@ import { variableAdapters } from '../adapters'; ...@@ -2,11 +2,10 @@ import { variableAdapters } from '../adapters';
import { updateCustomVariableOptions } from './actions'; import { updateCustomVariableOptions } from './actions';
import { createCustomVariableAdapter } from './adapter'; import { createCustomVariableAdapter } from './adapter';
import { reduxTester } from '../../../../test/core/redux/reduxTester'; import { reduxTester } from '../../../../test/core/redux/reduxTester';
import { getRootReducer } from '../state/helpers'; import { getRootReducer, RootReducerType } from '../state/helpers';
import { CustomVariableModel, initialVariableModelState, VariableOption } from '../types'; import { CustomVariableModel, initialVariableModelState, VariableOption } from '../types';
import { toVariablePayload } from '../state/types'; import { toVariablePayload } from '../state/types';
import { addVariable, setCurrentVariableValue } from '../state/sharedReducer'; import { addVariable, setCurrentVariableValue } from '../state/sharedReducer';
import { TemplatingState } from '../state/reducers';
import { createCustomOptionsFromQuery } from './reducer'; import { createCustomOptionsFromQuery } from './reducer';
describe('custom actions', () => { describe('custom actions', () => {
...@@ -48,19 +47,15 @@ describe('custom actions', () => { ...@@ -48,19 +47,15 @@ describe('custom actions', () => {
includeAll: false, includeAll: false,
}; };
const tester = await reduxTester<{ templating: TemplatingState }>() const tester = await reduxTester<RootReducerType>()
.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(updateCustomVariableOptions(toVariablePayload(variable)), true); .whenAsyncActionIsDispatched(updateCustomVariableOptions(toVariablePayload(variable)), true);
tester.thenDispatchedActionsPredicateShouldEqual((actions) => { tester.thenDispatchedActionsShouldEqual(
const [createAction, setCurrentAction] = actions; createCustomOptionsFromQuery(toVariablePayload(variable)),
const expectedNumberOfActions = 2; setCurrentVariableValue(toVariablePayload(variable, { option }))
);
expect(createAction).toEqual(createCustomOptionsFromQuery(toVariablePayload(variable)));
expect(setCurrentAction).toEqual(setCurrentVariableValue(toVariablePayload(variable, { option })));
return actions.length === expectedNumberOfActions;
});
}); });
}); });
}); });
...@@ -4,11 +4,11 @@ import { dispatch } from '../../../store/store'; ...@@ -4,11 +4,11 @@ import { dispatch } from '../../../store/store';
import { setOptionAsCurrent, setOptionFromUrl } from '../state/actions'; import { setOptionAsCurrent, setOptionFromUrl } from '../state/actions';
import { VariableAdapter } from '../adapters'; import { VariableAdapter } from '../adapters';
import { customVariableReducer, initialCustomVariableModelState } from './reducer'; import { customVariableReducer, initialCustomVariableModelState } from './reducer';
import { OptionsPicker } from '../pickers';
import { CustomVariableEditor } from './CustomVariableEditor'; import { CustomVariableEditor } from './CustomVariableEditor';
import { updateCustomVariableOptions } from './actions'; import { updateCustomVariableOptions } from './actions';
import { ALL_VARIABLE_TEXT, toVariableIdentifier } from '../state/types'; import { ALL_VARIABLE_TEXT, toVariableIdentifier } from '../state/types';
import { isAllVariable } from '../utils'; import { isAllVariable } from '../utils';
import { optionPickerFactory } from '../pickers';
export const createCustomVariableAdapter = (): VariableAdapter<CustomVariableModel> => { export const createCustomVariableAdapter = (): VariableAdapter<CustomVariableModel> => {
return { return {
...@@ -17,7 +17,7 @@ export const createCustomVariableAdapter = (): VariableAdapter<CustomVariableMod ...@@ -17,7 +17,7 @@ export const createCustomVariableAdapter = (): VariableAdapter<CustomVariableMod
name: 'Custom', name: 'Custom',
initialState: initialCustomVariableModelState, initialState: initialCustomVariableModelState,
reducer: customVariableReducer, reducer: customVariableReducer,
picker: OptionsPicker, picker: optionPickerFactory<CustomVariableModel>(),
editor: CustomVariableEditor, editor: CustomVariableEditor,
dependsOn: () => { dependsOn: () => {
return false; return false;
......
import React, { ChangeEvent, FocusEvent, PureComponent } from 'react'; import React, { FormEvent, PureComponent } from 'react';
import { MapDispatchToProps, MapStateToProps } from 'react-redux'; import { MapDispatchToProps, MapStateToProps } from 'react-redux';
import { InlineFieldRow, VerticalGroup } from '@grafana/ui'; import { InlineFieldRow, VerticalGroup } from '@grafana/ui';
...@@ -34,17 +34,17 @@ export class DataSourceVariableEditorUnConnected extends PureComponent<Props> { ...@@ -34,17 +34,17 @@ export class DataSourceVariableEditorUnConnected extends PureComponent<Props> {
this.props.initDataSourceVariableEditor(); this.props.initDataSourceVariableEditor();
} }
onRegExChange = (event: ChangeEvent<HTMLInputElement>) => { onRegExChange = (event: FormEvent<HTMLInputElement>) => {
this.props.onPropChange({ this.props.onPropChange({
propName: 'regex', propName: 'regex',
propValue: event.target.value, propValue: event.currentTarget.value,
}); });
}; };
onRegExBlur = (event: FocusEvent<HTMLInputElement>) => { onRegExBlur = (event: FormEvent<HTMLInputElement>) => {
this.props.onPropChange({ this.props.onPropChange({
propName: 'regex', propName: 'regex',
propValue: event.target.value, propValue: event.currentTarget.value,
updateOptions: true, updateOptions: true,
}); });
}; };
......
import { DataSourceInstanceSettings } from '@grafana/data'; import { DataSourceInstanceSettings } from '@grafana/data';
import { reduxTester } from '../../../../test/core/redux/reduxTester'; import { reduxTester } from '../../../../test/core/redux/reduxTester';
import { TemplatingState } from '../state/reducers'; import { getRootReducer, RootReducerType } from '../state/helpers';
import { getRootReducer } from '../state/helpers';
import { toVariableIdentifier, toVariablePayload } from '../state/types'; import { toVariableIdentifier, toVariablePayload } from '../state/types';
import { variableAdapters } from '../adapters'; import { variableAdapters } from '../adapters';
import { createDataSourceVariableAdapter } from './adapter'; import { createDataSourceVariableAdapter } from './adapter';
...@@ -49,7 +48,7 @@ describe('data source actions', () => { ...@@ -49,7 +48,7 @@ describe('data source actions', () => {
query: 'mock-data-id', query: 'mock-data-id',
}); });
const tester = await reduxTester<{ templating: TemplatingState }>() const tester = await reduxTester<RootReducerType>()
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenActionIsDispatched( .whenActionIsDispatched(
addVariable(toVariablePayload(datasource, { global: false, index: 0, model: datasource })) addVariable(toVariablePayload(datasource, { global: false, index: 0, model: datasource }))
...@@ -97,7 +96,7 @@ describe('data source actions', () => { ...@@ -97,7 +96,7 @@ describe('data source actions', () => {
regex: '/.*(second-name).*/', regex: '/.*(second-name).*/',
}); });
const tester = await reduxTester<{ templating: TemplatingState }>() const tester = await reduxTester<RootReducerType>()
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenActionIsDispatched( .whenActionIsDispatched(
addVariable(toVariablePayload(datasource, { global: false, index: 0, model: datasource })) addVariable(toVariablePayload(datasource, { global: false, index: 0, model: datasource }))
...@@ -142,7 +141,7 @@ describe('data source actions', () => { ...@@ -142,7 +141,7 @@ describe('data source actions', () => {
const { dependencies, getListMock, getDatasourceSrvMock } = getTestContext({ sources }); const { dependencies, getListMock, getDatasourceSrvMock } = getTestContext({ sources });
await reduxTester<{ templating: TemplatingState }>() await reduxTester<RootReducerType>()
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenActionIsDispatched(initDataSourceVariableEditor(dependencies)) .whenActionIsDispatched(initDataSourceVariableEditor(dependencies))
.thenDispatchedActionsShouldEqual( .thenDispatchedActionsShouldEqual(
......
...@@ -4,11 +4,11 @@ import { dispatch } from '../../../store/store'; ...@@ -4,11 +4,11 @@ import { dispatch } from '../../../store/store';
import { setOptionAsCurrent, setOptionFromUrl } from '../state/actions'; import { setOptionAsCurrent, setOptionFromUrl } from '../state/actions';
import { VariableAdapter } from '../adapters'; import { VariableAdapter } from '../adapters';
import { dataSourceVariableReducer, initialDataSourceVariableModelState } from './reducer'; import { dataSourceVariableReducer, initialDataSourceVariableModelState } from './reducer';
import { OptionsPicker } from '../pickers';
import { ALL_VARIABLE_TEXT, toVariableIdentifier } from '../state/types'; import { ALL_VARIABLE_TEXT, toVariableIdentifier } from '../state/types';
import { DataSourceVariableEditor } from './DataSourceVariableEditor'; import { DataSourceVariableEditor } from './DataSourceVariableEditor';
import { updateDataSourceVariableOptions } from './actions'; import { updateDataSourceVariableOptions } from './actions';
import { containsVariable, isAllVariable } from '../utils'; import { containsVariable, isAllVariable } from '../utils';
import { optionPickerFactory } from '../pickers';
export const createDataSourceVariableAdapter = (): VariableAdapter<DataSourceVariableModel> => { export const createDataSourceVariableAdapter = (): VariableAdapter<DataSourceVariableModel> => {
return { return {
...@@ -17,7 +17,7 @@ export const createDataSourceVariableAdapter = (): VariableAdapter<DataSourceVar ...@@ -17,7 +17,7 @@ export const createDataSourceVariableAdapter = (): VariableAdapter<DataSourceVar
name: 'Datasource', name: 'Datasource',
initialState: initialDataSourceVariableModelState, initialState: initialDataSourceVariableModelState,
reducer: dataSourceVariableReducer, reducer: dataSourceVariableReducer,
picker: OptionsPicker, picker: optionPickerFactory<DataSourceVariableModel>(),
editor: DataSourceVariableEditor, editor: DataSourceVariableEditor,
dependsOn: (variable, variableToTest) => { dependsOn: (variable, variableToTest) => {
if (variable.regex) { if (variable.regex) {
......
import React, { FunctionComponent, useCallback } from 'react'; import React, { ChangeEvent, FormEvent, FunctionComponent, useCallback } from 'react';
import { InlineFieldRow, VerticalGroup } from '@grafana/ui'; import { InlineFieldRow, VerticalGroup } from '@grafana/ui';
import { selectors } from '@grafana/e2e-selectors'; import { selectors } from '@grafana/e2e-selectors';
...@@ -16,22 +16,22 @@ export interface SelectionOptionsEditorProps<Model extends VariableWithMultiSupp ...@@ -16,22 +16,22 @@ export interface SelectionOptionsEditorProps<Model extends VariableWithMultiSupp
export const SelectionOptionsEditor: FunctionComponent<SelectionOptionsEditorProps> = (props) => { export const SelectionOptionsEditor: FunctionComponent<SelectionOptionsEditorProps> = (props) => {
const onMultiChanged = useCallback( const onMultiChanged = useCallback(
(event: React.ChangeEvent<HTMLInputElement>) => { (event: ChangeEvent<HTMLInputElement>) => {
props.onMultiChanged(toVariableIdentifier(props.variable), event.target.checked); props.onMultiChanged(toVariableIdentifier(props.variable), event.target.checked);
}, },
[props.onMultiChanged, props.variable] [props.onMultiChanged, props.variable]
); );
const onIncludeAllChanged = useCallback( const onIncludeAllChanged = useCallback(
(event: React.ChangeEvent<HTMLInputElement>) => { (event: ChangeEvent<HTMLInputElement>) => {
props.onPropChange({ propName: 'includeAll', propValue: event.target.checked }); props.onPropChange({ propName: 'includeAll', propValue: event.target.checked });
}, },
[props.onPropChange] [props.onPropChange]
); );
const onAllValueChanged = useCallback( const onAllValueChanged = useCallback(
(event: React.ChangeEvent<HTMLInputElement>) => { (event: FormEvent<HTMLInputElement>) => {
props.onPropChange({ propName: 'allValue', propValue: event.target.value }); props.onPropChange({ propName: 'allValue', propValue: event.currentTarget.value });
}, },
[props.onPropChange] [props.onPropChange]
); );
......
...@@ -5,34 +5,34 @@ import { selectors } from '@grafana/e2e-selectors'; ...@@ -5,34 +5,34 @@ import { selectors } from '@grafana/e2e-selectors';
import { toVariableIdentifier, toVariablePayload, VariableIdentifier } from '../state/types'; import { toVariableIdentifier, toVariablePayload, VariableIdentifier } from '../state/types';
import { StoreState } from '../../../types'; import { StoreState } from '../../../types';
import { VariableEditorEditor } from './VariableEditorEditor'; import { VariableEditorEditor } from './VariableEditorEditor';
import { connect, MapStateToProps, MapDispatchToProps } from 'react-redux'; import { connect, ConnectedProps } from 'react-redux';
import { getEditorVariables } from '../state/selectors'; import { getEditorVariables } from '../state/selectors';
import { VariableModel } from '../types';
import { switchToEditMode, switchToListMode, switchToNewMode } from './actions'; import { switchToEditMode, switchToListMode, switchToNewMode } from './actions';
import { changeVariableOrder, duplicateVariable, removeVariable } from '../state/sharedReducer'; import { changeVariableOrder, duplicateVariable, removeVariable } from '../state/sharedReducer';
import { VariableEditorList } from './VariableEditorList'; import { VariableEditorList } from './VariableEditorList';
import { DashboardModel } from '../../dashboard/state';
import { VariablesUnknownTable } from '../inspect/VariablesUnknownTable'; import { VariablesUnknownTable } from '../inspect/VariablesUnknownTable';
import { VariablesDependenciesButton } from '../inspect/VariablesDependenciesButton'; import { VariablesDependenciesButton } from '../inspect/VariablesDependenciesButton';
interface OwnProps {} const mapStateToProps = (state: StoreState) => ({
variables: getEditorVariables(state),
idInEditor: state.templating.editor.id,
dashboard: state.dashboard.getModel(),
});
interface ConnectedProps { const mapDispatchToProps = {
idInEditor: string | null; changeVariableOrder,
variables: VariableModel[]; duplicateVariable,
dashboard: DashboardModel | null; removeVariable,
} switchToNewMode,
switchToEditMode,
switchToListMode,
};
interface DispatchProps { interface OwnProps {}
changeVariableOrder: typeof changeVariableOrder;
duplicateVariable: typeof duplicateVariable;
removeVariable: typeof removeVariable;
switchToNewMode: typeof switchToNewMode;
switchToEditMode: typeof switchToEditMode;
switchToListMode: typeof switchToListMode;
}
type Props = OwnProps & ConnectedProps & DispatchProps; const connector = connect(mapStateToProps, mapDispatchToProps);
type Props = OwnProps & ConnectedProps<typeof connector>;
class VariableEditorContainerUnconnected extends PureComponent<Props> { class VariableEditorContainerUnconnected extends PureComponent<Props> {
componentDidMount(): void { componentDidMount(): void {
...@@ -48,7 +48,7 @@ class VariableEditorContainerUnconnected extends PureComponent<Props> { ...@@ -48,7 +48,7 @@ class VariableEditorContainerUnconnected extends PureComponent<Props> {
this.props.switchToEditMode(identifier); this.props.switchToEditMode(identifier);
}; };
onNewVariable = (event: MouseEvent<HTMLAnchorElement>) => { onNewVariable = (event: MouseEvent) => {
event.preventDefault(); event.preventDefault();
this.props.switchToNewMode(); this.props.switchToNewMode();
}; };
...@@ -124,19 +124,4 @@ class VariableEditorContainerUnconnected extends PureComponent<Props> { ...@@ -124,19 +124,4 @@ class VariableEditorContainerUnconnected extends PureComponent<Props> {
} }
} }
const mapStateToProps: MapStateToProps<ConnectedProps, OwnProps, StoreState> = (state) => ({ export const VariableEditorContainer = connector(VariableEditorContainerUnconnected);
variables: getEditorVariables(state),
idInEditor: state.templating.editor.id,
dashboard: state.dashboard.getModel(),
});
const mapDispatchToProps: MapDispatchToProps<DispatchProps, OwnProps> = {
changeVariableOrder,
duplicateVariable,
removeVariable,
switchToNewMode,
switchToEditMode,
switchToListMode,
};
export const VariableEditorContainer = connect(mapStateToProps, mapDispatchToProps)(VariableEditorContainerUnconnected);
import React, { ChangeEvent, FormEvent, PureComponent } from 'react'; import React, { FormEvent, PureComponent } from 'react';
import isEqual from 'lodash/isEqual'; import isEqual from 'lodash/isEqual';
import { AppEvents, LoadingState, SelectableValue, VariableType } from '@grafana/data'; import { AppEvents, LoadingState, SelectableValue, VariableType } from '@grafana/data';
import { Button, Icon, InlineFieldRow, VerticalGroup } from '@grafana/ui'; import { Button, Icon, InlineFieldRow, VerticalGroup } from '@grafana/ui';
...@@ -62,9 +62,9 @@ export class VariableEditorEditorUnConnected extends PureComponent<Props> { ...@@ -62,9 +62,9 @@ export class VariableEditorEditorUnConnected extends PureComponent<Props> {
this.props.variableEditorUnMount(this.props.identifier); this.props.variableEditorUnMount(this.props.identifier);
} }
onNameChange = (event: ChangeEvent<HTMLInputElement>) => { onNameChange = (event: FormEvent<HTMLInputElement>) => {
event.preventDefault(); event.preventDefault();
this.props.changeVariableName(this.props.identifier, event.target.value); this.props.changeVariableName(this.props.identifier, event.currentTarget.value);
}; };
onTypeChange = (option: SelectableValue<VariableType>) => { onTypeChange = (option: SelectableValue<VariableType>) => {
...@@ -74,16 +74,16 @@ export class VariableEditorEditorUnConnected extends PureComponent<Props> { ...@@ -74,16 +74,16 @@ export class VariableEditorEditorUnConnected extends PureComponent<Props> {
this.props.changeVariableType(toVariablePayload(this.props.identifier, { newType: option.value })); this.props.changeVariableType(toVariablePayload(this.props.identifier, { newType: option.value }));
}; };
onLabelChange = (event: ChangeEvent<HTMLInputElement>) => { onLabelChange = (event: FormEvent<HTMLInputElement>) => {
event.preventDefault(); event.preventDefault();
this.props.changeVariableProp( this.props.changeVariableProp(
toVariablePayload(this.props.identifier, { propName: 'label', propValue: event.target.value }) toVariablePayload(this.props.identifier, { propName: 'label', propValue: event.currentTarget.value })
); );
}; };
onDescriptionChange = (event: ChangeEvent<HTMLInputElement>) => { onDescriptionChange = (event: FormEvent<HTMLInputElement>) => {
this.props.changeVariableProp( this.props.changeVariableProp(
toVariablePayload(this.props.identifier, { propName: 'description', propValue: event.target.value }) toVariablePayload(this.props.identifier, { propName: 'description', propValue: event.currentTarget.value })
); );
}; };
......
...@@ -15,7 +15,7 @@ import { VariableUsagesButton } from '../inspect/VariableUsagesButton'; ...@@ -15,7 +15,7 @@ import { VariableUsagesButton } from '../inspect/VariableUsagesButton';
export interface Props { export interface Props {
variables: VariableModel[]; variables: VariableModel[];
dashboard: DashboardModel | null; dashboard: DashboardModel | null;
onAddClick: (event: MouseEvent<HTMLAnchorElement>) => void; onAddClick: (event: MouseEvent) => void;
onEditClick: (identifier: VariableIdentifier) => void; onEditClick: (identifier: VariableIdentifier) => void;
onChangeVariableOrder: (identifier: VariableIdentifier, fromIndex: number, toIndex: number) => void; onChangeVariableOrder: (identifier: VariableIdentifier, fromIndex: number, toIndex: number) => void;
onDuplicateVariable: (identifier: VariableIdentifier) => void; onDuplicateVariable: (identifier: VariableIdentifier) => void;
......
...@@ -176,7 +176,7 @@ export function isQueryEditor< ...@@ -176,7 +176,7 @@ export function isQueryEditor<
>( >(
component: VariableQueryEditorType, component: VariableQueryEditorType,
datasource: DataSourceApi<TQuery, TOptions> datasource: DataSourceApi<TQuery, TOptions>
): component is ComponentType<QueryEditorProps<any>> { ): component is ComponentType<QueryEditorProps<DataSourceApi<TQuery, TOptions>, TQuery, TOptions, any>> {
if (!component) { if (!component) {
return false; return false;
} }
......
import React, { ChangeEvent, FocusEvent, PureComponent } from 'react'; import React, { ChangeEvent, FormEvent, PureComponent } from 'react';
import { InlineFieldRow, VerticalGroup } from '@grafana/ui'; import { InlineFieldRow, VerticalGroup } from '@grafana/ui';
import { IntervalVariableModel } from '../types'; import { IntervalVariableModel } from '../types';
...@@ -20,17 +20,17 @@ export class IntervalVariableEditor extends PureComponent<Props> { ...@@ -20,17 +20,17 @@ export class IntervalVariableEditor extends PureComponent<Props> {
}); });
}; };
onQueryChanged = (event: ChangeEvent<HTMLInputElement>) => { onQueryChanged = (event: FormEvent<HTMLInputElement>) => {
this.props.onPropChange({ this.props.onPropChange({
propName: 'query', propName: 'query',
propValue: event.target.value, propValue: event.currentTarget.value,
}); });
}; };
onQueryBlur = (event: FocusEvent<HTMLInputElement>) => { onQueryBlur = (event: FormEvent<HTMLInputElement>) => {
this.props.onPropChange({ this.props.onPropChange({
propName: 'query', propName: 'query',
propValue: event.target.value, propValue: event.currentTarget.value,
updateOptions: true, updateOptions: true,
}); });
}; };
...@@ -43,10 +43,10 @@ export class IntervalVariableEditor extends PureComponent<Props> { ...@@ -43,10 +43,10 @@ export class IntervalVariableEditor extends PureComponent<Props> {
}); });
}; };
onAutoMinChanged = (event: ChangeEvent<HTMLInputElement>) => { onAutoMinChanged = (event: FormEvent<HTMLInputElement>) => {
this.props.onPropChange({ this.props.onPropChange({
propName: 'auto_min', propName: 'auto_min',
propValue: event.target.value, propValue: event.currentTarget.value,
updateOptions: true, updateOptions: true,
}); });
}; };
......
import { getRootReducer } from '../state/helpers'; import { getRootReducer, RootReducerType } from '../state/helpers';
import { reduxTester } from '../../../../test/core/redux/reduxTester'; import { reduxTester } from '../../../../test/core/redux/reduxTester';
import { TemplatingState } from '../state/reducers';
import { toVariableIdentifier, toVariablePayload } from '../state/types'; import { toVariableIdentifier, toVariablePayload } from '../state/types';
import { updateAutoValue, UpdateAutoValueDependencies, updateIntervalVariableOptions } from './actions'; import { updateAutoValue, UpdateAutoValueDependencies, updateIntervalVariableOptions } from './actions';
import { createIntervalOptions } from './reducer'; import { createIntervalOptions } from './reducer';
...@@ -26,7 +25,7 @@ describe('interval actions', () => { ...@@ -26,7 +25,7 @@ describe('interval actions', () => {
it('then correct actions are dispatched', async () => { it('then correct actions are dispatched', async () => {
const interval = intervalBuilder().withId('0').withQuery('1s,1m,1h,1d').withAuto(false).build(); const interval = intervalBuilder().withId('0').withQuery('1s,1m,1h,1d').withAuto(false).build();
const tester = await reduxTester<{ templating: TemplatingState }>() const tester = await reduxTester<RootReducerType>()
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenActionIsDispatched(addVariable(toVariablePayload(interval, { global: false, index: 0, model: interval }))) .whenActionIsDispatched(addVariable(toVariablePayload(interval, { global: false, index: 0, model: interval })))
.whenAsyncActionIsDispatched(updateIntervalVariableOptions(toVariableIdentifier(interval)), true); .whenAsyncActionIsDispatched(updateIntervalVariableOptions(toVariableIdentifier(interval)), true);
...@@ -64,7 +63,7 @@ describe('interval actions', () => { ...@@ -64,7 +63,7 @@ describe('interval actions', () => {
.withAutoMin('1xyz') // illegal interval string .withAutoMin('1xyz') // illegal interval string
.build(); .build();
const tester = await reduxTester<{ templating: TemplatingState }>() const tester = await reduxTester<RootReducerType>()
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenActionIsDispatched(addVariable(toVariablePayload(interval, { global: false, index: 0, model: interval }))) .whenActionIsDispatched(addVariable(toVariablePayload(interval, { global: false, index: 0, model: interval })))
.whenAsyncActionIsDispatched(updateOptions(toVariableIdentifier(interval)), true); .whenAsyncActionIsDispatched(updateOptions(toVariableIdentifier(interval)), true);
...@@ -121,7 +120,7 @@ describe('interval actions', () => { ...@@ -121,7 +120,7 @@ describe('interval actions', () => {
} as unknown) as TemplateSrv, } as unknown) as TemplateSrv,
}; };
await reduxTester<{ templating: TemplatingState }>() await reduxTester<RootReducerType>()
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenActionIsDispatched( .whenActionIsDispatched(
addVariable(toVariablePayload(interval, { global: false, index: 0, model: interval })) addVariable(toVariablePayload(interval, { global: false, index: 0, model: interval }))
...@@ -165,7 +164,7 @@ describe('interval actions', () => { ...@@ -165,7 +164,7 @@ describe('interval actions', () => {
} as unknown) as TemplateSrv, } as unknown) as TemplateSrv,
}; };
await reduxTester<{ templating: TemplatingState }>() await reduxTester<RootReducerType>()
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenActionIsDispatched( .whenActionIsDispatched(
addVariable(toVariablePayload(interval, { global: false, index: 0, model: interval })) addVariable(toVariablePayload(interval, { global: false, index: 0, model: interval }))
......
...@@ -4,10 +4,10 @@ import { dispatch } from '../../../store/store'; ...@@ -4,10 +4,10 @@ import { dispatch } from '../../../store/store';
import { setOptionAsCurrent, setOptionFromUrl } from '../state/actions'; import { setOptionAsCurrent, setOptionFromUrl } from '../state/actions';
import { VariableAdapter } from '../adapters'; import { VariableAdapter } from '../adapters';
import { initialIntervalVariableModelState, intervalVariableReducer } from './reducer'; import { initialIntervalVariableModelState, intervalVariableReducer } from './reducer';
import { OptionsPicker } from '../pickers';
import { toVariableIdentifier } from '../state/types'; import { toVariableIdentifier } from '../state/types';
import { IntervalVariableEditor } from './IntervalVariableEditor'; import { IntervalVariableEditor } from './IntervalVariableEditor';
import { updateAutoValue, updateIntervalVariableOptions } from './actions'; import { updateAutoValue, updateIntervalVariableOptions } from './actions';
import { optionPickerFactory } from '../pickers';
export const createIntervalVariableAdapter = (): VariableAdapter<IntervalVariableModel> => { export const createIntervalVariableAdapter = (): VariableAdapter<IntervalVariableModel> => {
return { return {
...@@ -16,7 +16,7 @@ export const createIntervalVariableAdapter = (): VariableAdapter<IntervalVariabl ...@@ -16,7 +16,7 @@ export const createIntervalVariableAdapter = (): VariableAdapter<IntervalVariabl
name: 'Interval', name: 'Interval',
initialState: initialIntervalVariableModelState, initialState: initialIntervalVariableModelState,
reducer: intervalVariableReducer, reducer: intervalVariableReducer,
picker: OptionsPicker, picker: optionPickerFactory<IntervalVariableModel>(),
editor: IntervalVariableEditor, editor: IntervalVariableEditor,
dependsOn: () => { dependsOn: () => {
return false; return false;
......
import React, { PureComponent } from 'react'; import React, { ComponentType, PureComponent } from 'react';
import { connect, MapDispatchToProps, MapStateToProps } from 'react-redux'; import { connect, ConnectedProps } from 'react-redux';
import { ClickOutsideWrapper } from '@grafana/ui'; import { ClickOutsideWrapper } from '@grafana/ui';
import { LoadingState } from '@grafana/data'; import { LoadingState } from '@grafana/data';
import { StoreState } from 'app/types'; import { StoreState } from 'app/types';
import { VariableLink } from '../shared/VariableLink';
import { VariableInput } from '../shared/VariableInput'; import { VariableInput } from '../shared/VariableInput';
import { commitChangesToVariable, filterOrSearchOptions, navigateOptions, toggleAndFetchTag } from './actions'; import { commitChangesToVariable, filterOrSearchOptions, navigateOptions, toggleAndFetchTag } from './actions';
import { OptionsPickerState, showOptions, toggleAllOptions, toggleOption } from './reducer'; import { OptionsPickerState, showOptions, toggleAllOptions, toggleOption } from './reducer';
import { VariableOption, VariableTag, VariableWithMultiSupport, VariableWithOptions } from '../../types'; import { VariableOption, VariableTag, VariableWithMultiSupport, VariableWithOptions } from '../../types';
import { VariableOptions } from '../shared/VariableOptions'; import { VariableOptions } from '../shared/VariableOptions';
import { isQuery } from '../../guard'; import { isMulti, isQuery } from '../../guard';
import { VariablePickerProps } from '../types'; import { VariablePickerProps } from '../types';
import { formatVariableLabel } from '../../shared/formatVariable'; import { formatVariableLabel } from '../../shared/formatVariable';
import { toVariableIdentifier } from '../../state/types'; import { toVariableIdentifier } from '../../state/types';
import { getVariableQueryRunner } from '../../query/VariableQueryRunner'; import { getVariableQueryRunner } from '../../query/VariableQueryRunner';
import { VariableLink } from '../shared/VariableLink';
interface OwnProps extends VariablePickerProps<VariableWithMultiSupport> {} export const optionPickerFactory = <Model extends VariableWithOptions | VariableWithMultiSupport>(): ComponentType<
VariablePickerProps<Model>
> => {
const mapDispatchToProps = {
showOptions,
commitChangesToVariable,
filterOrSearchOptions,
toggleAllOptions,
toggleOption,
toggleAndFetchTag,
navigateOptions,
};
interface ConnectedProps { const mapStateToProps = (state: StoreState) => ({
picker: OptionsPickerState; picker: state.templating.optionsPicker,
} });
interface DispatchProps { const connector = connect(mapStateToProps, mapDispatchToProps);
showOptions: typeof showOptions;
commitChangesToVariable: typeof commitChangesToVariable;
toggleAllOptions: typeof toggleAllOptions;
toggleOption: typeof toggleOption;
toggleAndFetchTag: typeof toggleAndFetchTag;
filterOrSearchOptions: typeof filterOrSearchOptions;
navigateOptions: typeof navigateOptions;
}
type Props = OwnProps & ConnectedProps & DispatchProps; interface OwnProps extends VariablePickerProps<Model> {}
export class OptionsPickerUnconnected extends PureComponent<Props> { type Props = OwnProps & ConnectedProps<typeof connector>;
onShowOptions = () => this.props.showOptions(this.props.variable);
onHideOptions = () => this.props.commitChangesToVariable(this.props.onVariableChange);
onToggleOption = (option: VariableOption, clearOthers: boolean) => { class OptionsPickerUnconnected extends PureComponent<Props> {
const toggleFunc = this.props.variable.multi ? this.onToggleMultiValueVariable : this.onToggleSingleValueVariable; onShowOptions = () => this.props.showOptions(this.props.variable);
toggleFunc(option, clearOthers); onHideOptions = () => this.props.commitChangesToVariable(this.props.onVariableChange);
};
onToggleSingleValueVariable = (option: VariableOption, clearOthers: boolean) => { onToggleOption = (option: VariableOption, clearOthers: boolean) => {
this.props.toggleOption({ option, clearOthers, forceSelect: false }); const toggleFunc =
this.onHideOptions(); isMulti(this.props.variable) && this.props.variable.multi
}; ? this.onToggleMultiValueVariable
: this.onToggleSingleValueVariable;
toggleFunc(option, clearOthers);
};
onToggleMultiValueVariable = (option: VariableOption, clearOthers: boolean) => { onToggleSingleValueVariable = (option: VariableOption, clearOthers: boolean) => {
this.props.toggleOption({ option, clearOthers, forceSelect: false }); this.props.toggleOption({ option, clearOthers, forceSelect: false });
}; this.onHideOptions();
};
render() { onToggleMultiValueVariable = (option: VariableOption, clearOthers: boolean) => {
const { variable, picker } = this.props; this.props.toggleOption({ option, clearOthers, forceSelect: false });
const showOptions = picker.id === variable.id; };
return ( render() {
<div className="variable-link-wrapper"> const { variable, picker } = this.props;
{this.renderLink(showOptions, variable)} const showOptions = picker.id === variable.id;
{this.renderOptions(showOptions, picker)}
</div>
);
}
renderLink(showOptions: boolean, variable: VariableWithMultiSupport) { return (
if (showOptions) { <div className="variable-link-wrapper">
return null; {showOptions ? this.renderOptions(picker) : this.renderLink(variable)}
</div>
);
} }
const linkText = formatVariableLabel(variable); renderLink(variable: VariableWithOptions) {
const tags = getSelectedTags(variable); const linkText = formatVariableLabel(variable);
const loading = variable.state === LoadingState.Loading; const tags = getSelectedTags(variable);
const loading = variable.state === LoadingState.Loading;
return (
<VariableLink return (
text={linkText} <VariableLink
tags={tags} text={linkText}
onClick={this.onShowOptions} tags={tags}
loading={loading} onClick={this.onShowOptions}
onCancel={this.onCancel} loading={loading}
/> onCancel={this.onCancel}
); />
} );
onCancel = () => {
getVariableQueryRunner().cancelRequest(toVariableIdentifier(this.props.variable));
};
renderOptions(showOptions: boolean, picker: OptionsPickerState) {
if (!showOptions) {
return null;
} }
return ( onCancel = () => {
<ClickOutsideWrapper onClick={this.onHideOptions}> getVariableQueryRunner().cancelRequest(toVariableIdentifier(this.props.variable));
<VariableInput };
value={picker.queryValue}
onChange={this.props.filterOrSearchOptions} renderOptions(picker: OptionsPickerState) {
onNavigate={this.props.navigateOptions} return (
/> <ClickOutsideWrapper onClick={this.onHideOptions}>
<VariableOptions <VariableInput
values={picker.options} value={picker.queryValue}
onToggle={this.onToggleOption} onChange={this.props.filterOrSearchOptions}
onToggleAll={this.props.toggleAllOptions} onNavigate={this.props.navigateOptions}
onToggleTag={this.props.toggleAndFetchTag} />
highlightIndex={picker.highlightIndex} <VariableOptions
multi={picker.multi} values={picker.options}
tags={picker.tags} onToggle={this.onToggleOption}
selectedValues={picker.selectedValues} onToggleAll={this.props.toggleAllOptions}
/> onToggleTag={this.props.toggleAndFetchTag}
</ClickOutsideWrapper> highlightIndex={picker.highlightIndex}
); multi={picker.multi}
tags={picker.tags}
selectedValues={picker.selectedValues}
/>
</ClickOutsideWrapper>
);
}
} }
}
const OptionsPicker = connector(OptionsPickerUnconnected);
OptionsPicker.displayName = 'OptionsPicker';
return OptionsPicker;
};
const getSelectedTags = (variable: VariableWithOptions): VariableTag[] => { const getSelectedTags = (variable: VariableWithOptions): VariableTag[] => {
if (!isQuery(variable) || !Array.isArray(variable.tags)) { if (!isQuery(variable) || !Array.isArray(variable.tags)) {
...@@ -121,20 +126,3 @@ const getSelectedTags = (variable: VariableWithOptions): VariableTag[] => { ...@@ -121,20 +126,3 @@ const getSelectedTags = (variable: VariableWithOptions): VariableTag[] => {
} }
return variable.tags.filter((t) => t.selected); return variable.tags.filter((t) => t.selected);
}; };
const mapDispatchToProps: MapDispatchToProps<DispatchProps, OwnProps> = {
showOptions,
commitChangesToVariable,
filterOrSearchOptions,
toggleAllOptions,
toggleOption,
toggleAndFetchTag,
navigateOptions,
};
const mapStateToProps: MapStateToProps<ConnectedProps, OwnProps, StoreState> = (state) => ({
picker: state.templating.optionsPicker,
});
export const OptionsPicker = connect(mapStateToProps, mapDispatchToProps)(OptionsPickerUnconnected);
OptionsPicker.displayName = 'OptionsPicker';
import { reduxTester } from '../../../../../test/core/redux/reduxTester'; import { reduxTester } from '../../../../../test/core/redux/reduxTester';
import { getRootReducer } from '../../state/helpers'; import { getRootReducer, RootReducerType } from '../../state/helpers';
import { TemplatingState } from '../../state/reducers';
import { initialVariableModelState, QueryVariableModel, VariableRefresh, VariableSort } from '../../types'; import { initialVariableModelState, QueryVariableModel, VariableRefresh, VariableSort } from '../../types';
import { import {
hideOptions, hideOptions,
...@@ -53,7 +52,7 @@ describe('options picker actions', () => { ...@@ -53,7 +52,7 @@ describe('options picker actions', () => {
const clearOthers = false; const clearOthers = false;
const key = NavigationKey.cancel; const key = NavigationKey.cancel;
const tester = await reduxTester<{ templating: TemplatingState }>() const tester = await reduxTester<RootReducerType>()
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenActionIsDispatched(addVariable(toVariablePayload(variable, { global: false, index: 0, model: variable }))) .whenActionIsDispatched(addVariable(toVariablePayload(variable, { global: false, index: 0, model: variable })))
.whenActionIsDispatched(showOptions(variable)) .whenActionIsDispatched(showOptions(variable))
...@@ -86,7 +85,7 @@ describe('options picker actions', () => { ...@@ -86,7 +85,7 @@ describe('options picker actions', () => {
const clearOthers = false; const clearOthers = false;
const key = NavigationKey.select; const key = NavigationKey.select;
const tester = await reduxTester<{ templating: TemplatingState }>() const tester = await reduxTester<RootReducerType>()
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenActionIsDispatched(addVariable(toVariablePayload(variable, { global: false, index: 0, model: variable }))) .whenActionIsDispatched(addVariable(toVariablePayload(variable, { global: false, index: 0, model: variable })))
.whenActionIsDispatched(showOptions(variable)) .whenActionIsDispatched(showOptions(variable))
...@@ -109,7 +108,7 @@ describe('options picker actions', () => { ...@@ -109,7 +108,7 @@ describe('options picker actions', () => {
const clearOthers = true; const clearOthers = true;
const key = NavigationKey.select; const key = NavigationKey.select;
const tester = await reduxTester<{ templating: TemplatingState }>() const tester = await reduxTester<RootReducerType>()
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenActionIsDispatched(addVariable(toVariablePayload(variable, { global: false, index: 0, model: variable }))) .whenActionIsDispatched(addVariable(toVariablePayload(variable, { global: false, index: 0, model: variable })))
.whenActionIsDispatched(showOptions(variable)) .whenActionIsDispatched(showOptions(variable))
...@@ -128,7 +127,7 @@ describe('options picker actions', () => { ...@@ -128,7 +127,7 @@ describe('options picker actions', () => {
const clearOthers = true; const clearOthers = true;
const key = NavigationKey.select; const key = NavigationKey.select;
const tester = await reduxTester<{ templating: TemplatingState }>() const tester = await reduxTester<RootReducerType>()
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenActionIsDispatched(addVariable(toVariablePayload(variable, { global: false, index: 0, model: variable }))) .whenActionIsDispatched(addVariable(toVariablePayload(variable, { global: false, index: 0, model: variable })))
.whenActionIsDispatched(showOptions(variable)) .whenActionIsDispatched(showOptions(variable))
...@@ -149,7 +148,7 @@ describe('options picker actions', () => { ...@@ -149,7 +148,7 @@ describe('options picker actions', () => {
const clearOthers = true; const clearOthers = true;
const key = NavigationKey.select; const key = NavigationKey.select;
const tester = await reduxTester<{ templating: TemplatingState }>() const tester = await reduxTester<RootReducerType>()
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenActionIsDispatched(addVariable(toVariablePayload(variable, { global: false, index: 0, model: variable }))) .whenActionIsDispatched(addVariable(toVariablePayload(variable, { global: false, index: 0, model: variable })))
.whenActionIsDispatched(showOptions(variable)) .whenActionIsDispatched(showOptions(variable))
...@@ -171,7 +170,7 @@ describe('options picker actions', () => { ...@@ -171,7 +170,7 @@ describe('options picker actions', () => {
const clearOthers = false; const clearOthers = false;
const key = NavigationKey.selectAndClose; const key = NavigationKey.selectAndClose;
const tester = await reduxTester<{ templating: TemplatingState }>() const tester = await reduxTester<RootReducerType>()
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenActionIsDispatched(addVariable(toVariablePayload(variable, { global: false, index: 0, model: variable }))) .whenActionIsDispatched(addVariable(toVariablePayload(variable, { global: false, index: 0, model: variable })))
.whenActionIsDispatched(showOptions(variable)) .whenActionIsDispatched(showOptions(variable))
...@@ -205,7 +204,7 @@ describe('options picker actions', () => { ...@@ -205,7 +204,7 @@ describe('options picker actions', () => {
const variable = createMultiVariable({ options, current: createOption(['A'], ['A'], true), includeAll: false }); const variable = createMultiVariable({ options, current: createOption(['A'], ['A'], true), includeAll: false });
const filter = 'A'; const filter = 'A';
const tester = await reduxTester<{ templating: TemplatingState }>() const tester = await reduxTester<RootReducerType>()
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenActionIsDispatched(addVariable(toVariablePayload(variable, { global: false, index: 0, model: variable }))) .whenActionIsDispatched(addVariable(toVariablePayload(variable, { global: false, index: 0, model: variable })))
.whenActionIsDispatched(showOptions(variable)) .whenActionIsDispatched(showOptions(variable))
...@@ -220,7 +219,7 @@ describe('options picker actions', () => { ...@@ -220,7 +219,7 @@ describe('options picker actions', () => {
const options = [createOption('A', 'A', true), createOption('B'), createOption('C')]; const options = [createOption('A', 'A', true), createOption('B'), createOption('C')];
const variable = createMultiVariable({ options, current: createOption(['A'], ['A'], true), includeAll: false }); const variable = createMultiVariable({ options, current: createOption(['A'], ['A'], true), includeAll: false });
const tester = await reduxTester<{ templating: TemplatingState }>() const tester = await reduxTester<RootReducerType>()
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenActionIsDispatched(addVariable(toVariablePayload(variable, { global: false, index: 0, model: variable }))) .whenActionIsDispatched(addVariable(toVariablePayload(variable, { global: false, index: 0, model: variable })))
.whenActionIsDispatched(showOptions(variable)) .whenActionIsDispatched(showOptions(variable))
...@@ -247,7 +246,7 @@ describe('options picker actions', () => { ...@@ -247,7 +246,7 @@ describe('options picker actions', () => {
const variable = createMultiVariable({ options, current: createOption(['A'], ['A'], true), includeAll: false }); const variable = createMultiVariable({ options, current: createOption(['A'], ['A'], true), includeAll: false });
const clearOthers = false; const clearOthers = false;
const tester = await reduxTester<{ templating: TemplatingState }>() const tester = await reduxTester<RootReducerType>()
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenActionIsDispatched(addVariable(toVariablePayload(variable, { global: false, index: 0, model: variable }))) .whenActionIsDispatched(addVariable(toVariablePayload(variable, { global: false, index: 0, model: variable })))
.whenActionIsDispatched(showOptions(variable)) .whenActionIsDispatched(showOptions(variable))
...@@ -278,7 +277,7 @@ describe('options picker actions', () => { ...@@ -278,7 +277,7 @@ describe('options picker actions', () => {
const variable = createMultiVariable({ options, current: createOption(['A'], ['A'], true), includeAll: false }); const variable = createMultiVariable({ options, current: createOption(['A'], ['A'], true), includeAll: false });
const clearOthers = false; const clearOthers = false;
const tester = await reduxTester<{ templating: TemplatingState }>() const tester = await reduxTester<RootReducerType>()
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenActionIsDispatched(addVariable(toVariablePayload(variable, { global: false, index: 0, model: variable }))) .whenActionIsDispatched(addVariable(toVariablePayload(variable, { global: false, index: 0, model: variable })))
.whenActionIsDispatched(showOptions(variable)) .whenActionIsDispatched(showOptions(variable))
...@@ -310,7 +309,7 @@ describe('options picker actions', () => { ...@@ -310,7 +309,7 @@ describe('options picker actions', () => {
const variable = createMultiVariable({ options, current: createOption(['A'], ['A'], true), includeAll: false }); const variable = createMultiVariable({ options, current: createOption(['A'], ['A'], true), includeAll: false });
const clearOthers = false; const clearOthers = false;
const tester = await reduxTester<{ templating: TemplatingState }>() const tester = await reduxTester<RootReducerType>()
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenActionIsDispatched(addVariable(toVariablePayload(variable, { global: false, index: 0, model: variable }))) .whenActionIsDispatched(addVariable(toVariablePayload(variable, { global: false, index: 0, model: variable })))
.whenActionIsDispatched(showOptions(variable)) .whenActionIsDispatched(showOptions(variable))
...@@ -329,7 +328,7 @@ describe('options picker actions', () => { ...@@ -329,7 +328,7 @@ describe('options picker actions', () => {
const variable = createMultiVariable({ options, current: createOption(['A'], ['A'], true), includeAll: false }); const variable = createMultiVariable({ options, current: createOption(['A'], ['A'], true), includeAll: false });
const clearOthers = false; const clearOthers = false;
const tester = await reduxTester<{ templating: TemplatingState }>() const tester = await reduxTester<RootReducerType>()
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenActionIsDispatched(addVariable(toVariablePayload(variable, { global: false, index: 0, model: variable }))) .whenActionIsDispatched(addVariable(toVariablePayload(variable, { global: false, index: 0, model: variable })))
.whenActionIsDispatched(showOptions(variable)) .whenActionIsDispatched(showOptions(variable))
...@@ -365,7 +364,7 @@ describe('options picker actions', () => { ...@@ -365,7 +364,7 @@ describe('options picker actions', () => {
tags: [tag], tags: [tag],
}); });
const tester = await reduxTester<{ templating: TemplatingState }>() const tester = await reduxTester<RootReducerType>()
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenActionIsDispatched(addVariable(toVariablePayload(variable, { global: false, index: 0, model: variable }))) .whenActionIsDispatched(addVariable(toVariablePayload(variable, { global: false, index: 0, model: variable })))
.whenActionIsDispatched(showOptions(variable)) .whenActionIsDispatched(showOptions(variable))
...@@ -391,7 +390,7 @@ describe('options picker actions', () => { ...@@ -391,7 +390,7 @@ describe('options picker actions', () => {
// @ts-ignore strict null error TS2345: Argument of type '() => Promise<{ value: string; text: string; }[]>' is not assignable to parameter of type '() => Promise<never[]>' // @ts-ignore strict null error TS2345: Argument of type '() => Promise<{ value: string; text: string; }[]>' is not assignable to parameter of type '() => Promise<never[]>'
datasource.metricFindQuery.mockImplementation(() => Promise.resolve(values)); datasource.metricFindQuery.mockImplementation(() => Promise.resolve(values));
const tester = await reduxTester<{ templating: TemplatingState }>() const tester = await reduxTester<RootReducerType>()
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenActionIsDispatched(addVariable(toVariablePayload(variable, { global: false, index: 0, model: variable }))) .whenActionIsDispatched(addVariable(toVariablePayload(variable, { global: false, index: 0, model: variable })))
.whenActionIsDispatched(showOptions(variable)) .whenActionIsDispatched(showOptions(variable))
......
...@@ -78,7 +78,7 @@ const setVariable = async (updated: VariableWithMultiSupport) => { ...@@ -78,7 +78,7 @@ const setVariable = async (updated: VariableWithMultiSupport) => {
return; return;
}; };
export const commitChangesToVariable = (callback?: (updated: VariableWithMultiSupport) => void): ThunkResult<void> => { export const commitChangesToVariable = (callback?: (updated: any) => void): ThunkResult<void> => {
return async (dispatch, getState) => { return async (dispatch, getState) => {
const picker = getState().templating.optionsPicker; const picker = getState().templating.optionsPicker;
const existing = getVariable<VariableWithMultiSupport>(picker.id, getState()); const existing = getVariable<VariableWithMultiSupport>(picker.id, getState());
......
import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import { cloneDeep, isString, trim } from 'lodash'; import { cloneDeep, isString, trim } from 'lodash';
import { VariableOption, VariableTag, VariableWithMultiSupport } from '../../types'; import { VariableOption, VariableTag, VariableWithMultiSupport, VariableWithOptions } from '../../types';
import { ALL_VARIABLE_VALUE } from '../../state/types'; import { ALL_VARIABLE_VALUE } from '../../state/types';
import { isQuery } from '../../guard'; import { isMulti, isQuery } from '../../guard';
import { applyStateChanges } from '../../../../core/utils/applyStateChanges'; import { applyStateChanges } from '../../../../core/utils/applyStateChanges';
import { containsSearchFilter } from '../../utils'; import { containsSearchFilter } from '../../utils';
...@@ -119,15 +119,19 @@ const optionsPickerSlice = createSlice({ ...@@ -119,15 +119,19 @@ const optionsPickerSlice = createSlice({
name: 'templating/optionsPicker', name: 'templating/optionsPicker',
initialState, initialState,
reducers: { reducers: {
showOptions: (state, action: PayloadAction<VariableWithMultiSupport>): OptionsPickerState => { showOptions: (state, action: PayloadAction<VariableWithOptions>): OptionsPickerState => {
const { query, options, multi } = action.payload; const { query, options } = action.payload;
state.highlightIndex = -1; state.highlightIndex = -1;
state.options = cloneDeep(options); state.options = cloneDeep(options);
state.tags = getTags(action.payload);
state.multi = multi ?? false;
state.id = action.payload.id; state.id = action.payload.id;
state.queryValue = ''; state.queryValue = '';
state.multi = false;
if (isMulti(action.payload)) {
state.tags = getTags(action.payload);
state.multi = action.payload.multi ?? false;
}
if (isQuery(action.payload)) { if (isQuery(action.payload)) {
const { queryValue } = action.payload; const { queryValue } = action.payload;
......
export { OptionsPicker } from './OptionsPicker/OptionsPicker'; export { optionPickerFactory } from './OptionsPicker/OptionsPicker';
import React, { ChangeEvent, PureComponent } from 'react'; import React, { ChangeEvent, FormEvent, PureComponent } from 'react';
import { css } from 'emotion'; import { css } from 'emotion';
import { MapDispatchToProps, MapStateToProps } from 'react-redux'; import { MapDispatchToProps, MapStateToProps } from 'react-redux';
import { InlineField, InlineFieldRow, VerticalGroup } from '@grafana/ui'; import { InlineField, InlineFieldRow, VerticalGroup } from '@grafana/ui';
...@@ -92,34 +92,34 @@ export class QueryVariableEditorUnConnected extends PureComponent<Props, State> ...@@ -92,34 +92,34 @@ export class QueryVariableEditorUnConnected extends PureComponent<Props, State>
} }
}; };
onRegExChange = (event: ChangeEvent<HTMLInputElement>) => { onRegExChange = (event: FormEvent<HTMLInputElement>) => {
this.setState({ regex: event.target.value }); this.setState({ regex: event.currentTarget.value });
}; };
onRegExBlur = async (event: ChangeEvent<HTMLInputElement>) => { onRegExBlur = async (event: FormEvent<HTMLInputElement>) => {
const regex = event.target.value; const regex = event.currentTarget.value;
if (this.props.variable.regex !== regex) { if (this.props.variable.regex !== regex) {
this.props.onPropChange({ propName: 'regex', propValue: regex, updateOptions: true }); this.props.onPropChange({ propName: 'regex', propValue: regex, updateOptions: true });
} }
}; };
onTagsQueryChange = async (event: ChangeEvent<HTMLInputElement>) => { onTagsQueryChange = async (event: FormEvent<HTMLInputElement>) => {
this.setState({ tagsQuery: event.target.value }); this.setState({ tagsQuery: event.currentTarget.value });
}; };
onTagsQueryBlur = async (event: ChangeEvent<HTMLInputElement>) => { onTagsQueryBlur = async (event: FormEvent<HTMLInputElement>) => {
const tagsQuery = event.target.value; const tagsQuery = event.currentTarget.value;
if (this.props.variable.tagsQuery !== tagsQuery) { if (this.props.variable.tagsQuery !== tagsQuery) {
this.props.onPropChange({ propName: 'tagsQuery', propValue: tagsQuery, updateOptions: true }); this.props.onPropChange({ propName: 'tagsQuery', propValue: tagsQuery, updateOptions: true });
} }
}; };
onTagValuesQueryChange = async (event: ChangeEvent<HTMLInputElement>) => { onTagValuesQueryChange = async (event: FormEvent<HTMLInputElement>) => {
this.setState({ tagValuesQuery: event.target.value }); this.setState({ tagValuesQuery: event.currentTarget.value });
}; };
onTagValuesQueryBlur = async (event: ChangeEvent<HTMLInputElement>) => { onTagValuesQueryBlur = async (event: FormEvent<HTMLInputElement>) => {
const tagValuesQuery = event.target.value; const tagValuesQuery = event.currentTarget.value;
if (this.props.variable.tagValuesQuery !== tagValuesQuery) { if (this.props.variable.tagValuesQuery !== tagValuesQuery) {
this.props.onPropChange({ propName: 'tagValuesQuery', propValue: tagValuesQuery, updateOptions: true }); this.props.onPropChange({ propName: 'tagValuesQuery', propValue: tagValuesQuery, updateOptions: true });
} }
......
...@@ -3,7 +3,7 @@ import { getDefaultTimeRange, LoadingState } from '@grafana/data'; ...@@ -3,7 +3,7 @@ import { getDefaultTimeRange, LoadingState } from '@grafana/data';
import { variableAdapters } from '../adapters'; import { variableAdapters } from '../adapters';
import { createQueryVariableAdapter } from './adapter'; import { createQueryVariableAdapter } from './adapter';
import { reduxTester } from '../../../../test/core/redux/reduxTester'; import { reduxTester } from '../../../../test/core/redux/reduxTester';
import { getRootReducer } from '../state/helpers'; import { getRootReducer, RootReducerType } from '../state/helpers';
import { QueryVariableModel, VariableHide, VariableRefresh, VariableSort } from '../types'; import { QueryVariableModel, VariableHide, VariableRefresh, VariableSort } from '../types';
import { ALL_VARIABLE_TEXT, ALL_VARIABLE_VALUE, toVariablePayload } from '../state/types'; import { ALL_VARIABLE_TEXT, ALL_VARIABLE_VALUE, toVariablePayload } from '../state/types';
import { import {
...@@ -14,7 +14,6 @@ import { ...@@ -14,7 +14,6 @@ import {
variableStateFailed, variableStateFailed,
variableStateFetching, variableStateFetching,
} from '../state/sharedReducer'; } from '../state/sharedReducer';
import { TemplatingState } from '../state/reducers';
import { import {
changeQueryVariableDataSource, changeQueryVariableDataSource,
changeQueryVariableQuery, changeQueryVariableQuery,
...@@ -87,7 +86,7 @@ describe('query actions', () => { ...@@ -87,7 +86,7 @@ describe('query actions', () => {
mockDatasourceMetrics(variable, optionsMetrics, tagsMetrics); mockDatasourceMetrics(variable, optionsMetrics, tagsMetrics);
const tester = await reduxTester<{ templating: TemplatingState }>() const tester = await reduxTester<RootReducerType>()
.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(updateQueryVariableOptions(toVariablePayload(variable)), true); .whenAsyncActionIsDispatched(updateQueryVariableOptions(toVariablePayload(variable)), true);
...@@ -111,7 +110,7 @@ describe('query actions', () => { ...@@ -111,7 +110,7 @@ describe('query actions', () => {
mockDatasourceMetrics(variable, optionsMetrics, tagsMetrics); mockDatasourceMetrics(variable, optionsMetrics, tagsMetrics);
const tester = await reduxTester<{ templating: TemplatingState }>() const tester = await reduxTester<RootReducerType>()
.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(updateQueryVariableOptions(toVariablePayload(variable)), true); .whenAsyncActionIsDispatched(updateQueryVariableOptions(toVariablePayload(variable)), true);
...@@ -138,7 +137,7 @@ describe('query actions', () => { ...@@ -138,7 +137,7 @@ describe('query actions', () => {
mockDatasourceMetrics(variable, optionsMetrics, []); mockDatasourceMetrics(variable, optionsMetrics, []);
const tester = await reduxTester<{ templating: TemplatingState }>() const tester = await reduxTester<RootReducerType>()
.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(updateQueryVariableOptions(toVariablePayload(variable)), true); .whenAsyncActionIsDispatched(updateQueryVariableOptions(toVariablePayload(variable)), true);
...@@ -160,7 +159,7 @@ describe('query actions', () => { ...@@ -160,7 +159,7 @@ describe('query actions', () => {
mockDatasourceMetrics(variable, optionsMetrics, []); mockDatasourceMetrics(variable, optionsMetrics, []);
const tester = await reduxTester<{ templating: TemplatingState }>() const tester = await reduxTester<RootReducerType>()
.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(updateQueryVariableOptions(toVariablePayload(variable)), true); .whenAsyncActionIsDispatched(updateQueryVariableOptions(toVariablePayload(variable)), true);
...@@ -186,7 +185,7 @@ describe('query actions', () => { ...@@ -186,7 +185,7 @@ describe('query actions', () => {
mockDatasourceMetrics(variable, optionsMetrics, []); mockDatasourceMetrics(variable, optionsMetrics, []);
const tester = await reduxTester<{ templating: TemplatingState }>() const tester = await reduxTester<RootReducerType>()
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenActionIsDispatched(addVariable(toVariablePayload(variable, { global: false, index: 0, model: variable }))) .whenActionIsDispatched(addVariable(toVariablePayload(variable, { global: false, index: 0, model: variable })))
.whenActionIsDispatched(setIdInEditor({ id: variable.id })) .whenActionIsDispatched(setIdInEditor({ id: variable.id }))
...@@ -214,7 +213,7 @@ describe('query actions', () => { ...@@ -214,7 +213,7 @@ describe('query actions', () => {
mockDatasourceMetrics(variable, optionsMetrics, []); mockDatasourceMetrics(variable, optionsMetrics, []);
const tester = await reduxTester<{ templating: TemplatingState }>() const tester = await reduxTester<RootReducerType>()
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenActionIsDispatched(addVariable(toVariablePayload(variable, { global: false, index: 0, model: variable }))) .whenActionIsDispatched(addVariable(toVariablePayload(variable, { global: false, index: 0, model: variable })))
.whenActionIsDispatched(setIdInEditor({ id: variable.id })) .whenActionIsDispatched(setIdInEditor({ id: variable.id }))
...@@ -241,7 +240,7 @@ describe('query actions', () => { ...@@ -241,7 +240,7 @@ describe('query actions', () => {
mocks[variable.datasource!].metricFindQuery = jest.fn(() => Promise.reject(error)); mocks[variable.datasource!].metricFindQuery = jest.fn(() => Promise.reject(error));
const tester = await reduxTester<{ templating: TemplatingState }>() const tester = await reduxTester<RootReducerType>()
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenActionIsDispatched(addVariable(toVariablePayload(variable, { global: false, index: 0, model: variable }))) .whenActionIsDispatched(addVariable(toVariablePayload(variable, { global: false, index: 0, model: variable })))
.whenActionIsDispatched(setIdInEditor({ id: variable.id })) .whenActionIsDispatched(setIdInEditor({ id: variable.id }))
...@@ -277,7 +276,7 @@ describe('query actions', () => { ...@@ -277,7 +276,7 @@ describe('query actions', () => {
components: { VariableQueryEditor: editor }, components: { VariableQueryEditor: editor },
}); });
const tester = await reduxTester<{ templating: TemplatingState }>() const tester = await reduxTester<RootReducerType>()
.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(initQueryVariableEditor(toVariablePayload(variable)), true); .whenAsyncActionIsDispatched(initQueryVariableEditor(toVariablePayload(variable)), true);
...@@ -306,7 +305,7 @@ describe('query actions', () => { ...@@ -306,7 +305,7 @@ describe('query actions', () => {
components: { VariableQueryEditor: editor }, components: { VariableQueryEditor: editor },
}); });
const tester = await reduxTester<{ templating: TemplatingState }>() const tester = await reduxTester<RootReducerType>()
.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(initQueryVariableEditor(toVariablePayload(variable)), true); .whenAsyncActionIsDispatched(initQueryVariableEditor(toVariablePayload(variable)), true);
...@@ -334,7 +333,7 @@ describe('query actions', () => { ...@@ -334,7 +333,7 @@ describe('query actions', () => {
components: { VariableQueryEditor: editor }, components: { VariableQueryEditor: editor },
}); });
const tester = await reduxTester<{ templating: TemplatingState }>() const tester = await reduxTester<RootReducerType>()
.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(initQueryVariableEditor(toVariablePayload(variable)), true); .whenAsyncActionIsDispatched(initQueryVariableEditor(toVariablePayload(variable)), true);
...@@ -356,7 +355,7 @@ describe('query actions', () => { ...@@ -356,7 +355,7 @@ describe('query actions', () => {
it('then correct actions are dispatched', async () => { it('then correct actions are dispatched', async () => {
const variable = createVariable({ datasource: undefined }); const variable = createVariable({ datasource: undefined });
const tester = await reduxTester<{ templating: TemplatingState }>() const tester = await reduxTester<RootReducerType>()
.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(initQueryVariableEditor(toVariablePayload(variable)), true); .whenAsyncActionIsDispatched(initQueryVariableEditor(toVariablePayload(variable)), true);
...@@ -380,7 +379,7 @@ describe('query actions', () => { ...@@ -380,7 +379,7 @@ describe('query actions', () => {
components: { VariableQueryEditor: editor }, components: { VariableQueryEditor: editor },
}); });
const tester = await reduxTester<{ templating: TemplatingState }>() const tester = await reduxTester<RootReducerType>()
.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(changeQueryVariableDataSource(toVariablePayload(variable), 'datasource'), true); .whenAsyncActionIsDispatched(changeQueryVariableDataSource(toVariablePayload(variable), 'datasource'), true);
...@@ -410,7 +409,7 @@ describe('query actions', () => { ...@@ -410,7 +409,7 @@ describe('query actions', () => {
components: {}, components: {},
}); });
const tester = await reduxTester<{ templating: TemplatingState }>() const tester = await reduxTester<RootReducerType>()
.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(changeQueryVariableDataSource(toVariablePayload(variable), 'datasource'), true); .whenAsyncActionIsDispatched(changeQueryVariableDataSource(toVariablePayload(variable), 'datasource'), true);
...@@ -442,7 +441,7 @@ describe('query actions', () => { ...@@ -442,7 +441,7 @@ describe('query actions', () => {
mockDatasourceMetrics({ ...variable, query }, optionsMetrics, tagsMetrics); mockDatasourceMetrics({ ...variable, query }, optionsMetrics, tagsMetrics);
const tester = await reduxTester<{ templating: TemplatingState }>() const tester = await reduxTester<RootReducerType>()
.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(changeQueryVariableQuery(toVariablePayload(variable), query, definition), true); .whenAsyncActionIsDispatched(changeQueryVariableQuery(toVariablePayload(variable), query, definition), true);
...@@ -473,7 +472,7 @@ describe('query actions', () => { ...@@ -473,7 +472,7 @@ describe('query actions', () => {
mockDatasourceMetrics({ ...variable, query }, optionsMetrics, []); mockDatasourceMetrics({ ...variable, query }, optionsMetrics, []);
const tester = await reduxTester<{ templating: TemplatingState }>() const tester = await reduxTester<RootReducerType>()
.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(changeQueryVariableQuery(toVariablePayload(variable), query, definition), true); .whenAsyncActionIsDispatched(changeQueryVariableQuery(toVariablePayload(variable), query, definition), true);
...@@ -502,7 +501,7 @@ describe('query actions', () => { ...@@ -502,7 +501,7 @@ describe('query actions', () => {
mockDatasourceMetrics({ ...variable, query }, optionsMetrics, []); mockDatasourceMetrics({ ...variable, query }, optionsMetrics, []);
const tester = await reduxTester<{ templating: TemplatingState }>() const tester = await reduxTester<RootReducerType>()
.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(changeQueryVariableQuery(toVariablePayload(variable), query, definition), true); .whenAsyncActionIsDispatched(changeQueryVariableQuery(toVariablePayload(variable), query, definition), true);
...@@ -528,7 +527,7 @@ describe('query actions', () => { ...@@ -528,7 +527,7 @@ describe('query actions', () => {
const query = `$${variable.name}`; const query = `$${variable.name}`;
const definition = 'depends on datasource variable'; const definition = 'depends on datasource variable';
const tester = await reduxTester<{ templating: TemplatingState }>() const tester = await reduxTester<RootReducerType>()
.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(changeQueryVariableQuery(toVariablePayload(variable), query, definition), true); .whenAsyncActionIsDispatched(changeQueryVariableQuery(toVariablePayload(variable), query, definition), true);
......
...@@ -5,11 +5,11 @@ import { initialQueryVariableModelState, queryVariableReducer } from './reducer' ...@@ -5,11 +5,11 @@ import { initialQueryVariableModelState, queryVariableReducer } from './reducer'
import { dispatch } from '../../../store/store'; import { dispatch } from '../../../store/store';
import { setOptionAsCurrent, setOptionFromUrl } from '../state/actions'; import { setOptionAsCurrent, setOptionFromUrl } from '../state/actions';
import { VariableAdapter } from '../adapters'; import { VariableAdapter } from '../adapters';
import { OptionsPicker } from '../pickers';
import { QueryVariableEditor } from './QueryVariableEditor'; import { QueryVariableEditor } from './QueryVariableEditor';
import { updateQueryVariableOptions } from './actions'; import { updateQueryVariableOptions } from './actions';
import { ALL_VARIABLE_TEXT, toVariableIdentifier } from '../state/types'; import { ALL_VARIABLE_TEXT, toVariableIdentifier } from '../state/types';
import { containsVariable, isAllVariable } from '../utils'; import { containsVariable, isAllVariable } from '../utils';
import { optionPickerFactory } from '../pickers';
export const createQueryVariableAdapter = (): VariableAdapter<QueryVariableModel> => { export const createQueryVariableAdapter = (): VariableAdapter<QueryVariableModel> => {
return { return {
...@@ -18,7 +18,7 @@ export const createQueryVariableAdapter = (): VariableAdapter<QueryVariableModel ...@@ -18,7 +18,7 @@ export const createQueryVariableAdapter = (): VariableAdapter<QueryVariableModel
name: 'Query', name: 'Query',
initialState: initialQueryVariableModelState, initialState: initialQueryVariableModelState,
reducer: queryVariableReducer, reducer: queryVariableReducer,
picker: OptionsPicker, picker: optionPickerFactory<QueryVariableModel>(),
editor: QueryVariableEditor, editor: QueryVariableEditor,
dependsOn: (variable, variableToTest) => { dependsOn: (variable, variableToTest) => {
return containsVariable(variable.query, variable.datasource, variable.regex, variableToTest.name); return containsVariable(variable.query, variable.datasource, variable.regex, variableToTest.name);
......
import { AnyAction } from 'redux'; import { AnyAction } from 'redux';
import { UrlQueryMap } from '@grafana/data';
import { getRootReducer, getTemplatingAndLocationRootReducer, getTemplatingRootReducer } from './helpers'; import {
getRootReducer,
getTemplatingAndLocationRootReducer,
getTemplatingRootReducer,
RootReducerType,
TemplatingAndLocationReducerType,
} from './helpers';
import { variableAdapters } from '../adapters'; import { variableAdapters } from '../adapters';
import { createQueryVariableAdapter } from '../query/adapter'; import { createQueryVariableAdapter } from '../query/adapter';
import { createCustomVariableAdapter } from '../custom/adapter'; import { createCustomVariableAdapter } from '../custom/adapter';
...@@ -49,7 +54,6 @@ import { ...@@ -49,7 +54,6 @@ import {
initialVariableEditorState, initialVariableEditorState,
setIdInEditor, setIdInEditor,
} from '../editor/reducer'; } from '../editor/reducer';
import { DashboardState, LocationState } from '../../../types';
import { import {
TransactionStatus, TransactionStatus,
variablesClearTransaction, variablesClearTransaction,
...@@ -63,6 +67,7 @@ import { ConstantVariableModel, VariableRefresh } from '../types'; ...@@ -63,6 +67,7 @@ import { ConstantVariableModel, VariableRefresh } from '../types';
import { updateVariableOptions } from '../query/reducer'; import { updateVariableOptions } from '../query/reducer';
import { setVariableQueryRunner, VariableQueryRunner } from '../query/VariableQueryRunner'; import { setVariableQueryRunner, VariableQueryRunner } from '../query/VariableQueryRunner';
import { setDataSourceSrv } from '@grafana/runtime'; import { setDataSourceSrv } from '@grafana/runtime';
import { LocationState } from 'app/types';
variableAdapters.setInit(() => [ variableAdapters.setInit(() => [
createQueryVariableAdapter(), createQueryVariableAdapter(),
...@@ -145,10 +150,12 @@ describe('shared actions', () => { ...@@ -145,10 +150,12 @@ describe('shared actions', () => {
const custom = customBuilder().build(); const custom = customBuilder().build();
const textbox = textboxBuilder().build(); const textbox = textboxBuilder().build();
const list = [query, constant, datasource, custom, textbox]; const list = [query, constant, datasource, custom, textbox];
const preloadedState = {
templating: ({} as unknown) as TemplatingState,
location: ({ query: {} } as unknown) as LocationState,
};
const tester = await reduxTester<{ templating: TemplatingState; location: { query: UrlQueryMap } }>({ const tester = await reduxTester<TemplatingAndLocationReducerType>({ preloadedState })
preloadedState: { templating: ({} as unknown) as TemplatingState, location: { query: {} } },
})
.givenRootReducer(getTemplatingAndLocationRootReducer()) .givenRootReducer(getTemplatingAndLocationRootReducer())
.whenActionIsDispatched(variablesInitTransaction({ uid: '' })) .whenActionIsDispatched(variablesInitTransaction({ uid: '' }))
.whenActionIsDispatched(initDashboardTemplating(list)) .whenActionIsDispatched(initDashboardTemplating(list))
...@@ -202,9 +209,12 @@ describe('shared actions', () => { ...@@ -202,9 +209,12 @@ describe('shared actions', () => {
const list = [stats, substats]; const list = [stats, substats];
const query = { orgId: '1', 'var-stats': 'response', 'var-substats': ALL_VARIABLE_TEXT }; const query = { orgId: '1', 'var-stats': 'response', 'var-substats': ALL_VARIABLE_TEXT };
const tester = await reduxTester<{ templating: TemplatingState; location: { query: UrlQueryMap } }>({ const preloadedState = {
preloadedState: { templating: ({} as unknown) as TemplatingState, location: { query } }, templating: ({} as unknown) as TemplatingState,
}) location: ({ query } as unknown) as LocationState,
};
const tester = await reduxTester<TemplatingAndLocationReducerType>({ preloadedState })
.givenRootReducer(getTemplatingAndLocationRootReducer()) .givenRootReducer(getTemplatingAndLocationRootReducer())
.whenActionIsDispatched(variablesInitTransaction({ uid: '' })) .whenActionIsDispatched(variablesInitTransaction({ uid: '' }))
.whenActionIsDispatched(initDashboardTemplating(list)) .whenActionIsDispatched(initDashboardTemplating(list))
...@@ -558,11 +568,6 @@ describe('shared actions', () => { ...@@ -558,11 +568,6 @@ describe('shared actions', () => {
}); });
describe('initVariablesTransaction', () => { describe('initVariablesTransaction', () => {
type ReducersUsedInContext = {
templating: TemplatingState;
dashboard: DashboardState;
location: LocationState;
};
const constant = constantBuilder().withId('constant').withName('constant').build(); const constant = constantBuilder().withId('constant').withName('constant').build();
const templating: any = { list: [constant] }; const templating: any = { list: [constant] };
const uid = 'uid'; const uid = 'uid';
...@@ -570,7 +575,7 @@ describe('shared actions', () => { ...@@ -570,7 +575,7 @@ describe('shared actions', () => {
describe('when called and the previous dashboard has completed', () => { describe('when called and the previous dashboard has completed', () => {
it('then correct actions are dispatched', async () => { it('then correct actions are dispatched', async () => {
const tester = await reduxTester<ReducersUsedInContext>() const tester = await reduxTester<RootReducerType>()
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenAsyncActionIsDispatched(initVariablesTransaction(uid, dashboard)); .whenAsyncActionIsDispatched(initVariablesTransaction(uid, dashboard));
...@@ -598,7 +603,7 @@ describe('shared actions', () => { ...@@ -598,7 +603,7 @@ describe('shared actions', () => {
it('then correct actions are dispatched', async () => { it('then correct actions are dispatched', async () => {
const transactionState = { uid: 'previous-uid', status: TransactionStatus.Fetching }; const transactionState = { uid: 'previous-uid', status: TransactionStatus.Fetching };
const tester = await reduxTester<ReducersUsedInContext>({ const tester = await reduxTester<RootReducerType>({
preloadedState: ({ preloadedState: ({
templating: { templating: {
transaction: transactionState, transaction: transactionState,
...@@ -606,7 +611,7 @@ describe('shared actions', () => { ...@@ -606,7 +611,7 @@ describe('shared actions', () => {
optionsPicker: { ...initialState }, optionsPicker: { ...initialState },
editor: { ...initialVariableEditorState }, editor: { ...initialVariableEditorState },
}, },
} as unknown) as ReducersUsedInContext, } as unknown) as RootReducerType,
}) })
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenAsyncActionIsDispatched(initVariablesTransaction(uid, dashboard)); .whenAsyncActionIsDispatched(initVariablesTransaction(uid, dashboard));
......
...@@ -516,7 +516,7 @@ export const onTimeRangeUpdated = ( ...@@ -516,7 +516,7 @@ export const onTimeRangeUpdated = (
} }
return false; return false;
}); }) as VariableWithOptions[];
const promises = variablesThatNeedRefresh.map((variable: VariableWithOptions) => const promises = variablesThatNeedRefresh.map((variable: VariableWithOptions) =>
dispatch(timeRangeUpdated(toVariableIdentifier(variable))) dispatch(timeRangeUpdated(toVariableIdentifier(variable)))
......
...@@ -7,7 +7,8 @@ import { VariablesState } from './variablesReducer'; ...@@ -7,7 +7,8 @@ import { VariablesState } from './variablesReducer';
import { locationReducer } from '../../../core/reducers/location'; import { locationReducer } from '../../../core/reducers/location';
import { VariableAdapter } from '../adapters'; import { VariableAdapter } from '../adapters';
import { dashboardReducer } from 'app/features/dashboard/state/reducers'; import { dashboardReducer } from 'app/features/dashboard/state/reducers';
import { templatingReducers } from './reducers'; import { templatingReducers, TemplatingState } from './reducers';
import { DashboardState, LocationState } from '../../../types';
export const getVariableState = ( export const getVariableState = (
noOfVariables: number, noOfVariables: number,
...@@ -76,6 +77,8 @@ export const getRootReducer = () => ...@@ -76,6 +77,8 @@ export const getRootReducer = () =>
templating: templatingReducers, templating: templatingReducers,
}); });
export type RootReducerType = { location: LocationState; dashboard: DashboardState; templating: TemplatingState };
export const getTemplatingRootReducer = () => export const getTemplatingRootReducer = () =>
combineReducers({ combineReducers({
templating: templatingReducers, templating: templatingReducers,
...@@ -86,3 +89,5 @@ export const getTemplatingAndLocationRootReducer = () => ...@@ -86,3 +89,5 @@ export const getTemplatingAndLocationRootReducer = () =>
templating: templatingReducers, templating: templatingReducers,
location: locationReducer, location: locationReducer,
}); });
export type TemplatingAndLocationReducerType = { location: LocationState; templating: TemplatingState };
...@@ -10,8 +10,7 @@ import { createConstantVariableAdapter } from '../constant/adapter'; ...@@ -10,8 +10,7 @@ import { createConstantVariableAdapter } from '../constant/adapter';
import { VariableRefresh } from '../types'; import { VariableRefresh } from '../types';
import { constantBuilder, intervalBuilder } from '../shared/testing/builders'; import { constantBuilder, intervalBuilder } from '../shared/testing/builders';
import { reduxTester } from '../../../../test/core/redux/reduxTester'; import { reduxTester } from '../../../../test/core/redux/reduxTester';
import { TemplatingState } from './reducers'; import { getRootReducer, RootReducerType } from './helpers';
import { getRootReducer } from './helpers';
import { toVariableIdentifier, toVariablePayload } from './types'; import { toVariableIdentifier, toVariablePayload } from './types';
import { import {
setCurrentVariableValue, setCurrentVariableValue,
...@@ -23,6 +22,7 @@ import { createIntervalOptions } from '../interval/reducer'; ...@@ -23,6 +22,7 @@ import { createIntervalOptions } from '../interval/reducer';
import { silenceConsoleOutput } from '../../../../test/core/utils/silenceConsoleOutput'; import { silenceConsoleOutput } from '../../../../test/core/utils/silenceConsoleOutput';
import { notifyApp } from '../../../core/reducers/appNotification'; import { notifyApp } from '../../../core/reducers/appNotification';
import { expect } from '../../../../test/lib/common'; import { expect } from '../../../../test/lib/common';
import { TemplatingState } from './reducers';
variableAdapters.setInit(() => [createIntervalVariableAdapter(), createConstantVariableAdapter()]); variableAdapters.setInit(() => [createIntervalVariableAdapter(), createConstantVariableAdapter()]);
...@@ -63,7 +63,7 @@ const getTestContext = () => { ...@@ -63,7 +63,7 @@ const getTestContext = () => {
} as unknown) as DashboardState; } as unknown) as DashboardState;
const startRefreshMock = jest.fn(); const startRefreshMock = jest.fn();
const adapter = variableAdapters.get('interval'); const adapter = variableAdapters.get('interval');
const preloadedState = { const preloadedState = ({
dashboard, dashboard,
location: { query: '' }, location: { query: '' },
templating: ({ templating: ({
...@@ -72,7 +72,7 @@ const getTestContext = () => { ...@@ -72,7 +72,7 @@ const getTestContext = () => {
'constant-1': { ...constant }, 'constant-1': { ...constant },
}, },
} as unknown) as TemplatingState, } as unknown) as TemplatingState,
}; } as unknown) as RootReducerType;
return { return {
interval, interval,
...@@ -98,7 +98,7 @@ describe('when onTimeRangeUpdated is dispatched', () => { ...@@ -98,7 +98,7 @@ describe('when onTimeRangeUpdated is dispatched', () => {
startRefreshMock, startRefreshMock,
} = getTestContext(); } = getTestContext();
const tester = await reduxTester<{ templating: TemplatingState }>({ preloadedState }) const tester = await reduxTester<RootReducerType>({ preloadedState })
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenAsyncActionIsDispatched(onTimeRangeUpdated(range, dependencies)); .whenAsyncActionIsDispatched(onTimeRangeUpdated(range, dependencies));
...@@ -133,7 +133,7 @@ describe('when onTimeRangeUpdated is dispatched', () => { ...@@ -133,7 +133,7 @@ describe('when onTimeRangeUpdated is dispatched', () => {
startRefreshMock, startRefreshMock,
} = getTestContext(); } = getTestContext();
const base = await reduxTester<{ templating: TemplatingState }>({ preloadedState }) const base = await reduxTester<RootReducerType>({ preloadedState })
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenAsyncActionIsDispatched(setOptionAsCurrent(toVariableIdentifier(interval), interval.options[0], false)); .whenAsyncActionIsDispatched(setOptionAsCurrent(toVariableIdentifier(interval), interval.options[0], false));
...@@ -173,7 +173,7 @@ describe('when onTimeRangeUpdated is dispatched', () => { ...@@ -173,7 +173,7 @@ describe('when onTimeRangeUpdated is dispatched', () => {
adapter.updateOptions = jest.fn().mockRejectedValue(new Error('Something broke')); adapter.updateOptions = jest.fn().mockRejectedValue(new Error('Something broke'));
const tester = await reduxTester<{ templating: TemplatingState }>({ preloadedState, debug: true }) const tester = await reduxTester<RootReducerType>({ preloadedState, debug: true })
.givenRootReducer(getRootReducer()) .givenRootReducer(getRootReducer())
.whenAsyncActionIsDispatched(onTimeRangeUpdated(range, dependencies), true); .whenAsyncActionIsDispatched(onTimeRangeUpdated(range, dependencies), true);
......
...@@ -2,6 +2,7 @@ import { reducerTester } from '../../../../test/core/redux/reducerTester'; ...@@ -2,6 +2,7 @@ import { reducerTester } from '../../../../test/core/redux/reducerTester';
import { import {
initialTransactionState, initialTransactionState,
transactionReducer, transactionReducer,
TransactionState,
TransactionStatus, TransactionStatus,
variablesClearTransaction, variablesClearTransaction,
variablesCompleteTransaction, variablesCompleteTransaction,
...@@ -11,7 +12,7 @@ import { ...@@ -11,7 +12,7 @@ import {
describe('transactionReducer', () => { describe('transactionReducer', () => {
describe('when variablesInitTransaction is dispatched', () => { describe('when variablesInitTransaction is dispatched', () => {
it('then state should be correct', () => { it('then state should be correct', () => {
reducerTester() reducerTester<TransactionState>()
.givenReducer(transactionReducer, { ...initialTransactionState }) .givenReducer(transactionReducer, { ...initialTransactionState })
.whenActionIsDispatched(variablesInitTransaction({ uid: 'a uid' })) .whenActionIsDispatched(variablesInitTransaction({ uid: 'a uid' }))
.thenStateShouldEqual({ ...initialTransactionState, uid: 'a uid', status: TransactionStatus.Fetching }); .thenStateShouldEqual({ ...initialTransactionState, uid: 'a uid', status: TransactionStatus.Fetching });
...@@ -21,7 +22,7 @@ describe('transactionReducer', () => { ...@@ -21,7 +22,7 @@ describe('transactionReducer', () => {
describe('when variablesCompleteTransaction is dispatched', () => { describe('when variablesCompleteTransaction is dispatched', () => {
describe('and transaction uid is the same', () => { describe('and transaction uid is the same', () => {
it('then state should be correct', () => { it('then state should be correct', () => {
reducerTester() reducerTester<TransactionState>()
.givenReducer(transactionReducer, { .givenReducer(transactionReducer, {
...initialTransactionState, ...initialTransactionState,
uid: 'before', uid: 'before',
...@@ -34,7 +35,7 @@ describe('transactionReducer', () => { ...@@ -34,7 +35,7 @@ describe('transactionReducer', () => {
describe('and transaction uid is not the same', () => { describe('and transaction uid is not the same', () => {
it('then state should be correct', () => { it('then state should be correct', () => {
reducerTester() reducerTester<TransactionState>()
.givenReducer(transactionReducer, { .givenReducer(transactionReducer, {
...initialTransactionState, ...initialTransactionState,
uid: 'before', uid: 'before',
...@@ -48,7 +49,7 @@ describe('transactionReducer', () => { ...@@ -48,7 +49,7 @@ describe('transactionReducer', () => {
describe('when variablesClearTransaction is dispatched', () => { describe('when variablesClearTransaction is dispatched', () => {
it('then state should be correct', () => { it('then state should be correct', () => {
reducerTester() reducerTester<TransactionState>()
.givenReducer(transactionReducer, { .givenReducer(transactionReducer, {
...initialTransactionState, ...initialTransactionState,
uid: 'before', uid: 'before',
......
import { createAction, PayloadAction } from '@reduxjs/toolkit'; import { createAction } from '@reduxjs/toolkit';
import { variableAdapters } from '../adapters'; import { variableAdapters } from '../adapters';
import { sharedReducer } from './sharedReducer'; import { sharedReducer } from './sharedReducer';
import { VariableModel } from '../types'; import { VariableModel } from '../types';
import { VariablePayload } from './types'; import { AnyAction } from 'redux';
export interface VariablesState extends Record<string, VariableModel> {} export interface VariablesState extends Record<string, VariableModel> {}
...@@ -10,10 +10,7 @@ export const initialVariablesState: VariablesState = {}; ...@@ -10,10 +10,7 @@ export const initialVariablesState: VariablesState = {};
export const cleanVariables = createAction<undefined>('templating/cleanVariables'); export const cleanVariables = createAction<undefined>('templating/cleanVariables');
export const variablesReducer = ( export const variablesReducer = (state: VariablesState = initialVariablesState, action: AnyAction): VariablesState => {
state: VariablesState = initialVariablesState,
action: PayloadAction<VariablePayload>
): VariablesState => {
if (cleanVariables.match(action)) { if (cleanVariables.match(action)) {
const globalVariables = Object.values(state).filter((v) => v.global); const globalVariables = Object.values(state).filter((v) => v.global);
if (!globalVariables) { if (!globalVariables) {
......
...@@ -20,8 +20,8 @@ export const createSystemVariableAdapter = (): VariableAdapter<SystemVariable<an ...@@ -20,8 +20,8 @@ export const createSystemVariableAdapter = (): VariableAdapter<SystemVariable<an
state: LoadingState.Done, state: LoadingState.Done,
}, },
reducer: (state: any, action: any) => state, reducer: (state: any, action: any) => state,
picker: (null as unknown) as ComponentType<VariablePickerProps>, picker: (null as unknown) as ComponentType<VariablePickerProps<SystemVariable<any>>>,
editor: (null as unknown) as ComponentType<VariableEditorProps>, editor: (null as unknown) as ComponentType<VariableEditorProps<SystemVariable<any>>>,
dependsOn: () => { dependsOn: () => {
return false; return false;
}, },
......
import React, { ChangeEvent, ReactElement, useCallback } from 'react'; import React, { FormEvent, ReactElement, useCallback } from 'react';
import { VerticalGroup } from '@grafana/ui'; import { VerticalGroup } from '@grafana/ui';
import { TextBoxVariableModel } from '../types'; import { TextBoxVariableModel } from '../types';
...@@ -11,16 +11,16 @@ export interface Props extends VariableEditorProps<TextBoxVariableModel> {} ...@@ -11,16 +11,16 @@ export interface Props extends VariableEditorProps<TextBoxVariableModel> {}
export function TextBoxVariableEditor({ onPropChange, variable: { query } }: Props): ReactElement { export function TextBoxVariableEditor({ onPropChange, variable: { query } }: Props): ReactElement {
const updateVariable = useCallback( const updateVariable = useCallback(
(event: ChangeEvent<HTMLInputElement>, updateOptions: boolean) => { (event: FormEvent<HTMLInputElement>, updateOptions: boolean) => {
event.preventDefault(); event.preventDefault();
onPropChange({ propName: 'originalQuery', propValue: event.target.value, updateOptions: false }); onPropChange({ propName: 'originalQuery', propValue: event.currentTarget.value, updateOptions: false });
onPropChange({ propName: 'query', propValue: event.target.value, updateOptions }); onPropChange({ propName: 'query', propValue: event.currentTarget.value, updateOptions });
}, },
[onPropChange] [onPropChange]
); );
const onChange = useCallback((e: ChangeEvent<HTMLInputElement>) => updateVariable(e, false), [updateVariable]); const onChange = useCallback((e: FormEvent<HTMLInputElement>) => updateVariable(e, false), [updateVariable]);
const onBlur = useCallback((e: ChangeEvent<HTMLInputElement>) => updateVariable(e, true), [updateVariable]); const onBlur = useCallback((e: FormEvent<HTMLInputElement>) => updateVariable(e, true), [updateVariable]);
return ( return (
<VerticalGroup spacing="xs"> <VerticalGroup spacing="xs">
......
import { variableAdapters } from '../adapters'; 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 { setTextBoxVariableOptionsFromUrl, updateTextBoxVariableOptions } from './actions'; import { setTextBoxVariableOptionsFromUrl, updateTextBoxVariableOptions } from './actions';
import { getRootReducer } from '../state/helpers'; import { getRootReducer, RootReducerType } from '../state/helpers';
import { VariableOption } from '../types'; import { VariableOption } from '../types';
import { toVariablePayload } from '../state/types'; import { toVariablePayload } from '../state/types';
import { createTextBoxOptions } from './reducer'; import { createTextBoxOptions } from './reducer';
...@@ -24,7 +23,7 @@ describe('textbox actions', () => { ...@@ -24,7 +23,7 @@ describe('textbox actions', () => {
const variable = textboxBuilder().withId('textbox').withName('textbox').withCurrent('A').withQuery('A').build(); const variable = textboxBuilder().withId('textbox').withName('textbox').withCurrent('A').withQuery('A').build();
const tester = await reduxTester<{ templating: TemplatingState }>() const tester = await reduxTester<RootReducerType>()
.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);
...@@ -42,7 +41,7 @@ describe('textbox actions', () => { ...@@ -42,7 +41,7 @@ describe('textbox actions', () => {
const urlValue = 'bB'; const urlValue = 'bB';
const variable = textboxBuilder().withId('textbox').withName('textbox').withCurrent('A').withQuery('A').build(); const variable = textboxBuilder().withId('textbox').withName('textbox').withCurrent('A').withQuery('A').build();
const tester = await reduxTester<{ templating: TemplatingState }>() const tester = await reduxTester<RootReducerType>()
.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(setTextBoxVariableOptionsFromUrl(toVariablePayload(variable), urlValue), true); .whenAsyncActionIsDispatched(setTextBoxVariableOptionsFromUrl(toVariablePayload(variable), urlValue), true);
......
...@@ -3,7 +3,7 @@ set -e ...@@ -3,7 +3,7 @@ set -e
echo -e "Collecting code stats (typescript errors & more)" echo -e "Collecting code stats (typescript errors & more)"
ERROR_COUNT_LIMIT=584 ERROR_COUNT_LIMIT=452
ERROR_COUNT="$(./node_modules/.bin/tsc --project tsconfig.json --noEmit --strict true | grep -oP 'Found \K(\d+)')" ERROR_COUNT="$(./node_modules/.bin/tsc --project tsconfig.json --noEmit --strict true | grep -oP 'Found \K(\d+)')"
if [ "$ERROR_COUNT" -gt $ERROR_COUNT_LIMIT ]; then if [ "$ERROR_COUNT" -gt $ERROR_COUNT_LIMIT ]; then
......
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