Backup Performance Dashboard
No failures in selected period.
';
} else {
failuresContainer.innerHTML = recentFailures.map(f => `
${f.Server}
${new Date(f.Date).toLocaleString()}
`).join('');
}
renderCharts(data);
}
function renderCharts(data) {
const statusCounts = data.reduce((acc, d) => { acc[d.Status] = (acc[d.Status] || 0) + 1; return acc; }, {});
const statusCtx = document.getElementById('bpd-status-chart').getContext('2d');
if(charts.status) charts.status.destroy();
charts.status = new Chart(statusCtx, {
type: 'doughnut',
data: {
labels: Object.keys(statusCounts),
datasets: [{
data: Object.values(statusCounts),
backgroundColor: Object.keys(statusCounts).map(s => s === 'Success' ? '#16a34a' : s === 'Failed' ? '#ef4444' : s === 'Warning' ? '#f59e0b' : '#3b82f6')
}]
},
options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { position: 'bottom', labels: { color: '#c9d1d9' } } } }
});
}
function renderJobsTable() {
const table = document.getElementById('jobs-table');
const headers = ['Date', 'Server/System', 'Job Name', 'Status', 'Size (GB)', 'Duration (min)'];
table.innerHTML = `
${headers.map(h=>`| ${h} | `).join('')}Actions |
${backupData.sort((a,b)=>new Date(b.Date)-new Date(a.Date)).map(d => `
|
|
|
|
|
|
|
`).join('')}
`;
}
function addJob() {
backupData.unshift({ id: Date.now(), Date: new Date().toISOString().split('T')[0], Server: 'New Server', Job: 'New Job', Status: 'Success', Size: 0, Duration: 0 });
renderAll();
}
function handleTableEvents(e) {
const target = e.target; if (!target) return;
const id = parseInt(target.closest('tr')?.dataset.id); if (!id) return;
if (target.classList.contains('remove-job-btn')) {
backupData = backupData.filter(d => d.id !== id);
} else if (target.tagName === 'INPUT' || target.tagName === 'SELECT') {
const key = target.dataset.key;
const item = backupData.find(d => d.id === id);
if (item) item[key] = (target.type === 'number') ? parseFloat(target.value) || 0 : target.value;
}
renderAll();
}
document.getElementById('bpd-add-job-btn').addEventListener('click', addJob);
document.getElementById('jobs-table').addEventListener('change', handleTableEvents);
document.getElementById('jobs-table').addEventListener('click', handleTableEvents);
allControls.forEach(input => input.addEventListener('change', renderAll));
function initialize() {
const today = new Date("2025-07-05");
const oneWeekAgo = new Date(today);
oneWeekAgo.setDate(today.getDate() - 7);
document.getElementById('start-date').value = oneWeekAgo.toISOString().split('T')[0];
document.getElementById('end-date').value = today.toISOString().split('T')[0];
let data = [];
const servers = ['DB-PROD-01', 'FILE-SERVER-01', 'WEB-APP-01', 'AD-CONTROLLER'];
for (let i = 0; i < 7; i++) {
const date = new Date(today);
date.setDate(today.getDate() - i);
servers.forEach(server => {
const isFailure = Math.random() < 0.05;
data.push({
id: Date.now() + data.length, Date: date.toISOString().split('T')[0], Server: server,
Job: `${server}-Backup`, Status: isFailure ? 'Failed' : 'Success',
Size: 100 + Math.floor(Math.random() * 400),
Duration: 15 + Math.floor(Math.random() * 45)
});
});
}
backupData = data;
renderAll();
}
initialize();
});