`;
dashboardGrid.appendChild(card);
});
}
function renderVmTable() {
vmTableBody.innerHTML = '';
vms.forEach(vm => {
const row = document.createElement('tr');
row.innerHTML = `
${vm.name} |
${vm.ip} |
${vm.status} |
|
`;
vmTableBody.appendChild(row);
});
}
// --- EVENT HANDLERS & GLOBAL FUNCTIONS ---
addVmForm.addEventListener('submit', (e) => {
e.preventDefault();
const vmId = document.getElementById('vm-id').value;
const vmData = {
name: document.getElementById('vm-name').value,
os: document.getElementById('vm-os').value,
ip: document.getElementById('vm-ip').value,
region: document.getElementById('vm-region').value,
};
if (vmId) { // Update existing
const index = vms.findIndex(v => v.id == vmId);
vms[index] = { ...vms[index], ...vmData };
} else { // Add new
const newId = vms.length > 0 ? Math.max(...vms.map(v => v.id)) + 1 : 1;
vms.push({ ...vmData, id: newId, status: 'Stopped', cpu: 0, ram: 0, storage: 20 });
}
cancelEdit();
renderAll();
});
window.editVm = (id) => {
const vm = vms.find(v => v.id === id);
if (!vm) return;
document.getElementById('vm-id').value = vm.id;
document.getElementById('vm-name').value = vm.name;
document.getElementById('vm-os').value = vm.os;
document.getElementById('vm-ip').value = vm.ip;
document.getElementById('vm-region').value = vm.region;
configFormTitle.textContent = 'Edit Virtual Machine';
submitVmBtn.textContent = 'Update VM';
cancelEditBtn.classList.remove('hidden');
};
window.cancelEdit = () => {
addVmForm.reset();
document.getElementById('vm-id').value = '';
configFormTitle.textContent = 'Add a New Virtual Machine';
submitVmBtn.textContent = 'Add VM';
cancelEditBtn.classList.add('hidden');
};
window.deleteVm = (id) => {
if (confirm('Are you sure you want to delete this VM?')) {
vms = vms.filter(v => v.id !== id);
renderAll();
}
};
window.controlVm = (id, action) => {
const vm = vms.find(v => v.id === id);
if (!vm) return;
const updateStatus = (newStatus, cpu, ram) => {
vm.status = newStatus;
vm.cpu = cpu;
vm.ram = ram;
renderDashboard();
};
switch (action) {
case 'start':
updateStatus('Pending', 30, 20);
setTimeout(() => updateStatus('Running', 65, 45), 1500);
break;
case 'stop':
updateStatus('Pending', 30, 20);
setTimeout(() => updateStatus('Stopped', 0, 0), 1500);
break;
case 'restart':
updateStatus('Pending', 30, 20);
setTimeout(() => updateStatus('Running', 65, 45), 2500);
break;
}
};
window.showTab = (tabName) => {
currentTab = tabName;
['dashboard', 'config'].forEach(t => {
document.getElementById(`${t}-tab`).classList.add('hidden');
document.getElementById(`tab-${t}-btn`).classList.replace('active', 'inactive');
});
document.getElementById(`${tabName}-tab`).classList.remove('hidden');
document.getElementById(`tab-${tabName}-btn`).classList.replace('inactive', 'active');
updateNavButtons();
};
window.navigateTabs = (direction) => {
const tabOrder = ['dashboard', 'config'];
const currentIndex = tabOrder.indexOf(currentTab);
let newIndex = currentIndex;
if (direction === 'next' && currentIndex < tabOrder.length - 1) newIndex++;
else if (direction === 'prev' && currentIndex > 0) newIndex--;
showTab(tabOrder[newIndex]);
};
function updateNavButtons() {
document.getElementById('prev-btn').disabled = (currentTab === 'dashboard');
document.getElementById('next-btn').disabled = (currentTab === 'config');
}
window.downloadPDF = async () => {
const { jsPDF } = window.jspdf;
const content = document.getElementById('pdf-content');
const title = document.createElement('h2');
title.className = 'text-xl font-bold mb-4 text-center';
title.innerText = 'Virtual Machine Status Report';
content.prepend(title);
try {
const canvas = await html2canvas(content, { scale: 2, useCORS: true, backgroundColor: '#ffffff' });
title.remove(); // Clean up title after canvas is created
const imgData = canvas.toDataURL('image/png');
const pdf = new jsPDF({
orientation: 'portrait',
unit: 'px',
format: [canvas.width, canvas.height]
});
pdf.addImage(imgData, 'PNG', 0, 0, canvas.width, canvas.height);
pdf.save('VM_Dashboard_Report.pdf');
} catch (error) {
console.error('Error generating PDF:', error);
title.remove();
}
};
// --- INITIALIZATION ---
renderAll();
updateNavButtons();
});