Files
gh-christianlouis-dmarq/backend/app/static/js/dashboard.js
T

245 lines
8.0 KiB
JavaScript

/**
* Dashboard page functionality
*/
async function renderDashboard() {
// Verify authentication
if (!appState.isAuthenticated) {
router.navigate('/login');
return;
}
const appElement = document.getElementById('app');
// Create dashboard layout
appElement.innerHTML = `
<div class="navbar">
<div class="logo">DMARQ</div>
<div class="user-menu">
<button id="logout-button">Logout</button>
</div>
</div>
<div class="sidebar">
<ul>
<li><a href="/dashboard" data-route>Dashboard</a></li>
<li><a href="/domains" data-route>Domains</a></li>
<li><a href="/reports" data-route>Reports</a></li>
<li><a href="/settings" data-route>Settings</a></li>
</ul>
</div>
<div class="main-content">
<h1>Dashboard</h1>
<div id="loading-dashboard">Loading dashboard data...</div>
<div id="dashboard-content" class="hidden">
<div class="dashboard-stats">
<div class="card">
<h3>Total Domains</h3>
<div id="total-domains" class="stat">-</div>
</div>
<div class="card">
<h3>Total Reports</h3>
<div id="total-reports" class="stat">-</div>
</div>
<div class="card">
<h3>Compliance Rate</h3>
<div id="compliance-rate" class="stat">-</div>
</div>
</div>
<div class="card">
<h2>Compliance Overview</h2>
<div class="chart-container">
<canvas id="compliance-chart"></canvas>
</div>
</div>
<div class="card">
<h2>Recent Reports</h2>
<div id="recent-reports">
<table>
<thead>
<tr>
<th>Domain</th>
<th>Date</th>
<th>Status</th>
</tr>
</thead>
<tbody id="reports-table-body">
</tbody>
</table>
</div>
</div>
</div>
</div>
`;
// Add event listener for logout
document.getElementById('logout-button').addEventListener('click', () => {
api.auth.logout();
});
try {
// Load dashboard data
await loadDashboardData();
} catch (error) {
console.error('Error loading dashboard data:', error);
showError('Failed to load dashboard data');
}
}
async function loadDashboardData() {
try {
// Fetch domains and reports data
const [domainsResponse, reportsResponse] = await Promise.all([
api.domains.getAll(),
api.reports.getAll()
]);
const domains = domainsResponse || [];
const reports = reportsResponse || [];
// Update stats
document.getElementById('total-domains').textContent = domains.length;
document.getElementById('total-reports').textContent = reports.length;
// Calculate compliance rate
const compliantReports = reports.filter(report => report.is_compliant);
const complianceRate = reports.length > 0
? Math.round((compliantReports.length / reports.length) * 100)
: 0;
document.getElementById('compliance-rate').textContent = `${complianceRate}%`;
// Render compliance chart
renderComplianceChart(reports);
// Render recent reports table
renderRecentReports(reports, domains);
// Hide loading, show content
document.getElementById('loading-dashboard').classList.add('hidden');
document.getElementById('dashboard-content').classList.remove('hidden');
} catch (error) {
throw new Error('Failed to load dashboard data');
}
}
function renderComplianceChart(reports) {
if (!reports || reports.length === 0) return;
const canvas = document.getElementById('compliance-chart');
if (!canvas) return;
// Prepare data
const last6Months = [];
const currentDate = new Date();
for (let i = 5; i >= 0; i--) {
const date = new Date(currentDate);
date.setMonth(currentDate.getMonth() - i);
const monthName = date.toLocaleString('default', { month: 'short' });
last6Months.push({
month: monthName,
year: date.getFullYear(),
reports: [],
startDate: new Date(date.getFullYear(), date.getMonth(), 1),
endDate: new Date(date.getFullYear(), date.getMonth() + 1, 0)
});
}
// Group reports by month
reports.forEach(report => {
const reportDate = new Date(report.report_date);
const monthData = last6Months.find(monthInfo =>
reportDate >= monthInfo.startDate && reportDate <= monthInfo.endDate
);
if (monthData) {
monthData.reports.push(report);
}
});
// Calculate compliance rates by month
const complianceData = last6Months.map(monthInfo => {
if (monthInfo.reports.length === 0) return 0;
const compliantCount = monthInfo.reports.filter(report => report.is_compliant).length;
return Math.round((compliantCount / monthInfo.reports.length) * 100);
});
const labels = last6Months.map(monthInfo => `${monthInfo.month} ${monthInfo.year}`);
// Create chart
new Chart(canvas, {
type: 'bar',
data: {
labels: labels,
datasets: [{
label: 'Compliance Rate (%)',
data: complianceData,
backgroundColor: '#3b82f6',
borderColor: '#2563eb',
borderWidth: 1
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
beginAtZero: true,
max: 100,
title: {
display: true,
text: 'Compliance Rate (%)'
}
}
}
}
});
}
function renderRecentReports(reports, domains) {
if (!reports || reports.length === 0) return;
const tableBody = document.getElementById('reports-table-body');
if (!tableBody) return;
// Sort reports by date (newest first) and take last 10
const sortedReports = [...reports]
.sort((a, b) => new Date(b.report_date) - new Date(a.report_date))
.slice(0, 10);
// Create a lookup map for domains
const domainMap = new Map();
domains.forEach(domain => {
domainMap.set(domain.id, domain.domain_name);
});
// Add rows to the table
sortedReports.forEach(report => {
const row = document.createElement('tr');
// Format date
const reportDate = new Date(report.report_date);
const formattedDate = reportDate.toLocaleDateString();
// Get domain name
const domainName = domainMap.get(report.domain_id) || 'Unknown';
row.innerHTML = `
<td>${domainName}</td>
<td>${formattedDate}</td>
<td>${report.is_compliant ?
'<span style="color: green;">Compliant</span>' :
'<span style="color: red;">Non-compliant</span>'
}</td>
`;
tableBody.appendChild(row);
});
}