Skip to content

Commit 39b58a8

Browse files
committed
Debounce query editor changes, improve usability
1 parent 55f88c7 commit 39b58a8

File tree

5 files changed

+34
-23
lines changed

5 files changed

+34
-23
lines changed

package-lock.json

Lines changed: 17 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
"@reduxjs/toolkit": "^1.9.5",
7171
"@uiw/react-codemirror": "^4.21.21",
7272
"lucene": "^2.1.1",
73+
"observable-hooks": "^4.2.3",
7374
"react": "17.0.2",
7475
"react-dom": "17.0.2",
7576
"tslib": "2.5.3"

src/LogContext/components/LogContextUI.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ export function LogContextUI(props: LogContextUIProps ){
6464
<LogContextQueryBuilderSidebar {...props} builder={builder} updateQuery={setParsedQuery} searchableFields={fields}/>
6565
<div className={css`width:100%; display:flex; flex-direction:column; gap:0.5rem; min-width:0;`}>
6666
{ActionBar}
67-
<LuceneQueryEditor builder={builder} autocompleter={getSuggestions} onChange={builder.setQuery}/>
67+
<LuceneQueryEditor value={builder.query} autocompleter={getSuggestions} onChange={builder.setQuery}/>
6868
</div>
6969
</DatasourceContext.Provider>
7070
</div>
Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
import React, { useRef, useCallback } from "react";
2+
import { debounceTime } from 'rxjs';
3+
import { useObservableCallback, useSubscription } from 'observable-hooks'
24
import { css } from "@emotion/css";
35

4-
import { LuceneQueryBuilder } from '@/QueryBuilder/lucene';
56

67
import CodeMirror, { ReactCodeMirrorRef } from '@uiw/react-codemirror';
78
import {linter, Diagnostic, lintGutter} from "@codemirror/lint"
89
import {autocompletion, CompletionContext} from "@codemirror/autocomplete"
10+
import { LuceneQuery } from "utils/lucene";
911

1012

1113
export type LuceneQueryEditorProps = {
1214
placeholder?: string,
13-
builder: LuceneQueryBuilder,
15+
value: string,
1416
autocompleter: (word: string) => any,
1517
onChange: (query: string) => void
1618
}
@@ -20,8 +22,8 @@ export function LuceneQueryEditor(props: LuceneQueryEditorProps){
2022

2123
const queryLinter = linter( view => {
2224
let diagnostics: Diagnostic[] = [];
23-
24-
const error = props.builder.parsedQuery?.parseError
25+
const query = LuceneQuery.parse(view.state.doc.toString())
26+
const error = query.parseError
2527
if (error) {
2628
diagnostics.push({
2729
severity: "error",
@@ -33,7 +35,6 @@ export function LuceneQueryEditor(props: LuceneQueryEditorProps){
3335
return diagnostics
3436
})
3537

36-
3738
const {autocompleter} = props;
3839
const datasourceCompletions = useCallback(async (context: CompletionContext)=>{
3940
let word = context.matchBefore(/\S*/);
@@ -43,19 +44,23 @@ export function LuceneQueryEditor(props: LuceneQueryEditorProps){
4344
from: word.from + suggestions.from,
4445
options: suggestions.options
4546
}
46-
},[autocompleter])
47+
}, [autocompleter])
4748

4849

4950
const autocomplete = autocompletion({ override: [datasourceCompletions] })
5051

52+
const [onChange, textChanged$] = useObservableCallback<string>(event$ => event$.pipe(debounceTime(1000)))
53+
54+
useSubscription(textChanged$, props.onChange)
55+
5156
return (<CodeMirror
5257
ref={editorRef}
5358
className={css`height:100%`} // XXX : need to set height for both wrapper elements
5459
height="100%"
5560
theme={'dark'}
5661
placeholder={props.placeholder}
57-
value={props.builder.query}
58-
onChange={props.onChange}
62+
value={props.value}
63+
onChange={onChange}
5964
extensions={[queryLinter, lintGutter(), autocomplete]}
6065
/>);
6166
}

src/components/QueryEditor/index.tsx

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { css } from '@emotion/css';
22

3-
import React, { createContext, useCallback, useEffect } from 'react';
3+
import React, { createContext } from 'react';
44

55
import { CoreApp, Field, getDefaultTimeRange, GrafanaTheme2, QueryEditorProps } from '@grafana/data';
66
import { InlineLabel, useStyles2 } from '@grafana/ui';
@@ -18,7 +18,6 @@ import { changeQuery } from './state';
1818
import { QuickwitOptions } from '../../quickwit';
1919
import { QueryTypeSelector } from './QueryTypeSelector';
2020

21-
import { useQueryBuilder } from '@/QueryBuilder/lucene';
2221
import { getHook } from 'utils/context';
2322
import { LuceneQueryEditor } from '@/components/LuceneQueryEditor';
2423
import { useDatasourceFields } from 'datasource.utils';
@@ -59,23 +58,12 @@ interface Props {
5958

6059
export const ElasticSearchQueryField = ({ value, onChange }: { value?: string; onChange: (v: string) => void }) => {
6160
const styles = useStyles2(getStyles);
62-
const builder = useQueryBuilder();
63-
const {setQuery} = builder;
6461
const datasource = useDatasource()
6562
const { getSuggestions } = useDatasourceFields(datasource);
6663

67-
useEffect(()=>{
68-
setQuery(value || '')
69-
}, [setQuery, value])
70-
71-
const onEditorChange = useCallback((query: string)=>{
72-
setQuery(query);
73-
onChange(query)
74-
},[setQuery, onChange])
75-
7664
return (
7765
<div className={styles.queryItem}>
78-
<LuceneQueryEditor placeholder="Enter a lucene query" builder={builder} autocompleter={getSuggestions} onChange={onEditorChange}/>
66+
<LuceneQueryEditor placeholder="Enter a lucene query" value={value || ''} autocompleter={getSuggestions} onChange={onChange}/>
7967
</div>
8068
);
8169
};

0 commit comments

Comments
 (0)