document.addEventListener('DOMContentLoaded', function () { const ipv4Ctx = document.getElementById('ipv4RoutesChart').getContext('2d'); const ipv6Ctx = document.getElementById('ipv6RoutesChart').getContext('2d'); let ipv4Chart, ipv6Chart; let currentRange = '24h'; const timeRangeButtons = document.querySelectorAll('.btn-group .btn'); timeRangeButtons.forEach(button => { button.addEventListener('click', () => { currentRange = button.getAttribute('data-range'); timeRangeButtons.forEach(btn => btn.classList.remove('active')); button.classList.add('active'); fetchDataAndRenderCharts(currentRange); }); }); function updateChartScale(chartInstance) { const dataset = chartInstance.data.datasets[0]; const validData = (dataset.data || []).filter(val => typeof val === 'number'); let suggestedMin, suggestedMax; if (validData.length > 0) { const minValue = Math.min(...validData); const maxValue = Math.max(...validData); const padding = (maxValue - minValue) * 0.1 || 200; suggestedMin = Math.floor(minValue - padding); suggestedMax = Math.ceil(maxValue + padding); } else { suggestedMin = 0; suggestedMax = 1000; } chartInstance.options.scales.y.min = suggestedMin; chartInstance.options.scales.y.max = suggestedMax; chartInstance.update(); } async function fetchDataAndRenderCharts(range) { try { const response = await fetch(`/history/api/total-routes?range=${range}`); if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`); const data = await response.json(); renderCharts(data); } catch (error) { console.error('Error fetching chart data:', error); const chartContainers = document.querySelectorAll('.achart-wrapper-chart'); if (chartContainers) { chartContainers.forEach(container => { container.innerHTML = '
Could not load chart data.
'; }); } } } function renderCharts(data) { if (ipv4Chart) ipv4Chart.destroy(); if (ipv6Chart) ipv6Chart.destroy(); const findLastValue = (arr) => { for (let i = arr.length - 1; i >= 0; i--) { if (arr[i] !== null && typeof arr[i] !== 'undefined') { return arr[i]; } } return 'N/A'; }; const ipv4LastValue = findLastValue(data.ipv4_routes); const ipv6LastValue = findLastValue(data.ipv6_routes); const ipv4Label = `Total IPv4 Routes: ${ipv4LastValue.toLocaleString()}`; const ipv6Label = `Total IPv6 Routes: ${ipv6LastValue.toLocaleString()}`; const commonOptions = { responsive: true, maintainAspectRatio: false, interaction: { intersect: false, mode: 'index', }, scales: { x: { type: 'time', time: { unit: 'minute', stepSize: 30, displayFormats: { minute: 'HH:mm', hour: 'HH:mm' } } }, y: { } }, plugins: { legend: { position: 'top', }, tooltip: { callbacks: { title: function(context) { if (!context[0]) return ''; return new Date(context[0].parsed.x).toLocaleString([], { year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit', hour12: false }); }, label: function(context) { let label = context.dataset.label.split(':')[0] || ''; if (label) label += ': '; if (context.parsed.y !== null) { label += context.parsed.y.toLocaleString(); } return label; } } } } }; ipv4Chart = new Chart(ipv4Ctx, { type: 'line', data: { labels: data.labels, datasets: [ { label: ipv4Label, data: data.ipv4_routes, borderColor: 'rgb(54, 162, 235)', borderWidth: 1.5, pointRadius: 2, pointHoverRadius: 5, spanGaps: true, fill: true, backgroundColor: 'rgba(54, 162, 235, 0.1)', } ] }, options: { ...commonOptions } }); ipv6Chart = new Chart(ipv6Ctx, { type: 'line', data: { labels: data.labels, datasets: [ { label: ipv6Label, data: data.ipv6_routes, borderColor: 'rgb(255, 99, 132)', borderWidth: 1.5, pointRadius: 2, pointHoverRadius: 5, spanGaps: true, fill: true, backgroundColor: 'rgba(255, 99, 132, 0.1)', } ] }, options: { ...commonOptions } }); updateChartScale(ipv4Chart); updateChartScale(ipv6Chart); } fetchDataAndRenderCharts(currentRange); });