fix(tabs): close connection tabs on disconnect
This commit is contained in:
parent
53239d91fb
commit
2ff4a3fd97
|
|
@ -2151,12 +2151,16 @@ function editConnection() {
|
|||
}
|
||||
}
|
||||
|
||||
function disconnectConnection() {
|
||||
async function disconnectConnection() {
|
||||
if (props.node.connectionId) {
|
||||
connectionStore.disconnect(props.node.connectionId);
|
||||
props.node.isExpanded = false;
|
||||
props.node.children = [];
|
||||
toast(t("connection.disconnected"), 2000);
|
||||
try {
|
||||
await connectionStore.disconnect(props.node.connectionId);
|
||||
props.node.isExpanded = false;
|
||||
props.node.children = [];
|
||||
toast(t("connection.disconnected"), 2000);
|
||||
} catch (e: any) {
|
||||
toast(t("connection.saveFailed", { message: e?.message || String(e) }), 5000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2165,7 +2169,6 @@ async function closeDatabaseConnection() {
|
|||
if (node.type !== "database" || !node.connectionId || node.database == null) return;
|
||||
try {
|
||||
await connectionStore.closeDatabaseConnection(node.connectionId, node.database);
|
||||
queryStore.closeDatabaseTabs(node.connectionId, node.database);
|
||||
toast(t("connection.databaseConnectionClosed", { name: node.label }), 2000);
|
||||
} catch (e: any) {
|
||||
toast(t("connection.saveFailed", { message: e?.message || String(e) }), 5000);
|
||||
|
|
|
|||
|
|
@ -675,6 +675,8 @@ export const useConnectionStore = defineStore("connection", () => {
|
|||
async function disconnect(connectionId: string) {
|
||||
const shouldRemoveOneTimeConnection = getConfig(connectionId)?.one_time === true;
|
||||
await api.disconnectDb(connectionId);
|
||||
const { useQueryStore } = await import("@/stores/queryStore");
|
||||
useQueryStore().closeConnectionTabs(connectionId);
|
||||
connectedIds.value.delete(connectionId);
|
||||
const node = findNode(treeNodes.value, connectionId);
|
||||
if (node) {
|
||||
|
|
@ -693,6 +695,8 @@ export const useConnectionStore = defineStore("connection", () => {
|
|||
|
||||
async function closeDatabaseConnection(connectionId: string, database: string) {
|
||||
await api.closeDatabaseConnection(connectionId, database);
|
||||
const { useQueryStore } = await import("@/stores/queryStore");
|
||||
useQueryStore().closeDatabaseTabs(connectionId, database);
|
||||
const node = findDatabaseTreeNode(treeNodes.value, connectionId, database);
|
||||
if (node) {
|
||||
node.isExpanded = false;
|
||||
|
|
|
|||
|
|
@ -313,13 +313,8 @@ export const useQueryStore = defineStore("query", () => {
|
|||
activeTabId.value = next.activeTabId;
|
||||
}
|
||||
|
||||
function closeDatabaseTabs(connectionId: string, database: string) {
|
||||
const closingModes = new Set<QueryTab["mode"]>(["data", "objects", "structure", "mongo"]);
|
||||
const closingIds = new Set(
|
||||
tabs.value
|
||||
.filter((tab) => tab.connectionId === connectionId && tab.database === database && closingModes.has(tab.mode))
|
||||
.map((tab) => tab.id),
|
||||
);
|
||||
function closeTabsWhere(predicate: (tab: QueryTab) => boolean) {
|
||||
const closingIds = new Set(tabs.value.filter((tab) => predicate(tab)).map((tab) => tab.id));
|
||||
if (closingIds.size === 0) return;
|
||||
|
||||
tabs.value
|
||||
|
|
@ -339,6 +334,14 @@ export const useQueryStore = defineStore("query", () => {
|
|||
}
|
||||
}
|
||||
|
||||
function closeConnectionTabs(connectionId: string) {
|
||||
closeTabsWhere((tab) => tab.connectionId === connectionId);
|
||||
}
|
||||
|
||||
function closeDatabaseTabs(connectionId: string, database: string) {
|
||||
closeTabsWhere((tab) => tab.connectionId === connectionId && tab.database === database);
|
||||
}
|
||||
|
||||
function updateSql(id: string, sql: string) {
|
||||
const tab = tabs.value.find((t) => t.id === id);
|
||||
if (tab) {
|
||||
|
|
@ -1257,6 +1260,7 @@ export const useQueryStore = defineStore("query", () => {
|
|||
closeTab,
|
||||
closeOtherTabs,
|
||||
closeAllTabs,
|
||||
closeConnectionTabs,
|
||||
closeDatabaseTabs,
|
||||
updateSql,
|
||||
renameTab,
|
||||
|
|
|
|||
|
|
@ -345,11 +345,11 @@ test("closing database tabs removes browser tabs for that database only", async
|
|||
|
||||
assert.deepEqual(
|
||||
store.tabs.map((tab) => tab.id),
|
||||
[queryId, otherDbId, otherConnectionId],
|
||||
[otherDbId, otherConnectionId],
|
||||
);
|
||||
assert.equal(store.activeTabId, otherConnectionId);
|
||||
assert.equal(
|
||||
store.tabs.some((tab) => [dataId, objectsId, structureId, mongoId].includes(tab.id)),
|
||||
store.tabs.some((tab) => [dataId, objectsId, structureId, mongoId, queryId].includes(tab.id)),
|
||||
false,
|
||||
);
|
||||
assert.equal(structureTab.result, undefined);
|
||||
|
|
@ -360,6 +360,89 @@ test("closing database tabs removes browser tabs for that database only", async
|
|||
}
|
||||
});
|
||||
|
||||
test("closing connection tabs removes every tab for that connection only", async () => {
|
||||
const restoreStorage = installMemoryStorage();
|
||||
const originalFetch = globalThis.fetch;
|
||||
globalThis.fetch = (async () => {
|
||||
return new Response(JSON.stringify(true), { status: 200, headers: { "Content-Type": "application/json" } });
|
||||
}) as typeof fetch;
|
||||
|
||||
try {
|
||||
setActivePinia(createPinia());
|
||||
const store = useQueryStore();
|
||||
const queryId = store.createTab("conn-1", "db", "draft query", "query");
|
||||
const dataId = store.createTab("conn-1", "db", "users", "data", "public");
|
||||
const objectsId = store.openObjectBrowser("conn-1", "db", "public");
|
||||
const otherConnectionId = store.createTab("conn-2", "db", "users", "data", "public");
|
||||
const queryTab = store.tabs.find((item) => item.id === queryId);
|
||||
|
||||
assert.ok(queryTab);
|
||||
queryTab.result = {
|
||||
columns: ["payload"],
|
||||
rows: [["query"]],
|
||||
affected_rows: 0,
|
||||
execution_time_ms: 1,
|
||||
session_id: "session-query",
|
||||
};
|
||||
queryTab.resultSessionId = "session-query";
|
||||
store.activeTabId = queryId;
|
||||
|
||||
store.closeConnectionTabs("conn-1");
|
||||
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||
|
||||
assert.deepEqual(
|
||||
store.tabs.map((tab) => tab.id),
|
||||
[otherConnectionId],
|
||||
);
|
||||
assert.equal(store.activeTabId, otherConnectionId);
|
||||
assert.equal(
|
||||
store.tabs.some((tab) => [queryId, dataId, objectsId].includes(tab.id)),
|
||||
false,
|
||||
);
|
||||
assert.equal(queryTab.result, undefined);
|
||||
assert.equal(queryTab.resultSessionId, undefined);
|
||||
} finally {
|
||||
globalThis.fetch = originalFetch;
|
||||
restoreStorage();
|
||||
}
|
||||
});
|
||||
|
||||
test("disconnecting a connection closes every tab for that connection", async () => {
|
||||
const restoreStorage = installMemoryStorage();
|
||||
const originalFetch = globalThis.fetch;
|
||||
globalThis.fetch = (async () => {
|
||||
return new Response(JSON.stringify(true), { status: 200, headers: { "Content-Type": "application/json" } });
|
||||
}) as typeof fetch;
|
||||
|
||||
try {
|
||||
setActivePinia(createPinia());
|
||||
const connectionStore = useConnectionStore();
|
||||
const queryStore = useQueryStore();
|
||||
connectionStore.addEphemeralConnection(conn("conn-1"));
|
||||
connectionStore.addEphemeralConnection(conn("conn-2"));
|
||||
const queryId = queryStore.createTab("conn-1", "db", "draft query", "query");
|
||||
const dataId = queryStore.createTab("conn-1", "db", "users", "data", "public");
|
||||
const otherConnectionId = queryStore.createTab("conn-2", "db", "users", "data", "public");
|
||||
|
||||
queryStore.activeTabId = dataId;
|
||||
await connectionStore.disconnect("conn-1");
|
||||
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||
|
||||
assert.deepEqual(
|
||||
queryStore.tabs.map((tab) => tab.id),
|
||||
[otherConnectionId],
|
||||
);
|
||||
assert.equal(queryStore.activeTabId, otherConnectionId);
|
||||
assert.equal(
|
||||
queryStore.tabs.some((tab) => [queryId, dataId].includes(tab.id)),
|
||||
false,
|
||||
);
|
||||
} finally {
|
||||
globalThis.fetch = originalFetch;
|
||||
restoreStorage();
|
||||
}
|
||||
});
|
||||
|
||||
test("starting a new query clears the previous result payload immediately", async () => {
|
||||
const restoreStorage = installMemoryStorage();
|
||||
setActivePinia(createPinia());
|
||||
|
|
|
|||
Loading…
Reference in New Issue