From ce1e58dbdcb2d368f482f514b5526a900ed6b18f Mon Sep 17 00:00:00 2001 From: Jan Prochazka Date: Sun, 22 Mar 2020 18:48:48 +0100 Subject: [PATCH] inplace editing --- packages/datalib/src/ChangeSet.ts | 13 ++++--- packages/datalib/src/GridDisplay.ts | 11 +++++- packages/web/src/datagrid/DataGridCore.js | 36 +++++++++++++++---- packages/web/src/datagrid/DataGridRow.js | 42 ++++++++++++++-------- packages/web/src/datagrid/InplaceEditor.js | 25 ++++++++++--- 5 files changed, 96 insertions(+), 31 deletions(-) diff --git a/packages/datalib/src/ChangeSet.ts b/packages/datalib/src/ChangeSet.ts index 7eacb9eab..fd37c1539 100644 --- a/packages/datalib/src/ChangeSet.ts +++ b/packages/datalib/src/ChangeSet.ts @@ -22,18 +22,21 @@ export function createChangeSet(): ChangeSet { }; } -export interface ChangeSetFieldDefinition { +export interface ChangeSetRowDefinition { pureName: string; schemaName: string; - uniqueName: string; - columnName: string; insertedRowIndex?: number; condition?: { [column: string]: string }; } -function findExistingChangeSetItem( +export interface ChangeSetFieldDefinition extends ChangeSetRowDefinition { + uniqueName: string; + columnName: string; +} + +export function findExistingChangeSetItem( changeSet: ChangeSet, - definition: ChangeSetFieldDefinition + definition: ChangeSetRowDefinition ): [keyof ChangeSet, ChangeSetItem] { if (definition.insertedRowIndex != null) { return [ diff --git a/packages/datalib/src/GridDisplay.ts b/packages/datalib/src/GridDisplay.ts index ae30a973e..45a165830 100644 --- a/packages/datalib/src/GridDisplay.ts +++ b/packages/datalib/src/GridDisplay.ts @@ -4,7 +4,7 @@ import { ForeignKeyInfo, TableInfo, ColumnInfo, DbType } from '@dbgate/types'; import { parseFilter, getFilterType } from '@dbgate/filterparser'; import { filterName } from './filterName'; import { Select, Expression } from '@dbgate/sqltree'; -import { ChangeSetFieldDefinition } from './ChangeSet'; +import { ChangeSetFieldDefinition, ChangeSetRowDefinition } from './ChangeSet'; export interface DisplayColumn { schemaName: string; @@ -372,4 +372,13 @@ export abstract class GridDisplay { condition: this.getChangeSetCondition(row), }; } + + getChangeSetRow(row): ChangeSetRowDefinition { + if (!this.baseTable) return null; + return { + pureName: this.baseTable.pureName, + schemaName: this.baseTable.schemaName, + condition: this.getChangeSetCondition(row), + }; + } } diff --git a/packages/web/src/datagrid/DataGridCore.js b/packages/web/src/datagrid/DataGridCore.js index d8b225808..4fb6ce0f7 100644 --- a/packages/web/src/datagrid/DataGridCore.js +++ b/packages/web/src/datagrid/DataGridCore.js @@ -100,6 +100,7 @@ export default function DataGridCore(props) { const [shiftDragStartCell, setShiftDragStartCell] = React.useState(nullCell); const [inplaceEditorCell, setInplaceEditorCell] = React.useState(nullCell); + const [inplaceEditorInitText, setInplaceEditorInitText] = React.useState(''); const loadNextData = async () => { if (isLoading) return; @@ -291,7 +292,7 @@ export default function DataGridCore(props) { if (isRegularCell(cell) && !_.isEqual(cell, inplaceEditorCell) && _.isEqual(cell, currentCell)) { setInplaceEditorCell(cell); } else if (!_.isEqual(cell, inplaceEditorCell)) { - setInplaceEditorCell(null); + handleCloseInplaceEditor(); } } @@ -334,14 +335,28 @@ export default function DataGridCore(props) { } function handleGridKeyDown(event) { - handleCursorMove(event); + if ( + !event.ctrlKey && + !event.altKey && + ((event.keyCode >= keycodes.a && event.keyCode <= keycodes.z) || + (event.keyCode >= keycodes.n0 && event.keyCode <= keycodes.n9) || + event.keyCode == keycodes.dash) + ) { + setInplaceEditorInitText(event.nativeEvent.key); + setInplaceEditorCell(currentCell); + // console.log('event', event.nativeEvent); + } - if (event.shiftKey) { - if (!isRegularCell(shiftDragStartCell)) { - setShiftDragStartCell(currentCell); + const moved = handleCursorMove(event); + + if (moved) { + if (event.shiftKey) { + if (!isRegularCell(shiftDragStartCell)) { + setShiftDragStartCell(currentCell); + } + } else { + setShiftDragStartCell(nullCell); } - } else { - setShiftDragStartCell(nullCell); } const newCell = handleCursorMove(event); @@ -480,6 +495,11 @@ export default function DataGridCore(props) { return false; } + function handleCloseInplaceEditor() { + setInplaceEditorCell(null); + setInplaceEditorInitText(null); + } + // console.log('visibleRowCountUpperBound', visibleRowCountUpperBound); // console.log('gridScrollAreaHeight', gridScrollAreaHeight); // console.log('containerHeight', containerHeight); @@ -599,6 +619,8 @@ export default function DataGridCore(props) { rowHeight={rowHeight} visibleRealColumns={visibleRealColumns} inplaceEditorCell={inplaceEditorCell} + inplaceEditorInitText={inplaceEditorInitText} + onCloseInplaceEditor={handleCloseInplaceEditor} cellIsSelected={cellIsSelected} changeSet={changeSet} setChangeSet={setChangeSet} diff --git a/packages/web/src/datagrid/DataGridRow.js b/packages/web/src/datagrid/DataGridRow.js index 57763f5ca..8582e28b2 100644 --- a/packages/web/src/datagrid/DataGridRow.js +++ b/packages/web/src/datagrid/DataGridRow.js @@ -1,3 +1,4 @@ +// @ts-nocheck import moment from 'moment'; import _ from 'lodash'; import React from 'react'; @@ -11,15 +12,7 @@ import axios from '../utility/axios'; import ColumnLabel from './ColumnLabel'; import DataFilterControl from './DataFilterControl'; import { getFilterType } from '@dbgate/filterparser'; -import { - convertCellAddress, - cellFromEvent, - getCellRange, - topLeftCell, - isRegularCell, - nullCell, - emptyCellArray, -} from './selection'; +import { findExistingChangeSetItem } from '@dbgate/datalib'; import keycodes from '../utility/keycodes'; import InplaceEditor from './InplaceEditor'; @@ -31,13 +24,23 @@ const TableBodyCell = styled.td` white-space: nowrap; overflow: hidden; ${props => - // @ts-ignore props.isSelected && ` background: initial; background-color: deepskyblue; color: white;`} -`; + ${props => + props.isModifiedRow && + !props.isSelected && + !props.isModifiedCell && + ` + background-color: #FFFFDB;`} + ${props => + !props.isSelected && + props.isModifiedCell && + ` + background-color: bisque;`} + `; const HintSpan = styled.span` color: gray; margin-left: 5px; @@ -77,12 +80,17 @@ export default function DataGridRow({ rowIndex, visibleRealColumns, inplaceEditorCell, + inplaceEditorInitText, + onCloseInplaceEditor, cellIsSelected, row, display, changeSet, setChangeSet, }) { + const rowDefinition = display.getChangeSetRow(row); + const [_fld, matchedChangeSetItem] = findExistingChangeSetItem(changeSet, rowDefinition); + const rowUpdated = matchedChangeSetItem ? { ...row, ...matchedChangeSetItem.fields } : row; return ( @@ -100,19 +108,25 @@ export default function DataGridRow({ data-col={col.colIndex} // @ts-ignore isSelected={cellIsSelected(rowIndex, col.colIndex)} + isModifiedRow={!!matchedChangeSetItem} + isModifiedCell={matchedChangeSetItem && col.uniqueName in matchedChangeSetItem.fields} > {inplaceEditorCell && rowIndex == inplaceEditorCell[0] && col.colIndex == inplaceEditorCell[1] ? ( ) : ( <> - - {col.hintColumnName && {row[col.hintColumnName]}} + + {(!matchedChangeSetItem || !(col.uniqueName in matchedChangeSetItem.fields)) && col.hintColumnName && ( + {row[col.hintColumnName]} + )} )} diff --git a/packages/web/src/datagrid/InplaceEditor.js b/packages/web/src/datagrid/InplaceEditor.js index 12da1cb0b..f22311dbb 100644 --- a/packages/web/src/datagrid/InplaceEditor.js +++ b/packages/web/src/datagrid/InplaceEditor.js @@ -1,3 +1,5 @@ +// @ts-nocheck + import _ from 'lodash'; import React from 'react'; import styled from 'styled-components'; @@ -12,23 +14,38 @@ const StyledInput = styled.input` padding: 0px; `; -export default function InplaceEditor({ widthPx, value, definition, changeSet, setChangeSet }) { +export default function InplaceEditor({ widthPx, value, definition, changeSet, setChangeSet, onClose, selectAll }) { const editorRef = React.useRef(); + const isChangedRef = React.createRef(); React.useEffect(() => { const editor = editorRef.current; editor.value = value; editor.focus(); - editor.select(); + if (selectAll) { + editor.select(); + } }, []); function handleBlur() { - const editor = editorRef.current; - setChangeSet(setChangeSetValue(changeSet, definition, editor.value)); + if (isChangedRef.current) { + const editor = editorRef.current; + setChangeSet(setChangeSetValue(changeSet, definition, editor.value)); + } + } + function handleKeyDown(event) { + switch (event.keyCode) { + case keycodes.escape: + isChangedRef.current = false; + onClose(); + break; + } } return ( (isChangedRef.current = true)} + onKeyDown={handleKeyDown} style={{ width: widthPx, minWidth: widthPx,