diff --git a/apps/desktop/src/components/sidebar/SidebarTreeRuntimeHost.vue b/apps/desktop/src/components/sidebar/SidebarTreeRuntimeHost.vue index 575208b7df..f7bbb3f634 100644 --- a/apps/desktop/src/components/sidebar/SidebarTreeRuntimeHost.vue +++ b/apps/desktop/src/components/sidebar/SidebarTreeRuntimeHost.vue @@ -63,7 +63,9 @@ import { useDatabaseOptions } from "@/composables/useDatabaseOptions"; import type { ColumnInfo, DatabaseType, TreeNode, TreeNodeType } from "@/types/database"; import * as api from "@/lib/backend/api"; import { resolveDefaultDatabase } from "@/lib/database/defaultDatabase"; +import { connectionUsesVisibleSchemaFilter } from "@/lib/database/visibleDatabases"; import { canTreeNodePin, canTreeNodeShowExpander } from "@/lib/sidebar/sidebarTreeItemLayout"; +import { sidebarConnectionVisibleFilterMenu } from "@/lib/sidebar/sidebarVisibleFilterMenu"; import { objectTypesForGroupNode } from "@/lib/table/tableTree"; import { loadSidebarObjectGroup } from "@/lib/sidebar/sidebarObjectGroupRouting"; import { mysqlObjectTemplateForGroup } from "@/lib/sidebar/mysqlObjectTemplates"; @@ -3715,23 +3717,15 @@ function buildConnectionSidebarMenu(context: SidebarMenuFactoryContext): boolean icon: RefreshCw, shortcut: shortcutRefresh, }); - if (canConfigureVisibleDatabases.value) { + const visibleFilterMenu = sidebarConnectionVisibleFilterMenu({ + canConfigureVisibleDatabases: canConfigureVisibleDatabases.value, + canConfigureVisibleSchemas: canConfigureVisibleSchemas.value, + databaseFilterUsesSchemas: connectionUsesVisibleSchemaFilter(node.connectionId ? connectionStore.getConfig(node.connectionId) : undefined), + }); + for (const entry of visibleFilterMenu) { items.push({ - label: t("contextMenu.configureVisibleObjects"), - action: openVisibleDatabasesDialog, - icon: ListFilter, - }); - } else if (canConfigureVisibleSchemas.value) { - items.push({ - label: t("visibleSchemas.title"), - action: openVisibleSchemasDialog, - icon: ListFilter, - }); - } - if (canConfigureVisibleSchemas.value) { - items.push({ - label: t("visibleSchemas.title"), - action: openVisibleSchemasDialog, + label: t(entry.label === "schemas" ? "visibleSchemas.title" : "contextMenu.configureVisibleObjects"), + action: entry.target === "visible-schemas" ? openVisibleSchemasDialog : openVisibleDatabasesDialog, icon: ListFilter, }); } diff --git a/apps/desktop/src/lib/sidebar/sidebarVisibleFilterMenu.ts b/apps/desktop/src/lib/sidebar/sidebarVisibleFilterMenu.ts new file mode 100644 index 0000000000..49eb26b11a --- /dev/null +++ b/apps/desktop/src/lib/sidebar/sidebarVisibleFilterMenu.ts @@ -0,0 +1,18 @@ +export type SidebarVisibleFilterMenuEntry = { + label: "objects" | "schemas"; + target: "visible-databases" | "visible-schemas"; +}; + +export function sidebarConnectionVisibleFilterMenu(options: { canConfigureVisibleDatabases: boolean; canConfigureVisibleSchemas: boolean; databaseFilterUsesSchemas: boolean }): SidebarVisibleFilterMenuEntry[] { + if (!options.canConfigureVisibleDatabases) { + return options.canConfigureVisibleSchemas ? [{ label: "schemas", target: "visible-schemas" }] : []; + } + + if (options.databaseFilterUsesSchemas) { + return [{ label: "schemas", target: "visible-databases" }]; + } + + const entries: SidebarVisibleFilterMenuEntry[] = [{ label: "objects", target: "visible-databases" }]; + if (options.canConfigureVisibleSchemas) entries.push({ label: "schemas", target: "visible-schemas" }); + return entries; +} diff --git a/packages/app-tests/sidebarVisibleFilterMenu.test.ts b/packages/app-tests/sidebarVisibleFilterMenu.test.ts new file mode 100644 index 0000000000..8427a74e44 --- /dev/null +++ b/packages/app-tests/sidebarVisibleFilterMenu.test.ts @@ -0,0 +1,50 @@ +import assert from "node:assert/strict"; +import { test } from "vitest"; +import { sidebarConnectionVisibleFilterMenu } from "../../apps/desktop/src/lib/sidebar/sidebarVisibleFilterMenu.ts"; + +test("Dameng and Oracle schema-mode filters keep the connection-level dialog with one schema label", () => { + assert.deepEqual( + sidebarConnectionVisibleFilterMenu({ + canConfigureVisibleDatabases: true, + canConfigureVisibleSchemas: true, + databaseFilterUsesSchemas: true, + }), + [{ label: "schemas", target: "visible-databases" }], + ); +}); + +test("connections with independent database and schema filters retain both entries", () => { + assert.deepEqual( + sidebarConnectionVisibleFilterMenu({ + canConfigureVisibleDatabases: true, + canConfigureVisibleSchemas: true, + databaseFilterUsesSchemas: false, + }), + [ + { label: "objects", target: "visible-databases" }, + { label: "schemas", target: "visible-schemas" }, + ], + ); +}); + +test("schema-mode database dialog does not depend on a dedicated schema action", () => { + assert.deepEqual( + sidebarConnectionVisibleFilterMenu({ + canConfigureVisibleDatabases: true, + canConfigureVisibleSchemas: false, + databaseFilterUsesSchemas: true, + }), + [{ label: "schemas", target: "visible-databases" }], + ); +}); + +test("schema-only connections produce one schema menu entry", () => { + assert.deepEqual( + sidebarConnectionVisibleFilterMenu({ + canConfigureVisibleDatabases: false, + canConfigureVisibleSchemas: true, + databaseFilterUsesSchemas: false, + }), + [{ label: "schemas", target: "visible-schemas" }], + ); +});