import { useState, useEffect } from 'react' import { api } from '../../../utils/api' /** * PlaceholderPicker - Modal zur Auswahl von Template-Platzhaltern * * Props: * - nodes: Array of workflow nodes (to extract workflow-specific placeholders) * - currentNodeId: ID des aktuellen Nodes (wird aus Placeholders ausgeschlossen) * - onSelect: (placeholderString) => void - Callback when placeholder is selected * - onClose: () => void * * Features: * - Lädt registrierte Platzhalter vom Backend (~120+) * - Extrahiert Workflow-spezifische Node-Outputs * - Filtert Selbst-Referenzierung (Node kann sich nicht selbst referenzieren) * - Zeigt Node-Namen (nicht nur IDs) * - Kategorisiert: System + Workflow * - Suchfunktion über alle Kategorien */ export function PlaceholderPicker({ nodes, currentNodeId, onSelect, onClose }) { const [searchQuery, setSearchQuery] = useState('') const [systemPlaceholders, setSystemPlaceholders] = useState([]) const [loading, setLoading] = useState(true) const [loadError, setLoadError] = useState(null) // Lade Backend-Platzhalter beim Mount useEffect(() => { async function loadPlaceholders() { try { console.log('🔄 Loading placeholders from backend...') const catalog = await api.listPlaceholders() console.log('✅ Catalog received:', catalog) console.log('📊 Catalog keys:', Object.keys(catalog)) // Konvertiere Katalog zu Flat-Liste const flattened = [] Object.entries(catalog).forEach(([category, items]) => { console.log(`📁 Category "${category}": ${items?.length || 0} items`) if (!Array.isArray(items)) { console.warn(`⚠️ Category "${category}" items is not an array:`, items) return } items.forEach(item => { flattened.push({ placeholder: `{{ ${item.key.trim()} }}`, description: item.description || 'Keine Beschreibung', example: item.example || '', category: category, icon: getCategoryIcon(category) }) }) }) console.log(`✅ Loaded ${flattened.length} system placeholders`) setSystemPlaceholders(flattened) } catch (e) { console.error('❌ Failed to load placeholders:', e) setLoadError(e.message) } finally { setLoading(false) } } loadPlaceholders() }, []) // Extrahiere Workflow-spezifische Platzhalter (ohne aktuellen Node) const workflowPlaceholders = extractWorkflowPlaceholders(nodes, currentNodeId) // Kombiniere beide Listen const allPlaceholders = [ ...workflowPlaceholders, ...systemPlaceholders ] // Filtere basierend auf Suchquery const filteredPlaceholders = allPlaceholders.filter(p => p.placeholder.toLowerCase().includes(searchQuery.toLowerCase()) || p.description.toLowerCase().includes(searchQuery.toLowerCase()) || (p.category && p.category.toLowerCase().includes(searchQuery.toLowerCase())) ) // Gruppiere nach Kategorie const grouped = {} filteredPlaceholders.forEach(p => { const cat = p.category || 'Sonstige' if (!grouped[cat]) grouped[cat] = [] grouped[cat].push(p) }) const handleSelect = (placeholderString) => { onSelect(placeholderString) onClose() } return (
{'{{ placeholder_name }}'}