Improve database page layout and highlight most recent data

Layout improvements:
- Reorganized cards to fit 3 across on large screens (col-lg-4)
- View database, download data, and danger zone now on same row
- Added h-100 class to cards for equal height
- Made delete button larger and full-width for better visibility

Button spacing:
- Added mb-2 (margin-bottom) to all measurement trigger buttons
- Improved vertical spacing for better readability

Data visualization:
- Added light green background (#d4edda) to first table row
- First row now highlights the most recent data entry
- Makes it easy to see the latest sensor reading at a glance

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
PaulVua
2026-01-07 14:48:34 +01:00
parent f679732591
commit a3b2bef5c1

View File

@@ -26,6 +26,10 @@
.offcanvas-backdrop {
z-index: 1040;
}
/* Highlight most recent data row with light green background */
.most-recent-row {
background-color: #d4edda !important;
}
</style>
</head>
<body>
@@ -54,8 +58,8 @@
<div class="row mb-3">
<div class="col-sm-5">
<div class="card text-dark bg-light">
<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.viewDatabase">Consulter la base de donnée</h5>
<!-- Dropdown to select number of records -->
@@ -67,23 +71,20 @@
<option value="30" data-i18n="database.last30">30 dernières</option>
</select>
</div>
<button class="btn btn-primary" onclick="get_data_sqlite('data_NPM',getSelectedLimit(),false)" data-i18n="database.pmMeasures">Mesures PM</button>
<button class="btn btn-primary" onclick="get_data_sqlite('data_BME280',getSelectedLimit(),false)" data-i18n="database.tempHumMeasures">Mesures Temp/Hum</button>
<button class="btn btn-primary" onclick="get_data_sqlite('data_NPM_5channels',getSelectedLimit(),false)" data-i18n="database.pm5Channels">Mesures PM (5 canaux)</button>
<button class="btn btn-primary" onclick="get_data_sqlite('data_envea',getSelectedLimit(),false)" data-i18n="database.cairsensProbe">Sonde Cairsens</button>
<button class="btn btn-primary" onclick="get_data_sqlite('data_NOISE',getSelectedLimit(),false)" data-i18n="database.noiseProbe">Sonde bruit</button>
<button class="btn btn-primary" onclick="get_data_sqlite('data_WIND',getSelectedLimit(),false)" data-i18n="database.windProbe">Sonde Vent</button>
<button class="btn btn-primary" onclick="get_data_sqlite('data_MPPT',getSelectedLimit(),false)" data-i18n="database.battery">Batterie</button>
<button class="btn btn-warning" onclick="get_data_sqlite('timestamp_table',getSelectedLimit(),false)" data-i18n="database.timestampTable">Timestamp Table</button>
<button class="btn btn-primary mb-2" onclick="get_data_sqlite('data_NPM',getSelectedLimit(),false)" data-i18n="database.pmMeasures">Mesures PM</button>
<button class="btn btn-primary mb-2" onclick="get_data_sqlite('data_BME280',getSelectedLimit(),false)" data-i18n="database.tempHumMeasures">Mesures Temp/Hum</button>
<button class="btn btn-primary mb-2" onclick="get_data_sqlite('data_NPM_5channels',getSelectedLimit(),false)" data-i18n="database.pm5Channels">Mesures PM (5 canaux)</button>
<button class="btn btn-primary mb-2" onclick="get_data_sqlite('data_envea',getSelectedLimit(),false)" data-i18n="database.cairsensProbe">Sonde Cairsens</button>
<button class="btn btn-primary mb-2" onclick="get_data_sqlite('data_NOISE',getSelectedLimit(),false)" data-i18n="database.noiseProbe">Sonde bruit</button>
<button class="btn btn-primary mb-2" onclick="get_data_sqlite('data_WIND',getSelectedLimit(),false)" data-i18n="database.windProbe">Sonde Vent</button>
<button class="btn btn-primary mb-2" onclick="get_data_sqlite('data_MPPT',getSelectedLimit(),false)" data-i18n="database.battery">Batterie</button>
<button class="btn btn-warning mb-2" onclick="get_data_sqlite('timestamp_table',getSelectedLimit(),false)" data-i18n="database.timestampTable">Timestamp Table</button>
</div>
</div>
</div>
<div class="col-sm-5">
<div class="card text-dark bg-light">
<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.downloadData">Télécharger les données</h5>
<!-- Date selection for download -->
@@ -94,32 +95,28 @@
<input type="date" id="end_date" class="form-control w-auto">
</div>
<button class="btn btn-primary" onclick="get_data_sqlite('data_NPM',10,true, getStartDate(), getEndDate())" data-i18n="database.pmMeasures">Mesures PM</button>
<button class="btn btn-primary" onclick="get_data_sqlite('data_BME280',10,true, getStartDate(), getEndDate())" data-i18n="database.tempHumMeasures">Mesures Temp/Hum</button>
<button class="btn btn-primary" onclick="get_data_sqlite('data_NPM_5channels',10,true, getStartDate(), getEndDate())" data-i18n="database.pm5Channels">Mesures PM (5 canaux)</button>
<button class="btn btn-primary" onclick="get_data_sqlite('data_envea',10,true, getStartDate(), getEndDate())" data-i18n="database.cairsensProbe">Sonde Cairsens</button>
<button class="btn btn-primary" onclick="get_data_sqlite('data_NOISE',10,true, getStartDate(), getEndDate())" data-i18n="database.noiseProbe">Sonde Bruit</button>
<button class="btn btn-primary" onclick="get_data_sqlite('data_mppt',10,true, getStartDate(), getEndDate())" data-i18n="database.battery">Batterie</button>
</table>
<button class="btn btn-primary mb-2" onclick="get_data_sqlite('data_NPM',10,true, getStartDate(), getEndDate())" data-i18n="database.pmMeasures">Mesures PM</button>
<button class="btn btn-primary mb-2" onclick="get_data_sqlite('data_BME280',10,true, getStartDate(), getEndDate())" data-i18n="database.tempHumMeasures">Mesures Temp/Hum</button>
<button class="btn btn-primary mb-2" onclick="get_data_sqlite('data_NPM_5channels',10,true, getStartDate(), getEndDate())" data-i18n="database.pm5Channels">Mesures PM (5 canaux)</button>
<button class="btn btn-primary mb-2" onclick="get_data_sqlite('data_envea',10,true, getStartDate(), getEndDate())" data-i18n="database.cairsensProbe">Sonde Cairsens</button>
<button class="btn btn-primary mb-2" onclick="get_data_sqlite('data_NOISE',10,true, getStartDate(), getEndDate())" data-i18n="database.noiseProbe">Sonde Bruit</button>
<button class="btn btn-primary mb-2" onclick="get_data_sqlite('data_mppt',10,true, getStartDate(), getEndDate())" data-i18n="database.battery">Batterie</button>
</div>
</div>
</div>
<div class="col-sm-5">
<div class="card text-white bg-danger">
<div class="col-lg-4 col-md-12 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>
<p class="card-text" data-i18n="database.dangerWarning">Attention: Cette action est irréversible!</p>
<button class="btn btn-dark" onclick="emptySensorTables()" data-i18n="database.emptyAllTables">Vider toutes les tables de capteurs</button>
<button class="btn btn-dark btn-lg w-100 mb-2" onclick="emptySensorTables()" data-i18n="database.emptyAllTables">Vider toutes les tables de capteurs</button>
<small class="d-block mt-2" data-i18n="database.emptyTablesNote">Note: Les tables de configuration et horodatage seront préservées.</small>
</div>
</div>
</div>
<div>
</div>
<div class="row mt-2">
<div id="table_data"></div>
@@ -346,9 +343,11 @@ function get_data_sqlite(table, limit, download , startDate = "", endDate = "")
tableHTML += `</tr></thead><tbody>`;
// Loop through rows and create table rows
rows.forEach(row => {
rows.forEach((row, index) => {
let columns = row.replace(/[()]/g, "").split(", "); // Remove parentheses and split
tableHTML += "<tr>";
// Add special class to first row (most recent data)
const rowClass = index === 0 ? ' class="most-recent-row"' : '';
tableHTML += `<tr${rowClass}>`;
if (table === "data_NPM") {
tableHTML += `