diff --git a/public/assets/js/server-show.js b/public/assets/js/server-show.js index 7ba0230..a667c15 100644 --- a/public/assets/js/server-show.js +++ b/public/assets/js/server-show.js @@ -152,9 +152,10 @@ function confirmAgentAction() { closeAgentModal(); - fetch('/servers/serverId/agent/' + action, { + fetch('/servers/' + serverId + '/agent/' + action, { method: 'POST', headers: { + 'Accept': 'application/json', 'Content-Type': 'application/x-www-form-urlencoded', 'X-CSRF-Token': getCsrfToken(), }, @@ -192,9 +193,10 @@ function copyAgentKey() { function regenerateAgentKey() { if (!confirm('Regenerate agent key? The current key will stop working immediately.')) return; - fetch('/servers/serverId/agent/regenerate-key', { + fetch('/servers/' + serverId + '/agent/regenerate-key', { method: 'POST', headers: { + 'Accept': 'application/json', 'Content-Type': 'application/x-www-form-urlencoded', 'X-CSRF-Token': getCsrfToken(), }, @@ -221,9 +223,10 @@ function serverAction(action) { if (!confirm('Are you sure you want to ' + action + ' this server?')) return; } - fetch('/servers/serverId/' + action, { + fetch('/servers/' + serverId + '/' + action, { method: 'POST', headers: { + 'Accept': 'application/json', 'Content-Type': 'application/x-www-form-urlencoded', 'X-CSRF-Token': getCsrfToken(), }, @@ -240,9 +243,10 @@ function restartService() { const service = prompt('Enter service name to restart (e.g., nginx, mysql, apache2):'); if (!service) return; - fetch('/servers/serverId/restart-service', { + fetch('/servers/' + serverId + '/restart-service', { method: 'POST', headers: { + 'Accept': 'application/json', 'Content-Type': 'application/x-www-form-urlencoded', 'X-CSRF-Token': getCsrfToken(), }, @@ -256,7 +260,9 @@ function restartService() { } function refreshMetrics() { - fetch('/servers/serverId/metrics') + fetch('/servers/' + serverId + '/metrics', { + headers: { 'Accept': 'application/json' }, + }) .then(r => r.json()) .then(data => { if (data.success && data.data) { @@ -303,9 +309,10 @@ function saveThresholds() { document.querySelector('#thresholdModal .btn-primary').disabled = true; - fetch('/servers/serverId/thresholds', { + fetch('/servers/' + serverId + '/thresholds', { method: 'POST', headers: { + 'Accept': 'application/json', 'Content-Type': 'application/x-www-form-urlencoded', 'X-CSRF-Token': getCsrfToken(), }, diff --git a/public/assets/js/terminal.js b/public/assets/js/terminal.js index bbcd415..bafc71a 100644 --- a/public/assets/js/terminal.js +++ b/public/assets/js/terminal.js @@ -12,6 +12,12 @@ terminalInput.addEventListener('keydown', function(e) { } }); +function escapeHtml(str) { + const d = document.createElement('div'); + d.textContent = str; + return d.innerHTML; +} + function executeCommand() { const command = terminalInput.value.trim(); if (!command) return; @@ -27,6 +33,7 @@ function executeCommand() { fetch('/terminal/' + serverId + '/execute', { method: 'POST', headers: { + 'Accept': 'application/json', 'Content-Type': 'application/x-www-form-urlencoded', 'X-CSRF-Token': getCsrfToken(), }, @@ -45,6 +52,9 @@ function executeCommand() { if (data.stderr) { appendTerminalLine(data.stderr, 'error'); } + if (data.history) { + appendHistoryRow(data.history); + } updateStatus('connected', 'Connected'); } else { appendTerminalLine(data.message || 'Command failed', 'error'); @@ -83,6 +93,23 @@ function clearTerminal() { terminalOutput.innerHTML = ''; } +function appendHistoryRow(h) { + const tbody = document.querySelector('.card-body .table tbody'); + if (!tbody) return; + const emptyState = tbody.closest('.card-body')?.querySelector('.empty-state'); + if (emptyState) emptyState.remove(); + const row = document.createElement('tr'); + const time = h.executed_at ? new Date(h.executed_at.replace(' ', 'T')).toLocaleTimeString('en-US', { hour12: false }) : ''; + row.innerHTML = + '
' + escapeHtml(h.command) + '