дзеркало
https://github.com/l0ng-ai/openidea.git
синхронізовано 2026-11-09 19:25:54 +02:00
Initial open-source release
Claude-Session: https://claude.ai/code/session_01B65qLEKnkeYTGdbwhLpjCu
Цей коміт міститься в:
коміт
9a2025b76e
2034 files changed
+243381
No files matched your search
@@ -0,0 +1,155 @@
|
||||
/** Menus of the Database tool window, laid out like IDEA's (New ▸, Copy/Paste ▸, SQL Scripts ▸ …). */
|
||||
import type { DbDriver } from "@/platform/ipc";
|
||||
import type { MenuItem } from "@/ui";
|
||||
import { driverIcon, fileSourceName } from "./model";
|
||||
import { nodeTarget, objectOf, tableOf, type DbNode } from "./nodes";
|
||||
import { SCRIPT_LABELS, canDrop, canRename, type ScriptKind } from "./objects";
|
||||
import { connectedTargets, openDialog, openSourceDialog, sourceById, useDatabase } from "./store";
|
||||
|
||||
const act = (action: string, node: DbNode | null, extra: Partial<{ label: string; disabled: boolean; icon: string }> = {}): MenuItem => ({
|
||||
kind: "action",
|
||||
action,
|
||||
arg: node ?? undefined,
|
||||
...extra,
|
||||
});
|
||||
|
||||
const sep: MenuItem = { kind: "separator" };
|
||||
|
||||
async function sqliteFromFile() {
|
||||
const { open } = await import("@tauri-apps/plugin-dialog");
|
||||
const file = await open({ multiple: false, directory: false, title: "SQLite Database File" });
|
||||
if (typeof file === "string") openSourceDialog(null, { driver: "sqlite", file, name: fileSourceName(file) });
|
||||
}
|
||||
|
||||
/** New ▸ Data Source ▸ — the drivers the backend speaks. */
|
||||
function dataSourceItems(): MenuItem[] {
|
||||
const preset = (label: string, driver: DbDriver): MenuItem => ({
|
||||
label,
|
||||
icon: driverIcon(driver),
|
||||
run: () => openSourceDialog(null, { driver }),
|
||||
});
|
||||
return [
|
||||
{
|
||||
label: "Data Source",
|
||||
icon: "database",
|
||||
submenu: [preset("MariaDB", "mysql"), preset("MySQL", "mysql"), preset("PostgreSQL", "postgres"), preset("SQLite", "sqlite")],
|
||||
},
|
||||
{ label: "Data Source from File…", icon: "folder", run: () => void sqliteFromFile() },
|
||||
{ label: "Data Source from URL…", icon: "external-link", run: () => openDialog({ kind: "sourceUrl" }) },
|
||||
];
|
||||
}
|
||||
|
||||
/** The toolbar's "+" menu (IDEA: New). */
|
||||
export function newMenu(): MenuItem[] {
|
||||
return [{ kind: "action", action: "db.openConsole", label: "Query Console" }, sep, ...dataSourceItems()];
|
||||
}
|
||||
|
||||
function sqlScripts(n: DbNode, table: boolean): MenuItem {
|
||||
const scripts: MenuItem[] = table
|
||||
? (Object.keys(SCRIPT_LABELS) as ScriptKind[]).map((kind) => ({
|
||||
kind: "action",
|
||||
action: "db.sqlScript",
|
||||
arg: { node: n, kind },
|
||||
label: SCRIPT_LABELS[kind],
|
||||
}))
|
||||
: [act("db.runSqlScript", n)];
|
||||
return { label: "SQL Scripts", submenu: [act("db.ddlToClipboard", n), act("db.ddlToConsole", n), sep, ...scripts] };
|
||||
}
|
||||
|
||||
/** Context menu of a tree node (`null`: the empty area). */
|
||||
export function nodeMenu(n: DbNode | null): MenuItem[] {
|
||||
if (!n) return [{ label: "New", icon: "plus", submenu: newMenu() }];
|
||||
const id = nodeTarget(n) ?? "";
|
||||
const driver = sourceById(id)?.driver ?? "sqlite";
|
||||
const o = objectOf(n);
|
||||
const t = tableOf(n);
|
||||
const newConsole = act("db.openConsole", n, { label: "Query Console", icon: "db-console" });
|
||||
const refresh = act("db.refresh", n);
|
||||
const quickDoc = act("db.quickDoc", n);
|
||||
const rename = act("db.rename", n, { disabled: !(n.kind === "source" || (o && canRename(driver, o))) });
|
||||
const drop = act("db.drop", n, { disabled: !o || !canDrop(driver, o) });
|
||||
const copyRef = act("db.copyReference", n);
|
||||
const navigation = (extra: MenuItem[] = []): MenuItem => ({ label: "Navigation", submenu: [...extra, act("db.jumpToConsole", n)] });
|
||||
|
||||
switch (n.kind) {
|
||||
case "source": {
|
||||
const connected = connectedTargets(n.source.id ?? "").length > 0;
|
||||
return [
|
||||
act("db.properties", n, { label: "Properties" }),
|
||||
sep,
|
||||
{ label: "New", icon: "plus", submenu: [newConsole, sep, ...dataSourceItems()] },
|
||||
{ label: "Copy/Paste", submenu: [copyRef, act("db.duplicateSource", n)] },
|
||||
refresh,
|
||||
act("db.disconnect", n, { disabled: !connected }),
|
||||
sep,
|
||||
rename,
|
||||
sep,
|
||||
quickDoc,
|
||||
navigation(),
|
||||
sep,
|
||||
sqlScripts(n, false),
|
||||
sep,
|
||||
act("db.drop", n, { label: "Remove Data Source…" }),
|
||||
];
|
||||
}
|
||||
case "database":
|
||||
return [
|
||||
{ label: "New", icon: "plus", submenu: [newConsole] },
|
||||
{ label: "Copy/Paste", submenu: [copyRef] },
|
||||
refresh,
|
||||
act("db.disconnect", n, { disabled: !useDatabase.getState().connected.has(id) || n.current }),
|
||||
sep,
|
||||
navigation(),
|
||||
sqlScripts(n, false),
|
||||
];
|
||||
case "schema":
|
||||
case "folder":
|
||||
return [
|
||||
{ label: "New", icon: "plus", submenu: [newConsole, sep, act("db.newTable", n)] },
|
||||
...(n.kind === "schema" ? [{ label: "Copy/Paste", submenu: [copyRef] }] : []),
|
||||
refresh,
|
||||
sep,
|
||||
...(n.kind === "schema" ? [quickDoc] : []),
|
||||
navigation(),
|
||||
sep,
|
||||
sqlScripts(n, false),
|
||||
...(n.kind === "schema" ? [sep, drop] : []),
|
||||
];
|
||||
case "table":
|
||||
case "column": {
|
||||
const view = !!t?.view;
|
||||
const column = n.kind === "column";
|
||||
return [
|
||||
{ label: "New", icon: "plus", submenu: [newConsole, sep, act("db.newColumn", n, { disabled: view }), act("db.newTable", n)] },
|
||||
act("db.modifyTable", n, { label: column ? "Modify Column…" : "Modify Table…", disabled: view }),
|
||||
{ label: "Copy/Paste", submenu: [copyRef] },
|
||||
act("db.editData", n),
|
||||
refresh,
|
||||
sep,
|
||||
rename,
|
||||
sep,
|
||||
quickDoc,
|
||||
navigation([act("db.goToDdl", n)]),
|
||||
sep,
|
||||
sqlScripts(n, true),
|
||||
...(n.kind === "table" && !view ? [{ label: "Object Actions", submenu: [act("db.truncate", n)] }] : []),
|
||||
sep,
|
||||
drop,
|
||||
];
|
||||
}
|
||||
case "index":
|
||||
return [{ label: "Copy/Paste", submenu: [copyRef] }, refresh, sep, rename, sep, navigation([act("db.goToDdl", n)]), sep, drop];
|
||||
case "foreignKey":
|
||||
return [refresh, sep, { label: "Navigation", submenu: [act("db.goToReferencedTable", n), act("db.goToDdl", n)] }];
|
||||
case "group":
|
||||
case "key":
|
||||
return [
|
||||
...(n.kind === "group" && n.group === "columns" ? [{ label: "New", icon: "plus", submenu: [act("db.newColumn", n)] }] : []),
|
||||
refresh,
|
||||
sep,
|
||||
{ label: "Navigation", submenu: [act("db.goToDdl", n)] },
|
||||
];
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
}
|
||||
Reference in new issue
Заблокувати користувача