mirror of
https://github.com/Fabio286/antares.git
synced 2025-06-05 21:59:22 +02:00
feat: unsaved file reminder closing file tabs
This commit is contained in:
@ -19,7 +19,10 @@
|
|||||||
<div ref="resizer" class="query-area-resizer" />
|
<div ref="resizer" class="query-area-resizer" />
|
||||||
<div ref="queryAreaFooter" class="workspace-query-runner-footer">
|
<div ref="queryAreaFooter" class="workspace-query-runner-footer">
|
||||||
<div class="workspace-query-buttons">
|
<div class="workspace-query-buttons">
|
||||||
<div @mouseenter="setCancelButtonVisibility(true)" @mouseleave="setCancelButtonVisibility(false)">
|
<div
|
||||||
|
@mouseenter="setCancelButtonVisibility(true)"
|
||||||
|
@mouseleave="setCancelButtonVisibility(false)"
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
v-if="showCancel && isQuering"
|
v-if="showCancel && isQuering"
|
||||||
class="btn btn-primary btn-sm cancellable"
|
class="btn btn-primary btn-sm cancellable"
|
||||||
@ -109,7 +112,7 @@
|
|||||||
:title="t('general.save')"
|
:title="t('general.save')"
|
||||||
@click="saveQuery()"
|
@click="saveQuery()"
|
||||||
>
|
>
|
||||||
<BaseIcon icon-name="mdiContentSaveOutline" :size="24" />
|
<BaseIcon icon-name="mdiHeartPlusOutline" :size="24" />
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="btn btn-dark btn-sm"
|
class="btn btn-dark btn-sm"
|
||||||
@ -117,13 +120,13 @@
|
|||||||
:title="t('database.savedQueries')"
|
:title="t('database.savedQueries')"
|
||||||
@click="openSavedModal()"
|
@click="openSavedModal()"
|
||||||
>
|
>
|
||||||
<BaseIcon icon-name="mdiStarOutline" :size="24" />
|
<BaseIcon icon-name="mdiNotebookHeartOutline" :size="24" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="btn-group">
|
<div class="btn-group">
|
||||||
<button
|
<button
|
||||||
class="btn btn-dark btn-sm mr-0"
|
class="btn btn-dark btn-sm mr-0"
|
||||||
:disabled="!filePath"
|
:disabled="!filePath || lastSavedQuery === query"
|
||||||
:title="t('application.saveFile')"
|
:title="t('application.saveFile')"
|
||||||
@click="saveFile()"
|
@click="saveFile()"
|
||||||
>
|
>
|
||||||
@ -275,7 +278,7 @@ import { uidGen } from 'common/libs/uidGen';
|
|||||||
import { ipcRenderer } from 'electron';
|
import { ipcRenderer } from 'electron';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { format } from 'sql-formatter';
|
import { format } from 'sql-formatter';
|
||||||
import { Component, computed, onBeforeUnmount, onMounted, Prop, Ref, ref, watch } from 'vue';
|
import { Component, computed, onBeforeUnmount, onMounted, Prop, Ref, ref, toRaw, watch } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
import BaseIcon from '@/components/BaseIcon.vue';
|
import BaseIcon from '@/components/BaseIcon.vue';
|
||||||
@ -338,6 +341,7 @@ const queryName = ref('');
|
|||||||
const query = ref('');
|
const query = ref('');
|
||||||
const filePath = ref('');
|
const filePath = ref('');
|
||||||
const lastQuery = ref('');
|
const lastQuery = ref('');
|
||||||
|
const lastSavedQuery = ref('');
|
||||||
const isCancelling = ref(false);
|
const isCancelling = ref(false);
|
||||||
const showCancel = ref(false);
|
const showCancel = ref(false);
|
||||||
const autocommit = ref(true);
|
const autocommit = ref(true);
|
||||||
@ -361,6 +365,9 @@ const databaseSchemas = computed(() => {
|
|||||||
});
|
});
|
||||||
const hasResults = computed(() => results.value.length && results.value[0].rows);
|
const hasResults = computed(() => results.value.length && results.value[0].rows);
|
||||||
const hasAffected = computed(() => affectedCount.value || (!resultsCount.value && affectedCount.value !== null));
|
const hasAffected = computed(() => affectedCount.value || (!resultsCount.value && affectedCount.value !== null));
|
||||||
|
const isChanged = computed(() => {
|
||||||
|
return filePath.value && lastSavedQuery.value !== query.value;
|
||||||
|
});
|
||||||
|
|
||||||
watch(query, (val) => {
|
watch(query, (val) => {
|
||||||
clearTimeout(debounceTimeout.value);
|
clearTimeout(debounceTimeout.value);
|
||||||
@ -426,6 +433,10 @@ watch(() => props.tab.content, () => {
|
|||||||
queryEditor.value.editor.session.setValue(query.value);
|
queryEditor.value.editor.session.setValue(query.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
watch(isChanged, (val) => {
|
||||||
|
setUnsavedChanges({ uid: props.connection.uid, tUid: props.tabUid, isChanged: val });
|
||||||
|
});
|
||||||
|
|
||||||
const runQuery = async (query: string) => {
|
const runQuery = async (query: string) => {
|
||||||
if (!query || isQuering.value) return;
|
if (!query || isQuering.value) return;
|
||||||
isQuering.value = true;
|
isQuering.value = true;
|
||||||
@ -725,23 +736,27 @@ const openFile = async () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const saveFileAs = async () => {
|
const saveFileAs = async () => {
|
||||||
const result = await Application.showSaveDialog({ filters: [{ name: 'SQL', extensions: ['sql'] }], defaultPath: `${queryName.value || 'query'}.sql` });
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
const result: any = await Application.showSaveDialog({ filters: [{ name: 'SQL', extensions: ['sql'] }], defaultPath: `${queryName.value || 'query'}.sql` });
|
||||||
if (result && !result.canceled) {
|
if (result && !result.canceled) {
|
||||||
await Application.writeFile(result.filePath, query.value);
|
await Application.writeFile(result.filePath, query.value);
|
||||||
addNotification({ status: 'success', message: t('general.actionSuccessful', { action: 'SAVE FILE' }) });
|
addNotification({ status: 'success', message: t('general.actionSuccessful', { action: t('application.saveFile') }) });
|
||||||
queryName.value = result.filePath.split('/').pop().split('\\').pop();
|
queryName.value = result.filePath.split('/').pop().split('\\').pop();
|
||||||
filePath.value = result.filePath;
|
filePath.value = result.filePath;
|
||||||
|
lastSavedQuery.value = toRaw(query.value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const saveFile = async () => {
|
const saveFile = async () => {
|
||||||
await Application.writeFile(filePath.value, query.value);
|
await Application.writeFile(filePath.value, query.value);
|
||||||
addNotification({ status: 'success', message: t('general.actionSuccessful', { action: 'SAVE FILE' }) });
|
addNotification({ status: 'success', message: t('general.actionSuccessful', { action: t('application.saveFile') }) });
|
||||||
|
lastSavedQuery.value = toRaw(query.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
const loadFileContent = async (file: string) => {
|
const loadFileContent = async (file: string) => {
|
||||||
const content = await Application.readFile(file);
|
const content = await Application.readFile(file);
|
||||||
query.value = content;
|
query.value = content;
|
||||||
|
lastSavedQuery.value = content;
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
@ -844,4 +859,4 @@ onBeforeUnmount(() => {
|
|||||||
min-height: 200px;
|
min-height: 200px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>filePathsfilePathsfilePaths
|
||||||
|
@ -36,7 +36,7 @@ export default class {
|
|||||||
return ipcRenderer.invoke('read-file', path);
|
return ipcRenderer.invoke('read-file', path);
|
||||||
}
|
}
|
||||||
|
|
||||||
static writeFile (path: string, content:any) {
|
static writeFile (path: string, content: unknown) {
|
||||||
return ipcRenderer.invoke('write-file', path, content);
|
return ipcRenderer.invoke('write-file', path, content);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user