mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-20 14:46:01 +00:00
vertical split tabs #394
This commit is contained in:
@@ -28,6 +28,7 @@
|
||||
import FontIcon from './icons/FontIcon.svelte';
|
||||
import getElectron from './utility/getElectron';
|
||||
import TabsContainer from './tabpanel/TabsContainer.svelte';
|
||||
import MultiTabsContainer from './tabpanel/MultiTabsContainer.svelte';
|
||||
|
||||
$: currentThemeType = $currentThemeDefinition?.themeType == 'dark' ? 'theme-type-dark' : 'theme-type-light';
|
||||
|
||||
@@ -71,7 +72,7 @@
|
||||
</div>
|
||||
{/if}
|
||||
<div class="tabs-container">
|
||||
<TabsContainer />
|
||||
<MultiTabsContainer />
|
||||
</div>
|
||||
{#if $selectedWidget && $visibleWidgetSideBar}
|
||||
<div
|
||||
|
||||
@@ -127,6 +127,7 @@
|
||||
'icon compare': 'mdi mdi-compare',
|
||||
'icon no-color': 'mdi mdi-format-color-marker-cancel',
|
||||
'icon palette': 'mdi mdi-palette',
|
||||
'icon split': 'mdi mdi-view-split-vertical',
|
||||
|
||||
'icon num-0': 'mdi mdi-numeric-0-circle',
|
||||
'icon num-1': 'mdi mdi-numeric-1-circle',
|
||||
|
||||
@@ -17,6 +17,8 @@ export interface TabDefinition {
|
||||
tabid: string;
|
||||
tabComponent: string;
|
||||
tabOrder?: number;
|
||||
multiTabIndex?: number;
|
||||
visibleSecondary?: boolean;
|
||||
}
|
||||
|
||||
export function writableWithStorage<T>(defaultValue: T, storageName) {
|
||||
|
||||
17
packages/web/src/tabpanel/MultiTabsContainer.svelte
Normal file
17
packages/web/src/tabpanel/MultiTabsContainer.svelte
Normal file
@@ -0,0 +1,17 @@
|
||||
<script>
|
||||
import HorizontalSplitter from '../elements/HorizontalSplitter.svelte';
|
||||
import { openedTabs } from '../stores';
|
||||
import TabsContainer from './TabsContainer.svelte';
|
||||
|
||||
$: isLeft = !!$openedTabs.find(x => x.closedTime == null && !x.multiTabIndex);
|
||||
$: isRight = !!$openedTabs.find(x => x.closedTime == null && x.multiTabIndex == 1);
|
||||
</script>
|
||||
|
||||
<HorizontalSplitter hideFirst={!isLeft && isRight} isSplitter={isRight}>
|
||||
<div class="container" slot="1">
|
||||
<TabsContainer multiTabIndex={0} />
|
||||
</div>
|
||||
<div class="container" slot="2">
|
||||
<TabsContainer multiTabIndex={1} />
|
||||
</div>
|
||||
</HorizontalSplitter>
|
||||
@@ -4,8 +4,12 @@
|
||||
import TabContent from './TabContent.svelte';
|
||||
import tabs from '../tabs';
|
||||
|
||||
export let multiTabIndex;
|
||||
|
||||
let mountedTabs = {};
|
||||
$: selectedTab = $openedTabs.find(x => x.selected && x.closedTime == null);
|
||||
$: selectedTab = $openedTabs.find(
|
||||
x => (x.selected || x.visibleSecondary) && x.closedTime == null && (x.multiTabIndex || 0) == multiTabIndex
|
||||
);
|
||||
|
||||
// cleanup closed tabs
|
||||
$: {
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
<script>
|
||||
<script lang='ts'>
|
||||
import TabRegister from './TabRegister.svelte';
|
||||
|
||||
import TabsPanel from './TabsPanel.svelte';
|
||||
|
||||
export let multiTabIndex;
|
||||
</script>
|
||||
|
||||
<div class="tabs">
|
||||
<TabsPanel />
|
||||
<TabsPanel {multiTabIndex} />
|
||||
</div>
|
||||
<div class="content">
|
||||
<TabRegister />
|
||||
<TabRegister {multiTabIndex} />
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
||||
@@ -43,6 +43,8 @@
|
||||
const newFiles = files.map(x => ({
|
||||
...x,
|
||||
closedTime: shouldShowTab(x) && closeCondition(x, active) ? new Date().getTime() : x.closedTime,
|
||||
selected: false,
|
||||
visibleSecondary: false,
|
||||
}));
|
||||
|
||||
if (newFiles.find(x => x.selected && shouldShowTab(x))) {
|
||||
@@ -72,6 +74,8 @@
|
||||
: files.map(x => ({
|
||||
...x,
|
||||
closedTime: shouldShowTab(x) && closeCondition(x) ? new Date().getTime() : x.closedTime,
|
||||
selected: false,
|
||||
visibleSecondary: false,
|
||||
}));
|
||||
|
||||
if (newFiles.find(x => x.selected && shouldShowTab(x))) {
|
||||
@@ -87,6 +91,17 @@
|
||||
});
|
||||
};
|
||||
|
||||
function splitTab(multiTabIndex) {
|
||||
openedTabs.update(tabs => {
|
||||
const secondaryIndex = _.findLastIndex(tabs, x => shouldShowTab(x) && !x.selected);
|
||||
return tabs.map((x, i) => ({
|
||||
...x,
|
||||
multiTabIndex: x.selected ? 1 - multiTabIndex : x.multiTabIndex,
|
||||
visibleSecondary: i == secondaryIndex,
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
const closeTab = closeTabFunc((x, active) => x.tabid == active.tabid);
|
||||
const closeAll = async () => {
|
||||
const closeCandidates = getOpenedTabs()
|
||||
@@ -101,6 +116,7 @@
|
||||
...tab,
|
||||
closedTime: shouldShowTab(tab) ? closedTime : tab.closedTime,
|
||||
selected: false,
|
||||
visibleSecondary: false,
|
||||
}))
|
||||
);
|
||||
};
|
||||
@@ -264,7 +280,10 @@
|
||||
import TabCloseButton from '../elements/TabCloseButton.svelte';
|
||||
import CloseTabModal from '../modals/CloseTabModal.svelte';
|
||||
|
||||
$: showTabFilterFunc = tab => shouldShowTab(tab, $lockedDatabaseMode, $currentDatabase);
|
||||
export let multiTabIndex;
|
||||
|
||||
$: showTabFilterFunc = tab =>
|
||||
shouldShowTab(tab, $lockedDatabaseMode, $currentDatabase) && (tab.multiTabIndex || 0) == multiTabIndex;
|
||||
$: connectionList = useConnectionList();
|
||||
|
||||
$: currentDbKey =
|
||||
@@ -287,6 +306,10 @@
|
||||
|
||||
$: scrollInViewTab($activeTabId);
|
||||
|
||||
$: filteredTabsFromAllParts = $openedTabs.filter(x => shouldShowTab(x));
|
||||
$: allowSplitTab =
|
||||
_.uniq(filteredTabsFromAllParts.map(x => x.multiTabIndex || 0)).length == 1 && filteredTabsFromAllParts.length >= 2;
|
||||
|
||||
let draggingTab = null;
|
||||
let draggingTabTarget = null;
|
||||
let draggingDbGroup = null;
|
||||
@@ -540,7 +563,16 @@
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
<div class="add-icon" on:click={() => newQuery({})} title="New query"><FontIcon icon="icon add" /></div>
|
||||
<div class="icons-wrapper">
|
||||
{#if allowSplitTab}
|
||||
<div class="icon-button" on:click={() => splitTab(multiTabIndex)} title="Split window">
|
||||
<FontIcon icon="icon split" />
|
||||
</div>
|
||||
{/if}
|
||||
<div class="icon-button" on:click={() => newQuery({})} title="New query">
|
||||
<FontIcon icon="icon add" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
@@ -551,7 +583,7 @@
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
.add-icon {
|
||||
.icons-wrapper {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
font-size: 20pt;
|
||||
@@ -559,10 +591,13 @@
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
}
|
||||
.icon-button {
|
||||
color: var(--theme-font-2);
|
||||
cursor: pointer;
|
||||
}
|
||||
.add-icon:hover {
|
||||
.icon-button:hover {
|
||||
color: var(--theme-font-1);
|
||||
}
|
||||
.tabs {
|
||||
|
||||
@@ -29,9 +29,24 @@ export function markTabSaved(tabid) {
|
||||
}
|
||||
|
||||
export function setSelectedTabFunc(files, tabid) {
|
||||
const oldSelected = files.find(x => x.selected);
|
||||
const newSelected = files.find(x => x.tabid == tabid);
|
||||
const changeVisibleSecondary = (oldSelected.multiTabIndex || 0) != (newSelected.multiTabIndex || 0);
|
||||
return [
|
||||
...(files || []).filter(x => x.tabid != tabid).map(x => ({ ...x, selected: false })),
|
||||
...(files || []).filter(x => x.tabid == tabid).map(x => ({ ...x, selected: true })),
|
||||
...(files || [])
|
||||
.filter(x => x.tabid != tabid)
|
||||
.map(x => ({
|
||||
...x,
|
||||
selected: false,
|
||||
visibleSecondary: changeVisibleSecondary ? x.selected : x.visibleSecondary,
|
||||
})),
|
||||
...(files || [])
|
||||
.filter(x => x.tabid == tabid)
|
||||
.map(x => ({
|
||||
...x,
|
||||
selected: true,
|
||||
visibleSecondary: false,
|
||||
})),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user