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