mirror of
https://github.com/t8y2/dbx.git
synced 2026-10-20 00:17:44 +00:00
feat(sidebar): open structure editor on field double click
This commit is contained in:
@@ -1618,8 +1618,8 @@ function onDoubleClick(event: MouseEvent) {
|
||||
return;
|
||||
}
|
||||
const action = treeNodeRowDoubleClickAction(activeNode.value.type, canOpenObjectBrowser.value, settingsStore.editorSettings.sidebarActivation, canExpand.value, currentDatabaseType(), canOpenConnectionDatabaseBrowser.value, settingsStore.editorSettings.sidebarBrowseObjectsOnDatabaseActivation);
|
||||
// In single-click mode the trailing dblclick normally has no action and must
|
||||
// leave the first click's request ownership intact.
|
||||
// Most trailing dblclick events are intentionally inert in single-click
|
||||
// mode, but field and index rows have an explicit editor action.
|
||||
if (action === "none") return;
|
||||
const requestId = beginNavigationRequest();
|
||||
if (action === "open-database-browser") {
|
||||
@@ -1635,6 +1635,8 @@ function onDoubleClick(event: MouseEvent) {
|
||||
activateDataTableFromDoubleClick();
|
||||
} else if (action === "locate-column") {
|
||||
locateColumnInDataGrid(activeNode.value);
|
||||
} else if (action === "open-structure-editor") {
|
||||
if (canOpenStructureEditor.value) openStructureEditor();
|
||||
} else if (action === "open-source") {
|
||||
openObjectSourceDialog(false);
|
||||
} else if (action === "open-extension-details") {
|
||||
|
||||
+7
-4
@@ -38,6 +38,7 @@ const settings = {
|
||||
};
|
||||
|
||||
const openDataMock = vi.fn();
|
||||
const openStructureEditorMock = vi.fn();
|
||||
|
||||
vi.mock("@/stores/connectionStore", () => ({
|
||||
CONNECTION_ATTEMPT_CANCELLED_MESSAGE: "connection attempt cancelled",
|
||||
@@ -55,7 +56,7 @@ vi.mock("@/composables/useSidebarConnectionMutationRuntime", () => ({ useSidebar
|
||||
vi.mock("@/composables/useSidebarDatabaseSpecificMutationRuntime", () => ({ useSidebarDatabaseSpecificMutationRuntime: () => ({}) }));
|
||||
vi.mock("@/composables/useSidebarTableMutationRuntime", () => ({ useSidebarTableMutationRuntime: () => ({}) }));
|
||||
vi.mock("@/composables/useSidebarTreeExportRuntime", () => ({ useSidebarTreeExportRuntime: () => ({}) }));
|
||||
vi.mock("@/composables/useSidebarTreeToolRuntime", () => ({ useSidebarTreeToolRuntime: () => ({}) }));
|
||||
vi.mock("@/composables/useSidebarTreeToolRuntime", () => ({ useSidebarTreeToolRuntime: () => ({ openStructureEditor: openStructureEditorMock }) }));
|
||||
|
||||
const mountedApps: App[] = [];
|
||||
|
||||
@@ -64,6 +65,7 @@ afterEach(() => {
|
||||
document.body.innerHTML = "";
|
||||
connectionStore.treeNodes = [];
|
||||
openDataMock.mockReset();
|
||||
openStructureEditorMock.mockReset();
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
@@ -119,7 +121,7 @@ describe("SidebarTreeRuntimeHost column locate", () => {
|
||||
expect(openDataMock).toHaveBeenCalledWith(expect.objectContaining({ label: "users" }), expect.anything(), "default", { revealColumn: "email" });
|
||||
});
|
||||
|
||||
it("locates column in data grid on double click in double-activation mode", async () => {
|
||||
it("opens the structure editor for a double-clicked column", async () => {
|
||||
settings.sidebarActivation = "double";
|
||||
|
||||
const tableNode: TreeNode = {
|
||||
@@ -166,7 +168,8 @@ describe("SidebarTreeRuntimeHost column locate", () => {
|
||||
host.value?.handleRowDoubleClick(columnNode, new MouseEvent("dblclick"));
|
||||
await nextTick();
|
||||
|
||||
expect(onOpenData).toHaveBeenCalledWith(expect.objectContaining({ label: "users", connectionId: "mysql", database: "app" }), false, "default", expect.any(Function));
|
||||
expect(openDataMock).toHaveBeenCalledWith(expect.objectContaining({ label: "users" }), expect.anything(), "default", { revealColumn: "age" });
|
||||
expect(onOpenData).not.toHaveBeenCalled();
|
||||
expect(openDataMock).not.toHaveBeenCalled();
|
||||
expect(openStructureEditorMock).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -219,10 +219,12 @@ describe("treeNodeClick", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("locates column in data grid on single click in single-activation mode and double click in double-activation mode", () => {
|
||||
it("keeps column single-click navigation and opens structure editor on double click", () => {
|
||||
expect(treeNodeRowAction("column", false, "single")).toBe("locate-column");
|
||||
expect(treeNodeRowAction("column", false, "double")).toBe("none");
|
||||
expect(treeNodeRowDoubleClickAction("column", false, "single")).toBe("none");
|
||||
expect(treeNodeRowDoubleClickAction("column", false, "double")).toBe("locate-column");
|
||||
expect(treeNodeRowDoubleClickAction("column", false, "single")).toBe("open-structure-editor");
|
||||
expect(treeNodeRowDoubleClickAction("column", false, "double")).toBe("open-structure-editor");
|
||||
expect(treeNodeRowDoubleClickAction("index", false, "single")).toBe("open-structure-editor");
|
||||
expect(treeNodeRowDoubleClickAction("index", false, "double")).toBe("open-structure-editor");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,7 +3,20 @@ import { customTypeCapabilities, supportsTypeObjectSource } from "@/lib/database
|
||||
import { matchesShortcut, type ShortcutLikeEvent } from "@/lib/editor/keyboardShortcuts";
|
||||
|
||||
export type TreeNodeRowAction = "open-data" | "open-source" | "open-extension-details" | "open-event-trigger-details" | "open-saved-sql" | "open-object-browser" | "open-object-browser-and-expand" | "locate-column" | "toggle" | "none";
|
||||
export type TreeNodeRowDoubleClickAction = "open-data" | "activate-data" | "open-database-browser" | "open-object-browser" | "open-object-browser-and-expand" | "open-source" | "open-extension-details" | "open-event-trigger-details" | "open-saved-sql" | "locate-column" | "toggle" | "none";
|
||||
export type TreeNodeRowDoubleClickAction =
|
||||
| "open-data"
|
||||
| "activate-data"
|
||||
| "open-database-browser"
|
||||
| "open-object-browser"
|
||||
| "open-object-browser-and-expand"
|
||||
| "open-source"
|
||||
| "open-extension-details"
|
||||
| "open-event-trigger-details"
|
||||
| "open-saved-sql"
|
||||
| "locate-column"
|
||||
| "open-structure-editor"
|
||||
| "toggle"
|
||||
| "none";
|
||||
export type SidebarSelectionCopyAction = "copy-name" | "none";
|
||||
export type SidebarActivation = "single" | "double";
|
||||
|
||||
@@ -160,11 +173,16 @@ export function shouldRunTreeNodeRowAction(action: TreeNodeRowAction, clickDetai
|
||||
|
||||
export function treeNodeRowDoubleClickAction(type: TreeNodeType, canOpenObjectBrowser: boolean, activation: SidebarActivation = "single", canExpand = false, dbType?: DatabaseType, canOpenDatabaseBrowser = false, browseObjectsOnDatabaseActivation = false): TreeNodeRowDoubleClickAction {
|
||||
// Single-click activation already handles the first click in a dblclick
|
||||
// sequence. Only double-click activation needs a second-stage table action.
|
||||
// sequence. Most rows have no trailing action, while field/index rows have
|
||||
// an explicit structure-editor action in either activation mode.
|
||||
if (type === "table") return activation === "double" ? "activate-data" : "none";
|
||||
// 双击激活模式下,双击连接节点应当展开树(与单击模式下单击展开一致),
|
||||
// “打开数据库浏览”只保留给单击激活模式下的双击手势。
|
||||
if (type === "connection" && canOpenDatabaseBrowser && activation !== "double") return "open-database-browser";
|
||||
// Field and index rows have an explicit double-click action regardless of
|
||||
// the sidebar activation preference. Single-click field navigation remains
|
||||
// responsible for locating a column in the data grid.
|
||||
if (type === "column" || type === "index") return "open-structure-editor";
|
||||
if (activation === "double") {
|
||||
if (canOpenObjectBrowser && shouldBrowseObjectsOnDatabaseActivation(type, browseObjectsOnDatabaseActivation)) {
|
||||
return canExpand ? "open-object-browser-and-expand" : "open-object-browser";
|
||||
@@ -173,7 +191,6 @@ export function treeNodeRowDoubleClickAction(type: TreeNodeType, canOpenObjectBr
|
||||
if (type === "extension") return "open-extension-details";
|
||||
if (type === "event-trigger") return "open-event-trigger-details";
|
||||
if (dataNodeTypes.has(type)) return "open-data";
|
||||
if (type === "column") return "locate-column";
|
||||
if (type === "type" && customTypeCapabilities(dbType).details) return canExpand ? "toggle" : "none";
|
||||
if (sourceNodeTypes.has(type) && canOpenTreeNodeSource(type, dbType)) return "open-source";
|
||||
if (savedSqlNodeTypes.has(type)) return "open-saved-sql";
|
||||
|
||||
+6
-3
@@ -102,10 +102,13 @@ test("plain metadata leaf rows do nothing on row clicks", () => {
|
||||
assert.equal(treeNodeRowAction("index", false), "none");
|
||||
});
|
||||
|
||||
test("column rows locate column in data grid", () => {
|
||||
test("column rows locate column on single click and open structure editor on double click", () => {
|
||||
assert.equal(treeNodeRowAction("column", false, "single"), "locate-column");
|
||||
assert.equal(treeNodeRowAction("column", false, "double"), "none");
|
||||
assert.equal(treeNodeRowDoubleClickAction("column", false, "double"), "locate-column");
|
||||
assert.equal(treeNodeRowDoubleClickAction("column", false, "single"), "open-structure-editor");
|
||||
assert.equal(treeNodeRowDoubleClickAction("column", false, "double"), "open-structure-editor");
|
||||
assert.equal(treeNodeRowDoubleClickAction("index", false, "single"), "open-structure-editor");
|
||||
assert.equal(treeNodeRowDoubleClickAction("index", false, "double"), "open-structure-editor");
|
||||
});
|
||||
|
||||
test("maps source-capable sidebar nodes to object source kinds", () => {
|
||||
@@ -152,7 +155,7 @@ test("double click does not open object browser for non-browsable rows", () => {
|
||||
assert.equal(treeNodeRowDoubleClickAction("database", false), "none");
|
||||
assert.equal(treeNodeRowDoubleClickAction("view", true), "none");
|
||||
assert.equal(treeNodeRowDoubleClickAction("materialized_view", true), "none");
|
||||
assert.equal(treeNodeRowDoubleClickAction("column", true), "none");
|
||||
assert.equal(treeNodeRowDoubleClickAction("column", true), "open-structure-editor");
|
||||
});
|
||||
|
||||
test("double click navigation mode copies the selected sidebar row name", () => {
|
||||
|
||||
Reference in New Issue
Block a user