mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-24 15:15:59 +00:00
export working
This commit is contained in:
@@ -31,6 +31,9 @@ body {
|
|||||||
.icon-invisible {
|
.icon-invisible {
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
|
.space-between {
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
.flex {
|
.flex {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,24 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { writable } from 'svelte/store';
|
||||||
|
|
||||||
|
import TableControl from '../elements/TableControl.svelte';
|
||||||
|
import { getFormContext } from '../forms/FormProviderCore.svelte';
|
||||||
|
|
||||||
import FontIcon from '../icons/FontIcon.svelte';
|
import FontIcon from '../icons/FontIcon.svelte';
|
||||||
|
import { useConnectionInfo, useDatabaseInfo } from '../utility/metadataLoaders';
|
||||||
|
import PreviewCheckBox from './PreviewCheckBox.svelte';
|
||||||
|
import SourceAction from './SourceAction.svelte';
|
||||||
|
import SourceName from './SourceName.svelte';
|
||||||
|
|
||||||
import SourceTargetConfig from './SourceTargetConfig.svelte';
|
import SourceTargetConfig from './SourceTargetConfig.svelte';
|
||||||
|
import TargetName from './TargetName.svelte';
|
||||||
|
|
||||||
|
const { values } = getFormContext();
|
||||||
|
|
||||||
|
$: targetDbinfo = useDatabaseInfo({ conid: $values.targetConnectionId, database: $values.targetDatabaseName });
|
||||||
|
$: sourceConnectionInfo = useConnectionInfo({ conid: $values.sourceConnectionId });
|
||||||
|
|
||||||
|
const previewSource = writable(null);
|
||||||
|
|
||||||
// engine={sourceEngine}
|
// engine={sourceEngine}
|
||||||
// {setPreviewSource}
|
// {setPreviewSource}
|
||||||
@@ -30,6 +47,40 @@
|
|||||||
schemaNameField="targetSchemaName"
|
schemaNameField="targetSchemaName"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="m-2">
|
||||||
|
<div class="title"><FontIcon icon="icon tables" /> Map source tables/files</div>
|
||||||
|
|
||||||
|
<TableControl
|
||||||
|
rows={$values.sourceList || []}
|
||||||
|
columns={[
|
||||||
|
{
|
||||||
|
fieldName: 'source',
|
||||||
|
header: 'Source',
|
||||||
|
component: SourceName,
|
||||||
|
getProps: row => ({ name: row }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'action',
|
||||||
|
header: 'Action',
|
||||||
|
component: SourceAction,
|
||||||
|
getProps: row => ({ name: row, targetDbinfo }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'target',
|
||||||
|
header: 'Target',
|
||||||
|
component: TargetName,
|
||||||
|
getProps: row => ({ name: row }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'preview',
|
||||||
|
header: 'Preview',
|
||||||
|
component: PreviewCheckBox,
|
||||||
|
getProps: row => ({ name: row, previewSource }),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@@ -38,4 +89,10 @@
|
|||||||
color: var(--theme-icon-blue);
|
color: var(--theme-icon-blue);
|
||||||
align-self: center;
|
align-self: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 20px;
|
||||||
|
text-align: center;
|
||||||
|
margin: 10px 0px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
26
packages/web/src/impexp/PreviewCheckBox.svelte
Normal file
26
packages/web/src/impexp/PreviewCheckBox.svelte
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import CheckboxField from '../forms/CheckboxField.svelte';
|
||||||
|
|
||||||
|
import { getFormContext } from '../forms/FormProviderCore.svelte';
|
||||||
|
|
||||||
|
import { findFileFormat } from '../plugins/fileformats';
|
||||||
|
import { extensions } from '../stores';
|
||||||
|
|
||||||
|
const { values } = getFormContext();
|
||||||
|
|
||||||
|
export let name;
|
||||||
|
export let previewSource;
|
||||||
|
|
||||||
|
$: supportsPreview =
|
||||||
|
!!findFileFormat($extensions, $values.sourceStorageType) || $values.sourceStorageType == 'archive';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if supportsPreview}
|
||||||
|
<CheckboxField
|
||||||
|
checked={$previewSource == name}
|
||||||
|
onChange={e => {
|
||||||
|
if (e.target.checked) $previewSource = name;
|
||||||
|
else $previewSource = null;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
20
packages/web/src/impexp/SourceAction.svelte
Normal file
20
packages/web/src/impexp/SourceAction.svelte
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { getFormContext } from '../forms/FormProviderCore.svelte';
|
||||||
|
import SelectField from '../forms/SelectField.svelte';
|
||||||
|
import { extensions } from '../stores';
|
||||||
|
import { getActionOptions } from './createImpExpScript';
|
||||||
|
|
||||||
|
export let name;
|
||||||
|
export let targetDbinfo;
|
||||||
|
|
||||||
|
const { values, setFieldValue } = getFormContext();
|
||||||
|
|
||||||
|
$: options = getActionOptions($extensions, name, $values, targetDbinfo);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<SelectField
|
||||||
|
{options}
|
||||||
|
isNative
|
||||||
|
value={values[`actionType_${name}`] || options[0].value}
|
||||||
|
on:change={e => setFieldValue(`actionType_${name}`, e.detail)}
|
||||||
|
/>
|
||||||
49
packages/web/src/impexp/SourceName.svelte
Normal file
49
packages/web/src/impexp/SourceName.svelte
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { getFormContext } from '../forms/FormProviderCore.svelte';
|
||||||
|
import FontIcon from '../icons/FontIcon.svelte';
|
||||||
|
import ChangeDownloadUrlModal from '../modals/ChangeDownloadUrlModal.svelte';
|
||||||
|
import { showModal } from '../modals/modalTools';
|
||||||
|
|
||||||
|
export let name;
|
||||||
|
const { values, setFieldValue } = getFormContext();
|
||||||
|
|
||||||
|
const handleDelete = () => {
|
||||||
|
setFieldValue(
|
||||||
|
'sourceList',
|
||||||
|
$values.sourceList.filter(x => x != name)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
const doChangeUrl = url => {
|
||||||
|
setFieldValue(`sourceFile_${name}`, { fileName: url, isDownload: true });
|
||||||
|
};
|
||||||
|
const handleChangeUrl = () => {
|
||||||
|
showModal(ChangeDownloadUrlModal, { url: obj.fileName, onConfirm: doChangeUrl });
|
||||||
|
};
|
||||||
|
|
||||||
|
$: obj = $values[`sourceFile_${name}`];
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="flex space-between">
|
||||||
|
<div>{name}</div>
|
||||||
|
<div class="flex">
|
||||||
|
{#if obj && !!obj.isDownload}
|
||||||
|
<div class="icon" on:click={handleChangeUrl} title={obj && obj.fileName}>
|
||||||
|
<FontIcon icon="icon web" />
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
<div class="icon" on:click={handleDelete}>
|
||||||
|
<FontIcon icon="icon delete" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.icon {
|
||||||
|
cursor: pointer;
|
||||||
|
color: var(--theme-font-link);
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
.icon:hover {
|
||||||
|
background-color: var(--theme-bg-2);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
16
packages/web/src/impexp/TargetName.svelte
Normal file
16
packages/web/src/impexp/TargetName.svelte
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { getFormContext } from '../forms/FormProviderCore.svelte';
|
||||||
|
|
||||||
|
import TextField from '../forms/TextField.svelte';
|
||||||
|
import { extensions } from '../stores';
|
||||||
|
import { getTargetName } from './createImpExpScript';
|
||||||
|
|
||||||
|
const { values, setFieldValue } = getFormContext();
|
||||||
|
|
||||||
|
export let name;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<TextField
|
||||||
|
value={getTargetName($extensions, name, $values)}
|
||||||
|
onChange={e => setFieldValue(`targetName_${name}`, e.target.value)}
|
||||||
|
/>
|
||||||
29
packages/web/src/modals/ChangeDownloadUrlModal.svelte
Normal file
29
packages/web/src/modals/ChangeDownloadUrlModal.svelte
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import FormStyledButton from '../elements/FormStyledButton.svelte';
|
||||||
|
|
||||||
|
import FormProvider from '../forms/FormProvider.svelte';
|
||||||
|
import FormSubmit from '../forms/FormSubmit.svelte';
|
||||||
|
import FormTextField from '../forms/FormTextField.svelte';
|
||||||
|
import ModalBase from './ModalBase.svelte';
|
||||||
|
import { closeCurrentModal } from './modalTools';
|
||||||
|
|
||||||
|
export let onConfirm;
|
||||||
|
|
||||||
|
const handleSubmit = async values => {
|
||||||
|
onConfirm(values.url);
|
||||||
|
closeCurrentModal();
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<FormProvider>
|
||||||
|
<ModalBase {...$$restProps}>
|
||||||
|
<svelte:fragment slot="header">Download imported file from web</svelte:fragment>
|
||||||
|
|
||||||
|
<FormTextField label="URL" name="url" style={{ width: '30vw' }} focused />
|
||||||
|
|
||||||
|
<svelte:fragment slot="footer">
|
||||||
|
<FormSubmit value="OK" on:click={handleSubmit} />
|
||||||
|
<FormStyledButton value="Cancel" on:click={closeCurrentModal} />
|
||||||
|
</svelte:fragment>
|
||||||
|
</ModalBase>
|
||||||
|
</FormProvider>
|
||||||
@@ -8,11 +8,16 @@
|
|||||||
import FormTextField from '../forms/FormTextField.svelte';
|
import FormTextField from '../forms/FormTextField.svelte';
|
||||||
import LargeFormButton from '../forms/LargeFormButton.svelte';
|
import LargeFormButton from '../forms/LargeFormButton.svelte';
|
||||||
import FontIcon from '../icons/FontIcon.svelte';
|
import FontIcon from '../icons/FontIcon.svelte';
|
||||||
|
import createImpExpScript from '../impexp/createImpExpScript';
|
||||||
import ImportExportConfigurator from '../impexp/ImportExportConfigurator.svelte';
|
import ImportExportConfigurator from '../impexp/ImportExportConfigurator.svelte';
|
||||||
import { getDefaultFileFormat } from '../plugins/fileformats';
|
import { getDefaultFileFormat } from '../plugins/fileformats';
|
||||||
import RunnerOutputFiles from '../query/RunnerOutputFiles';
|
import RunnerOutputFiles from '../query/RunnerOutputFiles';
|
||||||
import SocketMessageView from '../query/SocketMessageView.svelte';
|
import SocketMessageView from '../query/SocketMessageView.svelte';
|
||||||
import { currentArchive, extensions } from '../stores';
|
import { currentArchive, extensions, selectedWidget } from '../stores';
|
||||||
|
import axiosInstance from '../utility/axiosInstance';
|
||||||
|
import openNewTab from '../utility/openNewTab';
|
||||||
|
import socket from '../utility/socket';
|
||||||
|
import useEffect from '../utility/useEffect';
|
||||||
import WidgetColumnBar from '../widgets/WidgetColumnBar.svelte';
|
import WidgetColumnBar from '../widgets/WidgetColumnBar.svelte';
|
||||||
import WidgetColumnBarItem from '../widgets/WidgetColumnBarItem.svelte';
|
import WidgetColumnBarItem from '../widgets/WidgetColumnBarItem.svelte';
|
||||||
import ModalBase from './ModalBase.svelte';
|
import ModalBase from './ModalBase.svelte';
|
||||||
@@ -28,41 +33,70 @@
|
|||||||
export let openedFile = undefined;
|
export let openedFile = undefined;
|
||||||
export let importToArchive = false;
|
export let importToArchive = false;
|
||||||
|
|
||||||
|
const refreshArchiveFolderRef = { current: null };
|
||||||
|
|
||||||
$: targetArchiveFolder = importToArchive ? `import-${moment().format('YYYY-MM-DD-hh-mm-ss')}` : $currentArchive;
|
$: targetArchiveFolder = importToArchive ? `import-${moment().format('YYYY-MM-DD-hh-mm-ss')}` : $currentArchive;
|
||||||
|
|
||||||
const handleGenerateScript = async () => {
|
$: effect = useEffect(() => registerRunnerDone(runnerId));
|
||||||
// const code = await createImpExpScript(extensions, values);
|
|
||||||
// openNewTab(
|
function registerRunnerDone(rid) {
|
||||||
// {
|
if (rid) {
|
||||||
// title: 'Shell #',
|
socket.on(`runner-done-${rid}`, handleRunnerDone);
|
||||||
// icon: 'img shell',
|
return () => {
|
||||||
// tabComponent: 'ShellTab',
|
socket.off(`runner-done-${rid}`, handleRunnerDone);
|
||||||
// },
|
};
|
||||||
// { editor: code }
|
} else {
|
||||||
// );
|
return () => {};
|
||||||
// modalState.close();
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$: $effect;
|
||||||
|
|
||||||
|
const handleRunnerDone = () => {
|
||||||
|
busy = false;
|
||||||
|
if (refreshArchiveFolderRef.current) {
|
||||||
|
axiosInstance.post('archive/refresh-folders', {});
|
||||||
|
axiosInstance.post('archive/refresh-files', { folder: refreshArchiveFolderRef.current });
|
||||||
|
$currentArchive = refreshArchiveFolderRef.current;
|
||||||
|
$selectedWidget = 'archive';
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleExecute = async values => {
|
const handleGenerateScript = async e => {
|
||||||
// if (busy) return;
|
closeCurrentModal();
|
||||||
// setBusy(true);
|
const code = await createImpExpScript($extensions, e.detail);
|
||||||
// const script = await createImpExpScript(extensions, values);
|
openNewTab(
|
||||||
// setExecuteNumber(num => num + 1);
|
{
|
||||||
// let runid = runnerId;
|
title: 'Shell #',
|
||||||
// const resp = await axios.post('runners/start', { script });
|
icon: 'img shell',
|
||||||
// runid = resp.data.runid;
|
tabComponent: 'ShellTab',
|
||||||
// setRunnerId(runid);
|
},
|
||||||
// if (values.targetStorageType == 'archive') {
|
{ editor: code }
|
||||||
// refreshArchiveFolderRef.current = values.targetArchiveFolder;
|
);
|
||||||
// } else {
|
};
|
||||||
// refreshArchiveFolderRef.current = null;
|
|
||||||
// }
|
const handleExecute = async e => {
|
||||||
|
if (busy) return;
|
||||||
|
const values = e.detail;
|
||||||
|
busy = true;
|
||||||
|
const script = await createImpExpScript($extensions, values);
|
||||||
|
executeNumber += 1;
|
||||||
|
let runid = runnerId;
|
||||||
|
const resp = await axiosInstance.post('runners/start', { script });
|
||||||
|
runid = resp.data.runid;
|
||||||
|
runnerId = runid;
|
||||||
|
|
||||||
|
if (values.targetStorageType == 'archive') {
|
||||||
|
refreshArchiveFolderRef.current = values.targetArchiveFolder;
|
||||||
|
} else {
|
||||||
|
refreshArchiveFolderRef.current = null;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
// axios.post('runners/cancel', {
|
axiosInstance.post('runners/cancel', {
|
||||||
// runid: runnerId,
|
runid: runnerId,
|
||||||
// });
|
});
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -85,9 +119,9 @@
|
|||||||
|
|
||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
<HorizontalSplitter initialValue="70%">
|
<HorizontalSplitter initialValue="70%">
|
||||||
<svelte:fragment slot="1">
|
<div class="content" slot="1">
|
||||||
<ImportExportConfigurator />
|
<ImportExportConfigurator />
|
||||||
</svelte:fragment>
|
</div>
|
||||||
|
|
||||||
<svelte:fragment slot="2">
|
<svelte:fragment slot="2">
|
||||||
<WidgetColumnBar>
|
<WidgetColumnBar>
|
||||||
@@ -145,4 +179,13 @@
|
|||||||
border-top: 1px solid var(--theme-border);
|
border-top: 1px solid var(--theme-border);
|
||||||
background-color: var(--theme-bg-modalheader);
|
background-color: var(--theme-bg-modalheader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
border-top: 1px solid var(--theme-border);
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -58,7 +58,7 @@
|
|||||||
runnerId,
|
runnerId,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
!electron && {
|
electron && {
|
||||||
fieldName: 'copy',
|
fieldName: 'copy',
|
||||||
header: 'Copy',
|
header: 'Copy',
|
||||||
component: CopyLink,
|
component: CopyLink,
|
||||||
@@ -67,7 +67,7 @@
|
|||||||
runnerId,
|
runnerId,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
!electron && {
|
electron && {
|
||||||
fieldName: 'show',
|
fieldName: 'show',
|
||||||
header: 'Show',
|
header: 'Show',
|
||||||
component: ShowLink,
|
component: ShowLink,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script lang="ts" context="module">
|
<script lang="ts" context="module">
|
||||||
const lastFocusedEditor = writable(null);
|
const lastFocusedEditor = writable(null);
|
||||||
const currentEditor = derived([lastFocusedEditor, activeTabId], ([editor, tabid]) =>
|
const currentEditor = derived([lastFocusedEditor, activeTabId], ([editor, tabid]) =>
|
||||||
editor?.getTabId() == tabid ? editor : null
|
editor?.getTabId && editor?.getTabId() == tabid ? editor : null
|
||||||
);
|
);
|
||||||
|
|
||||||
registerFileCommands({
|
registerFileCommands({
|
||||||
@@ -53,10 +53,8 @@
|
|||||||
|
|
||||||
const instance = get_current_component();
|
const instance = get_current_component();
|
||||||
|
|
||||||
|
|
||||||
let domEditor;
|
let domEditor;
|
||||||
|
|
||||||
|
|
||||||
$: if ($tabVisible && domEditor) {
|
$: if ($tabVisible && domEditor) {
|
||||||
domEditor?.getEditor()?.focus();
|
domEditor?.getEditor()?.focus();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script lang="ts" context="module">
|
<script lang="ts" context="module">
|
||||||
const lastFocusedEditor = writable(null);
|
const lastFocusedEditor = writable(null);
|
||||||
const currentEditor = derived([lastFocusedEditor, activeTabId], ([editor, tabid]) =>
|
const currentEditor = derived([lastFocusedEditor, activeTabId], ([editor, tabid]) =>
|
||||||
editor?.getTabId() == tabid ? editor : null
|
editor?.getTabId && editor?.getTabId() == tabid ? editor : null
|
||||||
);
|
);
|
||||||
const currentEditorStatus = memberStore(currentEditor, editor => editor?.getStatus() || nullStore);
|
const currentEditorStatus = memberStore(currentEditor, editor => editor?.getStatus() || nullStore);
|
||||||
|
|
||||||
@@ -22,8 +22,8 @@
|
|||||||
fileExtension: 'sql',
|
fileExtension: 'sql',
|
||||||
|
|
||||||
execute: true,
|
execute: true,
|
||||||
toggleComment:true,
|
toggleComment: true,
|
||||||
findReplace:true
|
findReplace: true,
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script lang="ts" context="module">
|
<script lang="ts" context="module">
|
||||||
const lastFocusedEditor = writable(null);
|
const lastFocusedEditor = writable(null);
|
||||||
const currentEditor = derived([lastFocusedEditor, activeTabId], ([editor, tabid]) =>
|
const currentEditor = derived([lastFocusedEditor, activeTabId], ([editor, tabid]) =>
|
||||||
editor?.getTabId() == tabid ? editor : null
|
editor?.getTabId && editor?.getTabId() == tabid ? editor : null
|
||||||
);
|
);
|
||||||
const currentEditorStatus = memberStore(currentEditor, editor => editor?.getStatus() || nullStore);
|
const currentEditorStatus = memberStore(currentEditor, editor => editor?.getStatus() || nullStore);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user