diff --git a/src/components/sql-file/SqlFileExecutionDialog.vue b/src/components/sql-file/SqlFileExecutionDialog.vue index 354dd2b46..76f671b50 100644 --- a/src/components/sql-file/SqlFileExecutionDialog.vue +++ b/src/components/sql-file/SqlFileExecutionDialog.vue @@ -53,6 +53,7 @@ const executionId = ref(""); const progress = ref(null); const terminalStatus = ref("idle"); const terminalError = ref(""); +const refreshedTarget = ref(false); const sqlConnections = computed(() => store.connections.filter((c) => !["redis", "mongodb", "elasticsearch"].includes(c.db_type)), @@ -154,6 +155,7 @@ function resetExecution() { progress.value = null; terminalStatus.value = "idle"; terminalError.value = ""; + refreshedTarget.value = false; } function resetState() { @@ -265,6 +267,16 @@ async function listenProgress(id: string, handler: (next: SqlFileProgress) => vo return listenSqlFileProgressById(id, handler); } +async function refreshTargetAfterImport() { + if (refreshedTarget.value) return; + refreshedTarget.value = true; + try { + await store.refreshDatabaseTreeNode(connectionId.value, database.value.trim()); + } catch (e: any) { + toast(e?.message || String(e), 5000); + } +} + async function startExecution() { if (!canStart.value || !preview.value) return; @@ -295,6 +307,9 @@ async function startExecution() { running.value = false; cancelling.value = false; } + if (next.status === "done") { + void refreshTargetAfterImport(); + } }); if (cancelRequested.value) { @@ -312,6 +327,9 @@ async function startExecution() { }); if (!isTerminalStatus(terminalStatus.value)) { terminalStatus.value = cancelRequested.value ? "cancelled" : "done"; + if (terminalStatus.value === "done") { + await refreshTargetAfterImport(); + } } } catch (e: any) { terminalStatus.value = cancelRequested.value ? "cancelled" : "error"; diff --git a/src/lib/treeRefreshTarget.ts b/src/lib/treeRefreshTarget.ts new file mode 100644 index 000000000..62ebb5676 --- /dev/null +++ b/src/lib/treeRefreshTarget.ts @@ -0,0 +1,14 @@ +import type { TreeNode } from "@/types/database"; + +export function findDatabaseTreeNode(nodes: TreeNode[], connectionId: string, database: string): TreeNode | null { + for (const node of nodes) { + if (node.type === "database" && node.connectionId === connectionId && node.database === database) { + return node; + } + if (node.children) { + const found = findDatabaseTreeNode(node.children, connectionId, database); + if (found) return found; + } + } + return null; +} diff --git a/src/stores/connectionStore.ts b/src/stores/connectionStore.ts index c96cdde09..fa42fa58c 100644 --- a/src/stores/connectionStore.ts +++ b/src/stores/connectionStore.ts @@ -23,6 +23,7 @@ import { isTauriRuntime } from "@/lib/tauriRuntime"; import { isSchemaAware, usesTreeSchemaMode } from "@/lib/databaseCapabilities"; import { buildDatabaseTreeNodes } from "@/lib/databaseTree"; import { buildSqlServerDatabaseTreeNodes, SQLSERVER_DEFAULT_SCHEMA } from "@/lib/sqlServerTree"; +import { findDatabaseTreeNode } from "@/lib/treeRefreshTarget"; import { shouldMarkDisconnected } from "@/lib/connectionHealth"; import { filterVisibleDatabaseNames, normalizeVisibleDatabaseSelection } from "@/lib/visibleDatabases"; import { @@ -1147,6 +1148,15 @@ export const useConnectionStore = defineStore("connection", () => { await restoreExpandedChildren(node, expandedIds, { force: true }); } + async function refreshDatabaseTreeNode(connectionId: string, database: string) { + const node = findDatabaseTreeNode(treeNodes.value, connectionId, database); + if (node) { + await refreshTreeNode(node); + return; + } + await loadDatabases(connectionId, { force: true }); + } + function isSchemaAwareDatabase(connectionId: string): boolean { return isSchemaAware(getConfig(connectionId)?.db_type); } @@ -1576,6 +1586,7 @@ export const useConnectionStore = defineStore("connection", () => { refreshAllTree, refreshSavedSqlTree, refreshTreeNode, + refreshDatabaseTreeNode, connectedIds, connectionErrors, setConnectionError, diff --git a/tests/treeRefreshTarget.test.ts b/tests/treeRefreshTarget.test.ts new file mode 100644 index 000000000..7bae71588 --- /dev/null +++ b/tests/treeRefreshTarget.test.ts @@ -0,0 +1,36 @@ +import assert from "node:assert/strict"; +import test from "node:test"; +import { findDatabaseTreeNode } from "../src/lib/treeRefreshTarget.ts"; +import type { TreeNode } from "../src/types/database.ts"; + +test("finds database refresh targets inside grouped sidebar trees", () => { + const target: TreeNode = { + id: "conn-1:app", + label: "app", + type: "database", + connectionId: "conn-1", + database: "app", + }; + const nodes: TreeNode[] = [ + { + id: "group-1", + label: "Production", + type: "connection-group", + children: [ + { + id: "conn-1", + label: "mysql", + type: "connection", + connectionId: "conn-1", + children: [target], + }, + ], + }, + ]; + + assert.equal(findDatabaseTreeNode(nodes, "conn-1", "app"), target); +}); + +test("returns null when the target database node is not loaded", () => { + assert.equal(findDatabaseTreeNode([], "conn-1", "app"), null); +});