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