mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-30 20:53:57 +00:00
import files controls
This commit is contained in:
@@ -4,12 +4,14 @@ import { derived, get } from 'svelte/store';
|
|||||||
import { ThemeDefinition } from 'dbgate-types';
|
import { ThemeDefinition } from 'dbgate-types';
|
||||||
import ConnectionModal from '../modals/ConnectionModal.svelte';
|
import ConnectionModal from '../modals/ConnectionModal.svelte';
|
||||||
import AboutModal from '../modals/AboutModal.svelte';
|
import AboutModal from '../modals/AboutModal.svelte';
|
||||||
|
import ImportExportModal from '../modals/ImportExportModal.svelte';
|
||||||
import { showModal } from '../modals/modalTools';
|
import { showModal } from '../modals/modalTools';
|
||||||
import newQuery from '../query/newQuery';
|
import newQuery from '../query/newQuery';
|
||||||
import saveTabFile from '../utility/saveTabFile';
|
import saveTabFile from '../utility/saveTabFile';
|
||||||
import openNewTab from '../utility/openNewTab';
|
import openNewTab from '../utility/openNewTab';
|
||||||
import getElectron from '../utility/getElectron';
|
import getElectron from '../utility/getElectron';
|
||||||
import { openElectronFile } from '../utility/openElectronFile';
|
import { openElectronFile } from '../utility/openElectronFile';
|
||||||
|
import { getDefaultFileFormat } from '../plugins/fileformats';
|
||||||
|
|
||||||
const electron = getElectron();
|
const electron = getElectron();
|
||||||
|
|
||||||
@@ -150,6 +152,19 @@ if (electron) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
registerCommand({
|
||||||
|
id: 'file.import',
|
||||||
|
category: 'File',
|
||||||
|
name: 'Import data',
|
||||||
|
toolbar: true,
|
||||||
|
icon: 'icon import',
|
||||||
|
onClick: () =>
|
||||||
|
showModal(ImportExportModal, {
|
||||||
|
importToArchive: true,
|
||||||
|
initialValues: { sourceStorageType: getDefaultFileFormat(get(extensions)).storageType },
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
export function registerFileCommands({
|
export function registerFileCommands({
|
||||||
idPrefix,
|
idPrefix,
|
||||||
category,
|
category,
|
||||||
|
|||||||
30
packages/web/src/elements/FormStyledButtonLikeLabel.svelte
Normal file
30
packages/web/src/elements/FormStyledButtonLikeLabel.svelte
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
export let disabled = false;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<label {...$$props} class:disabled>
|
||||||
|
<slot />
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
label {
|
||||||
|
border: 1px solid var(--theme-bg-button-inv-2);
|
||||||
|
padding: 5px;
|
||||||
|
margin: 2px;
|
||||||
|
width: 100px;
|
||||||
|
background-color: var(--theme-bg-button-inv);
|
||||||
|
color: var(--theme-font-inv-1);
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
label:hover:not(.disabled) {
|
||||||
|
background-color: var(--theme-bg-button-inv-2);
|
||||||
|
}
|
||||||
|
label:active:not(.disabled) {
|
||||||
|
background-color: var(--theme-bg-button-inv-3);
|
||||||
|
}
|
||||||
|
label.disabled {
|
||||||
|
background-color: var(--theme-bg-button-inv-3);
|
||||||
|
color: var(--theme-font-inv-3);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
39
packages/web/src/forms/FormArchiveFilesSelect.svelte
Normal file
39
packages/web/src/forms/FormArchiveFilesSelect.svelte
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
|
import FormStyledButton from '../elements/FormStyledButton.svelte';
|
||||||
|
|
||||||
|
import { useArchiveFiles, useArchiveFolders } from '../utility/metadataLoaders';
|
||||||
|
import { getFormContext } from './FormProviderCore.svelte';
|
||||||
|
|
||||||
|
import FormSelectField from './FormSelectField.svelte';
|
||||||
|
|
||||||
|
export let folderName;
|
||||||
|
export let name;
|
||||||
|
|
||||||
|
const { setFieldValue, values } = getFormContext();
|
||||||
|
|
||||||
|
$: files = useArchiveFiles({ folder: folderName });
|
||||||
|
$: filesOptions = ($files || []).map(x => ({
|
||||||
|
value: x.name,
|
||||||
|
label: x.name,
|
||||||
|
}));
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="wrapper">
|
||||||
|
<FormSelectField {...$$props} options={filesOptions} isMulti templateProps={{ noMargin: true }} />
|
||||||
|
<div>
|
||||||
|
<FormStyledButton
|
||||||
|
type="button"
|
||||||
|
value="All files"
|
||||||
|
on:click={() => setFieldValue(name, _.uniq([...($values[name] || []), ...($files && $files.map(x => x.name))]))}
|
||||||
|
/>
|
||||||
|
<FormStyledButton type="button" value="Remove all" on:click={() => setFieldValue(name, [])} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.wrapper {
|
||||||
|
margin: var(--dim-large-form-margin);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
53
packages/web/src/impexp/ElectronFilesInput.svelte
Normal file
53
packages/web/src/impexp/ElectronFilesInput.svelte
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
<script lang="ts" context="module">
|
||||||
|
function getFileFilters(extensions, storageType) {
|
||||||
|
const res = [];
|
||||||
|
const format = findFileFormat(extensions, storageType);
|
||||||
|
if (format) res.push({ name: format.name, extensions: [format.extension] });
|
||||||
|
res.push({ name: 'All Files', extensions: ['*'] });
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import FormStyledButton from '../elements/FormStyledButton.svelte';
|
||||||
|
import LoadingInfo from '../elements/LoadingInfo.svelte';
|
||||||
|
import { getFormContext } from '../forms/FormProviderCore.svelte';
|
||||||
|
import { findFileFormat } from '../plugins/fileformats';
|
||||||
|
import { extensions } from '../stores';
|
||||||
|
import getElectron from '../utility/getElectron';
|
||||||
|
import { addFilesToSourceList } from './ImportExportConfigurator.svelte';
|
||||||
|
|
||||||
|
let isLoading = false;
|
||||||
|
|
||||||
|
const electron = getElectron();
|
||||||
|
const { values } = getFormContext();
|
||||||
|
|
||||||
|
const handleClick = async () => {
|
||||||
|
const files = electron.remote.dialog.showOpenDialogSync(electron.remote.getCurrentWindow(), {
|
||||||
|
properties: ['openFile', 'multiSelections'],
|
||||||
|
filters: getFileFilters($extensions, $values.sourceStorageType),
|
||||||
|
});
|
||||||
|
if (files) {
|
||||||
|
const path = window.require('path');
|
||||||
|
try {
|
||||||
|
isLoading = true;
|
||||||
|
await addFilesToSourceList(
|
||||||
|
$extensions,
|
||||||
|
files.map(full => ({
|
||||||
|
fileName: full,
|
||||||
|
shortName: path.parse(full).name,
|
||||||
|
})),
|
||||||
|
$values,
|
||||||
|
values
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
isLoading = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<FormStyledButton type="button" value="Add file(s)" on:click={handleClick} />
|
||||||
|
{#if isLoading}
|
||||||
|
<LoadingInfo message="Anaysing input files" />
|
||||||
|
{/if}
|
||||||
73
packages/web/src/impexp/FilesInput.svelte
Normal file
73
packages/web/src/impexp/FilesInput.svelte
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
<script lang="ts" context="module">
|
||||||
|
function extractUrlName(url, values) {
|
||||||
|
const match = url.match(/\/([^/]+)($|\?)/);
|
||||||
|
if (match) {
|
||||||
|
const res = match[1];
|
||||||
|
if (res.includes('.')) {
|
||||||
|
return res.slice(0, res.indexOf('.'));
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
return `url${values && values.sourceList ? values.sourceList.length + 1 : '1'}`;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import FormStyledButton from '../elements/FormStyledButton.svelte';
|
||||||
|
import { getFormContext } from '../forms/FormProviderCore.svelte';
|
||||||
|
import ChangeDownloadUrlModal from '../modals/ChangeDownloadUrlModal.svelte';
|
||||||
|
import { showModal } from '../modals/modalTools';
|
||||||
|
import { extensions } from '../stores';
|
||||||
|
|
||||||
|
import getElectron from '../utility/getElectron';
|
||||||
|
import ElectronFilesInput from './ElectronFilesInput.svelte';
|
||||||
|
import { addFilesToSourceList } from './ImportExportConfigurator.svelte';
|
||||||
|
import UploadButton from './UploadButton.svelte';
|
||||||
|
|
||||||
|
export let setPreviewSource = undefined;
|
||||||
|
|
||||||
|
const electron = getElectron();
|
||||||
|
const { values } = getFormContext();
|
||||||
|
|
||||||
|
const doAddUrl = url => {
|
||||||
|
addFilesToSourceList(
|
||||||
|
$extensions,
|
||||||
|
[
|
||||||
|
{
|
||||||
|
fileName: url,
|
||||||
|
shortName: extractUrlName(url, $values),
|
||||||
|
isDownload: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
$values,
|
||||||
|
values,
|
||||||
|
null,
|
||||||
|
setPreviewSource
|
||||||
|
);
|
||||||
|
};
|
||||||
|
const handleAddUrl = () => showModal(ChangeDownloadUrlModal, { onConfirm: doAddUrl });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="main">
|
||||||
|
<div class="flex">
|
||||||
|
{#if electron}
|
||||||
|
<ElectronFilesInput />
|
||||||
|
{:else}
|
||||||
|
<UploadButton />
|
||||||
|
{/if}
|
||||||
|
<FormStyledButton value="Add web URL" on:click={handleAddUrl} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="wrapper">Drag & drop imported files here</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.wrapper {
|
||||||
|
padding: 10px;
|
||||||
|
background: var(--theme-bg-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.main {
|
||||||
|
margin: var(--dim-large-form-margin);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -8,7 +8,14 @@
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async function addFilesToSourceList(extensions, files, values, valuesStore, preferedStorageType, setPreviewSource) {
|
export async function addFilesToSourceList(
|
||||||
|
extensions,
|
||||||
|
files,
|
||||||
|
values,
|
||||||
|
valuesStore,
|
||||||
|
preferedStorageType = undefined,
|
||||||
|
setPreviewSource = undefined
|
||||||
|
) {
|
||||||
const newSources = [];
|
const newSources = [];
|
||||||
const newValues = {};
|
const newValues = {};
|
||||||
const storage = preferedStorageType || values.sourceStorageType;
|
const storage = preferedStorageType || values.sourceStorageType;
|
||||||
@@ -118,6 +125,7 @@
|
|||||||
archiveFolderField="sourceArchiveFolder"
|
archiveFolderField="sourceArchiveFolder"
|
||||||
schemaNameField="sourceSchemaName"
|
schemaNameField="sourceSchemaName"
|
||||||
tablesField="sourceList"
|
tablesField="sourceList"
|
||||||
|
setPreviewSource={previewSource.set}
|
||||||
/>
|
/>
|
||||||
<div class="arrow">
|
<div class="arrow">
|
||||||
<FontIcon icon="icon arrow-right" />
|
<FontIcon icon="icon arrow-right" />
|
||||||
|
|||||||
@@ -1,11 +1,19 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import _ from 'lodash';
|
||||||
|
import FormArchiveFilesSelect from '../forms/FormArchiveFilesSelect.svelte';
|
||||||
|
|
||||||
|
import FormArchiveFolderSelect from '../forms/FormArchiveFolderSelect.svelte';
|
||||||
|
import FormArgumentList from '../forms/FormArgumentList.svelte';
|
||||||
|
|
||||||
import { getFormContext } from '../forms/FormProviderCore.svelte';
|
import { getFormContext } from '../forms/FormProviderCore.svelte';
|
||||||
import FormSelectField from '../forms/FormSelectField.svelte';
|
import FormSelectField from '../forms/FormSelectField.svelte';
|
||||||
|
|
||||||
import FontIcon from '../icons/FontIcon.svelte';
|
import FontIcon from '../icons/FontIcon.svelte';
|
||||||
import { findFileFormat, getFileFormatDirections } from '../plugins/fileformats';
|
import { findFileFormat, getFileFormatDirections } from '../plugins/fileformats';
|
||||||
|
import SqlEditor from '../query/SqlEditor.svelte';
|
||||||
import { extensions } from '../stores';
|
import { extensions } from '../stores';
|
||||||
import { useArchiveFiles, useDatabaseInfo } from '../utility/metadataLoaders';
|
import { useArchiveFiles, useDatabaseInfo } from '../utility/metadataLoaders';
|
||||||
|
import FilesInput from './FilesInput.svelte';
|
||||||
import FormConnectionSelect from './FormConnectionSelect.svelte';
|
import FormConnectionSelect from './FormConnectionSelect.svelte';
|
||||||
import FormDatabaseSelect from './FormDatabaseSelect.svelte';
|
import FormDatabaseSelect from './FormDatabaseSelect.svelte';
|
||||||
import FormSchemaSelect from './FormSchemaSelect.svelte';
|
import FormSchemaSelect from './FormSchemaSelect.svelte';
|
||||||
@@ -20,6 +28,7 @@
|
|||||||
export let schemaNameField;
|
export let schemaNameField;
|
||||||
export let tablesField = undefined;
|
export let tablesField = undefined;
|
||||||
export let engine = undefined;
|
export let engine = undefined;
|
||||||
|
export let setPreviewSource = undefined;
|
||||||
|
|
||||||
const { values, setFieldValue } = getFormContext();
|
const { values, setFieldValue } = getFormContext();
|
||||||
|
|
||||||
@@ -82,6 +91,40 @@
|
|||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
|
{#if storageType == 'query'}
|
||||||
|
<div class="label">Query</div>
|
||||||
|
<div class="sqlwrap">
|
||||||
|
<SqlEditor
|
||||||
|
value={$values.sourceSql}
|
||||||
|
on:input={e => setFieldValue('sourceSql', e.detail)}
|
||||||
|
{engine}
|
||||||
|
focusOnCreate
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if storageType == 'archive'}
|
||||||
|
<FormArchiveFolderSelect
|
||||||
|
label="Archive folder"
|
||||||
|
name={archiveFolderField}
|
||||||
|
additionalFolders={_.compact([$values[archiveFolderField]])}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if storageType == 'archive' && direction == 'source'}
|
||||||
|
<FormArchiveFilesSelect label="Source files" folderName={$values[archiveFolderField]} name={tablesField} />
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if format && direction == 'source'}
|
||||||
|
<FilesInput {setPreviewSource} />
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if format && format.args}
|
||||||
|
<FormArgumentList
|
||||||
|
args={format.args.filter(arg => !arg.direction || arg.direction == direction)}
|
||||||
|
namePrefix={`${direction}_${format.storageType}_`}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@@ -95,4 +138,19 @@
|
|||||||
margin: 10px;
|
margin: 10px;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sqlwrap {
|
||||||
|
position: relative;
|
||||||
|
height: 100px;
|
||||||
|
width: 20vw;
|
||||||
|
margin-left: var(--dim-large-form-margin);
|
||||||
|
margin-bottom: var(--dim-large-form-margin);
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
margin-left: var(--dim-large-form-margin);
|
||||||
|
margin-top: var(--dim-large-form-margin);
|
||||||
|
margin-bottom: 3px;
|
||||||
|
color: var(--theme-font-3);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
14
packages/web/src/impexp/UploadButton.svelte
Normal file
14
packages/web/src/impexp/UploadButton.svelte
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import FormStyledButtonLikeLabel from '../elements/FormStyledButtonLikeLabel.svelte';
|
||||||
|
import uploadFiles from '../utility/uploadFiles';
|
||||||
|
|
||||||
|
const handleChange = e => {
|
||||||
|
const files = [...e.target.files];
|
||||||
|
uploadFiles(files);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="m-1">
|
||||||
|
<FormStyledButtonLikeLabel htmlFor="uploadFileButton">Upload file</FormStyledButtonLikeLabel>
|
||||||
|
<input type="file" id="uploadFileButton" hidden on:change={handleChange} />
|
||||||
|
</div>
|
||||||
Reference in New Issue
Block a user