diff --git a/packages/web/src/datagrid/ChangeSetGrider.ts b/packages/web/src/datagrid/ChangeSetGrider.ts index a4ca2ec00..b207cb75a 100644 --- a/packages/web/src/datagrid/ChangeSetGrider.ts +++ b/packages/web/src/datagrid/ChangeSetGrider.ts @@ -66,6 +66,10 @@ export default class ChangeSetGrider extends Grider { this.rowCacheIndexes.add(index); } + get canInsert() { + return !!this.display.baseTable; + } + getRowData(index: number) { this.requireRowCache(index); return this.rowDataCache[index]; diff --git a/packages/web/src/datagrid/DataGridCore.js b/packages/web/src/datagrid/DataGridCore.js index 60a351ee1..21d60c54e 100644 --- a/packages/web/src/datagrid/DataGridCore.js +++ b/packages/web/src/datagrid/DataGridCore.js @@ -598,7 +598,7 @@ export default function DataGridCore(props) { } const insertNewRow = () => { - if (display.baseTable) { + if (grider.canInsert) { const rowIndex = grider.insertRow(); const cell = [rowIndex, (currentCell && currentCell[1]) || 0]; // @ts-ignore diff --git a/packages/web/src/datagrid/Grider.ts b/packages/web/src/datagrid/Grider.ts index dcd5807d3..43fc83caf 100644 --- a/packages/web/src/datagrid/Grider.ts +++ b/packages/web/src/datagrid/Grider.ts @@ -25,6 +25,9 @@ export default abstract class Grider { revertAllChanges() {} undo() {} redo() {} + get canInsert() { + return false; + } get rowCountInUpdate() { return this.rowCount; } diff --git a/packages/web/src/freetable/FreeTableGrider.ts b/packages/web/src/freetable/FreeTableGrider.ts index 2a1cd5fa8..0b640a69d 100644 --- a/packages/web/src/freetable/FreeTableGrider.ts +++ b/packages/web/src/freetable/FreeTableGrider.ts @@ -3,17 +3,59 @@ import Grider, { GriderRowStatus } from '../datagrid/Grider'; export default class FreeTableGrider extends Grider { public model: FreeTableModel; - public rows: any[]; + private batchModel: FreeTableModel; + constructor(public modelState, public dispatchModel) { super(); this.model = modelState && modelState.value; - this.rows = this.model.rows; } getRowData(index: any) { - return this.rows[index]; + return this.model.rows[index]; } get rowCount() { - return this.rows.length; + return this.model.rows.length; + } + get currentModel(): FreeTableModel { + return this.batchModel || this.model; + } + set currentModel(value) { + if (this.batchModel) this.batchModel = value; + else this.dispatchModel({ type: 'set', value }); + } + setCellValue(index: number, uniqueName: string, value: any) { + const model = this.currentModel; + if (model.rows[index]) + this.currentModel = { + ...model, + rows: model.rows.map((row, i) => (index == i ? { ...row, [uniqueName]: value } : row)), + }; + } + get canInsert() { + return true; + } + insertRow(): number { + const model = this.currentModel; + this.currentModel = { + ...model, + rows: [...model.rows, {}], + }; + return this.currentModel.rows.length - 1; + } + deleteRow(index: number) { + const model = this.currentModel; + this.currentModel = { + ...model, + rows: model.rows.filter((row, i) => index != i), + }; + } + beginUpdate() { + this.batchModel = this.model; + } + endUpdate() { + if (this.model != this.batchModel) { + this.dispatchModel({ type: 'set', value: this.batchModel }); + this.batchModel = null; + } } static factory({ modelState, dispatchModel }): FreeTableGrider { diff --git a/packages/web/src/tabs/FreeTableTab.js b/packages/web/src/tabs/FreeTableTab.js index 070ab1da6..89185047d 100644 --- a/packages/web/src/tabs/FreeTableTab.js +++ b/packages/web/src/tabs/FreeTableTab.js @@ -10,6 +10,20 @@ import FreeTableGrid from '../freetable/FreeTableGrid'; export default function FreeDataTab({ conid, database, schemaName, pureName, tabVisible, toolbarPortalRef, tabid }) { const [config, setConfig] = useGridConfig(tabid); const [modelState, dispatchModel] = useUndoReducer(createFreeTableModel()); + const storageKey = `tabdata_freetable_${tabid}`; + + React.useEffect(() => { + const existingData = localStorage.getItem(storageKey); + if (existingData) { + const value = JSON.parse(existingData); + // @ts-ignore + dispatchModel({ type: 'reset', value }); + } + }, []); + + React.useEffect(() => { + localStorage.setItem(storageKey, JSON.stringify(modelState.value)); + }, [modelState]); return (