SYNC: Merge pull request #3 from dbgate/feature/zip

This commit is contained in:
Jan Prochazka
2025-04-23 13:17:54 +02:00
committed by Diflow
parent 54c53f0b56
commit 8f4118a6b8
82 changed files with 3981 additions and 2814 deletions

View File

@@ -1,5 +1,5 @@
<script lang="ts" context="module">
function openArchive(fileName, folderName) {
async function openArchive(fileName, folderName) {
openNewTab({
title: fileName,
icon: 'img archive',
@@ -10,17 +10,21 @@
archiveFolder: folderName,
},
});
// }
}
async function openTextFile(fileName, fileType, folderName, tabComponent, icon) {
const connProps: any = {};
let tooltip = undefined;
const isZipped = folderName.endsWith('.zip');
const resp = await apiCall('files/load', {
folder: 'archive:' + folderName,
file: fileName + '.' + fileType,
format: 'text',
});
const resp = isZipped
? await apiCall('files/download-text', { uri: `zip://archive:${folderName}//${fileName}.jsonl` })
: await apiCall('files/load', {
folder: 'archive:' + folderName,
file: fileName + '.' + fileType,
format: 'text',
});
openNewTab(
{
@@ -58,7 +62,7 @@
if (data.fileType == 'jsonl') {
return 'img archive';
}
return ARCHIVE_ICONS[data.fileType];
return ARCHIVE_ICONS[data.fileType] ?? 'img anyfile';
}
</script>
@@ -79,6 +83,7 @@
import { openImportExportTab } from '../utility/importExportTools';
export let data;
$: isZipped = data.folderName?.endsWith('.zip');
const handleRename = () => {
showModal(InputTextModal, {
@@ -112,6 +117,9 @@
openArchive(data.fileName, data.folderName);
};
const handleClick = () => {
if (!data.fileType) {
return;
}
if (data.fileType == 'jsonl') {
handleOpenArchive();
}
@@ -133,11 +141,15 @@
};
function createMenu() {
if (!data.fileType) {
return [];
}
return [
data.fileType == 'jsonl' && { text: 'Open', onClick: handleOpenArchive },
data.fileType == 'jsonl' && { text: 'Open in text editor', onClick: handleOpenJsonLinesText },
{ text: 'Delete', onClick: handleDelete },
{ text: 'Rename', onClick: handleRename },
!isZipped && { text: 'Delete', onClick: handleDelete },
!isZipped && { text: 'Rename', onClick: handleRename },
data.fileType == 'jsonl' &&
createQuickExportMenu(
fmt => async () => {
@@ -174,29 +186,30 @@
),
data.fileType.endsWith('.sql') && { text: 'Open SQL', onClick: handleOpenSqlFile },
data.fileType.endsWith('.yaml') && { text: 'Open YAML', onClick: handleOpenYamlFile },
data.fileType == 'jsonl' && {
text: 'Open in profiler',
submenu: getExtensions()
.drivers.filter(eng => eng.profilerFormatterFunction)
.map(eng => ({
text: eng.title,
onClick: () => {
openNewTab({
title: 'Profiler',
icon: 'img profiler',
tabComponent: 'ProfilerTab',
props: {
jslidLoad: `archive://${data.folderName}/${data.fileName}`,
engine: eng.engine,
// profilerFormatterFunction: eng.profilerFormatterFunction,
// profilerTimestampFunction: eng.profilerTimestampFunction,
// profilerChartAggregateFunction: eng.profilerChartAggregateFunction,
// profilerChartMeasures: eng.profilerChartMeasures,
},
});
},
})),
},
!isZipped &&
data.fileType == 'jsonl' && {
text: 'Open in profiler',
submenu: getExtensions()
.drivers.filter(eng => eng.profilerFormatterFunction)
.map(eng => ({
text: eng.title,
onClick: () => {
openNewTab({
title: 'Profiler',
icon: 'img profiler',
tabComponent: 'ProfilerTab',
props: {
jslidLoad: `archive://${data.folderName}/${data.fileName}`,
engine: eng.engine,
// profilerFormatterFunction: eng.profilerFormatterFunction,
// profilerTimestampFunction: eng.profilerTimestampFunction,
// profilerChartAggregateFunction: eng.profilerChartAggregateFunction,
// profilerChartMeasures: eng.profilerChartMeasures,
},
});
},
})),
},
];
}
</script>

View File

@@ -20,6 +20,7 @@
import hasPermission from '../utility/hasPermission';
import { isProApp } from '../utility/proTools';
import { extractShellConnection } from '../impexp/createImpExpScript';
import { saveFileToDisk } from '../utility/exportFileTools';
export let data;
@@ -100,7 +101,7 @@ await dbgateApi.deployDb(${JSON.stringify(
props: {
conid: $currentDatabase?.connection?._id,
database: $currentDatabase?.name,
}
},
},
{
editor: {
@@ -113,12 +114,12 @@ await dbgateApi.deployDb(${JSON.stringify(
);
};
const handleOpenDuplicatorTab = () => {
const handleOpenDataDeployTab = () => {
openNewTab(
{
title: data.name,
icon: 'img duplicator',
tabComponent: 'DataDuplicatorTab',
icon: 'img data-deploy',
tabComponent: 'DataDeployTab',
props: {
conid: $currentDatabase?.connection?._id,
database: $currentDatabase?.name,
@@ -127,21 +128,56 @@ await dbgateApi.deployDb(${JSON.stringify(
{
editor: {
archiveFolder: data.name,
conid: $currentDatabase?.connection?._id,
database: $currentDatabase?.name,
},
}
);
};
const handleZipUnzip = async method => {
await apiCall(method, {
folder: data.name,
});
};
const handleDownloadZip = async () => {
saveFileToDisk(
async filePath => {
const zipped = await apiCall('archive/get-zipped-path', {
folder: data.name,
});
await apiCall('files/simple-copy', {
sourceFilePath: zipped.filePath,
targetFilePath: filePath,
});
},
{
formatLabel: 'ZIP files',
formatExtension: 'zip',
defaultFileName: data.name?.endsWith('.zip') ? data.name : data.name + '.zip',
}
);
};
function createMenu() {
return [
data.name != 'default' && { text: 'Delete', onClick: handleDelete },
data.name != 'default' && { text: 'Rename', onClick: handleRename },
data.name != 'default' &&
$currentDatabase && [
{ text: 'Data duplicator', onClick: handleOpenDuplicatorTab },
isProApp() && { text: 'Data deployer', onClick: handleOpenDataDeployTab },
{ text: 'Generate deploy DB SQL', onClick: handleGenerateDeploySql },
{ text: 'Shell: Deploy DB', onClick: handleGenerateDeployScript },
],
data.name != 'default' &&
isProApp() &&
data.name.endsWith('.zip') && { text: 'Unpack ZIP', onClick: () => handleZipUnzip('archive/unzip') },
data.name != 'default' &&
isProApp() &&
!data.name.endsWith('.zip') && { text: 'Pack (create ZIP)', onClick: () => handleZipUnzip('archive/zip') },
isProApp() && { text: 'Download ZIP', onClick: handleDownloadZip },
data.name != 'default' &&
hasPermission('dbops/model/compare') &&
@@ -158,7 +194,7 @@ await dbgateApi.deployDb(${JSON.stringify(
{...$$restProps}
{data}
title={data.name.endsWith('.link') ? data.name.slice(0, -5) : data.name}
icon={data.name.endsWith('.link') ? 'img link' : 'img archive-folder'}
icon={data.name.endsWith('.link') ? 'img link' : data.name.endsWith('.zip') ? 'img zipfile' : 'img archive-folder'}
isBold={data.name == $currentArchive}
on:click={() => ($currentArchive = data.name)}
menu={createMenu}

View File

@@ -330,15 +330,15 @@ await dbgateApi.dropAllDbObjects(${JSON.stringify(
});
};
const handleImportWithDbDuplicator = () => {
const handleShowDataDeployer = () => {
showModal(ChooseArchiveFolderModal, {
message: 'Choose archive folder for import from',
message: 'Choose archive folder for data deployer',
onConfirm: archiveFolder => {
openNewTab(
{
title: archiveFolder,
icon: 'img duplicator',
tabComponent: 'DataDuplicatorTab',
icon: 'img replicator',
tabComponent: 'DataDeployerTab',
props: {
conid: connection?._id,
database: name,
@@ -439,8 +439,8 @@ await dbgateApi.dropAllDbObjects(${JSON.stringify(
driver?.databaseEngineTypes?.includes('sql') &&
hasPermission(`dbops/import`) && {
onClick: handleImportWithDbDuplicator,
text: 'Import with DB duplicator',
onClick: handleShowDataDeployer,
text: 'Data deployer',
},
{ divider: true },

View File

@@ -7,6 +7,8 @@
tabComponent: string;
folder: string;
currentConnection: boolean;
extension: string;
label: string;
}
const sql: FileTypeHandler = {
@@ -15,6 +17,8 @@
tabComponent: 'QueryTab',
folder: 'sql',
currentConnection: true,
extension: 'sql',
label: 'SQL file',
};
const shell: FileTypeHandler = {
@@ -23,6 +27,8 @@
tabComponent: 'ShellTab',
folder: 'shell',
currentConnection: false,
extension: 'js',
label: 'JavaScript Shell script',
};
const markdown: FileTypeHandler = {
@@ -31,6 +37,8 @@
tabComponent: 'MarkdownEditorTab',
folder: 'markdown',
currentConnection: false,
extension: 'md',
label: 'Markdown file',
};
const charts: FileTypeHandler = {
@@ -39,6 +47,8 @@
tabComponent: 'ChartTab',
folder: 'charts',
currentConnection: true,
extension: 'json',
label: 'Chart file',
};
const query: FileTypeHandler = {
@@ -47,6 +57,8 @@
tabComponent: 'QueryDesignTab',
folder: 'query',
currentConnection: true,
extension: 'json',
label: 'Query design file',
};
const sqlite: FileTypeHandler = {
@@ -55,6 +67,8 @@
tabComponent: null,
folder: 'sqlite',
currentConnection: true,
extension: 'sqlite',
label: 'SQLite database',
};
const diagrams: FileTypeHandler = {
@@ -63,22 +77,52 @@
tabComponent: 'DiagramTab',
folder: 'diagrams',
currentConnection: true,
extension: 'json',
label: 'Diagram file',
};
const jobs: FileTypeHandler = {
const impexp: FileTypeHandler = {
icon: 'img export',
format: 'json',
tabComponent: 'ImportExportTab',
folder: 'jobs',
folder: 'impexp',
currentConnection: false,
extension: 'json',
label: 'Import/Export file',
};
const datadeploy: FileTypeHandler = isProApp()
? {
icon: 'img data-deploy',
format: 'json',
tabComponent: 'DataDeployTab',
folder: 'datadeploy',
currentConnection: false,
extension: 'json',
label: 'Data deploy file',
}
: undefined;
const dbcompare: FileTypeHandler = isProApp()
? {
icon: 'img compare',
format: 'json',
tabComponent: 'CompareModelTab',
folder: 'dbcompare',
currentConnection: false,
extension: 'json',
label: 'Database compare file',
}
: undefined;
const perspectives: FileTypeHandler = {
icon: 'img perspective',
format: 'json',
tabComponent: 'PerspectiveTab',
folder: 'pesrpectives',
currentConnection: true,
extension: 'json',
label: 'Perspective file',
};
const modtrans: FileTypeHandler = {
@@ -87,6 +131,8 @@
tabComponent: 'ModelTransformTab',
folder: 'modtrans',
currentConnection: false,
extension: 'json',
label: 'Model transform file',
};
export const SAVED_FILE_HANDLERS = {
@@ -98,8 +144,10 @@
sqlite,
diagrams,
perspectives,
jobs,
impexp,
modtrans,
datadeploy,
dbcompare,
};
export const extractKey = data => data.file;
@@ -122,6 +170,8 @@
import openNewTab from '../utility/openNewTab';
import AppObjectCore from './AppObjectCore.svelte';
import { isProApp } from '../utility/proTools';
import { saveFileToDisk } from '../utility/exportFileTools';
export let data;
@@ -148,6 +198,7 @@
hasPermission(`files/${data.folder}/write`) && { text: 'Create copy', onClick: handleCopy },
hasPermission(`files/${data.folder}/write`) && { text: 'Delete', onClick: handleDelete },
folder == 'markdown' && { text: 'Show page', onClick: showMarkdownPage },
{ text: 'Download', onClick: handleDownload },
];
}
@@ -182,6 +233,19 @@
});
};
const handleDownload = () => {
saveFileToDisk(
async filePath => {
await apiCall('files/export-file', {
folder,
file: data.file,
filePath,
});
},
{ formatLabel: handler.label, formatExtension: handler.format, defaultFileName: data.file }
);
};
async function openTab() {
const resp = await apiCall('files/load', { folder, file: data.file, format: handler.format });