diff --git a/src/components/sidebar/TreeItem.vue b/src/components/sidebar/TreeItem.vue index 94c86f706f..50062a51e2 100644 --- a/src/components/sidebar/TreeItem.vue +++ b/src/components/sidebar/TreeItem.vue @@ -80,7 +80,7 @@ import { isSchemaAware, usesFetchFirst, } from "@/lib/databaseCapabilities"; -import { treeNodeRowAction } from "@/lib/treeNodeClick"; +import { treeNodeRowAction, treeNodeRowDoubleClickAction } from "@/lib/treeNodeClick"; import { formatCsv, formatJson, formatSqlInsert } from "@/lib/exportFormats"; import { hexToRgba } from "@/lib/color"; import DangerConfirmDialog from "@/components/editor/DangerConfirmDialog.vue"; @@ -279,14 +279,8 @@ async function toggle() { } } -function onClick() { +function runRowClickAction() { const node = props.node; - if (canOpenObjectBrowser.value) { - const shouldOpenObjectBrowser = !canExpand.value || !node.isExpanded; - if (canExpand.value) void toggle(); - if (shouldOpenObjectBrowser) void openObjectBrowser(); - return; - } if (node.type === "object-browser") { void openObjectBrowser(); return; @@ -301,6 +295,18 @@ function onClick() { } } +function onClick(event: MouseEvent) { + if (event.detail > 1) return; + runRowClickAction(); +} + +function onDoubleClick() { + const action = treeNodeRowDoubleClickAction(props.node.type, canOpenObjectBrowser.value); + if (action === "open-object-browser") { + void openObjectBrowser(); + } +} + async function openObjectBrowser() { const node = props.node; if (!node.connectionId) return; @@ -1380,6 +1386,7 @@ const isDragging = computed(() => dragState.active && dragState.draggedId === pr }" :style="rowStyle" @click="onClick" + @dblclick="onDoubleClick" @mousedown="isDraggable ? startDrag($event, node.id, node.type) : undefined" @mousemove="isDropTarget ? updateTarget($event, node.id, node.type) : undefined" @mouseleave="clearTarget(node.id)" diff --git a/src/lib/treeNodeClick.ts b/src/lib/treeNodeClick.ts index 55ca95c490..55566e76e9 100644 --- a/src/lib/treeNodeClick.ts +++ b/src/lib/treeNodeClick.ts @@ -1,9 +1,11 @@ import type { TreeNodeType } from "@/types/database"; export type TreeNodeRowAction = "open-data" | "toggle" | "none"; +export type TreeNodeRowDoubleClickAction = "open-object-browser" | "none"; const dataNodeTypes = new Set(["table", "view"]); const toggleLeafNodeTypes = new Set(["redis-db", "mongo-collection"]); +const objectBrowserNodeTypes = new Set(["database", "schema", "object-browser"]); export function treeNodeRowAction(type: TreeNodeType, canExpand: boolean): TreeNodeRowAction { if (dataNodeTypes.has(type)) return "open-data"; @@ -11,3 +13,11 @@ export function treeNodeRowAction(type: TreeNodeType, canExpand: boolean): TreeN if (canExpand) return "toggle"; return "none"; } + +export function treeNodeRowDoubleClickAction( + type: TreeNodeType, + canOpenObjectBrowser: boolean, +): TreeNodeRowDoubleClickAction { + if (canOpenObjectBrowser && objectBrowserNodeTypes.has(type)) return "open-object-browser"; + return "none"; +} diff --git a/tests/treeNodeClick.test.ts b/tests/treeNodeClick.test.ts index 81e2df02e8..8b7d43c7b9 100644 --- a/tests/treeNodeClick.test.ts +++ b/tests/treeNodeClick.test.ts @@ -1,6 +1,6 @@ import test from "node:test"; import assert from "node:assert/strict"; -import { treeNodeRowAction } from "../src/lib/treeNodeClick.ts"; +import { treeNodeRowAction, treeNodeRowDoubleClickAction } from "../src/lib/treeNodeClick.ts"; test("table and view rows open data without toggling structure groups", () => { assert.equal(treeNodeRowAction("table", true), "open-data"); @@ -23,3 +23,16 @@ test("plain metadata leaf rows do nothing on row clicks", () => { assert.equal(treeNodeRowAction("column", false), "none"); assert.equal(treeNodeRowAction("index", false), "none"); }); + +test("database and schema rows open object browser only on double click", () => { + assert.equal(treeNodeRowAction("database", true), "toggle"); + assert.equal(treeNodeRowAction("schema", true), "toggle"); + assert.equal(treeNodeRowDoubleClickAction("database", true), "open-object-browser"); + assert.equal(treeNodeRowDoubleClickAction("schema", true), "open-object-browser"); +}); + +test("double click does not open object browser for non-browsable rows", () => { + assert.equal(treeNodeRowDoubleClickAction("database", false), "none"); + assert.equal(treeNodeRowDoubleClickAction("table", true), "none"); + assert.equal(treeNodeRowDoubleClickAction("column", true), "none"); +});