diff --git a/packages/api/src/proc/sessionProcess.js b/packages/api/src/proc/sessionProcess.js index a15bb3f83..ef15c74af 100644 --- a/packages/api/src/proc/sessionProcess.js +++ b/packages/api/src/proc/sessionProcess.js @@ -19,7 +19,7 @@ class TableWriter { this.jslid = uuidv1(); this.currentFile = path.join(jsldir(), `${this.jslid}.jsonl`); this.currentRowCount = 0; - this.currentChangeIndex = 0; + this.currentChangeIndex = 1; fs.writeFileSync(this.currentFile, JSON.stringify({ columns }) + '\n'); this.currentStream = fs.createWriteStream(this.currentFile, { flags: 'a' }); this.writeCurrentStats(false, false); diff --git a/packages/web/src/datagrid/ChangeSetDataGrid.js b/packages/web/src/datagrid/ChangeSetDataGrid.js deleted file mode 100644 index 3c20ec515..000000000 --- a/packages/web/src/datagrid/ChangeSetDataGrid.js +++ /dev/null @@ -1,17 +0,0 @@ -import { getChangeSetInsertedRows } from '@dbgate/datalib'; -import React from 'react'; -import DataGridCore from './DataGridCore'; - -export default function ChangeSetDataGrid(props) { - const { changeSet, display, dispatchChangeSet } = props; - function undo() { - dispatchChangeSet({ type: 'undo' }); - } - function redo() { - dispatchChangeSet({ type: 'redo' }); - } - - const insertedRows = getChangeSetInsertedRows(changeSet, display.baseTable); - - return ; -} diff --git a/packages/web/src/datagrid/DataGrid.js b/packages/web/src/datagrid/DataGrid.js index f7cfb19c4..c03078fc1 100644 --- a/packages/web/src/datagrid/DataGrid.js +++ b/packages/web/src/datagrid/DataGrid.js @@ -15,7 +15,6 @@ import { } from './ManagerStyles'; import ReferenceManager from './ReferenceManager'; import { HorizontalSplitter } from '../widgets/Splitter'; -import LoadingDataGrid from './LoadingDataGrid'; const MainContainer = styled.div` position: absolute; @@ -42,8 +41,8 @@ const DataGridContainer = styled.div` flex-grow: 1; `; -/** @param props {import('./types').LoadingDataGridProps} */ export default function DataGrid(props) { + const { GridCore } = props; const Container1 = props.showReferences ? ManagerOuterContainer1 : ManagerOuterContainerFull; const [managerSize, setManagerSize] = React.useState(0); return ( @@ -62,7 +61,7 @@ export default function DataGrid(props) { - + diff --git a/packages/web/src/datagrid/DataGridCore.js b/packages/web/src/datagrid/DataGridCore.js index d67480e8c..6edaf3e5d 100644 --- a/packages/web/src/datagrid/DataGridCore.js +++ b/packages/web/src/datagrid/DataGridCore.js @@ -145,8 +145,6 @@ export default function DataGridCore(props) { openQuery, insertedRowCount, isLoading, - undo, - redo } = props; // console.log('RENDER GRID', display.baseTable.pureName); const columns = React.useMemo(() => display.allColumns, [display]); @@ -687,6 +685,13 @@ export default function DataGridCore(props) { setvScrollValueToSetDate(new Date()); } + function undo() { + dispatchChangeSet({ type: 'undo' }); + } + function redo() { + dispatchChangeSet({ type: 'redo' }); + } + function handleSave() { if (inplaceEditorState.cell) { // @ts-ignore diff --git a/packages/web/src/datagrid/JslDataGridCore.js b/packages/web/src/datagrid/JslDataGridCore.js new file mode 100644 index 000000000..53ae17505 --- /dev/null +++ b/packages/web/src/datagrid/JslDataGridCore.js @@ -0,0 +1,93 @@ +import React from 'react'; +import axios from '../utility/axios'; +import { useSetOpenedTabs } from '../utility/globalState'; +import DataGridCore from './DataGridCore'; +import useSocket from '../utility/SocketProvider'; +import useShowModal from '../modals/showModal'; +import ImportExportModal from '../modals/ImportExportModal'; +import { getChangeSetInsertedRows } from '@dbgate/datalib'; +import { openNewTab } from '../utility/common'; +import LoadingDataGridCore from './LoadingDataGridCore'; + +async function loadDataPage(props, offset, limit) { + const { jslid } = props; + + const response = await axios.request({ + url: 'jsldata/get-rows', + method: 'get', + params: { + jslid, + offset, + limit, + }, + }); + return response.data; +} + +function dataPageAvailable(props) { + return true; +} + +async function loadRowCount(props) { + const { jslid } = props; + + const response = await axios.request({ + url: 'jsldata/get-stats', + method: 'get', + params: { + jslid, + }, + }); + return response.data.rowCount; +} + +export default function JslDataGridCore(props) { + const { jslid } = props; + const [changeIndex, setChangeIndex] = React.useState(0); + + const showModal = useShowModal(); + + const setOpenedTabs = useSetOpenedTabs(); + const socket = useSocket(); + + function exportGrid() { + const initialValues = {}; + const archiveMatch = jslid.match(/^archive:\/\/([^/]+)\/(.*)$/); + if (archiveMatch) { + initialValues.sourceStorageType = 'archive'; + initialValues.sourceArchiveFolder = archiveMatch[1]; + initialValues.sourceList = [archiveMatch[2]]; + } else { + initialValues.sourceStorageType = 'jsldata'; + initialValues.sourceJslId = jslid; + initialValues.sourceList = ['query-data']; + } + showModal((modalState) => ); + } + + const handleJslDataStats = React.useCallback((stats) => { + if (stats.changeIndex < changeIndex) return; + setChangeIndex(stats.changeIndex); + }, [changeIndex]); + + React.useEffect(() => { + if (jslid && socket) { + socket.on(`jsldata-stats-${jslid}`, handleJslDataStats); + return () => { + socket.off(`jsldata-stats-${jslid}`, handleJslDataStats); + }; + } + }, [jslid]); + + return ( + setChangeIndex(0)} + /> + ); +} diff --git a/packages/web/src/datagrid/LoadingDataGrid.js b/packages/web/src/datagrid/LoadingDataGridCore.js similarity index 69% rename from packages/web/src/datagrid/LoadingDataGrid.js rename to packages/web/src/datagrid/LoadingDataGridCore.js index d08ce67ea..9b87ff74f 100644 --- a/packages/web/src/datagrid/LoadingDataGrid.js +++ b/packages/web/src/datagrid/LoadingDataGridCore.js @@ -6,7 +6,6 @@ import useSocket from '../utility/SocketProvider'; import useShowModal from '../modals/showModal'; import ImportExportModal from '../modals/ImportExportModal'; import { getChangeSetInsertedRows } from '@dbgate/datalib'; -import ChangeSetDataGrid from './ChangeSetDataGrid'; import { openNewTab } from '../utility/common'; /** @param props {import('./types').LoadingDataGridProps} */ @@ -79,8 +78,20 @@ async function loadRowCount(props) { return parseInt(response.data.rows[0].count); } -export default function LoadingDataGrid(props) { - const { conid, database, display, changeSetState, dispatchChangeSet, tabVisible, jslid } = props; +export default function LoadingDataGridCore(props) { + const { + display, + changeSetState, + dispatchChangeSet, + tabVisible, + loadDataPage, + dataPageAvailable, + loadRowCount, + loadNextDataToken, + onReload, + exportGrid, + openQuery, + } = props; const [loadProps, setLoadProps] = React.useState({ isLoading: false, @@ -89,8 +100,7 @@ export default function LoadingDataGrid(props) { loadedTime: new Date().getTime(), allRowCount: null, errorMessage: null, - jslStatsCounter: 0, - jslChangeIndex: 0, + loadNextDataToken: 0, }); const { isLoading, loadedRows, isLoadedAll, loadedTime, allRowCount, errorMessage } = loadProps; const showModal = useShowModal(); @@ -122,34 +132,11 @@ export default function LoadingDataGrid(props) { isLoadedAll: false, loadedTime: new Date().getTime(), errorMessage: null, - jslStatsCounter: 0, - jslChangeIndex: 0, + loadNextDataToken: 0, }); + if (onReload) onReload(); }; - function exportGrid() { - const initialValues = {}; - if (jslid) { - const archiveMatch = jslid.match(/^archive:\/\/([^/]+)\/(.*)$/); - if (archiveMatch) { - initialValues.sourceStorageType = 'archive'; - initialValues.sourceArchiveFolder = archiveMatch[1]; - initialValues.sourceList = [archiveMatch[2]]; - } else { - initialValues.sourceStorageType = 'jsldata'; - initialValues.sourceJslId = jslid; - initialValues.sourceList = ['query-data']; - } - } else { - initialValues.sourceStorageType = 'query'; - initialValues.sourceConnectionId = conid; - initialValues.sourceDatabaseName = database; - initialValues.sourceSql = display.getExportQuery(); - initialValues.sourceList = display.baseTable ? [display.baseTable.pureName] : []; - } - showModal((modalState) => ); - } - React.useEffect(() => { if (props.masterLoadedTime && props.masterLoadedTime > loadedTime) { display.reload(); @@ -193,31 +180,19 @@ export default function LoadingDataGrid(props) { setLoadProps((oldLoadProps) => ({ ...oldLoadProps, isLoading: false, - isLoadedAll: oldLoadProps.jslStatsCounter == loadProps.jslStatsCounter && nextRows.length === 0, + isLoadedAll: oldLoadProps.loadNextDataToken == loadNextDataToken && nextRows.length === 0, + loadNextDataToken, ...loadedInfo, })); } }; - const handleJslDataStats = React.useCallback((stats) => { - if (stats.changeIndex < loadProps.jslChangeIndex) return; + React.useEffect(()=>{ setLoadProps((oldProps) => ({ ...oldProps, - allRowCount: stats.rowCount, isLoadedAll: false, - jslStatsCounter: oldProps.jslStatsCounter + 1, - jslChangeIndex: stats.changeIndex, })); - }, []); - - React.useEffect(() => { - if (jslid && socket) { - socket.on(`jsldata-stats-${jslid}`, handleJslDataStats); - return () => { - socket.off(`jsldata-stats-${jslid}`, handleJslDataStats); - }; - } - }, [jslid]); + },[loadNextDataToken]); const insertedRows = getChangeSetInsertedRows(changeSet, display.baseTable); const rowCountNewIncluded = loadedRows.length + insertedRows.length; @@ -231,23 +206,8 @@ export default function LoadingDataGrid(props) { } }; - function openQuery() { - openNewTab(setOpenedTabs, { - title: 'Query', - icon: 'sql.svg', - tabComponent: 'QueryTab', - props: { - initialScript: display.getExportQuery(), - schemaName: display.baseTable.schemaName, - pureName: display.baseTable.pureName, - conid, - database, - }, - }); - } - return ( - diff --git a/packages/web/src/datagrid/SqlDataGridCore.js b/packages/web/src/datagrid/SqlDataGridCore.js new file mode 100644 index 000000000..c44711124 --- /dev/null +++ b/packages/web/src/datagrid/SqlDataGridCore.js @@ -0,0 +1,95 @@ +import React from 'react'; +import axios from '../utility/axios'; +import { useSetOpenedTabs } from '../utility/globalState'; +import DataGridCore from './DataGridCore'; +import useSocket from '../utility/SocketProvider'; +import useShowModal from '../modals/showModal'; +import ImportExportModal from '../modals/ImportExportModal'; +import { getChangeSetInsertedRows } from '@dbgate/datalib'; +import { openNewTab } from '../utility/common'; +import LoadingDataGridCore from './LoadingDataGridCore'; + +/** @param props {import('./types').LoadingDataGridProps} */ +async function loadDataPage(props, offset, limit) { + const { display, conid, database } = props; + + const sql = display.getPageQuery(offset, limit); + + 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; +} + +function dataPageAvailable(props) { + const { display } = props; + const sql = display.getPageQuery(0, 1); + return !!sql; +} + +async function loadRowCount(props) { + const { display, conid, database } = props; + + const sql = display.getCountQuery(); + + const response = await axios.request({ + url: 'database-connections/query-data', + method: 'post', + params: { + conid, + database, + }, + data: { sql }, + }); + + return parseInt(response.data.rows[0].count); +} + +export default function SqlDataGridCore(props) { + const { conid, database, display, changeSetState, dispatchChangeSet, tabVisible } = props; + const showModal = useShowModal(); + const setOpenedTabs = useSetOpenedTabs(); + + function exportGrid() { + const initialValues = {}; + initialValues.sourceStorageType = 'query'; + initialValues.sourceConnectionId = conid; + initialValues.sourceDatabaseName = database; + initialValues.sourceSql = display.getExportQuery(); + initialValues.sourceList = display.baseTable ? [display.baseTable.pureName] : []; + showModal((modalState) => ); + } + function openQuery() { + openNewTab(setOpenedTabs, { + title: 'Query', + icon: 'sql.svg', + tabComponent: 'QueryTab', + props: { + initialScript: display.getExportQuery(), + schemaName: display.baseTable.schemaName, + pureName: display.baseTable.pureName, + conid, + database, + }, + }); + } + + return ( + + ); +} diff --git a/packages/web/src/datagrid/TableDataGrid.js b/packages/web/src/datagrid/TableDataGrid.js index 685465fe6..0f2fd147c 100644 --- a/packages/web/src/datagrid/TableDataGrid.js +++ b/packages/web/src/datagrid/TableDataGrid.js @@ -10,6 +10,7 @@ import useSocket from '../utility/SocketProvider'; import { VerticalSplitter } from '../widgets/Splitter'; import stableStringify from 'json-stable-stringify'; import ReferenceHeader from './ReferenceHeader'; +import SqlDataGridCore from './SqlDataGridCore'; const ReferenceContainer = styled.div` position: absolute; @@ -162,6 +163,7 @@ export default function TableDataGrid({ onReferenceSourceChanged={reference ? handleReferenceSourceChanged : null} refReloadToken={refReloadToken.toString()} masterLoadedTime={masterLoadedTime} + GridCore={SqlDataGridCore} /> {reference && ( diff --git a/packages/web/src/sqleditor/JslDataGrid.js b/packages/web/src/sqleditor/JslDataGrid.js index ad4dd3378..192c0ce03 100644 --- a/packages/web/src/sqleditor/JslDataGrid.js +++ b/packages/web/src/sqleditor/JslDataGrid.js @@ -2,6 +2,7 @@ import React from 'react'; import DataGrid from '../datagrid/DataGrid'; import { JslGridDisplay, createGridConfig, createGridCache } from '@dbgate/datalib'; import useFetch from '../utility/useFetch'; +import JslDataGridCore from '../datagrid/JslDataGridCore'; export default function JslDataGrid({ jslid }) { const info = useFetch({ @@ -19,5 +20,5 @@ export default function JslDataGrid({ jslid }) { cache, ]); - return ; + return ; } diff --git a/packages/web/src/tabs/ViewDataTab.js b/packages/web/src/tabs/ViewDataTab.js index ca134c2fa..14d0c546f 100644 --- a/packages/web/src/tabs/ViewDataTab.js +++ b/packages/web/src/tabs/ViewDataTab.js @@ -10,6 +10,7 @@ import useUndoReducer from '../utility/useUndoReducer'; import usePropsCompare from '../utility/usePropsCompare'; import { useUpdateDatabaseForTab } from '../utility/globalState'; import useGridConfig from '../utility/useGridConfig'; +import SqlDataGridCore from '../datagrid/SqlDataGridCore'; export default function ViewDataTab({ conid, database, schemaName, pureName, tabVisible, toolbarPortalRef, tabid }) { const viewInfo = useViewInfo({ conid, database, schemaName, pureName }); @@ -50,6 +51,7 @@ export default function ViewDataTab({ conid, database, schemaName, pureName, tab changeSetState={changeSetState} dispatchChangeSet={dispatchChangeSet} toolbarPortalRef={toolbarPortalRef} - /> + GridCore={SqlDataGridCore} + /> ); }