ngxstat/templates/index.html

156 lines
5.3 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>ngxstat Reports</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.4/css/bulma.min.css">
<link rel="stylesheet" href="https://cdn.datatables.net/1.13.4/css/jquery.dataTables.min.css">
</head>
<body class="section">
<div class="container">
<h1 class="title">ngxstat Reports</h1>
<div class="field is-grouped">
<div class="control has-icons-left">
<div class="select is-small">
<select id="interval-select">
{% for interval in intervals %}
<option value="{{ interval }}">{{ interval.title() }}</option>
{% endfor %}
</select>
</div>
<span class="icon is-small is-left"><i data-feather="clock"></i></span>
</div>
<div class="control has-icons-left">
<div class="select is-small">
<select id="domain-select">
<option value="">All Domains</option>
{% for domain in domains %}
<option value="{{ domain }}">{{ domain }}</option>
{% endfor %}
</select>
</div>
<span class="icon is-small is-left"><i data-feather="server"></i></span>
</div>
</div>
<div id="overview" class="box mb-5">
<h2 class="subtitle">Overview</h2>
<p>Total logs: <span id="stat-total">-</span></p>
<p>Date range: <span id="stat-start">-</span> to <span id="stat-end">-</span></p>
<p>Unique domains: <span id="stat-domains">-</span></p>
</div>
<div id="reports-container"></div>
</div>
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdn.jsdelivr.net/npm/jquery@3.7.0/dist/jquery.min.js"></script>
<script src="https://cdn.datatables.net/1.13.4/js/jquery.dataTables.min.js"></script>
<script>
const intervalSelect = document.getElementById('interval-select');
const domainSelect = document.getElementById('domain-select');
const container = document.getElementById('reports-container');
const totalElem = document.getElementById('stat-total');
const startElem = document.getElementById('stat-start');
const endElem = document.getElementById('stat-end');
const domainsElem = document.getElementById('stat-domains');
let currentInterval = intervalSelect.value;
let currentDomain = domainSelect.value;
function initReport(rep, base) {
fetch(base + '/' + rep.json)
.then(r => r.json())
.then(data => {
if (rep.chart === 'table') {
const rows = data.map(x => [x.bucket, x.value]);
new DataTable('#table-' + rep.name, {
data: rows,
columns: [
{ title: 'Bucket' },
{ title: 'Value' }
]
});
return;
}
const labels = data.map(x => x.bucket);
const values = data.map(x => x.value);
const chartType = rep.chart === 'stackedBar' ? 'bar' : rep.chart;
const options = { scales: { y: { beginAtZero: true } } };
if (rep.chart === 'stackedBar') {
options.scales.x = { stacked: true };
options.scales.y.stacked = true;
}
const dataset = {
label: rep.label,
data: values,
borderWidth: 1,
fill: rep.chart !== 'bar' && rep.chart !== 'stackedBar'
};
if (rep.colors) {
dataset.backgroundColor = rep.colors;
dataset.borderColor = rep.colors;
} else if (rep.color) {
dataset.backgroundColor = rep.color;
dataset.borderColor = rep.color;
} else {
dataset.backgroundColor = 'rgba(54, 162, 235, 0.5)';
dataset.borderColor = 'rgba(54, 162, 235, 1)';
}
new Chart(document.getElementById('chart-' + rep.name), {
type: chartType,
data: {
labels: labels,
datasets: [dataset]
},
options: options
});
});
}
function loadStats() {
fetch('global/stats.json')
.then(r => r.json())
.then(stats => {
totalElem.textContent = stats.total_logs;
startElem.textContent = stats.start_date;
endElem.textContent = stats.end_date;
domainsElem.textContent = stats.unique_domains;
});
}
function loadReports() {
let path = currentInterval;
if (currentDomain) {
path = 'domains/' + currentDomain + '/' + currentInterval;
}
fetch(path + '/reports.json')
.then(r => r.json())
.then(reports => {
container.innerHTML = '';
reports.forEach(rep => {
fetch(path + '/' + rep.html)
.then(r => r.text())
.then(html => {
container.insertAdjacentHTML('beforeend', html);
initReport(rep, path);
});
});
});
}
intervalSelect.addEventListener('change', () => {
currentInterval = intervalSelect.value;
loadReports();
});
domainSelect.addEventListener('change', () => {
currentDomain = domainSelect.value;
loadReports();
});
loadReports();
loadStats();
feather.replace();
</script>
</body>
</html>