fix(tabs): honor data tab reuse across activation paths
This commit is contained in:
18 files changed
+157
-34
No files matched your search
@@ -52,18 +52,19 @@ describe("dataTabOpenPolicy", () => {
|
||||
const existing = dataTab("users", "users");
|
||||
existing.tableMeta = { schema: "public", tableName: "users", columns: [], primaryKeys: [] };
|
||||
|
||||
expect(findExistingDataTabCandidate([existing], usersTarget, { openMode: "new-tab", reuseDataTab: true })).toBeUndefined();
|
||||
expect(findExistingDataTabCandidate([existing], usersTarget, { openMode: "new-tab", reuseDataTab: false })).toBeUndefined();
|
||||
expect(findExistingDataTabCandidate([existing], usersTarget, { openMode: "new-tab", reuseScope: "database" })).toBeUndefined();
|
||||
expect(findExistingDataTabCandidate([existing], usersTarget, { openMode: "new-tab", reuseScope: "none" })).toBeUndefined();
|
||||
});
|
||||
|
||||
it("preserves same-table activation and configured database-tab reuse for ordinary opens", () => {
|
||||
it("applies none, same-table, and database reuse scopes independently", () => {
|
||||
const sameTable = dataTab("users", "users");
|
||||
sameTable.tableMeta = { schema: "public", tableName: "users", columns: [], primaryKeys: [] };
|
||||
const otherTable = dataTab("orders", "orders");
|
||||
|
||||
expect(findExistingDataTabCandidate([sameTable], usersTarget, { openMode: "default", reuseDataTab: false })).toEqual({ tab: sameTable, match: "same-table" });
|
||||
expect(findExistingDataTabCandidate([otherTable], usersTarget, { openMode: "default", reuseDataTab: true })).toEqual({ tab: otherTable, match: "database" });
|
||||
expect(findExistingDataTabCandidate([otherTable], usersTarget, { openMode: "default", reuseDataTab: false })).toBeUndefined();
|
||||
expect(findExistingDataTabCandidate([sameTable], usersTarget, { openMode: "default", reuseScope: "none" })).toBeUndefined();
|
||||
expect(findExistingDataTabCandidate([sameTable], usersTarget, { openMode: "default", reuseScope: "same-table" })).toEqual({ tab: sameTable, match: "same-table" });
|
||||
expect(findExistingDataTabCandidate([otherTable], usersTarget, { openMode: "default", reuseScope: "same-table" })).toBeUndefined();
|
||||
expect(findExistingDataTabCandidate([otherTable], usersTarget, { openMode: "default", reuseScope: "database" })).toEqual({ tab: otherTable, match: "database" });
|
||||
});
|
||||
|
||||
it("allows metadata to update a tab that still points to the requested table", () => {
|
||||
@@ -79,7 +80,7 @@ describe("dataTabOpenPolicy", () => {
|
||||
tab.tableMeta = { schema: "public", tableName: "users", columns: [], primaryKeys: [] };
|
||||
|
||||
expect(canApplyDataTabMetadata(tab, usersTarget, new AbortController().signal)).toBe(true);
|
||||
expect(findExistingDataTabCandidate([tab], usersTarget, { openMode: "default", reuseDataTab: false })).toEqual({ tab, match: "same-table" });
|
||||
expect(findExistingDataTabCandidate([tab], usersTarget, { openMode: "default", reuseScope: "same-table" })).toEqual({ tab, match: "same-table" });
|
||||
});
|
||||
|
||||
it("ignores metadata query schemas for database-scoped tables", () => {
|
||||
@@ -89,7 +90,7 @@ describe("dataTabOpenPolicy", () => {
|
||||
const mysqlTarget = { connectionId: "conn", database: "app", tableName: "users" };
|
||||
|
||||
expect(canApplyDataTabMetadata(tab, mysqlTarget, new AbortController().signal)).toBe(true);
|
||||
expect(findExistingDataTabCandidate([tab], mysqlTarget, { openMode: "default", reuseDataTab: false })).toEqual({ tab, match: "same-table" });
|
||||
expect(findExistingDataTabCandidate([tab], mysqlTarget, { openMode: "default", reuseScope: "same-table" })).toEqual({ tab, match: "same-table" });
|
||||
});
|
||||
|
||||
it("rejects metadata after its request is cancelled", () => {
|
||||
|
||||
@@ -2,6 +2,7 @@ import { matchesModifierOnlyShortcut, type ShortcutLikeEvent } from "@/lib/edito
|
||||
import type { QueryTab, TreeNodeType } from "@/types/database";
|
||||
|
||||
export type DataTabOpenMode = "default" | "new-tab";
|
||||
export type DataTabReuseScope = "none" | "same-table" | "database";
|
||||
|
||||
type DataTabLike = Pick<QueryTab, "id" | "mode" | "connectionId" | "database" | "schema" | "title" | "tableMeta" | "tableMetaUpdatedAt">;
|
||||
|
||||
@@ -47,12 +48,12 @@ export function dataTabMetadataNeedsRefresh(tab: DataTabLike, maxAgeMs: number,
|
||||
return now - tab.tableMetaUpdatedAt >= maxAgeMs;
|
||||
}
|
||||
|
||||
export function findExistingDataTabCandidate<T extends DataTabLike>(tabs: T[], target: DataTabTarget, options: { openMode: DataTabOpenMode; reuseDataTab: boolean }): ExistingDataTabCandidate<T> | undefined {
|
||||
if (options.openMode === "new-tab") return undefined;
|
||||
export function findExistingDataTabCandidate<T extends DataTabLike>(tabs: T[], target: DataTabTarget, options: { openMode: DataTabOpenMode; reuseScope: DataTabReuseScope }): ExistingDataTabCandidate<T> | undefined {
|
||||
if (options.openMode === "new-tab" || options.reuseScope === "none") return undefined;
|
||||
|
||||
const sameTable = tabs.find((tab) => isSameTable(tab, target));
|
||||
if (sameTable) return { tab: sameTable, match: "same-table" };
|
||||
if (!options.reuseDataTab) return undefined;
|
||||
if (options.reuseScope === "same-table") return undefined;
|
||||
|
||||
const sameDatabase = tabs.find((tab) => isSameDatabase(tab, target));
|
||||
return sameDatabase ? { tab: sameDatabase, match: "database" } : undefined;
|
||||
|
||||
@@ -12,8 +12,9 @@ export function canActivateExistingDataTableTab(tab: QueryTab, options: { activa
|
||||
return !!tab.result || !!tab.results?.length;
|
||||
}
|
||||
|
||||
export function dataTableDoubleClickAction(tab: QueryTab | undefined, activation: "single" | "double"): DataTableDoubleClickAction {
|
||||
export function dataTableDoubleClickAction(tab: QueryTab | undefined, activation: "single" | "double", reuseDataTab = true): DataTableDoubleClickAction {
|
||||
if (activation === "single") return "none";
|
||||
if (!reuseDataTab) return "open";
|
||||
if (!tab) return activation === "double" ? "open" : "none";
|
||||
if (!canActivateExistingDataTableTab(tab)) return "open";
|
||||
return "activate";
|
||||
|
||||
Reference in new issue
Block a user