mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-24 15:45:35 +08:00
improvement(stores): standardized quality of stores and added max history to relevant stores
This commit is contained in:
@@ -2,6 +2,7 @@ import { create } from 'zustand'
|
||||
import { devtools, persist } from 'zustand/middleware'
|
||||
import { ConsoleEntry, ConsoleStore } from './types'
|
||||
|
||||
// MAX across all workflows
|
||||
const MAX_ENTRIES = 50
|
||||
|
||||
export const useConsoleStore = create<ConsoleStore>()(
|
||||
|
||||
@@ -3,18 +3,20 @@ import { devtools } from 'zustand/middleware'
|
||||
import { Notification, NotificationStore, NotificationType } from './types'
|
||||
|
||||
const STORAGE_KEY = 'workflow-notifications'
|
||||
// Maximum number of notifications to keep across all workflows
|
||||
const MAX_NOTIFICATIONS = 50
|
||||
|
||||
// Helper to load persisted notifications
|
||||
const loadPersistedNotifications = (): Notification[] => {
|
||||
if (typeof window === 'undefined') return []
|
||||
const saved = localStorage.getItem(STORAGE_KEY)
|
||||
return saved ? JSON.parse(saved) : []
|
||||
return saved ? JSON.parse(saved).slice(0, MAX_NOTIFICATIONS) : []
|
||||
}
|
||||
|
||||
// Helper to save notifications to localStorage
|
||||
const persistNotifications = (notifications: Notification[]) => {
|
||||
if (typeof window === 'undefined') return
|
||||
localStorage.setItem(STORAGE_KEY, JSON.stringify(notifications))
|
||||
localStorage.setItem(STORAGE_KEY, JSON.stringify(notifications.slice(0, MAX_NOTIFICATIONS)))
|
||||
}
|
||||
|
||||
export const useNotificationStore = create<NotificationStore>()(
|
||||
@@ -36,7 +38,11 @@ export const useNotificationStore = create<NotificationStore>()(
|
||||
}
|
||||
|
||||
set((state) => {
|
||||
const newNotifications = [...state.notifications, notification]
|
||||
// Add new notification at the start and limit total count
|
||||
const newNotifications = [notification, ...state.notifications].slice(
|
||||
0,
|
||||
MAX_NOTIFICATIONS
|
||||
)
|
||||
persistNotifications(newNotifications)
|
||||
return { notifications: newNotifications }
|
||||
})
|
||||
|
||||
@@ -2,16 +2,20 @@ import { StateCreator } from 'zustand'
|
||||
import { HistoryActions, HistoryEntry, WorkflowHistory } from './history-types'
|
||||
import { WorkflowState, WorkflowStore } from './types'
|
||||
|
||||
// MAX for each individual workflow
|
||||
const MAX_HISTORY_LENGTH = 20
|
||||
|
||||
// Types for workflow store with history management capabilities
|
||||
export interface WorkflowStoreWithHistory extends WorkflowStore, HistoryActions {
|
||||
history: WorkflowHistory
|
||||
}
|
||||
|
||||
// Higher-order store middleware that adds undo/redo functionality
|
||||
export const withHistory = (
|
||||
config: StateCreator<WorkflowStoreWithHistory>
|
||||
): StateCreator<WorkflowStoreWithHistory> => {
|
||||
return (set, get, api) => {
|
||||
// Initialize store with history tracking
|
||||
const initialState = config(set, get, api)
|
||||
const initialHistoryEntry: HistoryEntry = {
|
||||
state: {
|
||||
@@ -31,9 +35,13 @@ export const withHistory = (
|
||||
future: [],
|
||||
},
|
||||
|
||||
// Check if undo operation is available
|
||||
canUndo: () => get().history.past.length > 0,
|
||||
|
||||
// Check if redo operation is available
|
||||
canRedo: () => get().history.future.length > 0,
|
||||
|
||||
// Restore previous state from history
|
||||
undo: () => {
|
||||
const { history, ...state } = get()
|
||||
if (history.past.length === 0) return
|
||||
@@ -52,6 +60,7 @@ export const withHistory = (
|
||||
})
|
||||
},
|
||||
|
||||
// Restore next state from history
|
||||
redo: () => {
|
||||
const { history, ...state } = get()
|
||||
if (history.future.length === 0) return
|
||||
@@ -70,6 +79,7 @@ export const withHistory = (
|
||||
})
|
||||
},
|
||||
|
||||
// Reset workflow to empty state
|
||||
clear: () => {
|
||||
const newState = {
|
||||
blocks: {},
|
||||
@@ -89,6 +99,7 @@ export const withHistory = (
|
||||
return newState
|
||||
},
|
||||
|
||||
// Jump to specific point in history
|
||||
revertToHistoryState: (index: number) => {
|
||||
const { history, ...state } = get()
|
||||
const allStates = [...history.past, history.present, ...history.future]
|
||||
@@ -113,6 +124,7 @@ export const withHistory = (
|
||||
}
|
||||
}
|
||||
|
||||
// Create a new history entry with current state snapshot
|
||||
export const createHistoryEntry = (state: WorkflowState, action: string): HistoryEntry => ({
|
||||
state: {
|
||||
blocks: { ...state.blocks },
|
||||
@@ -123,6 +135,7 @@ export const createHistoryEntry = (state: WorkflowState, action: string): Histor
|
||||
action,
|
||||
})
|
||||
|
||||
// Add new entry to history and maintain history size limit
|
||||
export const pushHistory = (
|
||||
set: (
|
||||
partial:
|
||||
|
||||
@@ -2,15 +2,18 @@ import { create } from 'zustand'
|
||||
import { devtools } from 'zustand/middleware'
|
||||
import { useWorkflowStore } from '../store'
|
||||
import { WorkflowMetadata, WorkflowRegistry } from './types'
|
||||
import { generateUniqueName } from './utils'
|
||||
|
||||
export const useWorkflowRegistry = create<WorkflowRegistry>()(
|
||||
devtools(
|
||||
(set, get) => ({
|
||||
// Store state
|
||||
workflows: {},
|
||||
activeWorkflowId: null,
|
||||
isLoading: false,
|
||||
error: null,
|
||||
|
||||
// Switch to a different workflow and manage state persistence
|
||||
setActiveWorkflow: async (id: string) => {
|
||||
const { workflows } = get()
|
||||
if (!workflows[id]) {
|
||||
@@ -72,6 +75,7 @@ export const useWorkflowRegistry = create<WorkflowRegistry>()(
|
||||
set({ activeWorkflowId: id, error: null })
|
||||
},
|
||||
|
||||
// Create new workflow with default starter block
|
||||
addWorkflow: (metadata: WorkflowMetadata) => {
|
||||
const uniqueName = generateUniqueName(get().workflows)
|
||||
const updatedMetadata = { ...metadata, name: uniqueName }
|
||||
@@ -216,6 +220,7 @@ export const useWorkflowRegistry = create<WorkflowRegistry>()(
|
||||
}
|
||||
},
|
||||
|
||||
// Delete workflow and clean up associated storage
|
||||
removeWorkflow: (id: string) => {
|
||||
set((state) => {
|
||||
const newWorkflows = { ...state.workflows }
|
||||
@@ -277,6 +282,7 @@ export const useWorkflowRegistry = create<WorkflowRegistry>()(
|
||||
})
|
||||
},
|
||||
|
||||
// Update workflow metadata
|
||||
updateWorkflow: (id: string, metadata: Partial<WorkflowMetadata>) => {
|
||||
set((state) => {
|
||||
const workflow = state.workflows[id]
|
||||
@@ -305,25 +311,7 @@ export const useWorkflowRegistry = create<WorkflowRegistry>()(
|
||||
)
|
||||
)
|
||||
|
||||
const generateUniqueName = (existingWorkflows: Record<string, WorkflowMetadata>): string => {
|
||||
// Extract numbers from existing workflow names using regex
|
||||
const numbers = Object.values(existingWorkflows)
|
||||
.map((w) => {
|
||||
const match = w.name.match(/Workflow (\d+)/)
|
||||
return match ? parseInt(match[1]) : 0
|
||||
})
|
||||
.filter((n) => n > 0)
|
||||
|
||||
if (numbers.length === 0) {
|
||||
return 'Workflow 1'
|
||||
}
|
||||
|
||||
// Find the maximum number and add 1
|
||||
const nextNumber = Math.max(...numbers) + 1
|
||||
return `Workflow ${nextNumber}`
|
||||
}
|
||||
|
||||
// Initialize registry from localStorage
|
||||
// Initialize registry from localStorage and set up persistence
|
||||
const initializeRegistry = () => {
|
||||
const savedRegistry = localStorage.getItem('workflow-registry')
|
||||
if (savedRegistry) {
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import { WorkflowMetadata } from './types'
|
||||
|
||||
export function generateUniqueName(existingWorkflows: Record<string, WorkflowMetadata>): string {
|
||||
// Extract numbers from existing workflow names using regex
|
||||
const numbers = Object.values(existingWorkflows)
|
||||
.map((w) => {
|
||||
const match = w.name.match(/Workflow (\d+)/)
|
||||
return match ? parseInt(match[1]) : 0
|
||||
})
|
||||
.filter((n) => n > 0)
|
||||
|
||||
if (numbers.length === 0) {
|
||||
return 'Workflow 1'
|
||||
}
|
||||
|
||||
// Find the maximum number and add 1
|
||||
const nextNumber = Math.max(...numbers) + 1
|
||||
return `Workflow ${nextNumber}`
|
||||
}
|
||||
Reference in New Issue
Block a user