mirror of
https://github.com/dbgate/dbgate
synced 2024-11-07 20:26:23 +00:00
grider refactor
This commit is contained in:
parent
b314e363cd
commit
abc007753a
119
packages/web/src/datagrid/ChangeSetGrider.ts
Normal file
119
packages/web/src/datagrid/ChangeSetGrider.ts
Normal file
@ -0,0 +1,119 @@
|
||||
import {
|
||||
ChangeSet,
|
||||
changeSetInsertNewRow,
|
||||
deleteChangeSetRows,
|
||||
findExistingChangeSetItem,
|
||||
getChangeSetInsertedRows,
|
||||
GridDisplay,
|
||||
setChangeSetValue,
|
||||
} from '@dbgate/datalib';
|
||||
import Grider, { GriderRowStatus } from './Grider';
|
||||
|
||||
export default class ChangeSetGrider extends Grider {
|
||||
public insertedRows: any[];
|
||||
public setChangeSet: Function;
|
||||
private rowCacheIndexes: Set<number>;
|
||||
private rowDataCache;
|
||||
private rowStatusCache;
|
||||
private rowDefinitionsCache;
|
||||
private batchChangeSet: ChangeSet;
|
||||
|
||||
constructor(
|
||||
public sourceRows: any[],
|
||||
public changeSet: ChangeSet,
|
||||
public dispatchChangeSet,
|
||||
public display: GridDisplay
|
||||
) {
|
||||
super();
|
||||
this.insertedRows = getChangeSetInsertedRows(changeSet, display.baseTable);
|
||||
this.setChangeSet = (value) => dispatchChangeSet({ type: 'set', value });
|
||||
this.rowCacheIndexes = new Set();
|
||||
this.rowDataCache = {};
|
||||
this.rowStatusCache = {};
|
||||
this.rowDefinitionsCache = {};
|
||||
this.batchChangeSet = null;
|
||||
}
|
||||
|
||||
getRowSource(index: number) {
|
||||
if (index < this.sourceRows.length) return this.sourceRows[index];
|
||||
return null;
|
||||
}
|
||||
|
||||
getInsertedRowIndex(index) {
|
||||
return index >= this.sourceRows.length ? index - this.sourceRows.length : null;
|
||||
}
|
||||
|
||||
requireRowCache(index: number) {
|
||||
if (this.rowCacheIndexes.has(index)) return;
|
||||
const row = this.getRowSource(index);
|
||||
const insertedRowIndex = this.getInsertedRowIndex(index);
|
||||
const rowDefinition = this.display.getChangeSetRow(row, insertedRowIndex);
|
||||
const [matchedField, matchedChangeSetItem] = findExistingChangeSetItem(this.changeSet, rowDefinition);
|
||||
const rowUpdated = matchedChangeSetItem ? { ...row, ...matchedChangeSetItem.fields } : row;
|
||||
let status = 'regular';
|
||||
if (matchedChangeSetItem && matchedField == 'updates') status = 'updated';
|
||||
if (matchedField == 'deletes') status = 'deleted';
|
||||
if (insertedRowIndex != null) status = 'inserted';
|
||||
const rowStatus = {
|
||||
status,
|
||||
modifiedFields: new Set(matchedChangeSetItem ? Object.keys(matchedChangeSetItem.fields) : []),
|
||||
};
|
||||
this.rowDataCache[index] = rowUpdated;
|
||||
this.rowStatusCache[index] = rowStatus;
|
||||
this.rowDefinitionsCache[index] = rowDefinition;
|
||||
this.rowCacheIndexes.add(index);
|
||||
}
|
||||
|
||||
getRowData(index: number) {
|
||||
this.requireRowCache(index);
|
||||
return this.rowDataCache[index];
|
||||
}
|
||||
|
||||
getRowStatus(index): GriderRowStatus {
|
||||
this.requireRowCache(index);
|
||||
return this.rowStatusCache[index];
|
||||
}
|
||||
|
||||
get rowCount() {
|
||||
return this.sourceRows.length + this.insertedRows.length;
|
||||
}
|
||||
|
||||
applyModification(changeSetReducer) {
|
||||
if (this.batchChangeSet) {
|
||||
this.batchChangeSet = changeSetReducer(this.batchChangeSet);
|
||||
} else {
|
||||
this.setChangeSet(changeSetReducer(this.changeSet));
|
||||
}
|
||||
}
|
||||
|
||||
setCellValue(index: number, uniqueName: string, value: any) {
|
||||
const row = this.getRowSource(index);
|
||||
const definition = this.display.getChangeSetField(row, uniqueName, this.getInsertedRowIndex(index));
|
||||
this.applyModification((chs) => setChangeSetValue(chs, definition, value));
|
||||
}
|
||||
|
||||
deleteRow(index: number) {
|
||||
this.requireRowCache(index);
|
||||
this.applyModification((chs) => deleteChangeSetRows(chs, this.rowDefinitionsCache[index]));
|
||||
}
|
||||
|
||||
insertRow(): number {
|
||||
this.applyModification((chs) => changeSetInsertNewRow(chs, this.display.baseTable));
|
||||
return this.rowCount;
|
||||
}
|
||||
|
||||
beginUpdate() {
|
||||
this.batchChangeSet = this.changeSet;
|
||||
}
|
||||
endUpdate() {
|
||||
this.setChangeSet(this.batchChangeSet);
|
||||
this.batchChangeSet = null;
|
||||
}
|
||||
|
||||
static factory({ sourceRows, changeSet, dispatchChangeSet, display }): ChangeSetGrider {
|
||||
return new ChangeSetGrider(sourceRows, changeSet, dispatchChangeSet, display);
|
||||
}
|
||||
static factoryDeps({ sourceRows, changeSet, dispatchChangeSet, display }) {
|
||||
return [sourceRows, changeSet, dispatchChangeSet, display];
|
||||
}
|
||||
}
|
@ -126,7 +126,7 @@ const LoadingInfoBox = styled.div`
|
||||
border: 1px solid gray;
|
||||
`;
|
||||
|
||||
/** @param props {import('./types').DataGridCoreProps} */
|
||||
/** @param props {import('./types').DataGridProps} */
|
||||
export default function DataGridCore(props) {
|
||||
const {
|
||||
display,
|
||||
@ -135,7 +135,6 @@ export default function DataGridCore(props) {
|
||||
changeSetState,
|
||||
dispatchChangeSet,
|
||||
tabVisible,
|
||||
rows,
|
||||
loadNextData,
|
||||
errorMessage,
|
||||
isLoadedAll,
|
||||
@ -145,6 +144,7 @@ export default function DataGridCore(props) {
|
||||
openQuery,
|
||||
insertedRowCount,
|
||||
isLoading,
|
||||
grider,
|
||||
} = props;
|
||||
// console.log('RENDER GRID', display.baseTable.pureName);
|
||||
const columns = React.useMemo(() => display.allColumns, [display]);
|
||||
@ -236,8 +236,8 @@ export default function DataGridCore(props) {
|
||||
|
||||
// usePropsCompare({ loadedRows, columns, containerWidth, display });
|
||||
|
||||
const columnSizes = React.useMemo(() => countColumnSizes(rows, columns, containerWidth, display), [
|
||||
rows,
|
||||
const columnSizes = React.useMemo(() => countColumnSizes(grider, columns, containerWidth, display), [
|
||||
grider,
|
||||
columns,
|
||||
containerWidth,
|
||||
display,
|
||||
@ -269,10 +269,10 @@ export default function DataGridCore(props) {
|
||||
}, [columnSizes, gridScrollAreaWidth]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (props.onReferenceSourceChanged && ((rows && rows.length > 0) || isLoadedAll)) {
|
||||
if (props.onReferenceSourceChanged && (grider.rowCount > 0 || isLoadedAll)) {
|
||||
props.onReferenceSourceChanged(getSelectedRowData(), loadedTime);
|
||||
}
|
||||
}, [selectedCells, props.refReloadToken, rows && rows[0]]);
|
||||
}, [selectedCells, props.refReloadToken, grider.getRowData(0)]);
|
||||
|
||||
// const handleCloseInplaceEditor = React.useCallback(
|
||||
// mode => {
|
||||
@ -312,7 +312,7 @@ export default function DataGridCore(props) {
|
||||
}, [display && display.focusedColumn]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (rows && loadNextData && firstVisibleRowScrollIndex + visibleRowCountUpperBound >= rows.length) {
|
||||
if (loadNextData && firstVisibleRowScrollIndex + visibleRowCountUpperBound >= grider.rowCount) {
|
||||
loadNextData();
|
||||
}
|
||||
});
|
||||
@ -334,7 +334,7 @@ export default function DataGridCore(props) {
|
||||
const rowCountInfo = React.useMemo(() => {
|
||||
if (selectedCells.length > 1 && selectedCells.every((x) => _.isNumber(x[0]) && _.isNumber(x[1]))) {
|
||||
let sum = _.sumBy(selectedCells, (cell) => {
|
||||
const row = rows[cell[0]];
|
||||
const row = grider.getRowData(cell[0]);
|
||||
if (row) {
|
||||
const colName = realColumnUniqueNames[cell[1]];
|
||||
if (colName) {
|
||||
@ -356,9 +356,9 @@ export default function DataGridCore(props) {
|
||||
// if (this.isLoadingFirstPage) return "Loading first page...";
|
||||
// if (this.isFirstPageError) return "Error loading first page";
|
||||
// return `Rows: ${this.rowCount.toLocaleString()}`;
|
||||
}, [selectedCells, allRowCount, rows, visibleRealColumns]);
|
||||
}, [selectedCells, allRowCount, grider, visibleRealColumns]);
|
||||
|
||||
if (!rows || !columns || columns.length == 0)
|
||||
if (!columns || columns.length == 0)
|
||||
return (
|
||||
<LoadingInfoWrapper>
|
||||
<LoadingInfoBox>
|
||||
@ -551,7 +551,7 @@ export default function DataGridCore(props) {
|
||||
const rowIndexes = _.sortBy(_.uniq(cells.map((x) => x[0])));
|
||||
const lines = rowIndexes.map((rowIndex) => {
|
||||
let colIndexes = _.sortBy(cells.filter((x) => x[0] == rowIndex).map((x) => x[1]));
|
||||
const rowData = rows[rowIndex];
|
||||
const rowData = grider.getRowData(rowIndex);
|
||||
if (!rowData) return '';
|
||||
const line = colIndexes
|
||||
.map((col) => realColumnUniqueNames[col])
|
||||
@ -591,7 +591,7 @@ export default function DataGridCore(props) {
|
||||
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(rows[currentRowNumber], colNames);
|
||||
const changeObject = _.pick(grider.getRowData(currentRowNumber), colNames);
|
||||
setChangeSet(
|
||||
batchUpdateChangeSet(
|
||||
changeSet,
|
||||
@ -629,7 +629,7 @@ export default function DataGridCore(props) {
|
||||
}
|
||||
|
||||
function getSelectedRowData() {
|
||||
return _.compact(getSelectedRowIndexes().map((index) => rows && rows[index]));
|
||||
return _.compact(getSelectedRowIndexes().map((index) => grider.getRowData(index)));
|
||||
}
|
||||
|
||||
function revertRowChanges() {
|
||||
@ -646,7 +646,7 @@ export default function DataGridCore(props) {
|
||||
if (!isRegularCell(cell)) continue;
|
||||
const modelIndex = columnSizes.realToModel(cell[1]);
|
||||
const columnName = columns[modelIndex].uniqueName;
|
||||
let value = rows[cell[0]][columnName];
|
||||
let value = grider.getRowData(cell[0])[columnName];
|
||||
let svalue = getFilterValueExpression(value, columns[modelIndex].dataType);
|
||||
if (_.has(flts, columnName)) flts[columnName] += ',' + svalue;
|
||||
else flts[columnName] = svalue;
|
||||
@ -672,7 +672,7 @@ export default function DataGridCore(props) {
|
||||
if (event.deltaY < 0) {
|
||||
newFirstVisibleRowScrollIndex -= wheelRowCount;
|
||||
}
|
||||
let rowCount = rows.length;
|
||||
let rowCount = grider.rowCount;
|
||||
if (newFirstVisibleRowScrollIndex + visibleRowCountLowerBound > rowCount) {
|
||||
newFirstVisibleRowScrollIndex = rowCount - visibleRowCountLowerBound + 1;
|
||||
}
|
||||
@ -728,8 +728,9 @@ export default function DataGridCore(props) {
|
||||
|
||||
const insertNewRow = () => {
|
||||
if (display.baseTable) {
|
||||
setChangeSet(changeSetInsertNewRow(changeSet, display.baseTable));
|
||||
const cell = [rows.length, (currentCell && currentCell[1]) || 0];
|
||||
const rowIndex = grider.insertRow();
|
||||
// setChangeSet(changeSetInsertNewRow(changeSet, display.baseTable));
|
||||
const cell = [rowIndex, (currentCell && currentCell[1]) || 0];
|
||||
// @ts-ignore
|
||||
setCurrentCell(cell);
|
||||
// @ts-ignore
|
||||
@ -843,7 +844,7 @@ export default function DataGridCore(props) {
|
||||
|
||||
function handleCursorMove(event) {
|
||||
if (!isRegularCell(currentCell)) return null;
|
||||
let rowCount = rows.length;
|
||||
let rowCount = grider.rowCount;
|
||||
if (event.ctrlKey) {
|
||||
switch (event.keyCode) {
|
||||
case keycodes.upArrow:
|
||||
@ -901,7 +902,7 @@ export default function DataGridCore(props) {
|
||||
}
|
||||
|
||||
function moveCurrentCell(row, col, event = null) {
|
||||
const rowCount = rows.length;
|
||||
const rowCount = grider.rowCount;
|
||||
|
||||
if (row < 0) row = 0;
|
||||
if (row >= rowCount) row = rowCount - 1;
|
||||
@ -923,7 +924,7 @@ export default function DataGridCore(props) {
|
||||
|
||||
if (row != null) {
|
||||
let newRow = null;
|
||||
const rowCount = rows.length;
|
||||
const rowCount = grider.rowCount;
|
||||
if (rowCount == 0) return;
|
||||
|
||||
if (row < firstVisibleRowScrollIndex) newRow = row;
|
||||
@ -1065,28 +1066,29 @@ export default function DataGridCore(props) {
|
||||
)}
|
||||
</TableHead>
|
||||
<TableBody ref={tableBodyRef}>
|
||||
{rows
|
||||
.slice(firstVisibleRowScrollIndex, firstVisibleRowScrollIndex + visibleRowCountUpperBound)
|
||||
.map((row, index) => (
|
||||
{_.range(firstVisibleRowScrollIndex, firstVisibleRowScrollIndex + visibleRowCountUpperBound)
|
||||
// .slice(firstVisibleRowScrollIndex, firstVisibleRowScrollIndex + visibleRowCountUpperBound)
|
||||
.map((rowIndex) => (
|
||||
<DataGridRow
|
||||
key={firstVisibleRowScrollIndex + index}
|
||||
rowIndex={firstVisibleRowScrollIndex + index}
|
||||
key={rowIndex}
|
||||
grider={grider}
|
||||
rowIndex={rowIndex}
|
||||
rowHeight={rowHeight}
|
||||
visibleRealColumns={visibleRealColumns}
|
||||
inplaceEditorState={inplaceEditorState}
|
||||
dispatchInsplaceEditor={dispatchInsplaceEditor}
|
||||
autofillSelectedCells={autofillSelectedCells}
|
||||
selectedCells={filterCellsForRow(selectedCells, firstVisibleRowScrollIndex + index)}
|
||||
insertedRowIndex={
|
||||
firstVisibleRowScrollIndex + index >= rows.length - (insertedRowCount || 0)
|
||||
? firstVisibleRowScrollIndex + index - rows.length - (insertedRowCount || 0)
|
||||
: null
|
||||
}
|
||||
autofillMarkerCell={filterCellForRow(autofillMarkerCell, firstVisibleRowScrollIndex + index)}
|
||||
changeSet={changeSet}
|
||||
setChangeSet={setChangeSet}
|
||||
selectedCells={filterCellsForRow(selectedCells, rowIndex)}
|
||||
// insertedRowIndex={
|
||||
// firstVisibleRowScrollIndex + index >= rows.length - (insertedRowCount || 0)
|
||||
// ? firstVisibleRowScrollIndex + index - rows.length - (insertedRowCount || 0)
|
||||
// : null
|
||||
// }
|
||||
autofillMarkerCell={filterCellForRow(autofillMarkerCell, rowIndex)}
|
||||
// changeSet={changeSet}
|
||||
// setChangeSet={setChangeSet}
|
||||
display={display}
|
||||
row={row}
|
||||
// row={row}
|
||||
focusedColumn={display.focusedColumn}
|
||||
/>
|
||||
))}
|
||||
@ -1104,9 +1106,9 @@ export default function DataGridCore(props) {
|
||||
valueToSet={vScrollValueToSet}
|
||||
valueToSetDate={vScrollValueToSetDate}
|
||||
minimum={0}
|
||||
maximum={rows.length - visibleRowCountUpperBound + 2}
|
||||
maximum={grider.rowCount - visibleRowCountUpperBound + 2}
|
||||
onScroll={handleRowScroll}
|
||||
viewportRatio={visibleRowCountUpperBound / rows.length}
|
||||
viewportRatio={visibleRowCountUpperBound / grider.rowCount}
|
||||
/>
|
||||
<ConfirmSqlModal
|
||||
modalState={confirmSqlModalState}
|
||||
|
@ -34,13 +34,13 @@ const TableBodyCell = styled.td`
|
||||
color: white;`}
|
||||
|
||||
${(props) =>
|
||||
props.isModifiedRow &&
|
||||
!props.isInsertedRow &&
|
||||
!props.isSelected &&
|
||||
!props.isAutofillSelected &&
|
||||
!props.isModifiedCell &&
|
||||
!props.isFocusedColumn &&
|
||||
`
|
||||
props.isModifiedRow &&
|
||||
!props.isInsertedRow &&
|
||||
!props.isSelected &&
|
||||
!props.isAutofillSelected &&
|
||||
!props.isModifiedCell &&
|
||||
!props.isFocusedColumn &&
|
||||
`
|
||||
background-color: #FFFFDB;`}
|
||||
${(props) =>
|
||||
!props.isSelected &&
|
||||
@ -60,11 +60,11 @@ const TableBodyCell = styled.td`
|
||||
background-color: #DBFFDB;`}
|
||||
|
||||
${(props) =>
|
||||
!props.isSelected &&
|
||||
!props.isAutofillSelected &&
|
||||
!props.isFocusedColumn &&
|
||||
props.isDeletedRow &&
|
||||
`
|
||||
!props.isSelected &&
|
||||
!props.isAutofillSelected &&
|
||||
!props.isFocusedColumn &&
|
||||
props.isDeletedRow &&
|
||||
`
|
||||
background-color: #FFDBFF;
|
||||
`}
|
||||
|
||||
@ -75,14 +75,13 @@ const TableBodyCell = styled.td`
|
||||
`}
|
||||
|
||||
${(props) =>
|
||||
props.isDeletedRow &&
|
||||
`
|
||||
props.isDeletedRow &&
|
||||
`
|
||||
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAEElEQVQImWNgIAX8x4KJBAD+agT8INXz9wAAAABJRU5ErkJggg==');
|
||||
// from http://www.patternify.com/
|
||||
background-repeat: repeat-x;
|
||||
background-position: 50% 50%;`}
|
||||
|
||||
`;
|
||||
`;
|
||||
|
||||
const HintSpan = styled.span`
|
||||
color: gray;
|
||||
@ -163,22 +162,25 @@ function CellFormattedValue({ value, dataType }) {
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
function DataGridRow({
|
||||
rowHeight,
|
||||
rowIndex,
|
||||
visibleRealColumns,
|
||||
inplaceEditorState,
|
||||
dispatchInsplaceEditor,
|
||||
row,
|
||||
display,
|
||||
changeSet,
|
||||
setChangeSet,
|
||||
insertedRowIndex,
|
||||
autofillMarkerCell,
|
||||
selectedCells,
|
||||
autofillSelectedCells,
|
||||
focusedColumn,
|
||||
}) {
|
||||
/** @param props {import('./types').DataGridProps} */
|
||||
function DataGridRow(props) {
|
||||
const {
|
||||
rowHeight,
|
||||
rowIndex,
|
||||
visibleRealColumns,
|
||||
inplaceEditorState,
|
||||
dispatchInsplaceEditor,
|
||||
// row,
|
||||
display,
|
||||
// changeSet,
|
||||
// setChangeSet,
|
||||
insertedRowIndex,
|
||||
autofillMarkerCell,
|
||||
selectedCells,
|
||||
autofillSelectedCells,
|
||||
focusedColumn,
|
||||
grider,
|
||||
} = props;
|
||||
// usePropsCompare({
|
||||
// rowHeight,
|
||||
// rowIndex,
|
||||
@ -197,18 +199,23 @@ function DataGridRow({
|
||||
|
||||
// console.log('RENDER ROW', rowIndex);
|
||||
|
||||
const rowDefinition = display.getChangeSetRow(row, insertedRowIndex);
|
||||
const [matchedField, matchedChangeSetItem] = findExistingChangeSetItem(changeSet, rowDefinition);
|
||||
const rowUpdated = matchedChangeSetItem ? { ...row, ...matchedChangeSetItem.fields } : row;
|
||||
const rowData = grider.getRowData(rowIndex);
|
||||
const rowStatus = grider.getRowStatus(rowIndex);
|
||||
|
||||
// const rowDefinition = display.getChangeSetRow(row, insertedRowIndex);
|
||||
// const [matchedField, matchedChangeSetItem] = findExistingChangeSetItem(changeSet, rowDefinition);
|
||||
// const rowUpdated = matchedChangeSetItem ? { ...row, ...matchedChangeSetItem.fields } : row;
|
||||
|
||||
const hintFieldsAllowed = visibleRealColumns
|
||||
.filter((col) => {
|
||||
if (!col.hintColumnName) return false;
|
||||
if (matchedChangeSetItem && matchedField == 'updates' && col.uniqueName in matchedChangeSetItem.fields)
|
||||
return false;
|
||||
if (rowStatus.status == 'updated' && rowStatus.modifiedFields.has(col.uniqueName)) return false;
|
||||
return true;
|
||||
})
|
||||
.map((col) => col.uniqueName);
|
||||
|
||||
if (!rowData) return null;
|
||||
|
||||
return (
|
||||
<TableBodyRow style={{ height: `${rowHeight}px` }}>
|
||||
<TableHeaderCell data-row={rowIndex} data-col="header">
|
||||
@ -226,13 +233,11 @@ function DataGridRow({
|
||||
data-col={col.colIndex}
|
||||
isSelected={cellIsSelected(rowIndex, col.colIndex, selectedCells)}
|
||||
isAutofillSelected={cellIsSelected(rowIndex, col.colIndex, autofillSelectedCells)}
|
||||
isModifiedRow={!!matchedChangeSetItem}
|
||||
isModifiedRow={rowStatus.status == 'updated'}
|
||||
isFocusedColumn={col.uniqueName == focusedColumn}
|
||||
isModifiedCell={
|
||||
matchedChangeSetItem && matchedField == 'updates' && col.uniqueName in matchedChangeSetItem.fields
|
||||
}
|
||||
isModifiedCell={rowStatus.status == 'updated' && rowStatus.modifiedFields.has(col.uniqueName)}
|
||||
isInsertedRow={insertedRowIndex != null}
|
||||
isDeletedRow={matchedField == 'deletes'}
|
||||
isDeletedRow={rowStatus.status == 'deleted'}
|
||||
>
|
||||
{inplaceEditorState.cell &&
|
||||
rowIndex == inplaceEditorState.cell[0] &&
|
||||
@ -241,16 +246,19 @@ function DataGridRow({
|
||||
widthPx={col.widthPx}
|
||||
inplaceEditorState={inplaceEditorState}
|
||||
dispatchInsplaceEditor={dispatchInsplaceEditor}
|
||||
cellValue={rowUpdated[col.uniqueName]}
|
||||
changeSet={changeSet}
|
||||
setChangeSet={setChangeSet}
|
||||
insertedRowIndex={insertedRowIndex}
|
||||
definition={display.getChangeSetField(row, col.uniqueName, insertedRowIndex)}
|
||||
cellValue={rowData[col.uniqueName]}
|
||||
grider={grider}
|
||||
rowIndex={rowIndex}
|
||||
uniqueName={col.uniqueName}
|
||||
// changeSet={changeSet}
|
||||
// setChangeSet={setChangeSet}
|
||||
// insertedRowIndex={insertedRowIndex}
|
||||
// definition={display.getChangeSetField(row, col.uniqueName, insertedRowIndex)}
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
<CellFormattedValue value={rowUpdated[col.uniqueName]} dataType={col.dataType} />
|
||||
{hintFieldsAllowed.includes(col.uniqueName) && <HintSpan>{row[col.hintColumnName]}</HintSpan>}
|
||||
<CellFormattedValue value={rowData[col.uniqueName]} dataType={col.dataType} />
|
||||
{hintFieldsAllowed.includes(col.uniqueName) && <HintSpan>{rowData[col.hintColumnName]}</HintSpan>}
|
||||
</>
|
||||
)}
|
||||
{autofillMarkerCell && autofillMarkerCell[1] == col.colIndex && autofillMarkerCell[0] == rowIndex && (
|
||||
|
28
packages/web/src/datagrid/Grider.ts
Normal file
28
packages/web/src/datagrid/Grider.ts
Normal file
@ -0,0 +1,28 @@
|
||||
export interface GriderRowStatus {
|
||||
status: 'regular' | 'updated' | 'deleted' | 'inserted';
|
||||
modifiedFields: Set<string>;
|
||||
}
|
||||
|
||||
export default abstract class Grider {
|
||||
abstract getRowData(index): any;
|
||||
abstract get rowCount(): number;
|
||||
|
||||
getRowsSample() {
|
||||
return [this.getRowData(0)];
|
||||
}
|
||||
|
||||
getRowStatus(index): GriderRowStatus {
|
||||
const res: GriderRowStatus = {
|
||||
status: 'regular',
|
||||
modifiedFields: new Set(),
|
||||
};
|
||||
return res;
|
||||
}
|
||||
beginUpdate() {}
|
||||
endUpdate() {}
|
||||
setCellValue(index: number, uniqueName: string, value: any) {}
|
||||
deleteRow(index: number) {}
|
||||
insertRow(): number {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -16,13 +16,16 @@ const StyledInput = styled.input`
|
||||
|
||||
export default function InplaceEditor({
|
||||
widthPx,
|
||||
definition,
|
||||
changeSet,
|
||||
setChangeSet,
|
||||
// definition,
|
||||
// changeSet,
|
||||
// setChangeSet,
|
||||
rowIndex,
|
||||
uniqueName,
|
||||
grider,
|
||||
cellValue,
|
||||
inplaceEditorState,
|
||||
dispatchInsplaceEditor,
|
||||
isInsertedRow,
|
||||
// isInsertedRow,
|
||||
}) {
|
||||
const editorRef = React.useRef();
|
||||
const isChangedRef = React.useRef(!!inplaceEditorState.text);
|
||||
@ -37,7 +40,8 @@ export default function InplaceEditor({
|
||||
function handleBlur() {
|
||||
if (isChangedRef.current) {
|
||||
const editor = editorRef.current;
|
||||
setChangeSet(setChangeSetValue(changeSet, definition, editor.value));
|
||||
grider.setCellValue(rowIndex, uniqueName, editor.value);
|
||||
// setChangeSet(setChangeSetValue(changeSet, definition, editor.value));
|
||||
isChangedRef.current = false;
|
||||
}
|
||||
dispatchInsplaceEditor({ type: 'close' });
|
||||
@ -45,7 +49,8 @@ export default function InplaceEditor({
|
||||
if (inplaceEditorState.shouldSave) {
|
||||
const editor = editorRef.current;
|
||||
if (isChangedRef.current) {
|
||||
setChangeSet(setChangeSetValue(changeSet, definition, editor.value));
|
||||
grider.setCellValue(rowIndex, uniqueName, editor.value);
|
||||
// setChangeSet(setChangeSetValue(changeSet, definition, editor.value));
|
||||
isChangedRef.current = false;
|
||||
}
|
||||
editor.blur();
|
||||
@ -60,7 +65,8 @@ export default function InplaceEditor({
|
||||
break;
|
||||
case keycodes.enter:
|
||||
if (isChangedRef.current) {
|
||||
setChangeSet(setChangeSetValue(changeSet, definition, editor.value));
|
||||
grider.setCellValue(rowIndex, uniqueName, editor.value);
|
||||
// setChangeSet(setChangeSetValue(changeSet, definition, editor.value));
|
||||
isChangedRef.current = false;
|
||||
}
|
||||
editor.blur();
|
||||
@ -69,7 +75,8 @@ export default function InplaceEditor({
|
||||
case keycodes.s:
|
||||
if (event.ctrlKey) {
|
||||
if (isChangedRef.current) {
|
||||
setChangeSet(setChangeSetValue(changeSet, definition, editor.value));
|
||||
grider.setCellValue(rowIndex, uniqueName, editor.value);
|
||||
// setChangeSet(setChangeSetValue(changeSet, definition, editor.value));
|
||||
isChangedRef.current = false;
|
||||
}
|
||||
event.preventDefault();
|
||||
|
@ -8,6 +8,7 @@ import ImportExportModal from '../modals/ImportExportModal';
|
||||
import { getChangeSetInsertedRows } from '@dbgate/datalib';
|
||||
import { openNewTab } from '../utility/common';
|
||||
import LoadingDataGridCore from './LoadingDataGridCore';
|
||||
import RowsArrayGrider from './RowsArrayGrider';
|
||||
|
||||
async function loadDataPage(props, offset, limit) {
|
||||
const { jslid } = props;
|
||||
@ -88,6 +89,8 @@ export default function JslDataGridCore(props) {
|
||||
loadRowCount={loadRowCount}
|
||||
loadNextDataToken={changeIndex}
|
||||
onReload={() => setChangeIndex(0)}
|
||||
griderFactory={RowsArrayGrider.factory}
|
||||
griderFactoryDeps={RowsArrayGrider.factoryDeps}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -8,75 +8,75 @@ import ImportExportModal from '../modals/ImportExportModal';
|
||||
import { getChangeSetInsertedRows } from '@dbgate/datalib';
|
||||
import { openNewTab } from '../utility/common';
|
||||
|
||||
/** @param props {import('./types').LoadingDataGridProps} */
|
||||
async function loadDataPage(props, offset, limit) {
|
||||
const { display, conid, database, jslid } = props;
|
||||
// /** @param props {import('./types').LoadingDataGridProps} */
|
||||
// async function loadDataPage(props, offset, limit) {
|
||||
// const { display, conid, database, jslid } = props;
|
||||
|
||||
if (jslid) {
|
||||
const response = await axios.request({
|
||||
url: 'jsldata/get-rows',
|
||||
method: 'get',
|
||||
params: {
|
||||
jslid,
|
||||
offset,
|
||||
limit,
|
||||
},
|
||||
});
|
||||
return response.data;
|
||||
}
|
||||
// if (jslid) {
|
||||
// const response = await axios.request({
|
||||
// url: 'jsldata/get-rows',
|
||||
// method: 'get',
|
||||
// params: {
|
||||
// jslid,
|
||||
// offset,
|
||||
// limit,
|
||||
// },
|
||||
// });
|
||||
// return response.data;
|
||||
// }
|
||||
|
||||
const sql = display.getPageQuery(offset, limit);
|
||||
// const sql = display.getPageQuery(offset, limit);
|
||||
|
||||
const response = await axios.request({
|
||||
url: 'database-connections/query-data',
|
||||
method: 'post',
|
||||
params: {
|
||||
conid,
|
||||
database,
|
||||
},
|
||||
data: { sql },
|
||||
});
|
||||
// const response = await axios.request({
|
||||
// url: 'database-connections/query-data',
|
||||
// method: 'post',
|
||||
// params: {
|
||||
// conid,
|
||||
// database,
|
||||
// },
|
||||
// data: { sql },
|
||||
// });
|
||||
|
||||
if (response.data.errorMessage) return response.data;
|
||||
return response.data.rows;
|
||||
}
|
||||
// if (response.data.errorMessage) return response.data;
|
||||
// return response.data.rows;
|
||||
// }
|
||||
|
||||
function dataPageAvailable(props) {
|
||||
const { display, jslid } = props;
|
||||
if (jslid) return true;
|
||||
const sql = display.getPageQuery(0, 1);
|
||||
return !!sql;
|
||||
}
|
||||
// function dataPageAvailable(props) {
|
||||
// const { display, jslid } = props;
|
||||
// if (jslid) return true;
|
||||
// const sql = display.getPageQuery(0, 1);
|
||||
// return !!sql;
|
||||
// }
|
||||
|
||||
/** @param props {import('./types').LoadingDataGridProps} */
|
||||
async function loadRowCount(props) {
|
||||
const { display, conid, database, jslid } = props;
|
||||
// /** @param props {import('./types').LoadingDataGridProps} */
|
||||
// async function loadRowCount(props) {
|
||||
// const { display, conid, database, jslid } = props;
|
||||
|
||||
if (jslid) {
|
||||
const response = await axios.request({
|
||||
url: 'jsldata/get-stats',
|
||||
method: 'get',
|
||||
params: {
|
||||
jslid,
|
||||
},
|
||||
});
|
||||
return response.data.rowCount;
|
||||
}
|
||||
// if (jslid) {
|
||||
// const response = await axios.request({
|
||||
// url: 'jsldata/get-stats',
|
||||
// method: 'get',
|
||||
// params: {
|
||||
// jslid,
|
||||
// },
|
||||
// });
|
||||
// return response.data.rowCount;
|
||||
// }
|
||||
|
||||
const sql = display.getCountQuery();
|
||||
// const sql = display.getCountQuery();
|
||||
|
||||
const response = await axios.request({
|
||||
url: 'database-connections/query-data',
|
||||
method: 'post',
|
||||
params: {
|
||||
conid,
|
||||
database,
|
||||
},
|
||||
data: { sql },
|
||||
});
|
||||
// const response = await axios.request({
|
||||
// url: 'database-connections/query-data',
|
||||
// method: 'post',
|
||||
// params: {
|
||||
// conid,
|
||||
// database,
|
||||
// },
|
||||
// data: { sql },
|
||||
// });
|
||||
|
||||
return parseInt(response.data.rows[0].count);
|
||||
}
|
||||
// return parseInt(response.data.rows[0].count);
|
||||
// }
|
||||
|
||||
export default function LoadingDataGridCore(props) {
|
||||
const {
|
||||
@ -91,6 +91,8 @@ export default function LoadingDataGridCore(props) {
|
||||
onReload,
|
||||
exportGrid,
|
||||
openQuery,
|
||||
griderFactory,
|
||||
griderFactoryDeps,
|
||||
} = props;
|
||||
|
||||
const [loadProps, setLoadProps] = React.useState({
|
||||
@ -187,12 +189,12 @@ export default function LoadingDataGridCore(props) {
|
||||
}
|
||||
};
|
||||
|
||||
React.useEffect(()=>{
|
||||
React.useEffect(() => {
|
||||
setLoadProps((oldProps) => ({
|
||||
...oldProps,
|
||||
isLoadedAll: false,
|
||||
}));
|
||||
},[loadNextDataToken]);
|
||||
}, [loadNextDataToken]);
|
||||
|
||||
const insertedRows = getChangeSetInsertedRows(changeSet, display.baseTable);
|
||||
const rowCountNewIncluded = loadedRows.length + insertedRows.length;
|
||||
@ -206,6 +208,9 @@ export default function LoadingDataGridCore(props) {
|
||||
}
|
||||
};
|
||||
|
||||
const griderProps = { ...props, sourceRows: loadedRows };
|
||||
const grider = React.useMemo(() => griderFactory(griderProps), griderFactoryDeps(griderProps));
|
||||
|
||||
return (
|
||||
<DataGridCore
|
||||
{...props}
|
||||
@ -214,10 +219,11 @@ export default function LoadingDataGridCore(props) {
|
||||
isLoadedAll={isLoadedAll}
|
||||
loadedTime={loadedTime}
|
||||
exportGrid={exportGrid}
|
||||
allRowCount={allRowCount}
|
||||
// allRowCount={allRowCount}
|
||||
openQuery={openQuery}
|
||||
isLoading={isLoading}
|
||||
rows={loadedRows}
|
||||
// rows={loadedRows}
|
||||
grider={grider}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
23
packages/web/src/datagrid/RowsArrayGrider.ts
Normal file
23
packages/web/src/datagrid/RowsArrayGrider.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import Grider, { GriderRowStatus } from './Grider';
|
||||
|
||||
export default class RowsArrayGrider extends Grider {
|
||||
constructor(private rows: any[]) {
|
||||
super();
|
||||
}
|
||||
getRowData(index: any) {
|
||||
return this.rows[index];
|
||||
}
|
||||
get rowCount() {
|
||||
return this.rows.length;
|
||||
}
|
||||
|
||||
static factory({ sourceRows }): RowsArrayGrider {
|
||||
return new RowsArrayGrider(sourceRows);
|
||||
}
|
||||
static factoryDeps({ sourceRows }) {
|
||||
return [sourceRows];
|
||||
}
|
||||
getRowsSample() {
|
||||
return this.rows;
|
||||
}
|
||||
}
|
@ -8,8 +8,9 @@ import ImportExportModal from '../modals/ImportExportModal';
|
||||
import { getChangeSetInsertedRows } from '@dbgate/datalib';
|
||||
import { openNewTab } from '../utility/common';
|
||||
import LoadingDataGridCore from './LoadingDataGridCore';
|
||||
import ChangeSetGrider from './ChangeSetGrider';
|
||||
|
||||
/** @param props {import('./types').LoadingDataGridProps} */
|
||||
/** @param props {import('./types').DataGridProps} */
|
||||
async function loadDataPage(props, offset, limit) {
|
||||
const { display, conid, database } = props;
|
||||
|
||||
@ -53,6 +54,7 @@ async function loadRowCount(props) {
|
||||
return parseInt(response.data.rows[0].count);
|
||||
}
|
||||
|
||||
/** @param props {import('./types').DataGridProps} */
|
||||
export default function SqlDataGridCore(props) {
|
||||
const { conid, database, display, changeSetState, dispatchChangeSet, tabVisible } = props;
|
||||
const showModal = useShowModal();
|
||||
@ -82,6 +84,8 @@ export default function SqlDataGridCore(props) {
|
||||
});
|
||||
}
|
||||
|
||||
// const grider = React.useMemo(()=>new ChangeSetGrider())
|
||||
|
||||
return (
|
||||
<LoadingDataGridCore
|
||||
{...props}
|
||||
@ -90,6 +94,8 @@ export default function SqlDataGridCore(props) {
|
||||
loadDataPage={loadDataPage}
|
||||
dataPageAvailable={dataPageAvailable}
|
||||
loadRowCount={loadRowCount}
|
||||
griderFactory={ChangeSetGrider.factory}
|
||||
griderFactoryDeps={ChangeSetGrider.factoryDeps}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -2,10 +2,11 @@ import _ from 'lodash';
|
||||
import { SeriesSizes } from './SeriesSizes';
|
||||
import { CellAddress } from './selection';
|
||||
import { GridDisplay } from '@dbgate/datalib';
|
||||
import Grider from './Grider';
|
||||
|
||||
export function countColumnSizes(loadedRows, columns, containerWidth, display: GridDisplay) {
|
||||
export function countColumnSizes(grider: Grider, columns, containerWidth, display: GridDisplay) {
|
||||
const columnSizes = new SeriesSizes();
|
||||
if (!loadedRows || !columns) return columnSizes;
|
||||
if (!grider || !columns) return columnSizes;
|
||||
|
||||
let canvas = document.createElement('canvas');
|
||||
let context = canvas.getContext('2d');
|
||||
@ -51,7 +52,8 @@ export function countColumnSizes(loadedRows, columns, containerWidth, display: G
|
||||
// if (headerWidth > this.rowHeaderWidth) this.rowHeaderWidth = headerWidth;
|
||||
|
||||
context.font = '14px Helvetica';
|
||||
for (let row of loadedRows.slice(0, 20)) {
|
||||
for (let rowIndex = 0; rowIndex < Math.min(grider.rowCount, 20); rowIndex += 1) {
|
||||
const row = grider.getRowData(rowIndex);
|
||||
for (let colIndex = 0; colIndex < columns.length; colIndex++) {
|
||||
const uqName = columns[colIndex].uniqueName;
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { GridDisplay, ChangeSet, GridReferenceDefinition } from '@dbgate/datalib';
|
||||
import Grider from './Grider';
|
||||
|
||||
export interface DataGridProps {
|
||||
display: GridDisplay;
|
||||
@ -12,28 +13,34 @@ export interface DataGridProps {
|
||||
refReloadToken?: string;
|
||||
masterLoadedTime?: number;
|
||||
managerSize?: number;
|
||||
}
|
||||
|
||||
export interface DataGridCoreProps extends DataGridProps {
|
||||
rows: any[];
|
||||
loadNextData?: Function;
|
||||
exportGrid?: Function;
|
||||
openQuery?: Function;
|
||||
undo?: Function;
|
||||
redo?: Function;
|
||||
|
||||
errorMessage?: string;
|
||||
isLoadedAll?: boolean;
|
||||
loadedTime?: any;
|
||||
allRowCount?: number;
|
||||
conid?: string;
|
||||
database?: string;
|
||||
insertedRowCount?: number;
|
||||
isLoading?: boolean;
|
||||
}
|
||||
|
||||
export interface LoadingDataGridProps extends DataGridProps {
|
||||
grider?: Grider;
|
||||
conid?: string;
|
||||
database?: string;
|
||||
jslid?: string;
|
||||
|
||||
[field: string]: any;
|
||||
}
|
||||
|
||||
// export interface DataGridCoreProps extends DataGridProps {
|
||||
// rows: any[];
|
||||
// loadNextData?: Function;
|
||||
// exportGrid?: Function;
|
||||
// openQuery?: Function;
|
||||
// undo?: Function;
|
||||
// redo?: Function;
|
||||
|
||||
// errorMessage?: string;
|
||||
// isLoadedAll?: boolean;
|
||||
// loadedTime?: any;
|
||||
// allRowCount?: number;
|
||||
// conid?: string;
|
||||
// database?: string;
|
||||
// insertedRowCount?: number;
|
||||
// isLoading?: boolean;
|
||||
// }
|
||||
|
||||
// export interface LoadingDataGridProps extends DataGridProps {
|
||||
// conid?: string;
|
||||
// database?: string;
|
||||
// jslid?: string;
|
||||
// }
|
||||
|
Loading…
Reference in New Issue
Block a user