@@ -10,18 +10,21 @@ import { useFormikContext } from 'formik';
10
10
import {
11
11
EuiCodeEditor ,
12
12
EuiComboBox ,
13
+ EuiContextMenu ,
13
14
EuiEmptyPrompt ,
14
15
EuiFlexGroup ,
15
16
EuiFlexItem ,
17
+ EuiPopover ,
16
18
EuiSmallButton ,
17
19
EuiSmallButtonEmpty ,
18
20
EuiText ,
19
21
} from '@elastic/eui' ;
20
22
import {
21
23
CONFIG_STEP ,
22
24
customStringify ,
23
- FETCH_ALL_QUERY ,
25
+ QUERY_PRESETS ,
24
26
QueryParam ,
27
+ QueryPreset ,
25
28
SearchResponse ,
26
29
SearchResponseVerbose ,
27
30
WorkflowFormValues ,
@@ -47,6 +50,12 @@ interface QueryProps {
47
50
hasSearchPipeline : boolean ;
48
51
hasIngestResources : boolean ;
49
52
selectedStep : CONFIG_STEP ;
53
+ queryRequest : string ;
54
+ setQueryRequest : ( queryRequest : string ) => void ;
55
+ queryResponse : SearchResponse | undefined ;
56
+ setQueryResponse : ( queryResponse : SearchResponse | undefined ) => void ;
57
+ queryParams : QueryParam [ ] ;
58
+ setQueryParams : ( queryParams : QueryParam [ ] ) => void ;
50
59
}
51
60
52
61
const SEARCH_OPTIONS = [
@@ -66,28 +75,11 @@ export function Query(props: QueryProps) {
66
75
const dispatch = useAppDispatch ( ) ;
67
76
const dataSourceId = getDataSourceId ( ) ;
68
77
const dataSourceVersion = useDataSourceVersion ( dataSourceId ) ;
69
-
70
78
const { loading } = useSelector ( ( state : AppState ) => state . opensearch ) ;
71
-
72
- // Form state
73
79
const { values } = useFormikContext < WorkflowFormValues > ( ) ;
74
80
75
- // query response state
76
- const [ queryResponse , setQueryResponse ] = useState <
77
- SearchResponse | undefined
78
- > ( undefined ) ;
79
-
80
- // Standalone / sandboxed search request state. Users can test things out
81
- // without updating the base form / persisted value.
82
- // Update if the parent form values are changed, or if a newly-created search pipeline is detected.
83
- const [ tempRequest , setTempRequest ] = useState < string > ( '' ) ;
84
- useEffect ( ( ) => {
85
- if ( ! isEmpty ( values ?. search ?. request ) ) {
86
- setTempRequest ( values ?. search ?. request ) ;
87
- } else {
88
- setTempRequest ( customStringify ( FETCH_ALL_QUERY ) ) ;
89
- }
90
- } , [ values ?. search ?. request ] ) ;
81
+ // popover state
82
+ const [ popoverOpen , setPopoverOpen ] = useState < boolean > ( false ) ;
91
83
92
84
// state for if to execute search w/ or w/o any configured search pipeline.
93
85
// default based on if there is an available search pipeline or not.
@@ -96,31 +88,24 @@ export function Query(props: QueryProps) {
96
88
setIncludePipeline ( props . hasSearchPipeline ) ;
97
89
} , [ props . hasSearchPipeline ] ) ;
98
90
99
- // query params state
100
- const [ queryParams , setQueryParams ] = useState < QueryParam [ ] > ( [ ] ) ;
101
-
102
- // Do a few things when the request is changed:
103
- // 1. Check if there is a new set of query parameters, and if so,
104
- // reset the form.
105
- // 2. Clear any stale results
91
+ // Check if there is a new set of query parameters, and if so, reset the form
106
92
useEffect ( ( ) => {
107
- const placeholders = getPlaceholdersFromQuery ( tempRequest ) ;
93
+ const placeholders = getPlaceholdersFromQuery ( props . queryRequest ) ;
108
94
if (
109
95
! containsSameValues (
110
96
placeholders ,
111
- queryParams . map ( ( queryParam ) => queryParam . name )
97
+ props . queryParams . map ( ( queryParam ) => queryParam . name )
112
98
)
113
99
) {
114
- setQueryParams (
100
+ props . setQueryParams (
115
101
placeholders . map ( ( placeholder ) => ( {
116
102
name : placeholder ,
117
103
type : 'Text' ,
118
104
value : '' ,
119
105
} ) )
120
106
) ;
121
107
}
122
- setQueryResponse ( undefined ) ;
123
- } , [ tempRequest ] ) ;
108
+ } , [ props . queryRequest ] ) ;
124
109
125
110
// empty states
126
111
const noSearchIndex = isEmpty ( values ?. search ?. index ?. name ) ;
@@ -192,15 +177,18 @@ export function Query(props: QueryProps) {
192
177
fill = { true }
193
178
isLoading = { loading }
194
179
disabled = {
195
- containsEmptyValues ( queryParams ) ||
180
+ containsEmptyValues ( props . queryParams ) ||
196
181
isEmpty ( indexToSearch )
197
182
}
198
183
onClick = { ( ) => {
199
184
dispatch (
200
185
searchIndex ( {
201
186
apiBody : {
202
187
index : indexToSearch ,
203
- body : injectParameters ( queryParams , tempRequest ) ,
188
+ body : injectParameters (
189
+ props . queryParams ,
190
+ props . queryRequest
191
+ ) ,
204
192
searchPipeline : includePipeline
205
193
? values ?. search ?. pipelineName
206
194
: '_none' ,
@@ -230,11 +218,11 @@ export function Query(props: QueryProps) {
230
218
setSearchPipelineErrors ( { errors : { } } ) ;
231
219
}
232
220
233
- setQueryResponse ( resp ) ;
221
+ props . setQueryResponse ( resp ) ;
234
222
}
235
223
)
236
224
. catch ( ( error : any ) => {
237
- setQueryResponse ( undefined ) ;
225
+ props . setQueryResponse ( undefined ) ;
238
226
setSearchPipelineErrors ( { errors : { } } ) ;
239
227
console . error ( 'Error running query: ' , error ) ;
240
228
} ) ;
@@ -250,20 +238,63 @@ export function Query(props: QueryProps) {
250
238
< EuiFlexItem grow = { false } >
251
239
< EuiText size = "s" > Query</ EuiText >
252
240
</ EuiFlexItem >
253
- { props . selectedStep === CONFIG_STEP . SEARCH &&
254
- ! isEmpty ( values ?. search ?. request ) &&
255
- values ?. search ?. request !== tempRequest && (
256
- < EuiFlexItem grow = { false } style = { { marginBottom : '0px' } } >
257
- < EuiSmallButtonEmpty
258
- disabled = { false }
259
- onClick = { ( ) => {
260
- setTempRequest ( values ?. search ?. request ) ;
261
- } }
241
+ < EuiFlexItem grow = { false } >
242
+ < EuiFlexGroup direction = "row" gutterSize = "s" >
243
+ { props . selectedStep === CONFIG_STEP . SEARCH &&
244
+ ! isEmpty ( values ?. search ?. request ) &&
245
+ values ?. search ?. request !== props . queryRequest && (
246
+ < EuiFlexItem
247
+ grow = { false }
248
+ style = { { marginBottom : '0px' } }
249
+ >
250
+ < EuiSmallButtonEmpty
251
+ disabled = { false }
252
+ onClick = { ( ) => {
253
+ props . setQueryRequest ( values ?. search ?. request ) ;
254
+ } }
255
+ >
256
+ Revert to original query
257
+ </ EuiSmallButtonEmpty >
258
+ </ EuiFlexItem >
259
+ ) }
260
+ < EuiFlexItem grow = { false } >
261
+ < EuiPopover
262
+ button = {
263
+ < EuiSmallButton
264
+ onClick = { ( ) => setPopoverOpen ( ! popoverOpen ) }
265
+ data-testid = "inspectorQueryPresetButton"
266
+ iconSide = "right"
267
+ iconType = "arrowDown"
268
+ >
269
+ Query samples
270
+ </ EuiSmallButton >
271
+ }
272
+ isOpen = { popoverOpen }
273
+ closePopover = { ( ) => setPopoverOpen ( false ) }
274
+ anchorPosition = "downLeft"
262
275
>
263
- Revert to original query
264
- </ EuiSmallButtonEmpty >
276
+ < EuiContextMenu
277
+ size = "s"
278
+ initialPanelId = { 0 }
279
+ panels = { [
280
+ {
281
+ id : 0 ,
282
+ items : QUERY_PRESETS . map (
283
+ ( preset : QueryPreset ) => ( {
284
+ name : preset . name ,
285
+ onClick : ( ) => {
286
+ props . setQueryRequest ( preset . query ) ;
287
+ setPopoverOpen ( false ) ;
288
+ } ,
289
+ } )
290
+ ) ,
291
+ } ,
292
+ ] }
293
+ />
294
+ </ EuiPopover >
265
295
</ EuiFlexItem >
266
- ) }
296
+ </ EuiFlexGroup >
297
+ </ EuiFlexItem >
267
298
</ EuiFlexGroup >
268
299
</ EuiFlexItem >
269
300
< EuiFlexItem grow = { true } >
@@ -272,13 +303,16 @@ export function Query(props: QueryProps) {
272
303
theme = "textmate"
273
304
width = "100%"
274
305
height = { '100%' }
275
- value = { tempRequest }
306
+ value = { props . queryRequest }
276
307
onChange = { ( input ) => {
277
- setTempRequest ( input ) ;
308
+ props . setQueryRequest ( input ) ;
278
309
} }
310
+ // format the JSON on blur
279
311
onBlur = { ( ) => {
280
312
try {
281
- setTempRequest ( customStringify ( JSON . parse ( tempRequest ) ) ) ;
313
+ props . setQueryRequest (
314
+ customStringify ( JSON . parse ( props . queryRequest ) )
315
+ ) ;
282
316
} catch ( error ) { }
283
317
} }
284
318
readOnly = { false }
@@ -299,8 +333,8 @@ export function Query(props: QueryProps) {
299
333
* This may return nothing if the list of params are empty
300
334
*/ }
301
335
< QueryParamsList
302
- queryParams = { queryParams }
303
- setQueryParams = { setQueryParams }
336
+ queryParams = { props . queryParams }
337
+ setQueryParams = { props . setQueryParams }
304
338
/>
305
339
</ EuiFlexItem >
306
340
</ EuiFlexGroup >
@@ -311,7 +345,8 @@ export function Query(props: QueryProps) {
311
345
< EuiText size = "m" > Results</ EuiText >
312
346
</ EuiFlexItem >
313
347
< EuiFlexItem >
314
- { queryResponse === undefined || isEmpty ( queryResponse ) ? (
348
+ { props . queryResponse === undefined ||
349
+ isEmpty ( props . queryResponse ) ? (
315
350
< EuiEmptyPrompt
316
351
title = { < h2 > No results</ h2 > }
317
352
titleSize = "s"
@@ -324,7 +359,7 @@ export function Query(props: QueryProps) {
324
359
}
325
360
/>
326
361
) : (
327
- < Results response = { queryResponse } />
362
+ < Results response = { props . queryResponse } />
328
363
) }
329
364
</ EuiFlexItem >
330
365
</ EuiFlexGroup >
0 commit comments