mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-19 18:56:00 +00:00
focusable databases WIP
This commit is contained in:
@@ -446,6 +446,7 @@ await dbgateApi.dropAllDbObjects(${JSON.stringify(
|
|||||||
currentArchive,
|
currentArchive,
|
||||||
currentDatabase,
|
currentDatabase,
|
||||||
extensions,
|
extensions,
|
||||||
|
focusedConnectionOrDatabase,
|
||||||
getCurrentDatabase,
|
getCurrentDatabase,
|
||||||
getExtensions,
|
getExtensions,
|
||||||
getOpenedTabs,
|
getOpenedTabs,
|
||||||
@@ -512,7 +513,13 @@ await dbgateApi.dropAllDbObjects(${JSON.stringify(
|
|||||||
passProps?.connectionColorFactory({ conid: data?.connection?._id, database: data.name }, null, null, false)}
|
passProps?.connectionColorFactory({ conid: data?.connection?._id, database: data.name }, null, null, false)}
|
||||||
isBold={$currentDatabase?.connection?._id == data?.connection?._id &&
|
isBold={$currentDatabase?.connection?._id == data?.connection?._id &&
|
||||||
extractDbNameFromComposite($currentDatabase?.name) == data.name}
|
extractDbNameFromComposite($currentDatabase?.name) == data.name}
|
||||||
on:click={() => switchCurrentDatabase(data)}
|
on:dblclick={() => {
|
||||||
|
switchCurrentDatabase(data);
|
||||||
|
passProps?.onFocusSqlObjectList?.();
|
||||||
|
}}
|
||||||
|
on:click={() => {
|
||||||
|
$focusedConnectionOrDatabase = { conid: data.connection?._id, database: data.name };
|
||||||
|
}}
|
||||||
on:dragstart
|
on:dragstart
|
||||||
on:dragenter
|
on:dragenter
|
||||||
on:dragend
|
on:dragend
|
||||||
@@ -532,4 +539,6 @@ await dbgateApi.dropAllDbObjects(${JSON.stringify(
|
|||||||
list.filter(x => x?.name != data?.name || x?.connection?._id != data?.connection?._id)
|
list.filter(x => x?.name != data?.name || x?.connection?._id != data?.connection?._id)
|
||||||
)
|
)
|
||||||
: null}
|
: null}
|
||||||
|
isChoosed={data.connection?._id == $focusedConnectionOrDatabase?.conid &&
|
||||||
|
data.name == $focusedConnectionOrDatabase?.database}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -15,13 +15,11 @@
|
|||||||
|
|
||||||
$: databases = useDatabaseList({ conid: isExpandedOnlyBySearch ? null : data._id });
|
$: databases = useDatabaseList({ conid: isExpandedOnlyBySearch ? null : data._id });
|
||||||
$: dbList = isExpandedOnlyBySearch ? getLocalStorage(`database_list_${data._id}`) || [] : $databases || [];
|
$: dbList = isExpandedOnlyBySearch ? getLocalStorage(`database_list_${data._id}`) || [] : $databases || [];
|
||||||
|
|
||||||
$: connectionLabel = getConnectionLabel(data);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<AppObjectList
|
<AppObjectList
|
||||||
list={_.sortBy(
|
list={_.sortBy(
|
||||||
dbList.filter(x => filterName(filter, x.name, connectionLabel)),
|
dbList.filter(x => filterName(filter, x.name, data.displayName, data.server)),
|
||||||
x => x.sortOrder ?? x.name
|
x => x.sortOrder ?? x.name
|
||||||
).map(db => ({ ...db, connection: data }))}
|
).map(db => ({ ...db, connection: data }))}
|
||||||
module={databaseAppObject}
|
module={databaseAppObject}
|
||||||
|
|||||||
@@ -15,9 +15,11 @@
|
|||||||
let domDiv = null;
|
let domDiv = null;
|
||||||
|
|
||||||
function handleKeyDown(ev) {
|
function handleKeyDown(ev) {
|
||||||
|
const listInstance = _.isFunction(list) ? list() : list;
|
||||||
|
|
||||||
function selectByDiff(diff) {
|
function selectByDiff(diff) {
|
||||||
const selected = getSelectedObject();
|
const selected = getSelectedObject();
|
||||||
const index = _.findIndex(list, x => selectedObjectMatcher(x, selected));
|
const index = _.findIndex(listInstance, x => selectedObjectMatcher(x, selected));
|
||||||
|
|
||||||
if (index == 0 && diff < 0) {
|
if (index == 0 && diff < 0) {
|
||||||
onFocusFilterBox?.();
|
onFocusFilterBox?.();
|
||||||
@@ -26,16 +28,16 @@
|
|||||||
|
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
let newIndex = index + diff;
|
let newIndex = index + diff;
|
||||||
if (newIndex >= list.length) {
|
if (newIndex >= listInstance.length) {
|
||||||
newIndex = list.length - 1;
|
newIndex = listInstance.length - 1;
|
||||||
}
|
}
|
||||||
if (newIndex < 0) {
|
if (newIndex < 0) {
|
||||||
newIndex = 0;
|
newIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (list[newIndex]) {
|
if (listInstance[newIndex]) {
|
||||||
selectedObjectStore.set(list[newIndex]);
|
selectedObjectStore.set(listInstance[newIndex]);
|
||||||
handleObjectClick?.(list[newIndex], { tabPreviewMode: true });
|
handleObjectClick?.(listInstance[newIndex], { tabPreviewMode: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newIndex == 0) {
|
if (newIndex == 0) {
|
||||||
@@ -64,25 +66,27 @@
|
|||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
}
|
}
|
||||||
if (ev.keyCode == keycodes.home) {
|
if (ev.keyCode == keycodes.home) {
|
||||||
if (list[0]) {
|
if (listInstance[0]) {
|
||||||
selectedObjectStore.set(list[0]);
|
selectedObjectStore.set(listInstance[0]);
|
||||||
handleObjectClick?.(list[0], { tabPreviewMode: true });
|
handleObjectClick?.(listInstance[0], { tabPreviewMode: true });
|
||||||
onScrollTop?.();
|
onScrollTop?.();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ev.keyCode == keycodes.end) {
|
if (ev.keyCode == keycodes.end) {
|
||||||
if (list[list.length - 1]) {
|
if (listInstance[listInstance.length - 1]) {
|
||||||
selectedObjectStore.set(list[list.length - 1]);
|
selectedObjectStore.set(listInstance[listInstance.length - 1]);
|
||||||
handleObjectClick?.(list[list.length - 1], { tabPreviewMode: true });
|
handleObjectClick?.(listInstance[listInstance.length - 1], { tabPreviewMode: true });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function focusFirst() {
|
export function focusFirst() {
|
||||||
|
const listInstance = _.isFunction(list) ? list() : list;
|
||||||
|
|
||||||
domDiv?.focus();
|
domDiv?.focus();
|
||||||
if (list[0]) {
|
if (listInstance[0]) {
|
||||||
selectedObjectStore.set(list[0]);
|
selectedObjectStore.set(listInstance[0]);
|
||||||
handleObjectClick?.(list[0], { tabPreviewMode: true });
|
handleObjectClick?.(listInstance[0], { tabPreviewMode: true });
|
||||||
onScrollTop?.();
|
onScrollTop?.();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,10 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
connectionAppObject.
|
||||||
|
|
||||||
|
connectionAppObject.
|
||||||
|
|
||||||
|
connectionAppObject.
|
||||||
|
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import InlineButton from '../buttons/InlineButton.svelte';
|
import InlineButton from '../buttons/InlineButton.svelte';
|
||||||
import SearchInput from '../elements/SearchInput.svelte';
|
import SearchInput from '../elements/SearchInput.svelte';
|
||||||
@@ -20,7 +26,7 @@
|
|||||||
getFocusedConnectionOrDatabase,
|
getFocusedConnectionOrDatabase,
|
||||||
} from '../stores';
|
} from '../stores';
|
||||||
import runCommand from '../commands/runCommand';
|
import runCommand from '../commands/runCommand';
|
||||||
import { getConnectionLabel } from 'dbgate-tools';
|
import { filterName, getConnectionLabel } from 'dbgate-tools';
|
||||||
import { useConnectionColorFactory } from '../utility/useConnectionColor';
|
import { useConnectionColorFactory } from '../utility/useConnectionColor';
|
||||||
import FontIcon from '../icons/FontIcon.svelte';
|
import FontIcon from '../icons/FontIcon.svelte';
|
||||||
import CloseSearchButton from '../buttons/CloseSearchButton.svelte';
|
import CloseSearchButton from '../buttons/CloseSearchButton.svelte';
|
||||||
@@ -32,10 +38,16 @@
|
|||||||
import InputTextModal from '../modals/InputTextModal.svelte';
|
import InputTextModal from '../modals/InputTextModal.svelte';
|
||||||
import ConfirmModal from '../modals/ConfirmModal.svelte';
|
import ConfirmModal from '../modals/ConfirmModal.svelte';
|
||||||
import AppObjectListHandler from './AppObjectListHandler.svelte';
|
import AppObjectListHandler from './AppObjectListHandler.svelte';
|
||||||
|
import { getLocalStorage } from '../utility/storageCache';
|
||||||
|
import { switchCurrentDatabase } from '../utility/common';
|
||||||
|
import openNewTab from '../utility/openNewTab';
|
||||||
|
import {openConnection} from '../appobj/ConnectionAppObject.svelte';
|
||||||
|
|
||||||
const connections = useConnectionList();
|
const connections = useConnectionList();
|
||||||
const serverStatus = useServerStatus();
|
const serverStatus = useServerStatus();
|
||||||
|
|
||||||
|
export let passProps: any = {};
|
||||||
|
|
||||||
let filter = '';
|
let filter = '';
|
||||||
let domListHandler;
|
let domListHandler;
|
||||||
let domContainer = null;
|
let domContainer = null;
|
||||||
@@ -66,10 +78,42 @@
|
|||||||
connection => (getConnectionLabel(connection) || '').toUpperCase()
|
connection => (getConnectionLabel(connection) || '').toUpperCase()
|
||||||
);
|
);
|
||||||
|
|
||||||
$: focusFlatList = [
|
function getFocusFlatList() {
|
||||||
...connectionsWithParent.map(x => ({ conid: x._id })),
|
const expanded = $expandedConnections;
|
||||||
...connectionsWithoutParent.map(x => ({ conid: x._id })),
|
const opened = $openedConnections;
|
||||||
];
|
|
||||||
|
const res = [];
|
||||||
|
for (const con of [...connectionsWithParent, ...connectionsWithoutParent]) {
|
||||||
|
const databases = getLocalStorage(`database_list_${con._id}`) || [];
|
||||||
|
if (!filterName(filter, con.displayName, con.server, ...databases.map(x => x.name))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
res.push({
|
||||||
|
connection: con,
|
||||||
|
conid: con._id,
|
||||||
|
});
|
||||||
|
|
||||||
|
if ((expanded.includes(con._id) && opened.includes(con._id)) || filter) {
|
||||||
|
for (const db of _.sortBy(databases, x => x.sortOrder ?? x.name)) {
|
||||||
|
if (!filterName(filter, con.displayName, con.server, db.name)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
res.push({
|
||||||
|
conid: con._id,
|
||||||
|
database: db.name,
|
||||||
|
dbobj: {
|
||||||
|
connection: con,
|
||||||
|
name: db.name,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
const handleRefreshConnections = () => {
|
const handleRefreshConnections = () => {
|
||||||
for (const conid of $openedConnections) {
|
for (const conid of $openedConnections) {
|
||||||
@@ -161,7 +205,7 @@
|
|||||||
>
|
>
|
||||||
<AppObjectListHandler
|
<AppObjectListHandler
|
||||||
bind:this={domListHandler}
|
bind:this={domListHandler}
|
||||||
list={focusFlatList}
|
list={getFocusFlatList}
|
||||||
selectedObjectStore={focusedConnectionOrDatabase}
|
selectedObjectStore={focusedConnectionOrDatabase}
|
||||||
getSelectedObject={getFocusedConnectionOrDatabase}
|
getSelectedObject={getFocusedConnectionOrDatabase}
|
||||||
selectedObjectMatcher={(o1, o2) => o1.conid == o2.conid && o1.database == o2.database}
|
selectedObjectMatcher={(o1, o2) => o1.conid == o2.conid && o1.database == o2.database}
|
||||||
@@ -171,6 +215,28 @@
|
|||||||
onFocusFilterBox={() => {
|
onFocusFilterBox={() => {
|
||||||
domFilter?.focus();
|
domFilter?.focus();
|
||||||
}}
|
}}
|
||||||
|
handleObjectClick={(data, options) => {
|
||||||
|
if (data.database) {
|
||||||
|
if (options.focusTab) {
|
||||||
|
switchCurrentDatabase(data.dbobj);
|
||||||
|
passProps?.onFocusSqlObjectList?.();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (options.focusTab) {
|
||||||
|
openConnection(data.connection);
|
||||||
|
} else {
|
||||||
|
openNewTab({
|
||||||
|
title: getConnectionLabel(data.connection),
|
||||||
|
icon: 'img connection',
|
||||||
|
tabComponent: 'ConnectionTab',
|
||||||
|
tabPreviewMode: options.tabPreviewMode,
|
||||||
|
props: {
|
||||||
|
conid: data.conid,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<AppObjectList
|
<AppObjectList
|
||||||
list={connectionsWithParent}
|
list={connectionsWithParent}
|
||||||
@@ -179,7 +245,7 @@
|
|||||||
expandOnClick
|
expandOnClick
|
||||||
isExpandable={data => $openedConnections.includes(data._id) && !data.singleDatabase}
|
isExpandable={data => $openedConnections.includes(data._id) && !data.singleDatabase}
|
||||||
{filter}
|
{filter}
|
||||||
passProps={{ connectionColorFactory: $connectionColorFactory, showPinnedInsteadOfUnpin: true }}
|
passProps={{ ...passProps, connectionColorFactory: $connectionColorFactory, showPinnedInsteadOfUnpin: true }}
|
||||||
getIsExpanded={data => $expandedConnections.includes(data._id) && !data.singleDatabase}
|
getIsExpanded={data => $expandedConnections.includes(data._id) && !data.singleDatabase}
|
||||||
setIsExpanded={(data, value) => {
|
setIsExpanded={(data, value) => {
|
||||||
expandedConnections.update(old => (value ? [...old, data._id] : old.filter(x => x != data._id)));
|
expandedConnections.update(old => (value ? [...old, data._id] : old.filter(x => x != data._id)));
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
|
||||||
export let hidden = false;
|
export let hidden = false;
|
||||||
|
let domSqlObjectList = null;
|
||||||
|
|
||||||
$: conid = $currentDatabase?.connection?._id;
|
$: conid = $currentDatabase?.connection?._id;
|
||||||
$: connection = useConnectionInfo({ conid });
|
$: connection = useConnectionInfo({ conid });
|
||||||
@@ -32,7 +33,7 @@
|
|||||||
</WidgetColumnBarItem>
|
</WidgetColumnBarItem>
|
||||||
{:else if !$config?.singleDbConnection}
|
{:else if !$config?.singleDbConnection}
|
||||||
<WidgetColumnBarItem title="Connections" name="connections" height="35%" storageName="connectionsWidget">
|
<WidgetColumnBarItem title="Connections" name="connections" height="35%" storageName="connectionsWidget">
|
||||||
<ConnectionList />
|
<ConnectionList passProps={{ onFocusSqlObjectList: () => domSqlObjectList.focus() }} />
|
||||||
</WidgetColumnBarItem>
|
</WidgetColumnBarItem>
|
||||||
{/if}
|
{/if}
|
||||||
<WidgetColumnBarItem
|
<WidgetColumnBarItem
|
||||||
@@ -48,7 +49,7 @@
|
|||||||
|
|
||||||
<WidgetColumnBarItem
|
<WidgetColumnBarItem
|
||||||
title={driver?.databaseEngineTypes?.includes('document')
|
title={driver?.databaseEngineTypes?.includes('document')
|
||||||
? driver?.collectionPluralLabel ?? 'Collections/containers'
|
? (driver?.collectionPluralLabel ?? 'Collections/containers')
|
||||||
: 'Tables, views, functions'}
|
: 'Tables, views, functions'}
|
||||||
name="dbObjects"
|
name="dbObjects"
|
||||||
storageName="dbObjectsWidget"
|
storageName="dbObjectsWidget"
|
||||||
@@ -58,7 +59,7 @@
|
|||||||
(driver?.databaseEngineTypes?.includes('sql') || driver?.databaseEngineTypes?.includes('document'))
|
(driver?.databaseEngineTypes?.includes('sql') || driver?.databaseEngineTypes?.includes('document'))
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<SqlObjectList {conid} {database} />
|
<SqlObjectList {conid} {database} bind:this={domSqlObjectList} />
|
||||||
</WidgetColumnBarItem>
|
</WidgetColumnBarItem>
|
||||||
|
|
||||||
<WidgetColumnBarItem
|
<WidgetColumnBarItem
|
||||||
|
|||||||
@@ -125,6 +125,10 @@
|
|||||||
if (matcher && !matcher(filter)) return false;
|
if (matcher && !matcher(filter)) return false;
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export function focus() {
|
||||||
|
domListHandler?.focusFirst();
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if $status && $status.name == 'error'}
|
{#if $status && $status.name == 'error'}
|
||||||
|
|||||||
Reference in New Issue
Block a user