mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-07-12 16:02:48 +08:00
🐛 fix(sidebar): 修正树节点加载与展开时序
This commit is contained in:
@@ -24,11 +24,13 @@ import Sidebar, {
|
|||||||
resolveSidebarDropTargetMetricsFromDomEvent,
|
resolveSidebarDropTargetMetricsFromDomEvent,
|
||||||
resolveSidebarDropInsertBefore,
|
resolveSidebarDropInsertBefore,
|
||||||
resolveSidebarNodeConnectionId,
|
resolveSidebarNodeConnectionId,
|
||||||
|
resolveSidebarSwitcherLoadKey,
|
||||||
resolveV2ActiveConnectionId,
|
resolveV2ActiveConnectionId,
|
||||||
resolveV2ObjectGroupTitle,
|
resolveV2ObjectGroupTitle,
|
||||||
isSidebarTablePinned,
|
isSidebarTablePinned,
|
||||||
SQLFileExecutionProgressContent,
|
SQLFileExecutionProgressContent,
|
||||||
resolveSidebarTableNameForCopy,
|
resolveSidebarTableNameForCopy,
|
||||||
|
shouldKeepSidebarSwitcherCollapsedWhileLoading,
|
||||||
shouldClearSidebarActiveContextOnEmptySelect,
|
shouldClearSidebarActiveContextOnEmptySelect,
|
||||||
shouldSkipSidebarLoadOnExpandWhileDragging,
|
shouldSkipSidebarLoadOnExpandWhileDragging,
|
||||||
shouldSkipSidebarSelectWhileDragging,
|
shouldSkipSidebarSelectWhileDragging,
|
||||||
@@ -319,6 +321,45 @@ describe('Sidebar locate toolbar', () => {
|
|||||||
expect(shouldLoadSidebarNodeOnExpand({ type: 'object-group', children: [] })).toBe(false);
|
expect(shouldLoadSidebarNodeOnExpand({ type: 'object-group', children: [] })).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('keeps sidebar switchers collapsed while lazy loading is still pending', () => {
|
||||||
|
const connectionNode = {
|
||||||
|
key: 'conn-1',
|
||||||
|
data: {
|
||||||
|
key: 'conn-1',
|
||||||
|
title: '开发240',
|
||||||
|
type: 'connection' as const,
|
||||||
|
dataRef: { id: 'conn-1' },
|
||||||
|
},
|
||||||
|
expanded: true,
|
||||||
|
};
|
||||||
|
const databaseNode = {
|
||||||
|
key: 'conn-1-main',
|
||||||
|
data: {
|
||||||
|
key: 'conn-1-main',
|
||||||
|
title: 'main',
|
||||||
|
type: 'database' as const,
|
||||||
|
dataRef: { id: 'conn-1', dbName: 'main' },
|
||||||
|
},
|
||||||
|
expanded: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(resolveSidebarSwitcherLoadKey(connectionNode)).toBe('dbs-conn-1');
|
||||||
|
expect(resolveSidebarSwitcherLoadKey(databaseNode)).toBe('tables-conn-1-main');
|
||||||
|
expect(shouldKeepSidebarSwitcherCollapsedWhileLoading(connectionNode, new Set(['dbs-conn-1']))).toBe(true);
|
||||||
|
expect(shouldKeepSidebarSwitcherCollapsedWhileLoading(databaseNode, new Set(['tables-conn-1-main']))).toBe(true);
|
||||||
|
expect(shouldKeepSidebarSwitcherCollapsedWhileLoading({
|
||||||
|
key: 'table-users',
|
||||||
|
data: {
|
||||||
|
key: 'table-users',
|
||||||
|
title: 'users',
|
||||||
|
type: 'table' as const,
|
||||||
|
dataRef: { id: 'conn-1', dbName: 'main', tableName: 'users' },
|
||||||
|
},
|
||||||
|
loading: true,
|
||||||
|
}, new Set())).toBe(true);
|
||||||
|
expect(shouldKeepSidebarSwitcherCollapsedWhileLoading(databaseNode, new Set())).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
it('wires tree expand and double-click expansion to lazy loading', () => {
|
it('wires tree expand and double-click expansion to lazy loading', () => {
|
||||||
const source = readSidebarSource();
|
const source = readSidebarSource();
|
||||||
|
|
||||||
@@ -328,6 +369,9 @@ describe('Sidebar locate toolbar', () => {
|
|||||||
expect(source).toContain('clearTreeNodeChildrenByKeys(keysToClear);');
|
expect(source).toContain('clearTreeNodeChildrenByKeys(keysToClear);');
|
||||||
expect(source).toContain('if (!shouldSkipSidebarLoadOnExpandWhileDragging(isTreeDragging, info))');
|
expect(source).toContain('if (!shouldSkipSidebarLoadOnExpandWhileDragging(isTreeDragging, info))');
|
||||||
expect(source).toContain('if (shouldLoadSidebarNodeOnExpand(node))');
|
expect(source).toContain('if (shouldLoadSidebarNodeOnExpand(node))');
|
||||||
|
expect(source).toContain('const keepCollapsed = shouldKeepSidebarSwitcherCollapsedWhileLoading(node, loadingNodesRef.current);');
|
||||||
|
expect(source).toContain('return <CaretDownFilled rotate={keepCollapsed ? -90 : undefined} />;');
|
||||||
|
expect(source).toContain('switcherIcon={renderSidebarSwitcherIcon}');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('uses the appearance preference to switch table double-click to the embedded object designer', () => {
|
it('uses the appearance preference to switch table double-click to the embedded object designer', () => {
|
||||||
@@ -1133,6 +1177,13 @@ describe('Sidebar locate toolbar', () => {
|
|||||||
expect(source).toContain("export type SidebarConnectionState = 'loading' | 'success' | 'error';");
|
expect(source).toContain("export type SidebarConnectionState = 'loading' | 'success' | 'error';");
|
||||||
expect(treeLoaderSource).toContain("setConnectionStates(prev => ({ ...prev, [conn.id]: 'loading' }));");
|
expect(treeLoaderSource).toContain("setConnectionStates(prev => ({ ...prev, [conn.id]: 'loading' }));");
|
||||||
expect(treeLoaderSource).toContain("setConnectionStates(prev => ({ ...prev, [key as string]: 'loading' }));");
|
expect(treeLoaderSource).toContain("setConnectionStates(prev => ({ ...prev, [key as string]: 'loading' }));");
|
||||||
|
expect(treeLoaderSource).toContain('let shouldMarkConnectionSuccess = false;');
|
||||||
|
expect(treeLoaderSource).toContain('let shouldMarkDatabaseSuccess = false;');
|
||||||
|
expect(treeLoaderSource).toContain('loadingNodesRef.current.delete(loadKey);');
|
||||||
|
expect(treeLoaderSource).toContain('if (shouldMarkConnectionSuccess) {');
|
||||||
|
expect(treeLoaderSource).toContain("setConnectionStates(prev => ({ ...prev, [conn.id]: 'success' }));");
|
||||||
|
expect(treeLoaderSource).toContain('if (shouldMarkDatabaseSuccess) {');
|
||||||
|
expect(treeLoaderSource).toContain("setConnectionStates(prev => ({ ...prev, [key as string]: 'success' }));");
|
||||||
expect(titleRenderSource).toContain("let status: 'loading' | 'success' | 'error' | 'default' = 'default';");
|
expect(titleRenderSource).toContain("let status: 'loading' | 'success' | 'error' | 'default' = 'default';");
|
||||||
expect(titleRenderSource).toContain("if (connectionStates[node.key] === 'loading') status = 'loading';");
|
expect(titleRenderSource).toContain("if (connectionStates[node.key] === 'loading') status = 'loading';");
|
||||||
expect(v2ContextMenuSource).toContain("const statusMap = new Map<string, 'loading' | 'live' | 'error' | 'idle'>();");
|
expect(v2ContextMenuSource).toContain("const statusMap = new Map<string, 'loading' | 'live' | 'error' | 'idle'>();");
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ import React, { useEffect, useState, useMemo, useRef, useCallback, useDeferredVa
|
|||||||
import { createPortal } from 'react-dom';
|
import { createPortal } from 'react-dom';
|
||||||
import { Tree, message, Dropdown, MenuProps, Input, Button, Form, Popover, Tooltip } from 'antd';
|
import { Tree, message, Dropdown, MenuProps, Input, Button, Form, Popover, Tooltip } from 'antd';
|
||||||
import {
|
import {
|
||||||
|
CaretDownFilled,
|
||||||
DatabaseOutlined,
|
DatabaseOutlined,
|
||||||
TableOutlined,
|
TableOutlined,
|
||||||
ConsoleSqlOutlined,
|
ConsoleSqlOutlined,
|
||||||
@@ -209,6 +210,55 @@ export {
|
|||||||
};
|
};
|
||||||
export type { V2CommandSearchItem, V2RailConnectionGroup } from './sidebarV2Utils';
|
export type { V2CommandSearchItem, V2RailConnectionGroup } from './sidebarV2Utils';
|
||||||
|
|
||||||
|
type SidebarTreeSwitcherNodeLike = {
|
||||||
|
key?: React.Key;
|
||||||
|
data?: TreeNode;
|
||||||
|
isLeaf?: boolean;
|
||||||
|
loading?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const resolveSidebarSwitcherLoadKey = (node: SidebarTreeSwitcherNodeLike | null | undefined): string | null => {
|
||||||
|
const treeNode = node?.data;
|
||||||
|
const dataRef = treeNode?.dataRef;
|
||||||
|
if (!treeNode) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (treeNode.type === 'connection') {
|
||||||
|
const connectionId = String(dataRef?.id || treeNode.key || node?.key || '').trim();
|
||||||
|
return connectionId ? `dbs-${connectionId}` : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (treeNode.type === 'database') {
|
||||||
|
const connectionId = String(dataRef?.id || '').trim();
|
||||||
|
const dbName = String(dataRef?.dbName || '').trim();
|
||||||
|
return connectionId && dbName ? `tables-${connectionId}-${dbName}` : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (treeNode.type === 'jvm-mode' || treeNode.type === 'jvm-resource') {
|
||||||
|
const connectionId = String(dataRef?.id || '').trim();
|
||||||
|
const providerMode = String(dataRef?.providerMode || '').trim().toLowerCase();
|
||||||
|
const parentPath = treeNode.type === 'jvm-resource' ? String(dataRef?.resourcePath || '').trim() : '';
|
||||||
|
return connectionId && providerMode ? `jvm-resources-${connectionId}-${providerMode}-${parentPath}` : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const shouldKeepSidebarSwitcherCollapsedWhileLoading = (
|
||||||
|
node: SidebarTreeSwitcherNodeLike | null | undefined,
|
||||||
|
loadingKeys: ReadonlySet<string>,
|
||||||
|
): boolean => {
|
||||||
|
if (!node || node.isLeaf) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (node.loading) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const loadKey = resolveSidebarSwitcherLoadKey(node);
|
||||||
|
return !!loadKey && loadingKeys.has(loadKey);
|
||||||
|
};
|
||||||
|
|
||||||
const { Search } = Input;
|
const { Search } = Input;
|
||||||
const SIDEBAR_LOCATE_LOAD_WAIT_INTERVAL_MS = 50;
|
const SIDEBAR_LOCATE_LOAD_WAIT_INTERVAL_MS = 50;
|
||||||
const SIDEBAR_LOCATE_LOAD_WAIT_ATTEMPTS = 160;
|
const SIDEBAR_LOCATE_LOAD_WAIT_ATTEMPTS = 160;
|
||||||
@@ -1763,6 +1813,14 @@ const Sidebar: React.FC<{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const renderSidebarSwitcherIcon = useCallback((node: SidebarTreeSwitcherNodeLike) => {
|
||||||
|
if (node.isLeaf) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const keepCollapsed = shouldKeepSidebarSwitcherCollapsedWhileLoading(node, loadingNodesRef.current);
|
||||||
|
return <CaretDownFilled rotate={keepCollapsed ? -90 : undefined} />;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
const buildRuntimeConfig = (conn: any, overrideDatabase?: string, clearDatabase: boolean = false) => {
|
const buildRuntimeConfig = (conn: any, overrideDatabase?: string, clearDatabase: boolean = false) => {
|
||||||
@@ -2949,6 +3007,7 @@ const Sidebar: React.FC<{
|
|||||||
onDoubleClick={onDoubleClick}
|
onDoubleClick={onDoubleClick}
|
||||||
onSelect={onSelect}
|
onSelect={onSelect}
|
||||||
titleRender={titleRender}
|
titleRender={titleRender}
|
||||||
|
switcherIcon={renderSidebarSwitcherIcon}
|
||||||
expandedKeys={expandedKeys}
|
expandedKeys={expandedKeys}
|
||||||
onExpand={onExpand}
|
onExpand={onExpand}
|
||||||
loadedKeys={loadedKeys}
|
loadedKeys={loadedKeys}
|
||||||
|
|||||||
@@ -215,12 +215,13 @@ export const useSidebarTreeLoaders = ({
|
|||||||
console.warn('检查驱动代理更新状态失败', error);
|
console.warn('检查驱动代理更新状态失败', error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const loadDatabases = async (node: any) => {
|
const loadDatabases = async (node: any) => {
|
||||||
const conn = node.dataRef as SavedConnection;
|
const conn = node.dataRef as SavedConnection;
|
||||||
const loadKey = `dbs-${conn.id}`;
|
const loadKey = `dbs-${conn.id}`;
|
||||||
if (loadingNodesRef.current.has(loadKey)) return;
|
if (loadingNodesRef.current.has(loadKey)) return;
|
||||||
loadingNodesRef.current.add(loadKey);
|
loadingNodesRef.current.add(loadKey);
|
||||||
setConnectionStates(prev => ({ ...prev, [conn.id]: 'loading' }));
|
setConnectionStates(prev => ({ ...prev, [conn.id]: 'loading' }));
|
||||||
|
let shouldMarkConnectionSuccess = false;
|
||||||
const config = {
|
const config = {
|
||||||
...conn.config,
|
...conn.config,
|
||||||
port: Number(conn.config.port),
|
port: Number(conn.config.port),
|
||||||
@@ -234,7 +235,6 @@ export const useSidebarTreeLoaders = ({
|
|||||||
try {
|
try {
|
||||||
const res = await JVMProbeCapabilities(buildRuntimeConfig(conn) as any);
|
const res = await JVMProbeCapabilities(buildRuntimeConfig(conn) as any);
|
||||||
if (res.success) {
|
if (res.success) {
|
||||||
setConnectionStates(prev => ({ ...prev, [conn.id]: 'success' }));
|
|
||||||
const capabilities: JVMCapability[] = Array.isArray(res.data) ? res.data as JVMCapability[] : [];
|
const capabilities: JVMCapability[] = Array.isArray(res.data) ? res.data as JVMCapability[] : [];
|
||||||
const modeNodes: TreeNode[] = capabilities.map((capability) => ({
|
const modeNodes: TreeNode[] = capabilities.map((capability) => ({
|
||||||
title: capability.displayLabel || capability.mode,
|
title: capability.displayLabel || capability.mode,
|
||||||
@@ -264,6 +264,7 @@ export const useSidebarTreeLoaders = ({
|
|||||||
}));
|
}));
|
||||||
const diagnosticNode = buildJVMDiagnosticTreeNodes(conn);
|
const diagnosticNode = buildJVMDiagnosticTreeNodes(conn);
|
||||||
replaceTreeNodeChildren(node.key, [...monitoringNodes, ...modeNodes, ...diagnosticNode]);
|
replaceTreeNodeChildren(node.key, [...monitoringNodes, ...modeNodes, ...diagnosticNode]);
|
||||||
|
shouldMarkConnectionSuccess = true;
|
||||||
} else {
|
} else {
|
||||||
const diagnosticNode = buildJVMDiagnosticTreeNodes(conn);
|
const diagnosticNode = buildJVMDiagnosticTreeNodes(conn);
|
||||||
setConnectionStates(prev => ({ ...prev, [conn.id]: 'error' }));
|
setConnectionStates(prev => ({ ...prev, [conn.id]: 'error' }));
|
||||||
@@ -300,6 +301,9 @@ export const useSidebarTreeLoaders = ({
|
|||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
loadingNodesRef.current.delete(loadKey);
|
loadingNodesRef.current.delete(loadKey);
|
||||||
|
if (shouldMarkConnectionSuccess) {
|
||||||
|
setConnectionStates(prev => ({ ...prev, [conn.id]: 'success' }));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -309,7 +313,6 @@ export const useSidebarTreeLoaders = ({
|
|||||||
try {
|
try {
|
||||||
const res = await (window as any).go.app.App.RedisGetDatabases(buildRpcConnectionConfig(config));
|
const res = await (window as any).go.app.App.RedisGetDatabases(buildRpcConnectionConfig(config));
|
||||||
if (res.success) {
|
if (res.success) {
|
||||||
setConnectionStates(prev => ({ ...prev, [conn.id]: 'success' }));
|
|
||||||
const redisRows: any[] = Array.isArray(res.data) ? res.data : [];
|
const redisRows: any[] = Array.isArray(res.data) ? res.data : [];
|
||||||
const redisDbAliases = useStore.getState().appearance.redisDbAliases;
|
const redisDbAliases = useStore.getState().appearance.redisDbAliases;
|
||||||
let dbs = redisRows.map((db: any) => {
|
let dbs = redisRows.map((db: any) => {
|
||||||
@@ -333,6 +336,7 @@ export const useSidebarTreeLoaders = ({
|
|||||||
dbs = dbs.filter(db => conn.includeRedisDatabases!.includes(db.dbIndex));
|
dbs = dbs.filter(db => conn.includeRedisDatabases!.includes(db.dbIndex));
|
||||||
}
|
}
|
||||||
replaceTreeNodeChildren(node.key, dbs);
|
replaceTreeNodeChildren(node.key, dbs);
|
||||||
|
shouldMarkConnectionSuccess = true;
|
||||||
} else {
|
} else {
|
||||||
setConnectionStates(prev => ({ ...prev, [conn.id]: 'error' }));
|
setConnectionStates(prev => ({ ...prev, [conn.id]: 'error' }));
|
||||||
message.error({ content: res.message, key: `conn-${conn.id}-dbs` });
|
message.error({ content: res.message, key: `conn-${conn.id}-dbs` });
|
||||||
@@ -345,6 +349,9 @@ export const useSidebarTreeLoaders = ({
|
|||||||
});
|
});
|
||||||
} finally {
|
} finally {
|
||||||
loadingNodesRef.current.delete(loadKey);
|
loadingNodesRef.current.delete(loadKey);
|
||||||
|
if (shouldMarkConnectionSuccess) {
|
||||||
|
setConnectionStates(prev => ({ ...prev, [conn.id]: 'success' }));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -352,7 +359,6 @@ export const useSidebarTreeLoaders = ({
|
|||||||
try {
|
try {
|
||||||
const res = await DBGetDatabases(buildRpcConnectionConfig(config) as any);
|
const res = await DBGetDatabases(buildRpcConnectionConfig(config) as any);
|
||||||
if (res.success) {
|
if (res.success) {
|
||||||
setConnectionStates(prev => ({ ...prev, [conn.id]: 'success' }));
|
|
||||||
const dbRows: any[] = Array.isArray(res.data) ? res.data : [];
|
const dbRows: any[] = Array.isArray(res.data) ? res.data : [];
|
||||||
let dbs = dbRows.map((row: any) => ({
|
let dbs = dbRows.map((row: any) => ({
|
||||||
title: row.Database || row.database,
|
title: row.Database || row.database,
|
||||||
@@ -375,6 +381,7 @@ export const useSidebarTreeLoaders = ({
|
|||||||
setLoadedKeys(prev => prev.filter(k => k !== node.key));
|
setLoadedKeys(prev => prev.filter(k => k !== node.key));
|
||||||
message.warning({ content: t('sidebar.message.no_visible_databases'), key: `conn-${conn.id}-dbs` });
|
message.warning({ content: t('sidebar.message.no_visible_databases'), key: `conn-${conn.id}-dbs` });
|
||||||
}
|
}
|
||||||
|
shouldMarkConnectionSuccess = true;
|
||||||
} else {
|
} else {
|
||||||
setConnectionStates(prev => ({ ...prev, [conn.id]: 'error' }));
|
setConnectionStates(prev => ({ ...prev, [conn.id]: 'error' }));
|
||||||
setLoadedKeys(prev => prev.filter(k => k !== node.key));
|
setLoadedKeys(prev => prev.filter(k => k !== node.key));
|
||||||
@@ -389,6 +396,9 @@ export const useSidebarTreeLoaders = ({
|
|||||||
});
|
});
|
||||||
} finally {
|
} finally {
|
||||||
loadingNodesRef.current.delete(loadKey);
|
loadingNodesRef.current.delete(loadKey);
|
||||||
|
if (shouldMarkConnectionSuccess) {
|
||||||
|
setConnectionStates(prev => ({ ...prev, [conn.id]: 'success' }));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -450,6 +460,7 @@ export const useSidebarTreeLoaders = ({
|
|||||||
if (loadingNodesRef.current.has(loadKey)) return;
|
if (loadingNodesRef.current.has(loadKey)) return;
|
||||||
loadingNodesRef.current.add(loadKey);
|
loadingNodesRef.current.add(loadKey);
|
||||||
setConnectionStates(prev => ({ ...prev, [key as string]: 'loading' }));
|
setConnectionStates(prev => ({ ...prev, [key as string]: 'loading' }));
|
||||||
|
let shouldMarkDatabaseSuccess = false;
|
||||||
|
|
||||||
const dbQueries = savedQueries.filter(q => q.connectionId === conn.id && q.dbName === dbName);
|
const dbQueries = savedQueries.filter(q => q.connectionId === conn.id && q.dbName === dbName);
|
||||||
const queriesNode: TreeNode = {
|
const queriesNode: TreeNode = {
|
||||||
@@ -479,8 +490,6 @@ export const useSidebarTreeLoaders = ({
|
|||||||
try {
|
try {
|
||||||
const res = await DBGetTables(buildRpcConnectionConfig(config) as any, conn.dbName);
|
const res = await DBGetTables(buildRpcConnectionConfig(config) as any, conn.dbName);
|
||||||
if (res.success) {
|
if (res.success) {
|
||||||
setConnectionStates(prev => ({ ...prev, [key as string]: 'success' }));
|
|
||||||
|
|
||||||
const tableRows: any[] = Array.isArray(res.data) ? res.data : [];
|
const tableRows: any[] = Array.isArray(res.data) ? res.data : [];
|
||||||
const tableStatusSql = buildSidebarTableStatusSQL(conn as SavedConnection, conn.dbName);
|
const tableStatusSql = buildSidebarTableStatusSQL(conn as SavedConnection, conn.dbName);
|
||||||
const tableStatsResult = tableStatusSql
|
const tableStatsResult = tableStatusSql
|
||||||
@@ -959,6 +968,7 @@ export const useSidebarTreeLoaders = ({
|
|||||||
replaceTreeNodeChildren(key, [queriesNode, ...groupedNodes]);
|
replaceTreeNodeChildren(key, [queriesNode, ...groupedNodes]);
|
||||||
}
|
}
|
||||||
onDatabaseTreeLoaded?.(String(key));
|
onDatabaseTreeLoaded?.(String(key));
|
||||||
|
shouldMarkDatabaseSuccess = true;
|
||||||
} else {
|
} else {
|
||||||
setConnectionStates(prev => ({ ...prev, [key as string]: 'error' }));
|
setConnectionStates(prev => ({ ...prev, [key as string]: 'error' }));
|
||||||
message.error({ content: res.message, key: `db-${key}-tables` });
|
message.error({ content: res.message, key: `db-${key}-tables` });
|
||||||
@@ -971,6 +981,9 @@ export const useSidebarTreeLoaders = ({
|
|||||||
});
|
});
|
||||||
} finally {
|
} finally {
|
||||||
loadingNodesRef.current.delete(loadKey);
|
loadingNodesRef.current.delete(loadKey);
|
||||||
|
if (shouldMarkDatabaseSuccess) {
|
||||||
|
setConnectionStates(prev => ({ ...prev, [key as string]: 'success' }));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user