mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-29 22:43:58 +00:00
changed tabs order algorithm
This commit is contained in:
@@ -6,7 +6,7 @@ import { GlobalCommand } from './commands/registerCommand';
|
|||||||
import { useConfig, useSettings } from './utility/metadataLoaders';
|
import { useConfig, useSettings } from './utility/metadataLoaders';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
|
||||||
interface TabDefinition {
|
export interface TabDefinition {
|
||||||
title: string;
|
title: string;
|
||||||
closedTime?: number;
|
closedTime?: number;
|
||||||
icon: string;
|
icon: string;
|
||||||
@@ -15,6 +15,7 @@ interface TabDefinition {
|
|||||||
busy: boolean;
|
busy: boolean;
|
||||||
tabid: string;
|
tabid: string;
|
||||||
tabComponent: string;
|
tabComponent: string;
|
||||||
|
tabOrder?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function writableWithStorage<T>(defaultValue: T, storageName) {
|
export function writableWithStorage<T>(defaultValue: T, storageName) {
|
||||||
@@ -44,7 +45,6 @@ export const activeTab = derived([openedTabs], ([$openedTabs]) => $openedTabs.fi
|
|||||||
export const recentDatabases = writableWithStorage([], 'recentDatabases');
|
export const recentDatabases = writableWithStorage([], 'recentDatabases');
|
||||||
export const pinnedDatabases = writableWithStorage([], 'pinnedDatabases');
|
export const pinnedDatabases = writableWithStorage([], 'pinnedDatabases');
|
||||||
export const pinnedTables = writableWithStorage([], 'pinnedTables');
|
export const pinnedTables = writableWithStorage([], 'pinnedTables');
|
||||||
export const tabDatabaseGroupOrder = writableWithStorage({}, 'tabDatabaseGroupOrder');
|
|
||||||
export const commandsSettings = writable({});
|
export const commandsSettings = writable({});
|
||||||
export const allResultsInOneTabDefault = writableWithStorage(false, 'allResultsInOneTabDefault');
|
export const allResultsInOneTabDefault = writableWithStorage(false, 'allResultsInOneTabDefault');
|
||||||
export const archiveFilesAsDataSheets = writableWithStorage([], 'archiveFilesAsDataSheets');
|
export const archiveFilesAsDataSheets = writableWithStorage([], 'archiveFilesAsDataSheets');
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import uuidv1 from 'uuid/v1';
|
import uuidv1 from 'uuid/v1';
|
||||||
import { get } from 'svelte/store';
|
import { get } from 'svelte/store';
|
||||||
import { getOpenedTabs, openedTabs, tabDatabaseGroupOrder } from '../stores';
|
import { getOpenedTabs, openedTabs, TabDefinition } from '../stores';
|
||||||
import tabs from '../tabs';
|
import tabs from '../tabs';
|
||||||
import { setSelectedTabFunc } from './common';
|
import { setSelectedTabFunc } from './common';
|
||||||
import localforage from 'localforage';
|
import localforage from 'localforage';
|
||||||
@@ -73,35 +73,34 @@ export default async function openNewTab(newTab, initialData = undefined, option
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
openedTabs.update(files => [
|
openedTabs.update(files => {
|
||||||
...(files || []).map(x => ({ ...x, selected: false })),
|
const dbKey = getTabDbKey(newTab);
|
||||||
|
const items = sortTabs(files.filter(x => x.closedTime == null));
|
||||||
|
|
||||||
|
const newItem = {
|
||||||
|
...newTab,
|
||||||
|
tabid,
|
||||||
|
};
|
||||||
|
if (dbKey != null) {
|
||||||
|
const lastIndex = _.findLastIndex(items, x => getTabDbKey(x) == dbKey);
|
||||||
|
if (lastIndex >= 0) {
|
||||||
|
items.splice(lastIndex + 1, 0, newItem);
|
||||||
|
} else {
|
||||||
|
items.push(newItem);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
items.push(newItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
...(files || []).map(x => ({ ...x, selected: false, tabOrder: _.findIndex(items, y => y.tabid == x.tabid) })),
|
||||||
{
|
{
|
||||||
...newTab,
|
...newTab,
|
||||||
tabid,
|
tabid,
|
||||||
selected: true,
|
selected: true,
|
||||||
// @ts-ignore
|
tabOrder: _.findIndex(items, y => y.tabid == tabid),
|
||||||
tabOrder: (_.max(files.map(x => x.tabOrder || 0)) || 0) + 1,
|
|
||||||
},
|
},
|
||||||
]);
|
];
|
||||||
|
|
||||||
const allOpenedTabs = getOpenedTabs();
|
|
||||||
|
|
||||||
tabDatabaseGroupOrder.update(groupOrder => {
|
|
||||||
const groupOrderFiltered = _.pickBy(groupOrder, (v, k) =>
|
|
||||||
allOpenedTabs.filter(x => x.closedTime == null).find(x => getTabDbKey(x) == k)
|
|
||||||
);
|
|
||||||
const dbKey = getTabDbKey({
|
|
||||||
...newTab,
|
|
||||||
tabid,
|
|
||||||
});
|
|
||||||
const newOrder =
|
|
||||||
groupOrderFiltered[dbKey] ||
|
|
||||||
// @ts-ignore
|
|
||||||
(_.max(Object.values(groupOrderFiltered)) || 0) + 1;
|
|
||||||
return {
|
|
||||||
...groupOrderFiltered,
|
|
||||||
[dbKey]: newOrder,
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// console.log('OPENING NEW TAB', newTab);
|
// console.log('OPENING NEW TAB', newTab);
|
||||||
@@ -158,5 +157,29 @@ export function getTabDbKey(tab) {
|
|||||||
if (tab.props && tab.props.archiveFolder) {
|
if (tab.props && tab.props.archiveFolder) {
|
||||||
return `archive://${tab.props.archiveFolder}`;
|
return `archive://${tab.props.archiveFolder}`;
|
||||||
}
|
}
|
||||||
return `no://${tab.tabid}`;
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function sortTabs(tabs: any[]): any[] {
|
||||||
|
return _.sortBy(tabs, [x => x.tabOrder || 0, x => getTabDbKey(x), 'title', 'tabid']);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function groupTabs(tabs: any[]) {
|
||||||
|
const res = [];
|
||||||
|
|
||||||
|
for (const tab of sortTabs(tabs)) {
|
||||||
|
const lastGroup = res[res.length - 1];
|
||||||
|
if (lastGroup?.tabDbKey == tab.tabDbKey) {
|
||||||
|
lastGroup.tabs.push(tab);
|
||||||
|
} else {
|
||||||
|
res.push({
|
||||||
|
tabDbKey: tab.tabDbKey,
|
||||||
|
tabDbName: tab.tabDbName,
|
||||||
|
tabs: [tab],
|
||||||
|
grpid: tab.tabid,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,26 @@
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const closeMultipleTabs = closeCondition => {
|
||||||
|
openedTabs.update(files => {
|
||||||
|
const newFiles = files.map(x => ({
|
||||||
|
...x,
|
||||||
|
closedTime: x.closedTime || (closeCondition(x) ? new Date().getTime() : undefined),
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (newFiles.find(x => x.selected && x.closedTime == null)) {
|
||||||
|
return newFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectedIndex = _.findLastIndex(newFiles, x => x.closedTime == null);
|
||||||
|
|
||||||
|
return newFiles.map((x, index) => ({
|
||||||
|
...x,
|
||||||
|
selected: index == selectedIndex,
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const closeTab = closeTabFunc((x, active) => x.tabid == active.tabid);
|
const closeTab = closeTabFunc((x, active) => x.tabid == active.tabid);
|
||||||
const closeAll = () => {
|
const closeAll = () => {
|
||||||
const closedTime = new Date().getTime();
|
const closedTime = new Date().getTime();
|
||||||
@@ -60,14 +80,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getDbIcon(key) {
|
function getDbIcon(key) {
|
||||||
|
if (key) {
|
||||||
if (key.startsWith('database://')) return 'icon database';
|
if (key.startsWith('database://')) return 'icon database';
|
||||||
if (key.startsWith('archive://')) return 'icon archive';
|
if (key.startsWith('archive://')) return 'icon archive';
|
||||||
if (key.startsWith('server://')) return 'icon server';
|
if (key.startsWith('server://')) return 'icon server';
|
||||||
return 'icon file';
|
|
||||||
}
|
}
|
||||||
|
return 'icon file';
|
||||||
function sortTabs(tabs) {
|
|
||||||
return _.sortBy(tabs, [x => x['tabOrder'] || 0, 'title', 'tabid']);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
registerCommand({
|
registerCommand({
|
||||||
@@ -124,22 +142,14 @@
|
|||||||
import FavoriteModal from '../modals/FavoriteModal.svelte';
|
import FavoriteModal from '../modals/FavoriteModal.svelte';
|
||||||
import { showModal } from '../modals/modalTools';
|
import { showModal } from '../modals/modalTools';
|
||||||
|
|
||||||
import {
|
import { currentDatabase, getActiveTab, getOpenedTabs, openedTabs, activeTabId, getActiveTabId } from '../stores';
|
||||||
currentDatabase,
|
|
||||||
getActiveTab,
|
|
||||||
getOpenedTabs,
|
|
||||||
openedTabs,
|
|
||||||
activeTabId,
|
|
||||||
getActiveTabId,
|
|
||||||
tabDatabaseGroupOrder,
|
|
||||||
} from '../stores';
|
|
||||||
import tabs from '../tabs';
|
import tabs from '../tabs';
|
||||||
import { setSelectedTab } from '../utility/common';
|
import { setSelectedTab } from '../utility/common';
|
||||||
import contextMenu from '../utility/contextMenu';
|
import contextMenu from '../utility/contextMenu';
|
||||||
import getConnectionLabel from '../utility/getConnectionLabel';
|
import getConnectionLabel from '../utility/getConnectionLabel';
|
||||||
import { isElectronAvailable } from '../utility/getElectron';
|
import { isElectronAvailable } from '../utility/getElectron';
|
||||||
import { getConnectionInfo, useConnectionList } from '../utility/metadataLoaders';
|
import { getConnectionInfo, useConnectionList } from '../utility/metadataLoaders';
|
||||||
import { duplicateTab, getTabDbKey } from '../utility/openNewTab';
|
import { duplicateTab, getTabDbKey, sortTabs, groupTabs } from '../utility/openNewTab';
|
||||||
import { useConnectionColorFactory } from '../utility/useConnectionColor';
|
import { useConnectionColorFactory } from '../utility/useConnectionColor';
|
||||||
|
|
||||||
$: connectionList = useConnectionList();
|
$: connectionList = useConnectionList();
|
||||||
@@ -159,15 +169,17 @@
|
|||||||
tabDbKey: getTabDbKey(tab),
|
tabDbKey: getTabDbKey(tab),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
$: tabsByDb = _.groupBy(tabsWithDb, 'tabDbKey');
|
$: groupedTabs = groupTabs(tabsWithDb);
|
||||||
$: dbKeys = _.sortBy(_.keys(tabsByDb), [x => $tabDatabaseGroupOrder[x] || 0, x => x]);
|
|
||||||
|
// $: tabsByDb = _.groupBy(tabsWithDb, 'tabDbKey');
|
||||||
|
// $: dbKeys = _.sortBy(_.keys(tabsByDb), [x => $tabDatabaseGroupOrder[x] || 0, x => x]);
|
||||||
|
|
||||||
$: scrollInViewTab($activeTabId);
|
$: scrollInViewTab($activeTabId);
|
||||||
|
|
||||||
let draggingTab = null;
|
let draggingTab = null;
|
||||||
let draggingTabTarget = null;
|
let draggingTabTarget = null;
|
||||||
let draggingDbKey = null;
|
let draggingDbGroup = null;
|
||||||
let draggingDbKeyTarget = null;
|
let draggingDbGroupTarget = null;
|
||||||
|
|
||||||
const connectionColorFactory = useConnectionColorFactory(3, null, true);
|
const connectionColorFactory = useConnectionColorFactory(3, null, true);
|
||||||
|
|
||||||
@@ -260,13 +272,13 @@
|
|||||||
function dragDropTab(draggingTab, targetTab) {
|
function dragDropTab(draggingTab, targetTab) {
|
||||||
if (draggingTab.tabid == targetTab.tabid) return;
|
if (draggingTab.tabid == targetTab.tabid) return;
|
||||||
|
|
||||||
if (getTabDbKey(draggingTab) != getTabDbKey(targetTab)) {
|
// if (getTabDbKey(draggingTab) != getTabDbKey(targetTab)) {
|
||||||
dragDropDbKey(getTabDbKey(draggingTab), getTabDbKey(targetTab));
|
// // dragDropDbKey(getTabDbKey(draggingTab), getTabDbKey(targetTab));
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
const dbKey = getTabDbKey(draggingTab);
|
// const dbKey = getTabDbKey(draggingTab);
|
||||||
const items = sortTabs(tabsByDb[dbKey]);
|
const items = sortTabs($openedTabs.filter(x => x.closedTime == null));
|
||||||
const dstIndex = _.findIndex(items, x => x.tabid == targetTab.tabid);
|
const dstIndex = _.findIndex(items, x => x.tabid == targetTab.tabid);
|
||||||
const srcIndex = _.findIndex(items, x => x.tabid == draggingTab.tabid);
|
const srcIndex = _.findIndex(items, x => x.tabid == draggingTab.tabid);
|
||||||
if (srcIndex < 0 || dstIndex < 0) {
|
if (srcIndex < 0 || dstIndex < 0) {
|
||||||
@@ -296,78 +308,83 @@
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function dragDropDbKey(draggingDbKey, targetDbKey) {
|
// function dragDropDbKey(draggingDbKey, targetDbKey) {
|
||||||
if (!draggingDbKey) return;
|
// if (!draggingDbKey) return;
|
||||||
if (targetDbKey == draggingDbKey) return;
|
// if (targetDbKey == draggingDbKey) return;
|
||||||
|
|
||||||
const groupOrderFiltered = _.pickBy($tabDatabaseGroupOrder, (v, k) =>
|
// const groupOrderFiltered = _.pickBy($tabDatabaseGroupOrder, (v, k) =>
|
||||||
$openedTabs.filter(x => x.closedTime == null).find(x => getTabDbKey(x) == k)
|
// $openedTabs.filter(x => x.closedTime == null).find(x => getTabDbKey(x) == k)
|
||||||
);
|
// );
|
||||||
|
|
||||||
const items = _.sortBy(_.keys(groupOrderFiltered), x => groupOrderFiltered[x]);
|
// const items = _.sortBy(_.keys(groupOrderFiltered), x => groupOrderFiltered[x]);
|
||||||
|
|
||||||
const dstIndex = _.indexOf(items, targetDbKey);
|
// const dstIndex = _.indexOf(items, targetDbKey);
|
||||||
const srcIndex = _.indexOf(items, draggingDbKey);
|
// const srcIndex = _.indexOf(items, draggingDbKey);
|
||||||
if (srcIndex < 0 || dstIndex < 0) {
|
// if (srcIndex < 0 || dstIndex < 0) {
|
||||||
console.warn('Drag tab group index not found');
|
// console.warn('Drag tab group index not found');
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
const newItems =
|
// const newItems =
|
||||||
dstIndex < srcIndex
|
// dstIndex < srcIndex
|
||||||
? [...items.slice(0, dstIndex), draggingDbKey, ...items.slice(dstIndex).filter(x => x != draggingDbKey)]
|
// ? [...items.slice(0, dstIndex), draggingDbKey, ...items.slice(dstIndex).filter(x => x != draggingDbKey)]
|
||||||
: [
|
// : [
|
||||||
...items.slice(0, dstIndex + 1).filter(x => x != draggingDbKey),
|
// ...items.slice(0, dstIndex + 1).filter(x => x != draggingDbKey),
|
||||||
draggingDbKey,
|
// draggingDbKey,
|
||||||
...items.slice(dstIndex + 1),
|
// ...items.slice(dstIndex + 1),
|
||||||
];
|
// ];
|
||||||
|
|
||||||
const newGroupOrder = {};
|
// const newGroupOrder = {};
|
||||||
for (const key in groupOrderFiltered) {
|
// for (const key in groupOrderFiltered) {
|
||||||
const index = newItems.indexOf(key);
|
// const index = newItems.indexOf(key);
|
||||||
newGroupOrder[key] = index >= 0 ? index + 1 : groupOrderFiltered[key];
|
// newGroupOrder[key] = index >= 0 ? index + 1 : groupOrderFiltered[key];
|
||||||
}
|
// }
|
||||||
|
|
||||||
tabDatabaseGroupOrder.set(newGroupOrder);
|
// tabDatabaseGroupOrder.set(newGroupOrder);
|
||||||
}
|
// }
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#each dbKeys as dbKey}
|
{#each groupedTabs as tabGroup}
|
||||||
<div class="db-wrapper">
|
<div class="db-wrapper">
|
||||||
<div
|
<div
|
||||||
class="db-name"
|
class="db-name"
|
||||||
class:selected={draggingDbKey ? dbKey == draggingDbKeyTarget : tabsByDb[dbKey][0].tabDbKey == currentDbKey}
|
class:selected={draggingDbGroup
|
||||||
on:click={() => handleSetDb(tabsByDb[dbKey][0].props)}
|
? tabGroup.grpid == draggingDbGroupTarget?.grpid
|
||||||
use:contextMenu={getDatabaseContextMenu(tabsByDb[dbKey])}
|
: tabGroup.tabDbKey == currentDbKey}
|
||||||
|
on:click={() => handleSetDb(tabGroup.tabs[0].props)}
|
||||||
|
use:contextMenu={getDatabaseContextMenu(tabGroup.tabs)}
|
||||||
style={$connectionColorFactory(
|
style={$connectionColorFactory(
|
||||||
tabsByDb[dbKey][0].props,
|
tabGroup.tabs[0].props,
|
||||||
(draggingDbKey ? dbKey == draggingDbKeyTarget : tabsByDb[dbKey][0].tabDbKey == currentDbKey) ? 2 : 3
|
(draggingDbGroup ? tabGroup.grpid == draggingDbGroupTarget?.grpid : tabGroup.tabDbKey == currentDbKey) ? 2 : 3
|
||||||
)}
|
)}
|
||||||
draggable={true}
|
draggable={true}
|
||||||
on:dragstart={e => {
|
on:dragstart={e => {
|
||||||
draggingDbKey = dbKey;
|
draggingDbGroup = tabGroup;
|
||||||
}}
|
}}
|
||||||
on:dragenter={e => {
|
on:dragenter={e => {
|
||||||
draggingDbKeyTarget = dbKey;
|
draggingDbGroupTarget = tabGroup;
|
||||||
}}
|
}}
|
||||||
on:drop={e => {
|
on:drop={e => {
|
||||||
dragDropDbKey(draggingDbKey, dbKey);
|
// dragDropDbKey(draggingDbKey, dbKey);
|
||||||
}}
|
}}
|
||||||
on:dragend={e => {
|
on:dragend={e => {
|
||||||
draggingDbKey = null;
|
draggingDbGroup = null;
|
||||||
draggingDbKeyTarget = null;
|
draggingDbGroupTarget = null;
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<FontIcon icon={getDbIcon(dbKey)} />
|
<FontIcon icon={getDbIcon(tabGroup.tabDbKey)} />
|
||||||
{tabsByDb[dbKey][0].tabDbName}
|
{tabGroup.tabDbName}
|
||||||
|
|
||||||
{#if tabsByDb[dbKey].length > 1}
|
{#if tabGroup.tabs.length > 1}
|
||||||
<span class="close-button-right tabCloseButton" on:click={e => closeWithSameDb(tabsByDb[dbKey][0].tabid)}>
|
<span
|
||||||
|
class="close-button-right tabCloseButton"
|
||||||
|
on:click={e => closeMultipleTabs(tab => tabGroup.tabs.find(x => x.tabid == tab.tabid))}
|
||||||
|
>
|
||||||
<FontIcon icon="icon close" />
|
<FontIcon icon="icon close" />
|
||||||
</span>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="db-group">
|
<div class="db-group">
|
||||||
{#each sortTabs(tabsByDb[dbKey]) as tab}
|
{#each tabGroup.tabs as tab}
|
||||||
<div
|
<div
|
||||||
id={`file-tab-item-${tab.tabid}`}
|
id={`file-tab-item-${tab.tabid}`}
|
||||||
class="file-tab-item"
|
class="file-tab-item"
|
||||||
|
|||||||
Reference in New Issue
Block a user