Commit 9507eda9 by David Committed by GitHub

QueryField: Prevent query runs on blur in Explore (#20180)

As discussed in a UX feedback session, it's annoying that queries are
automatically executed in Explore. This change adds props to override
the blur behavior.

- add `onBlur` to Explore query field props
- Explore's query row will pass down an empty function for onBlur to the
query fields
- pass onBlur through to the QueryField component for Loki and
Prometheus
- add test to QueryField to make sure if onBlur is specified, the
onRunQuery is not executed
parent 620a3f2f
......@@ -281,6 +281,7 @@ export interface ExploreQueryFieldProps<
TOptions extends DataSourceJsonData = DataSourceJsonData
> extends QueryEditorProps<DSType, TQuery, TOptions> {
history: any[];
onBlur?: () => void;
onHint?: (action: QueryFixAction) => void;
}
......
import React from 'react';
import { shallow } from 'enzyme';
import { QueryField } from './QueryField';
import { Editor } from 'slate';
describe('<QueryField />', () => {
it('should render with null initial value', () => {
......@@ -17,4 +18,35 @@ describe('<QueryField />', () => {
const wrapper = shallow(<QueryField query="my query" onTypeahead={jest.fn()} portalOrigin="mock-origin" />);
expect(wrapper.find('div').exists()).toBeTruthy();
});
it('should execute query on blur', () => {
const onRun = jest.fn();
const wrapper = shallow(
<QueryField query="my query" onTypeahead={jest.fn()} onRunQuery={onRun} portalOrigin="mock-origin" />
);
const field = wrapper.instance() as QueryField;
expect(onRun.mock.calls.length).toBe(0);
field.handleBlur(new Event('bogus'), new Editor({}), () => {});
expect(onRun.mock.calls.length).toBe(1);
});
it('should run custom on blur, but not necessarily execute query', () => {
const onBlur = jest.fn();
const onRun = jest.fn();
const wrapper = shallow(
<QueryField
query="my query"
onTypeahead={jest.fn()}
onBlur={onBlur}
onRunQuery={onRun}
portalOrigin="mock-origin"
/>
);
const field = wrapper.instance() as QueryField;
expect(onBlur.mock.calls.length).toBe(0);
expect(onRun.mock.calls.length).toBe(0);
field.handleBlur(new Event('bogus'), new Editor({}), () => {});
expect(onBlur.mock.calls.length).toBe(1);
expect(onRun.mock.calls.length).toBe(0);
});
});
......@@ -27,6 +27,7 @@ export interface QueryFieldProps {
// creating a two way binding.
query: string | null;
onRunQuery?: () => void;
onBlur?: () => void;
onChange?: (value: string) => void;
onTypeahead?: (typeahead: TypeaheadInput) => Promise<TypeaheadOutput>;
onWillApplySuggestion?: (suggestion: string, state: SuggestionsState) => string;
......@@ -171,11 +172,17 @@ export class QueryField extends React.PureComponent<QueryFieldProps, QueryFieldS
* We need to handle blur events here mainly because of dashboard panels which expect to have query executed on blur.
*/
handleBlur = (event: Event, editor: CoreEditor, next: Function) => {
const previousValue = this.lastExecutedValue ? Plain.serialize(this.lastExecutedValue) : null;
const currentValue = Plain.serialize(editor.value);
if (previousValue !== currentValue) {
this.runOnChangeAndRunQuery();
const { onBlur } = this.props;
if (onBlur) {
onBlur();
} else {
// Run query by default on blur
const previousValue = this.lastExecutedValue ? Plain.serialize(this.lastExecutedValue) : null;
const currentValue = Plain.serialize(editor.value);
if (previousValue !== currentValue) {
this.runOnChangeAndRunQuery();
}
}
return next();
};
......
......@@ -57,6 +57,9 @@ interface QueryRowState {
textEditModeEnabled: boolean;
}
// Empty function to override blur execution on query field
const noopOnBlur = () => {};
export class QueryRow extends PureComponent<QueryRowProps, QueryRowState> {
state: QueryRowState = {
textEditModeEnabled: false,
......@@ -159,6 +162,7 @@ export class QueryRow extends PureComponent<QueryRowProps, QueryRowState> {
history={history}
onRunQuery={this.onRunQuery}
onHint={this.onClickHintFix}
onBlur={noopOnBlur}
onChange={this.onChange}
data={queryResponse}
absoluteRange={absoluteRange}
......
......@@ -172,6 +172,7 @@ export class LokiQueryFieldForm extends React.PureComponent<LokiQueryFieldFormPr
onTypeahead={this.onTypeahead}
onWillApplySuggestion={willApplySuggestion}
onChange={this.onChangeQuery}
onBlur={this.props.onBlur}
onRunQuery={this.props.onRunQuery}
placeholder="Enter a Loki query"
portalOrigin="loki"
......
......@@ -297,6 +297,7 @@ class PromQueryField extends React.PureComponent<PromQueryFieldProps, PromQueryF
query={query.expr}
onTypeahead={this.onTypeahead}
onWillApplySuggestion={willApplySuggestion}
onBlur={this.props.onBlur}
onChange={this.onChangeQuery}
onRunQuery={this.props.onRunQuery}
placeholder="Enter a PromQL query"
......
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