mirror of
https://github.com/Fabio286/antares.git
synced 2025-06-05 21:59:22 +02:00
feat: ability to export a table dump from table context menu
This commit is contained in:
@ -21,7 +21,15 @@
|
||||
<BaseTextEditor class="d-none" value="" />
|
||||
</div>
|
||||
</div>
|
||||
<ModalAllConnections v-if="isAllConnectionsModal" @close="isAllConnectionsModal = false" />
|
||||
<ModalAllConnections
|
||||
v-if="isAllConnectionsModal"
|
||||
@close="isAllConnectionsModal = false"
|
||||
/>
|
||||
|
||||
<ModalExportSchema
|
||||
v-if="isExportSchemaModal"
|
||||
@close="hideExportModal"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -33,9 +41,11 @@ import { useI18n } from 'vue-i18n';
|
||||
import { Menu, getCurrentWindow } from '@electron/remote';
|
||||
import { useApplicationStore } from '@/stores/application';
|
||||
import { useConnectionsStore } from '@/stores/connections';
|
||||
import { useSchemaExportStore } from '@/stores/schemaExport';
|
||||
import { useSettingsStore } from '@/stores/settings';
|
||||
import { useWorkspacesStore } from '@/stores/workspaces';
|
||||
import TheSettingBar from '@/components/TheSettingBar.vue';
|
||||
import ModalExportSchema from '@/components/ModalExportSchema.vue';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
@ -65,6 +75,10 @@ const { getSelected: selectedWorkspace } = storeToRefs(workspacesStore);
|
||||
const { checkVersionUpdate } = applicationStore;
|
||||
const { changeApplicationTheme } = settingsStore;
|
||||
|
||||
const schemaExportStore = useSchemaExportStore();
|
||||
const { hideExportModal } = schemaExportStore;
|
||||
const { isExportModal: isExportSchemaModal } = storeToRefs(schemaExportStore);
|
||||
|
||||
const isAllConnectionsModal: Ref<boolean> = ref(false);
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
|
@ -154,6 +154,7 @@
|
||||
v-for="item in tables"
|
||||
:key="item.table"
|
||||
class="tr"
|
||||
:class="{'selected': item.table === selectedTable}"
|
||||
>
|
||||
<div class="td">
|
||||
{{ item.table }}
|
||||
@ -278,6 +279,7 @@ import { useI18n } from 'vue-i18n';
|
||||
import { ClientCode, SchemaInfos } from 'common/interfaces/antares';
|
||||
import { ExportOptions, ExportState } from 'common/interfaces/exporter';
|
||||
import { useNotificationsStore } from '@/stores/notifications';
|
||||
import { useSchemaExportStore } from '@/stores/schemaExport';
|
||||
import { useWorkspacesStore } from '@/stores/workspaces';
|
||||
import { useFocusTrap } from '@/composables/useFocusTrap';
|
||||
import Application from '@/ipc-api/Application';
|
||||
@ -285,15 +287,12 @@ import Schema from '@/ipc-api/Schema';
|
||||
import { Customizations } from 'common/interfaces/customizations';
|
||||
import BaseSelect from '@/components/BaseSelect.vue';
|
||||
|
||||
const props = defineProps({
|
||||
selectedSchema: String
|
||||
});
|
||||
|
||||
const emit = defineEmits(['close']);
|
||||
const { t } = useI18n();
|
||||
|
||||
const { addNotification } = useNotificationsStore();
|
||||
const workspacesStore = useWorkspacesStore();
|
||||
const schemaExportStore = useSchemaExportStore();
|
||||
|
||||
const { getSelected: selectedWorkspace } = storeToRefs(workspacesStore);
|
||||
|
||||
@ -304,6 +303,8 @@ const {
|
||||
refreshSchema
|
||||
} = workspacesStore;
|
||||
|
||||
const { selectedTable, selectedSchema } = storeToRefs(schemaExportStore);
|
||||
|
||||
const isExporting = ref(false);
|
||||
const isRefreshing = ref(false);
|
||||
const progressPercentage = ref(0);
|
||||
@ -315,7 +316,7 @@ const tables: Ref<{
|
||||
includeDropStatement: boolean;
|
||||
}[]> = ref([]);
|
||||
const options: Ref<Partial<ExportOptions>> = ref({
|
||||
schema: props.selectedSchema,
|
||||
schema: selectedSchema.value,
|
||||
includes: {} as {[key: string]: boolean},
|
||||
outputFormat: 'sql' as 'sql' | 'sql.zip',
|
||||
sqlInsertAfter: 250,
|
||||
@ -327,7 +328,7 @@ const chosenFilename = ref('');
|
||||
const currentWorkspace = computed(() => getWorkspace(selectedWorkspace.value));
|
||||
const clientCustoms: Ref<Customizations> = computed(() => currentWorkspace.value.customizations);
|
||||
const schemaItems = computed(() => {
|
||||
const db: SchemaInfos = currentWorkspace.value.structure.find((db: SchemaInfos) => db.name === props.selectedSchema);
|
||||
const db: SchemaInfos = currentWorkspace.value.structure.find((db: SchemaInfos) => db.name === selectedSchema.value);
|
||||
if (db)
|
||||
return db.tables.filter(table => table.type === 'table');
|
||||
|
||||
@ -335,7 +336,7 @@ const schemaItems = computed(() => {
|
||||
});
|
||||
const filename = computed(() => {
|
||||
const date = moment().format('YYYY-MM-DD_HH-mm-ss');
|
||||
return `${props.selectedSchema}_${date}`;
|
||||
return `${selectedTable.value || selectedSchema.value}_${date}`;
|
||||
});
|
||||
const dumpFilePath = computed(() => `${basePath.value}/${chosenFilename.value || filename.value}.${options.value.outputFormat}`);
|
||||
const includeStructureStatus = computed(() => {
|
||||
@ -360,7 +361,7 @@ const startExport = async () => {
|
||||
const params = {
|
||||
uid,
|
||||
type: client,
|
||||
schema: props.selectedSchema,
|
||||
schema: selectedSchema.value,
|
||||
outputFile: dumpFilePath.value,
|
||||
tables: [...tables.value],
|
||||
...options.value
|
||||
@ -438,7 +439,7 @@ const toggleAllTablesOption = (option: 'includeStructure' | 'includeContent' |'i
|
||||
|
||||
const refresh = async () => {
|
||||
isRefreshing.value = true;
|
||||
await refreshSchema({ uid: currentWorkspace.value.uid, schema: props.selectedSchema });
|
||||
await refreshSchema({ uid: currentWorkspace.value.uid, schema: selectedSchema.value });
|
||||
isRefreshing.value = false;
|
||||
};
|
||||
|
||||
@ -453,12 +454,31 @@ const openPathDialog = async () => {
|
||||
|
||||
window.addEventListener('keydown', onKey);
|
||||
|
||||
if (selectedTable.value) {
|
||||
setTimeout(() => {
|
||||
const element = document.querySelector<HTMLElement>('.modal.active .selected');
|
||||
|
||||
if (element) {
|
||||
const rect = element.getBoundingClientRect();
|
||||
const elemTop = rect.top;
|
||||
const elemBottom = rect.bottom;
|
||||
const isVisible = (elemTop >= 0) && (elemBottom <= window.innerHeight);
|
||||
|
||||
if (!isVisible) {
|
||||
element.setAttribute('tabindex', '-1');
|
||||
element.focus();
|
||||
element.removeAttribute('tabindex');
|
||||
}
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
|
||||
basePath.value = await Application.getDownloadPathDirectory();
|
||||
tables.value = schemaItems.value.map(item => ({
|
||||
table: item.name,
|
||||
includeStructure: true,
|
||||
includeContent: true,
|
||||
includeDropStatement: true
|
||||
includeStructure: !selectedTable.value ? true : selectedTable.value === item.name,
|
||||
includeContent: !selectedTable.value ? true : selectedTable.value === item.name,
|
||||
includeDropStatement: !selectedTable.value ? true : selectedTable.value === item.name
|
||||
}));
|
||||
|
||||
const structure = ['functions', 'views', 'triggers', 'routines', 'schedulers'];
|
||||
@ -466,7 +486,7 @@ const openPathDialog = async () => {
|
||||
structure.forEach((feat: keyof Customizations) => {
|
||||
const val = clientCustoms.value[feat];
|
||||
if (val)
|
||||
options.value.includes[feat] = true;
|
||||
options.value.includes[feat] = !selectedTable.value;
|
||||
});
|
||||
|
||||
ipcRenderer.on('export-progress', updateProgress);
|
||||
|
@ -109,11 +109,6 @@
|
||||
:selected-schema="selectedSchema"
|
||||
@close="hideEditModal"
|
||||
/>
|
||||
<ModalExportSchema
|
||||
v-if="isExportSchemaModal"
|
||||
:selected-schema="selectedSchema"
|
||||
@close="hideExportSchemaModal"
|
||||
/>
|
||||
<ModalImportSchema
|
||||
v-if="isImportSchemaModal"
|
||||
ref="importModalRef"
|
||||
@ -128,10 +123,10 @@ import { Component, computed, nextTick, Ref, ref } from 'vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useNotificationsStore } from '@/stores/notifications';
|
||||
import { useWorkspacesStore } from '@/stores/workspaces';
|
||||
import { useSchemaExportStore } from '@/stores/schemaExport';
|
||||
import BaseContextMenu from '@/components/BaseContextMenu.vue';
|
||||
import ConfirmModal from '@/components/BaseConfirmModal.vue';
|
||||
import ModalEditSchema from '@/components/ModalEditSchema.vue';
|
||||
import ModalExportSchema from '@/components/ModalExportSchema.vue';
|
||||
import ModalImportSchema from '@/components/ModalImportSchema.vue';
|
||||
import Schema from '@/ipc-api/Schema';
|
||||
import Application from '@/ipc-api/Application';
|
||||
@ -158,6 +153,8 @@ const emit = defineEmits([
|
||||
|
||||
const { addNotification } = useNotificationsStore();
|
||||
const workspacesStore = useWorkspacesStore();
|
||||
const schemaExportStore = useSchemaExportStore();
|
||||
const { showExportModal } = schemaExportStore;
|
||||
|
||||
const { getSelected: selectedWorkspace } = storeToRefs(workspacesStore);
|
||||
|
||||
@ -169,7 +166,6 @@ const {
|
||||
const importModalRef: Ref<Component & {startImport: (file: string) => void}> = ref(null);
|
||||
const isDeleteModal = ref(false);
|
||||
const isEditModal = ref(false);
|
||||
const isExportSchemaModal = ref(false);
|
||||
const isImportSchemaModal = ref(false);
|
||||
|
||||
const workspace = computed(() => getWorkspace(selectedWorkspace.value));
|
||||
@ -220,11 +216,7 @@ const hideEditModal = () => {
|
||||
};
|
||||
|
||||
const showExportSchemaModal = () => {
|
||||
isExportSchemaModal.value = true;
|
||||
};
|
||||
|
||||
const hideExportSchemaModal = () => {
|
||||
isExportSchemaModal.value = false;
|
||||
showExportModal(props.selectedSchema);
|
||||
closeContext();
|
||||
};
|
||||
|
||||
|
@ -10,6 +10,13 @@
|
||||
>
|
||||
<span class="d-flex"><i class="mdi mdi-18px mdi-wrench-cog text-light pr-1" /> {{ t('application.settings') }}</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="selectedTable && selectedTable.type === 'table' && customizations.schemaExport"
|
||||
class="context-element"
|
||||
@click="showTableExportModal"
|
||||
>
|
||||
<span class="d-flex"><i class="mdi mdi-18px mdi-table-arrow-right text-light pr-1" /> {{ t('database.exportTable') }}</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="selectedTable && selectedTable.type === 'view' && customizations.viewSettings"
|
||||
class="context-element"
|
||||
@ -81,6 +88,7 @@ import { computed, ref } from 'vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useNotificationsStore } from '@/stores/notifications';
|
||||
import { useWorkspacesStore } from '@/stores/workspaces';
|
||||
import { useSchemaExportStore } from '@/stores/schemaExport';
|
||||
import BaseContextMenu from '@/components/BaseContextMenu.vue';
|
||||
import ConfirmModal from '@/components/BaseConfirmModal.vue';
|
||||
import Tables from '@/ipc-api/Tables';
|
||||
@ -98,6 +106,7 @@ const emit = defineEmits(['close-context', 'duplicate-table', 'reload', 'delete-
|
||||
|
||||
const { addNotification } = useNotificationsStore();
|
||||
const workspacesStore = useWorkspacesStore();
|
||||
const { showExportModal } = useSchemaExportStore();
|
||||
|
||||
const { getSelected: selectedWorkspace } = storeToRefs(workspacesStore);
|
||||
|
||||
@ -116,6 +125,11 @@ const forceTruncate = ref(false);
|
||||
const workspace = computed(() => getWorkspace(selectedWorkspace.value));
|
||||
const customizations = computed(() => workspace.value && workspace.value.customizations ? workspace.value.customizations : null);
|
||||
|
||||
const showTableExportModal = () => {
|
||||
showExportModal(props.selectedSchema, props.selectedTable.name);
|
||||
closeContext();
|
||||
};
|
||||
|
||||
const showDeleteModal = () => {
|
||||
isDeleteModal.value = true;
|
||||
};
|
||||
|
@ -181,6 +181,7 @@ export const enUS = {
|
||||
emptyTable: 'Empty table',
|
||||
duplicateTable: 'Duplicate table',
|
||||
deleteTable: 'Delete table',
|
||||
exportTable: 'Export table',
|
||||
emptyConfirm: 'Do you confirm to empty',
|
||||
thereAreNoIndexes: 'There are no indexes',
|
||||
thereAreNoForeign: 'There are no foreign keys',
|
||||
|
21
src/renderer/stores/schemaExport.ts
Normal file
21
src/renderer/stores/schemaExport.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { defineStore } from 'pinia';
|
||||
|
||||
export const useSchemaExportStore = defineStore('schemaExport', {
|
||||
state: () => ({
|
||||
isExportModal: false,
|
||||
selectedTable: undefined as undefined | string,
|
||||
selectedSchema: undefined as undefined | string
|
||||
}),
|
||||
actions: {
|
||||
showExportModal (schema?: string, table?: string) {
|
||||
this.selectedTable = table;
|
||||
this.selectedSchema = schema;
|
||||
this.isExportModal = true;
|
||||
},
|
||||
hideExportModal () {
|
||||
this.isExportModal = false;
|
||||
this.selectedTable = undefined;
|
||||
this.selectedSchema = undefined;
|
||||
}
|
||||
}
|
||||
});
|
Reference in New Issue
Block a user