Skip to content

Commit 29ac7f2

Browse files
[ES|QL] Adds pagination on the history component (elastic#235051)
## Summary Adds pagination on the history table as it is not so performant for many items - [ ] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --------- Co-authored-by: kibanamachine <[email protected]>
1 parent 338721d commit 29ac7f2

File tree

3 files changed

+138
-49
lines changed

3 files changed

+138
-49
lines changed

src/platform/packages/private/kbn-esql-editor/src/editor_footer/history_starred_queries.test.tsx

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,13 @@ const mockHistoryItems = [
4848
},
4949
];
5050

51+
// Add mock data with more than 20 items for pagination testing
52+
const mockManyHistoryItems = Array.from({ length: 25 }, (_, i) => ({
53+
queryString: `FROM index_${i} | WHERE field = "value_${i}"`,
54+
timeRan: '',
55+
status: 'success' as const,
56+
}));
57+
5158
describe('Starred and History queries components', () => {
5259
const services = {
5360
core: coreMock.createStart(),
@@ -500,5 +507,59 @@ describe('Starred and History queries components', () => {
500507
expect(screen.queryByTestId('ESQLEditor-history-search')).not.toBeInTheDocument();
501508
});
502509
});
510+
511+
it('should show pagination controls when there are more than 20 items', async () => {
512+
mockGetHistoryItems.mockReturnValue(mockManyHistoryItems);
513+
mockGetStorageStats.mockReturnValue({
514+
queryCount: 25,
515+
storageSizeKB: 5,
516+
maxStorageLimitKB: 50,
517+
storageUsagePercent: 10,
518+
});
519+
520+
render(
521+
<KibanaContextProvider services={services}>
522+
<HistoryAndStarredQueriesTabs
523+
containerCSS={{}}
524+
containerWidth={800}
525+
onUpdateAndSubmit={jest.fn()}
526+
height={400}
527+
/>
528+
</KibanaContextProvider>
529+
);
530+
531+
// Wait for the component to render
532+
await waitFor(() => {
533+
expect(screen.getByTestId('ESQLEditor-queryHistory')).toBeInTheDocument();
534+
});
535+
536+
// Check that pagination controls are present by looking for EUI pagination class
537+
await waitFor(() => {
538+
const paginationElement = document.querySelector('.euiPagination');
539+
expect(paginationElement).toBeInTheDocument();
540+
});
541+
});
542+
543+
it('should not show pagination controls when there are 20 or fewer items', async () => {
544+
render(
545+
<KibanaContextProvider services={services}>
546+
<HistoryAndStarredQueriesTabs
547+
containerCSS={{}}
548+
containerWidth={800}
549+
onUpdateAndSubmit={jest.fn()}
550+
height={400}
551+
/>
552+
</KibanaContextProvider>
553+
);
554+
555+
// Wait for the component to render
556+
await waitFor(() => {
557+
expect(screen.getByTestId('ESQLEditor-queryHistory')).toBeInTheDocument();
558+
});
559+
560+
// Check that pagination controls are not present
561+
const paginationElement = document.querySelector('.euiPagination');
562+
expect(paginationElement).not.toBeInTheDocument();
563+
});
503564
});
504565
});

src/platform/packages/private/kbn-esql-editor/src/editor_footer/history_starred_queries.tsx

Lines changed: 77 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ import { cssFavoriteHoverWithinEuiTableRow } from '@kbn/content-management-favor
3232
import { FAVORITES_LIMIT as ESQL_STARRED_QUERIES_LIMIT } from '@kbn/content-management-favorites-common';
3333
import type { Interpolation, Theme } from '@emotion/react';
3434
import { css } from '@emotion/react';
35-
import { useEuiTablePersist } from '@kbn/shared-ux-table-persist';
3635
import {
3736
type QueryHistoryItem,
3837
getHistoryItems,
@@ -253,13 +252,27 @@ export function QueryList({
253252
const scrollBarStyles = euiScrollBarStyles(theme);
254253
const [isDiscardQueryModalVisible, setIsDiscardQueryModalVisible] = useState(false);
255254

256-
const { sorting, onTableChange } = useEuiTablePersist<QueryHistoryItem>({
257-
tableId: 'esqlQueryHistory',
258-
initialSort: {
259-
field: 'timeRan',
260-
direction: 'desc',
261-
},
262-
});
255+
// Add simple sorting state that won't interfere with pagination
256+
const sorting = useMemo(
257+
() => ({
258+
sort: {
259+
field: 'timeRan' as keyof QueryHistoryItem,
260+
direction: 'desc' as const,
261+
},
262+
}),
263+
[]
264+
);
265+
266+
// Only show pagination if more than 20 items
267+
const pagination = useMemo(() => {
268+
if (listItems.length > 20) {
269+
return {
270+
initialPageSize: 20,
271+
showPerPageOptions: false,
272+
};
273+
}
274+
return undefined;
275+
}, [listItems.length]);
263276

264277
const actions: Array<CustomItemAction<QueryHistoryItem>> = useMemo(() => {
265278
return [
@@ -375,7 +388,7 @@ export function QueryList({
375388
items={listItems}
376389
columns={columns}
377390
sorting={sorting}
378-
onChange={onTableChange}
391+
pagination={pagination}
379392
css={tableStyling}
380393
tableLayout={containerWidth < 560 ? 'auto' : 'fixed'}
381394
/>
@@ -536,6 +549,58 @@ export function HistoryAndStarredQueriesTabs({
536549
);
537550
}, [starredSearchQuery, starredQueries]);
538551

552+
// Create stable QueryList components outside of tabs array
553+
const historyQueryList = useMemo(
554+
() => (
555+
<QueryList
556+
containerCSS={containerCSS}
557+
onUpdateAndSubmit={onUpdateAndSubmit}
558+
containerWidth={containerWidth}
559+
height={height}
560+
listItems={filteredHistoryItems}
561+
dataTestSubj="ESQLEditor-queryHistory"
562+
tableCaption={i18n.translate('esqlEditor.query.querieshistoryTable', {
563+
defaultMessage: 'Queries history table',
564+
})}
565+
starredQueriesService={starredQueriesService ?? undefined}
566+
/>
567+
),
568+
[
569+
containerCSS,
570+
onUpdateAndSubmit,
571+
containerWidth,
572+
height,
573+
filteredHistoryItems,
574+
starredQueriesService,
575+
]
576+
);
577+
578+
const starredQueryList = useMemo(
579+
() => (
580+
<QueryList
581+
containerCSS={containerCSS}
582+
onUpdateAndSubmit={onUpdateAndSubmit}
583+
containerWidth={containerWidth}
584+
height={height}
585+
listItems={filteredStarredQueries}
586+
dataTestSubj="ESQLEditor-starredQueries"
587+
tableCaption={i18n.translate('esqlEditor.query.starredQueriesTable', {
588+
defaultMessage: 'Starred queries table',
589+
})}
590+
starredQueriesService={starredQueriesService ?? undefined}
591+
isStarredTab={true}
592+
/>
593+
),
594+
[
595+
containerCSS,
596+
onUpdateAndSubmit,
597+
containerWidth,
598+
height,
599+
filteredStarredQueries,
600+
starredQueriesService,
601+
]
602+
);
603+
539604
const { euiTheme } = useEuiTheme();
540605
const tabs = useMemo(() => {
541606
// use typed helper instead of .filter directly to remove falsy values from result type
@@ -549,20 +614,7 @@ export function HistoryAndStarredQueriesTabs({
549614
defaultMessage: 'Recent',
550615
}),
551616
dataTestSubj: 'history-queries-tab',
552-
content: (
553-
<QueryList
554-
containerCSS={containerCSS}
555-
onUpdateAndSubmit={onUpdateAndSubmit}
556-
containerWidth={containerWidth}
557-
height={height}
558-
listItems={filteredHistoryItems}
559-
dataTestSubj="ESQLEditor-queryHistory"
560-
tableCaption={i18n.translate('esqlEditor.query.querieshistoryTable', {
561-
defaultMessage: 'Queries history table',
562-
})}
563-
starredQueriesService={starredQueriesService ?? undefined}
564-
/>
565-
),
617+
content: historyQueryList,
566618
},
567619
starredQueriesService !== null && {
568620
id: HistoryTabId.standardQueries,
@@ -575,33 +627,10 @@ export function HistoryAndStarredQueriesTabs({
575627
{starredQueries?.length}
576628
</EuiNotificationBadge>
577629
),
578-
content: (
579-
<QueryList
580-
containerCSS={containerCSS}
581-
onUpdateAndSubmit={onUpdateAndSubmit}
582-
containerWidth={containerWidth}
583-
height={height}
584-
listItems={filteredStarredQueries}
585-
dataTestSubj="ESQLEditor-starredQueries"
586-
tableCaption={i18n.translate('esqlEditor.query.starredQueriesTable', {
587-
defaultMessage: 'Starred queries table',
588-
})}
589-
starredQueriesService={starredQueriesService ?? undefined}
590-
isStarredTab={true}
591-
/>
592-
),
630+
content: starredQueryList,
593631
},
594632
]);
595-
}, [
596-
containerCSS,
597-
onUpdateAndSubmit,
598-
containerWidth,
599-
height,
600-
filteredHistoryItems,
601-
starredQueriesService,
602-
starredQueries?.length,
603-
filteredStarredQueries,
604-
]);
633+
}, [historyQueryList, starredQueriesService, starredQueries?.length, starredQueryList]);
605634

606635
const [selectedTabId, setSelectedTabId] = useRestorableState(
607636
'historySelectedTabId',

src/platform/packages/private/kbn-esql-editor/tsconfig.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
"@kbn/content-management-favorites-common",
3333
"@kbn/kibana-utils-plugin",
3434
"@kbn/ui-actions-plugin",
35-
"@kbn/shared-ux-table-persist",
3635
"@kbn/esql-types",
3736
"@kbn/field-types",
3837
"@kbn/i18n-react",

0 commit comments

Comments
 (0)