diff --git a/packages/web/src/datagrid/ChangeSetGrider.ts b/packages/web/src/datagrid/ChangeSetGrider.ts index 22116d2e6..84c1508c0 100644 --- a/packages/web/src/datagrid/ChangeSetGrider.ts +++ b/packages/web/src/datagrid/ChangeSetGrider.ts @@ -1,16 +1,20 @@ import { ChangeSet, + changeSetContainsChanges, changeSetInsertNewRow, + createChangeSet, deleteChangeSetRows, findExistingChangeSetItem, getChangeSetInsertedRows, GridDisplay, + revertChangeSetRowChanges, setChangeSetValue, } from '@dbgate/datalib'; import Grider, { GriderRowStatus } from './Grider'; export default class ChangeSetGrider extends Grider { public insertedRows: any[]; + public changeSet: ChangeSet; public setChangeSet: Function; private rowCacheIndexes: Set; private rowDataCache; @@ -18,14 +22,10 @@ export default class ChangeSetGrider extends Grider { private rowDefinitionsCache; private batchChangeSet: ChangeSet; - constructor( - public sourceRows: any[], - public changeSet: ChangeSet, - public dispatchChangeSet, - public display: GridDisplay - ) { + constructor(public sourceRows: any[], public changeSetState, public dispatchChangeSet, public display: GridDisplay) { super(); - this.insertedRows = getChangeSetInsertedRows(changeSet, display.baseTable); + this.changeSet = changeSetState && changeSetState.value; + this.insertedRows = getChangeSetInsertedRows(this.changeSet, display.baseTable); this.setChangeSet = (value) => dispatchChangeSet({ type: 'set', value }); this.rowCacheIndexes = new Set(); this.rowDataCache = {}; @@ -112,10 +112,36 @@ export default class ChangeSetGrider extends Grider { this.batchChangeSet = null; } - static factory({ sourceRows, changeSet, dispatchChangeSet, display }): ChangeSetGrider { - return new ChangeSetGrider(sourceRows, changeSet, dispatchChangeSet, display); + revertRowChanges(index: number) { + this.requireRowCache(index); + this.applyModification((chs) => revertChangeSetRowChanges(chs, this.rowDefinitionsCache[index])); } - static factoryDeps({ sourceRows, changeSet, dispatchChangeSet, display }) { - return [sourceRows, changeSet, dispatchChangeSet, display]; + revertAllChanges() { + this.applyModification((chs) => createChangeSet()); + } + undo() { + this.dispatchChangeSet({ type: 'undo' }); + } + redo() { + this.dispatchChangeSet({ type: 'redo' }); + } + get canUndo() { + return this.changeSetState.canUndo; + } + get canRedo() { + return this.changeSetState.canRedo; + } + get containsChanges() { + return changeSetContainsChanges(this.changeSet); + } + get disableLoadNextPage() { + return this.insertedRows.length > 0; + } + + static factory({ sourceRows, changeSetState, dispatchChangeSet, display }): ChangeSetGrider { + return new ChangeSetGrider(sourceRows, changeSetState, dispatchChangeSet, display); + } + static factoryDeps({ sourceRows, changeSetState, dispatchChangeSet, display }) { + return [sourceRows, changeSetState ? changeSetState.value : null, dispatchChangeSet, display]; } } diff --git a/packages/web/src/datagrid/DataGridCore.js b/packages/web/src/datagrid/DataGridCore.js index b7f8cd752..98cb48a3f 100644 --- a/packages/web/src/datagrid/DataGridCore.js +++ b/packages/web/src/datagrid/DataGridCore.js @@ -132,8 +132,8 @@ export default function DataGridCore(props) { display, conid, database, - changeSetState, - dispatchChangeSet, + // changeSetState, + // dispatchChangeSet, tabVisible, loadNextData, errorMessage, @@ -203,8 +203,8 @@ export default function DataGridCore(props) { const [containerRef, { height: containerHeight, width: containerWidth }] = useDimensions(); // const [tableRef, { height: tableHeight, width: tableWidth }] = useDimensions(); - const changeSet = changeSetState && changeSetState.value; - const setChangeSet = React.useCallback((value) => dispatchChangeSet({ type: 'set', value }), [dispatchChangeSet]); + // const changeSet = changeSetState && changeSetState.value; + // const setChangeSet = React.useCallback((value) => dispatchChangeSet({ type: 'set', value }), [dispatchChangeSet]); const [inplaceEditorState, dispatchInsplaceEditor] = React.useReducer((state, action) => { switch (action.type) { @@ -446,7 +446,8 @@ export default function DataGridCore(props) { copyToClipboard(); } - function setCellValue(chs, cell, value) { + function setCellValue(cell, value) { + grider.setCellValue(cell[0], realColumnUniqueNames[cell[1]], value); // return setChangeSetValue( // chs, // display.getChangeSetField( @@ -518,6 +519,11 @@ export default function DataGridCore(props) { } function setNull() { + grider.beginUpdate(); + selectedCells.filter(isRegularCell).forEach((cell) => { + setCellValue(cell, null); + }); + grider.endUpdate(); // let chs = changeSet; // selectedCells.filter(isRegularCell).forEach((cell) => { // chs = setCellValue(chs, cell, null); @@ -588,17 +594,11 @@ export default function DataGridCore(props) { const currentRowNumber = currentCell[0]; if (_.isNumber(currentRowNumber)) { const rowIndexes = _.uniq((autofillSelectedCells || []).map((x) => x[0])).filter((x) => x != currentRowNumber); - // @ts-ignore const colNames = selectedCells.map((cell) => realColumnUniqueNames[cell[1]]); const changeObject = _.pick(grider.getRowData(currentRowNumber), colNames); - setChangeSet( - batchUpdateChangeSet( - changeSet, - getRowDefinitions(rowIndexes), - // @ts-ignore - rowIndexes.map(() => changeObject) - ) - ); + grider.beginUpdate(); + for (const index of rowIndexes) grider.updateRow(index, changeObject); + grider.endUpdate(); } setAutofillDragStartCell(null); @@ -607,36 +607,41 @@ export default function DataGridCore(props) { } } - function getRowDefinitions(rowIndexes) { - const res = []; - // if (!loadedAndInsertedRows) return res; - // for (const index of rowIndexes) { - // if (loadedAndInsertedRows[index] && _.isNumber(index)) { - // const insertedRowIndex = index >= loadedRows.length ? index - loadedRows.length : null; - // res.push(display.getChangeSetRow(loadedAndInsertedRows[index], insertedRowIndex)); - // } - // } - return res; - } + // function getRowDefinitions(rowIndexes) { + // const res = []; + // // if (!loadedAndInsertedRows) return res; + // // for (const index of rowIndexes) { + // // if (loadedAndInsertedRows[index] && _.isNumber(index)) { + // // const insertedRowIndex = index >= loadedRows.length ? index - loadedRows.length : null; + // // res.push(display.getChangeSetRow(loadedAndInsertedRows[index], insertedRowIndex)); + // // } + // // } + // return res; + // } function getSelectedRowIndexes() { return _.uniq((selectedCells || []).map((x) => x[0])); } - function getSelectedRowDefinitions() { - return getRowDefinitions(getSelectedRowIndexes()); - } + // function getSelectedRowDefinitions() { + // return getRowDefinitions(getSelectedRowIndexes()); + // } function getSelectedRowData() { return _.compact(getSelectedRowIndexes().map((index) => grider.getRowData(index))); } function revertRowChanges() { - const updatedChangeSet = getSelectedRowDefinitions().reduce( - (chs, row) => revertChangeSetRowChanges(chs, row), - changeSet - ); - setChangeSet(updatedChangeSet); + grider.beginUpdate(); + for (const index of getSelectedRowIndexes()) { + if (_.isNumber(index)) grider.revertRowChanges(index); + } + grider.endUpdate(); + // const updatedChangeSet = getSelectedRowDefinitions().reduce( + // (chs, row) => revertChangeSetRowChanges(chs, row), + // changeSet + // ); + // setChangeSet(updatedChangeSet); } function filterSelectedValue() { @@ -655,7 +660,8 @@ export default function DataGridCore(props) { } function revertAllChanges() { - setChangeSet(createChangeSet()); + grider.revertAllChanges(); + // setChangeSet(createChangeSet()); } function deleteSelectedRows() { @@ -690,10 +696,10 @@ export default function DataGridCore(props) { } function undo() { - dispatchChangeSet({ type: 'undo' }); + grider.undo(); } function redo() { - dispatchChangeSet({ type: 'redo' }); + grider.redo(); } function handleSave() { @@ -709,7 +715,6 @@ export default function DataGridCore(props) { // confirmSqlModalState.open(); } - const insertNewRow = () => { if (display.baseTable) { const rowIndex = grider.insertRow(); @@ -1101,9 +1106,10 @@ export default function DataGridCore(props) { display.reload()} save={handleSave} - changeSetState={changeSetState} - dispatchChangeSet={dispatchChangeSet} - revert={revertAllChanges} + grider={grider} + // changeSetState={changeSetState} + // dispatchChangeSet={dispatchChangeSet} + // revert={revertAllChanges} />, props.toolbarPortalRef.current )} diff --git a/packages/web/src/datagrid/DataGridToolbar.js b/packages/web/src/datagrid/DataGridToolbar.js index edfc9eb3f..6fef8c3ae 100644 --- a/packages/web/src/datagrid/DataGridToolbar.js +++ b/packages/web/src/datagrid/DataGridToolbar.js @@ -1,23 +1,22 @@ import React from 'react'; import ToolbarButton from '../widgets/ToolbarButton'; -import { changeSetContainsChanges } from '@dbgate/datalib'; -export default function DataGridToolbar({ reload, changeSetState, dispatchChangeSet, save, revert }) { +export default function DataGridToolbar({ reload, grider, save }) { return ( <> Refresh - dispatchChangeSet({ type: 'undo' })} icon="fas fa-undo"> + grider.undo()} icon="fas fa-undo"> Undo - dispatchChangeSet({ type: 'redo' })} icon="fas fa-redo"> + grider.redo()} icon="fas fa-redo"> Redo - + Save - + grider.revertAllChanges()} icon="fas fa-times"> Revert diff --git a/packages/web/src/datagrid/Grider.ts b/packages/web/src/datagrid/Grider.ts index b5e818a18..7ef8f6f22 100644 --- a/packages/web/src/datagrid/Grider.ts +++ b/packages/web/src/datagrid/Grider.ts @@ -25,4 +25,25 @@ export default abstract class Grider { insertRow(): number { return null; } + revertRowChanges(index: number) {} + revertAllChanges() {} + undo() {} + redo() {} + get canUndo() { + return false; + } + get canRedo() { + return false; + } + get containsChanges() { + return false; + } + get disableLoadNextPage() { + return false; + } + updateRow(index, changeObject) { + for (const key of Object.keys(changeObject)) { + this.setCellValue(index, key, changeObject[key]); + } + } } diff --git a/packages/web/src/datagrid/LoadingDataGridCore.js b/packages/web/src/datagrid/LoadingDataGridCore.js index c744fc3aa..52ad56aef 100644 --- a/packages/web/src/datagrid/LoadingDataGridCore.js +++ b/packages/web/src/datagrid/LoadingDataGridCore.js @@ -109,14 +109,14 @@ export default function LoadingDataGridCore(props) { const loadedTimeRef = React.useRef(0); - const changeSet = changeSetState && changeSetState.value; - const setChangeSet = React.useCallback((value) => dispatchChangeSet({ type: 'set', value }), [dispatchChangeSet]); - const setOpenedTabs = useSetOpenedTabs(); - const socket = useSocket(); + // const changeSet = changeSetState && changeSetState.value; + // const setChangeSet = React.useCallback((value) => dispatchChangeSet({ type: 'set', value }), [dispatchChangeSet]); + // const setOpenedTabs = useSetOpenedTabs(); + // const socket = useSocket(); - const changeSetRef = React.useRef(changeSet); + // const changeSetRef = React.useRef(changeSet); - changeSetRef.current = changeSet; + // changeSetRef.current = changeSet; const handleLoadRowCount = async () => { const rowCount = await loadRowCount(props); @@ -196,11 +196,14 @@ export default function LoadingDataGridCore(props) { })); }, [loadNextDataToken]); - const insertedRows = getChangeSetInsertedRows(changeSet, display.baseTable); - const rowCountNewIncluded = loadedRows.length + insertedRows.length; + // const insertedRows = getChangeSetInsertedRows(changeSet, display.baseTable); + // const rowCountNewIncluded = loadedRows.length + insertedRows.length; + + const griderProps = { ...props, sourceRows: loadedRows }; + const grider = React.useMemo(() => griderFactory(griderProps), griderFactoryDeps(griderProps)); const handleLoadNextData = () => { - if (!isLoadedAll && !errorMessage && insertedRows.length == 0) { + if (!isLoadedAll && !errorMessage && !grider.disableLoadNextPage) { if (dataPageAvailable(props)) { // If not, callbacks to load missing metadata are dispatched loadNextData(); @@ -208,9 +211,6 @@ export default function LoadingDataGridCore(props) { } }; - const griderProps = { ...props, sourceRows: loadedRows }; - const grider = React.useMemo(() => griderFactory(griderProps), griderFactoryDeps(griderProps)); - return (