mirror of
https://github.com/Fabio286/antares.git
synced 2025-06-05 21:59:22 +02:00
feat: modal with all connections
This commit is contained in:
171
src/renderer/components/ModalAllConnections.vue
Normal file
171
src/renderer/components/ModalAllConnections.vue
Normal file
@ -0,0 +1,171 @@
|
||||
<template>
|
||||
<Teleport to="#window-content">
|
||||
<div class="modal active">
|
||||
<a class="modal-overlay" @click.stop="closeModal" />
|
||||
<div ref="trapRef" class="modal-container p-0 pb-4">
|
||||
<div class="modal-header pl-2">
|
||||
<div class="modal-title h6">
|
||||
<div class="d-flex">
|
||||
<i class="mdi mdi-24px mdi-apps mr-1" />
|
||||
<span class="cut-text">{{ $t('message.allConnections') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<a class="btn btn-clear c-hand" @click.stop="closeModal" />
|
||||
</div>
|
||||
<div class="modal-body py-0">
|
||||
<div class="columns">
|
||||
<div
|
||||
v-for="connection in connections"
|
||||
:key="connection.uid"
|
||||
class="column col-md-6 col-lg-4 col-3 p-3"
|
||||
>
|
||||
<div class="panel">
|
||||
<div class="panel-header text-center">
|
||||
<figure class="avatar avatar-lg">
|
||||
<i class="settingbar-element-icon dbi" :class="[`dbi-${connection.client}`]" />
|
||||
</figure>
|
||||
<div class="panel-title h6 mt-10">
|
||||
{{ getConnectionName(connection.uid) }}
|
||||
</div>
|
||||
<div class="panel-subtitle">
|
||||
{{ connection.client }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-body text-center">
|
||||
<div v-if="connection.databasePath">
|
||||
<div class="pl-1 text-break">
|
||||
<span class="text-bold">PATH:</span> {{ connection.databasePath }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div class="pl-1 text-break">
|
||||
<span class="text-bold">HOST:</span> {{ connection.host }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="connection.user">
|
||||
<div class="pl-1 text-break">
|
||||
<span class="text-bold">USER:</span> {{ connection.user }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="connection.schema">
|
||||
<div class="pl-1 text-break">
|
||||
<span class="text-bold">SCHEMA:</span> {{ connection.schema }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="connection.database">
|
||||
<div class="pl-1 text-break">
|
||||
<span class="text-bold">DATABASE:</span> {{ connection.database }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-footer text-center py-0">
|
||||
<div v-if="connection.ssl" class="chip bg-success mt-2">
|
||||
SSL
|
||||
</div>
|
||||
<div v-if="connection.ssh" class="chip bg-success mt-2">
|
||||
SSH
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Teleport>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useFocusTrap } from '@/composables/useFocusTrap';
|
||||
import { useConnectionsStore } from '@/stores/connections';
|
||||
import { useWorkspacesStore } from '@/stores/workspaces';
|
||||
import { storeToRefs } from 'pinia';
|
||||
|
||||
const connectionsStore = useConnectionsStore();
|
||||
const workspacesStore = useWorkspacesStore();
|
||||
|
||||
const { connections } = storeToRefs(connectionsStore);
|
||||
const { getConnectionName } = connectionsStore;
|
||||
const { getWorkspace } = workspacesStore;
|
||||
|
||||
const { trapRef } = useFocusTrap();
|
||||
|
||||
const emit = defineEmits(['close']);
|
||||
|
||||
const closeModal = () => emit('close');
|
||||
|
||||
const onKey = (e:KeyboardEvent) => {
|
||||
e.stopPropagation();
|
||||
if (e.key === 'Escape')
|
||||
closeModal();
|
||||
};
|
||||
|
||||
const getStatusBadge = (uid: string) => {
|
||||
if (getWorkspace(uid)) {
|
||||
const status = getWorkspace(uid).connectionStatus;
|
||||
|
||||
switch (status) {
|
||||
case 'connected':
|
||||
return 'badge badge-connected';
|
||||
case 'connecting':
|
||||
return 'badge badge-connecting';
|
||||
case 'failed':
|
||||
return 'badge badge-failed';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('keydown', onKey, { capture: true });
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.vscroll {
|
||||
height: 1000px;
|
||||
overflow: auto;
|
||||
overflow-anchor: none;
|
||||
}
|
||||
|
||||
.column-resizable {
|
||||
&:hover,
|
||||
&:active {
|
||||
resize: horizontal;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.table-column-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.sort-icon {
|
||||
font-size: 0.7rem;
|
||||
line-height: 1;
|
||||
margin-left: 0.2rem;
|
||||
}
|
||||
|
||||
.result-tabs {
|
||||
background: transparent !important;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.modal {
|
||||
align-items: flex-start;
|
||||
|
||||
.modal-container {
|
||||
max-width: 75vw;
|
||||
margin-top: 10vh;
|
||||
|
||||
.modal-body {
|
||||
height: 80vh;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.processes-toolbar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
</style>
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div id="settingbar">
|
||||
<div class="settingbar-top-elements">
|
||||
<div ref="sidebarConnections" class="settingbar-top-elements">
|
||||
<SettingBarContext
|
||||
v-if="isContext"
|
||||
:context-event="contextEvent"
|
||||
@ -24,7 +24,7 @@
|
||||
@mouseover.self="tooltipPosition"
|
||||
>
|
||||
<i class="settingbar-element-icon dbi" :class="[`dbi-${element.client}`, getStatusBadge(element.uid), (pinnedConnections.has(element.uid) ? 'settingbar-element-pin' : false)]" />
|
||||
<span v-if="!isDragging" class="ex-tooltip-content">{{ getConnectionName(element.uid) }}</span>
|
||||
<span v-if="!isDragging && !isScrolling" class="ex-tooltip-content">{{ getConnectionName(element.uid) }}</span>
|
||||
</li>
|
||||
</template>
|
||||
</Draggable>
|
||||
@ -41,7 +41,21 @@
|
||||
@mouseover.self="tooltipPosition"
|
||||
>
|
||||
<i class="settingbar-element-icon dbi" :class="[`dbi-${connection.client}`, getStatusBadge(connection.uid)]" />
|
||||
<span v-if="!isDragging" class="ex-tooltip-content">{{ getConnectionName(connection.uid) }}</span>
|
||||
<span v-if="!isDragging && !isScrolling" class="ex-tooltip-content">{{ getConnectionName(connection.uid) }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="settingbar-middle-elements">
|
||||
<ul class="settingbar-elements">
|
||||
<li
|
||||
v-if="isScrollable"
|
||||
class="settingbar-element btn btn-link ex-tooltip"
|
||||
@click="emit('show-connections-modal')"
|
||||
@mouseover.self="tooltipPosition"
|
||||
>
|
||||
<i class="settingbar-element-icon mdi mdi-24px mdi-dots-horizontal text-light" />
|
||||
<span class="ex-tooltip-content">{{ $t('message.allConnections') }}</span>
|
||||
</li>
|
||||
<li
|
||||
class="settingbar-element btn btn-link ex-tooltip"
|
||||
@ -79,6 +93,7 @@ import { useWorkspacesStore } from '@/stores/workspaces';
|
||||
import * as Draggable from 'vuedraggable';
|
||||
import SettingBarContext from '@/components/SettingBarContext.vue';
|
||||
import { ConnectionParams } from 'common/interfaces/antares';
|
||||
import { useElementBounding, useScroll } from '@vueuse/core';
|
||||
|
||||
const applicationStore = useApplicationStore();
|
||||
const connectionsStore = useConnectionsStore();
|
||||
@ -92,11 +107,18 @@ const { showSettingModal, showScratchpad } = applicationStore;
|
||||
const { getConnectionName, updatePinnedConnections } = connectionsStore;
|
||||
const { getWorkspace, selectWorkspace } = workspacesStore;
|
||||
|
||||
const emit = defineEmits(['show-connections-modal']);
|
||||
|
||||
const isLinux = process.platform === 'linux';
|
||||
|
||||
const sidebarConnections: Ref<HTMLDivElement> = ref(null);
|
||||
const isContext: Ref<boolean> = ref(false);
|
||||
const isDragging: Ref<boolean> = ref(false);
|
||||
const isScrollable: Ref<boolean> = ref(false);
|
||||
const isScrolling = ref(useScroll(sidebarConnections)?.isScrolling);
|
||||
const contextEvent: Ref<MouseEvent> = ref(null);
|
||||
const contextConnection: Ref<ConnectionParams> = ref(null);
|
||||
const sidebarConnectionsHeight = ref(useElementBounding(sidebarConnections)?.height);
|
||||
|
||||
const pinnedConnectionsArr = computed({
|
||||
get: () => [...pinnedConnections.value].map(c => storedConnections.value.find(sc => sc.uid === c)).filter(Boolean),
|
||||
@ -133,11 +155,14 @@ const contextMenu = (event: MouseEvent, connection: ConnectionParams) => {
|
||||
};
|
||||
|
||||
const tooltipPosition = (e: Event) => {
|
||||
const el = e.target ? e.target : e;
|
||||
const fromTop = isLinux
|
||||
? window.scrollY + (el as HTMLElement).getBoundingClientRect().top + ((el as HTMLElement).offsetHeight / 4)
|
||||
: window.scrollY + (el as HTMLElement).getBoundingClientRect().top - ((el as HTMLElement).offsetHeight / 4);
|
||||
(el as HTMLElement).querySelector<HTMLElement>('.ex-tooltip-content').style.top = `${fromTop}px`;
|
||||
const el = (e.target ? e.target : e) as unknown as HTMLElement;
|
||||
const tooltip = el.querySelector<HTMLElement>('.ex-tooltip-content');
|
||||
if (tooltip) {
|
||||
const fromTop = isLinux
|
||||
? window.scrollY + el.getBoundingClientRect().top + (el.offsetHeight / 4)
|
||||
: window.scrollY + el.getBoundingClientRect().top - (el.offsetHeight / 4);
|
||||
tooltip.style.top = `${fromTop}px`;
|
||||
}
|
||||
};
|
||||
|
||||
const getStatusBadge = (uid: string) => {
|
||||
@ -166,6 +191,10 @@ const dragStop = (e: any) => {
|
||||
}, 200);
|
||||
};
|
||||
|
||||
watch(sidebarConnectionsHeight, (value) => {
|
||||
isScrollable.value = value < sidebarConnections.value.scrollHeight;
|
||||
});
|
||||
|
||||
watch(unpinnedConnectionsArr, (newVal, oldVal) => {
|
||||
if (JSON.stringify(newVal) !== JSON.stringify(oldVal)) {
|
||||
setTimeout(() => {
|
||||
@ -193,7 +222,7 @@ watch(unpinnedConnectionsArr, (newVal, oldVal) => {
|
||||
height: calc(100vh - #{$excluding-size});
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
// justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0;
|
||||
z-index: 9;
|
||||
@ -201,7 +230,7 @@ watch(unpinnedConnectionsArr, (newVal, oldVal) => {
|
||||
.settingbar-top-elements {
|
||||
overflow-x: hidden;
|
||||
overflow-y: overlay;
|
||||
max-height: calc((100vh - 3.5rem) - #{$excluding-size});
|
||||
// max-height: calc((100vh - 3.5rem) - #{$excluding-size});
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 3px;
|
||||
@ -209,8 +238,8 @@ watch(unpinnedConnectionsArr, (newVal, oldVal) => {
|
||||
}
|
||||
|
||||
.settingbar-bottom-elements {
|
||||
padding-top: 0.5rem;
|
||||
z-index: 1;
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
.settingbar-elements {
|
||||
@ -273,6 +302,7 @@ watch(unpinnedConnectionsArr, (newVal, oldVal) => {
|
||||
&::before {
|
||||
font: normal normal normal 14px/1 "Material Design Icons";
|
||||
content: "\F0403";
|
||||
color: $body-font-color-dark;
|
||||
transform: rotate(45deg);
|
||||
opacity: .25;
|
||||
bottom: -8px;
|
||||
|
@ -332,7 +332,10 @@ const addField = () => {
|
||||
collation: defaultCollation.value,
|
||||
autoIncrement: false,
|
||||
onUpdate: '',
|
||||
comment: ''
|
||||
comment: '',
|
||||
alias: '',
|
||||
tableAlias: '',
|
||||
orgTable: ''
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
|
Reference in New Issue
Block a user