Server: restore checkbox + batch-delete. Conditional ID (server only) and checkbox via data-show-id/data-batch-delete-url.

This commit is contained in:
Mathieu Moran
2026-08-11 15:11:12 -04:00
parent 2ee4862edd
commit 5713417f4f
3 changed files with 27 additions and 2 deletions
+5
View File
@@ -16,6 +16,9 @@
<div class="card shadow-sm">
<div class="card-header py-2 d-flex justify-content-between align-items-center">
<h6 class="text-primary fw-bold m-0">Recorded trips</h6>
<button id="delete-selected-btn" class="btn btn-sm btn-outline-danger" type="button" hidden title="Delete selected trips">
<i class="fas fa-trash fa-fw"></i> Delete selected
</button>
</div>
<div class="card-body p-0">
<div id="trip-loading" class="text-center text-muted py-4">
@@ -39,6 +42,8 @@
true
) }}
<script>document.getElementById('trip-list').dataset.deleteUrl = '/api/v1/portal/trip/';</script>
<script>document.getElementById('trip-list').dataset.batchDeleteUrl = '/api/v1/portal/trips/delete';</script>
<script>document.getElementById('trip-list').dataset.showId = '1';</script>
</div>
</div>
</div>
+22 -1
View File
@@ -199,6 +199,23 @@
var tl = document.getElementById("trip-list");
var del = tl && tl.dataset.deletable === "1";
var dUrl = (tl && tl.dataset.deleteUrl) || "/api/trip/";
var showId = tl && tl.dataset.showId === "1";
var bUrl = tl && tl.dataset.batchDeleteUrl;
var btD = document.getElementById("delete-selected-btn");
function cIds() { return Array.from(body.querySelectorAll("input.trip-checkbox:checked")).map(function (c) { return parseInt(c.value); }); }
function upBt() { if (!btD) return; var n = cIds().length; btD.hidden = !n; btD.textContent = "Delete selected (" + n + ")"; }
async function delSel() {
var ids = cIds(); if (!ids.length || !bUrl) return;
if (!(await window.confirmDelete("Delete " + ids.length + " trip(s)? Raw GPS data is kept."))) return;
try {
var r = await fetch(bUrl, {method: "POST", headers: {"Content-Type": "application/json"}, body: JSON.stringify({ids: ids})});
if (!r.ok) throw new Error("Delete failed");
ids.forEach(function (id) { var row = body.querySelector('tr[data-trip-id="' + id + '"]'); if (row) row.remove(); });
upBt();
} catch (e) { showErr(e.message); }
}
if (btD) btD.addEventListener("click", delSel);
function render(tt) {
body.replaceChildren();
@@ -208,9 +225,13 @@
row.dataset.duration = t.duration_seconds; row.dataset.maxSpeed = t.max_speed_kmh;
row.dataset.tripId = t.id; row.style.cursor = "pointer";
var db = del ? '<button class="btn btn-sm btn-outline-danger ms-1" type="button" data-delete-trip-id="' + t.id + '" title="Delete"><i class="fas fa-trash fa-fw"></i></button>' : "";
row.innerHTML = "<td class=\"text-muted small text-end pe-1\" style=\"width:1%\">#" + t.id + "</td><td>" + fT(t.start_datetime) + "</td><td>" + fK(t.distance_km) + "</td><td>" + fD(t.duration_seconds) + "</td><td>" + fS(t.max_speed_kmh) + "</td><td class=\"text-muted small\">" + (t.odo_start_km != null ? t.odo_start_km.toFixed(0) + " \u2192 " + t.odo_end_km.toFixed(0) + " km" : "\u2014") + "</td><td class=\"text-end text-nowrap d-none d-sm-table-cell\">" + db + "</td>";
var cb = bUrl ? '<td class="text-center" onclick="event.stopPropagation()"><input type="checkbox" class="trip-checkbox form-check-input" value="' + t.id + '"></td>' : "";
var idCell = showId ? "<td class=\"text-muted small text-end pe-1\" style=\"width:1%\">#" + t.id + "</td>" : "";
row.innerHTML = cb + idCell + "<td>" + fT(t.start_datetime) + "</td><td>" + fK(t.distance_km) + "</td><td>" + fD(t.duration_seconds) + "</td><td>" + fS(t.max_speed_kmh) + "</td><td class=\"text-muted small\">" + (t.odo_start_km != null ? t.odo_start_km.toFixed(0) + " \u2192 " + t.odo_end_km.toFixed(0) + " km" : "\u2014") + "</td><td class=\"text-end text-nowrap d-none d-sm-table-cell\">" + db + "</td>";
body.appendChild(row);
});
body.querySelectorAll("input.trip-checkbox").forEach(function (c) { c.addEventListener("change", upBt); });
upBt();
}
body.addEventListener("click", function (e) {
if (del) {
-1
View File
@@ -27,7 +27,6 @@
{{ data_table(
"trip-list",
[
{"key": "id", "label": "ID", "sortable": false},
{"key": "started", "label": "Started", "sortable": true},
{"key": "distance", "label": "km", "sortable": true},
{"key": "duration", "label": "Time", "sortable": true},