Ermöglicht Analysis Nodes zwischen zwei Prompt-Modi zu wählen: - Reference Mode: Basis-Prompt aus DB referenzieren (bestehend) - Inline Mode: Template direkt im Node editieren (NEU) Frontend: - InlineTemplateEditor Component (~80 Zeilen) - Radio Buttons in WorkflowEditorPage für Mode-Auswahl - Placeholder Picker für beide Modi (End Node + Inline Template) - Cursor-Position Tracking mit textareaRef - Conditional Rendering basierend auf promptSource - Validation: Entweder prompt_slug ODER inline_template Backend: - load_prompt_template() akzeptiert ganzen WorkflowNode (statt nur slug) - Unterstützt inline_template (Mode 1) und prompt_slug (Mode 2) - WorkflowNode.inline_template Feld hinzugefügt - Validation: HTTPException wenn weder slug noch template Serialization: - inline_template in graph_data speichern/laden - Backward-compatible mit bestehenden Workflows Version: 0.9q Module: workflow 0.7.0 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
70 lines
2.1 KiB
JavaScript
70 lines
2.1 KiB
JavaScript
import { useRef } from 'react'
|
|
|
|
/**
|
|
* InlineTemplateEditor - Template-Editor für Inline-Prompts
|
|
*
|
|
* Props:
|
|
* - value: Template-String
|
|
* - onChange: (template) => void
|
|
* - onPlaceholderPick: () => void - Öffnet Placeholder Picker
|
|
* - textareaRef: Ref für Cursor-Position (von Parent)
|
|
*/
|
|
export function InlineTemplateEditor({ value, onChange, onPlaceholderPick, textareaRef }) {
|
|
return (
|
|
<div className="inline-template-editor" style={{ marginTop: '12px' }}>
|
|
<label className="form-label">Template</label>
|
|
<div style={{ position: 'relative' }}>
|
|
<textarea
|
|
ref={textareaRef}
|
|
value={value || ''}
|
|
onChange={(e) => onChange(e.target.value)}
|
|
placeholder="Analysiere folgende Daten: Gewicht: {{ weight_current }} Ziel: {{ goal_weight }} Gib eine Empfehlung..."
|
|
rows={12}
|
|
style={{
|
|
width: '100%',
|
|
fontFamily: 'monospace',
|
|
fontSize: '13px',
|
|
padding: '12px',
|
|
paddingRight: '120px', // Platz für Button
|
|
borderRadius: '8px',
|
|
border: '1px solid var(--border)',
|
|
background: 'var(--bg)',
|
|
color: 'var(--text1)',
|
|
resize: 'vertical',
|
|
lineHeight: '1.5'
|
|
}}
|
|
/>
|
|
<button
|
|
className="btn-secondary"
|
|
onClick={onPlaceholderPick}
|
|
style={{
|
|
position: 'absolute',
|
|
top: '8px',
|
|
right: '8px',
|
|
fontSize: '11px',
|
|
padding: '6px 10px',
|
|
whiteSpace: 'nowrap'
|
|
}}
|
|
>
|
|
{'{{ }}'} Platzhalter
|
|
</button>
|
|
</div>
|
|
<div
|
|
className="help-text"
|
|
style={{
|
|
fontSize: '12px',
|
|
color: 'var(--text3)',
|
|
marginTop: '6px'
|
|
}}
|
|
>
|
|
💡 Tipp: Verwende <code style={{
|
|
background: 'var(--surface2)',
|
|
padding: '2px 6px',
|
|
borderRadius: '4px',
|
|
fontFamily: 'monospace'
|
|
}}>{'{{ placeholder_name }}'}</code> für dynamische Werte
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|