Skip to content

Commit 51897dc

Browse files
authored
Fixed an issue where shift + click on rows/columns for range selection did not work in the query tool data output window. #5266
1 parent bbef00a commit 51897dc

1 file changed

Lines changed: 34 additions & 20 deletions

File tree

  • web/pgadmin/tools/sqleditor/static/js/components/QueryToolDataGrid

web/pgadmin/tools/sqleditor/static/js/components/QueryToolDataGrid/index.jsx

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ SelectAllHeaderRenderer.propTypes = {
166166
isCellSelected: PropTypes.bool,
167167
};
168168

169-
function SelectableHeaderRenderer({column, selectedColumns, onSelectedColumnsChange, isCellSelected}) {
169+
function SelectableHeaderRenderer({column, isSelected, onColumnSelected, isCellSelected}) {
170170
const cellRef = useRef();
171171
const eventBus = useContext(QueryToolEventsContext);
172172
const dataGridExtras = useContext(DataGridExtrasContext);
@@ -175,18 +175,10 @@ function SelectableHeaderRenderer({column, selectedColumns, onSelectedColumnsCha
175175
dataGridExtras.onSelectedCellChange?.(null);
176176
}
177177

178-
const onClick = ()=>{
179-
const newSelectedCols = new Set(selectedColumns);
180-
if (newSelectedCols.has(column.idx)) {
181-
newSelectedCols.delete(column.idx);
182-
} else {
183-
newSelectedCols.add(column.idx);
184-
}
185-
onSelectedColumnsChange(newSelectedCols);
178+
const onClick = (e)=>{
179+
onColumnSelected(column.idx, isSelected, (e.nativeEvent).shiftKey);
186180
};
187181

188-
const isSelected = selectedColumns.has(column.idx);
189-
190182
useLayoutEffect(() => {
191183
if (!isCellSelected) return;
192184
cellRef.current?.focus({ preventScroll: true });
@@ -215,8 +207,8 @@ function SelectableHeaderRenderer({column, selectedColumns, onSelectedColumnsCha
215207
}
216208
SelectableHeaderRenderer.propTypes = {
217209
column: PropTypes.object,
218-
selectedColumns: PropTypes.objectOf(Set),
219-
onSelectedColumnsChange: PropTypes.func,
210+
isSelected: PropTypes.bool,
211+
onColumnSelected: PropTypes.func,
220212
isCellSelected: PropTypes.bool,
221213
};
222214

@@ -305,9 +297,9 @@ function RowNumColFormatter({row, rowKeyGetter, rowIdx, dataChangeStore, onSelec
305297
} else if(rowKey in (dataChangeStore?.deleted || {})) {
306298
rownum = rownum+'-';
307299
}
308-
return (<div className='QueryTool-rowNumCell' onClick={()=>{
300+
return (<div className='QueryTool-rowNumCell' onClick={(e)=>{
309301
onSelectedColumnsChange(new Set());
310-
onRowSelectionChange({ type: 'ROW', row: row, checked: !isRowSelected, isShiftClick: false});
302+
onRowSelectionChange({ type: 'ROW', row: row, checked: !isRowSelected, isShiftClick: (e.nativeEvent).shiftKey});
311303
}} onKeyDown={()=>{/* already taken care by parent */}}>
312304
{rownum}
313305
</div>);
@@ -320,13 +312,16 @@ RowNumColFormatter.propTypes = {
320312
onSelectedColumnsChange: PropTypes.func,
321313
};
322314

323-
function formatColumns(columns, dataChangeStore, selectedColumns, onSelectedColumnsChange, rowKeyGetter) {
315+
function formatColumns(columns, dataChangeStore, selectedColumns, onColumnSelected, onSelectedColumnsChange, rowKeyGetter) {
324316
let retColumns = [
325317
...columns,
326318
];
327319

328-
const HeaderRenderer = (props)=>{
329-
return <SelectableHeaderRenderer {...props} selectedColumns={selectedColumns} onSelectedColumnsChange={onSelectedColumnsChange}/>;
320+
const HeaderRenderer = ({column, ...props})=>{
321+
return <SelectableHeaderRenderer {...props} column={column} isSelected={selectedColumns.has(column.idx)} onColumnSelected={onColumnSelected}/>;
322+
};
323+
HeaderRenderer.propTypes = {
324+
column: PropTypes.object,
330325
};
331326

332327
for(const [idx, col] of retColumns.entries()) {
@@ -377,7 +372,26 @@ function getColumnWidth(column, rows, canvas, columnWidthBy) {
377372
export default function QueryToolDataGrid({columns, rows, totalRowCount, dataChangeStore,
378373
onSelectedCellChange, selectedColumns, onSelectedColumnsChange, columnWidthBy, startRowNum, ...props}) {
379374
const [readyColumns, setReadyColumns] = useState([]);
375+
const [lastSelectedColumn, setLastSelectedColumn] = useState(null);
380376
const eventBus = useContext(QueryToolEventsContext);
377+
const onColumnSelected = (columnIdx, isSelected, isShiftClick)=>{
378+
const newSelectedCols = new Set(selectedColumns);
379+
const start = isShiftClick && lastSelectedColumn ? Math.min(columnIdx, lastSelectedColumn) : columnIdx;
380+
const end = isShiftClick && lastSelectedColumn ? Math.max(columnIdx, lastSelectedColumn) : columnIdx;
381+
for (let i = start; i <= end; i++) {
382+
if (isSelected) {
383+
newSelectedCols.delete(i);
384+
}
385+
else {
386+
newSelectedCols.add(i);
387+
}
388+
}
389+
390+
props.onSelectedRowsChange(new Set());
391+
setLastSelectedColumn(columnIdx);
392+
onSelectedColumnsChange(newSelectedCols);
393+
};
394+
381395
const onSelectedColumnsChangeWrapped = (arg)=>{
382396
props.onSelectedRowsChange(new Set());
383397
onSelectedColumnsChange(arg);
@@ -411,12 +425,12 @@ export default function QueryToolDataGrid({columns, rows, totalRowCount, dataCha
411425

412426
useEffect(()=>{
413427
let initCols = initialiseColumns(columns, rows, totalRowCount, columnWidthBy);
414-
setReadyColumns(formatColumns(initCols, dataChangeStore, selectedColumns, onSelectedColumnsChangeWrapped, props.rowKeyGetter));
428+
setReadyColumns(formatColumns(initCols, dataChangeStore, selectedColumns, onColumnSelected, onSelectedColumnsChangeWrapped, props.rowKeyGetter));
415429
}, [columns]);
416430

417431
useEffect(()=>{
418432
setReadyColumns((prevCols)=>{
419-
return formatColumns(prevCols, dataChangeStore, selectedColumns, onSelectedColumnsChangeWrapped, props.rowKeyGetter);
433+
return formatColumns(prevCols, dataChangeStore, selectedColumns, onColumnSelected, onSelectedColumnsChangeWrapped, props.rowKeyGetter);
420434
});
421435
}, [dataChangeStore, selectedColumns]);
422436

0 commit comments

Comments
 (0)