fix(sidebar): copy selected table names to clipboard
This commit is contained in:
parent
e6224ec0b0
commit
08d73ce371
|
|
@ -2837,23 +2837,6 @@ async function confirmPasteTable() {
|
|||
}
|
||||
}
|
||||
|
||||
function copyTableToClipboard() {
|
||||
const node = activeNode.value;
|
||||
if (node.type !== "table" || !node.connectionId || !node.database) return;
|
||||
connectionStore.treeClipboard = {
|
||||
kind: "table-copy",
|
||||
tables: [
|
||||
{
|
||||
connectionId: node.connectionId,
|
||||
database: node.database,
|
||||
schema: node.schema,
|
||||
tableName: node.label,
|
||||
},
|
||||
],
|
||||
};
|
||||
toast(t("contextMenu.pasteTableClipboardUpdated"), 2000);
|
||||
}
|
||||
|
||||
function openPasteTableDialog() {
|
||||
const clipboard = connectionStore.treeClipboard;
|
||||
if (clipboard?.kind !== "table-copy" || !canPasteTreeClipboardToCurrentNode()) {
|
||||
|
|
@ -3939,7 +3922,8 @@ function buildObjectSidebarMenu(context: SidebarMenuFactoryContext): boolean {
|
|||
if (isTableNotView.value) {
|
||||
items.push({ label: "", separator: true });
|
||||
items.push({ label: t("contextMenu.duplicateStructure"), action: duplicateStructure, icon: CopyPlus });
|
||||
items.push({ label: t("contextMenu.copyTable"), action: copyTableToClipboard, icon: Copy });
|
||||
// Keep menu copy aligned with keyboard copy so frozen multi-selection and single-row fallback stay compatible.
|
||||
items.push({ label: t("contextMenu.copyTable"), action: copySelectedNames, icon: Copy });
|
||||
if (supportsTruncate.value) {
|
||||
destructiveActions.push({
|
||||
label: truncateMenuLabel(t("contextMenu.truncateTable")),
|
||||
|
|
|
|||
|
|
@ -2,6 +2,26 @@ import { strict as assert } from "node:assert";
|
|||
import { readFileSync } from "node:fs";
|
||||
import { test } from "vitest";
|
||||
|
||||
function functionBody(source: string, name: string): string {
|
||||
const signature = `function ${name}(`;
|
||||
const asyncSignature = `async ${signature}`;
|
||||
const signatureIndex = source.indexOf(asyncSignature) >= 0 ? source.indexOf(asyncSignature) : source.indexOf(signature);
|
||||
assert.notEqual(signatureIndex, -1, `Could not find function ${name}`);
|
||||
const bodyStart = source.indexOf("{", signatureIndex);
|
||||
assert.notEqual(bodyStart, -1, `Could not find body for ${name}`);
|
||||
|
||||
let depth = 0;
|
||||
for (let index = bodyStart; index < source.length; index += 1) {
|
||||
const char = source[index];
|
||||
if (char === "{") depth += 1;
|
||||
if (char === "}") {
|
||||
depth -= 1;
|
||||
if (depth === 0) return source.slice(bodyStart + 1, index);
|
||||
}
|
||||
}
|
||||
throw new Error(`Could not parse body for ${name}`);
|
||||
}
|
||||
|
||||
test("tree-level context menu opens with the current row items atomically", () => {
|
||||
const connectionTree = readFileSync("apps/desktop/src/components/sidebar/ConnectionTree.vue", "utf8");
|
||||
const contextMenu = readFileSync("apps/desktop/src/components/ui/CustomContextMenu.vue", "utf8");
|
||||
|
|
@ -39,3 +59,15 @@ test("tree host owns sidebar data-open generations", () => {
|
|||
assert.match(connectionTree, /runSidebarDataOpenImmediately/);
|
||||
assert.match(connectionTree, /createSidebarActionTarget\(node\)/);
|
||||
});
|
||||
|
||||
test("table copy menu uses the shared single and multi-selection clipboard path", () => {
|
||||
const runtimeHost = readFileSync("apps/desktop/src/components/sidebar/SidebarTreeRuntimeHost.vue", "utf8");
|
||||
const copySelectedNamesBody = functionBody(runtimeHost, "copySelectedNames");
|
||||
|
||||
assert.match(runtimeHost, /label: t\("contextMenu\.copyTable"\), action: copySelectedNames, icon: Copy/);
|
||||
assert.doesNotMatch(runtimeHost, /function copyTableToClipboard\(/);
|
||||
assert.match(copySelectedNamesBody, /const selectedNodes = selectedTreeNodesInVisibleOrder\(\)/);
|
||||
assert.match(copySelectedNamesBody, /selectedNodes\.length > 1 && selectedNodes\.some\(\(node\) => node\.id === activeNode\.value\.id\) \? selectedNodes : \[activeNode\.value\]/);
|
||||
assert.match(copySelectedNamesBody, /updateTreeClipboardForNodes\(nodes\)/);
|
||||
assert.match(copySelectedNamesBody, /copyToClipboard\(nodes\.map\(copyNameForTreeNode\)\.join\("\\n"\)\)/);
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue