librelad c920ca2dc9 refactor(webui): align page-controller names with the -page convention
From the feng-shui audit naming findings:
- admin/overview/js/admin-overview.js -> overview-page.js (class AdminOverview ->
  OverviewPage, window globals + the 'admin-overview' task-refresh id ->
  overview-page, lazy-load path + typeof/new in config-manager.js).
- admin/system/js/admin-system.js -> system-page.js (class AdminSystem ->
  SystemPage; now sits beside its -page sub-views system-metric-page.js /
  system-storage-page.js).
- tasks/js/tasks-logs-modal.js -> tasks-log-modal.js (singular 'log' to match its
  sibling tasks-log-stream.js; single path ref in system-loader.js).

These were the only page controllers breaking the dominant <thing>-page.js /
<Thing>Page convention (ssh-page/peers-page/backup-page/updater-page/
system-metric-page/system-storage-page). Pure renames; node --check clean.

Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-31 01:21:07 +01:00

105 lines
4.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Auto-extracted from tasks-manager.js (verbatim) — augments TasksManager.prototype. Loaded after the base.
Object.assign(TasksManager.prototype, {
async viewTaskLogs(taskId) {
// Open logs in a modal or new view
const task = this.tasks.find(t => t.id === taskId);
if (!task) return;
// Load full logs for modal
const fullLogs = await this.taskManager.readFullTaskLog(taskId);
// Create modal with streaming logs
const modal = document.createElement('div');
modal.className = 'task-logs-modal';
modal.innerHTML = `
<div class="modal-overlay" onclick="closeTaskLogsModal()"></div>
<div class="modal-content">
<div class="modal-header">
<h3>📋 Task Logs - ${task.id}</h3>
<div class="log-status">
<span class="status-indicator" id="log-status-${taskId}">Loading...</span>
<button class="log-toggle" id="log-toggle-${taskId}" onclick="toggleLogStreaming('${taskId}')">⏸️ Pause</button>
</div>
<button class="modal-close" onclick="closeTaskLogsModal()">×</button>
</div>
<div class="modal-body">
<div class="task-info-summary">
<div class="info-row">
<strong>Command:</strong> <code>${task.command}</code>
</div>
<div class="info-row">
<strong>Status:</strong> <span class="status-${task.status || 'unknown'}">${this.getStatusIcon(task.status)} ${task.status ? task.status.toUpperCase() : 'UNKNOWN'}</span>
</div>
<div class="info-row">
<strong>Created:</strong> ${new Date(task.createdAt).toLocaleString()}
</div>
</div>
<div class="logs-section">
<h4>Execution Logs <span class="log-line-count">(0 lines)</span></h4>
<div class="log-viewer terminal-style" id="log-viewer-${taskId}">
${fullLogs.split('\n').map(log => `<div class="log-line">${this.taskManager.parseAnsiColors(log)}</div>`).join('')}
</div>
</div>
${task.output ? `
<div class="output-section">
<h4>Command Output</h4>
<pre class="output-viewer">${this.taskManager.parseAnsiColors(task.output)}</pre>
</div>
` : ''}
${task.error ? `
<div class="error-section">
<h4>Error Details</h4>
<pre class="error-viewer">${this.escapeHtml(task.error)}</pre>
</div>
` : ''}
</div>
</div>
`;
document.body.appendChild(modal);
// Update line count
const lineCount = fullLogs.split('\n').length;
const lineCountElement = modal.querySelector('.log-line-count');
if (lineCountElement) {
lineCountElement.textContent = `(${lineCount} lines)`;
}
// Start streaming if task is running
if (task.status === 'running' || task.status === 'queued') {
this.startLogStreaming(taskId, modal);
}
// Store streaming controller
this.activeLogStreams = this.activeLogStreams || new Map();
},
toggleLogStreaming(taskId) {
const streamData = this.activeLogStreams?.get(taskId);
if (!streamData) return;
const toggleButton = document.getElementById(`log-toggle-${taskId}`);
const statusIndicator = document.getElementById(`log-status-${taskId}`);
if (streamData.isPaused) {
// Resume streaming
streamData.isPaused = false;
if (toggleButton) toggleButton.textContent = '⏸️ Pause';
if (statusIndicator) {
statusIndicator.textContent = '🔴 Live';
statusIndicator.className = 'status-indicator live';
}
} else {
// Pause streaming
streamData.isPaused = true;
if (toggleButton) toggleButton.textContent = '▶️ Resume';
if (statusIndicator) {
statusIndicator.textContent = '⏸️ Paused';
statusIndicator.className = 'status-indicator paused';
}
}
},
});