mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-16 17:46:45 +00:00
fix(editor): Reset current page if out of bounds after page size change (#17124)
This commit is contained in:
committed by
GitHub
parent
591aa2d20c
commit
b9e7b719c0
@@ -20,7 +20,7 @@ const itemFactory = () => ({
|
||||
});
|
||||
type Item = ReturnType<typeof itemFactory>;
|
||||
|
||||
const items: Item[] = [...Array(20).keys()].map(itemFactory);
|
||||
const items: Item[] = [...Array(106).keys()].map(itemFactory);
|
||||
const headers: Array<TableHeader<Item>> = [
|
||||
{
|
||||
title: 'Id',
|
||||
@@ -102,26 +102,30 @@ describe('N8nDataTableServer', () => {
|
||||
await userEvent.click(container.querySelector('thead tr th')!);
|
||||
await userEvent.click(within(getByTestId('pagination')).getByLabelText('page 2'));
|
||||
|
||||
// change the page size select option
|
||||
const selectInput = await findAllByRole('combobox'); // Find the select input
|
||||
await userEvent.click(selectInput[0]);
|
||||
|
||||
const options = await getRenderedOptions();
|
||||
expect(options.length).toBe(4);
|
||||
|
||||
const option50 = Array.from(options).find((option) => option.textContent === '50');
|
||||
await userEvent.click(option50!);
|
||||
|
||||
expect(emitted('update:options').length).toBeGreaterThanOrEqual(4);
|
||||
expect(emitted('update:options').length).toBe(3);
|
||||
expect(emitted('update:options')[0]).toStrictEqual([
|
||||
expect.objectContaining({ sortBy: [{ id: 'id', desc: false }] }),
|
||||
]);
|
||||
expect(emitted('update:options')[1]).toStrictEqual([
|
||||
expect.objectContaining({ sortBy: [{ id: 'id', desc: true }] }),
|
||||
]);
|
||||
expect(emitted('update:options')[2]).toStrictEqual([expect.objectContaining({ page: 1 })]);
|
||||
expect(emitted('update:options')[3]).toStrictEqual([
|
||||
expect.objectContaining({ itemsPerPage: 50 }),
|
||||
|
||||
// // change the page size select option
|
||||
const selectInput = await findAllByRole('combobox'); // Find the select input
|
||||
await userEvent.click(selectInput[0]);
|
||||
|
||||
const options = await getRenderedOptions();
|
||||
expect(options.length).toBe(4);
|
||||
|
||||
// account for the debounce
|
||||
await new Promise((r) => setTimeout(r, 100));
|
||||
|
||||
const option50 = Array.from(options).find((option) => option.textContent === '50');
|
||||
await userEvent.click(option50!);
|
||||
|
||||
expect(emitted('update:options').length).toBe(4);
|
||||
expect(emitted('update:options').at(-1)).toStrictEqual([
|
||||
expect.objectContaining({ page: 1, itemsPerPage: 50 }),
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -157,4 +161,28 @@ describe('N8nDataTableServer', () => {
|
||||
|
||||
expect(queryByTestId('pagination')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should adjust page to highest available when page size changes and current page exceeds maximum', async () => {
|
||||
const { emitted, findAllByRole } = renderComponent({
|
||||
props: { items, headers, itemsLength: 106, itemsPerPage: 50, page: 2 },
|
||||
});
|
||||
|
||||
// change the page size select option
|
||||
const selectInput = await findAllByRole('combobox'); // Find the select input
|
||||
await userEvent.click(selectInput[0]);
|
||||
|
||||
const options = await getRenderedOptions();
|
||||
expect(options.length).toBe(4);
|
||||
|
||||
const option100 = Array.from(options).find((option) => option.textContent === '100');
|
||||
await userEvent.click(option100!);
|
||||
|
||||
// With 106 items and 50 per page, max page should be 2 (0-based index 1)
|
||||
// Since we were on page 2, we should be adjusted to page 1
|
||||
expect(emitted('update:options')).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.arrayContaining([expect.objectContaining({ page: 1, itemsPerPage: 100 })]),
|
||||
]),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -37,6 +37,7 @@ import type {
|
||||
Updater,
|
||||
} from '@tanstack/vue-table';
|
||||
import { createColumnHelper, FlexRender, getCoreRowModel, useVueTable } from '@tanstack/vue-table';
|
||||
import { useThrottleFn } from '@vueuse/core';
|
||||
import { ElCheckbox, ElOption, ElSelect, ElSkeletonItem } from 'element-plus';
|
||||
import get from 'lodash/get';
|
||||
import { computed, h, ref, shallowRef, useSlots, watch } from 'vue';
|
||||
@@ -204,10 +205,7 @@ const page = defineModel<number>('page', { default: 0 });
|
||||
watch(page, () => table.setPageIndex(page.value));
|
||||
|
||||
const itemsPerPage = defineModel<number>('items-per-page', { default: 10 });
|
||||
watch(itemsPerPage, () => {
|
||||
page.value = 0;
|
||||
table.setPageSize(itemsPerPage.value);
|
||||
});
|
||||
watch(itemsPerPage, () => table.setPageSize(itemsPerPage.value));
|
||||
|
||||
const pagination = computed<PaginationState>({
|
||||
get() {
|
||||
@@ -313,6 +311,20 @@ const rowSelection = ref(
|
||||
}, {}),
|
||||
);
|
||||
|
||||
const emitUpdateOptions = useThrottleFn(
|
||||
(payload: TableOptions) => emit('update:options', payload),
|
||||
100,
|
||||
);
|
||||
|
||||
function handlePageSizeChange(newPageSize: number) {
|
||||
// Calculate the maximum available page (0-based indexing)
|
||||
const maxPage = Math.max(0, Math.ceil(props.itemsLength / newPageSize) - 1);
|
||||
const newPage = Math.min(page.value, maxPage);
|
||||
|
||||
page.value = newPage;
|
||||
itemsPerPage.value = newPageSize;
|
||||
}
|
||||
|
||||
const columnHelper = createColumnHelper<T>();
|
||||
const table = useVueTable({
|
||||
data,
|
||||
@@ -334,12 +346,13 @@ const table = useVueTable({
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
onSortingChange: handleSortingChange,
|
||||
onPaginationChange(updaterOrValue) {
|
||||
pagination.value =
|
||||
const newValue =
|
||||
typeof updaterOrValue === 'function' ? updaterOrValue(pagination.value) : updaterOrValue;
|
||||
|
||||
emit('update:options', {
|
||||
page: page.value,
|
||||
itemsPerPage: itemsPerPage.value,
|
||||
// prevent duplicate events from being fired
|
||||
void emitUpdateOptions({
|
||||
page: newValue.pageIndex,
|
||||
itemsPerPage: newValue.pageSize,
|
||||
sortBy: sortBy.value,
|
||||
});
|
||||
},
|
||||
@@ -474,6 +487,7 @@ const table = useVueTable({
|
||||
class="table-pagination__sizes__select"
|
||||
size="small"
|
||||
:teleported="false"
|
||||
@update:model-value="handlePageSizeChange"
|
||||
>
|
||||
<ElOption v-for="item in pageSizes" :key="item" :label="item" :value="item" />
|
||||
</ElSelect>
|
||||
|
||||
@@ -508,4 +508,8 @@ async function onUpdateMfaEnforced(value: boolean) {
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.container {
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user