diff --git a/web/package.json b/web/package.json index 8be5818fbda..f7670618a7f 100644 --- a/web/package.json +++ b/web/package.json @@ -110,7 +110,7 @@ "react-arborist": "^3.16.0", "react-aspen": "^1.2.0", "react-checkbox-tree": "^2.1.1", - "react-data-grid": "https://github.com/pgadmin-org/react-data-grid.git#8ddaa7bed99c8329e39b8ff37ba156f7fc8e85d4", + "react-data-grid": "https://github.com/pgadmin-org/react-data-grid.git#d9dccda1ff4bfc155b6893d0c0ff7585cf0bc101", "react-dnd": "^16.0.1", "react-dnd-html5-backend": "^16.0.1", "react-dom": "^19.3.0", diff --git a/web/pgadmin/tools/sqleditor/static/js/components/QueryToolDataGrid/index.jsx b/web/pgadmin/tools/sqleditor/static/js/components/QueryToolDataGrid/index.jsx index 432f8e10ad3..1003761a393 100644 --- a/web/pgadmin/tools/sqleditor/static/js/components/QueryToolDataGrid/index.jsx +++ b/web/pgadmin/tools/sqleditor/static/js/components/QueryToolDataGrid/index.jsx @@ -311,6 +311,19 @@ RowNumColFormatter.propTypes = { onSelectedColumnsChange: PropTypes.func, }; +/* Shift + mousedown on a cell extends the selected cell range, but on the + * row number column shift + click belongs to row selection (handled by + * RowNumColFormatter). Select the row number cell as a plain click would, + * so a cell range left over from earlier is cleared rather than kept + * alongside the selected rows. + */ +export function onCellMouseDown({column, selectCell}, e) { + if(column.key == ROWNUM_KEY && e.shiftKey) { + e.preventGridDefault(); + selectCell(); + } +} + function formatColumns(columns, dataChangeStore, selectedColumns, onColumnSelected, onSelectedColumnsChange, rowKeyGetter) { let retColumns = [ ...columns, @@ -465,6 +478,7 @@ export default function QueryToolDataGrid({columns, rows, totalRowCount, dataCha }} enableRangeSelection={true} rangeLeftBoundaryColIdx={0} + onCellMouseDown={onCellMouseDown} onCellKeyDown={({column, rowIdx, selectCell, mode}, e)=>{ /* Enter should not be propagated to editor and should only be used to open the editor */ diff --git a/web/regression/javascript/sqleditor/QueryToolDataGridMouseDown.spec.js b/web/regression/javascript/sqleditor/QueryToolDataGridMouseDown.spec.js new file mode 100644 index 00000000000..86b02c3fd8a --- /dev/null +++ b/web/regression/javascript/sqleditor/QueryToolDataGridMouseDown.spec.js @@ -0,0 +1,55 @@ +///////////////////////////////////////////////////////////// +// +// pgAdmin 4 - PostgreSQL Tools +// +// Copyright (C) 2013 - 2026, The pgAdmin Development Team +// This software is released under the PostgreSQL Licence +// +////////////////////////////////////////////////////////////// + +// Shift + mousedown on a results grid cell extends the cell range, but on +// the row number column it must select the cell as a plain click does, so +// that row selection is not mixed with a left-over cell range. + +jest.mock('../../../pgadmin/tools/sqleditor/static/js/components/QueryToolComponent.jsx', () => { + const React = require('react'); + return { + QueryToolContext: React.createContext(null), + QueryToolConnectionContext: React.createContext(null), + QueryToolEventsContext: React.createContext(null), + }; +}); + +// The cell editors pull in ESM-only dependencies that Jest cannot load. +jest.mock('../../../pgadmin/tools/sqleditor/static/js/components/QueryToolDataGrid/Editors', () => ({})); + +import { + onCellMouseDown, ROWNUM_KEY, +} from '../../../pgadmin/tools/sqleditor/static/js/components/QueryToolDataGrid'; + +function mouseDown(columnKey, shiftKey) { + const selectCell = jest.fn(); + const e = {shiftKey, preventGridDefault: jest.fn()}; + onCellMouseDown({column: {key: columnKey}, selectCell}, e); + return {selectCell, e}; +} + +describe('QueryToolDataGrid onCellMouseDown', () => { + it('selects the row number cell on shift + mousedown', () => { + const {selectCell, e} = mouseDown(ROWNUM_KEY, true); + expect(e.preventGridDefault).toHaveBeenCalled(); + expect(selectCell).toHaveBeenCalled(); + }); + + it('leaves shift + mousedown on a data cell to the grid', () => { + const {selectCell, e} = mouseDown('col1', true); + expect(e.preventGridDefault).not.toHaveBeenCalled(); + expect(selectCell).not.toHaveBeenCalled(); + }); + + it('leaves a plain mousedown on the row number cell to the grid', () => { + const {selectCell, e} = mouseDown(ROWNUM_KEY, false); + expect(e.preventGridDefault).not.toHaveBeenCalled(); + expect(selectCell).not.toHaveBeenCalled(); + }); +}); diff --git a/web/yarn.lock b/web/yarn.lock index 9ae4d7952f0..60d4ea1a294 100644 --- a/web/yarn.lock +++ b/web/yarn.lock @@ -12407,13 +12407,13 @@ __metadata: languageName: node linkType: hard -"react-data-grid@https://github.com/pgadmin-org/react-data-grid.git#8ddaa7bed99c8329e39b8ff37ba156f7fc8e85d4": +"react-data-grid@https://github.com/pgadmin-org/react-data-grid.git#d9dccda1ff4bfc155b6893d0c0ff7585cf0bc101": version: 7.0.0-beta.58 - resolution: "react-data-grid@https://github.com/pgadmin-org/react-data-grid.git#commit=8ddaa7bed99c8329e39b8ff37ba156f7fc8e85d4" + resolution: "react-data-grid@https://github.com/pgadmin-org/react-data-grid.git#commit=d9dccda1ff4bfc155b6893d0c0ff7585cf0bc101" peerDependencies: react: ^19.2 react-dom: ^19.2 - checksum: 10c0/531f86c950e4f656cc45f496f7d5f95aaf2c7e2884d864d7954456e531810e7a7d99d52ee984b4140f034fafdc3f601913b8aa0949c8a06df784716dda66f06c + checksum: 10c0/53bc16d319c07fe5a4b4450f6afbab06b6d8210aebca2724ab13d339bf523fafb41af26d0e4991d0270aede6796e29c8fd388e7555219043398e8387e2c14a35 languageName: node linkType: hard @@ -13098,7 +13098,7 @@ __metadata: react-arborist: "npm:^3.16.0" react-aspen: "npm:^1.2.0" react-checkbox-tree: "npm:^2.1.1" - react-data-grid: "https://github.com/pgadmin-org/react-data-grid.git#8ddaa7bed99c8329e39b8ff37ba156f7fc8e85d4" + react-data-grid: "https://github.com/pgadmin-org/react-data-grid.git#d9dccda1ff4bfc155b6893d0c0ff7585cf0bc101" react-dnd: "npm:^16.0.1" react-dnd-html5-backend: "npm:^16.0.1" react-dom: "npm:^19.3.0"