This commit is contained in:
root
2026-02-12 17:14:01 +01:00
parent 2e9692777f
commit 8dfe3393a5
142 changed files with 32622 additions and 2 deletions
+117
View File
@@ -0,0 +1,117 @@
/**
* Live Status Monitor for Container Creation
* Provides real-time updates similar to Proxmox task viewer
*/
class LiveStatusMonitor {
constructor(taskId, logContainer) {
this.taskId = taskId;
this.logContainer = logContainer;
this.pollInterval = 1000; // Poll every second
this.init();
}
init() {
console.log(`Initializing live status for task: ${this.taskId}`);
// Initial request with error handling
$.get(`/manager/task/${this.taskId}/status/`)
.done((data) => {
console.log('Initial status data received:', data);
this.updateDisplay(data);
// Start polling only after successful initial request
this.startPolling();
})
.fail((xhr, status, error) => {
console.error('Failed to get initial status:', error, xhr.responseText);
this.showError(`Failed to connect to live status: ${error}`);
// Still try to start polling in case it's a temporary issue
setTimeout(() => {
this.startPolling();
}, 2000);
});
}
startPolling() {
setInterval(() => {
$.get(`/manager/task/${this.taskId}/status/`)
.done((data) => {
this.updateDisplay(data);
})
.fail((xhr, status, error) => {
console.error('Polling error:', error);
// Don't show error for every polling failure
});
}, this.pollInterval);
}
showError(message) {
const logContent = this.logContainer.querySelector('.live-log-content');
if (logContent) {
logContent.innerHTML = `<div class="error" style="color: red; padding: 10px;">${message}</div>`;
}
}
updateDisplay(data) {
const logContent = this.logContainer.querySelector('.live-log-content');
if (!logContent) return;
const logs = data.logs || {};
const steps = logs.steps || [];
if (steps.length === 0) {
logContent.innerHTML = '<div class="loading">Waiting for status updates...</div>';
return;
}
// Track existing entries to highlight new ones
const existingCount = logContent.querySelectorAll('.log-entry').length;
logContent.innerHTML = '';
steps.forEach((step, index) => {
const entry = this.createLogEntry(step);
if (index >= existingCount) {
entry.classList.add('new');
}
logContent.appendChild(entry);
});
// Auto-scroll to bottom
logContent.scrollTop = logContent.scrollHeight;
}
createLogEntry(step) {
const entry = document.createElement('div');
entry.className = 'log-entry';
const timestamp = new Date(step.timestamp).toLocaleTimeString();
const message = step.message || '';
entry.innerHTML = `
<div class="log-timestamp">${timestamp}</div>
<div class="log-message">${this.escapeHtml(message)}</div>
`;
return entry;
}
escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
}
let liveStatus = null;
function initLiveStatus(taskId, containerId) {
const container = document.getElementById(containerId);
if (container && taskId) {
liveStatus = new LiveStatusMonitor(taskId, container);
}
}