diff --git a/public/index.html b/public/index.html
index e29577f..f4a0641 100644
--- a/public/index.html
+++ b/public/index.html
@@ -875,15 +875,15 @@
-
+
-
-
-
-
+
+
+
+
Select 2-5 executions to compare their outputs. Click executions to toggle selection.
@@ -900,8 +900,8 @@
Execute a command on selected workers instantly
-
-
+
+
@@ -929,16 +929,16 @@
Loading workers...
-
-
-
+
+
+
-
+
@@ -950,8 +950,8 @@
⏰ Scheduled Commands
Automate command execution with flexible scheduling
-
-
+
+
@@ -987,7 +987,7 @@
Execution Details
-
+
@@ -996,7 +996,7 @@
Command Templates
-
+
@@ -1005,7 +1005,7 @@
Command History
-
+
@@ -1014,7 +1014,7 @@
⚖️ Execution Comparison
-
+
@@ -1031,7 +1031,7 @@
@@ -1091,8 +1091,8 @@
-
-
+
+
@@ -1215,7 +1215,7 @@
` : ''}
${currentUser && currentUser.isAdmin ? `
-
+
` : ''}
@@ -1292,6 +1292,8 @@
scheduleDesc = `Every ${s.schedule_value} hour(s)`;
} else if (s.schedule_type === 'daily') {
scheduleDesc = `Daily at ${s.schedule_value}`;
+ } else if (s.schedule_type === 'cron') {
+ scheduleDesc = `Cron: ${s.schedule_value}`;
}
const nextRun = s.next_run ? new Date(s.next_run).toLocaleString() : 'Not scheduled';
@@ -1498,7 +1500,7 @@
// Add "Load More" button if there are more executions
if (data.hasMore) {
- const loadMoreBtn = ``;
+ const loadMoreBtn = ``;
document.getElementById('executionList').innerHTML += loadMoreBtn;
}
@@ -1640,13 +1642,13 @@
const instructions = document.getElementById('compareInstructions');
if (compareMode) {
- btn.textContent = '[ ✗ Exit Compare Mode ]';
+ btn.textContent = '✗ Exit Compare Mode';
btn.style.borderColor = 'var(--terminal-amber)';
btn.style.color = 'var(--terminal-amber)';
compareBtn.style.display = 'inline-block';
instructions.style.display = 'block';
} else {
- btn.textContent = '[ 📊 Compare Mode ]';
+ btn.textContent = '📊 Compare Mode';
btn.style.borderColor = '';
btn.style.color = '';
compareBtn.style.display = 'none';
@@ -1672,9 +1674,9 @@
// Update compare button text
const compareBtn = document.getElementById('compareBtn');
if (selectedExecutions.size >= 2) {
- compareBtn.textContent = `[ ⚖️ Compare Selected (${selectedExecutions.size}) ]`;
+ compareBtn.textContent = `⚖️ Compare Selected (${selectedExecutions.size})`;
} else {
- compareBtn.textContent = '[ ⚖️ Compare Selected ]';
+ compareBtn.textContent = '⚖️ Compare Selected';
}
}
@@ -1999,17 +2001,17 @@
// Abort button (only for running executions)
if (execution.status === 'running') {
- html += ``;
+ html += ``;
}
// 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 += ``;
+ html += ``;
}
// Download logs button
- html += ``;
+ html += ``;
html += '';
@@ -2170,8 +2172,87 @@
`;
}
+ if (log.action === 'dry_run_skipped') {
+ return `
+
+
[${timestamp}]
+
🔍 [DRY RUN] Step ${log.step} Skipped: ${escapeHtml(log.step_name || '')}
+
+ `;
+ }
+
+ if (log.action === 'execution_timeout') {
+ return `
+
+
[${timestamp}]
+
⏱️ Execution Timeout
+
+
${escapeHtml(log.message || 'Execution exceeded maximum allowed time')}
+
+
+ `;
+ }
+
+ if (log.action === 'goto_error') {
+ return `
+
+
[${timestamp}]
+
✗ Goto Error
+
+
Target: ${escapeHtml(String(log.target || ''))}
+
+
+ `;
+ }
+
+ if (log.action === 'step_error') {
+ return `
+
+
[${timestamp}]
+
✗ Step ${log.step} Error: ${escapeHtml(log.step_name || '')}
+
+
Error: ${escapeHtml(log.error || '')}
+
+
+ `;
+ }
+
+ if (log.action === 'workflow_result') {
+ const statusIcon = log.success ? '✓' : '✗';
+ const statusClass = log.success ? 'success' : 'failed';
+ return `
+
+
[${timestamp}]
+
${statusIcon} Workflow Result: ${log.success ? 'Success' : 'Failed'}
+ ${log.message ? `
${escapeHtml(log.message)}
` : ''}
+
+ `;
+ }
+
+ if (log.action === 'params') {
+ const paramStr = Object.entries(log.params || {}).map(([k, v]) => `${escapeHtml(k)}=${escapeHtml(String(v))}`).join(', ');
+ return `
+
+
[${timestamp}]
+
⚙ Parameters: ${paramStr || '(none)'}
+
+ `;
+ }
+
+ if (log.action === 'server_restart_recovery') {
+ return `
+
+
[${timestamp}]
+
⚠️ Server Restart Recovery
+
+
${escapeHtml(log.message || 'Execution interrupted by server restart')}
+
+
+ `;
+ }
+
// Fallback for unknown log types
- return `${JSON.stringify(log, null, 2)} `;
+ return `[${timestamp}]
${escapeHtml(log.action || 'unknown')}
`;
}
function escapeHtml(text) {