Files
dss/admin-ui/js/core/workflow-persistence.js
Digital Production Factory 276ed71f31 Initial commit: Clean DSS implementation
Migrated from design-system-swarm with fresh git history.
Old project history preserved in /home/overbits/apps/design-system-swarm

Core components:
- MCP Server (Python FastAPI with mcp 1.23.1)
- Claude Plugin (agents, commands, skills, strategies, hooks, core)
- DSS Backend (dss-mvp1 - token translation, Figma sync)
- Admin UI (Node.js/React)
- Server (Node.js/Express)
- Storybook integration (dss-mvp1/.storybook)

Self-contained configuration:
- All paths relative or use DSS_BASE_PATH=/home/overbits/dss
- PYTHONPATH configured for dss-mvp1 and dss-claude-plugin
- .env file with all configuration
- Claude plugin uses ${CLAUDE_PLUGIN_ROOT} for portability

Migration completed: $(date)
🤖 Clean migration with full functionality preserved
2025-12-09 18:45:48 -03:00

194 lines
4.5 KiB
JavaScript

/**
* Workflow Persistence - Phase 8 Enterprise Pattern
*
* Saves and restores workflow states to localStorage and server,
* enabling crash recovery and session restoration.
*/
import store from '../stores/app-store.js';
class WorkflowPersistence {
constructor() {
this.storageKey = 'dss-workflow-state';
this.maxSnapshots = 10;
this.autoSaveInterval = 30000; // 30 seconds
this.isAutosaving = false;
}
/**
* Take a workflow snapshot of current state
*/
snapshot() {
const state = store.get();
const snapshot = {
id: `snapshot-${Date.now()}`,
timestamp: new Date().toISOString(),
data: {
currentPage: state.currentPage,
sidebarOpen: state.sidebarOpen,
user: state.user,
team: state.team,
role: state.role,
figmaConnected: state.figmaConnected,
figmaFileKey: state.figmaFileKey,
selectedProject: state.projects[0]?.id || null,
}
};
return snapshot;
}
/**
* Save snapshot to localStorage with versioning
*/
saveSnapshot(snapshot = null) {
try {
const snap = snapshot || this.snapshot();
const snapshots = this.getSnapshots();
// Keep only latest N snapshots
snapshots.unshift(snap);
snapshots.splice(this.maxSnapshots);
localStorage.setItem(this.storageKey, JSON.stringify(snapshots));
return snap.id;
} catch (e) {
console.error('[WorkflowPersistence] Failed to save snapshot:', e);
return null;
}
}
/**
* Get all saved snapshots
*/
getSnapshots() {
try {
const stored = localStorage.getItem(this.storageKey);
return stored ? JSON.parse(stored) : [];
} catch (e) {
console.warn('[WorkflowPersistence] Failed to load snapshots:', e);
return [];
}
}
/**
* Get latest snapshot
*/
getLatestSnapshot() {
const snapshots = this.getSnapshots();
return snapshots[0] || null;
}
/**
* Get snapshot by ID
*/
getSnapshot(id) {
const snapshots = this.getSnapshots();
return snapshots.find(s => s.id === id) || null;
}
/**
* Restore workflow from snapshot
*/
restoreSnapshot(id) {
const snapshot = this.getSnapshot(id);
if (!snapshot) {
console.warn('[WorkflowPersistence] Snapshot not found:', id);
return false;
}
try {
const data = snapshot.data;
store.set({
currentPage: data.currentPage,
sidebarOpen: data.sidebarOpen,
user: data.user,
team: data.team,
role: data.role,
figmaConnected: data.figmaConnected,
figmaFileKey: data.figmaFileKey,
});
return true;
} catch (e) {
console.error('[WorkflowPersistence] Failed to restore snapshot:', e);
return false;
}
}
/**
* Clear all snapshots
*/
clearSnapshots() {
localStorage.removeItem(this.storageKey);
}
/**
* Delete specific snapshot
*/
deleteSnapshot(id) {
const snapshots = this.getSnapshots();
const filtered = snapshots.filter(s => s.id !== id);
localStorage.setItem(this.storageKey, JSON.stringify(filtered));
}
/**
* Start auto-saving workflow every N milliseconds
*/
startAutoSave(interval = this.autoSaveInterval) {
if (this.isAutosaving) return;
this.isAutosaving = true;
this.autoSaveTimer = setInterval(() => {
this.saveSnapshot();
}, interval);
console.log('[WorkflowPersistence] Auto-save enabled');
}
/**
* Stop auto-saving
*/
stopAutoSave() {
if (this.autoSaveTimer) {
clearInterval(this.autoSaveTimer);
this.isAutosaving = false;
console.log('[WorkflowPersistence] Auto-save disabled');
}
}
/**
* Export snapshots as JSON file
*/
exportSnapshots() {
const snapshots = this.getSnapshots();
const data = {
exportDate: new Date().toISOString(),
version: '1.0',
snapshots: snapshots
};
return JSON.stringify(data, null, 2);
}
/**
* Import snapshots from JSON data
*/
importSnapshots(jsonData) {
try {
const data = JSON.parse(jsonData);
if (!Array.isArray(data.snapshots)) {
throw new Error('Invalid snapshot format');
}
localStorage.setItem(this.storageKey, JSON.stringify(data.snapshots));
return true;
} catch (e) {
console.error('[WorkflowPersistence] Failed to import snapshots:', e);
return false;
}
}
}
// Create and export singleton
const persistence = new WorkflowPersistence();
export { WorkflowPersistence };
export default persistence;