editing in form view

This commit is contained in:
Jan Prochazka
2021-01-10 16:50:08 +01:00
parent c5c4b0b6de
commit fe1180d1e4
7 changed files with 207 additions and 14 deletions

View File

@@ -0,0 +1,93 @@
import {
ChangeSet,
changeSetContainsChanges,
changeSetInsertNewRow,
createChangeSet,
deleteChangeSetRows,
findExistingChangeSetItem,
getChangeSetInsertedRows,
TableFormViewDisplay,
revertChangeSetRowChanges,
setChangeSetValue,
ChangeSetRowDefinition,
} from 'dbgate-datalib';
import Former from './Former';
export default class ChangeSetFormer extends Former {
public changeSet: ChangeSet;
public setChangeSet: Function;
private batchChangeSet: ChangeSet;
public rowDefinition: ChangeSetRowDefinition;
public rowStatus;
constructor(
public sourceRow: any,
public changeSetState,
public dispatchChangeSet,
public display: TableFormViewDisplay
) {
super();
this.changeSet = changeSetState && changeSetState.value;
this.setChangeSet = (value) => dispatchChangeSet({ type: 'set', value });
this.batchChangeSet = null;
this.rowDefinition = display.getChangeSetRow(sourceRow);
const [matchedField, matchedChangeSetItem] = findExistingChangeSetItem(this.changeSet, this.rowDefinition);
this.rowData = matchedChangeSetItem ? { ...sourceRow, ...matchedChangeSetItem.fields } : sourceRow;
let status = 'regular';
if (matchedChangeSetItem && matchedField == 'updates') status = 'updated';
if (matchedField == 'deletes') status = 'deleted';
this.rowStatus = {
status,
modifiedFields:
matchedChangeSetItem && matchedChangeSetItem.fields ? new Set(Object.keys(matchedChangeSetItem.fields)) : null,
};
}
applyModification(changeSetReducer) {
if (this.batchChangeSet) {
this.batchChangeSet = changeSetReducer(this.batchChangeSet);
} else {
this.setChangeSet(changeSetReducer(this.changeSet));
}
}
setCellValue( uniqueName: string, value: any) {
const row = this.sourceRow;
const definition = this.display.getChangeSetField(row, uniqueName);
this.applyModification((chs) => setChangeSetValue(chs, definition, value));
}
deleteRow(index: number) {
this.applyModification((chs) => deleteChangeSetRows(chs, this.rowDefinition));
}
beginUpdate() {
this.batchChangeSet = this.changeSet;
}
endUpdate() {
this.setChangeSet(this.batchChangeSet);
this.batchChangeSet = null;
}
revertRowChanges() {
this.applyModification((chs) => revertChangeSetRowChanges(chs, this.rowDefinition));
}
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);
}
}

View File

@@ -1,3 +1,5 @@
// @ts-nocheck
import _ from 'lodash';
import React from 'react';
import ReactDOM from 'react-dom';
@@ -48,7 +50,6 @@ const TableHeaderCell = styled.td`
position: relative;
${(props) =>
// @ts-ignore
props.isSelected &&
`
background: initial;
@@ -66,12 +67,17 @@ const TableBodyCell = styled.td`
overflow: hidden;
${(props) =>
// @ts-ignore
props.isSelected &&
`
background: initial;
background-color: ${props.theme.gridbody_selection[4]};
color: ${props.theme.gridbody_invfont1};`}
${(props) =>
!props.isSelected &&
props.isModifiedCell &&
`
background-color: ${props.theme.gridbody_background_orange[1]};`}
`;
const FocusField = styled.input`
@@ -86,7 +92,7 @@ function isDataCell(cell) {
}
export default function FormView(props) {
const { rowData, toolbarPortalRef, tabVisible, config, setConfig, onNavigate } = props;
const { toolbarPortalRef, tabVisible, config, setConfig, onNavigate, former } = props;
/** @type {import('dbgate-datalib').FormViewDisplay} */
const formDisplay = props.formDisplay;
const theme = useTheme();
@@ -100,6 +106,8 @@ export default function FormView(props) {
const rowCount = Math.floor((wrapperHeight - 20) / rowHeight);
const columnChunks = _.chunk(formDisplay.columns, rowCount);
const { rowData, rowStatus } = former;
const handleSwitchToTable = () => {
setConfig((cfg) => ({
...cfg,
@@ -318,6 +326,7 @@ export default function FormView(props) {
data-col={chunkIndex * 2 + 1}
// @ts-ignore
isSelected={currentCell[0] == rowIndex && currentCell[1] == chunkIndex * 2 + 1}
isModifiedCell={rowStatus.modifiedFields && rowStatus.modifiedFields.has(col.uniqueName)}
ref={(element) => setCellRef(rowIndex, chunkIndex * 2 + 1, element)}
>
{inplaceEditorState.cell &&
@@ -328,7 +337,9 @@ export default function FormView(props) {
inplaceEditorState={inplaceEditorState}
dispatchInsplaceEditor={dispatchInsplaceEditor}
cellValue={rowData[col.uniqueName]}
onSetValue={(value) => {}}
onSetValue={(value) => {
former.setCellValue(col.uniqueName, value);
}}
// grider={grider}
// rowIndex={rowIndex}
// uniqueName={col.uniqueName}

View File

@@ -0,0 +1,53 @@
// export interface GriderRowStatus {
// status: 'regular' | 'updated' | 'deleted' | 'inserted';
// modifiedFields?: Set<string>;
// insertedFields?: Set<string>;
// deletedFields?: Set<string>;
// }
export default abstract class Former {
public rowData: any;
// getRowStatus(index): GriderRowStatus {
// const res: GriderRowStatus = {
// status: 'regular',
// };
// return res;
// }
beginUpdate() {}
endUpdate() {}
setCellValue(uniqueName: string, value: any) {}
revertRowChanges() {}
revertAllChanges() {}
undo() {}
redo() {}
get editable() {
return false;
}
get canInsert() {
return false;
}
get allowSave() {
return this.containsChanges;
}
get canUndo() {
return false;
}
get canRedo() {
return false;
}
get containsChanges() {
return false;
}
get disableLoadNextPage() {
return false;
}
get errors() {
return null;
}
updateRow(changeObject) {
for (const key of Object.keys(changeObject)) {
this.setCellValue(key, changeObject[key]);
}
}
}

View File

@@ -5,6 +5,7 @@ import { useConnectionInfo, useDatabaseInfo } from '../utility/metadataLoaders';
import useExtensions from '../utility/useExtensions';
import FormView from './FormView';
import axios from '../utility/axios';
import ChangeSetFormer from './ChangeSetFormer';
async function loadRow(props, sql) {
const { conid, database } = props;
@@ -26,7 +27,7 @@ async function loadRow(props, sql) {
}
export default function SqlFormView(props) {
const { formDisplay } = props;
const { formDisplay, changeSetState, dispatchChangeSet } = props;
const [rowData, setRowData] = React.useState(null);
const handleLoadCurrentRow = async () => {
@@ -46,7 +47,14 @@ export default function SqlFormView(props) {
if (formDisplay && !formDisplay.isLoadedCurrentRow(rowData)) {
handleLoadCurrentRow();
}
}, [formDisplay]);
}, [formDisplay, rowData]);
const former = React.useMemo(() => new ChangeSetFormer(rowData, changeSetState, dispatchChangeSet, formDisplay), [
rowData,
changeSetState,
dispatchChangeSet,
formDisplay,
]);
// const { config, setConfig, cache, setCache, schemaName, pureName, conid, database } = props;
// const { formViewKey } = config;
@@ -76,5 +84,5 @@ export default function SqlFormView(props) {
// setDisplay(newDisplay);
// }, [config, cache, conid, database, schemaName, pureName, dbinfo, extensions]);
return <FormView {...props} rowData={rowData} onNavigate={handleNavigate} />;
return <FormView {...props} rowData={rowData} onNavigate={handleNavigate} former={former} />;
}