feat(ui): add database stats card on database page

Show table info (entry count, oldest/newest dates, total DB size) in a
new card on the database page, with auto-refresh and i18n support.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
PaulVua
2026-02-16 12:07:58 +01:00
parent e20bb0b8fc
commit 20c6a12251
4 changed files with 150 additions and 4 deletions

View File

@@ -108,7 +108,24 @@
</div>
</div>
<div class="col-lg-4 col-md-12 mb-3">
<div class="col-lg-4 col-md-6 mb-3">
<div class="card text-dark bg-light h-100">
<div class="card-body">
<h5 class="card-title" data-i18n="database.statsTitle">Informations sur la base</h5>
<div id="db_stats_content">
<div class="text-center py-3">
<div class="spinner-border spinner-border-sm" role="status"></div>
<span class="ms-2" data-i18n="common.loading">Chargement...</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row mb-3">
<div class="col-lg-4 col-md-6 mb-3">
<div class="card text-white bg-danger h-100">
<div class="card-body">
<h5 class="card-title" data-i18n="database.dangerZone">Zone dangereuse</h5>
@@ -118,7 +135,6 @@
</div>
</div>
</div>
</div>
<div class="row mt-2">
@@ -224,6 +240,9 @@ window.onload = function() {
}); //end ajax
// Get database table stats
loadDbStats();
//get local RTC
$.ajax({
url: 'launcher.php?type=RTC_time',
@@ -478,6 +497,67 @@ function downloadCSV(response, table) {
document.body.removeChild(a);
}
// Table display names
const tableDisplayNames = {
'data_NPM': 'PM (NextPM)',
'data_NPM_5channels': 'PM 5 canaux',
'data_BME280': 'Temp/Hum (BME280)',
'data_envea': 'Gaz (Cairsens)',
'data_WIND': 'Vent',
'data_MPPT': 'Batterie (MPPT)',
'data_NOISE': 'Bruit'
};
function loadDbStats() {
$.ajax({
url: 'launcher.php?type=db_table_stats',
dataType: 'json',
method: 'GET',
success: function(response) {
if (!response.success) {
document.getElementById('db_stats_content').innerHTML =
'<div class="alert alert-danger mb-0">' + (response.error || 'Erreur') + '</div>';
return;
}
let html = '<p class="mb-2"><strong data-i18n="database.statsDbSize">Taille totale:</strong> ' + response.size_mb + ' MB</p>';
html += '<div class="table-responsive"><table class="table table-sm table-bordered mb-0">';
html += '<thead class="table-secondary"><tr>';
html += '<th data-i18n="database.statsTable">Table</th>';
html += '<th data-i18n="database.statsCount">Entrées</th>';
html += '<th data-i18n="database.statsOldest">Plus ancienne</th>';
html += '<th data-i18n="database.statsNewest">Plus récente</th>';
html += '</tr></thead><tbody>';
response.tables.forEach(function(t) {
const displayName = tableDisplayNames[t.name] || t.name;
const oldest = t.oldest ? t.oldest.substring(0, 16) : '-';
const newest = t.newest ? t.newest.substring(0, 16) : '-';
html += '<tr>';
html += '<td>' + displayName + '</td>';
html += '<td>' + t.count.toLocaleString() + '</td>';
html += '<td><small>' + oldest + '</small></td>';
html += '<td><small>' + newest + '</small></td>';
html += '</tr>';
});
html += '</tbody></table></div>';
html += '<button class="btn btn-outline-secondary btn-sm mt-2" onclick="loadDbStats()" data-i18n="logs.refresh">Refresh</button>';
document.getElementById('db_stats_content').innerHTML = html;
// Re-apply translations if i18n is loaded
if (typeof i18n !== 'undefined' && i18n.translations && Object.keys(i18n.translations).length > 0) {
i18n.applyTranslations();
}
},
error: function(xhr, status, error) {
document.getElementById('db_stats_content').innerHTML =
'<div class="alert alert-danger mb-0">Erreur: ' + error + '</div>';
}
});
}
// Function to empty all sensor tables
function emptySensorTables() {
// Show confirmation dialog