mirror of https://github.com/Fabio286/antares.git
feat: connections sorted by last usage by default and option to pin them
This commit is contained in:
parent
f632a0f189
commit
36e98e0742
|
@ -9,7 +9,7 @@
|
||||||
/>
|
/>
|
||||||
<ul class="settingbar-elements">
|
<ul class="settingbar-elements">
|
||||||
<Draggable
|
<Draggable
|
||||||
v-model="connections"
|
v-model="pinnedConnectionsArr"
|
||||||
:item-key="'uid'"
|
:item-key="'uid'"
|
||||||
@start="isDragging = true"
|
@start="isDragging = true"
|
||||||
@end="dragStop"
|
@end="dragStop"
|
||||||
|
@ -23,11 +23,26 @@
|
||||||
@contextmenu.prevent="contextMenu($event, element)"
|
@contextmenu.prevent="contextMenu($event, element)"
|
||||||
@mouseover.self="tooltipPosition"
|
@mouseover.self="tooltipPosition"
|
||||||
>
|
>
|
||||||
<i class="settingbar-element-icon dbi" :class="`dbi-${element.client} ${getStatusBadge(element.uid)}`" />
|
<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" class="ex-tooltip-content">{{ getConnectionName(element.uid) }}</span>
|
||||||
</li>
|
</li>
|
||||||
</template>
|
</template>
|
||||||
</Draggable>
|
</Draggable>
|
||||||
|
|
||||||
|
<div v-if="pinnedConnectionsArr.length" class="divider" />
|
||||||
|
|
||||||
|
<li
|
||||||
|
v-for="connection in unpinnedConnectionsArr"
|
||||||
|
:key="connection.uid"
|
||||||
|
class="settingbar-element btn btn-link ex-tooltip"
|
||||||
|
:class="{'selected': connection.uid === selectedWorkspace}"
|
||||||
|
@click.stop="selectWorkspace(connection.uid)"
|
||||||
|
@contextmenu.prevent="contextMenu($event, connection)"
|
||||||
|
@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>
|
||||||
|
</li>
|
||||||
<li
|
<li
|
||||||
class="settingbar-element btn btn-link ex-tooltip"
|
class="settingbar-element btn btn-link ex-tooltip"
|
||||||
:class="{'selected': 'NEW' === selectedWorkspace}"
|
:class="{'selected': 'NEW' === selectedWorkspace}"
|
||||||
|
@ -56,7 +71,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, Ref, computed } 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 } from '@/stores/connections';
|
||||||
|
@ -74,7 +89,7 @@ const { connections: storedConnections, pinnedConnections, lastConnections } = s
|
||||||
const { getSelected: selectedWorkspace } = storeToRefs(workspacesStore);
|
const { getSelected: selectedWorkspace } = storeToRefs(workspacesStore);
|
||||||
|
|
||||||
const { showSettingModal, showScratchpad } = applicationStore;
|
const { showSettingModal, showScratchpad } = applicationStore;
|
||||||
const { getConnectionName, updateConnections } = connectionsStore;
|
const { getConnectionName, updatePinnedConnections } = connectionsStore;
|
||||||
const { getWorkspace, selectWorkspace } = workspacesStore;
|
const { getWorkspace, selectWorkspace } = workspacesStore;
|
||||||
|
|
||||||
const isLinux = process.platform === 'linux';
|
const isLinux = process.platform === 'linux';
|
||||||
|
@ -83,17 +98,31 @@ const isDragging: 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<ConnectionParams> = ref(null);
|
||||||
|
|
||||||
const connections = computed({
|
const pinnedConnectionsArr = computed({
|
||||||
get () {
|
get: () => [...pinnedConnections.value].map(c => storedConnections.value.find(sc => sc.uid === c)).filter(Boolean),
|
||||||
return storedConnections.value;
|
set: (value: ConnectionParams[]) => {
|
||||||
},
|
const pinnedUid = value.reduce((acc, curr) => {
|
||||||
set (value: ConnectionParams[]) {
|
acc.push(curr.uid);
|
||||||
updateConnections(value);
|
return acc;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
updatePinnedConnections(pinnedUid);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const pinnedConnectionsArr = computed(() => storedConnections.value.filter(c => pinnedConnections.value.has(c.uid)));
|
const unpinnedConnectionsArr = computed(() => {
|
||||||
const unpinnedConnectionsArr = computed(() => storedConnections.value.filter(c => !pinnedConnections.value.has(c.uid)));
|
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));
|
||||||
|
|
||||||
|
@ -129,13 +158,33 @@ const getStatusBadge = (uid: string) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
const dragStop = (e: any) => { // TODO: temp
|
const dragStop = (e: any) => {
|
||||||
isDragging.value = false;
|
isDragging.value = false;
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
tooltipPosition(e.originalEvent.target.parentNode);
|
tooltipPosition(e.originalEvent.target.parentNode);
|
||||||
}, 200);
|
}, 200);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
@ -217,6 +266,20 @@ const dragStop = (e: any) => { // TODO: temp
|
||||||
bottom: initial;
|
bottom: initial;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.settingbar-element-pin{
|
||||||
|
margin: 0 auto;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
font: normal normal normal 14px/1 "Material Design Icons";
|
||||||
|
content: "\F0403";
|
||||||
|
transform: rotate(45deg);
|
||||||
|
opacity: .25;
|
||||||
|
bottom: -8px;
|
||||||
|
left: -4px;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,9 +125,9 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Component, computed, onBeforeUnmount, onMounted, onUnmounted, Ref, ref, watch } from 'vue';
|
import { Component, computed, onBeforeUnmount, onMounted, onUnmounted, Prop, Ref, ref, watch } from 'vue';
|
||||||
import { Ace } from 'ace-builds';
|
import { Ace } from 'ace-builds';
|
||||||
import { EventInfos } from 'common/interfaces/antares';
|
import { ConnectionParams, EventInfos } from 'common/interfaces/antares';
|
||||||
import { useI18n } from 'vue-i18n';
|
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';
|
||||||
|
@ -141,7 +141,7 @@ const { t } = useI18n();
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
tabUid: String,
|
tabUid: String,
|
||||||
connection: Object,
|
connection: Object as Prop<ConnectionParams>,
|
||||||
tab: Object,
|
tab: Object,
|
||||||
isSelected: Boolean,
|
isSelected: Boolean,
|
||||||
schema: String
|
schema: String
|
||||||
|
@ -281,7 +281,7 @@ originalScheduler.value = {
|
||||||
state: 'DISABLE'
|
state: 'DISABLE'
|
||||||
};
|
};
|
||||||
|
|
||||||
originalScheduler.value = JSON.parse(JSON.stringify(originalScheduler.value));
|
localScheduler.value = { ...originalScheduler.value };
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
resizeQueryEditor();
|
resizeQueryEditor();
|
||||||
|
|
|
@ -60,12 +60,15 @@ const useFocusTrap = (args?: {disableAutofocus?: boolean}) => {
|
||||||
focusableElements = (trapRef.value as HTMLElement).querySelectorAll(
|
focusableElements = (trapRef.value as HTMLElement).querySelectorAll(
|
||||||
focusableElementsSelector
|
focusableElementsSelector
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (focusableElements.length) {
|
||||||
$firstFocusable = focusableElements[0];
|
$firstFocusable = focusableElements[0];
|
||||||
$lastFocusable = focusableElements[focusableElements.length - 1];
|
$lastFocusable = focusableElements[focusableElements.length - 1];
|
||||||
document.addEventListener('keydown', keyHandler);
|
document.addEventListener('keydown', keyHandler);
|
||||||
isInitiated.value = true;
|
isInitiated.value = true;
|
||||||
if (!localArgs.disableAutofocus) $firstFocusable.focus();
|
if (!localArgs.disableAutofocus) $firstFocusable.focus();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function clearFocusTrap () {
|
function clearFocusTrap () {
|
||||||
document.removeEventListener('keydown', keyHandler);
|
document.removeEventListener('keydown', keyHandler);
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
width: 42px;
|
width: 42px;
|
||||||
height: 42px;
|
height: 42px;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
&.dbi-mysql {
|
&.dbi-mysql {
|
||||||
background-image: url("../images/svg/mysql.svg");
|
background-image: url("../images/svg/mysql.svg");
|
||||||
|
|
|
@ -368,6 +368,10 @@ option:checked {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
margin: 0.15rem 0.3rem;
|
||||||
|
}
|
||||||
|
|
||||||
.table-dropdown {
|
.table-dropdown {
|
||||||
.menu {
|
.menu {
|
||||||
min-width: 100%;
|
min-width: 100%;
|
||||||
|
|
|
@ -148,6 +148,10 @@
|
||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
border-top: 0.05rem solid rgba($body-font-color-dark, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
.form-switch .form-icon::before {
|
.form-switch .form-icon::before {
|
||||||
background: $bg-color-light-dark;
|
background: $bg-color-light-dark;
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,6 +94,10 @@
|
||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
border-top: 0.05rem solid rgba($body-font-color-dark, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
.tile {
|
.tile {
|
||||||
transition: background 0.2s;
|
transition: background 0.2s;
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ 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>,
|
pinnedConnections: new Set([...persistentStore.get('pinnedConnections', []) as string[]]) as Set<string>,
|
||||||
lastConnections: persistentStore.get('lastConnections', {}) as {[k: string]: number}
|
lastConnections: persistentStore.get('lastConnections', []) as {uid: string; time: number}[]
|
||||||
}),
|
}),
|
||||||
getters: {
|
getters: {
|
||||||
getConnectionName: state => (uid: string) => {
|
getConnectionName: state => (uid: string) => {
|
||||||
|
@ -52,6 +52,8 @@ export const useConnectionsStore = defineStore('connections', {
|
||||||
deleteConnection (connection: ConnectionParams) {
|
deleteConnection (connection: ConnectionParams) {
|
||||||
this.connections = (this.connections as ConnectionParams[]).filter(el => el.uid !== connection.uid);
|
this.connections = (this.connections as ConnectionParams[]).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]);
|
||||||
},
|
},
|
||||||
editConnection (connection: ConnectionParams) {
|
editConnection (connection: ConnectionParams) {
|
||||||
const editedConnections = (this.connections as ConnectionParams[]).map(conn => {
|
const editedConnections = (this.connections as ConnectionParams[]).map(conn => {
|
||||||
|
@ -66,6 +68,10 @@ export const useConnectionsStore = defineStore('connections', {
|
||||||
this.connections = connections;
|
this.connections = connections;
|
||||||
persistentStore.set('connections', this.connections);
|
persistentStore.set('connections', this.connections);
|
||||||
},
|
},
|
||||||
|
updatePinnedConnections (pinned: string[]) {
|
||||||
|
this.pinnedConnections = new Set(pinned);
|
||||||
|
persistentStore.set('pinnedConnections', [...this.pinnedConnections]);
|
||||||
|
},
|
||||||
pinConnection (uid: string) {
|
pinConnection (uid: string) {
|
||||||
(this.pinnedConnections as Set<string>).add(uid);
|
(this.pinnedConnections as Set<string>).add(uid);
|
||||||
persistentStore.set('pinnedConnections', [...this.pinnedConnections]);
|
persistentStore.set('pinnedConnections', [...this.pinnedConnections]);
|
||||||
|
@ -75,7 +81,13 @@ export const useConnectionsStore = defineStore('connections', {
|
||||||
persistentStore.set('pinnedConnections', [...this.pinnedConnections]);
|
persistentStore.set('pinnedConnections', [...this.pinnedConnections]);
|
||||||
},
|
},
|
||||||
updateLastConnection (uid: string) {
|
updateLastConnection (uid: string) {
|
||||||
this.lastConnections[uid] = new Date().getTime();
|
const cIndex = (this.lastConnections as {uid: string; time: number}[]).findIndex((c) => c.uid === uid);
|
||||||
|
|
||||||
|
if (cIndex >= 0)
|
||||||
|
this.lastConnections[cIndex].time = new Date().getTime();
|
||||||
|
else
|
||||||
|
this.lastConnections.push({ uid, time: new Date().getTime() });
|
||||||
|
|
||||||
persistentStore.set('lastConnections', this.lastConnections);
|
persistentStore.set('lastConnections', this.lastConnections);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -718,44 +718,6 @@ export const useWorkspacesStore = defineStore('workspaces', {
|
||||||
);
|
);
|
||||||
persistentStore.set(uid, (this.workspaces as Workspace[]).find(workspace => workspace.uid === uid).tabs);
|
persistentStore.set(uid, (this.workspaces as Workspace[]).find(workspace => workspace.uid === uid).tabs);
|
||||||
},
|
},
|
||||||
// setTabFields ({ cUid, tUid, fields }: { cUid: string; tUid: string; fields: any }) {
|
|
||||||
// this.workspaces = (this.workspaces as Workspace[]).map(workspace => {
|
|
||||||
// if (workspace.uid === cUid) {
|
|
||||||
// return {
|
|
||||||
// ...workspace,
|
|
||||||
// tabs: workspace.tabs.map(tab => {
|
|
||||||
// if (tab.uid === tUid)
|
|
||||||
// return { ...tab, fields };
|
|
||||||
// else
|
|
||||||
// return tab;
|
|
||||||
// })
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// return workspace;
|
|
||||||
// });
|
|
||||||
|
|
||||||
// persistentStore.set(cUid, (this.workspaces as Workspace[]).find(workspace => workspace.uid === cUid).tabs);
|
|
||||||
// },
|
|
||||||
// setTabKeyUsage ({ cUid, tUid, keyUsage }: { cUid: string; tUid: string; keyUsage: any }) {
|
|
||||||
// this.workspaces = (this.workspaces as Workspace[]).map(workspace => {
|
|
||||||
// if (workspace.uid === cUid) {
|
|
||||||
// return {
|
|
||||||
// ...workspace,
|
|
||||||
// tabs: workspace.tabs.map(tab => {
|
|
||||||
// if (tab.uid === tUid)
|
|
||||||
// return { ...tab, keyUsage };
|
|
||||||
// else
|
|
||||||
// return tab;
|
|
||||||
// })
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// return workspace;
|
|
||||||
// });
|
|
||||||
|
|
||||||
// persistentStore.set(cUid, (this.workspaces as Workspace[]).find(workspace => workspace.uid === cUid).tabs);
|
|
||||||
// },
|
|
||||||
setUnsavedChanges ({ uid, tUid, isChanged }: { uid: string; tUid: string; isChanged: boolean }) {
|
setUnsavedChanges ({ uid, tUid, isChanged }: { uid: string; tUid: string; isChanged: boolean }) {
|
||||||
this.workspaces = (this.workspaces as Workspace[]).map(workspace => {
|
this.workspaces = (this.workspaces as Workspace[]).map(workspace => {
|
||||||
if (workspace.uid === uid) {
|
if (workspace.uid === uid) {
|
||||||
|
|
Loading…
Reference in New Issue