mirror of
https://github.com/dbgate/dbgate
synced 2024-11-07 12:13:57 +00:00
use editor data
This commit is contained in:
parent
00d5b25baa
commit
f4fe5b9b53
@ -6,7 +6,7 @@
|
||||
</script>
|
||||
|
||||
<div bind:clientWidth bind:clientHeight class="ace-container">
|
||||
<AceEditorCore {...$$props} width={clientWidth} height={clientHeight} />
|
||||
<AceEditorCore {...$$props} width={clientWidth} height={clientHeight} on:input/>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
@ -18,4 +18,4 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<AceEditor {mode} />
|
||||
<AceEditor {mode} {...$$props} on:input />
|
||||
|
148
packages/web/src/query/useEditorData.ts
Normal file
148
packages/web/src/query/useEditorData.ts
Normal file
@ -0,0 +1,148 @@
|
||||
import _ from 'lodash';
|
||||
import { writable, derived } from 'svelte/store';
|
||||
import { onMount, onDestroy } from 'svelte';
|
||||
import localforage from 'localforage';
|
||||
import { changeTab } from '../utility/common';
|
||||
|
||||
function getParsedLocalStorage(key) {
|
||||
const value = localStorage.getItem(key);
|
||||
if (value != null) {
|
||||
try {
|
||||
const res = JSON.parse(value);
|
||||
return res;
|
||||
} catch (e) {
|
||||
// console.log('FAILED LOAD FROM STORAGE', e);
|
||||
// console.log('VALUE', value);
|
||||
localStorage.removeItem(key);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export default function useEditorData({ tabid, reloadToken = 0, loadFromArgs = null }) {
|
||||
const localStorageKey = `tabdata_editor_${tabid}`;
|
||||
let changeCounter = 0;
|
||||
let savedCounter = 0;
|
||||
|
||||
const editorState = writable({
|
||||
errorMessage: null,
|
||||
isLoading: true,
|
||||
value: null,
|
||||
});
|
||||
|
||||
const editorValue = derived(editorState, $state => $state.value);
|
||||
|
||||
let initialData = null;
|
||||
let value = null;
|
||||
|
||||
// const valueRef = React.useRef(null);
|
||||
|
||||
const initialLoad = async () => {
|
||||
if (loadFromArgs) {
|
||||
try {
|
||||
const init = await loadFromArgs();
|
||||
changeTab(tabid, tab => ({
|
||||
...tab,
|
||||
props: _.omit(tab.props, ['initialArgs']),
|
||||
}));
|
||||
editorState.update(x => ({
|
||||
...x,
|
||||
value: init,
|
||||
}));
|
||||
value = init;
|
||||
initialData = init;
|
||||
// mark as not saved
|
||||
changeCounter += 1;
|
||||
} catch (err) {
|
||||
const message = (err && err.response && err.response.data && err.response.data.error) || 'Loading failed';
|
||||
editorState.update(x => ({
|
||||
...x,
|
||||
errorMessage: message,
|
||||
}));
|
||||
console.error(err.response);
|
||||
}
|
||||
} else {
|
||||
const initFallback = getParsedLocalStorage(localStorageKey);
|
||||
if (initFallback != null) {
|
||||
editorState.update(x => ({
|
||||
...x,
|
||||
value: initFallback,
|
||||
}));
|
||||
value = initFallback;
|
||||
// move to local forage
|
||||
await localforage.setItem(localStorageKey, initFallback);
|
||||
localStorage.removeItem(localStorageKey);
|
||||
initialData = initFallback;
|
||||
} else {
|
||||
const init = await localforage.getItem(localStorageKey);
|
||||
if (init) {
|
||||
editorState.update(x => ({
|
||||
...x,
|
||||
value: init,
|
||||
}));
|
||||
value = init;
|
||||
initialData = init;
|
||||
}
|
||||
}
|
||||
}
|
||||
editorState.update(x => ({
|
||||
...x,
|
||||
isLoading: false,
|
||||
}));
|
||||
};
|
||||
|
||||
const saveToStorage = async () => {
|
||||
if (value == null) return;
|
||||
try {
|
||||
await localforage.setItem(localStorageKey, value);
|
||||
localStorage.removeItem(localStorageKey);
|
||||
savedCounter = changeCounter;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
};
|
||||
|
||||
const saveToStorageSync = () => {
|
||||
if (value == null) return;
|
||||
if (savedCounter == changeCounter) return; // all saved
|
||||
// on window unload must be synchronous actions, save to local storage instead
|
||||
localStorage.setItem(localStorageKey, JSON.stringify(value));
|
||||
};
|
||||
|
||||
const saveToStorageDebounced = _.debounce(saveToStorage, 5000);
|
||||
|
||||
const setEditorData = newValue => {
|
||||
if (_.isFunction(newValue)) {
|
||||
value = newValue(value);
|
||||
} else {
|
||||
if (newValue != null) value = newValue;
|
||||
}
|
||||
editorState.update(x => ({
|
||||
...x,
|
||||
value,
|
||||
}));
|
||||
|
||||
changeCounter += 1;
|
||||
saveToStorageDebounced();
|
||||
};
|
||||
|
||||
onMount(() => {
|
||||
window.addEventListener('beforeunload', saveToStorageSync);
|
||||
initialLoad();
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
saveToStorage();
|
||||
window.removeEventListener('beforeunload', saveToStorageSync);
|
||||
});
|
||||
|
||||
return {
|
||||
editorState,
|
||||
editorValue,
|
||||
setEditorData,
|
||||
initialData,
|
||||
saveToStorage,
|
||||
saveToStorageSync,
|
||||
initialLoad,
|
||||
};
|
||||
}
|
@ -1,17 +1,33 @@
|
||||
<script lang="ts">
|
||||
import VerticalSplitter from '../elements/VerticalSplitter.svelte';
|
||||
import SqlEditor from '../query/SqlEditor.svelte';
|
||||
import useEditorData from '../query/useEditorData';
|
||||
import { extensions } from '../stores';
|
||||
import applySqlTemplate from '../utility/applySqlTemplate';
|
||||
import { useConnectionInfo } from '../utility/metadataLoaders';
|
||||
|
||||
export let tabid;
|
||||
export let conid;
|
||||
export let database;
|
||||
export let initialArgs;
|
||||
|
||||
$: connection = useConnectionInfo({ conid });
|
||||
|
||||
const { editorState, setEditorData } = useEditorData({
|
||||
tabid,
|
||||
loadFromArgs:
|
||||
initialArgs && initialArgs.sqlTemplate
|
||||
? () => applySqlTemplate(initialArgs.sqlTemplate, $extensions, $$props)
|
||||
: null,
|
||||
});
|
||||
</script>
|
||||
|
||||
<VerticalSplitter>
|
||||
<svelte:fragment slot="1">
|
||||
<SqlEditor engine={$connection && $connection.engine} />
|
||||
<SqlEditor
|
||||
engine={$connection && $connection.engine}
|
||||
value={$editorState.value || ''}
|
||||
on:input={e => setEditorData(e.detail)}
|
||||
/>
|
||||
</svelte:fragment>
|
||||
</VerticalSplitter>
|
||||
|
32
packages/web/src/utility/applySqlTemplate.ts
Normal file
32
packages/web/src/utility/applySqlTemplate.ts
Normal file
@ -0,0 +1,32 @@
|
||||
import { getDbCore, getConnectionInfo, getSqlObjectInfo } from './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;
|
||||
}
|
@ -1,9 +1,7 @@
|
||||
import { openedTabs } from '../stores';
|
||||
|
||||
export class LoadingToken {
|
||||
constructor() {
|
||||
this.isCanceled = false;
|
||||
}
|
||||
isCanceled = false;
|
||||
|
||||
cancel() {
|
||||
this.isCanceled = true;
|
||||
@ -14,8 +12,8 @@ export function sleep(milliseconds) {
|
||||
return new Promise(resolve => window.setTimeout(() => resolve(null), milliseconds));
|
||||
}
|
||||
|
||||
export function changeTab(tabid, setOpenedTabs, changeFunc) {
|
||||
setOpenedTabs(files => files.map(tab => (tab.tabid == tabid ? changeFunc(tab) : tab)));
|
||||
export function changeTab(tabid, changeFunc) {
|
||||
openedTabs.update(files => files.map(tab => (tab.tabid == tabid ? changeFunc(tab) : tab)));
|
||||
}
|
||||
|
||||
export function setSelectedTabFunc(files, tabid) {
|
@ -13,5 +13,7 @@
|
||||
"strictNullChecks": false,
|
||||
"strict": false,
|
||||
"target": "es6",
|
||||
// "allowJs": true,
|
||||
// "checkJs": true,
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user