203 lines
7.3 KiB
JavaScript
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();
|
|
});
|
|
});
|
|
});
|
|
} |