mirror of
https://github.com/grafana/grafana.git
synced 2026-07-30 00:08:10 -05:00
Variables: Explicitly type variable editor extended state (#44749)
* Narrow Variable editor state using selector functions - Explicitly type "extended" editor state in editor/reducter.ts using a union - Create selectors to narrow the types, using unique properties from each extended state to discriminate the union - Update DataSourceVariableEditor to use new style of redux connector - Update variable editor components to use new selectors * fix tests * Make adhoc variable infoText optional, because it is! * Add AdHocVariableEditor tests * DataSourceVariableEditor tests * comment * reset * Wrote tests for selectors \(that actually caught a bug, whodathunkit) * fix stray types and lint issues * Rename selector functions
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
import React from 'react';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
|
||||
import { AdHocVariableEditorUnConnected as AdHocVariableEditor } from './AdHocVariableEditor';
|
||||
import { initialAdHocVariableModelState } from './reducer';
|
||||
import { selectOptionInTest } from '@grafana/ui';
|
||||
import { getSelectParent } from '@grafana/ui/src/components/Select/test-utils';
|
||||
|
||||
const props = {
|
||||
extended: {
|
||||
dataSources: [
|
||||
{ text: 'Prometheus', value: null }, // default datasource
|
||||
{ text: 'Loki', value: { type: 'loki-ds', uid: 'abc' } },
|
||||
],
|
||||
},
|
||||
variable: { ...initialAdHocVariableModelState },
|
||||
onPropChange: jest.fn(),
|
||||
|
||||
// connected actions
|
||||
initAdHocVariableEditor: jest.fn(),
|
||||
changeVariableDatasource: jest.fn(),
|
||||
};
|
||||
|
||||
describe('AdHocVariableEditor', () => {
|
||||
beforeEach(() => {
|
||||
props.changeVariableDatasource.mockReset();
|
||||
});
|
||||
|
||||
it('has a datasource select menu', async () => {
|
||||
render(<AdHocVariableEditor {...props} />);
|
||||
|
||||
const selectContainer = getSelectParent(screen.getByLabelText('Data source'));
|
||||
expect(selectContainer).toHaveTextContent('Prometheus');
|
||||
});
|
||||
|
||||
it('calls the callback when changing the datasource', async () => {
|
||||
render(<AdHocVariableEditor {...props} />);
|
||||
await selectOptionInTest(screen.getByLabelText('Data source'), 'Loki');
|
||||
|
||||
expect(props.changeVariableDatasource).toBeCalledWith({ type: 'loki-ds', uid: 'abc' });
|
||||
});
|
||||
|
||||
it('renders informational text', () => {
|
||||
const extended = {
|
||||
...props.extended,
|
||||
infoText: "Here's a message that should help you",
|
||||
};
|
||||
render(<AdHocVariableEditor {...props} extended={extended} />);
|
||||
|
||||
const alert = screen.getByText("Here's a message that should help you");
|
||||
expect(alert).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -5,15 +5,14 @@ import { DataSourceRef, SelectableValue } from '@grafana/data';
|
||||
|
||||
import { AdHocVariableModel } from '../types';
|
||||
import { VariableEditorProps } from '../editor/types';
|
||||
import { VariableEditorState } from '../editor/reducer';
|
||||
import { AdHocVariableEditorState } from './reducer';
|
||||
import { changeVariableDatasource, initAdHocVariableEditor } from './actions';
|
||||
import { StoreState } from 'app/types';
|
||||
import { VariableSectionHeader } from '../editor/VariableSectionHeader';
|
||||
import { VariableSelectField } from '../editor/VariableSelectField';
|
||||
import { getAdhocVariableEditorState } from '../editor/selectors';
|
||||
|
||||
const mapStateToProps = (state: StoreState) => ({
|
||||
editor: state.templating.editor as VariableEditorState<AdHocVariableEditorState>,
|
||||
extended: getAdhocVariableEditorState(state.templating.editor),
|
||||
});
|
||||
|
||||
const mapDispatchToProps = {
|
||||
@@ -37,9 +36,9 @@ export class AdHocVariableEditorUnConnected extends PureComponent<Props> {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { variable, editor } = this.props;
|
||||
const dataSources = editor.extended?.dataSources ?? [];
|
||||
const infoText = editor.extended?.infoText ?? null;
|
||||
const { variable, extended } = this.props;
|
||||
const dataSources = extended?.dataSources ?? [];
|
||||
const infoText = extended?.infoText ?? null;
|
||||
const options = dataSources.map((ds) => ({ label: ds.text, value: ds.value }));
|
||||
const value = options.find((o) => o.value?.uid === variable.datasource?.uid) ?? options[0];
|
||||
|
||||
@@ -56,6 +55,7 @@ export class AdHocVariableEditorUnConnected extends PureComponent<Props> {
|
||||
labelWidth={10}
|
||||
/>
|
||||
</InlineFieldRow>
|
||||
|
||||
{infoText ? <Alert title={infoText} severity="info" /> : null}
|
||||
</VerticalGroup>
|
||||
</VerticalGroup>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
||||
import { DataSourceRef } from '@grafana/data';
|
||||
|
||||
import { AdHocVariableFilter, AdHocVariableModel, initialVariableModelState } from 'app/features/variables/types';
|
||||
import { getInstanceState, initialVariablesState, VariablePayload, VariablesState } from '../state/types';
|
||||
@@ -8,10 +7,6 @@ export interface AdHocVariabelFilterUpdate {
|
||||
index: number;
|
||||
filter: AdHocVariableFilter;
|
||||
}
|
||||
export interface AdHocVariableEditorState {
|
||||
infoText: string;
|
||||
dataSources: Array<{ text: string; value: DataSourceRef | null }>;
|
||||
}
|
||||
|
||||
export const initialAdHocVariableModelState: AdHocVariableModel = {
|
||||
...initialVariableModelState,
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
import React from 'react';
|
||||
import { render, screen, fireEvent } from '@testing-library/react';
|
||||
|
||||
import { DataSourceVariableEditorUnConnected as DataSourceVariableEditor } from './DataSourceVariableEditor';
|
||||
import { initialDataSourceVariableModelState } from './reducer';
|
||||
import { selectOptionInTest } from '@grafana/ui';
|
||||
import { getSelectParent } from '@grafana/ui/src/components/Select/test-utils';
|
||||
|
||||
const props = {
|
||||
extended: {
|
||||
dataSourceTypes: [
|
||||
{ text: 'Prometheus', value: 'ds-prom' },
|
||||
{ text: 'Loki', value: 'ds-loki' },
|
||||
],
|
||||
},
|
||||
variable: { ...initialDataSourceVariableModelState },
|
||||
onPropChange: jest.fn(),
|
||||
|
||||
// connected actions
|
||||
initDataSourceVariableEditor: jest.fn(),
|
||||
changeVariableMultiValue: jest.fn(),
|
||||
};
|
||||
|
||||
describe('DataSourceVariableEditor', () => {
|
||||
beforeEach(() => {
|
||||
props.onPropChange.mockReset();
|
||||
});
|
||||
|
||||
it('has a data source select menu', () => {
|
||||
render(<DataSourceVariableEditor {...props} />);
|
||||
|
||||
const selectContainer = getSelectParent(screen.getByLabelText('Type'));
|
||||
expect(selectContainer).toHaveTextContent('Prometheus');
|
||||
});
|
||||
|
||||
it('calls the handler when the data source is changed', async () => {
|
||||
render(<DataSourceVariableEditor {...props} />);
|
||||
await selectOptionInTest(screen.getByLabelText('Type'), 'Loki');
|
||||
|
||||
expect(props.onPropChange).toBeCalledWith({ propName: 'query', propValue: 'ds-loki', updateOptions: true });
|
||||
});
|
||||
|
||||
it('has a regex filter field', () => {
|
||||
render(<DataSourceVariableEditor {...props} />);
|
||||
const field = screen.getByLabelText('Instance name filter');
|
||||
expect(field).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('calls the handler when the regex filter is changed', () => {
|
||||
render(<DataSourceVariableEditor {...props} />);
|
||||
const field = screen.getByLabelText('Instance name filter');
|
||||
fireEvent.change(field, { target: { value: '/prod/' } });
|
||||
expect(props.onPropChange).toBeCalledWith({ propName: 'regex', propValue: '/prod/' });
|
||||
});
|
||||
});
|
||||
@@ -1,34 +1,34 @@
|
||||
import React, { FormEvent, PureComponent } from 'react';
|
||||
import { MapDispatchToProps, MapStateToProps } from 'react-redux';
|
||||
import { connect, ConnectedProps } from 'react-redux';
|
||||
import { InlineFieldRow, VerticalGroup } from '@grafana/ui';
|
||||
|
||||
import { DataSourceVariableModel, VariableWithMultiSupport } from '../types';
|
||||
import { OnPropChangeArguments, VariableEditorProps } from '../editor/types';
|
||||
import { SelectionOptionsEditor } from '../editor/SelectionOptionsEditor';
|
||||
import { VariableEditorState } from '../editor/reducer';
|
||||
import { DataSourceVariableEditorState } from './reducer';
|
||||
import { initDataSourceVariableEditor } from './actions';
|
||||
import { StoreState } from '../../../types';
|
||||
import { connectWithStore } from '../../../core/utils/connectWithReduxStore';
|
||||
import { changeVariableMultiValue } from '../state/actions';
|
||||
import { VariableSectionHeader } from '../editor/VariableSectionHeader';
|
||||
import { VariableSelectField } from '../editor/VariableSelectField';
|
||||
import { SelectableValue } from '@grafana/data';
|
||||
import { VariableTextField } from '../editor/VariableTextField';
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
import { getDatasourceVariableEditorState } from '../editor/selectors';
|
||||
|
||||
const mapStateToProps = (state: StoreState) => ({
|
||||
extended: getDatasourceVariableEditorState(state.templating.editor),
|
||||
});
|
||||
|
||||
const mapDispatchToProps = {
|
||||
initDataSourceVariableEditor,
|
||||
changeVariableMultiValue,
|
||||
};
|
||||
|
||||
const connector = connect(mapStateToProps, mapDispatchToProps);
|
||||
|
||||
export interface OwnProps extends VariableEditorProps<DataSourceVariableModel> {}
|
||||
|
||||
interface ConnectedProps {
|
||||
editor: VariableEditorState<DataSourceVariableEditorState>;
|
||||
}
|
||||
|
||||
interface DispatchProps {
|
||||
initDataSourceVariableEditor: typeof initDataSourceVariableEditor;
|
||||
changeVariableMultiValue: typeof changeVariableMultiValue;
|
||||
}
|
||||
|
||||
type Props = OwnProps & ConnectedProps & DispatchProps;
|
||||
type Props = OwnProps & ConnectedProps<typeof connector>;
|
||||
|
||||
export class DataSourceVariableEditorUnConnected extends PureComponent<Props> {
|
||||
componentDidMount() {
|
||||
@@ -55,11 +55,14 @@ export class DataSourceVariableEditorUnConnected extends PureComponent<Props> {
|
||||
};
|
||||
|
||||
getSelectedDataSourceTypeValue = (): string => {
|
||||
if (!this.props.editor.extended?.dataSourceTypes?.length) {
|
||||
const { extended } = this.props;
|
||||
|
||||
if (!extended?.dataSourceTypes.length) {
|
||||
return '';
|
||||
}
|
||||
const foundItem = this.props.editor.extended?.dataSourceTypes.find((ds) => ds.value === this.props.variable.query);
|
||||
const value = foundItem ? foundItem.value : this.props.editor.extended?.dataSourceTypes[0].value;
|
||||
|
||||
const foundItem = extended.dataSourceTypes.find((ds) => ds.value === this.props.variable.query);
|
||||
const value = foundItem ? foundItem.value : extended.dataSourceTypes[0].value;
|
||||
return value ?? '';
|
||||
};
|
||||
|
||||
@@ -68,10 +71,13 @@ export class DataSourceVariableEditorUnConnected extends PureComponent<Props> {
|
||||
};
|
||||
|
||||
render() {
|
||||
const typeOptions = this.props.editor.extended?.dataSourceTypes?.length
|
||||
? this.props.editor.extended?.dataSourceTypes?.map((ds) => ({ value: ds.value ?? '', label: ds.text }))
|
||||
const { variable, extended, changeVariableMultiValue } = this.props;
|
||||
|
||||
const typeOptions = extended?.dataSourceTypes?.length
|
||||
? extended.dataSourceTypes?.map((ds) => ({ value: ds.value ?? '', label: ds.text }))
|
||||
: [];
|
||||
const typeValue = typeOptions.find((o) => o.value === this.props.variable.query) ?? typeOptions[0];
|
||||
|
||||
const typeValue = typeOptions.find((o) => o.value === variable.query) ?? typeOptions[0];
|
||||
|
||||
return (
|
||||
<VerticalGroup spacing="xs">
|
||||
@@ -110,9 +116,9 @@ export class DataSourceVariableEditorUnConnected extends PureComponent<Props> {
|
||||
</VerticalGroup>
|
||||
|
||||
<SelectionOptionsEditor
|
||||
variable={this.props.variable}
|
||||
variable={variable}
|
||||
onPropChange={this.onSelectionOptionsChange}
|
||||
onMultiChanged={this.props.changeVariableMultiValue}
|
||||
onMultiChanged={changeVariableMultiValue}
|
||||
/>
|
||||
</VerticalGroup>
|
||||
</VerticalGroup>
|
||||
@@ -120,17 +126,4 @@ export class DataSourceVariableEditorUnConnected extends PureComponent<Props> {
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps: MapStateToProps<ConnectedProps, OwnProps, StoreState> = (state, ownProps) => ({
|
||||
editor: state.templating.editor as VariableEditorState<DataSourceVariableEditorState>,
|
||||
});
|
||||
|
||||
const mapDispatchToProps: MapDispatchToProps<DispatchProps, OwnProps> = {
|
||||
initDataSourceVariableEditor,
|
||||
changeVariableMultiValue,
|
||||
};
|
||||
|
||||
export const DataSourceVariableEditor = connectWithStore(
|
||||
DataSourceVariableEditorUnConnected,
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
);
|
||||
export const DataSourceVariableEditor = connector(DataSourceVariableEditorUnConnected);
|
||||
|
||||
@@ -5,10 +5,6 @@ import { DataSourceVariableModel, initialVariableModelState, VariableOption, Var
|
||||
import { getInstanceState, initialVariablesState, VariablePayload, VariablesState } from '../state/types';
|
||||
import { ALL_VARIABLE_TEXT, ALL_VARIABLE_VALUE } from '../constants';
|
||||
|
||||
export interface DataSourceVariableEditorState {
|
||||
dataSourceTypes: Array<{ text: string; value: string }>;
|
||||
}
|
||||
|
||||
export const initialDataSourceVariableModelState: DataSourceVariableModel = {
|
||||
...initialVariableModelState,
|
||||
type: 'datasource',
|
||||
|
||||
@@ -62,7 +62,7 @@ describe('variableEditorReducer', () => {
|
||||
name: 'A name',
|
||||
isValid: false,
|
||||
errors: { update: 'Something wrong' },
|
||||
extended: { prop: 1000 },
|
||||
extended: null,
|
||||
};
|
||||
const payload = toVariablePayload({ id: '0', type: 'textbox' });
|
||||
reducerTester<VariableEditorState>()
|
||||
@@ -188,6 +188,7 @@ describe('variableEditorReducer', () => {
|
||||
.thenStateShouldEqual({
|
||||
...initialVariableEditorState,
|
||||
extended: {
|
||||
// @ts-ignore - temp ignoring this, we'll fix it soon
|
||||
someProp: [{}],
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,13 +1,30 @@
|
||||
import { DataSourceApi, DataSourceRef } from '@grafana/data';
|
||||
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
||||
import { VariablePayload } from '../state/types';
|
||||
import { VariableQueryEditorType } from '../types';
|
||||
|
||||
type VariableEditorExtension<ExtendedProps extends {} = {}> = { [P in keyof ExtendedProps]: ExtendedProps[P] };
|
||||
export interface VariableEditorState<ExtendedProps extends {} = {}> {
|
||||
export interface AdHocVariableEditorState {
|
||||
infoText?: string;
|
||||
dataSources: Array<{ text: string; value: DataSourceRef | null }>;
|
||||
}
|
||||
|
||||
export interface DataSourceVariableEditorState {
|
||||
dataSourceTypes: Array<{ text: string; value: string }>;
|
||||
}
|
||||
|
||||
export interface QueryVariableEditorState {
|
||||
VariableQueryEditor: VariableQueryEditorType;
|
||||
dataSource: DataSourceApi | null;
|
||||
}
|
||||
|
||||
type VariableEditorExtension = AdHocVariableEditorState | DataSourceVariableEditorState | QueryVariableEditorState;
|
||||
|
||||
export interface VariableEditorState {
|
||||
id: string;
|
||||
name: string;
|
||||
errors: Record<string, string>;
|
||||
isValid: boolean;
|
||||
extended: VariableEditorExtension<ExtendedProps> | null;
|
||||
extended: VariableEditorExtension | null;
|
||||
}
|
||||
|
||||
export const initialVariableEditorState: VariableEditorState = {
|
||||
@@ -65,6 +82,7 @@ const variableEditorReducerSlice = createSlice({
|
||||
state: VariableEditorState,
|
||||
action: PayloadAction<{ propName: string; propValue: any }>
|
||||
) => {
|
||||
// @ts-ignore - temp ignoring the errors now the state type is more strict
|
||||
state.extended = {
|
||||
...state.extended,
|
||||
[action.payload.propName]: action.payload.propValue,
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
import {
|
||||
getAdhocVariableEditorState,
|
||||
getDatasourceVariableEditorState,
|
||||
getQueryVariableEditorState,
|
||||
} from './selectors';
|
||||
import {
|
||||
AdHocVariableEditorState,
|
||||
DataSourceVariableEditorState,
|
||||
initialVariableEditorState,
|
||||
QueryVariableEditorState,
|
||||
} from './reducer';
|
||||
import { LegacyVariableQueryEditor } from './LegacyVariableQueryEditor';
|
||||
import { DataSourceApi } from '@grafana/data';
|
||||
|
||||
const adhocExtended: AdHocVariableEditorState = {
|
||||
dataSources: [
|
||||
{ text: 'Prometheus', value: null }, // default datasource
|
||||
{ text: 'Loki', value: { type: 'loki-ds', uid: 'abc' } },
|
||||
],
|
||||
};
|
||||
|
||||
const datasourceExtended: DataSourceVariableEditorState = {
|
||||
dataSourceTypes: [
|
||||
{ text: 'Prometheus', value: 'ds-prom' },
|
||||
{ text: 'Loki', value: 'ds-loki' },
|
||||
],
|
||||
};
|
||||
|
||||
const queryExtended: QueryVariableEditorState = {
|
||||
VariableQueryEditor: LegacyVariableQueryEditor,
|
||||
dataSource: {} as unknown as DataSourceApi,
|
||||
};
|
||||
|
||||
const adhocVariableState = {
|
||||
...initialVariableEditorState,
|
||||
extended: adhocExtended,
|
||||
};
|
||||
|
||||
const datasourceVariableState = {
|
||||
...initialVariableEditorState,
|
||||
extended: datasourceExtended,
|
||||
};
|
||||
|
||||
const queryVariableState = {
|
||||
...initialVariableEditorState,
|
||||
extended: queryExtended,
|
||||
};
|
||||
|
||||
describe('getAdhocVariableEditorState', () => {
|
||||
it('returns the extended properties for adhoc variable state', () => {
|
||||
expect(getAdhocVariableEditorState(adhocVariableState)).toBe(adhocExtended);
|
||||
});
|
||||
|
||||
it('returns null for datasource variable state', () => {
|
||||
expect(getAdhocVariableEditorState(datasourceVariableState)).toBeNull();
|
||||
});
|
||||
|
||||
it('returns null for query variable state', () => {
|
||||
expect(getAdhocVariableEditorState(queryVariableState)).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getDatasourceVariableEditorState', () => {
|
||||
it('returns the extended properties for datasource variable state', () => {
|
||||
expect(getDatasourceVariableEditorState(datasourceVariableState)).toBe(datasourceExtended);
|
||||
});
|
||||
|
||||
it('returns null for adhoc variable state', () => {
|
||||
expect(getDatasourceVariableEditorState(adhocVariableState)).toBeNull();
|
||||
});
|
||||
|
||||
it('returns null for query variable state', () => {
|
||||
expect(getDatasourceVariableEditorState(queryVariableState)).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getQueryVariableEditorState', () => {
|
||||
it('returns the extended properties for query variable state', () => {
|
||||
expect(getQueryVariableEditorState(queryVariableState)).toBe(queryExtended);
|
||||
});
|
||||
|
||||
it('returns null for adhoc variable state', () => {
|
||||
expect(getQueryVariableEditorState(adhocVariableState)).toBeNull();
|
||||
});
|
||||
|
||||
it('returns null for datasource variable state', () => {
|
||||
expect(getQueryVariableEditorState(datasourceVariableState)).toBeNull();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,41 @@
|
||||
import {
|
||||
AdHocVariableEditorState,
|
||||
DataSourceVariableEditorState,
|
||||
QueryVariableEditorState,
|
||||
VariableEditorState,
|
||||
} from './reducer';
|
||||
|
||||
/**
|
||||
* Narrows generic variable editor state down to specific Adhoc variable extended editor state
|
||||
*/
|
||||
export function getAdhocVariableEditorState(editorState: VariableEditorState): AdHocVariableEditorState | null {
|
||||
if (editorState.extended && 'dataSources' in editorState.extended) {
|
||||
return editorState.extended;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Narrows generic variable editor state down to specific Datasource variable extended editor state
|
||||
*/
|
||||
export function getDatasourceVariableEditorState(
|
||||
editorState: VariableEditorState
|
||||
): DataSourceVariableEditorState | null {
|
||||
if (editorState.extended && 'dataSourceTypes' in editorState.extended) {
|
||||
return editorState.extended;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Narrows generic variable editor state down to specific Query variable extended editor state
|
||||
*/
|
||||
export function getQueryVariableEditorState(editorState: VariableEditorState): QueryVariableEditorState | null {
|
||||
if (editorState.extended && 'dataSource' in editorState.extended) {
|
||||
return editorState.extended;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -5,7 +5,6 @@ import { DataSourceApi } from '@grafana/data';
|
||||
|
||||
import { Props, QueryVariableEditorUnConnected } from './QueryVariableEditor';
|
||||
import { initialQueryVariableModelState } from './reducer';
|
||||
import { initialVariableEditorState } from '../editor/reducer';
|
||||
import { describe, expect } from '../../../../test/lib/common';
|
||||
import { LegacyVariableQueryEditor } from '../editor/LegacyVariableQueryEditor';
|
||||
import { mockDataSource } from 'app/features/alerting/unified/mocks';
|
||||
@@ -13,19 +12,17 @@ import { DataSourceType } from 'app/features/alerting/unified/utils/datasource';
|
||||
import { NEW_VARIABLE_ID } from '../constants';
|
||||
|
||||
const setupTestContext = (options: Partial<Props>) => {
|
||||
const extended = {
|
||||
VariableQueryEditor: LegacyVariableQueryEditor,
|
||||
dataSource: {} as unknown as DataSourceApi,
|
||||
};
|
||||
const defaults: Props = {
|
||||
variable: { ...initialQueryVariableModelState },
|
||||
initQueryVariableEditor: jest.fn(),
|
||||
changeQueryVariableDataSource: jest.fn(),
|
||||
changeQueryVariableQuery: jest.fn(),
|
||||
changeVariableMultiValue: jest.fn(),
|
||||
editor: {
|
||||
...initialVariableEditorState,
|
||||
extended: {
|
||||
VariableQueryEditor: LegacyVariableQueryEditor,
|
||||
dataSource: {} as unknown as DataSourceApi,
|
||||
},
|
||||
},
|
||||
extended,
|
||||
onPropChange: jest.fn(),
|
||||
};
|
||||
|
||||
|
||||
@@ -8,9 +8,7 @@ import { DataSourceInstanceSettings, getDataSourceRef, LoadingState, SelectableV
|
||||
|
||||
import { SelectionOptionsEditor } from '../editor/SelectionOptionsEditor';
|
||||
import { QueryVariableModel, VariableRefresh, VariableSort, VariableWithMultiSupport } from '../types';
|
||||
import { QueryVariableEditorState } from './reducer';
|
||||
import { changeQueryVariableDataSource, changeQueryVariableQuery, initQueryVariableEditor } from './actions';
|
||||
import { VariableEditorState } from '../editor/reducer';
|
||||
import { OnPropChangeArguments, VariableEditorProps } from '../editor/types';
|
||||
import { StoreState } from '../../../types';
|
||||
import { toVariableIdentifier } from '../state/types';
|
||||
@@ -21,9 +19,10 @@ import { VariableSectionHeader } from '../editor/VariableSectionHeader';
|
||||
import { VariableTextField } from '../editor/VariableTextField';
|
||||
import { QueryVariableRefreshSelect } from './QueryVariableRefreshSelect';
|
||||
import { QueryVariableSortSelect } from './QueryVariableSortSelect';
|
||||
import { getQueryVariableEditorState } from '../editor/selectors';
|
||||
|
||||
const mapStateToProps = (state: StoreState) => ({
|
||||
editor: state.templating.editor as VariableEditorState<QueryVariableEditorState>,
|
||||
extended: getQueryVariableEditorState(state.templating.editor),
|
||||
});
|
||||
|
||||
const mapDispatchToProps = {
|
||||
@@ -114,14 +113,15 @@ export class QueryVariableEditorUnConnected extends PureComponent<Props, State>
|
||||
};
|
||||
|
||||
renderQueryEditor = () => {
|
||||
const { editor, variable } = this.props;
|
||||
if (!editor.extended || !editor.extended.dataSource || !editor.extended.VariableQueryEditor) {
|
||||
const { extended, variable } = this.props;
|
||||
|
||||
if (!extended || !extended.dataSource || !extended.VariableQueryEditor) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const query = variable.query;
|
||||
const datasource = editor.extended.dataSource;
|
||||
const VariableQueryEditor = editor.extended.VariableQueryEditor;
|
||||
const datasource = extended.dataSource;
|
||||
const VariableQueryEditor = extended.VariableQueryEditor;
|
||||
|
||||
if (isLegacyQueryEditor(VariableQueryEditor, datasource)) {
|
||||
return (
|
||||
|
||||
@@ -6,19 +6,14 @@ import { updateOptions } from '../state/actions';
|
||||
import { QueryVariableModel } from '../types';
|
||||
import { ThunkResult } from '../../../types';
|
||||
import { getVariable } from '../state/selectors';
|
||||
import {
|
||||
addVariableEditorError,
|
||||
changeVariableEditorExtended,
|
||||
removeVariableEditorError,
|
||||
VariableEditorState,
|
||||
} from '../editor/reducer';
|
||||
import { addVariableEditorError, changeVariableEditorExtended, removeVariableEditorError } from '../editor/reducer';
|
||||
import { changeVariableProp } from '../state/sharedReducer';
|
||||
import { toVariableIdentifier, toVariablePayload, VariableIdentifier } from '../state/types';
|
||||
import { getVariableQueryEditor } from '../editor/getVariableQueryEditor';
|
||||
import { getVariableQueryRunner } from './VariableQueryRunner';
|
||||
import { variableQueryObserver } from './variableQueryObserver';
|
||||
import { QueryVariableEditorState } from './reducer';
|
||||
import { hasOngoingTransaction } from '../utils';
|
||||
import { getQueryVariableEditorState } from '../editor/selectors';
|
||||
|
||||
export const updateQueryVariableOptions = (
|
||||
identifier: VariableIdentifier,
|
||||
@@ -71,8 +66,8 @@ export const changeQueryVariableDataSource = (
|
||||
): ThunkResult<void> => {
|
||||
return async (dispatch, getState) => {
|
||||
try {
|
||||
const editorState = getState().templating.editor as VariableEditorState<QueryVariableEditorState>;
|
||||
const previousDatasource = editorState.extended?.dataSource;
|
||||
const extendedEditorState = getQueryVariableEditorState(getState().templating.editor);
|
||||
const previousDatasource = extendedEditorState?.dataSource;
|
||||
const dataSource = await getDataSourceSrv().get(name ?? '');
|
||||
if (previousDatasource && previousDatasource.type !== dataSource?.type) {
|
||||
dispatch(changeVariableProp(toVariablePayload(identifier, { propName: 'query', propValue: '' })));
|
||||
|
||||
@@ -1,15 +1,8 @@
|
||||
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
||||
import { isNumber, sortBy, toLower, uniqBy } from 'lodash';
|
||||
import { DataSourceApi, MetricFindValue, stringToJsRegex } from '@grafana/data';
|
||||
import { MetricFindValue, stringToJsRegex } from '@grafana/data';
|
||||
|
||||
import {
|
||||
initialVariableModelState,
|
||||
QueryVariableModel,
|
||||
VariableOption,
|
||||
VariableQueryEditorType,
|
||||
VariableRefresh,
|
||||
VariableSort,
|
||||
} from '../types';
|
||||
import { initialVariableModelState, QueryVariableModel, VariableOption, VariableRefresh, VariableSort } from '../types';
|
||||
|
||||
import { getInstanceState, initialVariablesState, VariablePayload, VariablesState } from '../state/types';
|
||||
import { ALL_VARIABLE_TEXT, ALL_VARIABLE_VALUE, NONE_VARIABLE_TEXT, NONE_VARIABLE_VALUE } from '../constants';
|
||||
@@ -19,11 +12,6 @@ interface VariableOptionsUpdate {
|
||||
results: MetricFindValue[];
|
||||
}
|
||||
|
||||
export interface QueryVariableEditorState {
|
||||
VariableQueryEditor: VariableQueryEditorType;
|
||||
dataSource: DataSourceApi | null;
|
||||
}
|
||||
|
||||
export const initialQueryVariableModelState: QueryVariableModel = {
|
||||
...initialVariableModelState,
|
||||
type: 'query',
|
||||
|
||||
Reference in New Issue
Block a user