Phase 4: Execution detail enhancements with re-run and download

Changes:
- Added "Re-run Command" button to execution details modal
- Added "Download Logs" button to export execution data as JSON
- Re-run automatically switches to Quick Command tab and pre-fills form
- Download includes all execution metadata and logs
- Buttons only show for applicable execution types
- Terminal-themed button styling

Features:
- Re-run: Quickly repeat a previous command on same worker
- Download: Export execution logs for auditing/debugging
- JSON format includes: execution_id, status, timestamps, logs
- Filename includes execution ID and date for easy organization

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-07 22:49:20 -05:00
parent 8152a827e6
commit fff50f19da

View File

@@ -1086,6 +1086,20 @@
}); });
} }
// Add action buttons
html += '<div style="margin-top: 20px; padding-top: 15px; border-top: 1px solid var(--terminal-green); display: flex; gap: 10px;">';
// Re-run button (only for quick commands with command in logs)
const commandLog = execution.logs?.find(l => l.action === 'command_sent');
if (commandLog && commandLog.command) {
html += `<button onclick="rerunCommand('${escapeHtml(commandLog.command)}', '${commandLog.worker_id}')">[ 🔄 Re-run Command ]</button>`;
}
// Download logs button
html += `<button onclick="downloadExecutionLogs('${executionId}')">[ 💾 Download Logs ]</button>`;
html += '</div>';
document.getElementById('executionDetails').innerHTML = html; document.getElementById('executionDetails').innerHTML = html;
const modal = document.getElementById('viewExecutionModal'); const modal = document.getElementById('viewExecutionModal');
modal.dataset.executionId = executionId; modal.dataset.executionId = executionId;
@@ -1169,6 +1183,52 @@
return `${days}d ago`; return `${days}d ago`;
} }
async function rerunCommand(command, workerId) {
if (!confirm(`Re-run command: ${command}?`)) return;
closeModal('viewExecutionModal');
switchTab('quickcommand');
// Set the worker and command
document.getElementById('quickWorkerSelect').value = workerId;
document.getElementById('quickCommand').value = command;
// Scroll to the command field
document.getElementById('quickCommand').scrollIntoView({ behavior: 'smooth' });
}
async function downloadExecutionLogs(executionId) {
try {
const response = await fetch(`/api/executions/${executionId}`);
const execution = await response.json();
// Create downloadable JSON
const data = {
execution_id: executionId,
workflow_name: execution.workflow_name || '[Quick Command]',
status: execution.status,
started_by: execution.started_by,
started_at: execution.started_at,
completed_at: execution.completed_at,
logs: execution.logs
};
// Create blob and download
const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `execution-${executionId}-${new Date().toISOString().split('T')[0]}.json`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
} catch (error) {
console.error('Error downloading logs:', error);
alert('Error downloading execution logs');
}
}
async function respondToPrompt(executionId, response) { async function respondToPrompt(executionId, response) {
try { try {
const res = await fetch(`/api/executions/${executionId}/respond`, { const res = await fetch(`/api/executions/${executionId}/respond`, {