mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-29 11:03:57 +00:00
single database mode
This commit is contained in:
@@ -13,7 +13,7 @@
|
|||||||
],
|
],
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ant-design/colors": "^5.0.0",
|
"@ant-design/colors": "^5.0.0",
|
||||||
"@mdi/font": "^5.9.55",
|
"@mdi/font": "^7.1.96",
|
||||||
"@rollup/plugin-commonjs": "^20.0.0",
|
"@rollup/plugin-commonjs": "^20.0.0",
|
||||||
"@rollup/plugin-node-resolve": "^13.0.5",
|
"@rollup/plugin-node-resolve": "^13.0.5",
|
||||||
"@rollup/plugin-replace": "^3.0.0",
|
"@rollup/plugin-replace": "^3.0.0",
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
--dim-widget-icon-size: 60px;
|
--dim-widget-icon-size: 60px;
|
||||||
--dim-statusbar-height: 22px;
|
--dim-statusbar-height: 22px;
|
||||||
--dim-left-panel-width: 300px;
|
--dim-left-panel-width: 300px;
|
||||||
--dim-tabs-panel-height: 53px;
|
|
||||||
--dim-tabs-height: 33px;
|
--dim-tabs-height: 33px;
|
||||||
|
--dim-tabs-panel-height: calc( var(--dim-visible-tabs-databases) * 20px + var(--dim-tabs-height) );
|
||||||
--dim-splitter-thickness: 3px;
|
--dim-splitter-thickness: 3px;
|
||||||
|
|
||||||
--dim-visible-left-panel: 1; /* set from JS */
|
--dim-visible-left-panel: 1; /* set from JS */
|
||||||
|
|||||||
@@ -40,6 +40,9 @@
|
|||||||
'icon columns': 'mdi mdi-view-column',
|
'icon columns': 'mdi mdi-view-column',
|
||||||
'icon columns-outline': 'mdi mdi-view-column-outline',
|
'icon columns-outline': 'mdi mdi-view-column-outline',
|
||||||
|
|
||||||
|
'icon single-database-mode': 'mdi mdi-database-lock',
|
||||||
|
'icon multi-database-mode': 'mdi mdi-database-eye',
|
||||||
|
|
||||||
'icon database': 'mdi mdi-database',
|
'icon database': 'mdi mdi-database',
|
||||||
'icon server': 'mdi mdi-server',
|
'icon server': 'mdi mdi-server',
|
||||||
'icon table': 'mdi mdi-table',
|
'icon table': 'mdi mdi-table',
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
import FormStyledButton from '../buttons/FormStyledButton.svelte';
|
import FormStyledButton from '../buttons/FormStyledButton.svelte';
|
||||||
import Link from '../elements/Link.svelte';
|
import Link from '../elements/Link.svelte';
|
||||||
import TabControl from '../elements/TabControl.svelte';
|
import TabControl from '../elements/TabControl.svelte';
|
||||||
|
import CheckboxField from '../forms/CheckboxField.svelte';
|
||||||
|
|
||||||
import FormCheckboxField from '../forms/FormCheckboxField.svelte';
|
import FormCheckboxField from '../forms/FormCheckboxField.svelte';
|
||||||
import FormFieldTemplateLarge from '../forms/FormFieldTemplateLarge.svelte';
|
import FormFieldTemplateLarge from '../forms/FormFieldTemplateLarge.svelte';
|
||||||
@@ -23,6 +24,7 @@
|
|||||||
currentEditorTheme,
|
currentEditorTheme,
|
||||||
extensions,
|
extensions,
|
||||||
selectedWidget,
|
selectedWidget,
|
||||||
|
singleDatabaseMode,
|
||||||
visibleWidgetSideBar,
|
visibleWidgetSideBar,
|
||||||
} from '../stores';
|
} from '../stores';
|
||||||
import { isMac } from '../utility/common';
|
import { isMac } from '../utility/common';
|
||||||
@@ -107,6 +109,19 @@ ORDER BY
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="heading">Connection</div>
|
<div class="heading">Connection</div>
|
||||||
|
|
||||||
|
<FormFieldTemplateLarge
|
||||||
|
label="Show only tabs from selected database"
|
||||||
|
type="checkbox"
|
||||||
|
labelProps={{
|
||||||
|
onClick: () => {
|
||||||
|
$singleDatabaseMode = !$singleDatabaseMode;
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CheckboxField checked={$singleDatabaseMode} on:change={e => ($singleDatabaseMode = e.target.checked)} />
|
||||||
|
</FormFieldTemplateLarge>
|
||||||
|
|
||||||
<FormCheckboxField
|
<FormCheckboxField
|
||||||
name="connection.autoRefresh"
|
name="connection.autoRefresh"
|
||||||
label="Automatic refresh of database model on background"
|
label="Automatic refresh of database model on background"
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ function subscribeCssVariable(store, transform, cssVariable) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const selectedWidget = writableWithStorage('database', 'selectedWidget');
|
export const selectedWidget = writableWithStorage('database', 'selectedWidget');
|
||||||
|
export const singleDatabaseMode = writableWithStorage<boolean>(false, 'singleDatabaseMode');
|
||||||
export const visibleWidgetSideBar = writableWithStorage(true, 'visibleWidgetSideBar');
|
export const visibleWidgetSideBar = writableWithStorage(true, 'visibleWidgetSideBar');
|
||||||
export const visibleSelectedWidget = derived(
|
export const visibleSelectedWidget = derived(
|
||||||
[selectedWidget, visibleWidgetSideBar],
|
[selectedWidget, visibleWidgetSideBar],
|
||||||
@@ -137,6 +138,7 @@ subscribeCssVariable(visibleSelectedWidget, x => (x ? 1 : 0), '--dim-visible-lef
|
|||||||
// subscribeCssVariable(visibleToolbar, x => (x ? 1 : 0), '--dim-visible-toolbar');
|
// subscribeCssVariable(visibleToolbar, x => (x ? 1 : 0), '--dim-visible-toolbar');
|
||||||
subscribeCssVariable(leftPanelWidth, x => `${x}px`, '--dim-left-panel-width');
|
subscribeCssVariable(leftPanelWidth, x => `${x}px`, '--dim-left-panel-width');
|
||||||
subscribeCssVariable(visibleTitleBar, x => (x ? 1 : 0), '--dim-visible-titlebar');
|
subscribeCssVariable(visibleTitleBar, x => (x ? 1 : 0), '--dim-visible-titlebar');
|
||||||
|
subscribeCssVariable(singleDatabaseMode, x => (x ? 0 : 1), '--dim-visible-tabs-databases');
|
||||||
|
|
||||||
let activeTabIdValue = null;
|
let activeTabIdValue = null;
|
||||||
activeTabId.subscribe(value => {
|
activeTabId.subscribe(value => {
|
||||||
@@ -198,6 +200,12 @@ pinnedDatabases.subscribe(value => {
|
|||||||
});
|
});
|
||||||
export const getPinnedDatabases = () => _.compact(pinnedDatabasesValue);
|
export const getPinnedDatabases = () => _.compact(pinnedDatabasesValue);
|
||||||
|
|
||||||
|
let singleDatabaseModeValue = null;
|
||||||
|
singleDatabaseMode.subscribe(value => {
|
||||||
|
singleDatabaseModeValue = value;
|
||||||
|
});
|
||||||
|
export const getSingleDatabaseMode = () => singleDatabaseModeValue;
|
||||||
|
|
||||||
let currentDatabaseValue = null;
|
let currentDatabaseValue = null;
|
||||||
currentDatabase.subscribe(value => {
|
currentDatabase.subscribe(value => {
|
||||||
currentDatabaseValue = value;
|
currentDatabaseValue = value;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { currentDatabase, openedTabs } from '../stores';
|
import { currentDatabase, getCurrentDatabase, getSingleDatabaseMode, openedTabs } from '../stores';
|
||||||
|
import { shouldShowTab } from '../widgets/TabsPanel.svelte';
|
||||||
import { callWhenAppLoaded } from './appLoadManager';
|
import { callWhenAppLoaded } from './appLoadManager';
|
||||||
import { getConnectionInfo } from './metadataLoaders';
|
import { getConnectionInfo } from './metadataLoaders';
|
||||||
|
|
||||||
@@ -8,6 +9,7 @@ let lastCurrentTab = null;
|
|||||||
openedTabs.subscribe(value => {
|
openedTabs.subscribe(value => {
|
||||||
const newCurrentTab = (value || []).find(x => x.selected);
|
const newCurrentTab = (value || []).find(x => x.selected);
|
||||||
if (newCurrentTab == lastCurrentTab) return;
|
if (newCurrentTab == lastCurrentTab) return;
|
||||||
|
if (getSingleDatabaseMode() && getCurrentDatabase()) return;
|
||||||
|
|
||||||
const lastTab = lastCurrentTab;
|
const lastTab = lastCurrentTab;
|
||||||
lastCurrentTab = newCurrentTab;
|
lastCurrentTab = newCurrentTab;
|
||||||
@@ -27,3 +29,22 @@ openedTabs.subscribe(value => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
currentDatabase.subscribe(currentDb => {
|
||||||
|
if (!getSingleDatabaseMode()) return;
|
||||||
|
openedTabs.update(tabs => {
|
||||||
|
const newTabs = tabs.map(tab => ({
|
||||||
|
...tab,
|
||||||
|
selected: tab.selected && shouldShowTab(tab, true, currentDb),
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (newTabs.find(x => x.selected)) return newTabs;
|
||||||
|
|
||||||
|
const selectedIndex = _.findLastIndex(newTabs, x => shouldShowTab(x));
|
||||||
|
|
||||||
|
return newTabs.map((x, index) => ({
|
||||||
|
...x,
|
||||||
|
selected: index == selectedIndex,
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,4 +1,23 @@
|
|||||||
<script lang="ts" context="module">
|
<script lang="ts" context="module">
|
||||||
|
const getCurrentValueMarker: any = {};
|
||||||
|
|
||||||
|
export function shouldShowTab(tab, singleDbMode = getCurrentValueMarker, currentDb = getCurrentValueMarker) {
|
||||||
|
if (singleDbMode == getCurrentValueMarker) {
|
||||||
|
singleDbMode = getSingleDatabaseMode();
|
||||||
|
}
|
||||||
|
if (singleDbMode) {
|
||||||
|
if (currentDb == getCurrentValueMarker) {
|
||||||
|
currentDb = getCurrentDatabase();
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
tab.closedTime == null &&
|
||||||
|
(!tab.props?.conid || tab.props?.conid == currentDb?.connection?._id) &&
|
||||||
|
(!tab.props?.database || tab.props?.database == currentDb?.name)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return tab.closedTime == null;
|
||||||
|
}
|
||||||
|
|
||||||
function allowCloseTabs(tabs) {
|
function allowCloseTabs(tabs) {
|
||||||
if (tabs.length == 0) return Promise.resolve(true);
|
if (tabs.length == 0) return Promise.resolve(true);
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
@@ -14,7 +33,8 @@
|
|||||||
const activeCandidate = getOpenedTabs().find(x => x.tabid == tabid);
|
const activeCandidate = getOpenedTabs().find(x => x.tabid == tabid);
|
||||||
const closeCandidates = getOpenedTabs()
|
const closeCandidates = getOpenedTabs()
|
||||||
.filter(x => closeCondition(x, activeCandidate))
|
.filter(x => closeCondition(x, activeCandidate))
|
||||||
.filter(x => x.unsaved && x.closedTime == null);
|
.filter(x => x.unsaved)
|
||||||
|
.filter(shouldShowTab);
|
||||||
|
|
||||||
if (!(await allowCloseTabs(closeCandidates))) return;
|
if (!(await allowCloseTabs(closeCandidates))) return;
|
||||||
|
|
||||||
@@ -24,14 +44,14 @@
|
|||||||
|
|
||||||
const newFiles = files.map(x => ({
|
const newFiles = files.map(x => ({
|
||||||
...x,
|
...x,
|
||||||
closedTime: x.closedTime || (closeCondition(x, active) ? new Date().getTime() : undefined),
|
closedTime: shouldShowTab(x) && closeCondition(x, active) ? new Date().getTime() : x.closedTime,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
if (newFiles.find(x => x.selected && x.closedTime == null)) {
|
if (newFiles.find(x => x.selected && shouldShowTab(x))) {
|
||||||
return newFiles;
|
return newFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
const selectedIndex = _.findLastIndex(newFiles, x => x.closedTime == null);
|
const selectedIndex = _.findLastIndex(newFiles, x => shouldShowTab(x));
|
||||||
|
|
||||||
return newFiles.map((x, index) => ({
|
return newFiles.map((x, index) => ({
|
||||||
...x,
|
...x,
|
||||||
@@ -43,7 +63,8 @@
|
|||||||
export const closeMultipleTabs = async (closeCondition, deleteFromHistory = false) => {
|
export const closeMultipleTabs = async (closeCondition, deleteFromHistory = false) => {
|
||||||
const closeCandidates = getOpenedTabs()
|
const closeCandidates = getOpenedTabs()
|
||||||
.filter(x => closeCondition(x))
|
.filter(x => closeCondition(x))
|
||||||
.filter(x => x.unsaved && x.closedTime == null);
|
.filter(x => x.unsaved)
|
||||||
|
.filter(shouldShowTab);
|
||||||
|
|
||||||
if (!(await allowCloseTabs(closeCandidates))) return;
|
if (!(await allowCloseTabs(closeCandidates))) return;
|
||||||
|
|
||||||
@@ -52,14 +73,14 @@
|
|||||||
? files.filter(x => !closeCondition(x))
|
? files.filter(x => !closeCondition(x))
|
||||||
: files.map(x => ({
|
: files.map(x => ({
|
||||||
...x,
|
...x,
|
||||||
closedTime: x.closedTime || (closeCondition(x) ? new Date().getTime() : undefined),
|
closedTime: shouldShowTab(x) && closeCondition(x) ? new Date().getTime() : x.closedTime,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
if (newFiles.find(x => x.selected && x.closedTime == null)) {
|
if (newFiles.find(x => x.selected && shouldShowTab(x))) {
|
||||||
return newFiles;
|
return newFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
const selectedIndex = _.findLastIndex(newFiles, x => x.closedTime == null);
|
const selectedIndex = _.findLastIndex(newFiles, x => shouldShowTab(x));
|
||||||
|
|
||||||
return newFiles.map((x, index) => ({
|
return newFiles.map((x, index) => ({
|
||||||
...x,
|
...x,
|
||||||
@@ -70,7 +91,9 @@
|
|||||||
|
|
||||||
const closeTab = closeTabFunc((x, active) => x.tabid == active.tabid);
|
const closeTab = closeTabFunc((x, active) => x.tabid == active.tabid);
|
||||||
const closeAll = async () => {
|
const closeAll = async () => {
|
||||||
const closeCandidates = getOpenedTabs().filter(x => x.unsaved && x.closedTime == null);
|
const closeCandidates = getOpenedTabs()
|
||||||
|
.filter(x => x.unsaved)
|
||||||
|
.filter(shouldShowTab);
|
||||||
|
|
||||||
if (!(await allowCloseTabs(closeCandidates))) return;
|
if (!(await allowCloseTabs(closeCandidates))) return;
|
||||||
|
|
||||||
@@ -78,7 +101,7 @@
|
|||||||
openedTabs.update(tabs =>
|
openedTabs.update(tabs =>
|
||||||
tabs.map(tab => ({
|
tabs.map(tab => ({
|
||||||
...tab,
|
...tab,
|
||||||
closedTime: tab.closedTime || closedTime,
|
closedTime: shouldShowTab(tab) ? closedTime : tab.closedTime,
|
||||||
selected: false,
|
selected: false,
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
@@ -133,10 +156,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function switchTabByOrder(reverse) {
|
function switchTabByOrder(reverse) {
|
||||||
const tabs = _.sortBy(
|
const tabs = _.sortBy(get(openedTabs).filter(shouldShowTab), 'tabOrder');
|
||||||
get(openedTabs).filter(x => x.closedTime == null),
|
|
||||||
'tabOrder'
|
|
||||||
);
|
|
||||||
if (reverse) tabs.reverse();
|
if (reverse) tabs.reverse();
|
||||||
const selectedTab = tabs.find(x => x.selected);
|
const selectedTab = tabs.find(x => x.selected);
|
||||||
if (!selectedTab) return;
|
if (!selectedTab) return;
|
||||||
@@ -212,8 +232,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { LogarithmicScale } from 'chart.js';
|
import _ from 'lodash';
|
||||||
import _, { map, slice, sortBy } from 'lodash';
|
|
||||||
import { tick } from 'svelte';
|
import { tick } from 'svelte';
|
||||||
import { derived, get } from 'svelte/store';
|
import { derived, get } from 'svelte/store';
|
||||||
import registerCommand from '../commands/registerCommand';
|
import registerCommand from '../commands/registerCommand';
|
||||||
@@ -231,6 +250,8 @@
|
|||||||
activeTabId,
|
activeTabId,
|
||||||
getActiveTabId,
|
getActiveTabId,
|
||||||
getCurrentDatabase,
|
getCurrentDatabase,
|
||||||
|
singleDatabaseMode,
|
||||||
|
getSingleDatabaseMode,
|
||||||
} from '../stores';
|
} from '../stores';
|
||||||
import tabs from '../tabs';
|
import tabs from '../tabs';
|
||||||
import { setSelectedTab } from '../utility/common';
|
import { setSelectedTab } from '../utility/common';
|
||||||
@@ -243,6 +264,7 @@
|
|||||||
import TabCloseButton from '../elements/TabCloseButton.svelte';
|
import TabCloseButton from '../elements/TabCloseButton.svelte';
|
||||||
import CloseTabModal from '../modals/CloseTabModal.svelte';
|
import CloseTabModal from '../modals/CloseTabModal.svelte';
|
||||||
|
|
||||||
|
$: showTabFilterFunc = tab => shouldShowTab(tab, $singleDatabaseMode, $currentDatabase);
|
||||||
$: connectionList = useConnectionList();
|
$: connectionList = useConnectionList();
|
||||||
|
|
||||||
$: currentDbKey =
|
$: currentDbKey =
|
||||||
@@ -252,13 +274,11 @@
|
|||||||
? `server://${$currentDatabase.connection._id}`
|
? `server://${$currentDatabase.connection._id}`
|
||||||
: '_no';
|
: '_no';
|
||||||
|
|
||||||
$: tabsWithDb = $openedTabs
|
$: tabsWithDb = $openedTabs.filter(showTabFilterFunc).map(tab => ({
|
||||||
.filter(x => !x.closedTime)
|
...tab,
|
||||||
.map(tab => ({
|
tabDbName: getTabDbName(tab, $connectionList),
|
||||||
...tab,
|
tabDbKey: getTabDbKey(tab),
|
||||||
tabDbName: getTabDbName(tab, $connectionList),
|
}));
|
||||||
tabDbKey: getTabDbKey(tab),
|
|
||||||
}));
|
|
||||||
|
|
||||||
$: groupedTabs = groupTabs(tabsWithDb);
|
$: groupedTabs = groupTabs(tabsWithDb);
|
||||||
|
|
||||||
@@ -423,54 +443,56 @@
|
|||||||
<div class="tabs" on:wheel={handleTabsWheel} bind:this={domTabs}>
|
<div class="tabs" on:wheel={handleTabsWheel} bind:this={domTabs}>
|
||||||
{#each groupedTabs as tabGroup}
|
{#each groupedTabs as tabGroup}
|
||||||
<div class="db-wrapper">
|
<div class="db-wrapper">
|
||||||
<div
|
{#if !$singleDatabaseMode}
|
||||||
class="db-name"
|
|
||||||
class:selected={draggingDbGroup
|
|
||||||
? tabGroup.grpid == draggingDbGroupTarget?.grpid
|
|
||||||
: tabGroup.tabDbKey == currentDbKey}
|
|
||||||
on:mouseup={e => {
|
|
||||||
if (e.button == 1) {
|
|
||||||
closeMultipleTabs(tab => tabGroup.tabs.find(x => x.tabid == tab.tabid));
|
|
||||||
} else {
|
|
||||||
handleSetDb(tabGroup.tabs[0].props);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
use:contextMenu={getDatabaseContextMenu(tabGroup.tabs)}
|
|
||||||
style={$connectionColorFactory(
|
|
||||||
tabGroup.tabs[0].props,
|
|
||||||
(draggingDbGroup ? tabGroup.grpid == draggingDbGroupTarget?.grpid : tabGroup.tabDbKey == currentDbKey)
|
|
||||||
? 2
|
|
||||||
: 3
|
|
||||||
)}
|
|
||||||
draggable={true}
|
|
||||||
on:dragstart={e => {
|
|
||||||
draggingDbGroup = tabGroup;
|
|
||||||
}}
|
|
||||||
on:dragenter={e => {
|
|
||||||
draggingDbGroupTarget = tabGroup;
|
|
||||||
}}
|
|
||||||
on:drop={e => {
|
|
||||||
dragDropTabs(draggingDbGroup.tabs, tabGroup.tabs);
|
|
||||||
}}
|
|
||||||
on:dragend={e => {
|
|
||||||
draggingDbGroup = null;
|
|
||||||
draggingDbGroupTarget = null;
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div class="db-name-inner">
|
|
||||||
<FontIcon icon={getDbIcon(tabGroup.tabDbKey)} />
|
|
||||||
{tabGroup.tabDbName}
|
|
||||||
{#if $connectionList?.find(x => x._id == tabGroup.tabs[0]?.props?.conid)?.isReadOnly}
|
|
||||||
<FontIcon icon="icon lock" />
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
<div
|
<div
|
||||||
class="close-button-right tabCloseButton"
|
class="db-name"
|
||||||
on:click={e => closeMultipleTabs(tab => tabGroup.tabs.find(x => x.tabid == tab.tabid))}
|
class:selected={draggingDbGroup
|
||||||
|
? tabGroup.grpid == draggingDbGroupTarget?.grpid
|
||||||
|
: tabGroup.tabDbKey == currentDbKey}
|
||||||
|
on:mouseup={e => {
|
||||||
|
if (e.button == 1) {
|
||||||
|
closeMultipleTabs(tab => tabGroup.tabs.find(x => x.tabid == tab.tabid));
|
||||||
|
} else {
|
||||||
|
handleSetDb(tabGroup.tabs[0].props);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
use:contextMenu={getDatabaseContextMenu(tabGroup.tabs)}
|
||||||
|
style={$connectionColorFactory(
|
||||||
|
tabGroup.tabs[0].props,
|
||||||
|
(draggingDbGroup ? tabGroup.grpid == draggingDbGroupTarget?.grpid : tabGroup.tabDbKey == currentDbKey)
|
||||||
|
? 2
|
||||||
|
: 3
|
||||||
|
)}
|
||||||
|
draggable={true}
|
||||||
|
on:dragstart={e => {
|
||||||
|
draggingDbGroup = tabGroup;
|
||||||
|
}}
|
||||||
|
on:dragenter={e => {
|
||||||
|
draggingDbGroupTarget = tabGroup;
|
||||||
|
}}
|
||||||
|
on:drop={e => {
|
||||||
|
dragDropTabs(draggingDbGroup.tabs, tabGroup.tabs);
|
||||||
|
}}
|
||||||
|
on:dragend={e => {
|
||||||
|
draggingDbGroup = null;
|
||||||
|
draggingDbGroupTarget = null;
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<FontIcon icon="icon close" />
|
<div class="db-name-inner">
|
||||||
|
<FontIcon icon={getDbIcon(tabGroup.tabDbKey)} />
|
||||||
|
{tabGroup.tabDbName}
|
||||||
|
{#if $connectionList?.find(x => x._id == tabGroup.tabs[0]?.props?.conid)?.isReadOnly}
|
||||||
|
<FontIcon icon="icon lock" />
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="close-button-right tabCloseButton"
|
||||||
|
on:click={e => closeMultipleTabs(tab => tabGroup.tabs.find(x => x.tabid == tab.tabid))}
|
||||||
|
>
|
||||||
|
<FontIcon icon="icon close" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{/if}
|
||||||
<div class="db-group">
|
<div class="db-group">
|
||||||
{#each tabGroup.tabs as tab}
|
{#each tabGroup.tabs as tab}
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -7,9 +7,9 @@
|
|||||||
visibleSelectedWidget,
|
visibleSelectedWidget,
|
||||||
visibleWidgetSideBar,
|
visibleWidgetSideBar,
|
||||||
visibleHamburgerMenuWidget,
|
visibleHamburgerMenuWidget,
|
||||||
|
singleDatabaseMode,
|
||||||
} from '../stores';
|
} from '../stores';
|
||||||
import mainMenuDefinition from '../../../../app/src/mainMenuDefinition';
|
import mainMenuDefinition from '../../../../app/src/mainMenuDefinition';
|
||||||
import { useConfig } from '../utility/metadataLoaders';
|
|
||||||
import hasPermission from '../utility/hasPermission';
|
import hasPermission from '../utility/hasPermission';
|
||||||
|
|
||||||
let domSettings;
|
let domSettings;
|
||||||
@@ -90,8 +90,6 @@
|
|||||||
const items = mainMenuDefinition({ editMenu: false });
|
const items = mainMenuDefinition({ editMenu: false });
|
||||||
currentDropDownMenu.set({ left, top, items });
|
currentDropDownMenu.set({ left, top, items });
|
||||||
}
|
}
|
||||||
|
|
||||||
$: config = useConfig();
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="main">
|
<div class="main">
|
||||||
@@ -112,6 +110,15 @@
|
|||||||
|
|
||||||
<div class="flex1"> </div>
|
<div class="flex1"> </div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="wrapper"
|
||||||
|
title={`Toggle whether tabs from all databases are visible. Currently - ${$singleDatabaseMode ? 'NO' : 'YES'}`}
|
||||||
|
on:click={() => {
|
||||||
|
$singleDatabaseMode = !$singleDatabaseMode;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FontIcon icon={$singleDatabaseMode ? 'icon single-database-mode' : 'icon multi-database-mode'} />
|
||||||
|
</div>
|
||||||
<div class="wrapper" on:click={handleSettingsMenu} bind:this={domSettings}>
|
<div class="wrapper" on:click={handleSettingsMenu} bind:this={domSettings}>
|
||||||
<FontIcon icon="icon settings" />
|
<FontIcon icon="icon settings" />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1069,10 +1069,10 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@js-joda/core/-/core-5.2.0.tgz#fcebb14cffbf25adaaeec20d4579530e896ecd4a"
|
resolved "https://registry.yarnpkg.com/@js-joda/core/-/core-5.2.0.tgz#fcebb14cffbf25adaaeec20d4579530e896ecd4a"
|
||||||
integrity sha512-0OriPYIaMLB3XiLQMe0BXKVIqeriTn3H7JMOzTsHEtt7Zqq+TetCu97KnAhU3ckiQZKBxfZshft+H1OC4D1lXw==
|
integrity sha512-0OriPYIaMLB3XiLQMe0BXKVIqeriTn3H7JMOzTsHEtt7Zqq+TetCu97KnAhU3ckiQZKBxfZshft+H1OC4D1lXw==
|
||||||
|
|
||||||
"@mdi/font@^5.9.55":
|
"@mdi/font@^7.1.96":
|
||||||
version "5.9.55"
|
version "7.1.96"
|
||||||
resolved "https://registry.yarnpkg.com/@mdi/font/-/font-5.9.55.tgz#41acd50b88073ded7095fc3029d8712b6e12f38e"
|
resolved "https://registry.yarnpkg.com/@mdi/font/-/font-7.1.96.tgz#211ca4acfa31964278e5085de595e8c73967d400"
|
||||||
integrity sha512-jswRF6q3eq8NWpWiqct6q+6Fg/I7nUhrxYJfiEM8JJpap0wVJLQdbKtyS65GdlK7S7Ytnx3TTi/bmw+tBhkGmg==
|
integrity sha512-Imag6npmfkBDi2Ze2jiZVAPTDIKLxhz2Sx82xJ2zctyAU5LYJejLI5ChnDwiD9bMkQfVuzEsI98Q8toHyC+HCg==
|
||||||
|
|
||||||
"@mrmlnc/readdir-enhanced@^2.2.1":
|
"@mrmlnc/readdir-enhanced@^2.2.1":
|
||||||
version "2.2.1"
|
version "2.2.1"
|
||||||
|
|||||||
Reference in New Issue
Block a user