4
4
* 2.0; you may not use this file except in compliance with the Elastic License
5
5
* 2.0.
6
6
*/
7
-
8
- import { EuiButtonIcon , EuiLink , EuiPanel , EuiPopover } from '@elastic/eui' ;
9
- import { EuiFormRow , EuiFlexItem , EuiFlexGroup } from '@elastic/eui' ;
7
+ import React , { useState , useEffect , useCallback } from 'react' ;
10
8
import { i18n } from '@kbn/i18n' ;
11
- import React , { useState } from 'react' ;
12
- import { Query } from 'src/plugins/data/public' ;
9
+ import { isEqual } from 'lodash' ;
10
+ import {
11
+ EuiButtonIcon ,
12
+ EuiLink ,
13
+ EuiPanel ,
14
+ EuiPopover ,
15
+ EuiFormRow ,
16
+ EuiFlexItem ,
17
+ EuiFlexGroup ,
18
+ EuiPopoverProps ,
19
+ } from '@elastic/eui' ;
20
+ import type { Query } from 'src/plugins/data/public' ;
13
21
import { IndexPatternColumn , operationDefinitionMap } from '../operations' ;
14
- import { isQueryValid } from '../operations/definitions/filters' ;
22
+ import { validateQuery } from '../operations/definitions/filters' ;
15
23
import { QueryInput } from '../query_input' ;
16
- import { IndexPattern , IndexPatternLayer } from '../types' ;
24
+ import type { IndexPattern , IndexPatternLayer } from '../types' ;
25
+
26
+ const filterByLabel = i18n . translate ( 'xpack.lens.indexPattern.filterBy.label' , {
27
+ defaultMessage : 'Filter by' ,
28
+ } ) ;
17
29
18
30
// to do: get the language from uiSettings
19
31
export const defaultFilter : Query = {
@@ -49,29 +61,49 @@ export function Filtering({
49
61
updateLayer : ( newLayer : IndexPatternLayer ) => void ;
50
62
isInitiallyOpen : boolean ;
51
63
} ) {
64
+ const inputFilter = selectedColumn . filter ;
65
+ const [ queryInput , setQueryInput ] = useState ( inputFilter ?? defaultFilter ) ;
52
66
const [ filterPopoverOpen , setFilterPopoverOpen ] = useState ( isInitiallyOpen ) ;
67
+
68
+ useEffect ( ( ) => {
69
+ const { isValid } = validateQuery ( queryInput , indexPattern ) ;
70
+
71
+ if ( isValid && ! isEqual ( inputFilter , queryInput ) ) {
72
+ updateLayer ( setFilter ( columnId , layer , queryInput ) ) ;
73
+ }
74
+ } , [ columnId , layer , queryInput , indexPattern , updateLayer , inputFilter ] ) ;
75
+
76
+ const onClosePopup : EuiPopoverProps [ 'closePopover' ] = useCallback ( ( ) => {
77
+ setFilterPopoverOpen ( false ) ;
78
+ if ( inputFilter ) {
79
+ setQueryInput ( inputFilter ) ;
80
+ }
81
+ } , [ inputFilter ] ) ;
82
+
53
83
const selectedOperation = operationDefinitionMap [ selectedColumn . operationType ] ;
54
- if ( ! selectedOperation . filterable || ! selectedColumn . filter ) {
84
+
85
+ if ( ! selectedOperation . filterable || ! inputFilter ) {
55
86
return null ;
56
87
}
57
88
58
- const isInvalid = ! isQueryValid ( selectedColumn . filter , indexPattern ) ;
89
+ const { isValid : isInputFilterValid } = validateQuery ( inputFilter , indexPattern ) ;
90
+ const { isValid : isQueryInputValid , error : queryInputError } = validateQuery (
91
+ queryInput ,
92
+ indexPattern
93
+ ) ;
59
94
60
95
return (
61
96
< EuiFormRow
62
97
display = "columnCompressed"
98
+ label = { filterByLabel }
63
99
fullWidth
64
- label = { i18n . translate ( 'xpack.lens.indexPattern.filterBy.label' , {
65
- defaultMessage : 'Filter by' ,
66
- } ) }
100
+ isInvalid = { ! isInputFilterValid }
67
101
>
68
102
< EuiFlexGroup gutterSize = "s" alignItems = "center" >
69
103
< EuiFlexItem >
70
104
< EuiPopover
71
105
isOpen = { filterPopoverOpen }
72
- closePopover = { ( ) => {
73
- setFilterPopoverOpen ( false ) ;
74
- } }
106
+ closePopover = { onClosePopup }
75
107
anchorClassName = "eui-fullWidth"
76
108
panelClassName = "lnsIndexPatternDimensionEditor__filtersEditor"
77
109
button = {
@@ -85,12 +117,12 @@ export function Filtering({
85
117
onClick = { ( ) => {
86
118
setFilterPopoverOpen ( ! filterPopoverOpen ) ;
87
119
} }
88
- color = { isInvalid ? 'danger ' : 'text ' }
120
+ color = { isInputFilterValid ? 'text ' : 'danger ' }
89
121
title = { i18n . translate ( 'xpack.lens.indexPattern.filterBy.clickToEdit' , {
90
122
defaultMessage : 'Click to edit' ,
91
123
} ) }
92
124
>
93
- { selectedColumn . filter . query ||
125
+ { inputFilter . query ||
94
126
i18n . translate ( 'xpack.lens.indexPattern.filterBy.emptyFilterQuery' , {
95
127
defaultMessage : '(empty)' ,
96
128
} ) }
@@ -113,16 +145,21 @@ export function Filtering({
113
145
</ EuiPanel >
114
146
}
115
147
>
116
- < QueryInput
117
- indexPatternTitle = { indexPattern . title }
118
- data-test-subj = "indexPattern-filter-by-input"
119
- value = { selectedColumn . filter || defaultFilter }
120
- onChange = { ( newQuery ) => {
121
- updateLayer ( setFilter ( columnId , layer , newQuery ) ) ;
122
- } }
123
- isInvalid = { false }
124
- onSubmit = { ( ) => { } }
125
- />
148
+ < EuiFormRow
149
+ label = { filterByLabel }
150
+ isInvalid = { ! isQueryInputValid }
151
+ error = { queryInputError }
152
+ fullWidth = { true }
153
+ >
154
+ < QueryInput
155
+ indexPatternTitle = { indexPattern . title }
156
+ data-test-subj = "indexPattern-filter-by-input"
157
+ value = { queryInput }
158
+ onChange = { setQueryInput }
159
+ isInvalid = { ! isQueryInputValid }
160
+ onSubmit = { ( ) => { } }
161
+ />
162
+ </ EuiFormRow >
126
163
</ EuiPopover >
127
164
</ EuiFlexItem >
128
165
</ EuiFlexGroup >
0 commit comments