diff --git a/packages/grid/src/Grid.tsx b/packages/grid/src/Grid.tsx index 228c77f943..8ca5f7ba46 100644 --- a/packages/grid/src/Grid.tsx +++ b/packages/grid/src/Grid.tsx @@ -488,12 +488,11 @@ class Grid extends PureComponent { // apply on mount, so that it works with a static model // https://github.com/deephaven/web-client-ui/issues/581 const { isStuckToBottom, isStuckToRight } = this.props; - if (isStuckToBottom) { - this.scrollToBottom(); - } - if (isStuckToRight) { - this.scrollToRight(); - } + const { top, left } = this.getStickyScrollPosition( + isStuckToBottom, + isStuckToRight + ); + this.setState({ top, left }); } componentDidUpdate(prevProps: GridProps, prevState: GridState): void { @@ -576,7 +575,14 @@ class Grid extends PureComponent { this.requestUpdateCanvas(); - this.checkStickyScroll(); + if (this.needToUpdateScroll()) { + const { top, left } = this.getStickyScrollPosition( + isStickyBottom, + isStickyRight + ); + updatedState.top = top; + updatedState.left = left; + } if (this.validateSelection()) { this.checkSelectionChange(prevState); @@ -741,29 +747,41 @@ class Grid extends PureComponent { this.setState({ isStuckToBottom: false }); } - /** - * Scrolls to bottom, if not already at bottom - */ - scrollToBottom(): void { - if (!this.metrics) return; - const { bottomVisible, rowCount, top, lastTop } = this.metrics; - if ((bottomVisible < rowCount - 1 && bottomVisible > 0) || top > lastTop) { - this.setState({ top: lastTop }); - } - } + getStickyScrollPosition( + isStickyBottom: boolean, + isStickyRight: boolean + ): { top: VisibleIndex; left: VisibleIndex } { + // eslint-disable-next-line react/destructuring-assignment + if (!this.metrics) return { left: this.state.left, top: this.state.top }; - /** - * Scrolls to right, if not already at right - */ - scrollToRight(): void { - if (!this.metrics) return; - const { rightVisible, columnCount, left, lastLeft } = this.metrics; + const { + bottomVisible, + rowCount, + top, + lastTop, + rightVisible, + columnCount, + left, + lastLeft, + } = this.metrics; + + let newTop = top; + let newLeft = left; + + if ( + isStickyBottom && + ((bottomVisible < rowCount - 1 && bottomVisible > 0) || top > lastTop) + ) { + newTop = lastTop; + } if ( - (rightVisible < columnCount - 1 && rightVisible > 0) || - left > lastLeft + isStickyRight && + ((rightVisible < columnCount - 1 && rightVisible > 0) || left > lastLeft) ) { - this.setState({ left: lastLeft }); + newLeft = lastLeft; } + + return { top: newTop, left: newLeft }; } /** @@ -888,35 +906,32 @@ class Grid extends PureComponent { /** * Compares the current metrics with the previous metrics to see if we need to scroll when it is stuck to the bottom or the right */ - checkStickyScroll(): void { - if (!this.metrics) { - return; + needToUpdateScroll(): boolean { + if (!this.metrics || !this.prevMetrics) { + return false; } - if (this.prevMetrics) { - const { rowCount, columnCount, height, width } = this.metrics; - const { - rowCount: prevRowCount, - columnCount: prevColumnCount, - height: prevHeight, - width: prevWidth, - } = this.prevMetrics; - - if (prevRowCount !== rowCount || height !== prevHeight) { - const { isStuckToBottom } = this.state; - if (isStuckToBottom) { - this.scrollToBottom(); - } + const { rowCount, columnCount, height, width } = this.metrics; + const { + rowCount: prevRowCount, + columnCount: prevColumnCount, + height: prevHeight, + width: prevWidth, + } = this.prevMetrics; + + if (prevRowCount !== rowCount || height !== prevHeight) { + const { isStuckToBottom } = this.state; + if (isStuckToBottom) { + return true; } - - if (prevColumnCount !== columnCount || width !== prevWidth) { - const { isStuckToRight } = this.state; - if (isStuckToRight) { - this.scrollToRight(); - } + } + if (prevColumnCount !== columnCount || width !== prevWidth) { + const { isStuckToRight } = this.state; + if (isStuckToRight) { + return true; } } - this.prevMetrics = this.metrics; + return false; } updateMetrics(state = this.state): GridMetrics { diff --git a/tests/docker-scripts/data/app.d/table_generators.py b/tests/docker-scripts/data/app.d/table_generators.py new file mode 100644 index 0000000000..36fe6ba9e0 --- /dev/null +++ b/tests/docker-scripts/data/app.d/table_generators.py @@ -0,0 +1,26 @@ +from deephaven import empty_table, function_generated_table +from deephaven.execution_context import get_exec_ctx + +# Creates a table that can be shrunk and grown in size +def create_shrink_grow_table(): + ctx = get_exec_ctx() + i = 50 + + def make_table(): + return empty_table(i).update(["X = i"]) + + def shrink_table(): + nonlocal i + i = 30; + + def grow_table(): + nonlocal i + i = 70; + + table = function_generated_table( + table_generator=make_table, + refresh_interval_ms=1000, + exec_ctx=ctx + ) + + return table, shrink_table, grow_table diff --git a/tests/docker-scripts/data/app.d/test.app b/tests/docker-scripts/data/app.d/test.app index 3da8f2d60b..7b4875cc06 100644 --- a/tests/docker-scripts/data/app.d/test.app +++ b/tests/docker-scripts/data/app.d/test.app @@ -6,3 +6,4 @@ name=Web UI Test Application file_0=common_figures.py file_1=common_tables.py file_2=multiselect_tables.py +file_3=table_generators.py diff --git a/tests/table-scroll.spec.ts b/tests/table-scroll.spec.ts new file mode 100644 index 0000000000..c23172a212 --- /dev/null +++ b/tests/table-scroll.spec.ts @@ -0,0 +1,98 @@ +import { test, expect } from '@playwright/test'; +import { + waitForLoadingDone, + gotoPage, + pasteInMonaco, + generateId, +} from './utils'; + +test.beforeEach(async ({ page }) => { + await gotoPage(page, ''); + + // Fail quickly if console errors are detected + page.on('console', msg => { + if (msg.type() === 'error') { + throw new Error(msg.text()); + } + }); + page.on('pageerror', error => { + throw error; + }); +}); + +test('stuck to bottom scroll growing table', async ({ page }) => { + // Need to generate a new shrink grow table for each test + const id = generateId(); + const tableName = `_${id}_shrink_grow_table`; + const growFunction = `func_${id}`; + const consoleInput = page.locator('.console-input'); + + await pasteInMonaco( + consoleInput, + `${tableName}, _, ${growFunction} = create_shrink_grow_table()` + ); + await page.keyboard.press('Enter'); + await waitForLoadingDone(page); + + // Open the newly created table + const openButton = page.getByRole('button', { name: tableName, exact: true }); + await openButton.click(); + await waitForLoadingDone(page); + + const gridCanvas = page.locator('.iris-grid .grid-wrapper'); + await gridCanvas.click({ position: { x: 10, y: 80 } }); + // Scroll to end of table to get stuck at bottom + await page.mouse.wheel(0, 1000); + await expect(page.locator('.iris-grid-column')).toHaveScreenshot(); + + // Add more rows to the table and take another screenshot + await pasteInMonaco(consoleInput, `${growFunction}()`); + await page.keyboard.press('Enter'); + + // No reliable way to know when the added rows have loaded, so just wait + await page.waitForTimeout(2000); + await expect(page.locator('.iris-grid-column')).toHaveScreenshot(); +}); + +test('stuck to bottom scroll shrinking and growing table', async ({ page }) => { + // Need to generate a new shrink grow table for each test + const id = generateId(); + const tableName = `_${id}_shrink_grow_table`; + const growFunction = `grow_${id}`; + const shrinkFunction = `shrink_${id}`; + const consoleInput = page.locator('.console-input'); + + await pasteInMonaco( + consoleInput, + `${tableName}, ${shrinkFunction}, ${growFunction} = create_shrink_grow_table()` + ); + await page.keyboard.press('Enter'); + await waitForLoadingDone(page); + + // Open the newly created table + const openButton = page.getByRole('button', { name: tableName, exact: true }); + await openButton.click(); + await waitForLoadingDone(page); + + const gridCanvas = page.locator('.iris-grid .grid-wrapper'); + await gridCanvas.click({ position: { x: 10, y: 80 } }); + // Scroll to end of table to get stuck at bottom + await page.mouse.wheel(0, 1000); + await expect(page.locator('.iris-grid-column')).toHaveScreenshot(); + + // Shrink the table and take another screenshot + await pasteInMonaco(consoleInput, `${shrinkFunction}()`); + await page.keyboard.press('Enter'); + + // No reliable way to know when the removed rows have loaded, so just wait + await page.waitForTimeout(2000); + await expect(page.locator('.iris-grid-column')).toHaveScreenshot(); + + // Add more rows to the table and take another screenshot + await pasteInMonaco(consoleInput, `${growFunction}()`); + await page.keyboard.press('Enter'); + + // No reliable way to know when the added rows have loaded, so just wait + await page.waitForTimeout(2000); + await expect(page.locator('.iris-grid-column')).toHaveScreenshot(); +}); diff --git a/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-growing-table-1-chromium-linux.png b/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-growing-table-1-chromium-linux.png new file mode 100644 index 0000000000..91319a48c9 Binary files /dev/null and b/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-growing-table-1-chromium-linux.png differ diff --git a/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-growing-table-1-firefox-linux.png b/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-growing-table-1-firefox-linux.png new file mode 100644 index 0000000000..bee9d4f0a2 Binary files /dev/null and b/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-growing-table-1-firefox-linux.png differ diff --git a/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-growing-table-1-webkit-linux.png b/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-growing-table-1-webkit-linux.png new file mode 100644 index 0000000000..40fab74472 Binary files /dev/null and b/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-growing-table-1-webkit-linux.png differ diff --git a/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-growing-table-2-chromium-linux.png b/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-growing-table-2-chromium-linux.png new file mode 100644 index 0000000000..6821eaa0ff Binary files /dev/null and b/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-growing-table-2-chromium-linux.png differ diff --git a/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-growing-table-2-firefox-linux.png b/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-growing-table-2-firefox-linux.png new file mode 100644 index 0000000000..b1924240af Binary files /dev/null and b/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-growing-table-2-firefox-linux.png differ diff --git a/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-growing-table-2-webkit-linux.png b/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-growing-table-2-webkit-linux.png new file mode 100644 index 0000000000..f3e92e58d9 Binary files /dev/null and b/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-growing-table-2-webkit-linux.png differ diff --git a/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-shrinking-and-growing-table-1-chromium-linux.png b/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-shrinking-and-growing-table-1-chromium-linux.png new file mode 100644 index 0000000000..91319a48c9 Binary files /dev/null and b/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-shrinking-and-growing-table-1-chromium-linux.png differ diff --git a/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-shrinking-and-growing-table-1-firefox-linux.png b/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-shrinking-and-growing-table-1-firefox-linux.png new file mode 100644 index 0000000000..bee9d4f0a2 Binary files /dev/null and b/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-shrinking-and-growing-table-1-firefox-linux.png differ diff --git a/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-shrinking-and-growing-table-1-webkit-linux.png b/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-shrinking-and-growing-table-1-webkit-linux.png new file mode 100644 index 0000000000..40fab74472 Binary files /dev/null and b/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-shrinking-and-growing-table-1-webkit-linux.png differ diff --git a/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-shrinking-and-growing-table-2-chromium-linux.png b/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-shrinking-and-growing-table-2-chromium-linux.png new file mode 100644 index 0000000000..0fc9372101 Binary files /dev/null and b/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-shrinking-and-growing-table-2-chromium-linux.png differ diff --git a/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-shrinking-and-growing-table-2-firefox-linux.png b/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-shrinking-and-growing-table-2-firefox-linux.png new file mode 100644 index 0000000000..9ab45efac3 Binary files /dev/null and b/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-shrinking-and-growing-table-2-firefox-linux.png differ diff --git a/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-shrinking-and-growing-table-2-webkit-linux.png b/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-shrinking-and-growing-table-2-webkit-linux.png new file mode 100644 index 0000000000..670bb43034 Binary files /dev/null and b/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-shrinking-and-growing-table-2-webkit-linux.png differ diff --git a/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-shrinking-and-growing-table-3-chromium-linux.png b/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-shrinking-and-growing-table-3-chromium-linux.png new file mode 100644 index 0000000000..6821eaa0ff Binary files /dev/null and b/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-shrinking-and-growing-table-3-chromium-linux.png differ diff --git a/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-shrinking-and-growing-table-3-firefox-linux.png b/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-shrinking-and-growing-table-3-firefox-linux.png new file mode 100644 index 0000000000..b1924240af Binary files /dev/null and b/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-shrinking-and-growing-table-3-firefox-linux.png differ diff --git a/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-shrinking-and-growing-table-3-webkit-linux.png b/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-shrinking-and-growing-table-3-webkit-linux.png new file mode 100644 index 0000000000..f3e92e58d9 Binary files /dev/null and b/tests/table-scroll.spec.ts-snapshots/stuck-to-bottom-scroll-shrinking-and-growing-table-3-webkit-linux.png differ