use editor data optimalizactions

This commit is contained in:
Jan Prochazka 2020-12-03 17:24:37 +01:00
parent d23a013579
commit 5df650bc51
4 changed files with 70 additions and 75 deletions

View File

@ -18,34 +18,27 @@ import SaveTabModal from '../modals/SaveTabModal';
import useModalState from '../modals/useModalState'; import useModalState from '../modals/useModalState';
import sqlFormatter from 'sql-formatter'; import sqlFormatter from 'sql-formatter';
import useEditorData from '../utility/useEditorData'; import useEditorData from '../utility/useEditorData';
import useSqlTemplate from '../utility/useSqlTemplate'; import applySqlTemplate from '../utility/applySqlTemplate';
import LoadingInfo from '../widgets/LoadingInfo'; import LoadingInfo from '../widgets/LoadingInfo';
import useExtensions from '../utility/useExtensions';
export default function QueryTab({ tabid, conid, database, initialArgs, tabVisible, toolbarPortalRef, ...other }) { export default function QueryTab({ tabid, conid, database, initialArgs, tabVisible, toolbarPortalRef, ...other }) {
const { sqlTemplate } = initialArgs || {};
const [sessionId, setSessionId] = React.useState(null); const [sessionId, setSessionId] = React.useState(null);
const [executeNumber, setExecuteNumber] = React.useState(0); const [executeNumber, setExecuteNumber] = React.useState(0);
const setOpenedTabs = useSetOpenedTabs(); const setOpenedTabs = useSetOpenedTabs();
const socket = useSocket(); const socket = useSocket();
const [busy, setBusy] = React.useState(false); const [busy, setBusy] = React.useState(false);
const saveFileModalState = useModalState(); const saveFileModalState = useModalState();
const { editorData, setEditorData, isLoading } = useEditorData(tabid); const extensions = useExtensions();
const { editorData, setEditorData, isLoading } = useEditorData({
tabid,
loadFromArgs: initialArgs && initialArgs.sqlTemplate
? () => applySqlTemplate(initialArgs.sqlTemplate, extensions, { conid, database, ...other })
: null,
});
const [sqlFromTemplate, isLoadingTemplate] = useSqlTemplate(sqlTemplate, { conid, database, ...other });
const editorRef = React.useRef(null); const editorRef = React.useRef(null);
React.useEffect(() => {
if (sqlFromTemplate && sqlTemplate) {
setEditorData(sqlFromTemplate);
// editorRef.current.editor.setValue(sqlFromTemplate);
// editorRef.current.editor.clearSelection();
changeTab(tabid, setOpenedTabs, (tab) => ({
...tab,
props: _.omit(tab.props, ['initialArgs']),
}));
}
}, [sqlFromTemplate]);
const handleSessionDone = React.useCallback(() => { const handleSessionDone = React.useCallback(() => {
setBusy(false); setBusy(false);
}, []); }, []);
@ -120,7 +113,7 @@ export default function QueryTab({ tabid, conid, database, initialArgs, tabVisib
editorRef.current.editor.clearSelection(); editorRef.current.editor.clearSelection();
}; };
if (isLoading || isLoadingTemplate) if (isLoading)
return ( return (
<div> <div>
<LoadingInfo message="Loading SQL script" /> <LoadingInfo message="Loading SQL script" />

View File

@ -0,0 +1,32 @@
import { getDbCore, getConnectionInfo, getSqlObjectInfo } from '../utility/metadataLoaders';
import sqlFormatter from 'sql-formatter';
import { driverBase, findEngineDriver } from 'dbgate-tools';
export default async function applySqlTemplate(sqlTemplate, extensions, props) {
if (sqlTemplate == 'CREATE TABLE') {
const tableInfo = await getDbCore(props, props.objectTypeField || 'tables');
const connection = await getConnectionInfo(props);
const driver = findEngineDriver(connection, extensions) || driverBase;
const dmp = driver.createDumper();
if (tableInfo) dmp.createTable(tableInfo);
return dmp.s;
}
if (sqlTemplate == 'CREATE OBJECT') {
const objectInfo = await getSqlObjectInfo(props);
if (objectInfo) {
if (objectInfo.requiresFormat && objectInfo.createSql) return sqlFormatter.format(objectInfo.createSql);
else return objectInfo.createSql;
}
}
if (sqlTemplate == 'EXECUTE PROCEDURE') {
const procedureInfo = await getSqlObjectInfo(props);
const connection = await getConnectionInfo(props);
const driver = findEngineDriver(connection, extensions) || driverBase;
const dmp = driver.createDumper();
if (procedureInfo) dmp.put('^execute %f', procedureInfo);
return dmp.s;
}
return null;
}

View File

@ -1,29 +1,44 @@
import React from 'react'; import React from 'react';
import _ from 'lodash'; import _ from 'lodash';
import localforage from 'localforage'; import localforage from 'localforage';
import { changeTab } from './common';
import { useSetOpenedTabs } from './globalState';
export default function useEditorData(tabid, initialData = null) { export default function useEditorData({ tabid, loadFromArgs }) {
const localStorageKey = `tabdata_${tabid}`; const localStorageKey = `tabdata_${tabid}`;
const setOpenedTabs = useSetOpenedTabs();
const changeCounterRef = React.useRef(0);
const savedCounterRef = React.useRef(0);
const [value, setValue] = React.useState(initialData); const [value, setValue] = React.useState(null);
const [isLoading, setIsLoading] = React.useState(true); const [isLoading, setIsLoading] = React.useState(true);
const valueRef = React.useRef(null); const valueRef = React.useRef(null);
const initialLoad = async () => { const initialLoad = async () => {
const initFallback = localStorage.getItem(localStorageKey); if (loadFromArgs) {
if (initFallback != null) { const init = await loadFromArgs();
const init = JSON.parse(initFallback); changeTab(tabid, setOpenedTabs, (tab) => ({
...tab,
props: _.omit(tab.props, ['initialArgs']),
}));
setValue(init); setValue(init);
valueRef.current = init; valueRef.current = init;
// move to local forage
await localforage.setItem(localStorageKey, init);
localStorage.removeItem(localStorageKey);
} else { } else {
const init = await localforage.getItem(localStorageKey); const initFallback = localStorage.getItem(localStorageKey);
if (init) { if (initFallback != null) {
const init = JSON.parse(initFallback);
setValue(init); setValue(init);
valueRef.current = init; valueRef.current = init;
// move to local forage
await localforage.setItem(localStorageKey, init);
localStorage.removeItem(localStorageKey);
} else {
const init = await localforage.getItem(localStorageKey);
if (init) {
setValue(init);
valueRef.current = init;
}
} }
} }
setIsLoading(false); setIsLoading(false);
@ -37,6 +52,7 @@ export default function useEditorData(tabid, initialData = null) {
if (valueRef.current == null) return; if (valueRef.current == null) return;
try { try {
await localforage.setItem(localStorageKey, valueRef.current); await localforage.setItem(localStorageKey, valueRef.current);
savedCounterRef.current = changeCounterRef.current;
} catch (err) { } catch (err) {
console.error(err); console.error(err);
} }
@ -44,6 +60,7 @@ export default function useEditorData(tabid, initialData = null) {
const saveToStorageFallback = React.useCallback(() => { const saveToStorageFallback = React.useCallback(() => {
if (valueRef.current == null) return; if (valueRef.current == null) return;
if (savedCounterRef.current == changeCounterRef.current) return; // all saved
// on window unload must be synchronous actions, save to local storage instead // on window unload must be synchronous actions, save to local storage instead
localStorage.setItem(localStorageKey, JSON.stringify(valueRef.current)); localStorage.setItem(localStorageKey, JSON.stringify(valueRef.current));
}, [localStorageKey, valueRef]); }, [localStorageKey, valueRef]);
@ -53,6 +70,7 @@ export default function useEditorData(tabid, initialData = null) {
const handleChange = (newValue) => { const handleChange = (newValue) => {
if (newValue != null) valueRef.current = newValue; if (newValue != null) valueRef.current = newValue;
setValue(newValue); setValue(newValue);
changeCounterRef.current += 1;
saveToStorageDebounced(); saveToStorageDebounced();
}; };

View File

@ -1,48 +0,0 @@
import React from 'react';
import { getDbCore, getConnectionInfo, getSqlObjectInfo } from '../utility/metadataLoaders';
import sqlFormatter from 'sql-formatter';
import useExtensions from '../utility/useExtensions';
import { driverBase, findEngineDriver } from 'dbgate-tools';
export default function useSqlTemplate(sqlTemplate, props) {
const [sql, setSql] = React.useState('');
const extensions = useExtensions();
const [isLoading, setIsLoading] = React.useState(!!sqlTemplate);
async function loadTemplate() {
if (sqlTemplate == 'CREATE TABLE') {
const tableInfo = await getDbCore(props, props.objectTypeField || 'tables');
const connection = await getConnectionInfo(props);
const driver = findEngineDriver(connection, extensions) || driverBase;
const dmp = driver.createDumper();
if (tableInfo) dmp.createTable(tableInfo);
setSql(dmp.s);
}
if (sqlTemplate == 'CREATE OBJECT') {
const objectInfo = await getSqlObjectInfo(props);
if (objectInfo) {
if (objectInfo.requiresFormat && objectInfo.createSql) setSql(sqlFormatter.format(objectInfo.createSql));
else setSql(objectInfo.createSql);
}
}
if (sqlTemplate == 'EXECUTE PROCEDURE') {
const procedureInfo = await getSqlObjectInfo(props);
const connection = await getConnectionInfo(props);
const driver = findEngineDriver(connection, extensions) || driverBase;
const dmp = driver.createDumper();
if (procedureInfo) dmp.put('^execute %f', procedureInfo);
setSql(dmp.s);
}
setIsLoading(false);
}
React.useEffect(() => {
if (sqlTemplate) {
loadTemplate();
}
}, []);
return [sql, isLoading];
}