fix(desktop): copy parent name for tree group nodes

This commit is contained in:
t8y2 2026-06-02 00:00:07 +08:00
parent 130a33808e
commit 088eaccecc
3 changed files with 67 additions and 2 deletions

View File

@ -81,6 +81,7 @@ import {
usesTreeSchemaMode,
} from "@/lib/databaseCapabilities";
import {
copyNameForTreeNode,
objectSourceKindForTreeNode,
sidebarSelectionCopyAction,
treeNodeRowAction,
@ -684,7 +685,7 @@ async function confirmDelete() {
async function copyName() {
try {
await copyToClipboard(props.node.label);
await copyToClipboard(copyNameForTreeNode(props.node));
toast(t("connection.copied"), 2000);
} catch (e: any) {
toast(t("grid.copyFailed", { message: e?.message || String(e) }), 5000);

View File

@ -1,4 +1,4 @@
import type { ObjectSourceKind, TreeNodeType } from "@/types/database";
import type { ObjectSourceKind, TreeNode, TreeNodeType } from "@/types/database";
import { matchesShortcut, type ShortcutLikeEvent } from "@/lib/keyboardShortcuts";
export type TreeNodeRowAction = "open-data" | "toggle" | "none";
@ -17,6 +17,20 @@ const dataNodeTypes = new Set<TreeNodeType>(["table", "view"]);
const toggleLeafNodeTypes = new Set<TreeNodeType>(["redis-db", "mongo-collection"]);
const objectBrowserNodeTypes = new Set<TreeNodeType>(["database", "schema", "object-browser"]);
const sourceNodeTypes = new Set<TreeNodeType>(["procedure", "function", "package", "package-body"]);
const tableChildGroupNodeTypes = new Set<TreeNodeType>([
"group-columns",
"group-indexes",
"group-fkeys",
"group-triggers",
"group-partitions",
]);
const databaseChildGroupNodeTypes = new Set<TreeNodeType>([
"group-tables",
"group-views",
"group-procedures",
"group-functions",
"group-packages",
]);
export function objectSourceKindForTreeNode(type: TreeNodeType): ObjectSourceKind | null {
if (type === "view") return "VIEW";
@ -61,3 +75,9 @@ export function treeNodeRowDoubleClickAction(
export function sidebarSelectionCopyAction(event: ShortcutLikeEvent): SidebarSelectionCopyAction {
return matchesShortcut(event, "Mod+C") ? "copy-name" : "none";
}
export function copyNameForTreeNode(node: TreeNode): string {
if (tableChildGroupNodeTypes.has(node.type) && node.tableName) return node.tableName;
if (databaseChildGroupNodeTypes.has(node.type)) return node.schema || node.database || node.label;
return node.label;
}

View File

@ -1,6 +1,7 @@
import test from "node:test";
import assert from "node:assert/strict";
import {
copyNameForTreeNode,
objectSourceKindForTreeNode,
sidebarSelectionCopyAction,
treeNodeRowAction,
@ -92,3 +93,46 @@ test("single click navigation mode copies the selected sidebar row name", () =>
assert.equal(sidebarSelectionCopyAction({ key: "c", metaKey: true }), "copy-name");
assert.equal(sidebarSelectionCopyAction({ key: "C", ctrlKey: true }), "copy-name");
});
test("copying table child group rows uses the parent table name", () => {
assert.equal(
copyNameForTreeNode({
id: "conn:db:public:orders:__columns",
label: "tree.columns",
type: "group-columns",
tableName: "orders",
}),
"orders",
);
assert.equal(
copyNameForTreeNode({
id: "conn:db:public:orders:__indexes",
label: "tree.indexes",
type: "group-indexes",
tableName: "orders",
}),
"orders",
);
});
test("copying database object group rows uses the parent schema or database name", () => {
assert.equal(
copyNameForTreeNode({
id: "conn:db:public:__tables",
label: "tree.tables",
type: "group-tables",
database: "db",
schema: "public",
}),
"public",
);
assert.equal(
copyNameForTreeNode({
id: "conn:db:__views",
label: "tree.views",
type: "group-views",
database: "db",
}),
"db",
);
});