document.addEventListener('DOMContentLoaded', function() { // Backend API Basis-URL const API_BASE_URL = 'http://localhost:8000'; // Status-Management let state = { workspaces: [], files: [], currentWorkspace: null, selectedFiles: [], selectedAgents: [], prompt: "", logs: [], results: [], isRunning: false, currentWorkflowId: null }; let activeView = 'workflow'; // Standard-Ansicht beim Start // DOM-Elemente für Menüpunkte const workflowLink = document.querySelector('a[href="#workflow"]').parentElement; const dataLink = document.querySelector('a[href="#data"]').parentElement; const promptsLink = document.querySelector('a[href="#prompts"]').parentElement; const agentsLink = document.querySelector('a[href="#agents"]').parentElement; // DOM-Elemente für die Ansichten const workflowView = document.querySelector('.workflow-container'); const dataView = document.getElementById('data-view'); const promptsView = document.getElementById('prompts-view'); const agentsView = document.getElementById('agents-view'); // DOM-Elemente const workspaceList = document.getElementById('workspace-list'); const availableFiles = document.getElementById('available-files'); const selectedFiles = document.getElementById('selected-files'); const emptyFilesState = document.getElementById('empty-files-state'); const fileInput = document.getElementById('file-input'); const uploadBtn = document.getElementById('upload-btn'); const promptInput = document.getElementById('prompt-input'); const agentList = document.getElementById('agent-list'); const resetBtn = document.getElementById('reset-btn'); const startWorkflowBtn = document.getElementById('start-workflow-btn'); const executionLog = document.getElementById('execution-log'); const resultsContainer = document.getElementById('results-container'); const emptyResultsState = document.getElementById('empty-results-state'); const resultsList = document.getElementById('results-list'); // API-Funktionen async function fetchWorkspaces() { try { const response = await fetch(`${API_BASE_URL}/workspaces`); if (!response.ok) throw new Error('Fehler beim Abrufen der Workspaces'); const workspaces = await response.json(); state.workspaces = workspaces; if (workspaces.length > 0) { state.currentWorkspace = workspaces[0]; } renderWorkspaces(); return workspaces; } catch (error) { console.error('Fehler beim Abrufen der Workspaces:', error); return []; } } async function fetchFiles() { try { const response = await fetch(`${API_BASE_URL}/files`); if (!response.ok) throw new Error('Fehler beim Abrufen der Dateien'); const files = await response.json(); state.files = files; renderFiles(); return files; } catch (error) { console.error('Fehler beim Abrufen der Dateien:', error); return []; } } async function uploadFile(file) { try { const formData = new FormData(); formData.append('file', file); const response = await fetch(`${API_BASE_URL}/files/upload`, { method: 'POST', body: formData }); if (!response.ok) throw new Error('Fehler beim Hochladen der Datei'); const newFile = await response.json(); return newFile; } catch (error) { console.error('Fehler beim Hochladen der Datei:', error); return null; } } async function runWorkflowAPI(workflowData) { try { const response = await fetch(`${API_BASE_URL}/workflow/run`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(workflowData) }); if (!response.ok) throw new Error('Fehler beim Starten des Workflows'); const result = await response.json(); return result; } catch (error) { console.error('Fehler beim Starten des Workflows:', error); return null; } } async function fetchWorkflowStatus(workflowId) { try { const response = await fetch(`${API_BASE_URL}/workflow/${workflowId}/status`); if (!response.ok) throw new Error('Fehler beim Abrufen des Workflow-Status'); const status = await response.json(); return status; } catch (error) { console.error('Fehler beim Abrufen des Workflow-Status:', error); return null; } } async function fetchWorkflowLogs(workflowId) { try { const response = await fetch(`${API_BASE_URL}/workflow/${workflowId}/logs`); if (!response.ok) throw new Error('Fehler beim Abrufen der Workflow-Logs'); const logs = await response.json(); return logs; } catch (error) { console.error('Fehler beim Abrufen der Workflow-Logs:', error); return []; } } async function fetchWorkflowResults(workflowId) { try { const response = await fetch(`${API_BASE_URL}/workflow/${workflowId}/results`); if (!response.ok) throw new Error('Fehler beim Abrufen der Workflow-Ergebnisse'); const results = await response.json(); return results; } catch (error) { console.error('Fehler beim Abrufen der Workflow-Ergebnisse:', error); return []; } } // Funktion zum Wechseln der Ansicht function setActiveView(view) { // Aktive Klasse von allen Menüpunkten entfernen workflowLink.classList.remove('active'); dataLink.classList.remove('active'); promptsLink.classList.remove('active'); agentsLink.classList.remove('active'); // Alle Ansichten ausblenden workflowView.style.display = 'none'; dataView.style.display = 'none'; promptsView.style.display = 'none'; agentsView.style.display = 'none'; // Aktive Ansicht und Menüpunkt setzen activeView = view; switch (view) { case 'workflow': workflowLink.classList.add('active'); workflowView.style.display = 'flex'; break; case 'data': dataLink.classList.add('active'); dataView.style.display = 'block'; // Aktualisiere Daten bei Ansichtswechsel fetchFiles(); break; case 'prompts': promptsLink.classList.add('active'); promptsView.style.display = 'block'; // Prompts laden wenn wir die Ansicht wechseln if (state.currentWorkspace) { renderPrompts(); } break; case 'agents': agentsLink.classList.add('active'); agentsView.style.display = 'block'; // Agenten laden wenn wir die Ansicht wechseln if (state.currentWorkspace) { renderAgentsList(); } break; } } // Workspaces rendern function renderWorkspaces() { workspaceList.innerHTML = ''; state.workspaces.forEach(workspace => { const li = document.createElement('li'); li.className = `workspace-item ${workspace.id === state.currentWorkspace?.id ? 'active' : ''}`; li.innerHTML = ` ${workspace.name} `; li.addEventListener('click', async () => { state.currentWorkspace = workspace; state.selectedFiles = []; state.selectedAgents = []; state.prompt = ""; renderWorkspaces(); renderFiles(); renderSelectedFiles(); renderAgents(); }); workspaceList.appendChild(li); }); } // Verfügbare Dateien rendern function renderFiles() { availableFiles.innerHTML = ''; state.files.forEach(file => { const li = document.createElement('li'); li.className = 'file-item'; const isSelected = state.selectedFiles.some(f => f.id === file.id); li.innerHTML = `
${file.size || ''} `; const checkbox = li.querySelector(`#file-${file.id}`); checkbox.addEventListener('change', () => { if (checkbox.checked) { state.selectedFiles.push(file); } else { state.selectedFiles = state.selectedFiles.filter(f => f.id !== file.id); } renderSelectedFiles(); }); availableFiles.appendChild(li); }); } // Ausgewählte Dateien rendern function renderSelectedFiles() { if (state.selectedFiles.length === 0) { emptyFilesState.style.display = 'flex'; selectedFiles.innerHTML = ''; } else { emptyFilesState.style.display = 'none'; selectedFiles.innerHTML = ''; state.selectedFiles.forEach(file => { const li = document.createElement('li'); li.className = 'selected-file-item'; li.innerHTML = `
${file.name}
`; selectedFiles.appendChild(li); }); // Event-Listener für Entfernen-Buttons document.querySelectorAll('.remove-file-btn').forEach(btn => { btn.addEventListener('click', () => { const fileId = btn.getAttribute('data-id'); state.selectedFiles = state.selectedFiles.filter(f => f.id !== fileId); renderSelectedFiles(); renderFiles(); }); }); } } // Prompts rendern function renderPrompts() { const promptsContainer = document.getElementById('prompts-list'); if (!promptsContainer) return; promptsContainer.innerHTML = ''; if (!state.currentWorkspace || !state.currentWorkspace.prompts || state.currentWorkspace.prompts.length === 0) { promptsContainer.innerHTML = '
Keine Prompts im aktuellen Workspace verfügbar.
'; return; } state.currentWorkspace.prompts.forEach(prompt => { const promptItem = document.createElement('div'); promptItem.className = 'prompt-item'; promptItem.innerHTML = `
${prompt.content}
Erstellt am: ${new Date(prompt.created_at).toLocaleString()}
`; // Event-Listener für "Verwenden"-Button const useBtn = promptItem.querySelector('.use-prompt-btn'); useBtn.addEventListener('click', () => { // Prompt zum aktuellen Workflow hinzufügen promptInput.value = prompt.content; state.prompt = prompt.content; setActiveView('workflow'); }); promptsContainer.appendChild(promptItem); }); } // Agentenliste rendern function renderAgentsList() { const agentsContainer = document.getElementById('agents-list-container'); if (!agentsContainer) return; agentsContainer.innerHTML = ''; if (!state.currentWorkspace || !state.currentWorkspace.agents || state.currentWorkspace.agents.length === 0) { agentsContainer.innerHTML = '
Keine Agenten im aktuellen Workspace verfügbar.
'; return; } state.currentWorkspace.agents.forEach(agent => { const agentItem = document.createElement('div'); agentItem.className = 'agent-list-item'; agentItem.innerHTML = `

${agent.name}

${agent.type}
${agent.description || ''}
${agent.capabilities ? agent.capabilities.map(cap => `${cap}`).join('') : ''}
`; agentsContainer.appendChild(agentItem); }); } // Agenten für Workflow rendern function renderAgents() { agentList.innerHTML = ''; if (!state.currentWorkspace || !state.currentWorkspace.agents || state.currentWorkspace.agents.length === 0) { agentList.innerHTML = '
Keine Agenten im ausgewählten Workspace verfügbar.
'; return; } state.currentWorkspace.agents.forEach(agent => { const li = document.createElement('li'); li.className = 'agent-item'; const isSelected = state.selectedAgents.some(a => a.id === agent.id); li.innerHTML = `
${agent.description || ''}
`; const checkbox = li.querySelector(`#agent-${agent.id}`); checkbox.addEventListener('change', () => { if (checkbox.checked) { state.selectedAgents.push(agent); } else { state.selectedAgents = state.selectedAgents.filter(a => a.id !== agent.id); } }); agentList.appendChild(li); }); } // Ausführungsprotokoll aktualisieren und rendern function updateLogs(logs) { state.logs = logs; renderLogs(); } // Protokoll rendern function renderLogs() { if (state.logs.length === 0) { executionLog.innerHTML = '
Workflow noch nicht gestartet. Protokoll wird hier angezeigt.
'; return; } executionLog.innerHTML = ''; state.logs.forEach(log => { const logEntry = document.createElement('div'); logEntry.className = 'log-entry'; logEntry.innerHTML = ` [${new Date(log.timestamp).toLocaleTimeString()}] ${log.message} `; executionLog.appendChild(logEntry); }); // Zum Ende scrollen executionLog.scrollTop = executionLog.scrollHeight; } // Ergebnisse aktualisieren und rendern function updateResults(results) { state.results = results; renderResults(); } // Ergebnisse rendern function renderResults() { if (state.results.length === 0) { emptyResultsState.style.display = 'flex'; resultsList.style.display = 'none'; return; } emptyResultsState.style.display = 'none'; resultsList.style.display = 'block'; resultsList.innerHTML = ''; state.results.forEach(result => { const resultItem = document.createElement('div'); resultItem.className = 'result-item'; if (result.type === 'text') { resultItem.innerHTML = `
${result.title}
Erstellt von: ${result.agent_name}
${result.content}
`; } else if (result.type === 'chart') { resultItem.innerHTML = `
${result.title}
Erstellt von: ${result.agent_name}
Umsatzentwicklung nach Quartal
${result.content}
`; } resultsList.appendChild(resultItem); }); } // Workflow-Ausführung async function runWorkflow() { if (state.selectedFiles.length === 0 || state.selectedAgents.length === 0 || !promptInput.value.trim()) { alert("Bitte wählen Sie Dateien und Agenten aus und geben Sie einen Prompt ein."); return; } state.isRunning = true; state.prompt = promptInput.value; state.logs = []; state.results = []; startWorkflowBtn.textContent = 'Wird ausgeführt...'; startWorkflowBtn.classList.add('running'); startWorkflowBtn.disabled = true; renderLogs(); renderResults(); // API-Aufruf an das Backend const workflowData = { workspace_id: state.currentWorkspace.id, files: state.selectedFiles.map(file => file.id), agents: state.selectedAgents.map(agent => agent.id), prompt: state.prompt, workflow_name: "Workflow " + new Date().toLocaleString() }; try { // Workflow starten const response = await runWorkflowAPI(workflowData); if (response && response.workflow_id) { state.currentWorkflowId = response.workflow_id; // Polling für Status, Logs und Ergebnisse pollWorkflowStatus(); } else { throw new Error("Workflow konnte nicht gestartet werden"); } } catch (error) { console.error("Fehler beim Starten des Workflows:", error); state.isRunning = false; startWorkflowBtn.textContent = 'Workflow starten'; startWorkflowBtn.classList.remove('running'); startWorkflowBtn.disabled = false; alert("Fehler beim Starten des Workflows: " + error.message); } } // Polling für Workflow-Status, Logs und Ergebnisse async function pollWorkflowStatus() { if (!state.currentWorkflowId || !state.isRunning) return; try { // Status abrufen const status = await fetchWorkflowStatus(state.currentWorkflowId); // Logs abrufen und anzeigen const logs = await fetchWorkflowLogs(state.currentWorkflowId); updateLogs(logs); // Wenn der Workflow abgeschlossen ist, Ergebnisse abrufen if (status && (status.status === 'completed' || status.status === 'failed')) { const results = await fetchWorkflowResults(state.currentWorkflowId); updateResults(results); state.isRunning = false; startWorkflowBtn.textContent = 'Workflow starten'; startWorkflowBtn.classList.remove('running'); startWorkflowBtn.disabled = false; return; // Polling beenden } // Weiteres Polling nach kurzer Verzögerung setTimeout(pollWorkflowStatus, 2000); } catch (error) { console.error("Fehler beim Abrufen des Workflow-Status:", error); state.isRunning = false; startWorkflowBtn.textContent = 'Workflow starten'; startWorkflowBtn.classList.remove('running'); startWorkflowBtn.disabled = false; } } // Zurücksetzen function resetWorkflow() { state.selectedFiles = []; state.selectedAgents = []; promptInput.value = ""; state.prompt = ""; renderFiles(); renderSelectedFiles(); renderAgents(); } // Event-Listener für Menüpunkte workflowLink.addEventListener('click', function(e) { e.preventDefault(); setActiveView('workflow'); }); dataLink.addEventListener('click', function(e) { e.preventDefault(); setActiveView('data'); }); promptsLink.addEventListener('click', function(e) { e.preventDefault(); setActiveView('prompts'); }); agentsLink.addEventListener('click', function(e) { e.preventDefault(); setActiveView('agents'); }); // Event-Listener uploadBtn.addEventListener('click', () => fileInput.click()); fileInput.addEventListener('change', async (e) => { if (e.target.files.length > 0) { // Dateien hochladen for (const file of e.target.files) { try { const newFile = await uploadFile(file); if (newFile) { state.files.push(newFile); state.selectedFiles.push(newFile); } } catch (error) { console.error("Fehler beim Hochladen der Datei:", error); } } renderFiles(); renderSelectedFiles(); fileInput.value = ""; } }); promptInput.addEventListener('input', (e) => { state.prompt = e.target.value; }); resetBtn.addEventListener('click', resetWorkflow); startWorkflowBtn.addEventListener('click', runWorkflow); // Initialisierung async function init() { // Daten vom Backend laden await fetchWorkspaces(); await fetchFiles(); // UI initialisieren renderFiles(); renderSelectedFiles(); renderAgents(); renderLogs(); renderResults(); // Initial die Standard-Ansicht setzen setActiveView(activeView); } // Anwendung initialisieren init(); });