mirror of
https://github.com/OFFIS-ESC/constellation-analyzer
synced 2026-01-27 15:53:42 +00:00
docs: add comprehensive JSDoc for all state sync points
Implements Phase 6.1 of the state management refactoring plan. Added detailed documentation for all 5 critical sync points in the state management architecture, making data flow explicit and traceable. Sync Points Documented: 1. Document → graphStore (useActiveDocument.ts:67-80) - When: Active document switches - What: Loads timeline state into editor - Direction: ConstellationDocument → graphStore 2. graphStore → timeline current state (useActiveDocument.ts:197-214) - When: Graph changes detected - What: Updates timeline's current state - Direction: graphStore → timeline.states[currentStateId] 3. timeline → document (workspaceStore.ts:789-818) - When: Document save - What: Serializes timeline to storage - Direction: timelineStore → document.timeline → localStorage 4. document types → graphStore (workspaceStore.ts:1018-1034) - When: Type management operations - What: Syncs types to editor if active - Direction: document → graphStore (if active) 5. timeline → graphStore (timelineStore.ts:286-311) - When: Timeline state switch - What: Loads state's graph into editor - Direction: timeline.states[targetId] → graphStore Each sync point includes: - ✅ Visual separator for easy identification - ✅ Trigger condition (when it occurs) - ✅ Data being synchronized (what changes) - ✅ Source of truth clarification - ✅ Data flow direction - ✅ Context and rationale Benefits: - Clear understanding of data flow through the system - Easier onboarding for new developers - Prevents accidental breaking of sync relationships - Makes debugging state issues much faster 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
f29c55a1b8
commit
4b60c4b7b2
3 changed files with 75 additions and 5 deletions
|
|
@ -283,8 +283,23 @@ export const useTimelineStore = create<TimelineStore & TimelineActions>(
|
||||||
return { timelines: newTimelines };
|
return { timelines: newTimelines };
|
||||||
});
|
});
|
||||||
|
|
||||||
// Load target state's graph (nodes, edges, and groups - types are global)
|
/**
|
||||||
// IMPORTANT: Use loadGraphState for atomic update to prevent React Flow errors
|
* ═══════════════════════════════════════════════════════════════════════════
|
||||||
|
* SYNC POINT 5: timeline → graphStore
|
||||||
|
* ═══════════════════════════════════════════════════════════════════════════
|
||||||
|
*
|
||||||
|
* When: Timeline state switch (user navigates to different state in timeline)
|
||||||
|
* What: Loads target state's graph (nodes, edges, groups) into graphStore
|
||||||
|
* Source of Truth: timelineStore (targetState.graph)
|
||||||
|
* Direction: timeline.states[targetStateId].graph → graphStore
|
||||||
|
*
|
||||||
|
* When switching between timeline states, we load the target state's graph
|
||||||
|
* into the editor. Types and labels remain the same (document-level config),
|
||||||
|
* only nodes/edges/groups change between states.
|
||||||
|
*
|
||||||
|
* IMPORTANT: Uses loadGraphState for atomic update to prevent React Flow
|
||||||
|
* "Parent node not found" errors when groups and their children load.
|
||||||
|
*/
|
||||||
const graphStore = useGraphStore.getState();
|
const graphStore = useGraphStore.getState();
|
||||||
graphStore.loadGraphState({
|
graphStore.loadGraphState({
|
||||||
nodes: targetState.graph.nodes as unknown as Actor[],
|
nodes: targetState.graph.nodes as unknown as Actor[],
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,20 @@ export function useActiveDocument() {
|
||||||
labels: [],
|
labels: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
// Load active document into graphStore when it changes
|
/**
|
||||||
|
* ═══════════════════════════════════════════════════════════════════════════
|
||||||
|
* SYNC POINT 1: Document → graphStore
|
||||||
|
* ═══════════════════════════════════════════════════════════════════════════
|
||||||
|
*
|
||||||
|
* When: Active document switches (document tab change)
|
||||||
|
* What: Loads nodes, edges, groups, types, labels from document into graphStore
|
||||||
|
* Source of Truth: ConstellationDocument (persistent storage)
|
||||||
|
* Direction: document.timeline.currentState → graphStore (working copy)
|
||||||
|
*
|
||||||
|
* This is the entry point for loading a document's data into the editor.
|
||||||
|
* It deserializes the document's current timeline state and populates the
|
||||||
|
* graphStore with the working copy that React Flow will render.
|
||||||
|
*/
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (activeDocument && activeDocumentId) {
|
if (activeDocument && activeDocumentId) {
|
||||||
console.log(`Loading document into graph editor: ${activeDocumentId}`, activeDocument.metadata.title);
|
console.log(`Loading document into graph editor: ${activeDocumentId}`, activeDocument.metadata.title);
|
||||||
|
|
@ -181,7 +194,19 @@ export function useActiveDocument() {
|
||||||
labels: graphLabels as LabelConfig[],
|
labels: graphLabels as LabelConfig[],
|
||||||
};
|
};
|
||||||
|
|
||||||
// Update the timeline's current state with the new graph data (nodes, edges, and groups)
|
/**
|
||||||
|
* ═══════════════════════════════════════════════════════════════════════════
|
||||||
|
* SYNC POINT 2: graphStore → timeline current state
|
||||||
|
* ═══════════════════════════════════════════════════════════════════════════
|
||||||
|
*
|
||||||
|
* When: Graph changes detected (node/edge/group add/delete/move)
|
||||||
|
* What: Updates timeline.states[currentStateId].graph with latest graphStore data
|
||||||
|
* Source of Truth: graphStore (working copy)
|
||||||
|
* Direction: graphStore → timeline.states[currentStateId].graph
|
||||||
|
*
|
||||||
|
* This keeps the timeline's current state in sync with the editor's working copy.
|
||||||
|
* When the document is saved, this updated timeline will be serialized to storage.
|
||||||
|
*/
|
||||||
useTimelineStore.getState().saveCurrentGraph({
|
useTimelineStore.getState().saveCurrentGraph({
|
||||||
nodes: graphNodes as never[],
|
nodes: graphNodes as never[],
|
||||||
edges: graphEdges as never[],
|
edges: graphEdges as never[],
|
||||||
|
|
|
||||||
|
|
@ -786,7 +786,20 @@ export const useWorkspaceStore = create<Workspace & WorkspaceActions>((set, get)
|
||||||
// and are managed via workspaceStore's type management actions.
|
// and are managed via workspaceStore's type management actions.
|
||||||
// We do NOT copy them from graphStore because the document is the source of truth.
|
// We do NOT copy them from graphStore because the document is the source of truth.
|
||||||
|
|
||||||
// Save timeline data if exists
|
/**
|
||||||
|
* ═══════════════════════════════════════════════════════════════════════════
|
||||||
|
* SYNC POINT 3: timeline → document
|
||||||
|
* ═══════════════════════════════════════════════════════════════════════════
|
||||||
|
*
|
||||||
|
* When: Document save (auto-save or manual)
|
||||||
|
* What: Serializes entire timeline (all states) to document.timeline
|
||||||
|
* Source of Truth: timelineStore (transient working copy)
|
||||||
|
* Direction: timelineStore → document.timeline → localStorage
|
||||||
|
*
|
||||||
|
* This persists the complete timeline structure to storage. The timeline's
|
||||||
|
* current state has already been updated by SYNC POINT 2, so we're saving
|
||||||
|
* the latest graph data along with all historical timeline branches.
|
||||||
|
*/
|
||||||
const timelineState = useTimelineStore.getState();
|
const timelineState = useTimelineStore.getState();
|
||||||
const timeline = timelineState.timelines.get(documentId);
|
const timeline = timelineState.timelines.get(documentId);
|
||||||
|
|
||||||
|
|
@ -1002,6 +1015,23 @@ export const useWorkspaceStore = create<Workspace & WorkspaceActions>((set, get)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ═══════════════════════════════════════════════════════════════════════════
|
||||||
|
* SYNC POINT 4: document types → graphStore
|
||||||
|
* ═══════════════════════════════════════════════════════════════════════════
|
||||||
|
*
|
||||||
|
* When: Type management operations (add/update/delete node/edge types, labels)
|
||||||
|
* What: Updates document types/labels and syncs to graphStore if document is active
|
||||||
|
* Source of Truth: ConstellationDocument (document.nodeTypes, document.edgeTypes, document.labels)
|
||||||
|
* Direction: document → graphStore (if active document)
|
||||||
|
*
|
||||||
|
* Type configurations are document-level properties. When modified, changes
|
||||||
|
* are persisted to the document first, then synced to graphStore if this is
|
||||||
|
* the currently active document. This ensures the editor always displays the
|
||||||
|
* correct types for the current document.
|
||||||
|
*
|
||||||
|
* All type operations use atomic transactions with rollback (Phase 3.1).
|
||||||
|
*/
|
||||||
addNodeTypeToDocument: (documentId: string, nodeType) => {
|
addNodeTypeToDocument: (documentId: string, nodeType) => {
|
||||||
const state = get();
|
const state = get();
|
||||||
const doc = state.documents.get(documentId);
|
const doc = state.documents.get(documentId);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue