diff --git a/packages/web/src/commands/CommandListener.svelte b/packages/web/src/commands/CommandListener.svelte index 8b75bec91..527fde9d0 100644 --- a/packages/web/src/commands/CommandListener.svelte +++ b/packages/web/src/commands/CommandListener.svelte @@ -31,6 +31,7 @@ if (command) { e.preventDefault(); + e.stopPropagation(); command.onClick(); } } diff --git a/packages/web/src/modals/SaveFileModal.svelte b/packages/web/src/modals/SaveFileModal.svelte new file mode 100644 index 000000000..064235e71 --- /dev/null +++ b/packages/web/src/modals/SaveFileModal.svelte @@ -0,0 +1,81 @@ + + + + + Save file + + + + {#if electron} + { + const file = electron.remote.dialog.showSaveDialogSync(electron.remote.getCurrentWindow(), { + filters: [ + { name: `${fileExtension.toUpperCase()} files`, extensions: [fileExtension] }, + { name: `All files`, extensions: ['*'] }, + ], + defaultPath: filePath || `${name}.${fileExtension}`, + properties: ['showOverwriteConfirmation'], + }); + if (file) { + handleSaveToDisk(file); + } + }} + /> + {/if} + + + diff --git a/packages/web/src/tabs/QueryTab.svelte b/packages/web/src/tabs/QueryTab.svelte index 7930771d8..df6daa04e 100644 --- a/packages/web/src/tabs/QueryTab.svelte +++ b/packages/web/src/tabs/QueryTab.svelte @@ -46,6 +46,14 @@ enabledStore: derived(currentQuery, query => query != null), onClick: () => get(currentQuery).formatCode(), }); + registerSaveCommands({ + idPrefix: 'query', + category: 'Query', + editorStore: currentQuery, + folder: 'sql', + format: 'text', + fileExtension: 'sql', + }); diff --git a/packages/web/src/utility/saveTabFile.ts b/packages/web/src/utility/saveTabFile.ts new file mode 100644 index 000000000..204e600e2 --- /dev/null +++ b/packages/web/src/utility/saveTabFile.ts @@ -0,0 +1,75 @@ +import { derived, get } from 'svelte/store'; +import { showModal } from '../modals/modalTools'; +import { openedTabs } from '../stores'; +import axiosInstance from '../utility/axiosInstance'; +import { changeTab } from './common'; +import SaveFileModal from '../modals/SaveFileModal.svelte'; +import registerCommand from '../commands/registerCommand'; + +export function saveTabEnabledStore(editorStore) { + return derived(editorStore, editor => editor != null); +} + +export default function saveTabFile(editorStore, saveAs, folder, format, fileExtension) { + const editor: any = get(editorStore); + const tabs = get(openedTabs); + const tabid = editor.getTabId(); + const data = editor.getData(); + const { savedFile, savedFilePath } = tabs.find(x => x.tabid == tabid).props || {}; + + const handleSave = async () => { + if (savedFile) { + await axiosInstance.post('files/save', { folder, file: savedFile, data, format }); + } + if (savedFilePath) { + await axiosInstance.post('files/save-as', { filePath: savedFilePath, data, format }); + } + }; + + const onSave = (title, newProps) => { + changeTab(tabid, tab => ({ + ...tab, + title, + props: { + ...tab.props, + savedFormat: format, + ...newProps, + }, + })); + }; + + if ((savedFile || savedFilePath) && !saveAs) { + handleSave(); + } else { + showModal(SaveFileModal, { + data, + folder, + format, + fileExtension, + name: savedFile || 'newFile', + filePath: savedFilePath, + onSave, + }); + } +} + +export function registerSaveCommands({ idPrefix, category, editorStore, folder, format, fileExtension }) { + registerCommand({ + id: idPrefix + '.save', + category, + name: 'Save', + keyText: 'Ctrl+S', + icon: 'icon save', + toolbar: true, + enabledStore: saveTabEnabledStore(editorStore), + onClick: () => saveTabFile(editorStore, false, folder, format, fileExtension), + }); + registerCommand({ + id: idPrefix + '.saveAs', + category, + name: 'Save As', + keyText: 'Ctrl+Shift+S', + enabledStore: saveTabEnabledStore(editorStore), + onClick: () => saveTabFile(editorStore, true, folder, format, fileExtension), + }); +}