mirror of
https://github.com/t8y2/dbx.git
synced 2026-10-30 00:19:35 +00:00
fix(editor): save object source tabs contextually
This commit is contained in:
+33
@@ -33,12 +33,14 @@ import "@/i18n";
|
||||
import { translateBackendError } from "@/i18n/backend-errors";
|
||||
import * as api from "@/lib/api";
|
||||
import { resolveDefaultDatabase } from "@/lib/defaultDatabase";
|
||||
import { buildExecutableObjectSourceSql, objectSourceSaveExecutionMode } from "@/lib/objectSourceEditor";
|
||||
import { resolveExecutableSql } from "@/lib/sqlExecutionTarget";
|
||||
import { isTauriRuntime } from "@/lib/tauriRuntime";
|
||||
import {
|
||||
isCloseTabShortcut,
|
||||
isExecuteSqlShortcut,
|
||||
isFocusSearchShortcut,
|
||||
isObjectSourceSaveShortcutTarget,
|
||||
isSaveShortcut,
|
||||
} from "@/lib/keyboardShortcuts";
|
||||
import { isPreviewTab } from "@/lib/tabPresentation";
|
||||
@@ -203,6 +205,10 @@ function defaultSavedSqlName(title: string) {
|
||||
async function openSaveSqlDialog() {
|
||||
const tab = activeTab.value;
|
||||
if (!tab || !tab.sql.trim()) return;
|
||||
if (tab.objectSource) {
|
||||
await saveActiveObjectSource(tab);
|
||||
return;
|
||||
}
|
||||
const existing = tab.savedSqlId ? savedSqlStore.getFile(tab.savedSqlId) : undefined;
|
||||
if (existing) {
|
||||
const updated = await savedSqlStore.saveFile({
|
||||
@@ -225,6 +231,30 @@ async function openSaveSqlDialog() {
|
||||
showSaveSqlDialog.value = true;
|
||||
}
|
||||
|
||||
async function saveActiveObjectSource(tab: NonNullable<typeof activeTab.value>) {
|
||||
const connection = connectionStore.getConfig(tab.connectionId);
|
||||
const source = tab.objectSource;
|
||||
if (!connection || !source) return;
|
||||
|
||||
try {
|
||||
const sql = buildExecutableObjectSourceSql({
|
||||
databaseType: connection.db_type,
|
||||
objectType: source.objectType,
|
||||
schema: source.schema || tab.schema || tab.database,
|
||||
name: source.name,
|
||||
source: tab.sql,
|
||||
});
|
||||
if (objectSourceSaveExecutionMode(connection.db_type) === "single") {
|
||||
await api.executeQuery(tab.connectionId, tab.database, sql, source.schema || tab.schema);
|
||||
} else {
|
||||
await api.executeScript(tab.connectionId, tab.database, sql, source.schema || tab.schema);
|
||||
}
|
||||
toast(t("objects.sourceSaved"), 2000);
|
||||
} catch (e: any) {
|
||||
toast(t("objects.sourceSaveFailed", { message: e?.message || String(e) }), 5000);
|
||||
}
|
||||
}
|
||||
|
||||
async function confirmSaveSqlToLibrary() {
|
||||
const tab = activeTab.value;
|
||||
const name = saveSqlName.value.trim();
|
||||
@@ -437,6 +467,9 @@ function handleKeydown(e: KeyboardEvent) {
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (isSaveShortcut(e) && e.target instanceof Element && isObjectSourceSaveShortcutTarget(e.target)) {
|
||||
return;
|
||||
}
|
||||
if (activeTab.value?.mode === "query" && !showSaveSqlDialog.value && isSaveShortcut(e)) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
@@ -63,6 +63,7 @@ const activeConnectionValue = computed(() => props.activeConnection?.id || "");
|
||||
const activeSchemaValue = computed(() => props.activeTab.schema || "");
|
||||
const isSingleDb = computed(() => isSingleDatabase(props.activeConnection?.db_type));
|
||||
const schemaDatabaseKey = computed(() => props.activeTab.database || (isSingleDb.value ? "_" : ""));
|
||||
const saveTooltip = computed(() => (props.activeTab.objectSource ? t("objects.saveSource") : t("toolbar.saveSql")));
|
||||
|
||||
const showSchemaSelector = computed(() => {
|
||||
const connection = props.activeConnection;
|
||||
@@ -178,7 +179,7 @@ function databaseDisplayName(database: string): string {
|
||||
<Save class="h-3.5 w-3.5" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{{ t("toolbar.saveSql") }}</TooltipContent>
|
||||
<TooltipContent>{{ saveTooltip }}</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger as-child>
|
||||
|
||||
@@ -590,6 +590,11 @@ function viewObjectSource() {
|
||||
.then((result) => {
|
||||
const tabId = queryStore.createTab(node.connectionId!, node.database!, node.label);
|
||||
queryStore.updateSql(tabId, result.source);
|
||||
queryStore.setObjectSource(tabId, {
|
||||
schema,
|
||||
name: node.label,
|
||||
objectType: objectType as "PROCEDURE" | "FUNCTION",
|
||||
});
|
||||
})
|
||||
.catch((e: any) => {
|
||||
toast(e?.message || String(e), 5000);
|
||||
|
||||
@@ -634,6 +634,7 @@ export default {
|
||||
saveSource: "Save",
|
||||
cancelEdit: "Cancel",
|
||||
sourceSaved: "Source saved",
|
||||
sourceSaveFailed: "Failed to save source: {message}",
|
||||
schemaColumn: "Schema",
|
||||
comment: "Comment",
|
||||
loadingSchemas: "Loading schemas...",
|
||||
|
||||
@@ -635,6 +635,7 @@ export default {
|
||||
saveSource: "Guardar",
|
||||
cancelEdit: "Cancelar",
|
||||
sourceSaved: "Código fuente guardado",
|
||||
sourceSaveFailed: "Error al guardar el código fuente: {message}",
|
||||
schemaColumn: "Esquema",
|
||||
comment: "Comentario",
|
||||
loadingSchemas: "Cargando esquemas...",
|
||||
|
||||
@@ -619,6 +619,7 @@ export default {
|
||||
saveSource: "保存",
|
||||
cancelEdit: "取消",
|
||||
sourceSaved: "源码已保存",
|
||||
sourceSaveFailed: "保存源码失败:{message}",
|
||||
schemaColumn: "Schema",
|
||||
comment: "注释",
|
||||
loadingSchemas: "加载 Schema...",
|
||||
|
||||
@@ -33,6 +33,12 @@ export function isSaveShortcut(event: ShortcutLikeEvent): boolean {
|
||||
return event.key.toLowerCase() === "s";
|
||||
}
|
||||
|
||||
export function isObjectSourceSaveShortcutTarget(
|
||||
target: { closest(selector: string): unknown } | null | undefined,
|
||||
): boolean {
|
||||
return !!target?.closest("[data-object-source-editor], [data-object-source-preview]");
|
||||
}
|
||||
|
||||
export function isCancelSearchShortcut(event: ShortcutLikeEvent): boolean {
|
||||
if (event.isComposing) return false;
|
||||
return event.key === "Escape";
|
||||
|
||||
@@ -39,6 +39,6 @@ export function buildExecutableObjectSourceSql(input: BuildEditableObjectSourceS
|
||||
return ensureSemicolon(source);
|
||||
}
|
||||
|
||||
export function objectSourceSaveExecutionMode(databaseType: DatabaseType): ObjectSourceSaveExecutionMode {
|
||||
return databaseType === "sqlserver" ? "single" : "script";
|
||||
export function objectSourceSaveExecutionMode(_databaseType: DatabaseType): ObjectSourceSaveExecutionMode {
|
||||
return "single";
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ export interface SavedOpenTab {
|
||||
pinned?: boolean;
|
||||
mode?: QueryTab["mode"];
|
||||
objectBrowser?: QueryTab["objectBrowser"];
|
||||
objectSource?: QueryTab["objectSource"];
|
||||
tableMeta?: QueryTab["tableMeta"];
|
||||
}
|
||||
|
||||
@@ -31,6 +32,7 @@ export function serializeOpenTabs(tabs: QueryTab[]): SavedOpenTab[] {
|
||||
pinned: tab.pinned,
|
||||
mode: tab.mode,
|
||||
objectBrowser: tab.objectBrowser,
|
||||
objectSource: tab.objectSource,
|
||||
tableMeta: tab.tableMeta,
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -52,6 +52,7 @@ export const useQueryStore = defineStore("query", () => {
|
||||
pinned: t.pinned,
|
||||
mode: t.mode,
|
||||
objectBrowser: t.objectBrowser,
|
||||
objectSource: t.objectSource,
|
||||
tableMeta: t.tableMeta,
|
||||
})),
|
||||
);
|
||||
@@ -253,6 +254,11 @@ export const useQueryStore = defineStore("query", () => {
|
||||
if (tab) tab.tableMeta = meta;
|
||||
}
|
||||
|
||||
function setObjectSource(id: string, objectSource: NonNullable<QueryTab["objectSource"]>) {
|
||||
const tab = tabs.value.find((t) => t.id === id);
|
||||
if (tab) tab.objectSource = objectSource;
|
||||
}
|
||||
|
||||
function setExecuting(id: string, isExecuting: boolean) {
|
||||
const tab = tabs.value.find((t) => t.id === id);
|
||||
if (!tab) return;
|
||||
@@ -600,6 +606,7 @@ export const useQueryStore = defineStore("query", () => {
|
||||
updateSchema,
|
||||
updateConnection,
|
||||
setTableMeta,
|
||||
setObjectSource,
|
||||
setExecuting,
|
||||
setErrorResult,
|
||||
setActiveResultIndex,
|
||||
|
||||
@@ -268,6 +268,11 @@ export interface QueryTab {
|
||||
schema?: string;
|
||||
objectType?: "tables";
|
||||
};
|
||||
objectSource?: {
|
||||
schema?: string;
|
||||
name: string;
|
||||
objectType: ObjectSourceKind;
|
||||
};
|
||||
tableMeta?: {
|
||||
schema?: string;
|
||||
tableName: string;
|
||||
|
||||
Reference in New Issue
Block a user