Ajout de la fonctionnalité d’activité en direct dans le tableau de bord des statistiques et mise à jour des templates, vues, URL, et styles associés.
This commit is contained in:
parent
a7b51e3a82
commit
7cf04968eb
6 changed files with 114 additions and 2 deletions
|
|
@ -20,7 +20,9 @@
|
|||
{% block content %}
|
||||
<div class="container">
|
||||
<h1>Tableau de bord statistiques</h1>
|
||||
<p style="margin:8px 0"><a href="{% url 'home:stats_charts' %}">→ Voir la page de graphiques</a></p>
|
||||
<p style="margin:8px 0">
|
||||
<a href="{% url 'home:stats_charts' %}">→ Voir la page de graphiques</a>
|
||||
</p>
|
||||
|
||||
<form method="get" class="toolbar">
|
||||
<div>
|
||||
|
|
@ -90,6 +92,20 @@
|
|||
</div>
|
||||
</section>
|
||||
|
||||
<section class="tables" id="live-activity">
|
||||
<div class="card" style="grid-column: 1 / -1;">
|
||||
<h3>Activité en direct (5 dernières minutes)</h3>
|
||||
<table id="live-activity-table" style="width:100%">
|
||||
<thead>
|
||||
<tr><th>Type</th><th>Identité</th><th>Page</th><th>Il y a</th><th>Source</th><th>Pays</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr id="live-empty"><td colspan="6">Chargement…</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="charts">
|
||||
<div class="card">
|
||||
<h3>Évolution quotidienne</h3>
|
||||
|
|
@ -173,5 +189,43 @@
|
|||
plugins: {legend: {position: 'bottom'}}
|
||||
}
|
||||
});
|
||||
|
||||
// Live activity polling
|
||||
function humanizeSeconds(s) {
|
||||
if (s < 60) return s + 's';
|
||||
const m = Math.floor(s/60); const r = s % 60;
|
||||
if (m < 60) return m + 'm' + (r?(' '+r+'s'):'');
|
||||
const h = Math.floor(m/60); const mr = m % 60; return h + 'h' + (mr?(' '+mr+'m'):'');
|
||||
}
|
||||
async function fetchLive() {
|
||||
try {
|
||||
const res = await fetch('{% url "home:live_activity" %}', {headers: {'Accept': 'application/json'}});
|
||||
if (!res.ok) throw new Error('HTTP '+res.status);
|
||||
const payload = await res.json();
|
||||
const tbody = document.querySelector('#live-activity-table tbody');
|
||||
tbody.innerHTML = '';
|
||||
const items = payload.items || [];
|
||||
if (items.length === 0) {
|
||||
const tr = document.createElement('tr');
|
||||
const td = document.createElement('td'); td.colSpan = 6; td.textContent = 'Aucune activité récente';
|
||||
tr.appendChild(td); tbody.appendChild(tr); return;
|
||||
}
|
||||
for (const it of items) {
|
||||
const tr = document.createElement('tr');
|
||||
const type = document.createElement('td'); type.textContent = it.is_user ? 'Utilisateur' : 'Visiteur';
|
||||
const ident = document.createElement('td'); ident.textContent = it.is_user ? (it.username || 'Utilisateur') : it.visitor;
|
||||
const page = document.createElement('td'); page.textContent = it.path || '/';
|
||||
const ago = document.createElement('td'); ago.textContent = humanizeSeconds(it.seconds_ago);
|
||||
const src = document.createElement('td'); src.textContent = it.source || '';
|
||||
const country = document.createElement('td'); country.textContent = it.country || '';
|
||||
tr.append(type, ident, page, ago, src, country);
|
||||
tbody.appendChild(tr);
|
||||
}
|
||||
} catch (e) {
|
||||
// silent fail in UI
|
||||
}
|
||||
}
|
||||
fetchLive();
|
||||
setInterval(fetchLive, 10000);
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue