34601-vm/assets/js/main.js
2025-10-02 19:19:12 +00:00

203 lines
7.3 KiB
JavaScript

// Main javascript file
document.addEventListener('DOMContentLoaded', function () {
const filters = document.querySelectorAll('select[id^="filter_"]');
filters.forEach(filter => {
filter.addEventListener('change', applyFilters);
});
if (document.getElementById('dateRange')) {
const dateRangePicker = $('#dateRange').daterangepicker({
opens: 'left',
autoUpdateInput: false,
locale: {
cancelLabel: 'Clear'
}
});
dateRangePicker.on('apply.daterangepicker', function(ev, picker) {
$(this).val(picker.startDate.format('YYYY-MM-DD') + ' - ' + picker.endDate.format('YYYY-MM-DD'));
applyFilters();
});
dateRangePicker.on('cancel.daterangepicker', function(ev, picker) {
$(this).val('');
applyFilters();
});
}
// Keep track of chart instances
const charts = {};
function applyFilters() {
const activeFilters = {};
filters.forEach(f => {
if (f.value) {
activeFilters[f.id.replace('filter_', '')] = f.value;
}
});
let filteredData = sampleData.filter(row => {
for (const col in activeFilters) {
if (row[col] != activeFilters[col]) {
return false;
}
}
return true;
});
const dateRange = $('#dateRange').val();
if (dateRange && charts.timeChart) {
const dates = dateRange.split(' - ');
const startDate = moment(dates[0], 'YYYY-MM-DD');
const endDate = moment(dates[1], 'YYYY-MM-DD');
const timeCol = Object.keys(charts.timeChart.data.datasets[0]._meta)[0];
filteredData = filteredData.filter(row => {
const rowDate = moment(row[timeCol], 'YYYY-MM-DD');
return rowDate.isBetween(startDate, endDate, null, '[]');
});
}
updateDashboard(filteredData);
}
function updateDashboard(data) {
updateKpis(data);
updateCharts(data);
updateTable(data);
}
function updateKpis(data) {
// This is a simplified example. It assumes the first KPI is always the one to be updated.
const kpiElements = document.querySelectorAll('.card-text.fs-4');
if (kpiElements.length >= 3) {
kpiElements[0].textContent = data.length;
const kpiCol = document.querySelector('.card-subtitle.mb-2.text-muted').textContent.replace('Avg. ', '').replace('Total ', '');
const total = data.reduce((sum, row) => sum + parseFloat(row[kpiCol] || 0), 0);
const avg = data.length > 0 ? total / data.length : 0;
kpiElements[1].textContent = Math.round(avg * 100) / 100;
kpiElements[2].textContent = total;
}
}
function updateCharts(data) {
if (charts.timeChart) {
const timeCol = charts.timeChart.data.datasets[0].label.replace(' over Time', '');
charts.timeChart.data.labels = data.map(row => row[timeCol]);
charts.timeChart.data.datasets[0].data = data.map(row => row[timeCol]);
charts.timeChart.update();
}
if (charts.categoryChart) {
const catCol = charts.categoryChart.data.datasets[0].label.replace('Top 10 by ', '');
const metCol = charts.categoryChart.data.datasets[0].label.replace('Top 10 by ', '');
const grouped_data = {};
data.forEach(row => {
const category = row[catCol];
if (!grouped_data[category]) {
grouped_data[category] = 0;
}
grouped_data[category] += parseFloat(row[metCol]);
});
const sorted_data = Object.entries(grouped_data).sort(([,a],[,b]) => b-a).slice(0, 10);
charts.categoryChart.data.labels = sorted_data.map(item => item[0]);
charts.categoryChart.data.datasets[0].data = sorted_data.map(item => item[1]);
charts.categoryChart.update();
}
if (charts.histogramChart) {
const metCol = charts.histogramChart.data.datasets[0].label.replace('Histogram of ', '');
charts.histogramChart.data.labels = data.map(row => row[metCol]);
charts.histogramChart.data.datasets[0].data = data.map(row => row[metCol]);
charts.histogramChart.update();
}
}
function updateTable(data) {
const tableBody = document.querySelector('.table-responsive tbody');
tableBody.innerHTML = '';
data.forEach(row => {
const tr = document.createElement('tr');
for (const cell in row) {
const td = document.createElement('td');
td.textContent = row[cell];
tr.appendChild(td);
}
tableBody.appendChild(tr);
});
}
document.getElementById('exportCsv').addEventListener('click', exportToCsv);
function exportToCsv() {
const activeFilters = {};
filters.forEach(f => {
if (f.value) {
activeFilters[f.id.replace('filter_', '')] = f.value;
}
});
let filteredData = sampleData.filter(row => {
for (const col in activeFilters) {
if (row[col] != activeFilters[col]) {
return false;
}
}
return true;
});
const dateRange = $('#dateRange').val();
if (dateRange && charts.timeChart) {
const dates = dateRange.split(' - ');
const startDate = moment(dates[0], 'YYYY-MM-DD');
const endDate = moment(dates[1], 'YYYY-MM-DD');
const timeCol = Object.keys(charts.timeChart.data.datasets[0]._meta)[0];
filteredData = filteredData.filter(row => {
const rowDate = moment(row[timeCol], 'YYYY-MM-DD');
return rowDate.isBetween(startDate, endDate, null, '[]');
});
}
if (filteredData.length === 0) {
alert("No data to export.");
return;
}
const headers = Object.keys(filteredData[0]);
const csvContent = [
headers.join(','),
...filteredData.map(row => headers.map(header => JSON.stringify(row[header])).join(','))
].join('\n');
const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
const link = document.createElement('a');
const url = URL.createObjectURL(blob);
link.setAttribute('href', url);
link.setAttribute('download', 'filtered_data.csv');
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
document.querySelectorAll('.export-png').forEach(button => {
button.addEventListener('click', function() {
const chartId = this.dataset.chart;
const canvas = document.getElementById(chartId);
html2canvas(canvas.parentElement).then(canvas => {
const link = document.createElement('a');
link.download = chartId + '.png';
link.href = canvas.toDataURL();
link.click();
});
});
});
}