mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-19 13:06:01 +00:00
SYNC: Merge pull request #3 from dbgate/feature/zip
This commit is contained in:
@@ -14,6 +14,8 @@
|
||||
import { apiCall } from '../utility/api';
|
||||
import { useArchiveFolders } from '../utility/metadataLoaders';
|
||||
import WidgetsInnerContainer from './WidgetsInnerContainer.svelte';
|
||||
import InlineUploadButton from '../buttons/InlineUploadButton.svelte';
|
||||
import { isProApp } from '../utility/proTools';
|
||||
|
||||
let filter = '';
|
||||
|
||||
@@ -22,11 +24,47 @@
|
||||
const handleRefreshFolders = () => {
|
||||
apiCall('archive/refresh-folders');
|
||||
};
|
||||
|
||||
async function handleUploadedFile(filePath, fileName) {
|
||||
await apiCall('archive/save-uploaded-zip', { filePath, fileName });
|
||||
}
|
||||
</script>
|
||||
|
||||
<SearchBoxWrapper>
|
||||
<SearchInput placeholder="Search archive folders" bind:value={filter} />
|
||||
<CloseSearchButton bind:filter />
|
||||
|
||||
{#if isProApp()}
|
||||
<InlineUploadButton
|
||||
icon="icon upload"
|
||||
filters={[
|
||||
{
|
||||
name: `All supported files`,
|
||||
extensions: ['zip'],
|
||||
},
|
||||
{ name: `ZIP files`, extensions: ['zip'] },
|
||||
]}
|
||||
onProcessFile={handleUploadedFile}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<!-- {#if electron}
|
||||
<InlineButton on:click={handleOpenElectronFile} title="Add file" data-testid="ArchiveFolderList_uploadZipFile">
|
||||
<FontIcon icon="icon plus-thick" />
|
||||
</InlineButton>
|
||||
{:else}
|
||||
<InlineButtonLabel
|
||||
on:click={() => {}}
|
||||
title="Add file"
|
||||
data-testid="ArchiveFolderList_uploadZipFile"
|
||||
htmlFor="uploadZipFileButton"
|
||||
>
|
||||
<FontIcon icon="icon plus-thick" />
|
||||
</InlineButtonLabel>
|
||||
{/if}
|
||||
|
||||
<input type="file" id="uploadZipFileButton" hidden on:change={handleUploadedFile} /> -->
|
||||
|
||||
<InlineButton on:click={() => runCommand('new.archiveFolder')} title="Add new archive folder">
|
||||
<FontIcon icon="icon plus-thick" />
|
||||
</InlineButton>
|
||||
|
||||
75
packages/web/src/widgets/MultiColumnFilterControl.svelte
Normal file
75
packages/web/src/widgets/MultiColumnFilterControl.svelte
Normal file
@@ -0,0 +1,75 @@
|
||||
<script lang="ts">
|
||||
import { evalFilterBehaviour } from 'dbgate-tools';
|
||||
import DataFilterControl from '../datagrid/DataFilterControl.svelte';
|
||||
import InlineButton from '../buttons/InlineButton.svelte';
|
||||
import SelectField from '../forms/SelectField.svelte';
|
||||
import _ from 'lodash';
|
||||
import FontIcon from '../icons/FontIcon.svelte';
|
||||
|
||||
export let compoudFilter: { [key: string]: string };
|
||||
export let onSetCompoudFilter;
|
||||
export let columnNames: string[];
|
||||
export let filterBehaviour = evalFilterBehaviour;
|
||||
|
||||
$: columnsReal = Object.keys(compoudFilter || {});
|
||||
$: columnsUsed = columnsReal.length > 0 ? columnsReal : [columnNames[0]];
|
||||
</script>
|
||||
|
||||
{#each columnsUsed as column, index}
|
||||
<div class="flex">
|
||||
<SelectField
|
||||
isNative
|
||||
value={column}
|
||||
on:change={e => {
|
||||
const keys = Object.keys(compoudFilter || {});
|
||||
const values = Object.values(compoudFilter || {});
|
||||
keys[index] = e.detail;
|
||||
const newFilter = _.zipObject(keys, values);
|
||||
onSetCompoudFilter(newFilter);
|
||||
}}
|
||||
options={columnNames.map(col => ({
|
||||
label: col,
|
||||
value: col,
|
||||
})) || []}
|
||||
/>
|
||||
|
||||
<DataFilterControl
|
||||
{filterBehaviour}
|
||||
filter={compoudFilter?.[column] ?? ''}
|
||||
setFilter={value => {
|
||||
onSetCompoudFilter({
|
||||
...compoudFilter,
|
||||
[column]: value,
|
||||
});
|
||||
}}
|
||||
placeholder="Filter"
|
||||
/>
|
||||
|
||||
{#if index == 0}
|
||||
<InlineButton
|
||||
on:click={() => {
|
||||
const newColumn = columnNames.find(x => !columnsUsed.includes(x));
|
||||
if (!newColumn) return;
|
||||
onSetCompoudFilter({
|
||||
...compoudFilter,
|
||||
[newColumn]: '',
|
||||
});
|
||||
}}
|
||||
title="Add filter column"
|
||||
square
|
||||
>
|
||||
<FontIcon icon="icon plus-thick" />
|
||||
</InlineButton>
|
||||
{:else}
|
||||
<InlineButton
|
||||
on:click={() => {
|
||||
onSetCompoudFilter(_.omit(compoudFilter, column));
|
||||
}}
|
||||
title="Remove filter column"
|
||||
square
|
||||
>
|
||||
<FontIcon icon="icon minus-thick" />
|
||||
</InlineButton>
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
@@ -10,9 +10,8 @@
|
||||
import { apiCall } from '../utility/api';
|
||||
import { useFiles } from '../utility/metadataLoaders';
|
||||
import WidgetsInnerContainer from './WidgetsInnerContainer.svelte';
|
||||
import getElectron from '../utility/getElectron';
|
||||
import InlineButtonLabel from '../buttons/InlineButtonLabel.svelte';
|
||||
import resolveApi, { resolveApiHeaders } from '../utility/resolveApi';
|
||||
import { isProApp } from '../utility/proTools';
|
||||
import InlineUploadButton from '../buttons/InlineUploadButton.svelte';
|
||||
|
||||
let filter = '';
|
||||
|
||||
@@ -23,12 +22,12 @@
|
||||
const queryFiles = useFiles({ folder: 'query' });
|
||||
const sqliteFiles = useFiles({ folder: 'sqlite' });
|
||||
const diagramFiles = useFiles({ folder: 'diagrams' });
|
||||
const jobFiles = useFiles({ folder: 'jobs' });
|
||||
const importExportJobFiles = useFiles({ folder: 'impexp' });
|
||||
const dataDeployJobFiles = useFiles({ folder: 'datadeploy' });
|
||||
const dbCompareJobFiles = useFiles({ folder: 'dbcompare' });
|
||||
const perspectiveFiles = useFiles({ folder: 'perspectives' });
|
||||
const modelTransformFiles = useFiles({ folder: 'modtrans' });
|
||||
|
||||
const electron = getElectron();
|
||||
|
||||
$: files = [
|
||||
...($sqlFiles || []),
|
||||
...($shellFiles || []),
|
||||
@@ -38,8 +37,10 @@
|
||||
...($sqliteFiles || []),
|
||||
...($diagramFiles || []),
|
||||
...($perspectiveFiles || []),
|
||||
...($jobFiles || []),
|
||||
...($importExportJobFiles || []),
|
||||
...($modelTransformFiles || []),
|
||||
...((isProApp() && $dataDeployJobFiles) || []),
|
||||
...((isProApp() && $dbCompareJobFiles) || []),
|
||||
];
|
||||
|
||||
function handleRefreshFiles() {
|
||||
@@ -53,50 +54,23 @@
|
||||
'sqlite',
|
||||
'diagrams',
|
||||
'perspectives',
|
||||
'jobs',
|
||||
'impexp',
|
||||
'modtrans',
|
||||
'datadeploy',
|
||||
'dbcompare',
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
function dataFolderTitle(folder) {
|
||||
if (folder == 'modtrans') return 'Model transforms';
|
||||
if (folder == 'datadeploy') return 'Data deploy jobs';
|
||||
if (folder == 'dbcompare') return 'Database compare jobs';
|
||||
return _.startCase(folder);
|
||||
}
|
||||
|
||||
async function handleUploadedFile(e) {
|
||||
const files = [...e.target.files];
|
||||
|
||||
for (const file of files) {
|
||||
const formData = new FormData();
|
||||
formData.append('name', file.name);
|
||||
formData.append('data', file);
|
||||
|
||||
const fetchOptions = {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
headers: resolveApiHeaders(),
|
||||
};
|
||||
|
||||
const apiBase = resolveApi();
|
||||
const resp = await fetch(`${apiBase}/uploads/upload-data-file`, fetchOptions);
|
||||
const fileData = await resp.json();
|
||||
}
|
||||
}
|
||||
|
||||
async function handleOpenElectronFile() {
|
||||
const filePaths = await electron.showOpenDialog({
|
||||
filters: [
|
||||
{
|
||||
name: `All supported files`,
|
||||
extensions: ['sql'],
|
||||
},
|
||||
{ name: `SQL files`, extensions: ['sql'] },
|
||||
],
|
||||
properties: ['showHiddenFiles', 'openFile'],
|
||||
});
|
||||
const filePath = filePaths && filePaths[0];
|
||||
await apiCall('uploads/save-data-file', { filePath });
|
||||
async function handleUploadedFile(filePath, fileName) {
|
||||
await apiCall('files/save-uploaded-file', { filePath, fileName });
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -104,26 +78,20 @@
|
||||
<SearchBoxWrapper>
|
||||
<SearchInput placeholder="Search saved files" bind:value={filter} />
|
||||
<CloseSearchButton bind:filter />
|
||||
{#if electron}
|
||||
<InlineButton on:click={handleOpenElectronFile} title="Add file" data-testid="SavedFileList_buttonAddFile">
|
||||
<FontIcon icon="icon plus-thick" />
|
||||
</InlineButton>
|
||||
{:else}
|
||||
<InlineButtonLabel
|
||||
on:click={() => {}}
|
||||
title="Add file"
|
||||
data-testid="SavedFileList_buttonAddFile"
|
||||
htmlFor="uploadSavedFileButton"
|
||||
>
|
||||
<FontIcon icon="icon plus-thick" />
|
||||
</InlineButtonLabel>
|
||||
{/if}
|
||||
<InlineUploadButton
|
||||
filters={[
|
||||
{
|
||||
name: `All supported files`,
|
||||
extensions: ['sql'],
|
||||
},
|
||||
{ name: `SQL files`, extensions: ['sql'] },
|
||||
]}
|
||||
onProcessFile={handleUploadedFile}
|
||||
/>
|
||||
<InlineButton on:click={handleRefreshFiles} title="Refresh files" data-testid="SavedFileList_buttonRefresh">
|
||||
<FontIcon icon="icon refresh" />
|
||||
</InlineButton>
|
||||
</SearchBoxWrapper>
|
||||
|
||||
<input type="file" id="uploadSavedFileButton" hidden on:change={handleUploadedFile} />
|
||||
|
||||
<AppObjectList list={files} module={savedFileAppObject} groupFunc={data => dataFolderTitle(data.folder)} {filter} />
|
||||
</WidgetsInnerContainer>
|
||||
|
||||
Reference in New Issue
Block a user