From 4d7887a37950e9f635220f5833b6d1164b2f8b7f Mon Sep 17 00:00:00 2001 From: Jan Prochazka Date: Sun, 24 Apr 2022 15:03:04 +0200 Subject: [PATCH] export sql dump - can export to files --- packages/api/src/controllers/files.js | 29 +++++ packages/web/package.json | 1 + .../web/src/appobj/DatabaseAppObject.svelte | 8 +- .../web/src/appobj/SavedFileAppObject.svelte | 3 + .../buttons/FormStyledButtonLikeLabel.svelte | 4 +- .../src/modals/ExportDatabaseDumpModal.svelte | 108 ++++++++++++++++++ .../src/modals/ImportDatabaseDumpModal.svelte | 2 +- packages/web/src/modals/RunScriptModal.svelte | 15 ++- packages/web/src/utility/exportFileTools.ts | 56 ++++++--- .../web/src/widgets/SavedFilesList.svelte | 22 +++- yarn.lock | 5 + 11 files changed, 230 insertions(+), 23 deletions(-) create mode 100644 packages/web/src/modals/ExportDatabaseDumpModal.svelte diff --git a/packages/api/src/controllers/files.js b/packages/api/src/controllers/files.js index 6ef6e05f..6d86d14c 100644 --- a/packages/api/src/controllers/files.js +++ b/packages/api/src/controllers/files.js @@ -62,6 +62,15 @@ module.exports = { return true; }, + refresh_meta: true, + async refresh({ folders }, req) { + for (const folder of folders) { + socket.emitChanged(`files-changed-${folder}`); + socket.emitChanged(`all-files-changed`); + } + return true; + }, + copy_meta: true, async copy({ folder, file, newFile }, req) { if (!hasPermission(`files/${folder}/write`, req)) return false; @@ -177,4 +186,24 @@ module.exports = { await fs.writeFile(filePath, getDiagramExport(html, css, themeType, themeClassName)); return true; }, + + getFileRealPath_meta: true, + async getFileRealPath({ folder, file }, req) { + if (folder.startsWith('archive:')) { + if (!hasPermission(`archive/write`, req)) return false; + const dir = resolveArchiveFolder(folder.substring('archive:'.length)); + return path.join(dir, file); + } else if (folder.startsWith('app:')) { + if (!hasPermission(`apps/write`, req)) return false; + const app = folder.substring('app:'.length); + return path.join(appdir(), app, file); + } else { + if (!hasPermission(`files/${folder}/write`, req)) return false; + const dir = path.join(filesdir(), folder); + if (!(await fs.exists(dir))) { + await fs.mkdir(dir); + } + return path.join(dir, file); + } + }, }; diff --git a/packages/web/package.json b/packages/web/package.json index acd970c5..7c245d46 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -56,6 +56,7 @@ }, "dependencies": { "chartjs-plugin-zoom": "^1.2.0", + "date-fns": "^2.28.0", "interval-operations": "^1.0.7" } } diff --git a/packages/web/src/appobj/DatabaseAppObject.svelte b/packages/web/src/appobj/DatabaseAppObject.svelte index 0fa593c9..7039416d 100644 --- a/packages/web/src/appobj/DatabaseAppObject.svelte +++ b/packages/web/src/appobj/DatabaseAppObject.svelte @@ -87,7 +87,10 @@ }; const handleSqlDump = () => { - exportSqlDump(connection, name); + showModal(ExportDatabaseDumpModal, { + connection: { ...connection, database: name }, + }); + // exportSqlDump(connection, name); }; const handleSqlRestore = () => { @@ -212,8 +215,8 @@ { divider: true }, isSqlOrDoc && !connection.isReadOnly && { onClick: handleImport, text: 'Import wizard' }, isSqlOrDoc && { onClick: handleExport, text: 'Export wizard' }, - driver?.supportsDatabaseDump && { onClick: handleSqlDump, text: 'Backup/export SQL dump' }, driver?.databaseEngineTypes?.includes('sql') && { onClick: handleSqlRestore, text: 'Restore/import SQL dump' }, + driver?.supportsDatabaseDump && { onClick: handleSqlDump, text: 'Backup/export SQL dump' }, { divider: true }, isSqlOrDoc && { onClick: handleShowDiagram, text: 'Show diagram' }, isSqlOrDoc && { onClick: handleSqlGenerator, text: 'SQL Generator' }, @@ -282,6 +285,7 @@ import newQuery from '../query/newQuery'; import { exportSqlDump } from '../utility/exportFileTools'; import ImportDatabaseDumpModal from '../modals/ImportDatabaseDumpModal.svelte'; +import ExportDatabaseDumpModal from '../modals/ExportDatabaseDumpModal.svelte'; export let data; export let passProps; diff --git a/packages/web/src/appobj/SavedFileAppObject.svelte b/packages/web/src/appobj/SavedFileAppObject.svelte index e7321334..b2f6f43e 100644 --- a/packages/web/src/appobj/SavedFileAppObject.svelte +++ b/packages/web/src/appobj/SavedFileAppObject.svelte @@ -1,4 +1,6 @@ + + + + Export database dump + +
Target: {outputLabel}
+ +
+ {#if electron} + + {:else} + + {/if} + +
+ + + handleSubmit(e.detail)} disabled={!outputFile} /> + + +
+
diff --git a/packages/web/src/modals/ImportDatabaseDumpModal.svelte b/packages/web/src/modals/ImportDatabaseDumpModal.svelte index 8b70835a..6784ef3c 100644 --- a/packages/web/src/modals/ImportDatabaseDumpModal.svelte +++ b/packages/web/src/modals/ImportDatabaseDumpModal.svelte @@ -79,7 +79,7 @@ {/if} - + diff --git a/packages/web/src/modals/RunScriptModal.svelte b/packages/web/src/modals/RunScriptModal.svelte index 2bf5d826..9b666b96 100644 --- a/packages/web/src/modals/RunScriptModal.svelte +++ b/packages/web/src/modals/RunScriptModal.svelte @@ -12,7 +12,10 @@ export let script; export let header; - let isRunning; + export let openResultLabel; + export let onOpenResult; + + let isRunning = true; let runid; let isCanceled; @@ -68,6 +71,16 @@ {:else} {/if} + + {#if onOpenResult && !isRunning} + { + closeCurrentModal(); + onOpenResult(); + }} + /> + {/if} diff --git a/packages/web/src/utility/exportFileTools.ts b/packages/web/src/utility/exportFileTools.ts index 352f0cfe..f330bc26 100644 --- a/packages/web/src/utility/exportFileTools.ts +++ b/packages/web/src/utility/exportFileTools.ts @@ -26,6 +26,28 @@ export async function importSqlDump(inputFile, connection) { // }); } +export async function exportSqlDump(outputFile, connection, databaseName, pureFileName) { + const script = getCurrentConfig().allowShellScripting ? new ScriptWriter() : new ScriptWriterJson(); + + script.dumpDatabase({ + connection, + databaseName, + outputFile, + }); + + showModal(RunScriptModal, { + script: script.getScript(), + header: 'Exporting database', + onOpenResult: + pureFileName && !getElectron() + ? () => { + window.open(`${resolveApi()}/uploads/get?file=${pureFileName}`, '_blank'); + } + : null, + openResultLabel: 'Download SQL file', + }); +} + async function runImportExportScript({ script, runningMessage, canceledMessage, finishedMessage, afterFinish = null }) { const electron = getElectron(); @@ -126,25 +148,25 @@ export async function exportQuickExportFile(dataName, reader, format, columnMap ); } -export async function exportSqlDump(connection, databaseName) { - await saveExportedFile( - [{ name: 'SQL files', extensions: ['sql'] }], - `${databaseName}.sql`, - 'sql', - `${databaseName}-dump`, - filePath => { - const script = getCurrentConfig().allowShellScripting ? new ScriptWriter() : new ScriptWriterJson(); +// export async function exportSqlDump(connection, databaseName) { +// await saveExportedFile( +// [{ name: 'SQL files', extensions: ['sql'] }], +// `${databaseName}.sql`, +// 'sql', +// `${databaseName}-dump`, +// filePath => { +// const script = getCurrentConfig().allowShellScripting ? new ScriptWriter() : new ScriptWriterJson(); - script.dumpDatabase({ - connection, - databaseName, - outputFile: filePath, - }); +// script.dumpDatabase({ +// connection, +// databaseName, +// outputFile: filePath, +// }); - return script.getScript(); - } - ); -} +// return script.getScript(); +// } +// ); +// } export async function saveFileToDisk( filePathFunc, diff --git a/packages/web/src/widgets/SavedFilesList.svelte b/packages/web/src/widgets/SavedFilesList.svelte index 4920441e..14aed58d 100644 --- a/packages/web/src/widgets/SavedFilesList.svelte +++ b/packages/web/src/widgets/SavedFilesList.svelte @@ -2,9 +2,17 @@ import _ from 'lodash'; import AppObjectList from '../appobj/AppObjectList.svelte'; import * as savedFileAppObject from '../appobj/SavedFileAppObject.svelte'; + import CloseSearchButton from '../buttons/CloseSearchButton.svelte'; + import InlineButton from '../buttons/InlineButton.svelte'; + import SearchBoxWrapper from '../elements/SearchBoxWrapper.svelte'; + import SearchInput from '../elements/SearchInput.svelte'; + import FontIcon from '../icons/FontIcon.svelte'; + import { apiCall } from '../utility/api'; import { useFiles } from '../utility/metadataLoaders'; import WidgetsInnerContainer from './WidgetsInnerContainer.svelte'; + let filter = ''; + const sqlFiles = useFiles({ folder: 'sql' }); const shellFiles = useFiles({ folder: 'shell' }); const markdownFiles = useFiles({ folder: 'markdown' }); @@ -22,8 +30,20 @@ ...($sqliteFiles || []), ...($diagramFiles || []), ]; + + function handleRefreshFiles() { + apiCall('files/refresh', { folders: ['sql', 'shell', 'markdown', 'charts', 'query', 'sqlite', 'diagrams'] }); + } - _.startCase(data.folder)} /> + + + + + + + + + _.startCase(data.folder)} {filter} /> diff --git a/yarn.lock b/yarn.lock index 0ff2f0a4..3fd40555 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3198,6 +3198,11 @@ date-fns@^2.0.1: resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.9.0.tgz#d0b175a5c37ed5f17b97e2272bbc1fa5aec677d2" integrity sha512-khbFLu/MlzLjEzy9Gh8oY1hNt/Dvxw3J6Rbc28cVoYWQaC1S3YI4xwkF9ZWcjDLscbZlY9hISMr66RFzZagLsA== +date-fns@^2.28.0: + version "2.28.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.28.0.tgz#9570d656f5fc13143e50c975a3b6bbeb46cd08b2" + integrity sha512-8d35hViGYx/QH0icHYCeLmsLmMUheMmTyV9Fcm6gvNwdw31yXXH+O85sOBJ+OLnLQMKZowvpKb6FgMIQjcpvQw== + date-utils@*: version "1.2.21" resolved "https://registry.yarnpkg.com/date-utils/-/date-utils-1.2.21.tgz#61fb16cdc1274b3c9acaaffe9fc69df8720a2b64"