grider refactor WIP

This commit is contained in:
Jan Prochazka
2020-10-24 21:05:24 +02:00
parent 00453ae379
commit 45d172d0b1
6 changed files with 123 additions and 71 deletions

View File

@@ -1,16 +1,20 @@
import { import {
ChangeSet, ChangeSet,
changeSetContainsChanges,
changeSetInsertNewRow, changeSetInsertNewRow,
createChangeSet,
deleteChangeSetRows, deleteChangeSetRows,
findExistingChangeSetItem, findExistingChangeSetItem,
getChangeSetInsertedRows, getChangeSetInsertedRows,
GridDisplay, GridDisplay,
revertChangeSetRowChanges,
setChangeSetValue, setChangeSetValue,
} from '@dbgate/datalib'; } from '@dbgate/datalib';
import Grider, { GriderRowStatus } from './Grider'; import Grider, { GriderRowStatus } from './Grider';
export default class ChangeSetGrider extends Grider { export default class ChangeSetGrider extends Grider {
public insertedRows: any[]; public insertedRows: any[];
public changeSet: ChangeSet;
public setChangeSet: Function; public setChangeSet: Function;
private rowCacheIndexes: Set<number>; private rowCacheIndexes: Set<number>;
private rowDataCache; private rowDataCache;
@@ -18,14 +22,10 @@ export default class ChangeSetGrider extends Grider {
private rowDefinitionsCache; private rowDefinitionsCache;
private batchChangeSet: ChangeSet; private batchChangeSet: ChangeSet;
constructor( constructor(public sourceRows: any[], public changeSetState, public dispatchChangeSet, public display: GridDisplay) {
public sourceRows: any[],
public changeSet: ChangeSet,
public dispatchChangeSet,
public display: GridDisplay
) {
super(); 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.setChangeSet = (value) => dispatchChangeSet({ type: 'set', value });
this.rowCacheIndexes = new Set(); this.rowCacheIndexes = new Set();
this.rowDataCache = {}; this.rowDataCache = {};
@@ -112,10 +112,36 @@ export default class ChangeSetGrider extends Grider {
this.batchChangeSet = null; this.batchChangeSet = null;
} }
static factory({ sourceRows, changeSet, dispatchChangeSet, display }): ChangeSetGrider { revertRowChanges(index: number) {
return new ChangeSetGrider(sourceRows, changeSet, dispatchChangeSet, display); this.requireRowCache(index);
this.applyModification((chs) => revertChangeSetRowChanges(chs, this.rowDefinitionsCache[index]));
} }
static factoryDeps({ sourceRows, changeSet, dispatchChangeSet, display }) { revertAllChanges() {
return [sourceRows, changeSet, dispatchChangeSet, display]; 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];
} }
} }

View File

@@ -132,8 +132,8 @@ export default function DataGridCore(props) {
display, display,
conid, conid,
database, database,
changeSetState, // changeSetState,
dispatchChangeSet, // dispatchChangeSet,
tabVisible, tabVisible,
loadNextData, loadNextData,
errorMessage, errorMessage,
@@ -203,8 +203,8 @@ export default function DataGridCore(props) {
const [containerRef, { height: containerHeight, width: containerWidth }] = useDimensions(); const [containerRef, { height: containerHeight, width: containerWidth }] = useDimensions();
// const [tableRef, { height: tableHeight, width: tableWidth }] = useDimensions(); // const [tableRef, { height: tableHeight, width: tableWidth }] = useDimensions();
const changeSet = changeSetState && changeSetState.value; // const changeSet = changeSetState && changeSetState.value;
const setChangeSet = React.useCallback((value) => dispatchChangeSet({ type: 'set', value }), [dispatchChangeSet]); // const setChangeSet = React.useCallback((value) => dispatchChangeSet({ type: 'set', value }), [dispatchChangeSet]);
const [inplaceEditorState, dispatchInsplaceEditor] = React.useReducer((state, action) => { const [inplaceEditorState, dispatchInsplaceEditor] = React.useReducer((state, action) => {
switch (action.type) { switch (action.type) {
@@ -446,7 +446,8 @@ export default function DataGridCore(props) {
copyToClipboard(); copyToClipboard();
} }
function setCellValue(chs, cell, value) { function setCellValue(cell, value) {
grider.setCellValue(cell[0], realColumnUniqueNames[cell[1]], value);
// return setChangeSetValue( // return setChangeSetValue(
// chs, // chs,
// display.getChangeSetField( // display.getChangeSetField(
@@ -518,6 +519,11 @@ export default function DataGridCore(props) {
} }
function setNull() { function setNull() {
grider.beginUpdate();
selectedCells.filter(isRegularCell).forEach((cell) => {
setCellValue(cell, null);
});
grider.endUpdate();
// let chs = changeSet; // let chs = changeSet;
// selectedCells.filter(isRegularCell).forEach((cell) => { // selectedCells.filter(isRegularCell).forEach((cell) => {
// chs = setCellValue(chs, cell, null); // chs = setCellValue(chs, cell, null);
@@ -588,17 +594,11 @@ export default function DataGridCore(props) {
const currentRowNumber = currentCell[0]; const currentRowNumber = currentCell[0];
if (_.isNumber(currentRowNumber)) { if (_.isNumber(currentRowNumber)) {
const rowIndexes = _.uniq((autofillSelectedCells || []).map((x) => x[0])).filter((x) => x != currentRowNumber); const rowIndexes = _.uniq((autofillSelectedCells || []).map((x) => x[0])).filter((x) => x != currentRowNumber);
// @ts-ignore
const colNames = selectedCells.map((cell) => realColumnUniqueNames[cell[1]]); const colNames = selectedCells.map((cell) => realColumnUniqueNames[cell[1]]);
const changeObject = _.pick(grider.getRowData(currentRowNumber), colNames); const changeObject = _.pick(grider.getRowData(currentRowNumber), colNames);
setChangeSet( grider.beginUpdate();
batchUpdateChangeSet( for (const index of rowIndexes) grider.updateRow(index, changeObject);
changeSet, grider.endUpdate();
getRowDefinitions(rowIndexes),
// @ts-ignore
rowIndexes.map(() => changeObject)
)
);
} }
setAutofillDragStartCell(null); setAutofillDragStartCell(null);
@@ -607,36 +607,41 @@ export default function DataGridCore(props) {
} }
} }
function getRowDefinitions(rowIndexes) { // function getRowDefinitions(rowIndexes) {
const res = []; // const res = [];
// if (!loadedAndInsertedRows) return res; // // if (!loadedAndInsertedRows) return res;
// for (const index of rowIndexes) { // // for (const index of rowIndexes) {
// if (loadedAndInsertedRows[index] && _.isNumber(index)) { // // if (loadedAndInsertedRows[index] && _.isNumber(index)) {
// const insertedRowIndex = index >= loadedRows.length ? index - loadedRows.length : null; // // const insertedRowIndex = index >= loadedRows.length ? index - loadedRows.length : null;
// res.push(display.getChangeSetRow(loadedAndInsertedRows[index], insertedRowIndex)); // // res.push(display.getChangeSetRow(loadedAndInsertedRows[index], insertedRowIndex));
// // }
// // }
// return res;
// } // }
// }
return res;
}
function getSelectedRowIndexes() { function getSelectedRowIndexes() {
return _.uniq((selectedCells || []).map((x) => x[0])); return _.uniq((selectedCells || []).map((x) => x[0]));
} }
function getSelectedRowDefinitions() { // function getSelectedRowDefinitions() {
return getRowDefinitions(getSelectedRowIndexes()); // return getRowDefinitions(getSelectedRowIndexes());
} // }
function getSelectedRowData() { function getSelectedRowData() {
return _.compact(getSelectedRowIndexes().map((index) => grider.getRowData(index))); return _.compact(getSelectedRowIndexes().map((index) => grider.getRowData(index)));
} }
function revertRowChanges() { function revertRowChanges() {
const updatedChangeSet = getSelectedRowDefinitions().reduce( grider.beginUpdate();
(chs, row) => revertChangeSetRowChanges(chs, row), for (const index of getSelectedRowIndexes()) {
changeSet if (_.isNumber(index)) grider.revertRowChanges(index);
); }
setChangeSet(updatedChangeSet); grider.endUpdate();
// const updatedChangeSet = getSelectedRowDefinitions().reduce(
// (chs, row) => revertChangeSetRowChanges(chs, row),
// changeSet
// );
// setChangeSet(updatedChangeSet);
} }
function filterSelectedValue() { function filterSelectedValue() {
@@ -655,7 +660,8 @@ export default function DataGridCore(props) {
} }
function revertAllChanges() { function revertAllChanges() {
setChangeSet(createChangeSet()); grider.revertAllChanges();
// setChangeSet(createChangeSet());
} }
function deleteSelectedRows() { function deleteSelectedRows() {
@@ -690,10 +696,10 @@ export default function DataGridCore(props) {
} }
function undo() { function undo() {
dispatchChangeSet({ type: 'undo' }); grider.undo();
} }
function redo() { function redo() {
dispatchChangeSet({ type: 'redo' }); grider.redo();
} }
function handleSave() { function handleSave() {
@@ -709,7 +715,6 @@ export default function DataGridCore(props) {
// confirmSqlModalState.open(); // confirmSqlModalState.open();
} }
const insertNewRow = () => { const insertNewRow = () => {
if (display.baseTable) { if (display.baseTable) {
const rowIndex = grider.insertRow(); const rowIndex = grider.insertRow();
@@ -1101,9 +1106,10 @@ export default function DataGridCore(props) {
<DataGridToolbar <DataGridToolbar
reload={() => display.reload()} reload={() => display.reload()}
save={handleSave} save={handleSave}
changeSetState={changeSetState} grider={grider}
dispatchChangeSet={dispatchChangeSet} // changeSetState={changeSetState}
revert={revertAllChanges} // dispatchChangeSet={dispatchChangeSet}
// revert={revertAllChanges}
/>, />,
props.toolbarPortalRef.current props.toolbarPortalRef.current
)} )}

View File

@@ -1,23 +1,22 @@
import React from 'react'; import React from 'react';
import ToolbarButton from '../widgets/ToolbarButton'; 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 ( return (
<> <>
<ToolbarButton onClick={reload} icon="fas fa-sync"> <ToolbarButton onClick={reload} icon="fas fa-sync">
Refresh Refresh
</ToolbarButton> </ToolbarButton>
<ToolbarButton disabled={!changeSetState.canUndo} onClick={() => dispatchChangeSet({ type: 'undo' })} icon="fas fa-undo"> <ToolbarButton disabled={!grider.canUndo} onClick={() => grider.undo()} icon="fas fa-undo">
Undo Undo
</ToolbarButton> </ToolbarButton>
<ToolbarButton disabled={!changeSetState.canRedo} onClick={() => dispatchChangeSet({ type: 'redo' })} icon="fas fa-redo"> <ToolbarButton disabled={!grider.canRedo} onClick={() => grider.redo()} icon="fas fa-redo">
Redo Redo
</ToolbarButton> </ToolbarButton>
<ToolbarButton disabled={!changeSetContainsChanges(changeSetState.value)} onClick={save} icon="fas fa-save"> <ToolbarButton disabled={!grider.containsChanges} onClick={save} icon="fas fa-save">
Save Save
</ToolbarButton> </ToolbarButton>
<ToolbarButton disabled={!changeSetContainsChanges(changeSetState.value)} onClick={revert} icon="fas fa-times"> <ToolbarButton disabled={!grider.containsChanges} onClick={() => grider.revertAllChanges()} icon="fas fa-times">
Revert Revert
</ToolbarButton> </ToolbarButton>
</> </>

View File

@@ -25,4 +25,25 @@ export default abstract class Grider {
insertRow(): number { insertRow(): number {
return null; 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]);
}
}
} }

View File

@@ -109,14 +109,14 @@ export default function LoadingDataGridCore(props) {
const loadedTimeRef = React.useRef(0); const loadedTimeRef = React.useRef(0);
const changeSet = changeSetState && changeSetState.value; // const changeSet = changeSetState && changeSetState.value;
const setChangeSet = React.useCallback((value) => dispatchChangeSet({ type: 'set', value }), [dispatchChangeSet]); // const setChangeSet = React.useCallback((value) => dispatchChangeSet({ type: 'set', value }), [dispatchChangeSet]);
const setOpenedTabs = useSetOpenedTabs(); // const setOpenedTabs = useSetOpenedTabs();
const socket = useSocket(); // const socket = useSocket();
const changeSetRef = React.useRef(changeSet); // const changeSetRef = React.useRef(changeSet);
changeSetRef.current = changeSet; // changeSetRef.current = changeSet;
const handleLoadRowCount = async () => { const handleLoadRowCount = async () => {
const rowCount = await loadRowCount(props); const rowCount = await loadRowCount(props);
@@ -196,11 +196,14 @@ export default function LoadingDataGridCore(props) {
})); }));
}, [loadNextDataToken]); }, [loadNextDataToken]);
const insertedRows = getChangeSetInsertedRows(changeSet, display.baseTable); // const insertedRows = getChangeSetInsertedRows(changeSet, display.baseTable);
const rowCountNewIncluded = loadedRows.length + insertedRows.length; // const rowCountNewIncluded = loadedRows.length + insertedRows.length;
const griderProps = { ...props, sourceRows: loadedRows };
const grider = React.useMemo(() => griderFactory(griderProps), griderFactoryDeps(griderProps));
const handleLoadNextData = () => { const handleLoadNextData = () => {
if (!isLoadedAll && !errorMessage && insertedRows.length == 0) { if (!isLoadedAll && !errorMessage && !grider.disableLoadNextPage) {
if (dataPageAvailable(props)) { if (dataPageAvailable(props)) {
// If not, callbacks to load missing metadata are dispatched // If not, callbacks to load missing metadata are dispatched
loadNextData(); loadNextData();
@@ -208,9 +211,6 @@ export default function LoadingDataGridCore(props) {
} }
}; };
const griderProps = { ...props, sourceRows: loadedRows };
const grider = React.useMemo(() => griderFactory(griderProps), griderFactoryDeps(griderProps));
return ( return (
<DataGridCore <DataGridCore
{...props} {...props}
@@ -219,7 +219,7 @@ export default function LoadingDataGridCore(props) {
isLoadedAll={isLoadedAll} isLoadedAll={isLoadedAll}
loadedTime={loadedTime} loadedTime={loadedTime}
exportGrid={exportGrid} exportGrid={exportGrid}
// allRowCount={allRowCount} allRowCount={allRowCount}
openQuery={openQuery} openQuery={openQuery}
isLoading={isLoading} isLoading={isLoading}
// rows={loadedRows} // rows={loadedRows}

View File

@@ -137,7 +137,7 @@ export default function SqlDataGridCore(props) {
loadRowCount={loadRowCount} loadRowCount={loadRowCount}
griderFactory={ChangeSetGrider.factory} griderFactory={ChangeSetGrider.factory}
griderFactoryDeps={ChangeSetGrider.factoryDeps} griderFactoryDeps={ChangeSetGrider.factoryDeps}
changeSet={changeSetState && changeSetState.value} // changeSet={changeSetState && changeSetState.value}
onSave={handleSave} onSave={handleSave}
/> />
<ConfirmSqlModal <ConfirmSqlModal