debug: Add comprehensive console logging for workflow editor debugging
All checks were successful
Deploy Development / deploy (push) Successful in 50s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 14s

Debug Logs Added:
- useEffect: Log ID validation and loadWorkflow calls
- loadWorkflow: Log API response, graph_data, deserialization results
- handleNodeUpdate: Log updates and resulting node state
- handleSave: Log serialization, API calls, navigation

Bug Fixes:
- useEffect: Add !isNaN(parseInt(id)) check to prevent /api/prompts/NaN calls
- Prompt selection: String conversion for value prop (Number vs String mismatch)
  - <select value={String(selectedNode.data.prompt_id)}>
  - <option value={String(prompt.id)}>
  - onChange: find with String(p.id) === promptId

Issues to Debug:
- Why does useEffect run with id=undefined after navigate?
- Why does loadWorkflow not populate nodes/edges?
- Why does prompt selection not persist?

Next Step: User tests with Browser Console open, reports logs
This commit is contained in:
Lars 2026-04-04 22:30:43 +02:00
parent 2f70a39052
commit 2b8bebd381

View File

@ -62,8 +62,11 @@ export default function WorkflowEditorPage() {
// Load workflow wenn ID vorhanden // Load workflow wenn ID vorhanden
useEffect(() => { useEffect(() => {
if (id && id !== 'new') { if (id && id !== 'new' && !isNaN(parseInt(id))) {
console.log('🔍 useEffect: Loading workflow with ID:', id)
loadWorkflow(parseInt(id)) loadWorkflow(parseInt(id))
} else if (id && id !== 'new') {
console.error('❌ useEffect: Invalid ID (NaN):', id)
} }
}, [id]) }, [id])
@ -99,9 +102,12 @@ export default function WorkflowEditorPage() {
} }
const handleNodeUpdate = (nodeId, updates) => { const handleNodeUpdate = (nodeId, updates) => {
setNodes((nds) => console.log('🔧 handleNodeUpdate:', { nodeId, updates })
nds.map((n) => (n.id === nodeId ? { ...n, data: { ...n.data, ...updates } } : n)) setNodes((nds) => {
) const updated = nds.map((n) => (n.id === nodeId ? { ...n, data: { ...n.data, ...updates } } : n))
console.log('📝 Nodes after update:', updated.find(n => n.id === nodeId))
return updated
})
} }
const handleDeleteNode = () => { const handleDeleteNode = () => {
@ -113,6 +119,7 @@ export default function WorkflowEditorPage() {
} }
const handleSave = async () => { const handleSave = async () => {
console.log('💾 handleSave called')
try { try {
setLoading(true) setLoading(true)
setError(null) setError(null)
@ -129,9 +136,11 @@ export default function WorkflowEditorPage() {
created_at: currentPrompt?.created_at, created_at: currentPrompt?.created_at,
version: '1.0' version: '1.0'
}) })
console.log('📊 Serialized graph_data:', graph_data)
if (currentPrompt) { if (currentPrompt) {
// Update existing // Update existing
console.log('📝 Updating existing workflow:', currentPrompt.id)
await api.updateUnifiedPrompt(currentPrompt.id, { await api.updateUnifiedPrompt(currentPrompt.id, {
type: 'workflow', type: 'workflow',
name: workflowName, name: workflowName,
@ -141,17 +150,21 @@ export default function WorkflowEditorPage() {
alert('Workflow gespeichert!') alert('Workflow gespeichert!')
} else { } else {
// Create new // Create new
console.log('✨ Creating new workflow')
const result = await api.createUnifiedPrompt({ const result = await api.createUnifiedPrompt({
type: 'workflow', type: 'workflow',
name: workflowName, name: workflowName,
description: workflowDescription, description: workflowDescription,
graph_data graph_data
}) })
console.log('✅ Workflow created:', result)
setCurrentPrompt({ id: result.id, name: workflowName }) setCurrentPrompt({ id: result.id, name: workflowName })
alert('Workflow erstellt!') alert('Workflow erstellt!')
console.log('🚀 Navigating to:', `/workflow-editor/${result.id}`)
navigate(`/workflow-editor/${result.id}`) navigate(`/workflow-editor/${result.id}`)
} }
} catch (e) { } catch (e) {
console.error('❌ handleSave error:', e)
setError(e.message) setError(e.message)
} finally { } finally {
setLoading(false) setLoading(false)
@ -159,11 +172,14 @@ export default function WorkflowEditorPage() {
} }
const loadWorkflow = async (promptId) => { const loadWorkflow = async (promptId) => {
console.log('📦 loadWorkflow called with:', promptId)
try { try {
setLoading(true) setLoading(true)
setError(null) setError(null)
const prompt = await api.getPrompt(promptId) const prompt = await api.getPrompt(promptId)
console.log('✅ Prompt loaded:', prompt)
console.log('📊 graph_data:', prompt.graph_data)
if (prompt.type !== 'workflow') { if (prompt.type !== 'workflow') {
throw new Error('Nicht ein Workflow') throw new Error('Nicht ein Workflow')
@ -171,6 +187,7 @@ export default function WorkflowEditorPage() {
// Deserialisieren // Deserialisieren
const { nodes: loadedNodes, edges: loadedEdges } = deserializeFromWorkflowGraph(prompt.graph_data) const { nodes: loadedNodes, edges: loadedEdges } = deserializeFromWorkflowGraph(prompt.graph_data)
console.log('🎯 Deserialized:', { nodes: loadedNodes, edges: loadedEdges })
setNodes(loadedNodes) setNodes(loadedNodes)
setEdges(loadedEdges) setEdges(loadedEdges)
@ -184,7 +201,9 @@ export default function WorkflowEditorPage() {
0 0
) )
nodeIdCounter = maxId + 1 nodeIdCounter = maxId + 1
console.log('✅ Workflow loaded successfully, nodes:', loadedNodes.length, 'edges:', loadedEdges.length)
} catch (e) { } catch (e) {
console.error('❌ loadWorkflow error:', e)
setError(e.message) setError(e.message)
} finally { } finally {
setLoading(false) setLoading(false)
@ -393,10 +412,12 @@ export default function WorkflowEditorPage() {
<div className="config-section"> <div className="config-section">
<label>KI-Prompt auswählen</label> <label>KI-Prompt auswählen</label>
<select <select
value={selectedNode.data.prompt_id || ''} value={selectedNode.data.prompt_id ? String(selectedNode.data.prompt_id) : ''}
onChange={(e) => { onChange={(e) => {
const promptId = e.target.value const promptId = e.target.value
const selectedPrompt = availablePrompts.find(p => p.id === parseInt(promptId)) console.log('🎯 Prompt selected:', promptId, 'Type:', typeof promptId)
const selectedPrompt = availablePrompts.find(p => String(p.id) === promptId)
console.log('📋 Selected prompt object:', selectedPrompt)
handleNodeUpdate(selectedNode.id, { handleNodeUpdate(selectedNode.id, {
prompt_id: promptId ? parseInt(promptId) : null, prompt_id: promptId ? parseInt(promptId) : null,
prompt_name: selectedPrompt?.name || null prompt_name: selectedPrompt?.name || null
@ -413,14 +434,14 @@ export default function WorkflowEditorPage() {
> >
<option value="">-- Basis-Prompt wählen --</option> <option value="">-- Basis-Prompt wählen --</option>
{availablePrompts.map(prompt => ( {availablePrompts.map(prompt => (
<option key={prompt.id} value={prompt.id}> <option key={prompt.id} value={String(prompt.id)}>
{prompt.name} {prompt.name}
</option> </option>
))} ))}
</select> </select>
{selectedNode.data.prompt_name && ( {selectedNode.data.prompt_id && (
<div style={{ marginTop: 8, fontSize: 12, color: 'var(--text3)' }}> <div style={{ marginTop: 8, fontSize: 12, color: 'var(--text3)' }}>
Gewählt: {selectedNode.data.prompt_name} Prompt ID: {selectedNode.data.prompt_id} ({selectedNode.data.prompt_name || 'unbekannt'})
</div> </div>
)} )}
</div> </div>