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;
|
||||
onRunQuery: () => void;
|
||||
onChange: (value: TQuery) => void;
|
||||
onBlur?: () => void;
|
||||
/**
|
||||
* Contains query response filtered by refId of QueryResultBase and possible query error
|
||||
*/
|
||||
data?: PanelData;
|
||||
exploreMode?: ExploreMode;
|
||||
exploreId?: any;
|
||||
history?: HistoryItem[];
|
||||
}
|
||||
|
||||
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
|
||||
import { connect } from 'react-redux';
|
||||
// Components
|
||||
import QueryEditor from './QueryEditor';
|
||||
import AngularQueryEditor from './QueryEditor';
|
||||
import { QueryRowActions } from './QueryRowActions';
|
||||
// Actions
|
||||
import { changeQuery, modifyQueries, runQueries } from './state/actions';
|
||||
@ -34,7 +34,7 @@ interface PropsFromParent {
|
||||
exploreEvents: Emitter;
|
||||
}
|
||||
|
||||
interface QueryRowProps extends PropsFromParent {
|
||||
export interface QueryRowProps extends PropsFromParent {
|
||||
changeQuery: typeof changeQuery;
|
||||
className?: string;
|
||||
exploreId: ExploreId;
|
||||
@ -101,6 +101,69 @@ export class QueryRow extends PureComponent<QueryRowProps, QueryRowState> {
|
||||
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) => {
|
||||
const { datasourceInstance } = this.props;
|
||||
if (datasourceInstance.getHighlighterExpression) {
|
||||
@ -111,63 +174,17 @@ export class QueryRow extends PureComponent<QueryRowProps, QueryRowState> {
|
||||
}, 500);
|
||||
|
||||
render() {
|
||||
const {
|
||||
datasourceInstance,
|
||||
history,
|
||||
query,
|
||||
exploreEvents,
|
||||
range,
|
||||
absoluteRange,
|
||||
queryResponse,
|
||||
mode,
|
||||
latency,
|
||||
exploreId,
|
||||
} = this.props;
|
||||
const { datasourceInstance, query, queryResponse, mode, latency } = this.props;
|
||||
|
||||
const canToggleEditorModes =
|
||||
mode === ExploreMode.Metrics && has(datasourceInstance, 'components.QueryCtrl.prototype.toggleEditorMode');
|
||||
const isNotStarted = queryResponse.state === LoadingState.NotStarted;
|
||||
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 (
|
||||
<>
|
||||
<div className="query-row">
|
||||
<div className="query-row-field flex-shrink-1">
|
||||
{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>
|
||||
<div className="query-row-field flex-shrink-1">{this.renderQueryEditor()}</div>
|
||||
<QueryRowActions
|
||||
canToggleEditorModes={canToggleEditorModes}
|
||||
isDisabled={query.hide}
|
||||
|
Loading…
Reference in New Issue
Block a user