44 * you may not use this file except in compliance with the Elastic License.
55 */
66
7- import React , { MouseEventHandler , FC , useContext , useState } from 'react' ;
7+ import React , { MouseEventHandler , FC , useContext , useEffect , useState } from 'react' ;
88
99import { i18n } from '@kbn/i18n' ;
1010
1111import {
12- Direction ,
13- EuiBadge ,
12+ EuiBasicTable ,
13+ EuiBasicTableProps ,
1414 EuiButtonEmpty ,
1515 EuiButtonIcon ,
1616 EuiCallOut ,
1717 EuiEmptyPrompt ,
1818 EuiFlexGroup ,
1919 EuiFlexItem ,
20- EuiInMemoryTable ,
21- EuiSearchBarProps ,
20+ EuiSearchBar ,
21+ EuiSpacer ,
2222 EuiPopover ,
2323 EuiTitle ,
2424} from '@elastic/eui' ;
2525
26- import { TransformId , TRANSFORM_STATE } from '../../../../../../common' ;
26+ import { TransformId } from '../../../../../../common' ;
2727
2828import {
2929 useRefreshTransformList ,
3030 TransformListRow ,
31- TRANSFORM_MODE ,
3231 TRANSFORM_LIST_COLUMN ,
3332} from '../../../../common' ;
3433import { useStopTransforms } from '../../../../hooks' ;
@@ -45,9 +44,11 @@ import {
4544import { useStartAction , StartActionName , StartActionModal } from '../action_start' ;
4645import { StopActionName } from '../action_stop' ;
4746
48- import { ItemIdToExpandedRowMap , Clause , TermClause , FieldClause , Value } from './common' ;
49- import { getTaskStateBadge , useColumns } from './use_columns' ;
47+ import { ItemIdToExpandedRowMap } from './common' ;
48+ import { useColumns } from './use_columns' ;
5049import { ExpandedRow } from './expanded_row' ;
50+ import { TransformSearchBar , filterTransforms } from './transform_search_bar' ;
51+ import { useTableSettings } from './use_table_settings' ;
5152
5253function getItemIdToExpandedRowMap (
5354 itemIds : TransformId [ ] ,
@@ -62,14 +63,6 @@ function getItemIdToExpandedRowMap(
6263 } , { } as ItemIdToExpandedRowMap ) ;
6364}
6465
65- function stringMatch ( str : string | undefined , substr : any ) {
66- return (
67- typeof str === 'string' &&
68- typeof substr === 'string' &&
69- ( str . toLowerCase ( ) . match ( substr . toLowerCase ( ) ) === null ) === false
70- ) ;
71- }
72-
7366interface Props {
7467 errorMessage : any ;
7568 isInitialized : boolean ;
@@ -88,24 +81,14 @@ export const TransformList: FC<Props> = ({
8881 const [ isLoading , setIsLoading ] = useState ( false ) ;
8982 const { refresh } = useRefreshTransformList ( { isLoading : setIsLoading } ) ;
9083
91- const [ filterActive , setFilterActive ] = useState ( false ) ;
92-
84+ const [ searchQueryText , setSearchQueryText ] = useState < string > ( '' ) ;
9385 const [ filteredTransforms , setFilteredTransforms ] = useState < TransformListRow [ ] > ( [ ] ) ;
9486 const [ expandedRowItemIds , setExpandedRowItemIds ] = useState < TransformId [ ] > ( [ ] ) ;
95-
9687 const [ transformSelection , setTransformSelection ] = useState < TransformListRow [ ] > ( [ ] ) ;
9788 const [ isActionsMenuOpen , setIsActionsMenuOpen ] = useState ( false ) ;
9889 const bulkStartAction = useStartAction ( false ) ;
9990 const bulkDeleteAction = useDeleteAction ( false ) ;
10091
101- const [ searchError , setSearchError ] = useState < any > ( undefined ) ;
102-
103- const [ pageIndex , setPageIndex ] = useState ( 0 ) ;
104- const [ pageSize , setPageSize ] = useState ( 10 ) ;
105-
106- const [ sortField , setSortField ] = useState < string > ( TRANSFORM_LIST_COLUMN . ID ) ;
107- const [ sortDirection , setSortDirection ] = useState < Direction > ( 'asc' ) ;
108-
10992 const stopTransforms = useStopTransforms ( ) ;
11093
11194 const { capabilities } = useContext ( AuthorizationContext ) ;
@@ -114,90 +97,41 @@ export const TransformList: FC<Props> = ({
11497 ! capabilities . canPreviewTransform ||
11598 ! capabilities . canStartStopTransform ;
11699
117- const onQueryChange = ( {
118- query,
119- error,
120- } : Parameters < NonNullable < EuiSearchBarProps [ 'onChange' ] > > [ 0 ] ) => {
121- if ( error ) {
122- setSearchError ( error . message ) ;
100+ const { columns, modals : singleActionModals } = useColumns (
101+ expandedRowItemIds ,
102+ setExpandedRowItemIds ,
103+ transformSelection
104+ ) ;
105+
106+ const updateFilteredItems = ( queryClauses : any ) => {
107+ if ( queryClauses . length ) {
108+ const filtered = filterTransforms ( transforms , queryClauses ) ;
109+ setFilteredTransforms ( filtered ) ;
123110 } else {
124- let clauses : Clause [ ] = [ ] ;
125- if ( query && query . ast !== undefined && query . ast . clauses !== undefined ) {
126- clauses = query . ast . clauses ;
127- }
128- if ( clauses . length > 0 ) {
129- setFilterActive ( true ) ;
130- filterTransforms ( clauses as Array < TermClause | FieldClause > ) ;
131- } else {
132- setFilterActive ( false ) ;
133- }
134- setSearchError ( undefined ) ;
111+ setFilteredTransforms ( transforms ) ;
135112 }
136113 } ;
137114
138- const filterTransforms = ( clauses : Array < TermClause | FieldClause > ) => {
139- setIsLoading ( true ) ;
140- // keep count of the number of matches we make as we're looping over the clauses
141- // we only want to return transforms which match all clauses, i.e. each search term is ANDed
142- // { transform-one: { transform: { id: transform-one, config: {}, state: {}, ... }, count: 0 }, transform-two: {...} }
143- const matches : Record < string , any > = transforms . reduce ( ( p : Record < string , any > , c ) => {
144- p [ c . id ] = {
145- transform : c ,
146- count : 0 ,
147- } ;
148- return p ;
149- } , { } ) ;
150-
151- clauses . forEach ( ( c ) => {
152- // the search term could be negated with a minus, e.g. -bananas
153- const bool = c . match === 'must' ;
154- let ts = [ ] ;
155-
156- if ( c . type === 'term' ) {
157- // filter term based clauses, e.g. bananas
158- // match on ID and description
159- // if the term has been negated, AND the matches
160- if ( bool === true ) {
161- ts = transforms . filter (
162- ( transform ) =>
163- stringMatch ( transform . id , c . value ) === bool ||
164- stringMatch ( transform . config . description , c . value ) === bool
165- ) ;
166- } else {
167- ts = transforms . filter (
168- ( transform ) =>
169- stringMatch ( transform . id , c . value ) === bool &&
170- stringMatch ( transform . config . description , c . value ) === bool
171- ) ;
115+ useEffect ( ( ) => {
116+ const filterList = ( ) => {
117+ if ( searchQueryText !== '' ) {
118+ const query = EuiSearchBar . Query . parse ( searchQueryText ) ;
119+ let clauses : any = [ ] ;
120+ if ( query && query . ast !== undefined && query . ast . clauses !== undefined ) {
121+ clauses = query . ast . clauses ;
172122 }
123+ updateFilteredItems ( clauses ) ;
173124 } else {
174- // filter other clauses, i.e. the mode and status filters
175- if ( Array . isArray ( c . value ) ) {
176- // the status value is an array of string(s) e.g. ['failed', 'stopped']
177- ts = transforms . filter ( ( transform ) =>
178- ( c . value as Value [ ] ) . includes ( transform . stats . state )
179- ) ;
180- } else {
181- ts = transforms . filter ( ( transform ) => transform . mode === c . value ) ;
182- }
125+ updateFilteredItems ( [ ] ) ;
183126 }
184-
185- ts . forEach ( ( t ) => matches [ t . id ] . count ++ ) ;
186- } ) ;
187-
188- // loop through the matches and return only transforms which have match all the clauses
189- const filtered = Object . values ( matches )
190- . filter ( ( m ) => ( m && m . count ) >= clauses . length )
191- . map ( ( m ) => m . transform ) ;
192-
193- setFilteredTransforms ( filtered ) ;
194- setIsLoading ( false ) ;
195- } ;
196-
197- const { columns, modals : singleActionModals } = useColumns (
198- expandedRowItemIds ,
199- setExpandedRowItemIds ,
200- transformSelection
127+ } ;
128+ filterList ( ) ;
129+ // eslint-disable-next-line
130+ } , [ searchQueryText , transforms ] ) ; // missing dependency updateFilteredItems
131+
132+ const { onTableChange, pageOfItems, pagination, sorting } = useTableSettings < TransformListRow > (
133+ TRANSFORM_LIST_COLUMN . ID ,
134+ filteredTransforms
201135 ) ;
202136
203137 // Before the transforms have been loaded for the first time, display the loading indicator only.
@@ -246,23 +180,8 @@ export const TransformList: FC<Props> = ({
246180 ) ;
247181 }
248182
249- const sorting = {
250- sort : {
251- field : sortField ,
252- direction : sortDirection ,
253- } ,
254- } ;
255-
256183 const itemIdToExpandedRowMap = getItemIdToExpandedRowMap ( expandedRowItemIds , transforms ) ;
257184
258- const pagination = {
259- initialPageIndex : pageIndex ,
260- initialPageSize : pageSize ,
261- totalItemCount : transforms . length ,
262- pageSizeOptions : [ 10 , 20 , 50 ] ,
263- hidePerPageOptions : false ,
264- } ;
265-
266185 const bulkActionMenuItems = [
267186 < div key = "startAction" className = "transform__BulkActionItem" >
268187 < EuiButtonEmpty onClick = { ( ) => bulkStartAction . openModal ( transformSelection ) } >
@@ -331,7 +250,7 @@ export const TransformList: FC<Props> = ({
331250 ] ;
332251 } ;
333252
334- const renderToolsRight = ( ) => (
253+ const toolsRight = (
335254 < EuiFlexGroup gutterSize = "m" justifyContent = "spaceAround" >
336255 < EuiFlexItem >
337256 < RefreshTransformListButton onClick = { refresh } isLoading = { isLoading } />
@@ -342,56 +261,6 @@ export const TransformList: FC<Props> = ({
342261 </ EuiFlexGroup >
343262 ) ;
344263
345- const search = {
346- toolsLeft : transformSelection . length > 0 ? renderToolsLeft ( ) : undefined ,
347- toolsRight : renderToolsRight ( ) ,
348- onChange : onQueryChange ,
349- box : {
350- incremental : true ,
351- } ,
352- filters : [
353- {
354- type : 'field_value_selection' as const ,
355- field : 'state.state' ,
356- name : i18n . translate ( 'xpack.transform.statusFilter' , { defaultMessage : 'Status' } ) ,
357- multiSelect : 'or' as const ,
358- options : Object . values ( TRANSFORM_STATE ) . map ( ( val ) => ( {
359- value : val ,
360- name : val ,
361- view : getTaskStateBadge ( val ) ,
362- } ) ) ,
363- } ,
364- {
365- type : 'field_value_selection' as const ,
366- field : 'mode' ,
367- name : i18n . translate ( 'xpack.transform.modeFilter' , { defaultMessage : 'Mode' } ) ,
368- multiSelect : false ,
369- options : Object . values ( TRANSFORM_MODE ) . map ( ( val ) => ( {
370- value : val ,
371- name : val ,
372- view : (
373- < EuiBadge className = "transform__TaskModeBadge" color = "hollow" >
374- { val }
375- </ EuiBadge >
376- ) ,
377- } ) ) ,
378- } ,
379- ] ,
380- } ;
381-
382- const onTableChange = ( {
383- page = { index : 0 , size : 10 } ,
384- sort = { field : TRANSFORM_LIST_COLUMN . ID as string , direction : 'asc' } ,
385- } ) => {
386- const { index, size } = page ;
387- setPageIndex ( index ) ;
388- setPageSize ( size ) ;
389-
390- const { field, direction } = sort ;
391- setSortField ( field as string ) ;
392- setSortDirection ( direction as Direction ) ;
393- } ;
394-
395264 const selection = {
396265 onSelectionChange : ( selected : TransformListRow [ ] ) => setTransformSelection ( selected ) ,
397266 } ;
@@ -404,30 +273,38 @@ export const TransformList: FC<Props> = ({
404273
405274 { /* Single Action Modals */ }
406275 { singleActionModals }
407-
408- < EuiInMemoryTable
409- allowNeutralSort = { false }
410- className = "transform__TransformTable"
276+ < EuiFlexGroup alignItems = "center" >
277+ { transformSelection . length > 0 ? (
278+ < EuiFlexItem grow = { false } > { renderToolsLeft ( ) } </ EuiFlexItem >
279+ ) : null }
280+ < EuiFlexItem >
281+ < TransformSearchBar
282+ searchQueryText = { searchQueryText }
283+ setSearchQueryText = { setSearchQueryText }
284+ />
285+ </ EuiFlexItem >
286+ < EuiFlexItem grow = { false } > { toolsRight } </ EuiFlexItem >
287+ </ EuiFlexGroup >
288+ < EuiSpacer size = "l" />
289+ < EuiBasicTable < TransformListRow >
411290 columns = { columns }
412- error = { searchError }
413291 hasActions = { false }
414292 isExpandable = { true }
415293 isSelectable = { false }
416- items = { filterActive ? filteredTransforms : transforms }
294+ items = { pageOfItems as TransformListRow [ ] }
417295 itemId = { TRANSFORM_LIST_COLUMN . ID }
418296 itemIdToExpandedRowMap = { itemIdToExpandedRowMap }
419297 loading = { isLoading || transformsLoading }
420- onTableChange = { onTableChange }
421- pagination = { pagination }
422- rowProps = { ( item ) => ( {
423- 'data-test-subj' : `transformListRow row-${ item . id } ` ,
424- } ) }
298+ onChange = { onTableChange as EuiBasicTableProps < TransformListRow > [ 'onChange' ] }
425299 selection = { selection }
300+ pagination = { pagination ! }
426301 sorting = { sorting }
427- search = { search }
428302 data-test-subj = { `transformListTable ${
429303 isLoading || transformsLoading ? 'loading' : 'loaded'
430304 } `}
305+ rowProps = { ( item ) => ( {
306+ 'data-test-subj' : `transformListRow row-${ item . id } ` ,
307+ } ) }
431308 />
432309 </ div >
433310 ) ;
0 commit comments