From e3474f581fc9abf1c356571f87d81bac25da98ba Mon Sep 17 00:00:00 2001 From: t8y2 <1156263951@qq.com> Date: Mon, 18 May 2026 11:29:52 +0800 Subject: [PATCH] fix(sidebar): expose view source action --- apps/desktop/src/components/sidebar/TreeItem.vue | 15 ++++++++++++--- apps/desktop/src/lib/treeNodeClick.ts | 9 ++++++++- packages/app-tests/treeNodeClick.test.ts | 14 +++++++++++++- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/apps/desktop/src/components/sidebar/TreeItem.vue b/apps/desktop/src/components/sidebar/TreeItem.vue index 9355e387fc..514226ac1b 100644 --- a/apps/desktop/src/components/sidebar/TreeItem.vue +++ b/apps/desktop/src/components/sidebar/TreeItem.vue @@ -86,7 +86,12 @@ import { usesTreeSchemaMode, usesFetchFirst, } from "@/lib/databaseCapabilities"; -import { sidebarSelectionCopyAction, treeNodeRowAction, treeNodeRowDoubleClickAction } from "@/lib/treeNodeClick"; +import { + objectSourceKindForTreeNode, + sidebarSelectionCopyAction, + treeNodeRowAction, + treeNodeRowDoubleClickAction, +} from "@/lib/treeNodeClick"; import { formatCsv, formatJson, formatSqlInsert } from "@/lib/exportFormats"; import { fetchTableDataForExport } from "@/lib/tableDataExport"; import { buildCreateDatabaseSql, supportsCreateDatabaseCharset } from "@/lib/createDatabaseSql"; @@ -632,7 +637,8 @@ function buildDropObjectSql(): string { function viewObjectSource() { const node = props.node; if (!node.connectionId || !node.database) return; - const objectType = node.type === "procedure" ? "PROCEDURE" : "FUNCTION"; + const objectType = objectSourceKindForTreeNode(node.type); + if (!objectType) return; const schema = node.schema || node.database; connectionStore .ensureConnected(node.connectionId) @@ -646,7 +652,7 @@ function viewObjectSource() { queryStore.setObjectSource(tabId, { schema, name: node.label, - objectType: objectType as "PROCEDURE" | "FUNCTION", + objectType, }); }) .catch((e: any) => { @@ -1819,6 +1825,9 @@ const isDragging = computed(() => dragState.active && dragState.draggedId === pr {{ t("contextMenu.viewData") }} + + {{ t("contextMenu.viewSource") }} + {{ t("contextMenu.editStructure") }} diff --git a/apps/desktop/src/lib/treeNodeClick.ts b/apps/desktop/src/lib/treeNodeClick.ts index c09d324926..2629d9aec2 100644 --- a/apps/desktop/src/lib/treeNodeClick.ts +++ b/apps/desktop/src/lib/treeNodeClick.ts @@ -1,4 +1,4 @@ -import type { TreeNodeType } from "@/types/database"; +import type { ObjectSourceKind, TreeNodeType } from "@/types/database"; import { matchesShortcut, type ShortcutLikeEvent } from "@/lib/keyboardShortcuts"; export type TreeNodeRowAction = "open-data" | "toggle" | "none"; @@ -18,6 +18,13 @@ const toggleLeafNodeTypes = new Set(["redis-db", "mongo-collection const objectBrowserNodeTypes = new Set(["database", "schema", "object-browser"]); const sourceNodeTypes = new Set(["procedure", "function"]); +export function objectSourceKindForTreeNode(type: TreeNodeType): ObjectSourceKind | null { + if (type === "view") return "VIEW"; + if (type === "procedure") return "PROCEDURE"; + if (type === "function") return "FUNCTION"; + return null; +} + export function treeNodeRowAction( type: TreeNodeType, canExpand: boolean, diff --git a/packages/app-tests/treeNodeClick.test.ts b/packages/app-tests/treeNodeClick.test.ts index 31380f9832..931c2ce994 100644 --- a/packages/app-tests/treeNodeClick.test.ts +++ b/packages/app-tests/treeNodeClick.test.ts @@ -1,6 +1,11 @@ import test from "node:test"; import assert from "node:assert/strict"; -import { sidebarSelectionCopyAction, treeNodeRowAction, treeNodeRowDoubleClickAction } from "../../apps/desktop/src/lib/treeNodeClick.ts"; +import { + objectSourceKindForTreeNode, + sidebarSelectionCopyAction, + treeNodeRowAction, + treeNodeRowDoubleClickAction, +} from "../../apps/desktop/src/lib/treeNodeClick.ts"; test("table and view rows open data without toggling structure groups", () => { assert.equal(treeNodeRowAction("table", true), "open-data"); @@ -44,6 +49,13 @@ test("plain metadata leaf rows do nothing on row clicks", () => { assert.equal(treeNodeRowAction("index", false), "none"); }); +test("maps source-capable sidebar nodes to object source kinds", () => { + assert.equal(objectSourceKindForTreeNode("view"), "VIEW"); + assert.equal(objectSourceKindForTreeNode("procedure"), "PROCEDURE"); + assert.equal(objectSourceKindForTreeNode("function"), "FUNCTION"); + assert.equal(objectSourceKindForTreeNode("table"), null); +}); + test("database and schema rows open object browser only on double click", () => { assert.equal(treeNodeRowAction("database", true), "toggle"); assert.equal(treeNodeRowAction("schema", true), "toggle");