...
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user