mirror of
https://github.com/l0ng-ai/openidea.git
synced 2026-11-14 16:07:52 +00:00
fix(database): keep expanded nodes loaded after editing a data source (#3243)
saveSource forgot the source's cached metadata before writing the new settings, so the following refresh found nothing loaded and reloaded only the first level; expanded schemas and tables stayed on Loading. saveSource now captures the loaded levels before forgetting them and passes them to refresh.
This commit is contained in:
@@ -334,6 +334,17 @@ describe("database metadata request lifetimes", () => {
|
||||
});
|
||||
|
||||
describe("connection and metadata continuations", () => {
|
||||
it("reloads every level the tree had expanded after a data source is edited", async () => {
|
||||
await loadSchemas("pg");
|
||||
await loadTables("pg", "public");
|
||||
await loadDetails("pg", "public", "users");
|
||||
await saveSource({ ...pg, host: "new-host" }, undefined);
|
||||
const st = useDatabase.getState();
|
||||
expect(st.schemas.pg).toEqual({ status: "ok", value: ["public"] });
|
||||
expect(st.tables["pg\u0000public"]?.status).toBe("ok");
|
||||
expect(st.details["pg\u0000public\u0000users"]?.status).toBe("ok");
|
||||
});
|
||||
|
||||
it("stores credentials when the save emits a source-change event before returning", async () => {
|
||||
backend.save.mockImplementationOnce(async (sources: DataSource[]) => {
|
||||
savedSources = sources;
|
||||
|
||||
@@ -363,6 +363,8 @@ export async function saveSource(
|
||||
const id = source.id ?? "";
|
||||
const st = useDatabase.getState();
|
||||
const loaded = id in st.databases || Object.keys(st.schemas).some((t) => splitTarget(t).id === id);
|
||||
// Taken before anything is forgotten: what the tree had expanded under this source.
|
||||
const levels = loadedLevels(id);
|
||||
const connection = connectionIntents.get(id);
|
||||
forget(id);
|
||||
const current = sourceMutation(id);
|
||||
@@ -381,7 +383,7 @@ export async function saveSource(
|
||||
// expanded nodes don't stay on Loading.
|
||||
await loadSources();
|
||||
if (!current() || !sourceById(id)) return;
|
||||
if (loaded && connectionIntents.get(id) === connection) await refresh(id);
|
||||
if (loaded && connectionIntents.get(id) === connection) await refresh(id, levels);
|
||||
}
|
||||
|
||||
/** Copy/Paste › Duplicate: a copy of data source `id` named `<name> [2]` (its password is not copied). */
|
||||
@@ -588,11 +590,14 @@ export function listsDatabases(source: DataSource | undefined): boolean {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-reads the metadata of target `id` (a data source id: all its databases),
|
||||
* reloading the levels that were loaded so the tree keeps its expanded nodes.
|
||||
*/
|
||||
export async function refresh(id: string): Promise<void> {
|
||||
interface LoadedLevels {
|
||||
schemas: string[];
|
||||
tables: [string, string][];
|
||||
details: [string, string, string][];
|
||||
}
|
||||
|
||||
/** The metadata of target `id` (a data source id: all its databases) the tree has loaded. */
|
||||
function loadedLevels(id: string): LoadedLevels {
|
||||
const whole = !splitTarget(id).database;
|
||||
const ofTarget = (k: string) => {
|
||||
const t = k.split("\u0000")[0]!;
|
||||
@@ -601,9 +606,21 @@ export async function refresh(id: string): Promise<void> {
|
||||
const st = useDatabase.getState();
|
||||
const loaded = (m: Record<string, Loaded<unknown>>) =>
|
||||
Object.keys(m).filter((k) => ofTarget(k) && m[k]!.status === "ok");
|
||||
const schemas = loaded(st.schemas);
|
||||
const tables = loaded(st.tables).map((k) => k.split("\u0000") as [string, string]);
|
||||
const details = loaded(st.details).map((k) => k.split("\u0000") as [string, string, string]);
|
||||
return {
|
||||
schemas: loaded(st.schemas),
|
||||
tables: loaded(st.tables).map((k) => k.split("\u0000") as [string, string]),
|
||||
details: loaded(st.details).map((k) => k.split("\u0000") as [string, string, string]),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-reads the metadata of target `id` (a data source id: all its databases),
|
||||
* reloading the levels that were loaded (`levels`) so the tree keeps its expanded nodes.
|
||||
*/
|
||||
export async function refresh(id: string, levels = loadedLevels(id)): Promise<void> {
|
||||
const whole = !splitTarget(id).database;
|
||||
const { tables, details } = levels;
|
||||
const schemas = [...levels.schemas];
|
||||
forget(id);
|
||||
const current = databaseRequest(id);
|
||||
const targets = new Map(
|
||||
|
||||
Reference in New Issue
Block a user