1
1
mirror of https://github.com/Fabio286/antares.git synced 2025-02-10 16:50:42 +01:00

refactor: ts and composition api on WorkspaceExplorebar* components

This commit is contained in:
Fabio Di Stasio 2022-06-09 20:08:32 +02:00
parent be70b5be7f
commit bd46d17424
16 changed files with 853 additions and 910 deletions

View File

@ -87,7 +87,7 @@ export interface TableInfos {
updated: Date; updated: Date;
engine: string; engine: string;
comment: string; comment: string;
size: number; size: number | false;
autoIncrement: number; autoIncrement: number;
collation: string; collation: string;
} }
@ -216,6 +216,7 @@ export interface TriggerInfos {
sqlMode: string; sqlMode: string;
created: Date; created: Date;
charset: string; charset: string;
enabled?: boolean;
} }
export interface CreateTriggerParams { export interface CreateTriggerParams {
@ -231,8 +232,21 @@ export interface CreateTriggerParams {
export interface AlterTriggerParams extends CreateTriggerParams { export interface AlterTriggerParams extends CreateTriggerParams {
oldName?: string; oldName?: string;
} }
export interface TriggerFunctionInfos {
name: string;
type: string;
security: string;
}
// Routines & Functions // Routines & Functions
export interface FunctionParam {
context: string;
name: string;
type: string;
length: number;
}
export interface RoutineInfos { export interface RoutineInfos {
name: string; name: string;
type: string; type: string;
@ -242,17 +256,11 @@ export interface RoutineInfos {
comment?: string; comment?: string;
charset?: string; charset?: string;
security?: string; security?: string;
parameters?: FunctionParam[];
} }
export type FunctionInfos = RoutineInfos export type FunctionInfos = RoutineInfos
export interface FunctionParam {
context: string;
name: string;
type: string;
length: number;
}
export interface CreateRoutineParams { export interface CreateRoutineParams {
name: string; name: string;
parameters?: FunctionParam[]; parameters?: FunctionParam[];
@ -337,7 +345,7 @@ export interface SchemaInfos {
name: string; name: string;
size: number; size: number;
tables: TableInfos[]; tables: TableInfos[];
functions: RoutineInfos[]; functions: FunctionInfos[];
procedures: RoutineInfos[]; procedures: RoutineInfos[];
triggers: TriggerInfos[]; triggers: TriggerInfos[];
schedulers: EventInfos[]; schedulers: EventInfos[];

View File

@ -101,7 +101,7 @@ const contextMenu = (event: MouseEvent, connection: ConnectionParams) => {
const tooltipPosition = (e: Event) => { const tooltipPosition = (e: Event) => {
const el = e.target ? e.target : e; const el = e.target ? e.target : e;
const fromTop = window.pageYOffset + (el as HTMLElement).getBoundingClientRect().top - ((el as HTMLElement).offsetHeight / 4); const fromTop = window.scrollY + (el as HTMLElement).getBoundingClientRect().top - ((el as HTMLElement).offsetHeight / 4);
(el as HTMLElement).querySelector<HTMLElement>('.ex-tooltip-content').style.top = `${fromTop}px`; (el as HTMLElement).querySelector<HTMLElement>('.ex-tooltip-content').style.top = `${fromTop}px`;
}; };

View File

@ -161,8 +161,7 @@ const {
const searchInput: Ref<HTMLInputElement> = ref(null); const searchInput: Ref<HTMLInputElement> = ref(null);
const explorebar: Ref<HTMLInputElement> = ref(null); const explorebar: Ref<HTMLInputElement> = ref(null);
const resizer: Ref<HTMLInputElement> = ref(null); const resizer: Ref<HTMLInputElement> = ref(null);
// eslint-disable-next-line @typescript-eslint/no-explicit-any const schema: Ref<Component & { selectSchema: (name: string) => void; $refs: {schemaAccordion: HTMLDetailsElement} }[]> = ref(null);
const schema: Ref<Component & { selectSchema: (name: string) => void; $refs: any }[]> = ref(null);
const isRefreshing = ref(false); const isRefreshing = ref(false);
const isNewDBModal = ref(false); const isNewDBModal = ref(false);
const localWidth = ref(null); const localWidth = ref(null);

View File

@ -56,7 +56,7 @@
</ConfirmModal> </ConfirmModal>
<ModalAskParameters <ModalAskParameters
v-if="isAskingParameters" v-if="isAskingParameters"
:local-routine="localElement" :local-routine="(localElement as any)"
:client="workspace.client" :client="workspace.client"
@confirm="runElement" @confirm="runElement"
@close="hideAskParamsModal" @close="hideAskParamsModal"
@ -64,32 +64,31 @@
</BaseContextMenu> </BaseContextMenu>
</template> </template>
<script> <script setup lang="ts">
import { computed, Prop, Ref, ref } from 'vue';
import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n';
import { useNotificationsStore } from '@/stores/notifications'; import { useNotificationsStore } from '@/stores/notifications';
import { useWorkspacesStore } from '@/stores/workspaces'; import { useWorkspacesStore } from '@/stores/workspaces';
import BaseContextMenu from '@/components/BaseContextMenu'; import BaseContextMenu from '@/components/BaseContextMenu.vue';
import ConfirmModal from '@/components/BaseConfirmModal'; import ConfirmModal from '@/components/BaseConfirmModal.vue';
import ModalAskParameters from '@/components/ModalAskParameters'; import ModalAskParameters from '@/components/ModalAskParameters.vue';
import Triggers from '@/ipc-api/Triggers'; import Triggers from '@/ipc-api/Triggers';
import Routines from '@/ipc-api/Routines'; import Routines from '@/ipc-api/Routines';
import Functions from '@/ipc-api/Functions'; import Functions from '@/ipc-api/Functions';
import Schedulers from '@/ipc-api/Schedulers'; import Schedulers from '@/ipc-api/Schedulers';
import { storeToRefs } from 'pinia'; import { EventInfos, FunctionInfos, RoutineInfos, TriggerInfos } from 'common/interfaces/antares';
export default { const { t } = useI18n();
name: 'WorkspaceExploreBarMiscContext',
components: { const props = defineProps({
BaseContextMenu,
ConfirmModal,
ModalAskParameters
},
props: {
contextEvent: MouseEvent, contextEvent: MouseEvent,
selectedMisc: Object, selectedMisc: Object as Prop<{ name:string; type:string; enabled?: boolean }>,
selectedSchema: String selectedSchema: String
}, });
emits: ['close-context', 'reload'],
setup () { const emit = defineEmits(['close-context', 'reload']);
const { addNotification } = useNotificationsStore(); const { addNotification } = useNotificationsStore();
const workspacesStore = useWorkspacesStore(); const workspacesStore = useWorkspacesStore();
@ -97,104 +96,93 @@ export default {
const { const {
getWorkspace, getWorkspace,
changeBreadcrumbs,
addLoadingElement, addLoadingElement,
removeLoadingElement, removeLoadingElement,
removeTabs, removeTabs,
newTab newTab
} = workspacesStore; } = workspacesStore;
return { const isDeleteModal = ref(false);
addNotification, const isAskingParameters = ref(false);
selectedWorkspace, const localElement: Ref<TriggerInfos | RoutineInfos | FunctionInfos | EventInfos> = ref(null);
getWorkspace,
changeBreadcrumbs, const workspace = computed(() => {
addLoadingElement, return getWorkspace(selectedWorkspace.value);
removeLoadingElement, });
removeTabs,
newTab const customizations = computed(() => {
}; return getWorkspace(selectedWorkspace.value).customizations;
}, });
data () {
return { const deleteMessage = computed(() => {
isDeleteModal: false, switch (props.selectedMisc.type) {
isRunModal: false,
isAskingParameters: false,
localElement: {}
};
},
computed: {
workspace () {
return this.getWorkspace(this.selectedWorkspace);
},
customizations () {
return this.getWorkspace(this.selectedWorkspace).customizations;
},
deleteMessage () {
switch (this.selectedMisc.type) {
case 'trigger': case 'trigger':
return this.$t('message.deleteTrigger'); return t('message.deleteTrigger');
case 'procedure': case 'procedure':
return this.$t('message.deleteRoutine'); return t('message.deleteRoutine');
case 'function': case 'function':
case 'triggerFunction': case 'triggerFunction':
return this.$t('message.deleteFunction'); return t('message.deleteFunction');
case 'scheduler': case 'scheduler':
return this.$t('message.deleteScheduler'); return t('message.deleteScheduler');
default: default:
return ''; return '';
} }
} });
},
methods: { const showDeleteModal = () => {
showDeleteModal () { isDeleteModal.value = true;
this.isDeleteModal = true; };
},
hideDeleteModal () { const hideDeleteModal = () => {
this.isDeleteModal = false; isDeleteModal.value = false;
}, };
showAskParamsModal () {
this.isAskingParameters = true; const showAskParamsModal = () => {
}, isAskingParameters.value = true;
hideAskParamsModal () { };
this.isAskingParameters = false;
this.closeContext(); const hideAskParamsModal = () => {
}, isAskingParameters.value = false;
closeContext () { closeContext();
this.$emit('close-context'); };
},
async deleteMisc () { const closeContext = () => {
emit('close-context');
};
const deleteMisc = async () => {
try { try {
let res; let res;
switch (this.selectedMisc.type) { switch (props.selectedMisc.type) {
case 'trigger': case 'trigger':
res = await Triggers.dropTrigger({ res = await Triggers.dropTrigger({
uid: this.selectedWorkspace, uid: selectedWorkspace.value,
schema: this.selectedSchema, schema: props.selectedSchema,
trigger: this.selectedMisc.name trigger: props.selectedMisc.name
}); });
break; break;
case 'procedure': case 'procedure':
res = await Routines.dropRoutine({ res = await Routines.dropRoutine({
uid: this.selectedWorkspace, uid: selectedWorkspace.value,
schema: this.selectedSchema, schema: props.selectedSchema,
routine: this.selectedMisc.name routine: props.selectedMisc.name
}); });
break; break;
case 'function': case 'function':
case 'triggerFunction': case 'triggerFunction':
res = await Functions.dropFunction({ res = await Functions.dropFunction({
uid: this.selectedWorkspace, uid: selectedWorkspace.value,
schema: this.selectedSchema, schema: props.selectedSchema,
func: this.selectedMisc.name func: props.selectedMisc.name
}); });
break; break;
case 'scheduler': case 'scheduler':
res = await Schedulers.dropScheduler({ res = await Schedulers.dropScheduler({
uid: this.selectedWorkspace, uid: selectedWorkspace.value,
schema: this.selectedSchema, schema: props.selectedSchema,
scheduler: this.selectedMisc.name scheduler: props.selectedMisc.name
}); });
break; break;
} }
@ -202,198 +190,204 @@ export default {
const { status, response } = res; const { status, response } = res;
if (status === 'success') { if (status === 'success') {
this.removeTabs({ removeTabs({
uid: this.selectedWorkspace, uid: selectedWorkspace.value,
elementName: this.selectedMisc.name, elementName: props.selectedMisc.name,
elementType: this.selectedMisc.type, elementType: props.selectedMisc.type,
schema: this.selectedSchema schema: props.selectedSchema
}); });
this.closeContext(); closeContext();
this.$emit('reload'); emit('reload');
} }
else else
this.addNotification({ status: 'error', message: response }); addNotification({ status: 'error', message: response });
} }
catch (err) { catch (err) {
this.addNotification({ status: 'error', message: err.stack }); addNotification({ status: 'error', message: err.stack });
} }
}, };
runElementCheck () {
if (this.selectedMisc.type === 'procedure') const runElementCheck = () => {
this.runRoutineCheck(); if (props.selectedMisc.type === 'procedure')
else if (this.selectedMisc.type === 'function') runRoutineCheck();
this.runFunctionCheck(); else if (props.selectedMisc.type === 'function')
}, runFunctionCheck();
runElement (params) { };
if (this.selectedMisc.type === 'procedure')
this.runRoutine(params); const runElement = (params: string[]) => {
else if (this.selectedMisc.type === 'function') if (props.selectedMisc.type === 'procedure')
this.runFunction(params); runRoutine(params);
}, else if (props.selectedMisc.type === 'function')
async runRoutineCheck () { runFunction(params);
};
const runRoutineCheck = async () => {
const params = { const params = {
uid: this.selectedWorkspace, uid: selectedWorkspace.value,
schema: this.selectedSchema, schema: props.selectedSchema,
routine: this.selectedMisc.name routine: props.selectedMisc.name
}; };
try { try {
const { status, response } = await Routines.getRoutineInformations(params); const { status, response } = await Routines.getRoutineInformations(params);
if (status === 'success') if (status === 'success')
this.localElement = response; localElement.value = response;
else else
this.addNotification({ status: 'error', message: response }); addNotification({ status: 'error', message: response });
} }
catch (err) { catch (err) {
this.addNotification({ status: 'error', message: err.stack }); addNotification({ status: 'error', message: err.stack });
} }
if (this.localElement.parameters.length) if ((localElement.value as RoutineInfos).parameters.length)
this.showAskParamsModal(); showAskParamsModal();
else else
this.runRoutine(); runRoutine();
}, };
runRoutine (params) {
const runRoutine = (params?: string[]) => {
if (!params) params = []; if (!params) params = [];
let sql; let sql;
switch (this.workspace.client) { // TODO: move in a better place switch (workspace.value.client) { // TODO: move in a better place
case 'maria': case 'maria':
case 'mysql': case 'mysql':
case 'pg': case 'pg':
sql = `CALL ${this.localElement.name}(${params.join(',')})`; sql = `CALL ${localElement.value.name}(${params.join(',')})`;
break; break;
case 'mssql': case 'mssql':
sql = `EXEC ${this.localElement.name} ${params.join(',')}`; sql = `EXEC ${localElement.value.name} ${params.join(',')}`;
break; break;
default: default:
sql = `CALL \`${this.localElement.name}\`(${params.join(',')})`; sql = `CALL \`${localElement.value.name}\`(${params.join(',')})`;
} }
this.newTab({ newTab({
uid: this.workspace.uid, uid: workspace.value.uid,
content: sql, content: sql,
type: 'query', type: 'query',
schema: this.selectedSchema, schema: props.selectedSchema,
autorun: true autorun: true
}); });
this.closeContext(); closeContext();
}, };
async runFunctionCheck () {
const runFunctionCheck = async () => {
const params = { const params = {
uid: this.selectedWorkspace, uid: selectedWorkspace.value,
schema: this.selectedSchema, schema: props.selectedSchema,
func: this.selectedMisc.name func: props.selectedMisc.name
}; };
try { try {
const { status, response } = await Functions.getFunctionInformations(params); const { status, response } = await Functions.getFunctionInformations(params);
if (status === 'success') if (status === 'success')
this.localElement = response; localElement.value = response;
else else
this.addNotification({ status: 'error', message: response }); addNotification({ status: 'error', message: response });
} }
catch (err) { catch (err) {
this.addNotification({ status: 'error', message: err.stack }); addNotification({ status: 'error', message: err.stack });
} }
if (this.localElement.parameters.length) if ((localElement.value as FunctionInfos).parameters.length)
this.showAskParamsModal(); showAskParamsModal();
else else
this.runFunction(); runFunction();
}, };
runFunction (params) {
const runFunction = (params?: string[]) => {
if (!params) params = []; if (!params) params = [];
let sql; let sql;
switch (this.workspace.client) { // TODO: move in a better place switch (workspace.value.client) { // TODO: move in a better place
case 'maria': case 'maria':
case 'mysql': case 'mysql':
sql = `SELECT \`${this.localElement.name}\` (${params.join(',')})`; sql = `SELECT \`${localElement.value.name}\` (${params.join(',')})`;
break; break;
case 'pg': case 'pg':
sql = `SELECT ${this.localElement.name}(${params.join(',')})`; sql = `SELECT ${localElement.value.name}(${params.join(',')})`;
break; break;
case 'mssql': case 'mssql':
sql = `SELECT ${this.localElement.name} ${params.join(',')}`; sql = `SELECT ${localElement.value.name} ${params.join(',')}`;
break; break;
default: default:
sql = `SELECT \`${this.localElement.name}\` (${params.join(',')})`; sql = `SELECT \`${localElement.value.name}\` (${params.join(',')})`;
} }
this.newTab({ newTab({
uid: this.workspace.uid, uid: workspace.value.uid,
content: sql, content: sql,
type: 'query', type: 'query',
schema: this.selectedSchema, schema: props.selectedSchema,
autorun: true autorun: true
}); });
this.closeContext(); closeContext();
}, };
async toggleTrigger () {
this.addLoadingElement({ const toggleTrigger = async () => {
name: this.selectedMisc.name, addLoadingElement({
schema: this.selectedSchema, name: props.selectedMisc.name,
schema: props.selectedSchema,
type: 'trigger' type: 'trigger'
}); });
try { try {
const { status, response } = await Triggers.toggleTrigger({ const { status, response } = await Triggers.toggleTrigger({
uid: this.selectedWorkspace, uid: selectedWorkspace.value,
schema: this.selectedSchema, schema: props.selectedSchema,
trigger: this.selectedMisc.name, trigger: props.selectedMisc.name,
enabled: this.selectedMisc.enabled enabled: props.selectedMisc.enabled
}); });
if (status !== 'success') if (status !== 'success')
this.addNotification({ status: 'error', message: response }); addNotification({ status: 'error', message: response });
} }
catch (err) { catch (err) {
this.addNotification({ status: 'error', message: err.stack }); addNotification({ status: 'error', message: err.stack });
} }
this.removeLoadingElement({ removeLoadingElement({
name: this.selectedMisc.name, name: props.selectedMisc.name,
schema: this.selectedSchema, schema: props.selectedSchema,
type: 'trigger' type: 'trigger'
}); });
this.closeContext(); closeContext();
this.$emit('reload'); emit('reload');
}, };
async toggleScheduler () {
this.addLoadingElement({ const toggleScheduler = async () => {
name: this.selectedMisc.name, addLoadingElement({
schema: this.selectedSchema, name: props.selectedMisc.name,
schema: props.selectedSchema,
type: 'scheduler' type: 'scheduler'
}); });
try { try {
const { status, response } = await Schedulers.toggleScheduler({ const { status, response } = await Schedulers.toggleScheduler({
uid: this.selectedWorkspace, uid: selectedWorkspace.value,
schema: this.selectedSchema, schema: props.selectedSchema,
scheduler: this.selectedMisc.name, scheduler: props.selectedMisc.name,
enabled: this.selectedMisc.enabled enabled: props.selectedMisc.enabled
}); });
if (status !== 'success') if (status !== 'success')
this.addNotification({ status: 'error', message: response }); addNotification({ status: 'error', message: response });
} }
catch (err) { catch (err) {
this.addNotification({ status: 'error', message: err.stack }); addNotification({ status: 'error', message: err.stack });
} }
this.removeLoadingElement({ removeLoadingElement({
name: this.selectedMisc.name, name: props.selectedMisc.name,
schema: this.selectedSchema, schema: props.selectedSchema,
type: 'scheduler' type: 'scheduler'
}); });
this.closeContext(); closeContext();
this.$emit('reload'); emit('reload');
}
}
}; };
</script> </script>

View File

@ -1,112 +1,68 @@
<template> <template>
<BaseContextMenu <BaseContextMenu
:context-event="contextEvent" :context-event="props.contextEvent"
@close-context="closeContext" @close-context="closeContext"
> >
<div <div
v-if="selectedMisc === 'trigger'" v-if="props.selectedMisc === 'trigger'"
class="context-element" class="context-element"
@click="$emit('open-create-trigger-tab')" @click="emit('open-create-trigger-tab')"
> >
<span class="d-flex"><i class="mdi mdi-18px mdi-table-cog text-light pr-1" /> {{ $t('message.createNewTrigger') }}</span> <span class="d-flex"><i class="mdi mdi-18px mdi-table-cog text-light pr-1" /> {{ t('message.createNewTrigger') }}</span>
</div> </div>
<div <div
v-if="selectedMisc === 'procedure'" v-if="props.selectedMisc === 'procedure'"
class="context-element" class="context-element"
@click="$emit('open-create-routine-tab')" @click="emit('open-create-routine-tab')"
> >
<span class="d-flex"><i class="mdi mdi-18px mdi-sync-circle text-light pr-1" /> {{ $t('message.createNewRoutine') }}</span> <span class="d-flex"><i class="mdi mdi-18px mdi-sync-circle text-light pr-1" /> {{ t('message.createNewRoutine') }}</span>
</div> </div>
<div <div
v-if="selectedMisc === 'function'" v-if="props.selectedMisc === 'function'"
class="context-element" class="context-element"
@click="$emit('open-create-function-tab')" @click="emit('open-create-function-tab')"
> >
<span class="d-flex"><i class="mdi mdi-18px mdi-arrow-right-bold-box text-light pr-1" /> {{ $t('message.createNewFunction') }}</span> <span class="d-flex"><i class="mdi mdi-18px mdi-arrow-right-bold-box text-light pr-1" /> {{ t('message.createNewFunction') }}</span>
</div> </div>
<div <div
v-if="selectedMisc === 'triggerFunction'" v-if="props.selectedMisc === 'triggerFunction'"
class="context-element" class="context-element"
@click="$emit('open-create-trigger-function-tab')" @click="emit('open-create-trigger-function-tab')"
> >
<span class="d-flex"><i class="mdi mdi-18px mdi-cog-clockwise text-light pr-1" /> {{ $t('message.createNewFunction') }}</span> <span class="d-flex"><i class="mdi mdi-18px mdi-cog-clockwise text-light pr-1" /> {{ t('message.createNewFunction') }}</span>
</div> </div>
<div <div
v-if="selectedMisc === 'scheduler'" v-if="props.selectedMisc === 'scheduler'"
class="context-element" class="context-element"
@click="$emit('open-create-scheduler-tab')" @click="emit('open-create-scheduler-tab')"
> >
<span class="d-flex"><i class="mdi mdi-18px mdi-calendar-clock text-light pr-1" /> {{ $t('message.createNewScheduler') }}</span> <span class="d-flex"><i class="mdi mdi-18px mdi-calendar-clock text-light pr-1" /> {{ t('message.createNewScheduler') }}</span>
</div> </div>
</BaseContextMenu> </BaseContextMenu>
</template> </template>
<script> <script setup lang="ts">
import { useNotificationsStore } from '@/stores/notifications'; import { useI18n } from 'vue-i18n';
import { useWorkspacesStore } from '@/stores/workspaces'; import BaseContextMenu from '@/components/BaseContextMenu.vue';
import BaseContextMenu from '@/components/BaseContextMenu';
import { storeToRefs } from 'pinia';
export default { const { t } = useI18n();
name: 'WorkspaceExploreBarMiscContext',
components: { const props = defineProps({
BaseContextMenu
},
props: {
contextEvent: MouseEvent, contextEvent: MouseEvent,
selectedMisc: String, selectedMisc: String,
selectedSchema: String selectedSchema: String
}, });
emits: [
const emit = defineEmits([
'open-create-trigger-tab', 'open-create-trigger-tab',
'open-create-routine-tab', 'open-create-routine-tab',
'open-create-function-tab', 'open-create-function-tab',
'open-create-trigger-function-tab', 'open-create-trigger-function-tab',
'open-create-scheduler-tab', 'open-create-scheduler-tab',
'close-context' 'close-context'
], ]);
setup () {
const { addNotification } = useNotificationsStore();
const workspacesStore = useWorkspacesStore();
const { getSelected: selectedWorkspace } = storeToRefs(workspacesStore); const closeContext = () => {
emit('close-context');
const { getWorkspace, changeBreadcrumbs } = workspacesStore;
return {
addNotification,
selectedWorkspace,
getWorkspace,
changeBreadcrumbs
};
},
data () {
return {
localElement: {}
};
},
computed: {
workspace () {
return this.getWorkspace(this.selectedWorkspace);
}
},
methods: {
showDeleteModal () {
this.isDeleteModal = true;
},
hideDeleteModal () {
this.isDeleteModal = false;
},
showAskParamsModal () {
this.isAskingParameters = true;
},
hideAskParamsModal () {
this.isAskingParameters = false;
this.closeContext();
},
closeContext () {
this.$emit('close-context');
}
}
}; };
</script> </script>

View File

@ -25,7 +25,7 @@
<ul class="menu menu-nav pt-0"> <ul class="menu menu-nav pt-0">
<li <li
v-for="table of filteredTables" v-for="table of filteredTables"
:ref="breadcrumbs.schema === database.name && [breadcrumbs.table, breadcrumbs.view].includes(table.name) ? 'explorebar-selected' : ''" :ref="breadcrumbs.schema === database.name && [breadcrumbs.table, breadcrumbs.view].includes(table.name) ? 'explorebarSelected' : ''"
:key="table.name" :key="table.name"
class="menu-item" class="menu-item"
:class="{'selected': breadcrumbs.schema === database.name && [breadcrumbs.table, breadcrumbs.view].includes(table.name)}" :class="{'selected': breadcrumbs.schema === database.name && [breadcrumbs.table, breadcrumbs.view].includes(table.name)}"
@ -61,7 +61,7 @@
@contextmenu.prevent="showMiscFolderContext($event, 'trigger')" @contextmenu.prevent="showMiscFolderContext($event, 'trigger')"
> >
<i class="misc-icon mdi mdi-18px mdi-folder-cog mr-1" /> <i class="misc-icon mdi mdi-18px mdi-folder-cog mr-1" />
{{ $tc('word.trigger', 2) }} {{ t('word.trigger', 2) }}
</summary> </summary>
<div class="accordion-body"> <div class="accordion-body">
<div> <div>
@ -69,7 +69,7 @@
<li <li
v-for="trigger of filteredTriggers" v-for="trigger of filteredTriggers"
:key="trigger.name" :key="trigger.name"
:ref="breadcrumbs.schema === database.name && breadcrumbs.trigger === trigger.name ? 'explorebar-selected' : ''" :ref="breadcrumbs.schema === database.name && breadcrumbs.trigger === trigger.name ? 'explorebarSelected' : ''"
class="menu-item" class="menu-item"
:class="{'selected': breadcrumbs.schema === database.name && breadcrumbs.trigger === trigger.name}" :class="{'selected': breadcrumbs.schema === database.name && breadcrumbs.trigger === trigger.name}"
@mousedown.left="selectMisc({schema: database.name, misc: trigger, type: 'trigger'})" @mousedown.left="selectMisc({schema: database.name, misc: trigger, type: 'trigger'})"
@ -84,7 +84,7 @@
<div <div
v-if="trigger.enabled === false" v-if="trigger.enabled === false"
class="tooltip tooltip-left disabled-indicator" class="tooltip tooltip-left disabled-indicator"
:data-tooltip="$t('word.disabled')" :data-tooltip="t('word.disabled')"
> >
<i class="table-icon mdi mdi-pause mdi-18px mr-1" /> <i class="table-icon mdi mdi-pause mdi-18px mr-1" />
</div> </div>
@ -100,27 +100,27 @@
<summary <summary
class="accordion-header misc-name" class="accordion-header misc-name"
:class="{'text-bold': breadcrumbs.schema === database.name && breadcrumbs.routine}" :class="{'text-bold': breadcrumbs.schema === database.name && breadcrumbs.routine}"
@contextmenu.prevent="showMiscFolderContext($event, 'procedure')" @contextmenu.prevent="showMiscFolderContext($event, 'routine')"
> >
<i class="misc-icon mdi mdi-18px mdi-folder-sync mr-1" /> <i class="misc-icon mdi mdi-18px mdi-folder-sync mr-1" />
{{ $tc('word.storedRoutine', 2) }} {{ t('word.storedRoutine', 2) }}
</summary> </summary>
<div class="accordion-body"> <div class="accordion-body">
<div> <div>
<ul class="menu menu-nav pt-0"> <ul class="menu menu-nav pt-0">
<li <li
v-for="(procedure, i) of filteredProcedures" v-for="(routine, i) of filteredProcedures"
:key="`${procedure.name}-${i}`" :key="`${routine.name}-${i}`"
:ref="breadcrumbs.schema === database.name && breadcrumbs.routine === procedure.name ? 'explorebar-selected' : ''" :ref="breadcrumbs.schema === database.name && breadcrumbs.routine === routine.name ? 'explorebarSelected' : ''"
class="menu-item" class="menu-item"
:class="{'selected': breadcrumbs.schema === database.name && breadcrumbs.routine === procedure.name}" :class="{'selected': breadcrumbs.schema === database.name && breadcrumbs.routine === routine.name}"
@mousedown.left="selectMisc({schema: database.name, misc: procedure, type: 'routine'})" @mousedown.left="selectMisc({schema: database.name, misc: routine, type: 'routine'})"
@dblclick="openMiscPermanentTab({schema: database.name, misc: procedure, type: 'routine'})" @dblclick="openMiscPermanentTab({schema: database.name, misc: routine, type: 'routine'})"
@contextmenu.prevent="showMiscContext($event, {...procedure, type: 'procedure'})" @contextmenu.prevent="showMiscContext($event, {...routine, type: 'routine'})"
> >
<a class="table-name"> <a class="table-name">
<i class="table-icon mdi mdi-sync-circle mdi-18px mr-1" /> <i class="table-icon mdi mdi-sync-circle mdi-18px mr-1" />
<span v-html="highlightWord(procedure.name)" /> <span v-html="highlightWord(routine.name)" />
</a> </a>
</li> </li>
</ul> </ul>
@ -137,7 +137,7 @@
@contextmenu.prevent="showMiscFolderContext($event, 'triggerFunction')" @contextmenu.prevent="showMiscFolderContext($event, 'triggerFunction')"
> >
<i class="misc-icon mdi mdi-18px mdi-folder-refresh mr-1" /> <i class="misc-icon mdi mdi-18px mdi-folder-refresh mr-1" />
{{ $tc('word.triggerFunction', 2) }} {{ t('word.triggerFunction', 2) }}
</summary> </summary>
<div class="accordion-body"> <div class="accordion-body">
<div> <div>
@ -145,7 +145,7 @@
<li <li
v-for="(func, i) of filteredTriggerFunctions" v-for="(func, i) of filteredTriggerFunctions"
:key="`${func.name}-${i}`" :key="`${func.name}-${i}`"
:ref="breadcrumbs.schema === database.name && breadcrumbs.triggerFunction === func.name ? 'explorebar-selected' : ''" :ref="breadcrumbs.schema === database.name && breadcrumbs.triggerFunction === func.name ? 'explorebarSelected' : ''"
class="menu-item" class="menu-item"
:class="{'selected': breadcrumbs.schema === database.name && breadcrumbs.triggerFunction === func.name}" :class="{'selected': breadcrumbs.schema === database.name && breadcrumbs.triggerFunction === func.name}"
@mousedown.left="selectMisc({schema: database.name, misc: func, type: 'triggerFunction'})" @mousedown.left="selectMisc({schema: database.name, misc: func, type: 'triggerFunction'})"
@ -171,7 +171,7 @@
@contextmenu.prevent="showMiscFolderContext($event, 'function')" @contextmenu.prevent="showMiscFolderContext($event, 'function')"
> >
<i class="misc-icon mdi mdi-18px mdi-folder-move mr-1" /> <i class="misc-icon mdi mdi-18px mdi-folder-move mr-1" />
{{ $tc('word.function', 2) }} {{ t('word.function', 2) }}
</summary> </summary>
<div class="accordion-body"> <div class="accordion-body">
<div> <div>
@ -179,7 +179,7 @@
<li <li
v-for="(func, i) of filteredFunctions" v-for="(func, i) of filteredFunctions"
:key="`${func.name}-${i}`" :key="`${func.name}-${i}`"
:ref="breadcrumbs.schema === database.name && breadcrumbs.function === func.name ? 'explorebar-selected' : ''" :ref="breadcrumbs.schema === database.name && breadcrumbs.function === func.name ? 'explorebarSelected' : ''"
class="menu-item" class="menu-item"
:class="{'selected': breadcrumbs.schema === database.name && breadcrumbs.function === func.name}" :class="{'selected': breadcrumbs.schema === database.name && breadcrumbs.function === func.name}"
@mousedown.left="selectMisc({schema: database.name, misc: func, type: 'function'})" @mousedown.left="selectMisc({schema: database.name, misc: func, type: 'function'})"
@ -205,7 +205,7 @@
@contextmenu.prevent="showMiscFolderContext($event, 'scheduler')" @contextmenu.prevent="showMiscFolderContext($event, 'scheduler')"
> >
<i class="misc-icon mdi mdi-18px mdi-folder-clock mr-1" /> <i class="misc-icon mdi mdi-18px mdi-folder-clock mr-1" />
{{ $tc('word.scheduler', 2) }} {{ t('word.scheduler', 2) }}
</summary> </summary>
<div class="accordion-body"> <div class="accordion-body">
<div> <div>
@ -213,7 +213,7 @@
<li <li
v-for="scheduler of filteredSchedulers" v-for="scheduler of filteredSchedulers"
:key="scheduler.name" :key="scheduler.name"
:ref="breadcrumbs.schema === database.name && breadcrumbs.scheduler === scheduler.name ? 'explorebar-selected' : ''" :ref="breadcrumbs.schema === database.name && breadcrumbs.scheduler === scheduler.name ? 'explorebarSelected' : ''"
class="menu-item" class="menu-item"
:class="{'selected': breadcrumbs.schema === database.name && breadcrumbs.scheduler === scheduler.name}" :class="{'selected': breadcrumbs.schema === database.name && breadcrumbs.scheduler === scheduler.name}"
@mousedown.left="selectMisc({schema: database.name, misc: scheduler, type: 'scheduler'})" @mousedown.left="selectMisc({schema: database.name, misc: scheduler, type: 'scheduler'})"
@ -228,7 +228,7 @@
<div <div
v-if="scheduler.enabled === false" v-if="scheduler.enabled === false"
class="tooltip tooltip-left disabled-indicator" class="tooltip tooltip-left disabled-indicator"
:data-tooltip="$t('word.disabled')" :data-tooltip="t('word.disabled')"
> >
<i class="table-icon mdi mdi-pause mdi-18px mr-1" /> <i class="table-icon mdi mdi-pause mdi-18px mr-1" />
</div> </div>
@ -242,27 +242,29 @@
</details> </details>
</template> </template>
<script> <script setup lang="ts">
import { useSettingsStore } from '@/stores/settings'; import { computed, Prop, Ref, ref, watch } from 'vue';
import { useWorkspacesStore } from '@/stores/workspaces';
import { formatBytes } from 'common/libs/formatBytes';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n';
import { useSettingsStore } from '@/stores/settings';
import { Breadcrumb, useWorkspacesStore, WorkspaceStructure } from '@/stores/workspaces';
import { formatBytes } from 'common/libs/formatBytes';
import { EventInfos, FunctionInfos, RoutineInfos, TableInfos, TriggerFunctionInfos, TriggerInfos } from 'common/interfaces/antares';
// TODO: expose selectSchema & schemaAccordion const { t } = useI18n();
export default { const props = defineProps({
name: 'WorkspaceExploreBarSchema', database: Object as Prop<WorkspaceStructure>,
props: {
database: Object,
connection: Object connection: Object
}, });
emits: [
const emit = defineEmits([
'show-schema-context', 'show-schema-context',
'show-table-context', 'show-table-context',
'show-misc-context', 'show-misc-context',
'show-misc-folder-context' 'show-misc-folder-context'
], ]);
setup () {
const settingsStore = useSettingsStore(); const settingsStore = useSettingsStore();
const workspacesStore = useWorkspacesStore(); const workspacesStore = useWorkspacesStore();
@ -278,73 +280,67 @@ export default {
refreshSchema refreshSchema
} = workspacesStore; } = workspacesStore;
return { const schemaAccordion: Ref<HTMLDetailsElement> = ref(null);
applicationTheme, const explorebarSelected: Ref<HTMLElement[]> = ref(null);
getLoadedSchemas, const isLoading = ref(false);
getWorkspace,
getSearchTerm, const searchTerm = computed(() => {
changeBreadcrumbs, return getSearchTerm(props.connection.uid);
addLoadedSchema, });
newTab,
refreshSchema const filteredTables = computed(() => {
}; return props.database.tables.filter(table => table.name.search(searchTerm.value) >= 0);
}, });
data () {
return { const filteredTriggers = computed(() => {
isLoading: false return props.database.triggers.filter(trigger => trigger.name.search(searchTerm.value) >= 0);
}; });
},
computed: { const filteredProcedures = computed(() => {
searchTerm () { return props.database.procedures.filter(procedure => procedure.name.search(searchTerm.value) >= 0);
return this.getSearchTerm(this.connection.uid); });
},
filteredTables () { const filteredFunctions = computed(() => {
return this.database.tables.filter(table => table.name.search(this.searchTerm) >= 0); return props.database.functions.filter(func => func.name.search(searchTerm.value) >= 0);
}, });
filteredTriggers () {
return this.database.triggers.filter(trigger => trigger.name.search(this.searchTerm) >= 0); const filteredTriggerFunctions = computed(() => {
}, return props.database.triggerFunctions
filteredProcedures () { ? props.database.triggerFunctions.filter(func => func.name.search(searchTerm.value) >= 0)
return this.database.procedures.filter(procedure => procedure.name.search(this.searchTerm) >= 0);
},
filteredFunctions () {
return this.database.functions.filter(func => func.name.search(this.searchTerm) >= 0);
},
filteredTriggerFunctions () {
return this.database.triggerFunctions
? this.database.triggerFunctions.filter(func => func.name.search(this.searchTerm) >= 0)
: []; : [];
}, });
filteredSchedulers () {
return this.database.schedulers.filter(scheduler => scheduler.name.search(this.searchTerm) >= 0); const filteredSchedulers = computed(() => {
}, return props.database.schedulers.filter(scheduler => scheduler.name.search(searchTerm.value) >= 0);
workspace () { });
return this.getWorkspace(this.connection.uid);
}, const workspace = computed(() => {
breadcrumbs () { return getWorkspace(props.connection.uid);
return this.workspace.breadcrumbs; });
},
customizations () { const breadcrumbs = computed(() => {
return this.workspace.customizations; return workspace.value.breadcrumbs;
}, });
loadedSchemas () {
return this.getLoadedSchemas(this.connection.uid); const customizations = computed(() => {
}, return workspace.value.customizations;
maxSize () { });
return this.database.tables.reduce((acc, curr) => {
if (curr.size > acc) acc = curr.size; const loadedSchemas = computed(() => {
return getLoadedSchemas(props.connection.uid);
});
const maxSize = computed(() => {
return props.database.tables.reduce((acc: number, curr) => {
if (curr.size && curr.size > acc) acc = curr.size;
return acc; return acc;
}, 0); }, 0);
}, });
totalSize () {
return this.database.tables.reduce((acc, curr) => acc + curr.size, 0); watch(breadcrumbs, (newVal, oldVal) => {
}
},
watch: {
breadcrumbs (newVal, oldVal) {
if (JSON.stringify(newVal) !== JSON.stringify(oldVal)) { if (JSON.stringify(newVal) !== JSON.stringify(oldVal)) {
setTimeout(() => { setTimeout(() => {
const element = this.$refs['explorebar-selected'] ? this.$refs['explorebar-selected'][0] : null; const element = explorebarSelected.value ? explorebarSelected.value[0] : null;
if (element) { if (element) {
const rect = element.getBoundingClientRect(); const rect = element.getBoundingClientRect();
const elemTop = rect.top; const elemTop = rect.top;
@ -359,30 +355,31 @@ export default {
} }
}, 50); }, 50);
} }
});
const selectSchema = async (schema: string) => {
if (!loadedSchemas.value.has(schema) && !isLoading.value) {
isLoading.value = true;
setBreadcrumbs({ schema });
await refreshSchema({ uid: props.connection.uid, schema });
addLoadedSchema(schema);
isLoading.value = false;
} }
}, };
methods: {
formatBytes, const selectTable = ({ schema, table }: { schema: string; table: TableInfos }) => {
async selectSchema (schema) { newTab({
if (!this.loadedSchemas.has(schema) && !this.isLoading) { uid: props.connection.uid,
this.isLoading = true;
await this.refreshSchema({ uid: this.connection.uid, schema });
this.addLoadedSchema(schema);
this.isLoading = false;
}
},
selectTable ({ schema, table }) {
this.newTab({
uid: this.connection.uid,
elementName: table.name, elementName: table.name,
schema: this.database.name, schema: props.database.name,
type: 'temp-data', type: 'temp-data',
elementType: table.type elementType: table.type
}); });
this.setBreadcrumbs({ schema, [table.type]: table.name }); setBreadcrumbs({ schema, [table.type]: table.name });
}, };
selectMisc ({ schema, misc, type }) {
const selectMisc = ({ schema, misc, type }: { schema: string; misc: { name: string }; type: 'trigger' | 'triggerFunction' | 'function' | 'routine' | 'scheduler' }) => {
const miscTempTabs = { const miscTempTabs = {
trigger: 'temp-trigger-props', trigger: 'temp-trigger-props',
triggerFunction: 'temp-trigger-function-props', triggerFunction: 'temp-trigger-function-props',
@ -391,21 +388,23 @@ export default {
scheduler: 'temp-scheduler-props' scheduler: 'temp-scheduler-props'
}; };
this.newTab({ newTab({
uid: this.connection.uid, uid: props.connection.uid,
elementName: misc.name, elementName: misc.name,
schema: this.database.name, schema: props.database.name,
type: miscTempTabs[type], type: miscTempTabs[type],
elementType: type elementType: type
}); });
this.setBreadcrumbs({ schema, [type]: misc.name }); setBreadcrumbs({ schema, [type]: misc.name });
}, };
openDataTab ({ schema, table }) {
this.newTab({ uid: this.connection.uid, elementName: table.name, schema: this.database.name, type: 'data', elementType: table.type }); const openDataTab = ({ schema, table }: { schema: string; table: TableInfos }) => {
this.setBreadcrumbs({ schema, [table.type]: table.name }); newTab({ uid: props.connection.uid, elementName: table.name, schema: props.database.name, type: 'data', elementType: table.type });
}, setBreadcrumbs({ schema, [table.type]: table.name });
openMiscPermanentTab ({ schema, misc, type }) { };
const openMiscPermanentTab = ({ schema, misc, type }: { schema: string; misc: { name: string }; type: 'trigger' | 'triggerFunction' | 'function' | 'routine' | 'scheduler' }) => {
const miscTabs = { const miscTabs = {
trigger: 'trigger-props', trigger: 'trigger-props',
triggerFunction: 'trigger-function-props', triggerFunction: 'trigger-function-props',
@ -414,56 +413,64 @@ export default {
scheduler: 'scheduler-props' scheduler: 'scheduler-props'
}; };
this.newTab({ newTab({
uid: this.connection.uid, uid: props.connection.uid,
elementName: misc.name, elementName: misc.name,
schema: this.database.name, schema: props.database.name,
type: miscTabs[type], type: miscTabs[type],
elementType: type elementType: type
}); });
this.setBreadcrumbs({ schema, [type]: misc.name }); setBreadcrumbs({ schema, [type]: misc.name });
}, };
showSchemaContext (event, schema) {
this.$emit('show-schema-context', { event, schema }); const showSchemaContext = (event: MouseEvent, schema: string) => {
}, emit('show-schema-context', { event, schema });
showTableContext (event, table) { };
this.$emit('show-table-context', { event, schema: this.database.name, table });
}, const showTableContext = (event: MouseEvent, table: TableInfos) => {
showMiscContext (event, misc) { emit('show-table-context', { event, schema: props.database.name, table });
this.$emit('show-misc-context', { event, schema: this.database.name, misc }); };
},
showMiscFolderContext (event, type) { const showMiscContext = (event: MouseEvent, misc: TriggerInfos | TriggerFunctionInfos | RoutineInfos | FunctionInfos | EventInfos) => {
this.$emit('show-misc-folder-context', { event, schema: this.database.name, type }); emit('show-misc-context', { event, schema: props.database.name, misc });
}, };
piePercentage (val) {
const perc = val / this.maxSize * 100; const showMiscFolderContext = (event: MouseEvent, type: string) => {
if (this.applicationTheme === 'dark') emit('show-misc-folder-context', { event, schema: props.database.name, type });
};
const piePercentage = (val: number) => {
const perc = val / maxSize.value * 100;
if (applicationTheme.value === 'dark')
return { background: `conic-gradient(lime ${perc}%, white 0)` }; return { background: `conic-gradient(lime ${perc}%, white 0)` };
else else
return { background: `conic-gradient(teal ${perc}%, silver 0)` }; return { background: `conic-gradient(teal ${perc}%, silver 0)` };
}, };
setBreadcrumbs (payload) {
if (this.breadcrumbs.schema === payload.schema && this.breadcrumbs.table === payload.table) return; const setBreadcrumbs = (payload: Breadcrumb) => {
this.changeBreadcrumbs(payload); if (breadcrumbs.value.schema === payload.schema && breadcrumbs.value.table === payload.table) return;
}, changeBreadcrumbs(payload);
highlightWord (string) { };
const highlightWord = (string: string) => {
string = string.replaceAll('<', '&lt;').replaceAll('>', '&gt;'); string = string.replaceAll('<', '&lt;').replaceAll('>', '&gt;');
if (this.searchTerm) { if (searchTerm.value) {
const regexp = new RegExp(`(${this.searchTerm.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi'); const regexp = new RegExp(`(${searchTerm.value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi');
return string.replace(regexp, '<span class="text-primary">$1</span>'); return string.replace(regexp, '<span class="text-primary">$1</span>');
} }
else else
return string; return string;
}, };
checkLoadingStatus (name, type) {
return this.workspace.loadingElements.some(el => const checkLoadingStatus = (name: string, type: string) => {
return workspace.value.loadingElements.some(el =>
el.name === name && el.name === name &&
el.type === type && el.type === type &&
el.schema === this.database.name); el.schema === props.database.name);
}
}
}; };
defineExpose({ selectSchema, schemaAccordion });
</script> </script>
<style lang="scss"> <style lang="scss">

View File

@ -123,32 +123,25 @@
</BaseContextMenu> </BaseContextMenu>
</template> </template>
<script> <script setup lang="ts">
import { Component, computed, nextTick, Ref, ref } from 'vue';
import { storeToRefs } from 'pinia';
import { useNotificationsStore } from '@/stores/notifications'; import { useNotificationsStore } from '@/stores/notifications';
import { useWorkspacesStore } from '@/stores/workspaces'; import { useWorkspacesStore } from '@/stores/workspaces';
import BaseContextMenu from '@/components/BaseContextMenu'; import BaseContextMenu from '@/components/BaseContextMenu.vue';
import ConfirmModal from '@/components/BaseConfirmModal'; import ConfirmModal from '@/components/BaseConfirmModal.vue';
import ModalEditSchema from '@/components/ModalEditSchema'; import ModalEditSchema from '@/components/ModalEditSchema.vue';
import ModalExportSchema from '@/components/ModalExportSchema'; import ModalExportSchema from '@/components/ModalExportSchema.vue';
import ModalImportSchema from '@/components/ModalImportSchema'; import ModalImportSchema from '@/components/ModalImportSchema.vue';
import Schema from '@/ipc-api/Schema'; import Schema from '@/ipc-api/Schema';
import Application from '@/ipc-api/Application'; import Application from '@/ipc-api/Application';
import { storeToRefs } from 'pinia';
export default { const props = defineProps({
name: 'WorkspaceExploreBarSchemaContext',
components: {
BaseContextMenu,
ConfirmModal,
ModalEditSchema,
ModalExportSchema,
ModalImportSchema
},
props: {
contextEvent: MouseEvent, contextEvent: MouseEvent,
selectedSchema: String selectedSchema: String
}, });
emits: [
const emit = defineEmits([
'open-create-table-tab', 'open-create-table-tab',
'open-create-view-tab', 'open-create-view-tab',
'open-create-trigger-tab', 'open-create-trigger-tab',
@ -158,8 +151,8 @@ export default {
'open-create-scheduler-tab', 'open-create-scheduler-tab',
'close-context', 'close-context',
'reload' 'reload'
], ]);
setup () {
const { addNotification } = useNotificationsStore(); const { addNotification } = useNotificationsStore();
const workspacesStore = useWorkspacesStore(); const workspacesStore = useWorkspacesStore();
@ -170,112 +163,114 @@ export default {
changeBreadcrumbs changeBreadcrumbs
} = workspacesStore; } = workspacesStore;
return { const importModalRef: Ref<Component & {startImport: (file: string) => void}> = ref(null);
addNotification, const isDeleteModal = ref(false);
selectedWorkspace, const isEditModal = ref(false);
getWorkspace, const isExportSchemaModal = ref(false);
changeBreadcrumbs const isImportSchemaModal = ref(false);
const workspace = computed(() => getWorkspace(selectedWorkspace.value));
const openCreateTableTab = () => {
emit('open-create-table-tab');
}; };
},
data () { const openCreateViewTab = () => {
return { emit('open-create-view-tab');
isDeleteModal: false,
isEditModal: false,
isExportSchemaModal: false,
isImportSchemaModal: false
}; };
},
computed: { const openCreateTriggerTab = () => {
workspace () { emit('open-create-trigger-tab');
return this.getWorkspace(this.selectedWorkspace); };
}
}, const openCreateRoutineTab = () => {
methods: { emit('open-create-routine-tab');
openCreateTableTab () { };
this.$emit('open-create-table-tab');
}, const openCreateFunctionTab = () => {
openCreateViewTab () { emit('open-create-function-tab');
this.$emit('open-create-view-tab'); };
},
openCreateTriggerTab () { const openCreateTriggerFunctionTab = () => {
this.$emit('open-create-trigger-tab'); emit('open-create-trigger-function-tab');
}, };
openCreateRoutineTab () {
this.$emit('open-create-routine-tab'); const openCreateSchedulerTab = () => {
}, emit('open-create-scheduler-tab');
openCreateFunctionTab () { };
this.$emit('open-create-function-tab');
}, const showDeleteModal = () => {
openCreateTriggerFunctionTab () { isDeleteModal.value = true;
this.$emit('open-create-trigger-function-tab'); };
},
openCreateSchedulerTab () { const hideDeleteModal = () => {
this.$emit('open-create-scheduler-tab'); isDeleteModal.value = false;
}, };
showDeleteModal () {
this.isDeleteModal = true; const showEditModal = () => {
}, isEditModal.value = true;
hideDeleteModal () { };
this.isDeleteModal = false;
}, const hideEditModal = () => {
showEditModal () { isEditModal.value = false;
this.isEditModal = true; closeContext();
}, };
hideEditModal () {
this.isEditModal = false; const showExportSchemaModal = () => {
this.closeContext(); isExportSchemaModal.value = true;
}, };
showExportSchemaModal () {
this.isExportSchemaModal = true; const hideExportSchemaModal = () => {
}, isExportSchemaModal.value = false;
hideExportSchemaModal () { closeContext();
this.isExportSchemaModal = false; };
this.closeContext();
}, const showImportSchemaModal = () => {
showImportSchemaModal () { isImportSchemaModal.value = true;
this.isImportSchemaModal = true; };
},
hideImportSchemaModal () { const hideImportSchemaModal = () => {
this.isImportSchemaModal = false; isImportSchemaModal.value = false;
this.closeContext(); closeContext();
}, };
async initImport () {
const initImport = async () => {
const result = await Application.showOpenDialog({ properties: ['openFile'], filters: [{ name: 'SQL', extensions: ['sql'] }] }); const result = await Application.showOpenDialog({ properties: ['openFile'], filters: [{ name: 'SQL', extensions: ['sql'] }] });
if (result && !result.canceled) { if (result && !result.canceled) {
const file = result.filePaths[0]; const file = result.filePaths[0];
this.showImportSchemaModal(); showImportSchemaModal();
this.$nextTick(() => { await nextTick();
this.$refs.importModalRef.startImport(file); importModalRef.value.startImport(file);
});
} }
}, };
closeContext () {
this.$emit('close-context'); const closeContext = () => {
}, emit('close-context');
async deleteSchema () { };
const deleteSchema = async () => {
try { try {
const { status, response } = await Schema.deleteSchema({ const { status, response } = await Schema.deleteSchema({
uid: this.selectedWorkspace, uid: selectedWorkspace.value,
database: this.selectedSchema database: props.selectedSchema
}); });
if (status === 'success') { if (status === 'success') {
if (this.selectedSchema === this.workspace.breadcrumbs.schema) if (props.selectedSchema === workspace.value.breadcrumbs.schema)
this.changeBreadcrumbs({ schema: null }); changeBreadcrumbs({ schema: null });
this.closeContext(); closeContext();
this.$emit('reload'); emit('reload');
} }
else else
this.addNotification({ status: 'error', message: response }); addNotification({ status: 'error', message: response });
} }
catch (err) { catch (err) {
this.addNotification({ status: 'error', message: err.stack }); addNotification({ status: 'error', message: err.stack });
}
}
} }
}; };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.context-submenu { .context-submenu {
min-width: 150px !important; min-width: 150px !important;

View File

@ -71,27 +71,23 @@
</BaseContextMenu> </BaseContextMenu>
</template> </template>
<script> <script setup lang="ts">
import { computed, ref } from 'vue';
import { storeToRefs } from 'pinia';
import { useNotificationsStore } from '@/stores/notifications'; import { useNotificationsStore } from '@/stores/notifications';
import { useWorkspacesStore } from '@/stores/workspaces'; import { useWorkspacesStore } from '@/stores/workspaces';
import BaseContextMenu from '@/components/BaseContextMenu'; import BaseContextMenu from '@/components/BaseContextMenu.vue';
import ConfirmModal from '@/components/BaseConfirmModal'; import ConfirmModal from '@/components/BaseConfirmModal.vue';
import Tables from '@/ipc-api/Tables'; import Tables from '@/ipc-api/Tables';
import { storeToRefs } from 'pinia';
export default { const props = defineProps({
name: 'WorkspaceExploreBarTableContext',
components: {
BaseContextMenu,
ConfirmModal
},
props: {
contextEvent: MouseEvent, contextEvent: MouseEvent,
selectedTable: Object, selectedTable: Object,
selectedSchema: String selectedSchema: String
}, });
emits: ['close-context', 'duplicate-table', 'reload', 'delete-table'],
setup () { const emit = defineEmits(['close-context', 'duplicate-table', 'reload', 'delete-table']);
const { addNotification } = useNotificationsStore(); const { addNotification } = useNotificationsStore();
const workspacesStore = useWorkspacesStore(); const workspacesStore = useWorkspacesStore();
@ -100,122 +96,108 @@ export default {
const { const {
getWorkspace, getWorkspace,
newTab, newTab,
removeTabs,
addLoadingElement, addLoadingElement,
removeLoadingElement, removeLoadingElement,
changeBreadcrumbs changeBreadcrumbs
} = workspacesStore; } = workspacesStore;
return { const isDeleteModal = ref(false);
addNotification, const isEmptyModal = ref(false);
getWorkspace,
newTab, const workspace = computed(() => getWorkspace(selectedWorkspace.value));
removeTabs, const customizations = computed(() => workspace.value && workspace.value.customizations ? workspace.value.customizations : null);
addLoadingElement,
removeLoadingElement, const showDeleteModal = () => {
changeBreadcrumbs, isDeleteModal.value = true;
selectedWorkspace
}; };
},
data () { const hideDeleteModal = () => {
return { isDeleteModal.value = false;
isDeleteModal: false,
isEmptyModal: false
}; };
},
computed: { const showEmptyModal = () => {
workspace () { isEmptyModal.value = true;
return this.getWorkspace(this.selectedWorkspace); };
},
customizations () { const hideEmptyModal = () => {
return this.workspace && this.workspace.customizations ? this.workspace.customizations : {}; isEmptyModal.value = false;
} };
},
methods: { const closeContext = () => {
showDeleteModal () { emit('close-context');
this.isDeleteModal = true; };
},
hideDeleteModal () { const openTableSettingTab = () => {
this.isDeleteModal = false; newTab({
}, uid: selectedWorkspace.value,
showEmptyModal () { elementName: props.selectedTable.name,
this.isEmptyModal = true; schema: props.selectedSchema,
},
hideEmptyModal () {
this.isEmptyModal = false;
},
closeContext () {
this.$emit('close-context');
},
openTableSettingTab () {
this.newTab({
uid: this.selectedWorkspace,
elementName: this.selectedTable.name,
schema: this.selectedSchema,
type: 'table-props', type: 'table-props',
elementType: 'table' elementType: 'table'
}); });
this.changeBreadcrumbs({ changeBreadcrumbs({
schema: this.selectedSchema, schema: props.selectedSchema,
table: this.selectedTable.name table: props.selectedTable.name
}); });
this.closeContext(); closeContext();
}, };
openViewSettingTab () {
this.newTab({ const openViewSettingTab = () => {
uid: this.selectedWorkspace, newTab({
uid: selectedWorkspace.value,
elementType: 'table', elementType: 'table',
elementName: this.selectedTable.name, elementName: props.selectedTable.name,
schema: this.selectedSchema, schema: props.selectedSchema,
type: 'view-props' type: 'view-props'
}); });
this.changeBreadcrumbs({ changeBreadcrumbs({
schema: this.selectedSchema, schema: props.selectedSchema,
view: this.selectedTable.name view: props.selectedTable.name
}); });
this.closeContext(); closeContext();
}, };
duplicateTable () {
this.$emit('duplicate-table', { schema: this.selectedSchema, table: this.selectedTable });
},
async emptyTable () {
this.closeContext();
this.addLoadingElement({ const duplicateTable = () => {
name: this.selectedTable.name, emit('duplicate-table', { schema: props.selectedSchema, table: props.selectedTable });
schema: this.selectedSchema, };
const emptyTable = async () => {
closeContext();
addLoadingElement({
name: props.selectedTable.name,
schema: props.selectedSchema,
type: 'table' type: 'table'
}); });
try { try {
const { status, response } = await Tables.truncateTable({ const { status, response } = await Tables.truncateTable({
uid: this.selectedWorkspace, uid: selectedWorkspace.value,
table: this.selectedTable.name, table: props.selectedTable.name,
schema: this.selectedSchema schema: props.selectedSchema
}); });
if (status === 'success') if (status === 'success')
this.$emit('reload'); emit('reload');
else else
this.addNotification({ status: 'error', message: response }); addNotification({ status: 'error', message: response });
} }
catch (err) { catch (err) {
this.addNotification({ status: 'error', message: err.stack }); addNotification({ status: 'error', message: err.stack });
} }
this.removeLoadingElement({ removeLoadingElement({
name: this.selectedTable.name, name: props.selectedTable.name,
schema: this.selectedSchema, schema: props.selectedSchema,
type: 'table' type: 'table'
}); });
}, };
deleteTable () {
this.$emit('delete-table', { schema: this.selectedSchema, table: this.selectedTable }); const deleteTable = () => {
} emit('delete-table', { schema: props.selectedSchema, table: props.selectedTable });
}
}; };
</script> </script>

View File

@ -4,12 +4,12 @@ import connStringConstruct from '../libs/connStringDecode';
import { unproxify } from '../libs/unproxify'; import { unproxify } from '../libs/unproxify';
export default class { export default class {
static makeTest (params: ConnectionParams & { pgConnString: string }): Promise<IpcResponse> { static makeTest (params: ConnectionParams & { pgConnString?: string }): Promise<IpcResponse> {
const newParams = connStringConstruct(params) as ConnectionParams; const newParams = connStringConstruct(params) as ConnectionParams;
return ipcRenderer.invoke('test-connection', unproxify(newParams)); return ipcRenderer.invoke('test-connection', unproxify(newParams));
} }
static connect (params: ConnectionParams & { pgConnString: string }): Promise<IpcResponse> { static connect (params: ConnectionParams & { pgConnString?: string }): Promise<IpcResponse> {
const newParams = connStringConstruct(params) as ConnectionParams; const newParams = connStringConstruct(params) as ConnectionParams;
return ipcRenderer.invoke('connect', unproxify(newParams)); return ipcRenderer.invoke('connect', unproxify(newParams));
} }

View File

@ -1,9 +1,9 @@
import { AlterFunctionParams, CreateFunctionParams, FunctionInfos, IpcResponse } from 'common/interfaces/antares'; import { AlterFunctionParams, CreateFunctionParams, IpcResponse } from 'common/interfaces/antares';
import { ipcRenderer } from 'electron'; import { ipcRenderer } from 'electron';
import { unproxify } from '../libs/unproxify'; import { unproxify } from '../libs/unproxify';
export default class { export default class {
static getFunctionInformations (params: { uid: string; schema: string; func: string}): Promise<IpcResponse<FunctionInfos>> { static getFunctionInformations (params: { uid: string; schema: string; func: string}): Promise<IpcResponse> {
return ipcRenderer.invoke('get-function-informations', unproxify(params)); return ipcRenderer.invoke('get-function-informations', unproxify(params));
} }

View File

@ -1,9 +1,9 @@
import { ipcRenderer } from 'electron'; import { ipcRenderer } from 'electron';
import { unproxify } from '../libs/unproxify'; import { unproxify } from '../libs/unproxify';
import { AlterRoutineParams, CreateRoutineParams, IpcResponse, RoutineInfos } from 'common/interfaces/antares'; import { AlterRoutineParams, CreateRoutineParams, IpcResponse } from 'common/interfaces/antares';
export default class { export default class {
static getRoutineInformations (params: { uid: string; schema: string; routine: string}): Promise<IpcResponse<RoutineInfos>> { static getRoutineInformations (params: { uid: string; schema: string; routine: string}): Promise<IpcResponse> {
return ipcRenderer.invoke('get-routine-informations', unproxify(params)); return ipcRenderer.invoke('get-routine-informations', unproxify(params));
} }

View File

@ -19,7 +19,7 @@ export default class {
return ipcRenderer.invoke('create-scheduler', unproxify(params)); return ipcRenderer.invoke('create-scheduler', unproxify(params));
} }
static toggleScheduler (params: { uid: string; schema: string; scheduler: string}): Promise<IpcResponse> { static toggleScheduler (params: { uid: string; schema: string; scheduler: string; enabled: boolean}): Promise<IpcResponse> {
return ipcRenderer.invoke('toggle-scheduler', unproxify(params)); return ipcRenderer.invoke('toggle-scheduler', unproxify(params));
} }
} }

View File

@ -7,7 +7,7 @@ export default class {
return ipcRenderer.invoke('get-trigger-informations', unproxify(params)); return ipcRenderer.invoke('get-trigger-informations', unproxify(params));
} }
static dropTrigger (params: { schema: string; trigger: string }): Promise<IpcResponse> { static dropTrigger (params: { uid: string; schema: string; trigger: string }): Promise<IpcResponse> {
return ipcRenderer.invoke('drop-trigger', unproxify(params)); return ipcRenderer.invoke('drop-trigger', unproxify(params));
} }
@ -19,7 +19,7 @@ export default class {
return ipcRenderer.invoke('create-trigger', unproxify(params)); return ipcRenderer.invoke('create-trigger', unproxify(params));
} }
static toggleTrigger (params: { uid: string; schema: string; trigger: string }): Promise<IpcResponse> { static toggleTrigger (params: { uid: string; schema: string; trigger: string; enabled: boolean }): Promise<IpcResponse> {
return ipcRenderer.invoke('toggle-trigger', unproxify(params)); return ipcRenderer.invoke('toggle-trigger', unproxify(params));
} }
} }

View File

@ -10,7 +10,7 @@ const checkForSSl = (conn: string) => {
return conn.includes('ssl=true'); return conn.includes('ssl=true');
}; };
const connStringConstruct = (args: ConnectionParams & { pgConnString: string }): ConnectionParams => { const connStringConstruct = (args: ConnectionParams & { pgConnString?: string }): ConnectionParams => {
if (!args.pgConnString) if (!args.pgConnString)
return args; return args;

View File

@ -11,12 +11,14 @@ import { useConnectionsStore } from '@/stores/connections';
import { useNotificationsStore } from '@/stores/notifications'; import { useNotificationsStore } from '@/stores/notifications';
import { useSettingsStore } from '@/stores/settings'; import { useSettingsStore } from '@/stores/settings';
import { import {
ClientCode,
CollationInfos, CollationInfos,
ConnectionParams, ConnectionParams,
EventInfos, EventInfos,
FunctionInfos, FunctionInfos,
RoutineInfos, RoutineInfos,
TableInfos, TableInfos,
TriggerFunctionInfos,
TriggerInfos, TriggerInfos,
TypesGroup TypesGroup
} from 'common/interfaces/antares'; } from 'common/interfaces/antares';
@ -44,12 +46,13 @@ export interface WorkspaceStructure {
schedulers: EventInfos[]; schedulers: EventInfos[];
tables: TableInfos[]; tables: TableInfos[];
triggers: TriggerInfos[]; triggers: TriggerInfos[];
triggerFunctions: TriggerFunctionInfos[];
size: number; size: number;
} }
export interface Breadcrumb { export interface Breadcrumb {
function?: string; function?: string;
procedure?: string; routine?: string;
query?: string; query?: string;
scheduler?: string; scheduler?: string;
schema?: string; schema?: string;
@ -61,7 +64,7 @@ export interface Breadcrumb {
export interface Workspace { export interface Workspace {
uid: string; uid: string;
client?: string; client?: ClientCode;
connectionStatus: string; connectionStatus: string;
selectedTab: string | number; selectedTab: string | number;
searchTerm: string; searchTerm: string;
@ -133,7 +136,7 @@ export const useWorkspacesStore = defineStore('workspaces', {
else else
this.selectedWorkspace = uid; this.selectedWorkspace = uid;
}, },
async connectWorkspace (connection: ConnectionParams & { pgConnString: string }) { async connectWorkspace (connection: ConnectionParams & { pgConnString?: string }) {
this.workspaces = (this.workspaces as Workspace[]).map(workspace => workspace.uid === connection.uid this.workspaces = (this.workspaces as Workspace[]).map(workspace => workspace.uid === connection.uid
? { ? {
...workspace, ...workspace,
@ -405,7 +408,7 @@ export const useWorkspacesStore = defineStore('workspaces', {
table: null, table: null,
trigger: null, trigger: null,
triggerFunction: null, triggerFunction: null,
procedure: null, routine: null,
function: null, function: null,
scheduler: null, scheduler: null,
view: null, view: null,

View File

@ -21,7 +21,6 @@ test('launch app', async () => {
test('main window elements visibility', async () => { test('main window elements visibility', async () => {
const visibleSelectors = [ const visibleSelectors = [
'#titlebar',
'#window-content', '#window-content',
'#settingbar', '#settingbar',
'#footer' '#footer'