mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-17 21:26:00 +00:00
SYNC: improved data grid navigation
This commit is contained in:
committed by
Diflow
parent
a57063adf7
commit
76ae2e0e5a
@@ -25,6 +25,7 @@
|
||||
export let setFilter;
|
||||
export let showResizeSplitter = false;
|
||||
export let onFocusGrid = null;
|
||||
export let onFocusGridHeader = null;
|
||||
export let onGetReference = null;
|
||||
export let foreignKey = null;
|
||||
export let conid = null;
|
||||
@@ -204,6 +205,11 @@
|
||||
// ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
}
|
||||
if (ev.keyCode == keycodes.upArrow) {
|
||||
if (onFocusGridHeader) onFocusGridHeader();
|
||||
// ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
}
|
||||
// if (ev.keyCode == KeyCodes.DownArrow || ev.keyCode == KeyCodes.UpArrow) {
|
||||
// if (this.props.onControlKey) this.props.onControlKey(ev.keyCode);
|
||||
// }
|
||||
|
||||
@@ -380,7 +380,17 @@
|
||||
filterCellsForRow,
|
||||
} from './gridutil';
|
||||
import HorizontalScrollBar from './HorizontalScrollBar.svelte';
|
||||
import { cellFromEvent, emptyCellArray, getCellRange, isRegularCell, nullCell, topLeftCell } from './selection';
|
||||
import {
|
||||
cellFromEvent,
|
||||
emptyCellArray,
|
||||
getCellRange,
|
||||
isColumnHeaderCell,
|
||||
isRegularCell,
|
||||
isRowHeaderCell,
|
||||
isTableHeaderCell,
|
||||
nullCell,
|
||||
topLeftCell,
|
||||
} from './selection';
|
||||
import VerticalScrollBar from './VerticalScrollBar.svelte';
|
||||
import LoadingInfo from '../elements/LoadingInfo.svelte';
|
||||
import InlineButton from '../buttons/InlineButton.svelte';
|
||||
@@ -1305,7 +1315,7 @@
|
||||
function scrollIntoView(cell) {
|
||||
const [row, col] = cell;
|
||||
|
||||
if (row != null) {
|
||||
if (_.isNumber(row)) {
|
||||
let newRow = null;
|
||||
const rowCount = grider.rowCount;
|
||||
if (rowCount == 0) return;
|
||||
@@ -1323,7 +1333,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
if (col != null) {
|
||||
if (_.isNumber(col)) {
|
||||
if (col >= columnSizes.frozenCount) {
|
||||
let newColumn = columnSizes.scrollInView(
|
||||
firstVisibleColumnScrollIndex,
|
||||
@@ -1553,7 +1563,11 @@
|
||||
}
|
||||
|
||||
if (event.shiftKey) {
|
||||
if (!isRegularCell(shiftDragStartCell)) {
|
||||
if (
|
||||
!isRegularCell(shiftDragStartCell) &&
|
||||
!isColumnHeaderCell(shiftDragStartCell) &&
|
||||
!isRowHeaderCell(shiftDragStartCell)
|
||||
) {
|
||||
shiftDragStartCell = currentCell;
|
||||
}
|
||||
} else {
|
||||
@@ -1581,7 +1595,13 @@
|
||||
}
|
||||
|
||||
function handleCursorMove(event) {
|
||||
if (!isRegularCell(currentCell)) return null;
|
||||
if (
|
||||
!isRegularCell(currentCell) &&
|
||||
!isColumnHeaderCell(currentCell) &&
|
||||
!isRowHeaderCell(currentCell) &&
|
||||
!isTableHeaderCell(currentCell)
|
||||
)
|
||||
return null;
|
||||
let rowCount = grider.rowCount;
|
||||
if (isCtrlOrCommandKey(event)) {
|
||||
switch (event.keyCode) {
|
||||
@@ -1608,24 +1628,36 @@
|
||||
switch (event.keyCode) {
|
||||
case keycodes.upArrow:
|
||||
if (currentCell[0] == 0) return focusFilterEditor(currentCell[1]);
|
||||
return moveCurrentCell(currentCell[0] - 1, currentCell[1], event);
|
||||
return _.isNumber(currentCell[0]) ? moveCurrentCell(currentCell[0] - 1, currentCell[1], event) : null;
|
||||
case keycodes.downArrow:
|
||||
return moveCurrentCell(currentCell[0] + 1, currentCell[1], event);
|
||||
if (currentCell[0] == 'header') return focusFilterEditor(currentCell[1]);
|
||||
return _.isNumber(currentCell[0]) ? moveCurrentCell(currentCell[0] + 1, currentCell[1], event) : null;
|
||||
case keycodes.enter:
|
||||
if (!grider.editable) return moveCurrentCell(currentCell[0] + 1, currentCell[1], event);
|
||||
if (!grider.editable)
|
||||
return _.isNumber(currentCell[0]) ? moveCurrentCell(currentCell[0] + 1, currentCell[1], event) : null;
|
||||
break;
|
||||
case keycodes.leftArrow:
|
||||
return moveCurrentCell(currentCell[0], currentCell[1] - 1, event);
|
||||
return _.isNumber(currentCell[1])
|
||||
? moveCurrentCell(currentCell[0], currentCell[1] == 0 ? 'header' : currentCell[1] - 1, event)
|
||||
: null;
|
||||
case keycodes.rightArrow:
|
||||
return moveCurrentCell(currentCell[0], currentCell[1] + 1, event);
|
||||
return currentCell[1] == 'header'
|
||||
? moveCurrentCell(currentCell[0], 0, event)
|
||||
: _.isNumber(currentCell[1])
|
||||
? moveCurrentCell(currentCell[0], currentCell[1] + 1, event)
|
||||
: null;
|
||||
case keycodes.home:
|
||||
return moveCurrentCell(currentCell[0], 0, event);
|
||||
case keycodes.end:
|
||||
return moveCurrentCell(currentCell[0], columnSizes.realCount - 1, event);
|
||||
case keycodes.pageUp:
|
||||
return moveCurrentCell(currentCell[0] - visibleRowCountLowerBound, currentCell[1], event);
|
||||
return _.isNumber(currentCell[0])
|
||||
? moveCurrentCell(currentCell[0] - visibleRowCountLowerBound, currentCell[1], event)
|
||||
: null;
|
||||
case keycodes.pageDown:
|
||||
return moveCurrentCell(currentCell[0] + visibleRowCountLowerBound, currentCell[1], event);
|
||||
return _.isNumber(currentCell[0])
|
||||
? moveCurrentCell(currentCell[0] + visibleRowCountLowerBound, currentCell[1], event)
|
||||
: null;
|
||||
case keycodes.tab: {
|
||||
return moveCurrentCellWithTabKey(event.shiftKey);
|
||||
}
|
||||
@@ -1659,10 +1691,14 @@
|
||||
function moveCurrentCell(row, col, event = null) {
|
||||
const rowCount = grider.rowCount;
|
||||
|
||||
if (row < 0) row = 0;
|
||||
if (row >= rowCount) row = rowCount - 1;
|
||||
if (col < 0) col = 0;
|
||||
if (col >= columnSizes.realCount) col = columnSizes.realCount - 1;
|
||||
if (_.isNumber(row)) {
|
||||
if (row < 0) row = 0;
|
||||
if (row >= rowCount) row = rowCount - 1;
|
||||
}
|
||||
if (_.isNumber(col)) {
|
||||
if (col < 0) col = 0;
|
||||
if (col >= columnSizes.realCount) col = columnSizes.realCount - 1;
|
||||
}
|
||||
currentCell = [row, col];
|
||||
// setSelectedCells([...(event.ctrlKey ? selectedCells : []), [row, col]]);
|
||||
selectedCells = [[row, col]];
|
||||
@@ -1782,6 +1818,17 @@
|
||||
if (domFocusField) domFocusField.focus();
|
||||
};
|
||||
|
||||
const selectColumnHeaderCell = uniquePath => {
|
||||
const modelIndex = columns.findIndex(x => x.uniquePath == uniquePath);
|
||||
const realIndex = columnSizes.modelToReal(modelIndex);
|
||||
let cell = ['header', realIndex];
|
||||
// @ts-ignore
|
||||
currentCell = cell;
|
||||
// @ts-ignore
|
||||
selectedCells = [cell];
|
||||
if (domFocusField) domFocusField.focus();
|
||||
};
|
||||
|
||||
const [inplaceEditorState, dispatchInsplaceEditor] = createReducer((state, action) => {
|
||||
switch (action.type) {
|
||||
case 'show':
|
||||
@@ -2031,6 +2078,7 @@
|
||||
data-row="header"
|
||||
data-col={col.colIndex}
|
||||
style={`width:${col.width}px; min-width:${col.width}px; max-width:${col.width}px`}
|
||||
class:active-header-cell={currentCell && currentCell[0] == 'header' && currentCell[1] == col.colIndex}
|
||||
>
|
||||
<ColumnHeaderControl
|
||||
column={col}
|
||||
@@ -2105,6 +2153,9 @@
|
||||
onFocusGrid={() => {
|
||||
selectTopmostCell(col.uniqueName);
|
||||
}}
|
||||
onFocusGridHeader={() => {
|
||||
selectColumnHeaderCell(col.uniqueName);
|
||||
}}
|
||||
dataType={col.dataType}
|
||||
filterDisabled={display.isFilterDisabled(col.uniqueName)}
|
||||
/>
|
||||
@@ -2231,6 +2282,9 @@
|
||||
background-color: var(--theme-bg-1);
|
||||
overflow: hidden;
|
||||
}
|
||||
:global(.data-grid-focused) .active-header-cell {
|
||||
background-color: var(--theme-bg-selected);
|
||||
}
|
||||
.filter-cell {
|
||||
text-align: left;
|
||||
overflow: hidden;
|
||||
|
||||
@@ -76,6 +76,7 @@
|
||||
onShowForm={onSetFormView && !overlayDefinition ? () => onSetFormView(rowData, null) : null}
|
||||
extraIcon={overlayDefinition ? OVERLAY_STATUS_ICONS[rowStatus.status] : null}
|
||||
extraIconTooltip={overlayDefinition ? OVERLAY_STATUS_TOOLTIPS[rowStatus.status] : null}
|
||||
isSelected={frameSelection ? false : !!selectedCells?.find(cell => cell[0] == rowIndex && cell[1] == 'header')}
|
||||
/>
|
||||
{#each visibleRealColumns as col (col.uniqueName)}
|
||||
{#if inplaceEditorState.cell && rowIndex == inplaceEditorState.cell[0] && col.colIndex == inplaceEditorState.cell[1]}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
export let extraIcon = null;
|
||||
export let extraIconTooltip = null;
|
||||
export let isSelected = false;
|
||||
|
||||
let mouseIn = false;
|
||||
</script>
|
||||
@@ -14,6 +15,7 @@
|
||||
<td
|
||||
data-row={rowIndex}
|
||||
data-col="header"
|
||||
class:selected={isSelected}
|
||||
on:mouseenter={() => (mouseIn = true)}
|
||||
on:mouseleave={() => (mouseIn = false)}
|
||||
>
|
||||
@@ -43,4 +45,7 @@
|
||||
right: 0px;
|
||||
top: 1px;
|
||||
}
|
||||
:global(.data-grid-focused) td.selected {
|
||||
background-color: var(--theme-bg-selected);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -13,6 +13,24 @@ export function isRegularCell(cell: CellAddress): cell is RegularCellAddress {
|
||||
return _.isNumber(row) && _.isNumber(col);
|
||||
}
|
||||
|
||||
export function isRowHeaderCell(cell: CellAddress): boolean {
|
||||
if (!cell) return false;
|
||||
const [row, col] = cell;
|
||||
return col === 'header' && _.isNumber(row);
|
||||
}
|
||||
|
||||
export function isColumnHeaderCell(cell: CellAddress): boolean {
|
||||
if (!cell) return false;
|
||||
const [row, col] = cell;
|
||||
return row === 'header' && _.isNumber(col);
|
||||
}
|
||||
|
||||
export function isTableHeaderCell(cell: CellAddress): boolean {
|
||||
if (!cell) return false;
|
||||
const [row, col] = cell;
|
||||
return row === 'header' && col === 'header';
|
||||
}
|
||||
|
||||
function normalizeHeaderForSelection(addr: CellAddress): CellAddress {
|
||||
if (addr[0] == 'filter') return ['header', addr[1]];
|
||||
return addr;
|
||||
|
||||
Reference in New Issue
Block a user