diff --git a/packages/datalib/src/GridDisplay.ts b/packages/datalib/src/GridDisplay.ts index cbaeddfd..f9683262 100644 --- a/packages/datalib/src/GridDisplay.ts +++ b/packages/datalib/src/GridDisplay.ts @@ -1,9 +1,14 @@ import GridConfig from "./GridConfig"; +export interface DisplayColumn { + columnName: string; +} + export default abstract class GridDisplay { constructor( public config: GridConfig, protected setConfig: (configh: GridConfig) => void ) {} abstract getPageQuery(offset: number, count: number): string; + columns: DisplayColumn[]; } diff --git a/packages/datalib/src/TableGridDisplay.ts b/packages/datalib/src/TableGridDisplay.ts index 69d4a0d2..a8507e8e 100644 --- a/packages/datalib/src/TableGridDisplay.ts +++ b/packages/datalib/src/TableGridDisplay.ts @@ -1,12 +1,7 @@ -import GridDisplay from "./GridDisplay"; -import { - Select, - treeToSql, - dumpSqlSelect, - createColumnResultField -} from "@dbgate/sqltree"; -import { TableInfo, EngineDriver } from "@dbgate/types"; -import GridConfig from "./GridConfig"; +import GridDisplay from './GridDisplay'; +import { Select, treeToSql, dumpSqlSelect, createColumnResultField } from '@dbgate/sqltree'; +import { TableInfo, EngineDriver } from '@dbgate/types'; +import GridConfig from './GridConfig'; export default class TableGridDisplay extends GridDisplay { constructor( @@ -16,17 +11,16 @@ export default class TableGridDisplay extends GridDisplay { setConfig: (configh: GridConfig) => void ) { super(config, setConfig); + this.columns = table.columns; } createSelect() { const select: Select = { - commandType: "select", + commandType: 'select', from: { - source: { name: this.table } + source: { name: this.table }, }, - columns: this.table.columns.map(col => - createColumnResultField(col.columnName) - ) + columns: this.table.columns.map(col => createColumnResultField(col.columnName)), }; return select; } @@ -34,8 +28,7 @@ export default class TableGridDisplay extends GridDisplay { getPageQuery(offset: number, count: number) { const select = this.createSelect(); if (this.driver.dialect.limitSelect) select.topRecords = count; - if (this.driver.dialect.rangeSelect) - select.range = { offset: offset, limit: count }; + if (this.driver.dialect.rangeSelect) select.range = { offset: offset, limit: count }; const sql = treeToSql(this.driver, select, dumpSqlSelect); return sql; } diff --git a/packages/datalib/src/index.ts b/packages/datalib/src/index.ts index 906defb8..67440163 100644 --- a/packages/datalib/src/index.ts +++ b/packages/datalib/src/index.ts @@ -1,2 +1,2 @@ -export { default as GridDisplay } from "./GridDisplay"; +export { default as GridDisplay, DisplayColumn } from "./GridDisplay"; export { default as TableGridDisplay } from "./TableGridDisplay"; diff --git a/packages/web/src/datagrid/DataGrid.js b/packages/web/src/datagrid/DataGrid.js index ee25a57c..4b5d8dd4 100644 --- a/packages/web/src/datagrid/DataGrid.js +++ b/packages/web/src/datagrid/DataGrid.js @@ -5,6 +5,7 @@ import theme from '../theme'; import { HorizontalScrollBar, VerticalScrollBar } from './ScrollBars'; import useDimensions from '../utility/useDimensions'; import { SeriesSizes } from './SeriesSizes'; +import axios from '../utility/axios'; const GridContainer = styled.div` position: absolute; @@ -71,20 +72,71 @@ const TableBodyCell = styled.td` */ export default function DataGrid(props) { const { conid, database, display } = props; - const sql = display.getPageQuery(0, 100); + const columns = display.columns; - console.log(`GRID, conid=${conid}, database=${database}, sql=${sql}`); - - const data = useFetch({ - url: 'database-connections/query-data', - method: 'post', - params: { - conid, - database, - }, - data: { sql }, + // console.log(`GRID, conid=${conid}, database=${database}, sql=${sql}`); + const [loadProps, setLoadProps] = React.useState({ + isLoading: false, + loadedRows: [], + isLoadedAll: false, + loadedTime: new Date().getTime(), }); - const { rows, columns } = data || {}; + const { isLoading, loadedRows, isLoadedAll, loadedTime } = loadProps; + + const loadedTimeRef = React.useRef(0); + + const loadNextData = async () => { + if (isLoading) return; + setLoadProps({ + ...loadProps, + isLoading: true, + }); + const loadStart = new Date().getTime(); + loadedTimeRef.current = loadStart; + + const sql = display.getPageQuery(loadedRows.length, 100); + + let response = await axios.request({ + url: 'database-connections/query-data', + method: 'post', + params: { + conid, + database, + }, + data: { sql }, + }); + if (loadedTimeRef.current !== loadStart) { + // new load was dispatched + return; + } + // if (!_.isArray(nextRows)) { + // console.log('Error loading data from server', nextRows); + // nextRows = []; + // } + const { rows: nextRows } = response.data; + console.log('nextRows',nextRows) + const loadedInfo = { + loadedRows: [...loadedRows, ...nextRows], + loadedTime, + isLoadedAll: nextRows.length === 0, + }; + setLoadProps({ + ...loadProps, + isLoading: false, + ...loadedInfo, + }); + }; + + // const data = useFetch({ + // url: 'database-connections/query-data', + // method: 'post', + // params: { + // conid, + // database, + // }, + // data: { sql }, + // }); + // const { rows, columns } = data || {}; const [firstVisibleRowScrollIndex, setFirstVisibleRowScrollIndex] = React.useState(0); const [firstVisibleColumnScrollIndex, setFirstVisibleColumnScrollIndex] = React.useState(0); @@ -92,7 +144,7 @@ export default function DataGrid(props) { const [tableBodyRef] = useDimensions(); const [containerRef, { height: containerHeight, width: containerWidth }] = useDimensions(); - const columnSizes = React.useMemo(() => countColumnSizes(), [data, containerWidth]); + const columnSizes = React.useMemo(() => countColumnSizes(), [loadedRows, containerWidth]); console.log('containerWidth', containerWidth); @@ -104,8 +156,14 @@ export default function DataGrid(props) { // const visibleRowCountUpperBound = 20; // const visibleRowCountLowerBound = 20; - if (!columns || !rows) return null; - const rowCountNewIncluded = rows.length; + React.useEffect(() => { + if (!isLoadedAll && firstVisibleRowScrollIndex + visibleRowCountUpperBound >= loadedRows.length) { + loadNextData(); + } + }); + + if (!loadedRows || !columns) return null; + const rowCountNewIncluded = loadedRows.length; const handleRowScroll = value => { setFirstVisibleRowScrollIndex(value); @@ -121,9 +179,9 @@ export default function DataGrid(props) { //return this.context.measureText(txt).width; const columnSizes = new SeriesSizes(); - if (!rows || !columns) return columnSizes; + if (!loadedRows || !columns) return columnSizes; - console.log('countColumnSizes', rows.length, containerWidth); + console.log('countColumnSizes', loadedRows.length, containerWidth); columnSizes.maxSize = (containerWidth * 2) / 3; columnSizes.count = columns.length; @@ -139,7 +197,7 @@ export default function DataGrid(props) { // else context.font = "14px Helvetica"; context.font = 'bold 14px Helvetica'; - let text = column.name; + let text = column.columnName; let headerWidth = context.measureText(text).width + 32; // if (column.columnClientObject != null && column.columnClientObject.icon != null) headerWidth += 16; @@ -155,9 +213,9 @@ export default function DataGrid(props) { // if (headerWidth > this.rowHeaderWidth) this.rowHeaderWidth = headerWidth; context.font = '14px Helvetica'; - for (let row of data.rows) { + for (let row of loadedRows) { for (let colIndex = 0; colIndex < columns.length; colIndex++) { - let colName = columns[colIndex].name; + let colName = columns[colIndex].columnName; let text = row[colName]; let width = context.measureText(text).width + 8; // console.log('colName', colName, text, width); @@ -188,6 +246,7 @@ export default function DataGrid(props) { const visibleRealColumnIndexes = []; const modelIndexes = {}; + /** @type {(import('@dbgate/datalib').DisplayColumn & {widthPx: string})[]} */ const realColumns = []; // frozen columns @@ -226,25 +285,25 @@ export default function DataGrid(props) { {realColumns.map(col => ( - {col.name} + {col.columnName} ))} - {rows + {loadedRows .slice(firstVisibleRowScrollIndex, firstVisibleRowScrollIndex + visibleRowCountUpperBound) .map((row, index) => ( {realColumns.map(col => ( - {row[col.name]} + {row[col.columnName]} ))}