Portal Community

State Shape

// executionStore.ts
export interface ExecutionStoreState {
    executionId        : string | null;
    status             : ExecutionStatus | null;  // 'running' | 'completed' | 'failed' | 'suspended'
    nodeStatuses       : Record<string, NodeExecutionStatus>;
    logs               : LogEntry[];
    selectedNodeId     : string | null;
    nodeInspectorData  : NodeInspectorData | null;
    startedAt          : DateTimeOffset | null;
    completedAt        : DateTimeOffset | null;
    durationMs         : number | null;
    errorMessage       : string | null;
}

Actions

interface ExecutionStoreActions {
    setExecutionId      : (id: string) => void;
    setStatus           : (status: ExecutionStatus) => void;
    setNodeStatus       : (nodeId: string, status: NodeExecutionStatus) => void;
    appendLog           : (entry: LogEntry) => void;
    setSelectedNodeId   : (nodeId: string | null) => void;
    setNodeInspectorData: (data: NodeInspectorData | null) => void;
    setTiming           : (startedAt: DateTimeOffset, completedAt: DateTimeOffset | null) => void;
    resetExecutionStore : () => void;
}

Example State Snapshot

{
  "executionId"  : "exec-abc-123",
  "status"       : "running",
  "startedAt"    : "2026-05-25T09:00:00Z",
  "completedAt"  : null,
  "durationMs"   : null,
  "errorMessage" : null,
  "selectedNodeId": "node-approval",
  "nodeInspectorData": { ... },
  "nodeStatuses" : {
    "node-trigger"  : { "status": "success", "durationMs": 12 },
    "node-approval" : { "status": "suspended" }
  },
  "logs": [
    { "logId": "l1", "nodeId": "node-trigger", "level": "Info", "message": "Trigger received" }
  ]
}
executionStore.nodeStatuses and designerModeStore.nodeStatuses are kept in sync by the useExecutionSignalR hook. Both are updated on every NodeStatusChanged event. Tab components read from executionStore; canvas node overlays read from designerModeStore.