Skip to content

Commit c0fa084

Browse files
use basic table in transforms to persist pagination
1 parent caa4e0c commit c0fa084

File tree

3 files changed

+367
-184
lines changed

3 files changed

+367
-184
lines changed

x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/transform_list.tsx

Lines changed: 67 additions & 184 deletions
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,30 @@
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

99
import { i18n } from '@kbn/i18n';
1010

1111
import {
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

2828
import {
2929
useRefreshTransformList,
3030
TransformListRow,
31-
TRANSFORM_MODE,
3231
TRANSFORM_LIST_COLUMN,
3332
} from '../../../../common';
3433
import { useStopTransforms } from '../../../../hooks';
@@ -45,9 +44,11 @@ import {
4544
import { useStartAction, StartActionName, StartActionModal } from '../action_start';
4645
import { 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';
5049
import { ExpandedRow } from './expanded_row';
50+
import { TransformSearchBar, filterTransforms } from './transform_search_bar';
51+
import { useTableSettings } from './use_table_settings';
5152

5253
function 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-
7366
interface Props {
7467
errorMessage: any;
7568
isInitialized: boolean;
@@ -88,24 +81,20 @@ 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-
93-
const [filteredTransforms, setFilteredTransforms] = useState<TransformListRow[]>([]);
84+
const [searchQueryText, setSearchQueryText] = useState<string>('');
85+
const [filteredTransforms, setFilteredTransforms] = useState<{
86+
active: boolean;
87+
items: TransformListRow[];
88+
}>({
89+
active: false,
90+
items: [],
91+
});
9492
const [expandedRowItemIds, setExpandedRowItemIds] = useState<TransformId[]>([]);
95-
9693
const [transformSelection, setTransformSelection] = useState<TransformListRow[]>([]);
9794
const [isActionsMenuOpen, setIsActionsMenuOpen] = useState(false);
9895
const bulkStartAction = useStartAction(false);
9996
const bulkDeleteAction = useDeleteAction(false);
10097

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-
10998
const stopTransforms = useStopTransforms();
11099

111100
const { capabilities } = useContext(AuthorizationContext);
@@ -114,90 +103,41 @@ export const TransformList: FC<Props> = ({
114103
!capabilities.canPreviewTransform ||
115104
!capabilities.canStartStopTransform;
116105

117-
const onQueryChange = ({
118-
query,
119-
error,
120-
}: Parameters<NonNullable<EuiSearchBarProps['onChange']>>[0]) => {
121-
if (error) {
122-
setSearchError(error.message);
106+
const { columns, modals: singleActionModals } = useColumns(
107+
expandedRowItemIds,
108+
setExpandedRowItemIds,
109+
transformSelection
110+
);
111+
112+
const setQueryClauses = (queryClauses: any) => {
113+
if (queryClauses.length) {
114+
const filtered = filterTransforms(transforms, queryClauses);
115+
setFilteredTransforms({ active: true, items: filtered });
123116
} 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);
117+
setFilteredTransforms({ active: false, items: [] });
135118
}
136119
};
137120

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-
);
121+
useEffect(() => {
122+
const filterList = () => {
123+
if (searchQueryText !== '') {
124+
const query = EuiSearchBar.Query.parse(searchQueryText);
125+
let clauses: any = [];
126+
if (query && query.ast !== undefined && query.ast.clauses !== undefined) {
127+
clauses = query.ast.clauses;
172128
}
129+
setQueryClauses(clauses);
173130
} 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-
}
131+
setQueryClauses([]);
183132
}
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
133+
};
134+
filterList();
135+
// eslint-disable-next-line
136+
}, [searchQueryText, transforms]); // missing dependency setQueryClauses
137+
138+
const { onTableChange, pageOfItems, pagination, sorting } = useTableSettings(
139+
TRANSFORM_LIST_COLUMN.ID,
140+
filteredTransforms.active ? filteredTransforms.items : transforms
201141
);
202142

203143
// Before the transforms have been loaded for the first time, display the loading indicator only.
@@ -246,23 +186,8 @@ export const TransformList: FC<Props> = ({
246186
);
247187
}
248188

249-
const sorting = {
250-
sort: {
251-
field: sortField,
252-
direction: sortDirection,
253-
},
254-
};
255-
256189
const itemIdToExpandedRowMap = getItemIdToExpandedRowMap(expandedRowItemIds, transforms);
257190

258-
const pagination = {
259-
initialPageIndex: pageIndex,
260-
initialPageSize: pageSize,
261-
totalItemCount: transforms.length,
262-
pageSizeOptions: [10, 20, 50],
263-
hidePerPageOptions: false,
264-
};
265-
266191
const bulkActionMenuItems = [
267192
<div key="startAction" className="transform__BulkActionItem">
268193
<EuiButtonEmpty onClick={() => bulkStartAction.openModal(transformSelection)}>
@@ -331,7 +256,7 @@ export const TransformList: FC<Props> = ({
331256
];
332257
};
333258

334-
const renderToolsRight = () => (
259+
const toolsRight = (
335260
<EuiFlexGroup gutterSize="m" justifyContent="spaceAround">
336261
<EuiFlexItem>
337262
<RefreshTransformListButton onClick={refresh} isLoading={isLoading} />
@@ -342,56 +267,6 @@ export const TransformList: FC<Props> = ({
342267
</EuiFlexGroup>
343268
);
344269

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-
395270
const selection = {
396271
onSelectionChange: (selected: TransformListRow[]) => setTransformSelection(selected),
397272
};
@@ -404,30 +279,38 @@ export const TransformList: FC<Props> = ({
404279

405280
{/* Single Action Modals */}
406281
{singleActionModals}
407-
408-
<EuiInMemoryTable
409-
allowNeutralSort={false}
410-
className="transform__TransformTable"
282+
<EuiFlexGroup alignItems="center">
283+
{transformSelection.length > 0 ? (
284+
<EuiFlexItem grow={false}>{renderToolsLeft()}</EuiFlexItem>
285+
) : null}
286+
<EuiFlexItem>
287+
<TransformSearchBar
288+
searchQueryText={searchQueryText}
289+
setSearchQueryText={setSearchQueryText}
290+
/>
291+
</EuiFlexItem>
292+
<EuiFlexItem grow={false}>{toolsRight}</EuiFlexItem>
293+
</EuiFlexGroup>
294+
<EuiSpacer size="l" />
295+
<EuiBasicTable<TransformListRow>
411296
columns={columns}
412-
error={searchError}
413297
hasActions={false}
414298
isExpandable={true}
415299
isSelectable={false}
416-
items={filterActive ? filteredTransforms : transforms}
300+
items={pageOfItems as TransformListRow[]}
417301
itemId={TRANSFORM_LIST_COLUMN.ID}
418302
itemIdToExpandedRowMap={itemIdToExpandedRowMap}
419303
loading={isLoading || transformsLoading}
420-
onTableChange={onTableChange}
421-
pagination={pagination}
422-
rowProps={(item) => ({
423-
'data-test-subj': `transformListRow row-${item.id}`,
424-
})}
304+
onChange={onTableChange as EuiBasicTableProps<TransformListRow>['onChange']}
425305
selection={selection}
306+
pagination={pagination!}
426307
sorting={sorting}
427-
search={search}
428308
data-test-subj={`transformListTable ${
429309
isLoading || transformsLoading ? 'loading' : 'loaded'
430310
}`}
311+
rowProps={(item) => ({
312+
'data-test-subj': `transformListRow row-${item.id}`,
313+
})}
431314
/>
432315
</div>
433316
);

0 commit comments

Comments
 (0)