diff --git a/packages/api/src/controllers/archive.js b/packages/api/src/controllers/archive.js index 39506a663..c1b38c3f2 100644 --- a/packages/api/src/controllers/archive.js +++ b/packages/api/src/controllers/archive.js @@ -38,12 +38,25 @@ module.exports = { const dir = path.join(archivedir(), folder); if (!(await fs.exists(dir))) return []; const files = await fs.readdir(dir); - return files - .filter(name => name.endsWith('.jsonl')) - .map(name => ({ - name: name.slice(0, -'.jsonl'.length), - type: 'jsonl', - })); + + function fileType(ext, type) { + return files + .filter(name => name.endsWith(ext)) + .map(name => ({ + name: name.slice(0, -ext.length), + type, + })); + } + + return [ + ...fileType('.jsonl', 'jsonl'), + ...fileType('.table.yaml', 'table.yaml'), + ...fileType('.view.sql', 'view.sql'), + ...fileType('.proc.sql', 'proc.sql'), + ...fileType('.func.sql', 'func.sql'), + ...fileType('.trigger.sql', 'trigger.sql'), + ...fileType('.matview.sql', 'matview.sql'), + ]; }, refreshFiles_meta: 'post', diff --git a/packages/api/src/controllers/files.js b/packages/api/src/controllers/files.js index ad3e91cb2..c080c8445 100644 --- a/packages/api/src/controllers/files.js +++ b/packages/api/src/controllers/files.js @@ -1,6 +1,6 @@ const fs = require('fs-extra'); const path = require('path'); -const { filesdir } = require('../utility/directories'); +const { filesdir, archivedir } = require('../utility/directories'); const hasPermission = require('../utility/hasPermission'); const socket = require('../utility/socket'); const scheduler = require('./scheduler'); @@ -58,23 +58,36 @@ module.exports = { load_meta: 'post', async load({ folder, file, format }) { - if (!hasPermission(`files/${folder}/read`)) return null; - const text = await fs.readFile(path.join(filesdir(), folder, file), { encoding: 'utf-8' }); - return deserialize(format, text); + if (folder.startsWith('archive:')) { + const text = await fs.readFile(path.join(archivedir(), folder.substring('archive:'.length), file), { + encoding: 'utf-8', + }); + return deserialize(format, text); + } else { + if (!hasPermission(`files/${folder}/read`)) return null; + const text = await fs.readFile(path.join(filesdir(), folder, file), { encoding: 'utf-8' }); + return deserialize(format, text); + } }, save_meta: 'post', async save({ folder, file, data, format }) { - if (!hasPermission(`files/${folder}/write`)) return; - const dir = path.join(filesdir(), folder); - if (!(await fs.exists(dir))) { - await fs.mkdir(dir); - } - await fs.writeFile(path.join(dir, file), serialize(format, data)); - socket.emitChanged(`files-changed-${folder}`); - socket.emitChanged(`all-files-changed`); - if (folder == 'shell') { - scheduler.reload(); + if (folder.startsWith('archive:')) { + const dir = path.join(archivedir(), folder.substring('archive:'.length)); + await fs.writeFile(path.join(dir, file), serialize(format, data)); + socket.emitChanged(`archive-files-changed-${folder.substring('archive:'.length)}`); + } else { + if (!hasPermission(`files/${folder}/write`)) return; + const dir = path.join(filesdir(), folder); + if (!(await fs.exists(dir))) { + await fs.mkdir(dir); + } + await fs.writeFile(path.join(dir, file), serialize(format, data)); + socket.emitChanged(`files-changed-${folder}`); + socket.emitChanged(`all-files-changed`); + if (folder == 'shell') { + scheduler.reload(); + } } }, diff --git a/packages/web/src/appobj/ArchiveFileAppObject.svelte b/packages/web/src/appobj/ArchiveFileAppObject.svelte index 35cd5f07b..c563c0307 100644 --- a/packages/web/src/appobj/ArchiveFileAppObject.svelte +++ b/packages/web/src/appobj/ArchiveFileAppObject.svelte @@ -12,23 +12,66 @@ }); } + async function openSqlFile(fileName, fileType, folderName) { + const connProps: any = {}; + let tooltip = undefined; + + const connection = _.get(getCurrentDatabase(), 'connection') || {}; + const database = _.get(getCurrentDatabase(), 'name'); + connProps.conid = connection._id; + connProps.database = database; + tooltip = `${getConnectionLabel(connection)}\n${database}`; + const resp = await axiosInstance.post('files/load', { + folder: 'archive:' + folderName, + file: fileName + '.' + fileType, + format: 'text', + }); + + openNewTab( + { + title: fileName, + icon: 'img sql-file', + tabComponent: 'QueryTab', + tooltip, + props: { + savedFile: fileName + '.' + fileType, + savedFolder: 'archive:' + folderName, + savedFormat: 'text', + ...connProps, + }, + }, + { editor: resp.data } + ); + } + export const extractKey = data => data.fileName; export const createMatcher = ({ fileName }) => filter => filterName(filter, fileName); - + const ARCHIVE_ICONS = { + jsonl: 'img archive', + 'table.yaml': 'img table', + 'view.sql': 'img view', + 'proce.sql': 'img procedure', + 'func.sql': 'img function', + 'trigger.sql': 'img sql-file', + 'matview.sql': 'img view', + }; diff --git a/packages/web/src/utility/saveTabFile.ts b/packages/web/src/utility/saveTabFile.ts index b2410a0ad..c04599c64 100644 --- a/packages/web/src/utility/saveTabFile.ts +++ b/packages/web/src/utility/saveTabFile.ts @@ -14,11 +14,11 @@ export default function saveTabFile(editor, saveAs, folder, format, fileExtensio const tabs = get(openedTabs); const tabid = editor.activator.tabid; const data = editor.getData(); - const { savedFile, savedFilePath } = tabs.find(x => x.tabid == tabid).props || {}; + const { savedFile, savedFilePath, savedFolder } = tabs.find(x => x.tabid == tabid).props || {}; const handleSave = async () => { if (savedFile) { - await axiosInstance.post('files/save', { folder, file: savedFile, data, format }); + await axiosInstance.post('files/save', { folder: savedFolder || folder, file: savedFile, data, format }); } if (savedFilePath) { await axiosInstance.post('files/save-as', { filePath: savedFilePath, data, format }); diff --git a/packages/web/src/widgets/ArchiveFilesList.svelte b/packages/web/src/widgets/ArchiveFilesList.svelte index aee0e0ffa..7847fb2d1 100644 --- a/packages/web/src/widgets/ArchiveFilesList.svelte +++ b/packages/web/src/widgets/ArchiveFilesList.svelte @@ -1,3 +1,15 @@ + +