Skip to content

Commit 22febe5

Browse files
committed
Fix query button
1 parent 2c57ad4 commit 22febe5

File tree

1 file changed

+63
-51
lines changed

1 file changed

+63
-51
lines changed

src/components/QueryEditor.tsx

Lines changed: 63 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import React from 'react';
2-
import { ChangeEvent, useState } from 'react';
1+
import React, { ChangeEvent, useState } from 'react';
32
import {
43
Button,
54
InlineField,
@@ -9,17 +8,15 @@ import {
98
InlineSwitch,
109
Modal,
1110
useTheme2,
12-
Tooltip,
1311
} from '@grafana/ui';
1412
import { EditorHeader, InlineSelect, FlexItem } from '@grafana/plugin-ui';
15-
import { CoreApp, QueryEditorProps, SelectableValue } from '@grafana/data';
13+
import { CoreApp, QueryEditorProps, SelectableValue, LoadingState } from '@grafana/data';
1614
import { DataSource } from '../datasource';
1715
import { MongoDataSourceOptions, MongoQuery, QueryLanguage, QueryType, DEFAULT_QUERY } from '../types';
1816
import { parseJsQuery, parseJsQueryLegacy } from '../utils';
1917
import { QueryEditorRaw } from './QueryEditorRaw';
2018
import { QueryToolbox } from './QueryToolbox';
2119
import validator from 'validator';
22-
import './QueryEditor.css';
2320

2421
type Props = QueryEditorProps<DataSource, MongoQuery, MongoDataSourceOptions>;
2522

@@ -43,32 +40,14 @@ const languageOptions: Array<SelectableValue<string>> = [
4340
];
4441

4542
export function QueryEditor(props: Props) {
46-
const { query, app, onRunQuery } = props;
43+
const { query, app, data, onRunQuery } = props;
4744

4845
const theme = useTheme2();
4946

5047
const [queryTextError, setQueryTextError] = useState<string | null>(null);
5148
const [isAggregateOptionExpanded, setIsAggregateOptionExpanded] = useState(false);
5249
const [isEditorExpanded, setIsEditorExpanded] = useState(false);
5350

54-
55-
const renderRunButton = (isQueryRunnable: boolean) => {
56-
if (isQueryRunnable) {
57-
return (
58-
<Button icon="play" variant="primary" size="sm" onClick={() => onRunQuery()}>
59-
Run query
60-
</Button>
61-
);
62-
}
63-
return (
64-
<Tooltip theme="error" content={<>Your query is invalid. Check below for details.</>} placement="top">
65-
<Button icon="exclamation-triangle" variant="secondary" size="sm" onClick={onRunQuery}>
66-
Run query
67-
</Button>
68-
</Tooltip>
69-
);
70-
};
71-
7251
const renderCodeEditor = (showTools: boolean, width?: number, height?: number) => {
7352
return (
7453
<>
@@ -88,21 +67,34 @@ export function QueryEditor(props: Props) {
8867
placeholder="Select query language"
8968
options={languageOptions}
9069
value={query.queryLanguage}
91-
onChange={val => props.onChange({ ...query, queryLanguage: val.value })}
70+
onChange={(val) => props.onChange({ ...query, queryLanguage: val.value })}
9271
/>
9372
<FlexItem grow={1} />
94-
{renderRunButton(true)}
73+
{!query.isStreaming && (
74+
<Button
75+
icon="play"
76+
variant="primary"
77+
size="sm"
78+
onClick={() => onRunQuery()}
79+
disabled={data?.state === LoadingState.Loading}
80+
>
81+
Run query
82+
</Button>
83+
)}
9584
</EditorHeader>
9685
)}
9786
<QueryEditorRaw
98-
query={query.queryText || ''}
87+
query={query.queryText ?? ''}
9988
language={
10089
query.queryLanguage === QueryLanguage.JAVASCRIPT || query.queryLanguage === QueryLanguage.JAVASCRIPT_SHADOW
10190
? 'javascript'
10291
: 'json'
10392
}
10493
onBlur={(queryText: string) => {
105-
if (query.queryLanguage === QueryLanguage.JAVASCRIPT || query.queryLanguage === QueryLanguage.JAVASCRIPT_SHADOW) {
94+
if (
95+
query.queryLanguage === QueryLanguage.JAVASCRIPT ||
96+
query.queryLanguage === QueryLanguage.JAVASCRIPT_SHADOW
97+
) {
10698
// parse the JavaScript query
10799
const { error, collection } =
108100
query.queryLanguage === QueryLanguage.JAVASCRIPT_SHADOW
@@ -114,7 +106,7 @@ export function QueryEditor(props: Props) {
114106
} else {
115107
props.onChange({ ...query, queryText: queryText });
116108
if (!validator.isJSON(queryText)) {
117-
setQueryTextError("Query should be a valid JSON")
109+
setQueryTextError('Query should be a valid JSON');
118110
} else {
119111
setQueryTextError(null);
120112
}
@@ -163,25 +155,30 @@ export function QueryEditor(props: Props) {
163155
<>
164156
<InlineFieldRow>
165157
<InlineField
166-
label="Collection" error="Collection is required"
158+
label="Collection"
159+
error="Collection is required"
167160
invalid={query.queryLanguage !== QueryLanguage.JAVASCRIPT && !query.collection}
168161
tooltip="Name of MongoDB collection to query"
169162
>
170163
<Input
171-
width={25} id="query-editor-collection" value={query.collection}
172-
onChange={(evt: ChangeEvent<HTMLInputElement>) => props.onChange({ ...query, collection: evt.target.value })}
164+
width={25}
165+
id="query-editor-collection"
166+
value={query.collection}
167+
onChange={(evt: ChangeEvent<HTMLInputElement>) =>
168+
props.onChange({ ...query, collection: evt.target.value })
169+
}
173170
disabled={query.queryLanguage === QueryLanguage.JAVASCRIPT}
174171
/>
175172
</InlineField>
176-
{app !== CoreApp.Explore && <InlineField label="Streaming" tooltip="Watch MongoDB change streams">
177-
<InlineSwitch
178-
id="query-editor-collection-streaming"
179-
value={query.isStreaming === true}
180-
onChange={evt => props.onChange({ ...query, isStreaming: evt.currentTarget.checked })}
181-
/>
182-
</InlineField>
183-
}
184-
173+
{app !== CoreApp.Explore && (
174+
<InlineField label="Streaming" tooltip="(Experimental) Watch MongoDB change streams">
175+
<InlineSwitch
176+
id="query-editor-collection-streaming"
177+
value={query.isStreaming === true}
178+
onChange={(evt) => props.onChange({ ...query, isStreaming: evt.currentTarget.checked })}
179+
/>
180+
</InlineField>
181+
)}
185182
</InlineFieldRow>
186183
{isEditorExpanded ? renderPlaceholder() : renderCodeEditor(true, undefined, 300)}
187184

@@ -196,7 +193,8 @@ export function QueryEditor(props: Props) {
196193
tooltip="The maximum amount of time that the query can run on the server. The default value is nil, meaning that there is no time limit for query execution."
197194
>
198195
<Input
199-
id="query-editor-max-time-ms" value={query.aggregateMaxTimeMS}
196+
id="query-editor-max-time-ms"
197+
value={query.aggregateMaxTimeMS}
200198
onChange={(evt: ChangeEvent<HTMLInputElement>) => {
201199
if (!evt.target.value) {
202200
props.onChange({ ...query, aggregateMaxTimeMS: undefined });
@@ -210,33 +208,41 @@ export function QueryEditor(props: Props) {
210208
label="Max await time(ms)"
211209
tooltip="The maximum amount of time that the server should wait for new documents to satisfy a tailable cursor query."
212210
>
213-
<Input id="query-editor-max-await-time-ms" value={query.aggregateMaxAwaitTime}
211+
<Input
212+
id="query-editor-max-await-time-ms"
213+
value={query.aggregateMaxAwaitTime}
214214
onChange={(evt: ChangeEvent<HTMLInputElement>) => {
215215
if (!evt.target.value) {
216216
props.onChange({ ...query, aggregateMaxAwaitTime: undefined });
217217
} else if (validator.isInt(evt.target.value, { gt: 0 })) {
218218
props.onChange({ ...query, aggregateMaxAwaitTime: parseInt(evt.target.value, 10) });
219219
}
220-
}} />
220+
}}
221+
/>
221222
</InlineField>
222223
</InlineFieldRow>
223224
<InlineFieldRow>
224225
<InlineField
225226
label="Comment"
226227
tooltip="A string that will be included in server logs, profiling logs, and currentOp queries to help trace the operation."
227228
>
228-
<Input id="query-editor-comment" value={query.aggregateComment}
229+
<Input
230+
id="query-editor-comment"
231+
value={query.aggregateComment}
229232
onChange={(evt: ChangeEvent<HTMLInputElement>) => {
230233
if (evt.target.value) {
231234
props.onChange({ ...query, aggregateComment: evt.target.value });
232235
}
233-
}} />
236+
}}
237+
/>
234238
</InlineField>
235239
<InlineField
236240
label="Batch size"
237241
tooltip="The maximum number of documents to be included in each batch returned by the server."
238242
>
239-
<Input id="query-editor-batch-size" value={query.aggregateBatchSize}
243+
<Input
244+
id="query-editor-batch-size"
245+
value={query.aggregateBatchSize}
240246
onChange={(evt: ChangeEvent<HTMLInputElement>) => {
241247
if (validator.isInt(evt.target.value, { gt: 0 })) {
242248
props.onChange({ ...query, aggregateBatchSize: parseInt(evt.target.value, 10) });
@@ -251,17 +257,23 @@ export function QueryEditor(props: Props) {
251257
tooltip="If true, the operation can write to temporary files in the _tmp subdirectory of the database directory path on the server. The default value is false."
252258
>
253259
<InlineSwitch
254-
id="query-editor-allow-disk-use" value={query.aggregateAllowDiskUse}
255-
onChange={(evt: ChangeEvent<HTMLInputElement>) => props.onChange({ ...query, aggregateAllowDiskUse: evt.target.checked })}
260+
id="query-editor-allow-disk-use"
261+
value={query.aggregateAllowDiskUse}
262+
onChange={(evt: ChangeEvent<HTMLInputElement>) =>
263+
props.onChange({ ...query, aggregateAllowDiskUse: evt.target.checked })
264+
}
256265
/>
257266
</InlineField>
258267
<InlineField
259268
label="Bypass document validation"
260269
tooltip="If true, writes executed as part of the operation will opt out of document-level validation on the server. This option is valid for MongoDB versions >= 3.2 and is ignored for previous server versions. The default value is false."
261270
>
262271
<InlineSwitch
263-
id="query-editor-bypass-document-validation" value={query.aggregateBypassDocumentValidation}
264-
onChange={(evt: ChangeEvent<HTMLInputElement>) => props.onChange({ ...query, aggregateBypassDocumentValidation: evt.target.checked })}
272+
id="query-editor-bypass-document-validation"
273+
value={query.aggregateBypassDocumentValidation}
274+
onChange={(evt: ChangeEvent<HTMLInputElement>) =>
275+
props.onChange({ ...query, aggregateBypassDocumentValidation: evt.target.checked })
276+
}
265277
/>
266278
</InlineField>
267279
</InlineFieldRow>

0 commit comments

Comments
 (0)