Commit graph

10 commits

Author SHA1 Message Date
Jan-Henrik Bruhn
6a56b94477 refactor: move snapshot creation to historyStore (architectural fix)
Fixes architectural issue where snapshot logic was duplicated between
hook and store layers.

Problem Identified:
- useDocumentHistory (hook) created snapshots with duplicate logic
- timelineStore (store) created snapshots with duplicate logic
- timelineStore couldn't call useDocumentHistory (hooks can't be used in stores)
- Snapshot creation logic scattered across codebase

Root Cause:
Timeline operations happen in the store layer but history was managed
via a hook. This architectural mismatch forced duplication.

Solution:
- Add pushToHistory() method to historyStore
- Single source of truth for snapshot creation
- Both hook and store layers call historyStore.pushToHistory()
- Eliminates all snapshot creation duplication

Changes:
- Add historyStore.pushToHistory() - high-level API with snapshot creation
- Keep historyStore.pushAction() - low-level API (for future use)
- Update useDocumentHistory to call historyStore.pushToHistory()
- Update timelineStore pushDocumentHistory() to call historyStore.pushToHistory()
- Remove createDocumentSnapshot import from useDocumentHistory
- Remove createDocumentSnapshot import from timelineStore

Architecture:
Before:
  Hook (useDocumentHistory) → creates snapshot → historyStore.pushAction()
  Store (timelineStore) → creates snapshot → historyStore.pushAction()
  [Duplication at 2 call sites]

After:
  Hook (useDocumentHistory) → historyStore.pushToHistory() → creates snapshot
  Store (timelineStore) → historyStore.pushToHistory() → creates snapshot
  [Single implementation in historyStore]

Benefits:
-  Zero snapshot creation duplication
-  Proper architectural separation (store handles snapshots, not hook/store)
-  Single source of truth (historyStore.pushToHistory)
-  Timeline and graph operations use identical snapshot logic
-  Easy to modify snapshot behavior in future (one place)

Impact:
- No breaking changes
- No behavior changes
- Better code organization
- Easier maintenance

Related: Phase 2.1 architectural improvement

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-20 12:24:52 +02:00
Jan-Henrik Bruhn
0ef81260cc refactor: centralize snapshot creation logic (Phase 2.1)
Eliminates duplicate snapshot logic between useDocumentHistory and timelineStore.

Problem:
- useDocumentHistory created snapshots reading types from document (correct)
- timelineStore created snapshots reading types from graphStore (incorrect)
- ~30 lines of duplicated snapshot creation logic
- Risk of inconsistent behavior between graph and timeline operations

Solution:
- Created createDocumentSnapshot() in documentUtils.ts
- Single source of truth for snapshot creation
- Always reads types/labels from document (correct source)
- Syncs timeline current state before snapshot (ensures latest data)

Changes:
- Add createDocumentSnapshot() to src/stores/workspace/documentUtils.ts
- Update useDocumentHistory.ts to use centralized helper
- Update timelineStore.ts pushDocumentHistory() to use centralized helper
- Remove duplicate snapshot creation code (~30 lines)

Benefits:
-  Consistent snapshot behavior everywhere
-  Types always read from document (source of truth)
-  Easier to maintain (single implementation)
-  Fixes potential bug where timelineStore had stale types
-  Better code organization

Impact:
- No breaking changes
- Undo/redo behavior unchanged for users
- Timeline operations now have correct type information
- Safer - impossible for snapshot logic to diverge

Testing:
- TypeScript compilation passes
- No runtime behavior changes expected
- Snapshot structure unchanged

Related: Phase 2.1 of STATE_MANAGEMENT_REFACTORING_PLAN.md

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-20 12:19:58 +02:00
Jan-Henrik Bruhn
b1e634d3c4 feat: add group minimize/maximize with floating edges and React Flow v12
Implements comprehensive group minimize/maximize functionality and migrates
to React Flow v12 (@xyflow/react) with improved edge routing.

## Group Minimize/Maximize Features:
- Minimized groups render as compact 220×80px solid rectangles
- Original dimensions preserved in metadata and restored on maximize
- Child actors hidden (not filtered) to prevent React Flow state issues
- Solid color backgrounds (transparency removed for minimized state)
- Internal edges filtered out when group is minimized
- Dimension sync before minimize ensures correct size on maximize

## Floating Edges:
- Dynamic edge routing for connections to/from minimized groups
- Edges connect to closest point on minimized group border
- Regular actors maintain fixed handle connections
- Smooth transitions when toggling group state

## React Flow v12 Migration:
- Updated package from 'reactflow' to '@xyflow/react'
- Changed imports to named imports (ReactFlow is now named)
- Updated CSS imports to '@xyflow/react/dist/style.css'
- Fixed NodeProps/EdgeProps to use full Node/Edge types
- Added Record<string, unknown> to data interfaces for v12 compatibility
- Replaced useStore(state => state.connectionNodeId) with useConnection()
- Updated nodeInternals to nodeLookup (renamed in v12)
- Fixed event handler types for v12 API changes

## Edge Label Improvements:
- Added explicit z-index (1000) to edge labels via EdgeLabelRenderer
- Labels now properly render above edge paths

## Type Safety & Code Quality:
- Removed all 'any' type assertions in useDocumentHistory
- Fixed missing React Hook dependencies
- Fixed unused variable warnings
- All ESLint checks passing (0 errors, 0 warnings)
- TypeScript compilation clean

## Bug Fixes:
- Group drag positions now properly persisted to store
- Minimized group styling (removed dotted border, padding)
- Node visibility using 'hidden' property instead of array filtering
- Dimension sync prevents actors from disappearing on maximize

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-20 11:52:44 +02:00
Jan-Henrik Bruhn
f5adbc8ead feat: add resizable actor grouping with full undo/redo support
Implements visual grouping of actors with context menu operations,
resizable containers, and complete history tracking integration.

Features:
- Create groups from multiple selected actors via context menu
- Groups visualized as resizable containers with child nodes
- Ungroup actors (non-destructive) or delete group with actors
- Right-click context menu with group-specific operations
- Dedicated GroupEditorPanel for group properties
- Smart minimum size constraint based on child node positions
- Full undo/redo support for group operations and resizes

Technical Implementation:
- GroupNode component with React Flow NodeResizer integration
- Atomic createGroupWithActors operation for consistent history
- Parent-child relationship using React Flow v11 parentId pattern
- Groups stored separately from actors in graphStore
- Fixed history tracking to sync graphStore before snapshots
- Resize tracking to prevent state sync loops during interaction
- Dynamic minimum dimensions to keep children inside bounds
- Sanitization of orphaned parentId references on state load

History Fixes:
- pushToHistory now syncs timeline with graphStore before snapshot
- Prevents missing groups/nodes in history states
- Ensures undo/redo correctly restores all graph elements
- Atomic state updates to avoid React Flow processing stale state

Storage & Persistence:
- Groups saved in timeline states and document structure
- Safe JSON serialization to prevent prototype pollution
- Cleanup utilities for removing __proto__ from localStorage

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-18 20:06:59 +02:00
Jan-Henrik Bruhn
d98acf963b feat: implement label system and redesign filtering with positive filters
Implements a comprehensive label system and completely redesigns all
filtering (labels, actor types, relation types) to use intuitive positive
filtering where empty selection shows all items.

Label System Features:
- Create, edit, delete labels with names, colors, and scope (actors/relations/both)
- Inline editing with click-to-edit UI for quick modifications
- Quick-add label forms in config modals
- Autocomplete label selector with inline label creation
- Label badges rendered on nodes and edges (no overflow limits)
- Full undo/redo support for label operations
- Label validation and cleanup when labels are deleted
- Labels stored per-document in workspace system

Filter System Redesign:
- Changed from negative to positive filtering for all filter types
- Empty selection = show all items (intuitive default)
- Selected items = show only those items (positive filter)
- Consistent behavior across actor types, relation types, and labels
- Clear visual feedback with selection counts and helper text
- Auto-zoom viewport adjustment works for all filter types including labels

Label Cleanup & Validation:
- When label deleted, automatically removed from all nodes/edges across all timeline states
- Label references validated during node/edge updates
- Unknown label IDs filtered out to maintain data integrity

UI Improvements:
- All labels rendered without overflow limits (removed +N more indicators)
- Filter checkboxes start unchecked (select to filter, not hide)
- Helper text explains current filter state
- Selection counts displayed in filter section headers

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-17 10:40:00 +02:00
Jan-Henrik Bruhn
89117415ed refactor: establish document as source of truth for node/edge types
Refactors the type management system to properly follow the
Workspace→Document→Timeline→Graph hierarchy, where nodeTypes and
edgeTypes are owned by the document rather than being independent
state in graphStore.

Changes:
- Add type management actions to workspaceStore (document-level)
- Update workspaceStore.saveDocument to stop copying types from graphStore
- Modify useActiveDocument to only track node/edge changes for dirty state
- Update useGraphWithHistory to route type operations through workspaceStore
- Update useDocumentHistory to read/restore types from document

Architecture:
- Document: Source of truth for types (persistent storage)
- graphStore: Synchronized working memory (optimized for React Flow)
- useActiveDocument: Bridge that syncs document → graphStore
- Type mutations: Always go through workspaceStore, then sync to graphStore

This ensures proper data ownership while maintaining graphStore as a
performance optimization layer for the UI.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 14:27:57 +02:00
Jan-Henrik Bruhn
d775cb8863 refactor: migrate undo/redo from per-state to per-document level
Refactors the history system to track complete document state instead of
individual timeline states, making timeline operations fully undoable.

BREAKING CHANGE: History is now per-document instead of per-timeline-state.
Existing undo/redo stacks will be cleared on first load with this change.

Changes:
- historyStore: Track complete document snapshots (timeline + all states + types)
- useDocumentHistory: Simplified to work with document-level operations
- timelineStore: All timeline operations now record history
  - createState, switchToState, deleteState, updateState, duplicateState
- Fixed redo button bug (was mutating Zustand state directly)

New capabilities:
- Undo/redo timeline state creation
- Undo/redo timeline state deletion
- Undo/redo switching between timeline states
- Undo/redo renaming timeline states
- Unified history for all document operations

Technical improvements:
- Proper Zustand state management (no direct mutations)
- Document snapshots include entire timeline structure
- History methods accept currentSnapshot parameter
- Removed TypeScript 'any' types for better type safety

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-11 22:38:23 +02:00
Jan-Henrik Bruhn
28f8224284 feat: add timeline system for multi-state constellation analysis
Implements a comprehensive timeline system that enables documents to contain
multiple constellation states with branching timelines. This allows users to
create different versions of their analysis for temporal evolution, alternative
scenarios, or what-if analysis.

Core Features:
- Timeline store managing multiple states per document with branching structure
- Visual timeline panel with React Flow-based state graph visualization
- State management: create, switch, rename, duplicate (parallel/series), delete
- Per-state undo/redo history (max 50 actions per state)
- Context menu for timeline node operations
- Collapsible timeline panel (always visible, moved toolbar to panel header)

Architecture Changes:
- Document structure: removed top-level graph field, states now only in timeline
- Global types: nodeTypes and edgeTypes are now global per document, not per state
- State graphs: only contain nodes and edges, types inherited from document
- Persistence: full timeline serialization/deserialization with all states
- History system: converted from document-level to per-state independent stacks

Timeline Components:
- TimelineView: main timeline visualization with state nodes and edges
- BottomPanel: collapsible container with timeline controls in header
- StateNode: custom node component showing state info and active indicator
- CreateStateDialog: dialog for creating new timeline states
- RenameStateDialog: dialog for renaming existing states
- Context menu: right-click operations (rename, duplicate parallel/series, delete)

Document Management:
- Documents always have timeline (initialized with root state on creation)
- Timeline persisted with document in localStorage
- Export/import includes complete timeline with all states
- Migration support for legacy single-state documents

Store Updates:
- timelineStore: manages timelines, states, and timeline operations
- historyStore: per-state history with independent undo/redo stacks
- workspaceStore: saves/loads timeline data, handles global types
- panelStore: added timeline panel visibility state
- useActiveDocument: syncs timeline state with graph editor

Context Menu Improvements:
- Smart viewport edge detection to prevent overflow
- Click-outside detection for React Flow panes
- Consistent styling across application

Files Added:
- src/types/timeline.ts - Timeline type definitions
- src/stores/timelineStore.ts - Timeline state management
- src/components/Timeline/TimelineView.tsx - Main timeline component
- src/components/Timeline/BottomPanel.tsx - Timeline panel container
- src/components/Timeline/StateNode.tsx - State node visualization
- src/components/Timeline/CreateStateDialog.tsx - State creation dialog
- src/components/Timeline/RenameStateDialog.tsx - State rename dialog

Files Removed:
- src/stores/persistence/middleware.ts - Obsolete persistence middleware

Documentation:
- Added comprehensive timeline feature documentation
- Implementation checklists and quick reference guides
- Temporal analysis concepts and UX guidelines

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-11 22:00:34 +02:00
Jan-Henrik Bruhn
e7ff53dcd7 feat: side panels for properties and tools 2025-10-10 18:13:18 +02:00
Jan-Henrik Bruhn
f56f928dcf Initial commit 2025-10-10 11:15:51 +02:00