feat: implement snapshot restore functionality and enhance graph state management
All checks were successful
On Push to Main / test (push) Successful in 40s
On Push to Main / publish (push) Successful in 1m10s
On Push to Main / deploy-dev (push) Successful in 1m35s

This commit is contained in:
RaymondVerhoef
2026-05-27 17:43:18 +02:00
parent 6ea8860b96
commit 6309ae716b
4 changed files with 164 additions and 11 deletions

View File

@@ -284,6 +284,60 @@ export function setSetting(key, value) {
return pbUpsert('settings', `key="${key}"`, { value: String(value) }, { key, value: String(value) });
}
// ── Graph Snapshots ───────────────────────────────────────────────────────────
//
// A single "latest" snapshot is persisted in the settings collection before
// every bulk graph write. This survives browser/tab close and lets the admin
// roll back an AI analysis that produced unwanted results.
//
// The value is stored as a JSON string because the settings collection only
// has a plain text `value` field. Large graphs (150+ topics) can produce
// ~100 KB of JSON, which SQLite handles without issue.
const SNAPSHOT_KEY = 'graph_snapshot:latest';
/**
* Persist the current graph state as a rollback point.
* Called by useGraphData.bulkSave() before overwriting the graph.
*
* @param {object[]} topics — the graph state to preserve
* @param {object[]} relations — the graph state to preserve
*/
export async function saveGraphSnapshot(topics, relations) {
const payload = JSON.stringify({
ts: Date.now(),
topicCount: topics.length,
relationCount: relations.length,
topics,
relations,
});
return setSetting(SNAPSHOT_KEY, payload);
}
/**
* Read the latest snapshot back from PocketBase.
* Returns null when no snapshot exists or the stored value is malformed.
*
* @returns {{ ts: number, topicCount: number, relationCount: number, topics: object[], relations: object[] } | null}
*/
export async function getGraphSnapshot() {
const raw = await getSetting(SNAPSHOT_KEY, null);
if (!raw) return null;
try {
return JSON.parse(raw);
} catch {
return null;
}
}
/**
* Delete the stored snapshot (e.g. after a successful restore so the
* admin cannot accidentally restore twice).
*/
export function clearGraphSnapshot() {
return setSetting(SNAPSHOT_KEY, '');
}
// ── Curriculum Versions (v2) ──────────────────────────────────────────────────
export async function getCurriculumVersions(status) {