mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Explore: Fix rendering of react query editors (#24593)
* Fix rendering of react query editors * Refactor solution for improved readability * Update * Add test coverage * Refactor
This commit is contained in:
parent
f29b70b442
commit
285ea7595d
@ -305,12 +305,14 @@ export interface QueryEditorProps<
|
|||||||
query: TQuery;
|
query: TQuery;
|
||||||
onRunQuery: () => void;
|
onRunQuery: () => void;
|
||||||
onChange: (value: TQuery) => void;
|
onChange: (value: TQuery) => void;
|
||||||
|
onBlur?: () => void;
|
||||||
/**
|
/**
|
||||||
* Contains query response filtered by refId of QueryResultBase and possible query error
|
* Contains query response filtered by refId of QueryResultBase and possible query error
|
||||||
*/
|
*/
|
||||||
data?: PanelData;
|
data?: PanelData;
|
||||||
exploreMode?: ExploreMode;
|
exploreMode?: ExploreMode;
|
||||||
exploreId?: any;
|
exploreId?: any;
|
||||||
|
history?: HistoryItem[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum DataSourceStatus {
|
export enum DataSourceStatus {
|
||||||
|
74
public/app/features/explore/QueryRow.test.tsx
Normal file
74
public/app/features/explore/QueryRow.test.tsx
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { QueryRow, QueryRowProps } from './QueryRow';
|
||||||
|
import { shallow } from 'enzyme';
|
||||||
|
import { ExploreId } from 'app/types/explore';
|
||||||
|
import { Emitter } from 'app/core/utils/emitter';
|
||||||
|
import { DataSourceApi, TimeRange, AbsoluteTimeRange, ExploreMode, PanelData } from '@grafana/data';
|
||||||
|
|
||||||
|
const setup = (propOverrides?: object) => {
|
||||||
|
const props: QueryRowProps = {
|
||||||
|
exploreId: ExploreId.left,
|
||||||
|
index: 1,
|
||||||
|
exploreEvents: {} as Emitter,
|
||||||
|
changeQuery: jest.fn(),
|
||||||
|
datasourceInstance: {} as DataSourceApi,
|
||||||
|
highlightLogsExpressionAction: jest.fn() as any,
|
||||||
|
history: [],
|
||||||
|
query: {
|
||||||
|
refId: 'A',
|
||||||
|
},
|
||||||
|
modifyQueries: jest.fn(),
|
||||||
|
range: {} as TimeRange,
|
||||||
|
absoluteRange: {} as AbsoluteTimeRange,
|
||||||
|
removeQueryRowAction: jest.fn() as any,
|
||||||
|
runQueries: jest.fn(),
|
||||||
|
queryResponse: {} as PanelData,
|
||||||
|
mode: ExploreMode.Metrics,
|
||||||
|
latency: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.assign(props, propOverrides);
|
||||||
|
|
||||||
|
const wrapper = shallow(<QueryRow {...props} />);
|
||||||
|
return wrapper;
|
||||||
|
};
|
||||||
|
|
||||||
|
const ExploreMetricsQueryField = () => <div />;
|
||||||
|
const ExploreLogsQueryField = () => <div />;
|
||||||
|
const ExploreQueryField = () => <div />;
|
||||||
|
const QueryEditor = () => <div />;
|
||||||
|
|
||||||
|
describe('QueryRow', () => {
|
||||||
|
describe('if datasource has all query field components ', () => {
|
||||||
|
const allComponents = {
|
||||||
|
ExploreMetricsQueryField,
|
||||||
|
ExploreLogsQueryField,
|
||||||
|
ExploreQueryField,
|
||||||
|
QueryEditor,
|
||||||
|
};
|
||||||
|
|
||||||
|
it('it should render ExploreMetricsQueryField in metrics mode', () => {
|
||||||
|
const wrapper = setup({ mode: ExploreMode.Metrics, datasourceInstance: { components: allComponents } });
|
||||||
|
expect(wrapper.find(ExploreMetricsQueryField)).toHaveLength(1);
|
||||||
|
});
|
||||||
|
it('it should render ExploreLogsQueryField in logs mode', () => {
|
||||||
|
const wrapper = setup({ mode: ExploreMode.Logs, datasourceInstance: { components: allComponents } });
|
||||||
|
expect(wrapper.find(ExploreLogsQueryField)).toHaveLength(1);
|
||||||
|
});
|
||||||
|
it('it should render ExploreQueryField in tracing mode', () => {
|
||||||
|
const wrapper = setup({ mode: ExploreMode.Tracing, datasourceInstance: { components: allComponents } });
|
||||||
|
expect(wrapper.find(ExploreQueryField)).toHaveLength(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('if datasource does not have Explore query fields ', () => {
|
||||||
|
it('it should render QueryEditor if datasource has it', () => {
|
||||||
|
const wrapper = setup({ datasourceInstance: { components: { QueryEditor } } });
|
||||||
|
expect(wrapper.find(QueryEditor)).toHaveLength(1);
|
||||||
|
});
|
||||||
|
it('it should not render QueryEditor if datasource does not have it', () => {
|
||||||
|
const wrapper = setup({ datasourceInstance: { components: {} } });
|
||||||
|
expect(wrapper.find(QueryEditor)).toHaveLength(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -6,7 +6,7 @@ import { hot } from 'react-hot-loader';
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
// Components
|
// Components
|
||||||
import QueryEditor from './QueryEditor';
|
import AngularQueryEditor from './QueryEditor';
|
||||||
import { QueryRowActions } from './QueryRowActions';
|
import { QueryRowActions } from './QueryRowActions';
|
||||||
// Actions
|
// Actions
|
||||||
import { changeQuery, modifyQueries, runQueries } from './state/actions';
|
import { changeQuery, modifyQueries, runQueries } from './state/actions';
|
||||||
@ -34,7 +34,7 @@ interface PropsFromParent {
|
|||||||
exploreEvents: Emitter;
|
exploreEvents: Emitter;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface QueryRowProps extends PropsFromParent {
|
export interface QueryRowProps extends PropsFromParent {
|
||||||
changeQuery: typeof changeQuery;
|
changeQuery: typeof changeQuery;
|
||||||
className?: string;
|
className?: string;
|
||||||
exploreId: ExploreId;
|
exploreId: ExploreId;
|
||||||
@ -101,6 +101,69 @@ export class QueryRow extends PureComponent<QueryRowProps, QueryRowState> {
|
|||||||
this.setState({ textEditModeEnabled: !this.state.textEditModeEnabled });
|
this.setState({ textEditModeEnabled: !this.state.textEditModeEnabled });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
setReactQueryEditor = () => {
|
||||||
|
const { mode, datasourceInstance } = this.props;
|
||||||
|
let QueryEditor;
|
||||||
|
|
||||||
|
if (mode === ExploreMode.Metrics && datasourceInstance.components?.ExploreMetricsQueryField) {
|
||||||
|
QueryEditor = datasourceInstance.components.ExploreMetricsQueryField;
|
||||||
|
} else if (mode === ExploreMode.Logs && datasourceInstance.components?.ExploreLogsQueryField) {
|
||||||
|
QueryEditor = datasourceInstance.components.ExploreLogsQueryField;
|
||||||
|
} else if (datasourceInstance.components?.ExploreQueryField) {
|
||||||
|
QueryEditor = datasourceInstance.components.ExploreQueryField;
|
||||||
|
} else {
|
||||||
|
QueryEditor = datasourceInstance.components?.QueryEditor;
|
||||||
|
}
|
||||||
|
return QueryEditor;
|
||||||
|
};
|
||||||
|
|
||||||
|
renderQueryEditor = () => {
|
||||||
|
const {
|
||||||
|
datasourceInstance,
|
||||||
|
history,
|
||||||
|
query,
|
||||||
|
exploreEvents,
|
||||||
|
range,
|
||||||
|
absoluteRange,
|
||||||
|
queryResponse,
|
||||||
|
mode,
|
||||||
|
exploreId,
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
const queryErrors = queryResponse.error && queryResponse.error.refId === query.refId ? [queryResponse.error] : [];
|
||||||
|
|
||||||
|
const ReactQueryEditor = this.setReactQueryEditor();
|
||||||
|
|
||||||
|
if (ReactQueryEditor) {
|
||||||
|
return (
|
||||||
|
<ReactQueryEditor
|
||||||
|
datasource={datasourceInstance}
|
||||||
|
query={query}
|
||||||
|
history={history}
|
||||||
|
onRunQuery={this.onRunQuery}
|
||||||
|
onBlur={noopOnBlur}
|
||||||
|
onChange={this.onChange}
|
||||||
|
data={queryResponse}
|
||||||
|
absoluteRange={absoluteRange}
|
||||||
|
exploreMode={mode}
|
||||||
|
exploreId={exploreId}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<AngularQueryEditor
|
||||||
|
error={queryErrors}
|
||||||
|
datasource={datasourceInstance}
|
||||||
|
onQueryChange={this.onChange}
|
||||||
|
onExecuteQuery={this.onRunQuery}
|
||||||
|
initialQuery={query}
|
||||||
|
exploreEvents={exploreEvents}
|
||||||
|
range={range}
|
||||||
|
textEditModeEnabled={this.state.textEditModeEnabled}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
updateLogsHighlights = debounce((value: DataQuery) => {
|
updateLogsHighlights = debounce((value: DataQuery) => {
|
||||||
const { datasourceInstance } = this.props;
|
const { datasourceInstance } = this.props;
|
||||||
if (datasourceInstance.getHighlighterExpression) {
|
if (datasourceInstance.getHighlighterExpression) {
|
||||||
@ -111,63 +174,17 @@ export class QueryRow extends PureComponent<QueryRowProps, QueryRowState> {
|
|||||||
}, 500);
|
}, 500);
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const { datasourceInstance, query, queryResponse, mode, latency } = this.props;
|
||||||
datasourceInstance,
|
|
||||||
history,
|
|
||||||
query,
|
|
||||||
exploreEvents,
|
|
||||||
range,
|
|
||||||
absoluteRange,
|
|
||||||
queryResponse,
|
|
||||||
mode,
|
|
||||||
latency,
|
|
||||||
exploreId,
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
const canToggleEditorModes =
|
const canToggleEditorModes =
|
||||||
mode === ExploreMode.Metrics && has(datasourceInstance, 'components.QueryCtrl.prototype.toggleEditorMode');
|
mode === ExploreMode.Metrics && has(datasourceInstance, 'components.QueryCtrl.prototype.toggleEditorMode');
|
||||||
const isNotStarted = queryResponse.state === LoadingState.NotStarted;
|
const isNotStarted = queryResponse.state === LoadingState.NotStarted;
|
||||||
const queryErrors = queryResponse.error && queryResponse.error.refId === query.refId ? [queryResponse.error] : [];
|
const queryErrors = queryResponse.error && queryResponse.error.refId === query.refId ? [queryResponse.error] : [];
|
||||||
let QueryField;
|
|
||||||
|
|
||||||
if (mode === ExploreMode.Metrics && datasourceInstance.components?.ExploreMetricsQueryField) {
|
|
||||||
QueryField = datasourceInstance.components.ExploreMetricsQueryField;
|
|
||||||
} else if (mode === ExploreMode.Logs && datasourceInstance.components?.ExploreLogsQueryField) {
|
|
||||||
QueryField = datasourceInstance.components.ExploreLogsQueryField;
|
|
||||||
} else {
|
|
||||||
QueryField = datasourceInstance.components?.ExploreQueryField;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="query-row">
|
<div className="query-row">
|
||||||
<div className="query-row-field flex-shrink-1">
|
<div className="query-row-field flex-shrink-1">{this.renderQueryEditor()}</div>
|
||||||
{QueryField ? (
|
|
||||||
<QueryField
|
|
||||||
datasource={datasourceInstance}
|
|
||||||
query={query}
|
|
||||||
history={history}
|
|
||||||
onRunQuery={this.onRunQuery}
|
|
||||||
onBlur={noopOnBlur}
|
|
||||||
onChange={this.onChange}
|
|
||||||
data={queryResponse}
|
|
||||||
absoluteRange={absoluteRange}
|
|
||||||
exploreMode={mode}
|
|
||||||
exploreId={exploreId}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<QueryEditor
|
|
||||||
error={queryErrors}
|
|
||||||
datasource={datasourceInstance}
|
|
||||||
onQueryChange={this.onChange}
|
|
||||||
onExecuteQuery={this.onRunQuery}
|
|
||||||
initialQuery={query}
|
|
||||||
exploreEvents={exploreEvents}
|
|
||||||
range={range}
|
|
||||||
textEditModeEnabled={this.state.textEditModeEnabled}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<QueryRowActions
|
<QueryRowActions
|
||||||
canToggleEditorModes={canToggleEditorModes}
|
canToggleEditorModes={canToggleEditorModes}
|
||||||
isDisabled={query.hide}
|
isDisabled={query.hide}
|
||||||
|
Loading…
Reference in New Issue
Block a user