diff --git a/packages/datalib/src/ChangeSet.ts b/packages/datalib/src/ChangeSet.ts index eeb534fa..83de5bb6 100644 --- a/packages/datalib/src/ChangeSet.ts +++ b/packages/datalib/src/ChangeSet.ts @@ -1,5 +1,6 @@ import _ from 'lodash'; import { Command, Insert, Update, Delete, UpdateField, Condition } from '@dbgate/sqltree'; +import { NamedObjectInfo } from '@dbgate/types'; export interface ChangeSetItem { pureName: string; @@ -189,3 +190,31 @@ export function revertChangeSetRowChanges(changeSet: ChangeSet, definition: Chan }; return changeSet; } + +export function getChangeSetInsertedRows(changeSet: ChangeSet, name?: NamedObjectInfo) { + if (!name) return []; + if (!changeSet) return []; + const rows = changeSet.inserts.filter(x => x.pureName == name.pureName && x.schemaName == name.schemaName); + const maxIndex = _.maxBy(rows, x => x.insertedRowIndex)?.insertedRowIndex; + if (maxIndex == null) return []; + const res = Array(maxIndex + 1).fill({}); + for (const row of rows) { + res[row.insertedRowIndex] = row.fields; + } + return res; +} + +export function changeSetInsertNewRow(changeSet: ChangeSet, name?: NamedObjectInfo): ChangeSet { + const insertedRows = getChangeSetInsertedRows(changeSet, name); + return { + ...changeSet, + inserts: [ + ...changeSet.inserts, + { + ...name, + insertedRowIndex: insertedRows.length, + fields: {}, + }, + ], + }; +} diff --git a/packages/datalib/src/GridDisplay.ts b/packages/datalib/src/GridDisplay.ts index e29ed479..d8621d40 100644 --- a/packages/datalib/src/GridDisplay.ts +++ b/packages/datalib/src/GridDisplay.ts @@ -365,7 +365,7 @@ export abstract class GridDisplay { return _.pick(row, this.changeSetKeyFields); } - getChangeSetField(row, uniqueName): ChangeSetFieldDefinition { + getChangeSetField(row, uniqueName, insertedRowIndex): ChangeSetFieldDefinition { const col = this.columns.find(x => x.uniqueName == uniqueName); if (!col) return null; if (!this.baseTable) return null; @@ -375,7 +375,8 @@ export abstract class GridDisplay { schemaName: col.schemaName, uniqueName: uniqueName, columnName: col.columnName, - condition: this.getChangeSetCondition(row), + insertedRowIndex, + condition: insertedRowIndex == null ? this.getChangeSetCondition(row) : null, }; } diff --git a/packages/sqltree/src/types.ts b/packages/sqltree/src/types.ts index 67d7ad10..a088ac11 100644 --- a/packages/sqltree/src/types.ts +++ b/packages/sqltree/src/types.ts @@ -36,10 +36,7 @@ export interface Delete { export interface Insert { commandType: 'insert'; fields: UpdateField[]; - targetTable: { - schemaName: string; - pureName: string; - }; + targetTable: NamedObjectInfo; } export type Command = Select | Update | Delete | Insert; diff --git a/packages/web/src/datagrid/DataGridCore.js b/packages/web/src/datagrid/DataGridCore.js index 7210b16a..b76f8b68 100644 --- a/packages/web/src/datagrid/DataGridCore.js +++ b/packages/web/src/datagrid/DataGridCore.js @@ -26,7 +26,13 @@ import DataGridRow from './DataGridRow'; import { countColumnSizes, countVisibleRealColumns } from './gridutil'; import useModalState from '../modals/useModalState'; import ConfirmSqlModal from '../modals/ConfirmSqlModal'; -import { changeSetToSql, createChangeSet, revertChangeSetRowChanges } from '@dbgate/datalib'; +import { + changeSetToSql, + createChangeSet, + revertChangeSetRowChanges, + getChangeSetInsertedRows, + changeSetInsertNewRow, +} from '@dbgate/datalib'; import { scriptToSql } from '@dbgate/sqltree'; import { sleep } from '../utility/common'; @@ -232,7 +238,11 @@ export default function DataGridCore(props) { }; React.useEffect(() => { - if (!isLoadedAll && firstVisibleRowScrollIndex + visibleRowCountUpperBound >= loadedRows.length) { + if ( + !isLoadedAll && + firstVisibleRowScrollIndex + visibleRowCountUpperBound >= loadedRows.length && + insertedRows.length == 0 + ) { const sql = display.getPageQuery(0, 1); // try to get SQL, if success, load page. If not, callbacks to load missing metadata are dispatched if (sql) loadNextData(); @@ -284,7 +294,8 @@ export default function DataGridCore(props) { ); if (!loadedRows || !columns) return null; - const rowCountNewIncluded = loadedRows.length; + const insertedRows = getChangeSetInsertedRows(changeSet, display.baseTable); + const rowCountNewIncluded = loadedRows.length + insertedRows.length; const handleRowScroll = value => { setFirstVisibleRowScrollIndex(value); @@ -401,6 +412,18 @@ export default function DataGridCore(props) { // this.saveAndFocus(); } + if (event.keyCode == keycodes.insert) { + event.preventDefault(); + if (display.baseTable) { + setChangeSet(changeSetInsertNewRow(changeSet, display.baseTable)); + const cell = [rowCountNewIncluded, (currentCell && currentCell[1]) || 0]; + // @ts-ignore + setCurrentCell(cell); + scrollIntoView(cell); + } + // this.saveAndFocus(); + } + if (inplaceEditorState.cell) return; if ( @@ -574,6 +597,8 @@ export default function DataGridCore(props) { // columnSizes.getVisibleScrollSizeSum() // ); + const loadedAndInsertedRows = [...loadedRows, ...insertedRows]; + return ( - {loadedRows + {loadedAndInsertedRows .slice(firstVisibleRowScrollIndex, firstVisibleRowScrollIndex + visibleRowCountUpperBound) .map((row, index) => ( = loadedRows.length + ? firstVisibleRowScrollIndex + index - loadedRows.length + : null + } changeSet={changeSet} setChangeSet={setChangeSet} display={display} diff --git a/packages/web/src/datagrid/DataGridRow.js b/packages/web/src/datagrid/DataGridRow.js index 2cf0a68b..1b8c5eea 100644 --- a/packages/web/src/datagrid/DataGridRow.js +++ b/packages/web/src/datagrid/DataGridRow.js @@ -31,15 +31,24 @@ const TableBodyCell = styled.td` color: white;`} ${props => props.isModifiedRow && + !props.isInsertedRow && !props.isSelected && !props.isModifiedCell && ` background-color: #FFFFDB;`} ${props => !props.isSelected && + !props.isInsertedRow && props.isModifiedCell && ` background-color: bisque;`} + + ${props => + !props.isSelected && + props.isInsertedRow && + ` + background-color: #DBFFDB;`} + `; const HintSpan = styled.span` color: gray; @@ -86,6 +95,7 @@ export default function DataGridRow({ display, changeSet, setChangeSet, + insertedRowIndex, }) { // console.log('RENDER ROW', rowIndex); const rowDefinition = display.getChangeSetRow(row); @@ -110,8 +120,11 @@ export default function DataGridRow({ isSelected={cellIsSelected(rowIndex, col.colIndex)} isModifiedRow={!!matchedChangeSetItem} isModifiedCell={matchedChangeSetItem && col.uniqueName in matchedChangeSetItem.fields} + isInsertedRow={insertedRowIndex != null} > - {inplaceEditorState.cell && rowIndex == inplaceEditorState.cell[0] && col.colIndex == inplaceEditorState.cell[1] ? ( + {inplaceEditorState.cell && + rowIndex == inplaceEditorState.cell[0] && + col.colIndex == inplaceEditorState.cell[1] ? ( + insertedRowIndex={insertedRowIndex} + definition={display.getChangeSetField(row, col.uniqueName, insertedRowIndex)} + /> ) : ( <> diff --git a/packages/web/src/datagrid/InplaceEditor.js b/packages/web/src/datagrid/InplaceEditor.js index 8b687a83..bb91ca4e 100644 --- a/packages/web/src/datagrid/InplaceEditor.js +++ b/packages/web/src/datagrid/InplaceEditor.js @@ -22,6 +22,7 @@ export default function InplaceEditor({ cellValue, inplaceEditorState, dispatchInsplaceEditor, + isInsertedRow, }) { const editorRef = React.useRef(); const isChangedRef = React.useRef(!!inplaceEditorState.text);