Summarize LiveTrack sessions and prune stale ones
CI / check (push) Successful in 48s
CI / deploy (push) Successful in 23s

Fetching a session's track now also grabs its summary (name, activity
type, distance, duration) from the same page and stores it — sessions
the panel has actually shown replace their raw UUID with that summary,
and are kept indefinitely regardless of age. A session nobody ever
opened (no summary) is more likely test/dead data than something worth
keeping, so it's dropped automatically after 48h.
This commit is contained in:
randy committed 2026-09-06 22:18:25 +02:00
1 parent f4b5237f01
commit 0ee98d8f07
5 files changed
+175 -47

No files matched your search

+5 -2
View File
@@ -471,13 +471,16 @@ html, body {
cursor: wait;
}
.livetrack-panel__id {
font-family: monospace;
.livetrack-panel__label {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.livetrack-panel__label--id {
font-family: monospace;
}
.livetrack-panel__time {
flex-shrink: 0;
color: #888;
+31 -5
View File
@@ -68,7 +68,7 @@ export class LiveTrackPanelControl {
return;
}
sessions.forEach(({ id, received_at }) => {
sessions.forEach(({ id, received_at, summary }) => {
const li = document.createElement("li");
li.className = "livetrack-panel__item";
@@ -76,16 +76,18 @@ export class LiveTrackPanelControl {
button.type = "button";
button.className = "livetrack-panel__row";
button.classList.toggle("active", id === this._activeSessionId);
button.title = id;
const idSpan = document.createElement("span");
idSpan.className = "livetrack-panel__id";
idSpan.textContent = id;
const labelSpan = document.createElement("span");
labelSpan.className = "livetrack-panel__label";
labelSpan.classList.toggle("livetrack-panel__label--id", !summary);
labelSpan.textContent = summary ? summaryLabel(summary) : id;
const timeSpan = document.createElement("span");
timeSpan.className = "livetrack-panel__time";
timeSpan.textContent = new Date(received_at).toLocaleString();
button.append(idSpan, timeSpan);
button.append(labelSpan, timeSpan);
button.addEventListener("click", () => this._toggleTrack(id, button));
li.appendChild(button);
this._list.appendChild(li);
@@ -110,6 +112,10 @@ export class LiveTrackPanelControl {
this._showTrack(this._geojson);
this._activeSessionId = id;
button.classList.add("active");
// The fetch above also computed and stored a summary server-side
// (see LiveTrackClient.summarize) — reload so this row picks it up
// instead of showing the raw id from here on.
this._loadSessions();
} finally {
button.classList.remove("loading");
}
@@ -170,3 +176,23 @@ export class LiveTrackPanelControl {
if (this._map.getSource(TRACK_SOURCE)) this._map.removeSource(TRACK_SOURCE);
}
}
function summaryLabel({ session_name, activity_type, distance_meters, duration_secs }) {
const parts = [];
if (activity_type) parts.push(titleCase(activity_type));
if (typeof distance_meters === "number") parts.push(`${(distance_meters / 1000).toFixed(1)} km`);
if (typeof duration_secs === "number") parts.push(formatDuration(duration_secs));
const stats = parts.join(" · ");
if (session_name && stats) return `${session_name} — ${stats}`;
return session_name || stats || "Untitled session";
}
function titleCase(text) {
return text.charAt(0) + text.slice(1).toLowerCase();
}
function formatDuration(totalSeconds) {
const hours = Math.floor(totalSeconds / 3600);
const minutes = Math.floor((totalSeconds % 3600) / 60);
return hours > 0 ? `${hours}h ${minutes}m` : `${minutes}m`;
}