feat(sidebar): expose visible object filters in the connection tree
* feat(sidebar): expose visible object filter * fix(sidebar): refine visible filter status * refactor(sidebar): move visible filter status to details * fix(sidebar): clarify visible filter action
This commit is contained in:
1 parent
cc5a4068d2
commit
dfb9971849
26 files changed
+793
-9
No files matched your search
+121
@@ -0,0 +1,121 @@
|
||||
import { createPinia, setActivePinia } from "pinia";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { ConnectionConfig, TreeNode } from "@/types/database";
|
||||
|
||||
function installLocalStorage() {
|
||||
const data = new Map<string, string>();
|
||||
vi.stubGlobal("localStorage", {
|
||||
getItem: vi.fn((key: string) => data.get(key) ?? null),
|
||||
setItem: vi.fn((key: string, value: string) => data.set(key, value)),
|
||||
removeItem: vi.fn((key: string) => data.delete(key)),
|
||||
});
|
||||
}
|
||||
|
||||
function duckDbConnection(visibleDatabases?: string[]): ConnectionConfig {
|
||||
return {
|
||||
id: "duckdb-1",
|
||||
name: "DuckDB",
|
||||
db_type: "duckdb",
|
||||
host: "",
|
||||
port: 0,
|
||||
username: "",
|
||||
password: "",
|
||||
database: "main",
|
||||
visible_databases: visibleDatabases,
|
||||
} as ConnectionConfig;
|
||||
}
|
||||
|
||||
function connectionNode(connection: ConnectionConfig): TreeNode {
|
||||
return {
|
||||
id: connection.id,
|
||||
label: connection.name,
|
||||
type: "connection",
|
||||
connectionId: connection.id,
|
||||
isExpanded: false,
|
||||
children: [],
|
||||
};
|
||||
}
|
||||
|
||||
function rootEntries(node: TreeNode | undefined) {
|
||||
return (node?.children ?? []).map((child) => ({
|
||||
type: child.type,
|
||||
database: child.database,
|
||||
schema: child.schema,
|
||||
label: child.label,
|
||||
}));
|
||||
}
|
||||
|
||||
async function setupStore(visibleDatabases?: string[]) {
|
||||
const listDatabases = vi.fn().mockResolvedValue([{ name: "main" }, { name: "analytics" }, { name: "warehouse" }]);
|
||||
const listSchemas = vi.fn().mockResolvedValue(["main", "reporting"]);
|
||||
const saveConnections = vi.fn().mockResolvedValue(undefined);
|
||||
vi.doMock("@/lib/backend/tauriRuntime", () => ({ isTauriRuntime: () => false }));
|
||||
vi.doMock("@/lib/backend/api", () => ({
|
||||
checkConnectionHealth: vi.fn().mockResolvedValue(undefined),
|
||||
deleteSchemaCachePrefix: vi.fn().mockResolvedValue(undefined),
|
||||
listDatabases,
|
||||
listSchemas,
|
||||
loadSchemaCache: vi.fn().mockResolvedValue(null),
|
||||
saveConnections,
|
||||
saveSchemaCache: vi.fn().mockResolvedValue(undefined),
|
||||
saveSidebarLayout: vi.fn().mockResolvedValue(undefined),
|
||||
}));
|
||||
|
||||
const { useConnectionStore } = await import("@/stores/connectionStore");
|
||||
const store = useConnectionStore();
|
||||
const connection = duckDbConnection(visibleDatabases);
|
||||
store.connections = [connection];
|
||||
store.connectedIds.add(connection.id);
|
||||
store.sidebarLayout = { groups: [], order: [{ type: "connection", id: connection.id }] };
|
||||
store.treeNodes = [connectionNode(connection)];
|
||||
return { store, connection, saveConnections };
|
||||
}
|
||||
|
||||
describe("connectionStore DuckDB visible databases", () => {
|
||||
beforeEach(() => {
|
||||
vi.resetModules();
|
||||
vi.unstubAllGlobals();
|
||||
installLocalStorage();
|
||||
setActivePinia(createPinia());
|
||||
});
|
||||
|
||||
it("keeps main schemas and hides attached databases when only main is visible", async () => {
|
||||
const { store, connection } = await setupStore();
|
||||
|
||||
await store.loadDatabases(connection.id, { force: true });
|
||||
await store.setVisibleDatabases(connection.id, ["main"]);
|
||||
|
||||
expect(rootEntries(store.treeNodes[0])).toEqual([
|
||||
{ type: "schema", database: "main", schema: "main", label: "main" },
|
||||
{ type: "schema", database: "main", schema: "reporting", label: "reporting" },
|
||||
]);
|
||||
expect(store.getSidebarVisibleFilterSummary(connection.id)).toEqual({ mode: "database", isActive: true, selected: 1, total: 3 });
|
||||
});
|
||||
|
||||
it("hides main schemas and unselected attached databases", async () => {
|
||||
const { store, connection } = await setupStore();
|
||||
|
||||
await store.loadDatabases(connection.id, { force: true });
|
||||
await store.setVisibleDatabases(connection.id, ["warehouse"]);
|
||||
|
||||
expect(rootEntries(store.treeNodes[0])).toEqual([{ type: "database", database: "warehouse", schema: undefined, label: "warehouse" }]);
|
||||
expect(store.getSidebarVisibleFilterSummary(connection.id)).toEqual({ mode: "database", isActive: true, selected: 1, total: 3 });
|
||||
});
|
||||
|
||||
it("restores main schemas and every attached database after clearing the filter", async () => {
|
||||
const { store, connection, saveConnections } = await setupStore();
|
||||
await store.loadDatabases(connection.id, { force: true });
|
||||
await store.setVisibleDatabases(connection.id, ["warehouse"]);
|
||||
|
||||
await store.clearVisibleDatabases(connection.id);
|
||||
|
||||
expect(rootEntries(store.treeNodes[0])).toEqual([
|
||||
{ type: "schema", database: "main", schema: "main", label: "main" },
|
||||
{ type: "schema", database: "main", schema: "reporting", label: "reporting" },
|
||||
{ type: "database", database: "analytics", schema: undefined, label: "analytics" },
|
||||
{ type: "database", database: "warehouse", schema: undefined, label: "warehouse" },
|
||||
]);
|
||||
expect(store.getSidebarVisibleFilterSummary(connection.id)).toEqual({ mode: "database", isActive: false, selected: 3, total: 3 });
|
||||
expect(saveConnections).toHaveBeenLastCalledWith([expect.objectContaining({ id: connection.id, visible_databases: undefined })]);
|
||||
});
|
||||
});
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
import { createPinia, setActivePinia } from "pinia";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { encodeSchemaTreeCache } from "@/lib/metadata/schemaTreeCache";
|
||||
import type { ConnectionConfig, TreeNode } from "@/types/database";
|
||||
|
||||
function installLocalStorage() {
|
||||
const data = new Map<string, string>();
|
||||
vi.stubGlobal("localStorage", {
|
||||
getItem: vi.fn((key: string) => data.get(key) ?? null),
|
||||
setItem: vi.fn((key: string, value: string) => data.set(key, value)),
|
||||
removeItem: vi.fn((key: string) => data.delete(key)),
|
||||
});
|
||||
}
|
||||
|
||||
function mysqlConnection(visibleDatabases?: string[]): ConnectionConfig {
|
||||
return {
|
||||
id: "mysql-visible-1",
|
||||
name: "MySQL visible filter",
|
||||
db_type: "mysql",
|
||||
host: "127.0.0.1",
|
||||
port: 3306,
|
||||
username: "root",
|
||||
password: "",
|
||||
database: "filter_alpha",
|
||||
visible_databases: visibleDatabases,
|
||||
} as ConnectionConfig;
|
||||
}
|
||||
|
||||
async function setupStore(visibleDatabases?: string[]) {
|
||||
const connection = mysqlConnection(visibleDatabases);
|
||||
const cachedChildren = [databaseNode(connection.id, "filter_alpha"), databaseNode(connection.id, "filter_beta")];
|
||||
const listDatabases = vi.fn().mockResolvedValue([
|
||||
{ name: "filter_alpha", comment: null },
|
||||
{ name: "filter_beta", comment: null },
|
||||
{ name: "filter_gamma", comment: null },
|
||||
]);
|
||||
const disconnectDb = vi.fn().mockResolvedValue(undefined);
|
||||
|
||||
vi.doMock("@/lib/backend/tauriRuntime", () => ({ isTauriRuntime: () => false }));
|
||||
vi.doMock("@/lib/backend/api", () => ({
|
||||
checkConnectionHealth: vi.fn().mockResolvedValue(undefined),
|
||||
connectDb: vi.fn().mockResolvedValue(connection.id),
|
||||
connectionDatabaseInfo: vi.fn().mockResolvedValue(null),
|
||||
connectionIdentifierQuote: vi.fn().mockResolvedValue("`"),
|
||||
deleteSchemaCachePrefix: vi.fn().mockResolvedValue(undefined),
|
||||
disconnectDb,
|
||||
listDatabases,
|
||||
listInstalledAgents: vi.fn().mockResolvedValue([]),
|
||||
loadSchemaCache: vi.fn().mockResolvedValue(encodeSchemaTreeCache(cachedChildren)),
|
||||
saveConnections: vi.fn().mockResolvedValue(undefined),
|
||||
saveSchemaCache: vi.fn().mockResolvedValue(undefined),
|
||||
saveSidebarLayout: vi.fn().mockResolvedValue(undefined),
|
||||
}));
|
||||
|
||||
const { useConnectionStore } = await import("@/stores/connectionStore");
|
||||
const store = useConnectionStore();
|
||||
store.connections = [connection];
|
||||
store.sidebarLayout = { groups: [], order: [{ type: "connection", id: connection.id }] };
|
||||
store.treeNodes = [
|
||||
{
|
||||
id: connection.id,
|
||||
label: connection.name,
|
||||
type: "connection",
|
||||
connectionId: connection.id,
|
||||
isExpanded: false,
|
||||
children: [],
|
||||
},
|
||||
];
|
||||
return { connection, disconnectDb, listDatabases, store };
|
||||
}
|
||||
|
||||
function databaseNode(connectionId: string, database: string): TreeNode {
|
||||
return {
|
||||
id: `${connectionId}:${database}`,
|
||||
label: database,
|
||||
type: "database",
|
||||
connectionId,
|
||||
database,
|
||||
isExpanded: false,
|
||||
children: [],
|
||||
};
|
||||
}
|
||||
|
||||
describe("connectionStore visible filter lifecycle", () => {
|
||||
beforeEach(() => {
|
||||
vi.resetModules();
|
||||
vi.unstubAllGlobals();
|
||||
installLocalStorage();
|
||||
setActivePinia(createPinia());
|
||||
});
|
||||
|
||||
it("hydrates a saved partial filter count on first expansion and clears it on disconnect", async () => {
|
||||
const { connection, disconnectDb, listDatabases, store } = await setupStore(["filter_alpha", "filter_beta"]);
|
||||
|
||||
expect(store.getSidebarVisibleFilterSummary(connection.id)).toEqual({ mode: "database", isActive: false, selected: null, total: null });
|
||||
|
||||
await store.loadDatabases(connection.id);
|
||||
|
||||
await vi.waitFor(() => expect(listDatabases).toHaveBeenCalledTimes(1));
|
||||
await vi.waitFor(() =>
|
||||
expect(store.getSidebarVisibleFilterSummary(connection.id)).toEqual({
|
||||
mode: "database",
|
||||
isActive: true,
|
||||
selected: 2,
|
||||
total: 3,
|
||||
}),
|
||||
);
|
||||
expect(store.connectedIds.has(connection.id)).toBe(true);
|
||||
|
||||
await store.disconnect(connection.id);
|
||||
|
||||
expect(disconnectDb).toHaveBeenCalledWith(connection.id, expect.any(Number));
|
||||
expect(store.connectedIds.has(connection.id)).toBe(false);
|
||||
expect(store.getSidebarVisibleFilterSummary(connection.id)).toEqual({ mode: "database", isActive: false, selected: null, total: null });
|
||||
});
|
||||
|
||||
it("does not add a background refresh for an unfiltered cached connection", async () => {
|
||||
const { connection, listDatabases, store } = await setupStore();
|
||||
|
||||
await store.loadDatabases(connection.id);
|
||||
|
||||
expect(store.connectedIds.has(connection.id)).toBe(true);
|
||||
expect(listDatabases).not.toHaveBeenCalled();
|
||||
expect(store.getSidebarVisibleFilterSummary(connection.id)).toEqual({ mode: "database", isActive: false, selected: null, total: null });
|
||||
});
|
||||
});
|
||||
@@ -123,6 +123,8 @@ import i18n from "@/i18n";
|
||||
import type { MqAdminConfig } from "@/types/mq";
|
||||
import { RABBITMQ_MQ_TENANT, resolveMqSystemKindFromConnection } from "@/lib/mq/mqConsoleDefaults";
|
||||
import { applySidebarDatabaseStorage, applySidebarTableStorage, sidebarDatabaseNames, supportsSidebarDatabaseStorage, supportsSidebarTableStorage, type SidebarTableStorageScope } from "@/lib/sidebar/sidebarDatabaseStorage";
|
||||
import { connectionHasConfiguredSidebarVisibleFilter, sidebarVisibleFilterSummary } from "@/lib/sidebar/sidebarVisibleFilterSummary";
|
||||
import { connectionCanConfigureSidebarVisibleDatabases } from "@/lib/sidebar/sidebarVisibleFilterMenu";
|
||||
|
||||
const PINNED_TREE_NODES_STORAGE_KEY = "dbx-pinned-tree-nodes";
|
||||
const ACTIVE_CONNECTION_STORAGE_KEY = "dbx-active-connection";
|
||||
@@ -344,6 +346,7 @@ export const useConnectionStore = defineStore("connection", () => {
|
||||
const completionColumnsCache = ref<Record<string, ColumnInfo[]>>({});
|
||||
const completionForeignKeysCache = ref<Record<string, ForeignKeyInfo[]>>({});
|
||||
const completionDatabasesCache = ref<Record<string, string[]>>({});
|
||||
const primaryVisibleObjectNames = ref<Record<string, string[]>>({});
|
||||
const sqlServerCompletionContextCache = ref<Record<string, SqlServerCompletionContext>>({});
|
||||
const elasticsearchCompletionIndicesCache = ref<Record<string, string[]>>({});
|
||||
const redisCompletionKeysCache = ref<Record<string, string[]>>({});
|
||||
@@ -444,6 +447,7 @@ export const useConnectionStore = defineStore("connection", () => {
|
||||
const connectionStateRevisions = new Map<string, number>();
|
||||
const connectionErrorRevisions = new Map<string, number>();
|
||||
const treeNodeLoads = new TreeNodeLoadRegistry();
|
||||
const primaryVisibleObjectRefreshInFlight = new Set<string>();
|
||||
let nextLocalConnectionAttempt = 0;
|
||||
let beforeConnectHandler: BeforeConnectHandler | null = null;
|
||||
let initFromDiskPromise: Promise<void> | null = null;
|
||||
@@ -902,6 +906,7 @@ export const useConnectionStore = defineStore("connection", () => {
|
||||
|
||||
function markConnectionLost(connectionId: string, error: unknown) {
|
||||
connectedIds.value.delete(connectionId);
|
||||
clearPrimaryVisibleObjectNames(connectionId);
|
||||
clearConnectionIdentifierQuote(connectionId);
|
||||
clearConnectionNodeLoading(connectionId);
|
||||
clearConnectionHealthCheck(connectionId);
|
||||
@@ -2377,6 +2382,7 @@ export const useConnectionStore = defineStore("connection", () => {
|
||||
clearConnectionError(id);
|
||||
connectionErrorRevisions.delete(id);
|
||||
connectedIds.value.delete(id);
|
||||
clearPrimaryVisibleObjectNames(id);
|
||||
clearConnectionIdentifierQuote(id);
|
||||
clearConnectionHealthCheck(id);
|
||||
sidebarLayout.value = removeConnectionFromSidebarLayout(sidebarLayout.value, id);
|
||||
@@ -2412,6 +2418,7 @@ export const useConnectionStore = defineStore("connection", () => {
|
||||
connections.value = nextConnections;
|
||||
rebuildTreeNodes();
|
||||
if (!runtimeConfigChanged) return;
|
||||
clearPrimaryVisibleObjectNames(config.id);
|
||||
connectedIds.value.delete(config.id);
|
||||
clearConnectionIdentifierQuote(config.id);
|
||||
clearConnectionHealthCheck(config.id);
|
||||
@@ -2557,6 +2564,34 @@ export const useConnectionStore = defineStore("connection", () => {
|
||||
await reloadConnectionDatabaseChildren(connectionId);
|
||||
}
|
||||
|
||||
function recordPrimaryVisibleObjectNames(connectionId: string, objectNames: readonly string[]) {
|
||||
const names = [...objectNames];
|
||||
const existing = primaryVisibleObjectNames.value[connectionId];
|
||||
if (existing?.length === names.length && existing.every((name, index) => name === names[index])) return;
|
||||
primaryVisibleObjectNames.value = { ...primaryVisibleObjectNames.value, [connectionId]: names };
|
||||
}
|
||||
|
||||
function clearPrimaryVisibleObjectNames(connectionId: string) {
|
||||
if (!(connectionId in primaryVisibleObjectNames.value)) return;
|
||||
const next = { ...primaryVisibleObjectNames.value };
|
||||
delete next[connectionId];
|
||||
primaryVisibleObjectNames.value = next;
|
||||
}
|
||||
|
||||
function getSidebarVisibleFilterSummary(connectionId: string) {
|
||||
const config = getConfig(connectionId);
|
||||
return config ? sidebarVisibleFilterSummary(config, primaryVisibleObjectNames.value[connectionId]) : null;
|
||||
}
|
||||
|
||||
function scheduleMissingPrimaryVisibleObjectNamesRefresh(connectionId: string, config: ConnectionConfig | undefined, options?: LoadTreeOptions) {
|
||||
if (options?.force || !config || primaryVisibleObjectNames.value[connectionId] || primaryVisibleObjectRefreshInFlight.has(connectionId)) return;
|
||||
if (!connectionCanConfigureSidebarVisibleDatabases(config.db_type) || !connectionHasConfiguredSidebarVisibleFilter(config)) return;
|
||||
primaryVisibleObjectRefreshInFlight.add(connectionId);
|
||||
void loadDatabases(connectionId, { force: true, connectedOnly: true })
|
||||
.catch(() => undefined)
|
||||
.finally(() => primaryVisibleObjectRefreshInFlight.delete(connectionId));
|
||||
}
|
||||
|
||||
async function clearVisibleDatabases(connectionId: string) {
|
||||
const config = getConfig(connectionId);
|
||||
if (!config || !Array.isArray(config.visible_databases)) return;
|
||||
@@ -2738,6 +2773,7 @@ export const useConnectionStore = defineStore("connection", () => {
|
||||
if (!cancelled) return false;
|
||||
clearConnectionError(connectionId);
|
||||
connectedIds.value.delete(connectionId);
|
||||
clearPrimaryVisibleObjectNames(connectionId);
|
||||
clearConnectionIdentifierQuote(connectionId);
|
||||
clearConnectionHealthCheck(connectionId);
|
||||
if (activeConnectionId.value === connectionId) activeConnectionId.value = null;
|
||||
@@ -2753,6 +2789,7 @@ export const useConnectionStore = defineStore("connection", () => {
|
||||
const shouldRemoveOneTimeConnection = getConfig(connectionId)?.one_time === true;
|
||||
|
||||
connectedIds.value.delete(connectionId);
|
||||
clearPrimaryVisibleObjectNames(connectionId);
|
||||
clearConnectionIdentifierQuote(connectionId);
|
||||
forgetSuccessfulLocalConnectionAttempt(connectionId);
|
||||
clearConnectionHealthCheck(connectionId);
|
||||
@@ -2829,6 +2866,7 @@ export const useConnectionStore = defineStore("connection", () => {
|
||||
} catch {
|
||||
// Backend pool is dead — remove from connectedIds and reconnect
|
||||
connectedIds.value.delete(connectionId);
|
||||
clearPrimaryVisibleObjectNames(connectionId);
|
||||
clearConnectionHealthCheck(connectionId);
|
||||
if (activeConnectionId.value === connectionId) activeConnectionId.value = null;
|
||||
}
|
||||
@@ -3028,23 +3066,33 @@ export const useConnectionStore = defineStore("connection", () => {
|
||||
await ensureConnected(connectionId);
|
||||
load = reclaimTreeNodeLoad(load, node);
|
||||
}
|
||||
if (useCachedChildren(node, options, load)) return;
|
||||
|
||||
const config = getConfig(connectionId);
|
||||
if (useCachedChildren(node, options, load)) {
|
||||
scheduleMissingPrimaryVisibleObjectNamesRefresh(connectionId, config, options);
|
||||
return;
|
||||
}
|
||||
|
||||
if (config?.db_type === "duckdb") {
|
||||
const cacheKey = schemaCacheKey(connectionId, "duckdb-root");
|
||||
if (!options?.force) {
|
||||
const cached = await loadPersistedTreeChildren(node, cacheKey, load);
|
||||
if (cached.hit) {
|
||||
if (cached.isStale) refreshStaleTreeNode(node);
|
||||
else scheduleMissingPrimaryVisibleObjectNamesRefresh(connectionId, config, options);
|
||||
return;
|
||||
}
|
||||
}
|
||||
const [databases, schemas] = await Promise.all([withMetadataLoadTimeout(connectionId, api.listDatabases(connectionId), "databases"), withMetadataLoadTimeout(connectionId, api.listSchemas(connectionId, "main"), "schemas")]);
|
||||
const children = withSavedSqlRoot(connectionId, buildDuckDbConnectionTreeNodes(connectionId, databases, schemas), node);
|
||||
const databaseNames = databases.map((database) => database.name);
|
||||
const visibleNames = filterDatabaseNamesForConnection(databaseNames, config);
|
||||
const visibleNameSet = new Set(visibleNames);
|
||||
const visibleDatabases = databases.filter((database) => visibleNameSet.has(database.name));
|
||||
const visibleSchemas = visibleNameSet.has("main") ? schemas : [];
|
||||
const children = withSavedSqlRoot(connectionId, buildDuckDbConnectionTreeNodes(connectionId, visibleDatabases, visibleSchemas), node);
|
||||
if (isSidebarSearchQueryChanged(options)) return;
|
||||
const targetNode = treeNodeLoadTarget(load);
|
||||
if (!targetNode) return;
|
||||
recordPrimaryVisibleObjectNames(connectionId, databaseNames);
|
||||
setChildren(targetNode, children);
|
||||
await savePersistedConnectionTreeChildren(cacheKey, targetNode.children || children);
|
||||
} else if (config && connectionUsesVisibleSchemaFilter(config)) {
|
||||
@@ -3056,10 +3104,11 @@ export const useConnectionStore = defineStore("connection", () => {
|
||||
const cached = await loadPersistedTreeChildren(node, cacheKey, load);
|
||||
if (cached.hit) {
|
||||
if (cached.isStale) refreshStaleTreeNode(node);
|
||||
else scheduleMissingPrimaryVisibleObjectNamesRefresh(connectionId, config, options);
|
||||
return;
|
||||
}
|
||||
}
|
||||
const schemas = await withMetadataLoadTimeout(connectionId, api.listSchemas(connectionId, effectiveDb, true), "schemas");
|
||||
const schemas = await withMetadataLoadTimeout(connectionId, api.listSchemas(connectionId, effectiveDb), "schemas");
|
||||
const visibleSchemas = filterSchemaNamesForConnection(schemas, schemaFilterConfig, effectiveDb || "", { showSystemSchemas });
|
||||
const schemaNodes: TreeNode[] = sortSidebarNames(visibleSchemas).map((s) => ({
|
||||
id: `${connectionId}:${s}:${s}`,
|
||||
@@ -3074,6 +3123,7 @@ export const useConnectionStore = defineStore("connection", () => {
|
||||
if (isSidebarSearchQueryChanged(options)) return;
|
||||
const targetNode = treeNodeLoadTarget(load);
|
||||
if (!targetNode) return;
|
||||
recordPrimaryVisibleObjectNames(connectionId, schemas);
|
||||
setChildren(targetNode, withSavedSqlRoot(connectionId, schemaNodes, targetNode));
|
||||
await savePersistedConnectionTreeChildren(cacheKey, targetNode.children || schemaNodes);
|
||||
} else {
|
||||
@@ -3120,6 +3170,7 @@ export const useConnectionStore = defineStore("connection", () => {
|
||||
const cached = await loadPersistedTreeChildren(node, cacheKey, load);
|
||||
if (cached.hit) {
|
||||
if (cached.isStale) refreshStaleTreeNode(node);
|
||||
else scheduleMissingPrimaryVisibleObjectNamesRefresh(connectionId, config, options);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -3157,6 +3208,10 @@ export const useConnectionStore = defineStore("connection", () => {
|
||||
if (isSidebarSearchQueryChanged(options)) return;
|
||||
const targetNode = treeNodeLoadTarget(load);
|
||||
if (!targetNode) return;
|
||||
recordPrimaryVisibleObjectNames(
|
||||
connectionId,
|
||||
databases.map((database) => database.name),
|
||||
);
|
||||
setChildren(targetNode, children);
|
||||
await savePersistedConnectionTreeChildren(cacheKey, targetNode.children || children);
|
||||
}
|
||||
@@ -3212,6 +3267,10 @@ export const useConnectionStore = defineStore("connection", () => {
|
||||
const visibleNameSet = new Set(visibleNames);
|
||||
const targetNode = treeNodeLoadTarget(load);
|
||||
if (!targetNode) return;
|
||||
recordPrimaryVisibleObjectNames(
|
||||
connectionId,
|
||||
dbs.map((db) => String(db.db)),
|
||||
);
|
||||
setChildren(
|
||||
targetNode,
|
||||
withSavedSqlRoot(
|
||||
@@ -3516,6 +3575,7 @@ export const useConnectionStore = defineStore("connection", () => {
|
||||
const visibleDbs = filterDatabaseNamesForConnection(dbs, config);
|
||||
const targetNode = treeNodeLoadTarget(load);
|
||||
if (!targetNode) return;
|
||||
recordPrimaryVisibleObjectNames(connectionId, dbs);
|
||||
setChildren(
|
||||
targetNode,
|
||||
withSavedSqlRoot(
|
||||
@@ -6903,6 +6963,8 @@ export const useConnectionStore = defineStore("connection", () => {
|
||||
ensureVisibleDatabase,
|
||||
setVisibleSchemas,
|
||||
clearVisibleSchemas,
|
||||
recordPrimaryVisibleObjectNames,
|
||||
getSidebarVisibleFilterSummary,
|
||||
removeConnection,
|
||||
removeConnections,
|
||||
editingConnectionId,
|
||||
|
||||
Reference in new issue
Block a user