From eada0ef13ab9beb304c7e1a3cce1ce035033aee4 Mon Sep 17 00:00:00 2001 From: Jon Langevin Date: Tue, 10 Feb 2026 13:01:31 -0500 Subject: [PATCH] Fix 3 UI bugs found during exploratory testing - Fix node handle mapping: http.router/handler/proxy were mapped to HTTPServerNode (no input handle), preventing incoming connections. Now only http.server maps to httpNode; other http.* types map to httpRouterNode which has both input and output handles. - Fix dynamic component API field mismatch: createDynamicComponent sent {name} but Go server expects {id}. Changed to {id: name}. - Fix missing undo history for property edits: updateNodeConfig and updateNodeName now call pushHistory() before mutating state, so property changes can be undone with Ctrl+Z. Co-Authored-By: Claude Opus 4.6 --- ui/src/store/workflowStore.ts | 9 ++++++--- ui/src/utils/api.ts | 2 +- ui/src/utils/serialization.ts | 7 ++++--- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/ui/src/store/workflowStore.ts b/ui/src/store/workflowStore.ts index 6429bd05..fcd29164 100644 --- a/ui/src/store/workflowStore.ts +++ b/ui/src/store/workflowStore.ts @@ -182,6 +182,7 @@ const useWorkflowStore = create((set, get) => ({ }, updateNodeConfig: (id, config) => { + get().pushHistory(); set({ nodes: get().nodes.map((n) => n.id === id ? { ...n, data: { ...n.data, config: { ...n.data.config, ...config } } } : n @@ -190,6 +191,7 @@ const useWorkflowStore = create((set, get) => ({ }, updateNodeName: (id, name) => { + get().pushHistory(); set({ nodes: get().nodes.map((n) => n.id === id ? { ...n, data: { ...n.data, label: name } } : n @@ -216,14 +218,15 @@ const useWorkflowStore = create((set, get) => ({ function nodeComponentType(moduleType: string): string { if (moduleType.startsWith('http.middleware.')) return 'middlewareNode'; - if (moduleType.startsWith('http.')) return 'httpNode'; - if (moduleType === 'api.handler') return 'httpNode'; + if (moduleType === 'http.server') return 'httpNode'; + if (moduleType.startsWith('http.')) return 'httpRouterNode'; + if (moduleType === 'api.handler') return 'httpRouterNode'; if (moduleType.startsWith('messaging.')) return 'messagingNode'; if (moduleType.startsWith('statemachine.') || moduleType.startsWith('state.')) return 'stateMachineNode'; if (moduleType === 'scheduler.modular') return 'schedulerNode'; if (moduleType === 'eventlogger.modular' || moduleType === 'eventbus.modular') return 'eventNode'; if (moduleType === 'httpclient.modular') return 'integrationNode'; - if (moduleType === 'chimux.router') return 'httpNode'; + if (moduleType === 'chimux.router') return 'httpRouterNode'; return 'infrastructureNode'; } diff --git a/ui/src/utils/api.ts b/ui/src/utils/api.ts index 7061e216..a660c936 100644 --- a/ui/src/utils/api.ts +++ b/ui/src/utils/api.ts @@ -108,7 +108,7 @@ export async function listDynamicComponents(): Promise { export async function createDynamicComponent(name: string, source: string, language: string): Promise { await apiFetch('/dynamic/components', { method: 'POST', - body: JSON.stringify({ name, source, language }), + body: JSON.stringify({ id: name, source, language }), }); } diff --git a/ui/src/utils/serialization.ts b/ui/src/utils/serialization.ts index 5e8f9929..85cebebc 100644 --- a/ui/src/utils/serialization.ts +++ b/ui/src/utils/serialization.ts @@ -94,14 +94,15 @@ export function configToNodes(config: WorkflowConfig): { function nodeComponentType(moduleType: string): string { if (moduleType.startsWith('http.middleware.')) return 'middlewareNode'; - if (moduleType.startsWith('http.')) return 'httpNode'; - if (moduleType === 'api.handler') return 'httpNode'; + if (moduleType === 'http.server') return 'httpNode'; + if (moduleType.startsWith('http.')) return 'httpRouterNode'; + if (moduleType === 'api.handler') return 'httpRouterNode'; if (moduleType.startsWith('messaging.')) return 'messagingNode'; if (moduleType.startsWith('statemachine.') || moduleType.startsWith('state.')) return 'stateMachineNode'; if (moduleType === 'scheduler.modular') return 'schedulerNode'; if (moduleType === 'eventlogger.modular' || moduleType === 'eventbus.modular') return 'eventNode'; if (moduleType === 'httpclient.modular') return 'integrationNode'; - if (moduleType === 'chimux.router') return 'httpNode'; + if (moduleType === 'chimux.router') return 'httpRouterNode'; return 'infrastructureNode'; }