diff --git a/packages/nc-gui/components/smartsheet/grid/Table.vue b/packages/nc-gui/components/smartsheet/grid/Table.vue index 67f4b53d4f..08d061c85f 100644 --- a/packages/nc-gui/components/smartsheet/grid/Table.vue +++ b/packages/nc-gui/components/smartsheet/grid/Table.vue @@ -558,7 +558,7 @@ const { clearSelectedRangeOfCells, makeEditable, scrollToCell, - (e: KeyboardEvent) => { + async (e: KeyboardEvent) => { // ignore navigating if picker(Date, Time, DateTime, Year) // or single/multi select options is open const activePickerOrDropdownEl = document.querySelector( @@ -601,6 +601,42 @@ const { editEnabled.value = false return true } + } else if (e.key === 'Tab') { + if (e.shiftKey && activeCell.row === 0 && activeCell.col === 0 && !paginationDataRef.value?.isFirstPage) { + e.preventDefault() + await resetAndChangePage((paginationDataRef.value?.pageSize ?? 25) - 1, fields.value?.length - 1, -1) + return true + } else if (!e.shiftKey && activeCell.row === dataRef.value.length - 1 && activeCell.col === fields.value?.length - 1) { + e.preventDefault() + + if (paginationDataRef.value?.isLastPage && isAddingEmptyRowAllowed.value) { + addEmptyRow() + await resetAndChangePage(dataRef.value.length - 1, 0) + return true + } else if (!paginationDataRef.value?.isLastPage) { + await resetAndChangePage(0, 0, 1) + return true + } + } + } else if (!cmdOrCtrl && !e.shiftKey && e.key === 'ArrowUp') { + if (activeCell.row === 0 && !paginationDataRef.value?.isFirstPage) { + e.preventDefault() + await resetAndChangePage((paginationDataRef.value?.pageSize ?? 25) - 1, activeCell.col!, -1) + return true + } + } else if (!cmdOrCtrl && !e.shiftKey && e.key === 'ArrowDown') { + if (activeCell.row === dataRef.value.length - 1) { + e.preventDefault() + + if (paginationDataRef.value?.isLastPage && isAddingEmptyRowAllowed.value) { + addEmptyRow() + await resetAndChangePage(dataRef.value.length - 1, activeCell.col!) + return true + } else if (!paginationDataRef.value?.isLastPage) { + await resetAndChangePage(0, activeCell.col!, 1) + return true + } + } } if (cmdOrCtrl) { @@ -938,6 +974,21 @@ function scrollToCell(row?: number | null, col?: number | null) { } } +async function resetAndChangePage(row: number, col: number, pageChange?: number) { + clearSelectedRange() + + if (pageChange !== undefined && paginationDataRef.value?.page) { + await changePage?.(paginationDataRef.value.page + pageChange) + await nextTick() + makeActive(row, col) + } else { + makeActive(row, col) + await nextTick() + } + + scrollToCell?.() +} + const saveOrUpdateRecords = async (args: { metaValue?: TableType; viewMetaValue?: ViewType; data?: any } = {}) => { let index = -1 for (const currentRow of args.data || dataRef.value) { diff --git a/tests/playwright/tests/db/features/keyboardShortcuts.spec.ts b/tests/playwright/tests/db/features/keyboardShortcuts.spec.ts index 73795f3c90..7a3a72e012 100644 --- a/tests/playwright/tests/db/features/keyboardShortcuts.spec.ts +++ b/tests/playwright/tests/db/features/keyboardShortcuts.spec.ts @@ -137,6 +137,61 @@ test.describe('Verify shortcuts', () => { await page.keyboard.press((await grid.isMacOs()) ? 'Meta+Enter' : 'Control+Enter'); await page.reload(); await grid.cell.verify({ index: 1, columnHeader: 'Country', value: 'NewAlgeria' }); + + // Tab: + // If current page is not last page and and current cell is last column of last row and user press `Tab` then current page will be incremented by 1 + await grid.cell.click({ index: 24, columnHeader: 'Cities' }); + await page.keyboard.press('Tab'); + await grid.verifyActivePage({ pageNumber: '2' }); + await grid.cell.verifyCellActiveSelected({ index: 0, columnHeader: 'Country' }); + + // If current page is last page and and current cell is last column of last row and user press `Tab` then new empty row will be added + await grid.clickPagination({ type: 'last-page' }); + await grid.cell.click({ index: 8, columnHeader: 'Cities' }); + await page.keyboard.press('Tab'); + await grid.verifyRowCount({ count: 10 }); + await grid.cell.verifyCellActiveSelected({ index: 9, columnHeader: 'Country' }); + + // If current page is not first page and and current cell is first column of first row and user press `Shift+Tab` then current page will be decremented by 1 + await grid.cell.click({ index: 0, columnHeader: 'Country' }); + await page.keyboard.press('Shift+Tab'); + await grid.verifyActivePage({ pageNumber: '4' }); + await grid.cell.verifyCellActiveSelected({ index: 24, columnHeader: 'Cities' }); + + // If current page is first page and and current cell is first column of first row and user press `Shift+Tab` then current page will not change + await grid.clickPagination({ type: 'first-page' }); + await grid.cell.click({ index: 0, columnHeader: 'Country' }); + await page.keyboard.press('Shift+Tab'); + await grid.verifyActivePage({ pageNumber: '1' }); + await grid.cell.verifyCellActiveSelected({ index: 0, columnHeader: 'Country' }); + + // ArrowDown: + // If current page is not last page and and current cell is in last row and user press `ArrowDown` then current page will be incremented by 1 + await grid.cell.click({ index: 24, columnHeader: 'Cities' }); + await page.keyboard.press('ArrowDown'); + await grid.verifyActivePage({ pageNumber: '2' }); + await grid.cell.verifyCellActiveSelected({ index: 0, columnHeader: 'Cities' }); + + // If current page is last page and and current cell is in last row and user press `ArrowDown` then new empty row will be added + await grid.clickPagination({ type: 'last-page' }); + await grid.cell.click({ index: 8, columnHeader: 'Cities' }); + await page.keyboard.press('ArrowDown'); + await grid.verifyRowCount({ count: 10 }); + await grid.cell.verifyCellActiveSelected({ index: 9, columnHeader: 'Country' }); + + // ArrowUp: + // If current page is not first page and and current cell is in first row and user press `ArrwoUp` then current page will be decremented by 1 + await grid.cell.click({ index: 0, columnHeader: 'Cities' }); + await page.keyboard.press('ArrowUp'); + await grid.verifyActivePage({ pageNumber: '4' }); + await grid.cell.verifyCellActiveSelected({ index: 24, columnHeader: 'Cities' }); + + // If current page is first page and and current cell is in first row and user press `ArrwoUp` then current page will not change + await grid.clickPagination({ type: 'first-page' }); + await grid.cell.click({ index: 0, columnHeader: 'Cities' }); + await page.keyboard.press('ArrowUp'); + await grid.verifyActivePage({ pageNumber: '1' }); + await grid.cell.verifyCellActiveSelected({ index: 0, columnHeader: 'Cities' }); }); });