mirror of
https://github.com/Fabio286/antares.git
synced 2025-06-05 21:59:22 +02:00
refactor: changes to implement folders
This commit is contained in:
@ -55,20 +55,7 @@
|
|||||||
<div class="panel-subtitle">
|
<div class="panel-subtitle">
|
||||||
{{ clients.get(connection.client) || connection.client }}
|
{{ clients.get(connection.client) || connection.client }}
|
||||||
</div>
|
</div>
|
||||||
<div class="all-connections-buttons p-absolute d-flex" style="top: 0; right: 0;">
|
<div class="all-connections-buttons p-absolute d-flex" :style="'top: 0; right: 0;'">
|
||||||
<i
|
|
||||||
v-if="connection.isPinned"
|
|
||||||
class="all-connections-pinned mdi mdi-18px"
|
|
||||||
:class="connectionHover === connection.uid ? 'mdi-pin-off' : 'mdi-pin'"
|
|
||||||
:title="t('word.unpin')"
|
|
||||||
@click.stop="unpinConnection(connection.uid)"
|
|
||||||
/>
|
|
||||||
<i
|
|
||||||
v-else
|
|
||||||
class="all-connections-pin mdi mdi-18px mdi-pin mdi-rotate-45"
|
|
||||||
:title="t('word.pin')"
|
|
||||||
@click.stop="pinConnection(connection.uid)"
|
|
||||||
/>
|
|
||||||
<i
|
<i
|
||||||
class="all-connections-delete mdi mdi-delete mdi-18px ml-2"
|
class="all-connections-delete mdi mdi-delete mdi-18px ml-2"
|
||||||
:title="t('word.delete')"
|
:title="t('word.delete')"
|
||||||
@ -126,7 +113,7 @@
|
|||||||
key="trick"
|
key="trick"
|
||||||
readonly
|
readonly
|
||||||
class="p-absolute"
|
class="p-absolute"
|
||||||
style="width: 1px; height: 1px; opacity: 0;"
|
:style="'width: 1px; height: 1px; opacity: 0;'"
|
||||||
type="text"
|
type="text"
|
||||||
>
|
>
|
||||||
<!-- workaround for useFocusTrap $lastFocusable -->
|
<!-- workaround for useFocusTrap $lastFocusable -->
|
||||||
@ -171,15 +158,12 @@ const connectionsStore = useConnectionsStore();
|
|||||||
const workspacesStore = useWorkspacesStore();
|
const workspacesStore = useWorkspacesStore();
|
||||||
|
|
||||||
const { connections,
|
const { connections,
|
||||||
pinnedConnections,
|
|
||||||
lastConnections
|
lastConnections
|
||||||
} = storeToRefs(connectionsStore);
|
} = storeToRefs(connectionsStore);
|
||||||
const { getSelected: selectedWorkspace } = storeToRefs(workspacesStore);
|
const { getSelected: selectedWorkspace } = storeToRefs(workspacesStore);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
getConnectionName,
|
getConnectionName,
|
||||||
pinConnection,
|
|
||||||
unpinConnection,
|
|
||||||
deleteConnection
|
deleteConnection
|
||||||
} = connectionsStore;
|
} = connectionsStore;
|
||||||
const { selectWorkspace } = workspacesStore;
|
const { selectWorkspace } = workspacesStore;
|
||||||
@ -206,13 +190,10 @@ const sortedConnections = computed(() => {
|
|||||||
const connTime = lastConnections.value.find((lc) => lc.uid === c.uid)?.time || 0;
|
const connTime = lastConnections.value.find((lc) => lc.uid === c.uid)?.time || 0;
|
||||||
return {
|
return {
|
||||||
...c,
|
...c,
|
||||||
time: connTime,
|
time: connTime
|
||||||
isPinned: pinnedConnections.value.has(c.uid)
|
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.sort((a, b) => {
|
.sort((a, b) => {
|
||||||
if (a.isPinned < b.isPinned) return 1;
|
|
||||||
if (a.isPinned > b.isPinned) return -1;
|
|
||||||
if (a.time < b.time) return 1;
|
if (a.time < b.time) return 1;
|
||||||
if (a.time > b.time) return -1;
|
if (a.time > b.time) return -1;
|
||||||
return 0;
|
return 0;
|
||||||
|
173
src/renderer/components/SettingBarConnections.vue
Normal file
173
src/renderer/components/SettingBarConnections.vue
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
<template>
|
||||||
|
<Draggable
|
||||||
|
:list="localList"
|
||||||
|
item-key="'uid'"
|
||||||
|
ghost-class="ghost"
|
||||||
|
:group="{ name: 'connections', pull: 'clone' }"
|
||||||
|
class="pb-1"
|
||||||
|
:swap-threshold="0.3"
|
||||||
|
@start="emit('start', $event)"
|
||||||
|
@end="emit('end', $event)"
|
||||||
|
@move="emit('move', $event)"
|
||||||
|
@change="emit('update:modelValue', localList)"
|
||||||
|
>
|
||||||
|
<template #item="{ element }">
|
||||||
|
<li
|
||||||
|
v-if="element.isFolder || !folderedConnections.includes(element.uid)"
|
||||||
|
:draggable="true"
|
||||||
|
class="settingbar-element btn btn-link"
|
||||||
|
:class="{ 'selected': element.uid === selectedWorkspace }"
|
||||||
|
@dragstart="draggedElement = element.uid"
|
||||||
|
@dragend="coveredElement = false"
|
||||||
|
@contextmenu.prevent="emit('context', $event, element)"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-if="!element.isFolder && !folderedConnections.includes(element.uid)"
|
||||||
|
class="p-relative"
|
||||||
|
:style="`
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
`"
|
||||||
|
:title="getConnectionName(element.uid)"
|
||||||
|
@click.stop="selectWorkspace(element.uid)"
|
||||||
|
>
|
||||||
|
<!-- Creates a new folder -->
|
||||||
|
<SettingBarConnections
|
||||||
|
v-if="draggedElement && !foldersUid.includes(draggedElement)"
|
||||||
|
class="drag-area"
|
||||||
|
:class="[{'folder-preview': coveredElement === element.uid && draggedElement !== coveredElement}]"
|
||||||
|
:list="dummyNested"
|
||||||
|
@dragenter="coveredElement = element.uid"
|
||||||
|
@dragleave="coveredElement = false"
|
||||||
|
@change="createFolder"
|
||||||
|
/>
|
||||||
|
<i
|
||||||
|
class="settingbar-element-icon dbi"
|
||||||
|
:class="[`dbi-${element.client}`, getStatusBadge(element.uid)]"
|
||||||
|
/>
|
||||||
|
<small class="settingbar-element-name">{{ getConnectionName(element.uid) }}</small>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-else-if="element.isFolder"
|
||||||
|
class="p-relative"
|
||||||
|
:style="`
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
`"
|
||||||
|
>
|
||||||
|
<i class="settingbar-element-icon mdi mdi-folder mdi-36px" />
|
||||||
|
<small class="settingbar-element-name">{{ element.name }}</small>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</template>
|
||||||
|
</Draggable>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, PropType, Ref, ref, watch } from 'vue';
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
|
import * as Draggable from 'vuedraggable';
|
||||||
|
import { SidebarElement, useConnectionsStore } from '@/stores/connections';
|
||||||
|
import { useWorkspacesStore } from '@/stores/workspaces';
|
||||||
|
|
||||||
|
const workspacesStore = useWorkspacesStore();
|
||||||
|
const connectionsStore = useConnectionsStore();
|
||||||
|
|
||||||
|
const { getSelected: selectedWorkspace } = storeToRefs(workspacesStore);
|
||||||
|
const { getFolders: folders } = storeToRefs(connectionsStore);
|
||||||
|
|
||||||
|
const { getWorkspace, selectWorkspace } = workspacesStore;
|
||||||
|
const { getConnectionName, addFolder } = connectionsStore;
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
modelValue: {
|
||||||
|
type: Array as PropType<SidebarElement[]>,
|
||||||
|
default: () => []
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(['start', 'end', 'move', 'context', 'update:modelValue']);
|
||||||
|
|
||||||
|
const localList = ref(props.modelValue);
|
||||||
|
const dummyNested = ref([]);
|
||||||
|
const draggedElement: Ref<string | false> = ref(false);
|
||||||
|
const coveredElement: Ref<string | false> = ref(false);
|
||||||
|
|
||||||
|
const foldersUid = computed(() => folders.value.reduce<string[]>((acc, curr) => {
|
||||||
|
acc.push(curr.uid);
|
||||||
|
return acc;
|
||||||
|
}, []));
|
||||||
|
const folderedConnections = computed(() => {
|
||||||
|
return folders.value.reduce<string[]>((acc, curr) => {
|
||||||
|
acc = [...acc, ...curr.connections];
|
||||||
|
return acc;
|
||||||
|
}, []);
|
||||||
|
});
|
||||||
|
|
||||||
|
const createFolder = ({ added }: {added: { element: SidebarElement }}) => {
|
||||||
|
if (typeof coveredElement.value === 'string' && !added.element.isFolder) {
|
||||||
|
console.log('added', added.element);
|
||||||
|
// Create folder
|
||||||
|
addFolder({
|
||||||
|
after: coveredElement.value,
|
||||||
|
connections: [coveredElement.value, added.element.uid]
|
||||||
|
});
|
||||||
|
|
||||||
|
coveredElement.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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 '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(() => dummyNested.value.length, () => {
|
||||||
|
dummyNested.value = [];
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(() => props.modelValue, (value) => {
|
||||||
|
localList.value = value;
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.drag-area {
|
||||||
|
background-color: transparent;
|
||||||
|
z-index: 10;
|
||||||
|
position: absolute;
|
||||||
|
left: 20px;
|
||||||
|
top: 20px;
|
||||||
|
right: 20px;
|
||||||
|
bottom: 20px;
|
||||||
|
transition: all .2s;
|
||||||
|
|
||||||
|
&.folder-preview {
|
||||||
|
border: 1px dashed;
|
||||||
|
border-radius: 5px;
|
||||||
|
left: 5px;
|
||||||
|
top: 5px;
|
||||||
|
right: 5px;
|
||||||
|
bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
display: none!important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -3,20 +3,6 @@
|
|||||||
:context-event="contextEvent"
|
:context-event="contextEvent"
|
||||||
@close-context="$emit('close-context')"
|
@close-context="$emit('close-context')"
|
||||||
>
|
>
|
||||||
<div
|
|
||||||
v-if="isPinned"
|
|
||||||
class="context-element"
|
|
||||||
@click="unpin"
|
|
||||||
>
|
|
||||||
<span class="d-flex"><i class="mdi mdi-18px mdi-pin-off text-light pr-1" /> {{ t('word.unpin') }}</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-else
|
|
||||||
class="context-element"
|
|
||||||
@click="pin"
|
|
||||||
>
|
|
||||||
<span class="d-flex"><i class="mdi mdi-18px mdi-pin mdi-rotate-45 text-light pr-1" /> {{ t('word.pin') }}</span>
|
|
||||||
</div>
|
|
||||||
<div
|
<div
|
||||||
v-if="isConnected"
|
v-if="isConnected"
|
||||||
class="context-element"
|
class="context-element"
|
||||||
@ -24,7 +10,11 @@
|
|||||||
>
|
>
|
||||||
<span class="d-flex"><i class="mdi mdi-18px mdi-power text-light pr-1" /> {{ t('word.disconnect') }}</span>
|
<span class="d-flex"><i class="mdi mdi-18px mdi-power text-light pr-1" /> {{ t('word.disconnect') }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="context-element" @click="duplicateConnection">
|
<div
|
||||||
|
v-if="!contextConnection.isFolder"
|
||||||
|
class="context-element"
|
||||||
|
@click="duplicateConnection"
|
||||||
|
>
|
||||||
<span class="d-flex"><i class="mdi mdi-18px mdi-content-duplicate text-light pr-1" /> {{ t('word.duplicate') }}</span>
|
<span class="d-flex"><i class="mdi mdi-18px mdi-content-duplicate text-light pr-1" /> {{ t('word.duplicate') }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="context-element" @click="showConfirmModal">
|
<div class="context-element" @click="showConfirmModal">
|
||||||
@ -38,7 +28,7 @@
|
|||||||
>
|
>
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
<i class="mdi mdi-24px mdi-server-remove mr-1" /> {{ t('message.deleteConnection') }}
|
<i class="mdi mdi-24px mdi-server-remove mr-1" /> {{ t(contextConnection.isFolder ? 'message.deleteFolder' : 'message.deleteConnection') }}
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #body>
|
<template #body>
|
||||||
@ -55,26 +45,22 @@ import { computed, Prop, ref } from 'vue';
|
|||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { uidGen } from 'common/libs/uidGen';
|
import { uidGen } from 'common/libs/uidGen';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useConnectionsStore } from '@/stores/connections';
|
import { SidebarElement, useConnectionsStore } from '@/stores/connections';
|
||||||
import { useWorkspacesStore } from '@/stores/workspaces';
|
import { useWorkspacesStore } from '@/stores/workspaces';
|
||||||
import BaseContextMenu from '@/components/BaseContextMenu.vue';
|
import BaseContextMenu from '@/components/BaseContextMenu.vue';
|
||||||
import ConfirmModal from '@/components/BaseConfirmModal.vue';
|
import ConfirmModal from '@/components/BaseConfirmModal.vue';
|
||||||
import { ConnectionParams } from 'common/interfaces/antares';
|
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const connectionsStore = useConnectionsStore();
|
const connectionsStore = useConnectionsStore();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
getConnectionByUid,
|
||||||
getConnectionName,
|
getConnectionName,
|
||||||
addConnection,
|
addConnection,
|
||||||
deleteConnection,
|
deleteConnection
|
||||||
pinConnection,
|
|
||||||
unpinConnection
|
|
||||||
} = connectionsStore;
|
} = connectionsStore;
|
||||||
|
|
||||||
const { pinnedConnections } = storeToRefs(connectionsStore);
|
|
||||||
|
|
||||||
const workspacesStore = useWorkspacesStore();
|
const workspacesStore = useWorkspacesStore();
|
||||||
const { getSelected: selectedWorkspace } = storeToRefs(workspacesStore);
|
const { getSelected: selectedWorkspace } = storeToRefs(workspacesStore);
|
||||||
|
|
||||||
@ -86,16 +72,15 @@ const {
|
|||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
contextEvent: MouseEvent,
|
contextEvent: MouseEvent,
|
||||||
contextConnection: Object as Prop<ConnectionParams>
|
contextConnection: Object as Prop<SidebarElement>
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits(['close-context']);
|
const emit = defineEmits(['close-context']);
|
||||||
|
|
||||||
const isConfirmModal = ref(false);
|
const isConfirmModal = ref(false);
|
||||||
|
|
||||||
const connectionName = computed(() => getConnectionName(props.contextConnection.uid));
|
const connectionName = computed(() => props.contextConnection.name || getConnectionName(props.contextConnection.uid) || t('word.folder', 1));
|
||||||
const isConnected = computed(() => getWorkspace(props.contextConnection.uid).connectionStatus === 'connected');
|
const isConnected = computed(() => getWorkspace(props.contextConnection.uid)?.connectionStatus === 'connected');
|
||||||
const isPinned = computed(() => pinnedConnections.value.has(props.contextConnection.uid));
|
|
||||||
|
|
||||||
const confirmDeleteConnection = () => {
|
const confirmDeleteConnection = () => {
|
||||||
if (selectedWorkspace.value === props.contextConnection.uid)
|
if (selectedWorkspace.value === props.contextConnection.uid)
|
||||||
@ -105,7 +90,7 @@ const confirmDeleteConnection = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const duplicateConnection = () => {
|
const duplicateConnection = () => {
|
||||||
let connectionCopy = Object.assign({}, props.contextConnection);
|
let connectionCopy = getConnectionByUid(props.contextConnection.uid);
|
||||||
connectionCopy = {
|
connectionCopy = {
|
||||||
...connectionCopy,
|
...connectionCopy,
|
||||||
uid: uidGen('C'),
|
uid: uidGen('C'),
|
||||||
@ -125,16 +110,6 @@ const hideConfirmModal = () => {
|
|||||||
closeContext();
|
closeContext();
|
||||||
};
|
};
|
||||||
|
|
||||||
const pin = () => {
|
|
||||||
pinConnection(props.contextConnection.uid);
|
|
||||||
closeContext();
|
|
||||||
};
|
|
||||||
|
|
||||||
const unpin = () => {
|
|
||||||
unpinConnection(props.contextConnection.uid);
|
|
||||||
closeContext();
|
|
||||||
};
|
|
||||||
|
|
||||||
const disconnect = () => {
|
const disconnect = () => {
|
||||||
disconnectWorkspace(props.contextConnection.uid);
|
disconnectWorkspace(props.contextConnection.uid);
|
||||||
closeContext();
|
closeContext();
|
||||||
|
@ -8,47 +8,10 @@
|
|||||||
@close-context="isContext = false"
|
@close-context="isContext = false"
|
||||||
/>
|
/>
|
||||||
<ul class="settingbar-elements">
|
<ul class="settingbar-elements">
|
||||||
<Draggable
|
<SettingBarConnections
|
||||||
v-model="pinnedConnectionsArr"
|
v-model="connectionsArr"
|
||||||
:item-key="'uid'"
|
@context="contextMenu"
|
||||||
@start="isDragging = true"
|
/>
|
||||||
@end="dragStop"
|
|
||||||
>
|
|
||||||
<template #item="{ element }">
|
|
||||||
<li
|
|
||||||
:draggable="true"
|
|
||||||
class="settingbar-element btn btn-link"
|
|
||||||
:class="{ 'selected': element.uid === selectedWorkspace }"
|
|
||||||
:title="getConnectionName(element.uid)"
|
|
||||||
@click.stop="selectWorkspace(element.uid)"
|
|
||||||
@contextmenu.prevent="contextMenu($event, element)"
|
|
||||||
>
|
|
||||||
<i
|
|
||||||
class="settingbar-element-icon dbi"
|
|
||||||
:class="[`dbi-${element.client}`, getStatusBadge(element.uid), (pinnedConnections.has(element.uid) ? 'settingbar-element-pin' : false)]"
|
|
||||||
/>
|
|
||||||
<small class="settingbar-element-name">{{ getConnectionName(element.uid) }}</small>
|
|
||||||
</li>
|
|
||||||
</template>
|
|
||||||
</Draggable>
|
|
||||||
|
|
||||||
<div v-if="pinnedConnectionsArr.length" class="divider" />
|
|
||||||
|
|
||||||
<li
|
|
||||||
v-for="connection in unpinnedConnectionsArr"
|
|
||||||
:key="connection.uid"
|
|
||||||
class="settingbar-element btn btn-link"
|
|
||||||
:class="{ 'selected': connection.uid === selectedWorkspace }"
|
|
||||||
:title="getConnectionName(connection.uid)"
|
|
||||||
@click.stop="selectWorkspace(connection.uid)"
|
|
||||||
@contextmenu.prevent="contextMenu($event, connection)"
|
|
||||||
>
|
|
||||||
<i
|
|
||||||
class="settingbar-element-icon dbi"
|
|
||||||
:class="[`dbi-${connection.client}`, getStatusBadge(connection.uid)]"
|
|
||||||
/>
|
|
||||||
<small class="settingbar-element-name">{{ getConnectionName(connection.uid) }}</small>
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -102,12 +65,11 @@
|
|||||||
import { ref, Ref, computed, watch } from 'vue';
|
import { ref, Ref, computed, watch } from 'vue';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { useApplicationStore } from '@/stores/application';
|
import { useApplicationStore } from '@/stores/application';
|
||||||
import { useConnectionsStore } from '@/stores/connections';
|
import { useConnectionsStore, SidebarElement } from '@/stores/connections';
|
||||||
import { useWorkspacesStore } from '@/stores/workspaces';
|
import { useWorkspacesStore } from '@/stores/workspaces';
|
||||||
import { useSettingsStore } from '@/stores/settings';
|
import { useSettingsStore } from '@/stores/settings';
|
||||||
import * as Draggable from 'vuedraggable';
|
|
||||||
import SettingBarContext from '@/components/SettingBarContext.vue';
|
import SettingBarContext from '@/components/SettingBarContext.vue';
|
||||||
import { ConnectionParams } from 'common/interfaces/antares';
|
import SettingBarConnections from '@/components/SettingBarConnections.vue';
|
||||||
import { useElementBounding } from '@vueuse/core';
|
import { useElementBounding } from '@vueuse/core';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
@ -119,121 +81,42 @@ const workspacesStore = useWorkspacesStore();
|
|||||||
const settingsStore = useSettingsStore();
|
const settingsStore = useSettingsStore();
|
||||||
|
|
||||||
const { updateStatus } = storeToRefs(applicationStore);
|
const { updateStatus } = storeToRefs(applicationStore);
|
||||||
const { connections: storedConnections, pinnedConnections, lastConnections } = storeToRefs(connectionsStore);
|
|
||||||
const { getSelected: selectedWorkspace } = storeToRefs(workspacesStore);
|
const { getSelected: selectedWorkspace } = storeToRefs(workspacesStore);
|
||||||
|
const { getConnectionsOrder: connectionsOrder } = storeToRefs(connectionsStore);
|
||||||
const { disableScratchpad } = storeToRefs(settingsStore);
|
const { disableScratchpad } = storeToRefs(settingsStore);
|
||||||
|
|
||||||
const { showSettingModal, showScratchpad } = applicationStore;
|
const { showSettingModal, showScratchpad } = applicationStore;
|
||||||
const { getConnectionName, updatePinnedConnections } = connectionsStore;
|
const { updateConnectionsOrder } = connectionsStore;
|
||||||
const { getWorkspace, selectWorkspace } = workspacesStore;
|
const { selectWorkspace } = workspacesStore;
|
||||||
|
|
||||||
const emit = defineEmits(['show-connections-modal']);
|
const emit = defineEmits(['show-connections-modal']);
|
||||||
|
|
||||||
const isLinux = process.platform === 'linux';
|
|
||||||
|
|
||||||
const sidebarConnections: Ref<HTMLDivElement> = ref(null);
|
const sidebarConnections: Ref<HTMLDivElement> = ref(null);
|
||||||
const isContext: Ref<boolean> = ref(false);
|
const isContext: Ref<boolean> = ref(false);
|
||||||
const isDragging: Ref<boolean> = ref(false);
|
|
||||||
const isScrollable: Ref<boolean> = ref(false);
|
const isScrollable: Ref<boolean> = ref(false);
|
||||||
const contextEvent: Ref<MouseEvent> = ref(null);
|
const contextEvent: Ref<MouseEvent> = ref(null);
|
||||||
const contextConnection: Ref<ConnectionParams> = ref(null);
|
const contextConnection: Ref<SidebarElement> = ref(null);
|
||||||
const sidebarConnectionsHeight = ref(useElementBounding(sidebarConnections)?.height);
|
const sidebarConnectionsHeight = ref(useElementBounding(sidebarConnections)?.height);
|
||||||
|
|
||||||
const pinnedConnectionsArr = computed({
|
const connectionsArr = computed({
|
||||||
get: () => [...pinnedConnections.value].map(c => storedConnections.value.find(sc => sc.uid === c)).filter(Boolean),
|
get: () => connectionsOrder.value,
|
||||||
set: (value: ConnectionParams[]) => {
|
set: (value: SidebarElement[]) => {
|
||||||
const pinnedUid = value.reduce((acc, curr) => {
|
updateConnectionsOrder(value);
|
||||||
acc.push(curr.uid);
|
|
||||||
return acc;
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
updatePinnedConnections(pinnedUid);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const unpinnedConnectionsArr = computed(() => {
|
|
||||||
return storedConnections.value
|
|
||||||
.filter(c => !pinnedConnections.value.has(c.uid))
|
|
||||||
.map(c => {
|
|
||||||
const connTime = lastConnections.value.find((lc) => lc.uid === c.uid)?.time || 0;
|
|
||||||
return { ...c, time: connTime };
|
|
||||||
})
|
|
||||||
.sort((a, b) => {
|
|
||||||
if (a.time < b.time) return 1;
|
|
||||||
else if (a.time > b.time) return -1;
|
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const hasUpdates = computed(() => ['available', 'downloading', 'downloaded', 'link'].includes(updateStatus.value));
|
const hasUpdates = computed(() => ['available', 'downloading', 'downloaded', 'link'].includes(updateStatus.value));
|
||||||
|
|
||||||
const contextMenu = (event: MouseEvent, connection: ConnectionParams) => {
|
const contextMenu = (event: MouseEvent, connection: SidebarElement) => {
|
||||||
contextEvent.value = event;
|
contextEvent.value = event;
|
||||||
contextConnection.value = connection;
|
contextConnection.value = connection;
|
||||||
isContext.value = true;
|
isContext.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
const tooltipPosition = (e: Event) => {
|
|
||||||
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) => {
|
|
||||||
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 '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
const dragStop = (e: any) => {
|
|
||||||
isDragging.value = false;
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
tooltipPosition(e.originalEvent.target.parentNode);
|
|
||||||
}, 200);
|
|
||||||
};
|
|
||||||
|
|
||||||
watch(sidebarConnectionsHeight, (value) => {
|
watch(sidebarConnectionsHeight, (value) => {
|
||||||
isScrollable.value = value < sidebarConnections.value.scrollHeight;
|
isScrollable.value = value < sidebarConnections.value.scrollHeight;
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(unpinnedConnectionsArr, (newVal, oldVal) => {
|
|
||||||
if (JSON.stringify(newVal) !== JSON.stringify(oldVal)) {
|
|
||||||
setTimeout(() => {
|
|
||||||
const element = document.querySelector<HTMLElement>('.settingbar-element.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');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, 50);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
watch(selectedWorkspace, (newVal, oldVal) => {
|
watch(selectedWorkspace, (newVal, oldVal) => {
|
||||||
if (newVal !== oldVal) {
|
if (newVal !== oldVal) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
@ -143,7 +143,8 @@ export const enUS = {
|
|||||||
pin: 'Pin',
|
pin: 'Pin',
|
||||||
unpin: 'Unpin',
|
unpin: 'Unpin',
|
||||||
console: 'Console',
|
console: 'Console',
|
||||||
shortcuts: 'Shortcuts'
|
shortcuts: 'Shortcuts',
|
||||||
|
folder: 'Folder | Folders'
|
||||||
},
|
},
|
||||||
message: {
|
message: {
|
||||||
appWelcome: 'Welcome to Antares SQL Client!',
|
appWelcome: 'Welcome to Antares SQL Client!',
|
||||||
@ -323,7 +324,8 @@ export const enUS = {
|
|||||||
openFilter: 'Open filter',
|
openFilter: 'Open filter',
|
||||||
nextResultsPage: 'Next results page',
|
nextResultsPage: 'Next results page',
|
||||||
previousResultsPage: 'Previous results page',
|
previousResultsPage: 'Previous results page',
|
||||||
fillCell: 'Fill cell'
|
fillCell: 'Fill cell',
|
||||||
|
deleteFolder: 'Delete folder'
|
||||||
},
|
},
|
||||||
faker: {
|
faker: {
|
||||||
address: 'Address',
|
address: 'Address',
|
||||||
|
@ -2,8 +2,18 @@ import { defineStore } from 'pinia';
|
|||||||
import * as Store from 'electron-store';
|
import * as Store from 'electron-store';
|
||||||
import * as crypto from 'crypto';
|
import * as crypto from 'crypto';
|
||||||
import { ConnectionParams } from 'common/interfaces/antares';
|
import { ConnectionParams } from 'common/interfaces/antares';
|
||||||
|
import { uidGen } from 'common/libs/uidGen';
|
||||||
const key = localStorage.getItem('key');
|
const key = localStorage.getItem('key');
|
||||||
|
|
||||||
|
export interface SidebarElement {
|
||||||
|
isFolder: boolean;
|
||||||
|
uid: string;
|
||||||
|
client?: string;
|
||||||
|
connections?: string[];
|
||||||
|
color?: string;
|
||||||
|
name?: string;
|
||||||
|
}
|
||||||
|
|
||||||
if (!key)
|
if (!key)
|
||||||
localStorage.setItem('key', crypto.randomBytes(16).toString('hex'));
|
localStorage.setItem('key', crypto.randomBytes(16).toString('hex'));
|
||||||
else
|
else
|
||||||
@ -18,42 +28,80 @@ const persistentStore = new Store({
|
|||||||
export const useConnectionsStore = defineStore('connections', {
|
export const useConnectionsStore = defineStore('connections', {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
connections: persistentStore.get('connections', []) as ConnectionParams[],
|
connections: persistentStore.get('connections', []) as ConnectionParams[],
|
||||||
pinnedConnections: new Set([...persistentStore.get('pinnedConnections', []) as string[]]) as Set<string>,
|
lastConnections: persistentStore.get('lastConnections', []) as {uid: string; time: number}[],
|
||||||
lastConnections: persistentStore.get('lastConnections', []) as {uid: string; time: number}[]
|
connectionsOrder: persistentStore.get('connectionsOrder', []) as SidebarElement[]
|
||||||
}),
|
}),
|
||||||
getters: {
|
getters: {
|
||||||
|
getConnectionByUid: state => (uid:string) => state.connections.find(connection => connection.uid === uid),
|
||||||
getConnectionName: state => (uid: string) => {
|
getConnectionName: state => (uid: string) => {
|
||||||
const connection = state.connections.filter(connection => connection.uid === uid)[0];
|
const connection = state.connections.find(connection => connection.uid === uid);
|
||||||
let connectionName = '';
|
let connectionName = '';
|
||||||
|
if (connection) {
|
||||||
|
if (connection.name)
|
||||||
|
connectionName = connection.name;
|
||||||
|
else if (connection.ask)
|
||||||
|
connectionName = `${connection.host}:${connection.port}`;
|
||||||
|
else if (connection.databasePath) {
|
||||||
|
let string = connection.databasePath.split(/[/\\]+/).pop();
|
||||||
|
|
||||||
if (connection.name)
|
if (string.length >= 30)
|
||||||
connectionName = connection.name;
|
string = `...${string.slice(-30)}`;
|
||||||
else if (connection.ask)
|
|
||||||
connectionName = `${connection.host}:${connection.port}`;
|
|
||||||
else if (connection.databasePath) {
|
|
||||||
let string = connection.databasePath.split(/[/\\]+/).pop();
|
|
||||||
|
|
||||||
if (string.length >= 30)
|
connectionName = string;
|
||||||
string = `...${string.slice(-30)}`;
|
}
|
||||||
|
else
|
||||||
connectionName = string;
|
connectionName = `${connection.user + '@'}${connection.host}:${connection.port}`;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
connectionName = `${connection.user + '@'}${connection.host}:${connection.port}`;
|
|
||||||
|
|
||||||
return connectionName;
|
return connectionName;
|
||||||
}
|
},
|
||||||
|
getConnectionsOrder: state => {
|
||||||
|
if (state.connectionsOrder.length)
|
||||||
|
return state.connectionsOrder;
|
||||||
|
else {
|
||||||
|
const connectionsOrder = state.connections.map<SidebarElement>(conn => {
|
||||||
|
return {
|
||||||
|
isFolder: false,
|
||||||
|
uid: conn.uid,
|
||||||
|
client: conn.client
|
||||||
|
};
|
||||||
|
});
|
||||||
|
persistentStore.set('connectionsOrder', connectionsOrder);
|
||||||
|
return connectionsOrder;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getFolders: state => state.connectionsOrder.filter(conn => conn.isFolder)
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
addConnection (connection: ConnectionParams) {
|
addConnection (connection: ConnectionParams) {
|
||||||
this.connections.push(connection);
|
this.connections.push(connection);
|
||||||
persistentStore.set('connections', this.connections);
|
persistentStore.set('connections', this.connections);
|
||||||
|
|
||||||
|
this.connectionsOrder.push({
|
||||||
|
isFolder: false,
|
||||||
|
uid: connection.uid,
|
||||||
|
client: connection.client
|
||||||
|
});
|
||||||
|
persistentStore.set('connectionsOrder', this.connectionsOrder);
|
||||||
},
|
},
|
||||||
deleteConnection (connection: ConnectionParams) {
|
addFolder (params: {after: string; connections: [string, string]}) {
|
||||||
this.connections = (this.connections as ConnectionParams[]).filter(el => el.uid !== connection.uid);
|
const index = this.connectionsOrder.findIndex((conn: SidebarElement) => conn.uid === params.after);
|
||||||
|
this.connectionsOrder.splice(index, 0, {
|
||||||
|
isFolder: true,
|
||||||
|
uid: uidGen('F'),
|
||||||
|
name: '',
|
||||||
|
color: 'orange',
|
||||||
|
connections: params.connections
|
||||||
|
});
|
||||||
|
persistentStore.set('connectionsOrder', this.connectionsOrder);
|
||||||
|
},
|
||||||
|
deleteConnection (connection: SidebarElement | ConnectionParams) {
|
||||||
|
this.connections = (this.connections as SidebarElement[]).filter(el => el.uid !== connection.uid);
|
||||||
persistentStore.set('connections', this.connections);
|
persistentStore.set('connections', this.connections);
|
||||||
(this.pinnedConnections as Set<string>).delete(connection.uid);
|
|
||||||
persistentStore.set('pinnedConnections', [...this.pinnedConnections]);
|
this.connectionsOrder = (this.connectionsOrder as SidebarElement[]).filter(el => el.uid !== connection.uid);
|
||||||
|
console.log(connection.uid, this.connectionsOrder);
|
||||||
|
persistentStore.set('connectionsOrder', this.connectionsOrder);
|
||||||
},
|
},
|
||||||
editConnection (connection: ConnectionParams) {
|
editConnection (connection: ConnectionParams) {
|
||||||
const editedConnections = (this.connections as ConnectionParams[]).map(conn => {
|
const editedConnections = (this.connections as ConnectionParams[]).map(conn => {
|
||||||
@ -68,17 +116,9 @@ export const useConnectionsStore = defineStore('connections', {
|
|||||||
this.connections = connections;
|
this.connections = connections;
|
||||||
persistentStore.set('connections', this.connections);
|
persistentStore.set('connections', this.connections);
|
||||||
},
|
},
|
||||||
updatePinnedConnections (pinned: string[]) {
|
updateConnectionsOrder (connections: SidebarElement[]) {
|
||||||
this.pinnedConnections = new Set(pinned);
|
this.connectionsOrder = connections;
|
||||||
persistentStore.set('pinnedConnections', [...this.pinnedConnections]);
|
persistentStore.set('connectionsOrder', this.connectionsOrder);
|
||||||
},
|
|
||||||
pinConnection (uid: string) {
|
|
||||||
(this.pinnedConnections as Set<string>).add(uid);
|
|
||||||
persistentStore.set('pinnedConnections', [...this.pinnedConnections]);
|
|
||||||
},
|
|
||||||
unpinConnection (uid: string) {
|
|
||||||
(this.pinnedConnections as Set<string>).delete(uid);
|
|
||||||
persistentStore.set('pinnedConnections', [...this.pinnedConnections]);
|
|
||||||
},
|
},
|
||||||
updateLastConnection (uid: string) {
|
updateLastConnection (uid: string) {
|
||||||
const cIndex = (this.lastConnections as {uid: string; time: number}[]).findIndex((c) => c.uid === uid);
|
const cIndex = (this.lastConnections as {uid: string; time: number}[]).findIndex((c) => c.uid === uid);
|
||||||
|
Reference in New Issue
Block a user