fix(sidebar): load visible schema filters on mount
This commit is contained in:
parent
1e7a33bd99
commit
86a6846b10
|
|
@ -85,6 +85,7 @@ import { usesSyntheticRowIdKey } from "@/lib/table/tableEditing";
|
|||
import { tableOpenPageLimit } from "@/lib/table/tableOpenPageLimit";
|
||||
import { getCachedTableMetadata, loadTableMetadata, TABLE_METADATA_CACHE_TTL_MS, tableMetadataToDataTabMeta } from "@/lib/metadata/tableMetadataCache";
|
||||
import {
|
||||
canConfigureVisibleSchemasForTreeNode,
|
||||
canCreateConnectionNamespace,
|
||||
canCreateDatabaseNodeNamespace,
|
||||
canEditDatabaseProperties as canEditDatabasePropertiesForNode,
|
||||
|
|
@ -161,7 +162,6 @@ import { isSqlServerLinkedNode } from "@/lib/database/sqlServerLinkedServers";
|
|||
import DatabaseIcon from "@/components/icons/DatabaseIcon.vue";
|
||||
import ConnectionErrorIndicator from "@/components/connection/ConnectionErrorIndicator.vue";
|
||||
import ProductionContextBadge from "@/components/common/ProductionContextBadge.vue";
|
||||
import { isSchemaAware } from "@/lib/database/databaseFeatureSupport";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import LightTooltip from "@/components/ui/LightTooltip.vue";
|
||||
|
|
@ -4251,15 +4251,9 @@ const canConfigureVisibleDatabases = computed(() => {
|
|||
});
|
||||
|
||||
const canConfigureVisibleSchemas = computed(() => {
|
||||
if (props.node.type === "database" && props.node.connectionId && props.node.database != null) {
|
||||
const dbType = connectionStore.getConfig(props.node.connectionId)?.db_type;
|
||||
return isSchemaAware(dbType);
|
||||
}
|
||||
if (props.node.type === "connection" && props.node.connectionId) {
|
||||
const dbType = connectionStore.getConfig(props.node.connectionId)?.db_type;
|
||||
return isSchemaAware(dbType) && !usesTreeSchemaMode(dbType);
|
||||
}
|
||||
return false;
|
||||
if (!props.node.connectionId) return false;
|
||||
const dbType = connectionStore.getConfig(props.node.connectionId)?.db_type;
|
||||
return canConfigureVisibleSchemasForTreeNode(dbType, props.node.type, props.node.database);
|
||||
});
|
||||
|
||||
const canCopyFinalProxyPort = computed(() => {
|
||||
|
|
|
|||
|
|
@ -67,6 +67,8 @@ watch(
|
|||
if (!open) return;
|
||||
loadDatabases().catch(() => {});
|
||||
},
|
||||
// Tree-level async hosts mount the dialog with `open` already true.
|
||||
{ immediate: true },
|
||||
);
|
||||
|
||||
watch(showSystemDatabases, (show) => {
|
||||
|
|
|
|||
|
|
@ -64,6 +64,8 @@ watch(
|
|||
loadSchemas().catch(() => {});
|
||||
}
|
||||
},
|
||||
// Tree-level async hosts mount the dialog with `open` already true.
|
||||
{ immediate: true },
|
||||
);
|
||||
|
||||
function initDraftMode() {
|
||||
|
|
|
|||
|
|
@ -40,6 +40,12 @@ export function usesTreeSchemaMode(dbType?: DatabaseType): boolean {
|
|||
return !!dbType && TREE_SCHEMA_TYPES.has(dbType);
|
||||
}
|
||||
|
||||
export function canConfigureVisibleSchemasForTreeNode(dbType: DatabaseType | undefined, nodeType: TreeNodeType, database?: string | null): boolean {
|
||||
if (!isSchemaAware(dbType)) return false;
|
||||
if (nodeType === "database") return database != null;
|
||||
return nodeType === "connection" && !usesTreeSchemaMode(dbType);
|
||||
}
|
||||
|
||||
export function usesDatabaseObjectTreeMode(dbType?: DatabaseType): boolean {
|
||||
return !!dbType && DATABASE_OBJECT_TREE_TYPES.has(dbType);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import assert from "node:assert/strict";
|
||||
import { test } from "vitest";
|
||||
import { appendVisibleDatabaseSelection, buildDraftVisibleDatabasesConnectionId, connectionCanChooseVisibleDatabases, visibleDatabaseSelectionIsStale, initialVisibleDatabaseSelection } from "../../apps/desktop/src/lib/connection/connectionVisibleDatabases.ts";
|
||||
import { connectionUsesVisibleSchemaFilter, filterDatabaseNamesForConnection, filterDatabaseNamesForVisiblePicker } from "../../apps/desktop/src/lib/database/visibleDatabases.ts";
|
||||
import { connectionUsesVisibleSchemaFilter, filterDatabaseNamesForConnection, filterDatabaseNamesForVisiblePicker, filterSchemaNamesForConnection, normalizeVisibleSchemaSelection } from "../../apps/desktop/src/lib/database/visibleDatabases.ts";
|
||||
import type { ConnectionConfig } from "../../apps/desktop/src/types/database.ts";
|
||||
|
||||
function config(overrides: Partial<ConnectionConfig> = {}): ConnectionConfig {
|
||||
|
|
@ -95,6 +95,14 @@ test("OceanBase Oracle uses schema filtering for visible object selection", () =
|
|||
assert.equal(connectionUsesVisibleSchemaFilter(config({ db_type: "mysql", driver_profile: "oceanbase" })), false);
|
||||
});
|
||||
|
||||
test("Vastbase schema filters preserve ordinary schemas and explicit empty selections", () => {
|
||||
const schemas = ["public", "app"];
|
||||
assert.deepEqual(filterSchemaNamesForConnection(schemas, config({ db_type: "vastbase", database: "vastbase" }), "vastbase"), schemas);
|
||||
assert.deepEqual(filterSchemaNamesForConnection(schemas, config({ db_type: "vastbase", database: "vastbase", visible_schemas: { vastbase: [] } }), "vastbase"), []);
|
||||
assert.deepEqual(normalizeVisibleSchemaSelection([], schemas), []);
|
||||
assert.deepEqual(normalizeVisibleSchemaSelection(["app", "missing", "app", "public"], schemas), ["app", "public"]);
|
||||
});
|
||||
|
||||
test("Dameng default SYSDBA user remains selectable", () => {
|
||||
assert.deepEqual(filterDatabaseNamesForConnection(["SYS", "SYSDBA", "SYSAUDITOR"], config({ db_type: "dameng" })), ["SYSDBA"]);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import assert from "node:assert/strict";
|
||||
import { test } from "vitest";
|
||||
import { isSchemaAware, supportsClearableQuerySchema, supportsDatabaseCreation, usesTreeSchemaMode } from "../../apps/desktop/src/lib/database/databaseCapabilities.ts";
|
||||
import { canConfigureVisibleSchemasForTreeNode, isSchemaAware, supportsClearableQuerySchema, supportsDatabaseCreation, usesTreeSchemaMode } from "../../apps/desktop/src/lib/database/databaseCapabilities.ts";
|
||||
|
||||
test("TDengine uses database/catalog tree nodes without a schema layer", () => {
|
||||
assert.equal(isSchemaAware("tdengine"), false);
|
||||
|
|
@ -17,6 +17,22 @@ test("GoldenDB and Vastbase expose database creation", () => {
|
|||
assert.equal(supportsDatabaseCreation("vastbase"), true);
|
||||
});
|
||||
|
||||
test("Vastbase keeps PostgreSQL-like schema filtering on database nodes", () => {
|
||||
assert.equal(isSchemaAware("vastbase"), true);
|
||||
assert.equal(usesTreeSchemaMode("vastbase"), true);
|
||||
assert.equal(canConfigureVisibleSchemasForTreeNode("vastbase", "database", "vastbase"), true);
|
||||
assert.equal(canConfigureVisibleSchemasForTreeNode("vastbase", "connection"), false);
|
||||
});
|
||||
|
||||
test("visible schema menu capability preserves adjacent database families", () => {
|
||||
assert.equal(canConfigureVisibleSchemasForTreeNode("oracle", "connection"), true);
|
||||
assert.equal(canConfigureVisibleSchemasForTreeNode("dameng", "connection"), true);
|
||||
assert.equal(canConfigureVisibleSchemasForTreeNode("oceanbase-oracle", "connection"), false);
|
||||
assert.equal(canConfigureVisibleSchemasForTreeNode("postgres", "database", "app"), true);
|
||||
assert.equal(canConfigureVisibleSchemasForTreeNode("sqlserver", "database", "app"), true);
|
||||
assert.equal(canConfigureVisibleSchemasForTreeNode("mysql", "database", "app"), false);
|
||||
});
|
||||
|
||||
test("only Oracle-compatible single-database schemas can be cleared from query tabs", () => {
|
||||
assert.equal(supportsClearableQuerySchema("oracle"), true);
|
||||
assert.equal(supportsClearableQuerySchema("dameng"), true);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ const connectionTree = readFileSync("apps/desktop/src/components/sidebar/Connect
|
|||
const treeItem = readFileSync("apps/desktop/src/components/sidebar/TreeItem.vue", "utf8");
|
||||
const dialogHost = readFileSync("apps/desktop/src/components/sidebar/SidebarTreeItemDialogs.vue", "utf8");
|
||||
const dialogState = readFileSync("apps/desktop/src/components/sidebar/sidebarTreeDialogState.ts", "utf8");
|
||||
const visibleDatabasesDialog = readFileSync("apps/desktop/src/components/sidebar/VisibleDatabasesDialog.vue", "utf8");
|
||||
const visibleSchemasDialog = readFileSync("apps/desktop/src/components/sidebar/VisibleSchemasDialog.vue", "utf8");
|
||||
|
||||
function occurrences(source: string, value: string): number {
|
||||
return source.split(value).length - 1;
|
||||
|
|
@ -43,6 +45,11 @@ test("saved object dialogs refresh the immutable active target", () => {
|
|||
assert.match(connectionTree, /findSidebarActionTarget\(store\.treeNodes, target\)/);
|
||||
});
|
||||
|
||||
test("lazy visible object dialogs load when first mounted open", () => {
|
||||
assert.match(visibleDatabasesDialog, /watch\([\s\S]*?loadDatabases\(\)[\s\S]*?\{ immediate: true \}/);
|
||||
assert.match(visibleSchemasDialog, /watch\([\s\S]*?loadSchemas\(\)[\s\S]*?\{ immediate: true \}/);
|
||||
});
|
||||
|
||||
test("shared dialog state is owner-gated and confirm handlers use snapshots", () => {
|
||||
assert.match(dialogState, /export const sidebarTreeDialogOwner = shallowRef<symbol \| null>\(null\)/);
|
||||
assert.match(dialogState, /export const sidebarDangerTarget = shallowRef<TreeNode \| null>\(null\)/);
|
||||
|
|
|
|||
Loading…
Reference in New Issue