Let a cached file's GeoJSON be downloaded by clicking its tree name

Once a .gpx/.fit is cached, the tree shows it under its converted name
("ride.gpx" -> "ride.gpx.geojson", matching the real cache file next
to it on disk) instead of still reading as un-converted -- the
GeoJSON is what's actually on the map from that point on, and the
original is never deleted, just not re-shown as itself. The name is
now a real link (GET /api/gpx/file/<path>?download=1) instead of
plain text, the only way to get that converted form out of the app.

Verified in a real browser that an <a> nested in a <label> claims its
own click rather than the label forwarding it to the checkbox, so
downloading and toggling visibility don't fight over the same click.
This commit is contained in:
randy committed 2026-09-07 22:56:46 +02:00
1 parent b4f205667b
commit cd92dadf6a
5 files changed
+70 -4

No files matched your search

+6
View File
@@ -360,6 +360,12 @@ html, body {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: inherit;
text-decoration: none;
}
.gpx-tree__file-name:hover {
text-decoration: underline;
}
.gpx-tree__kind-icon {
+16 -3
View File
@@ -271,10 +271,23 @@ export class GpxPanelControl {
checkbox.type = "checkbox";
checkbox.checked = this._visible.has(file.path);
checkbox.addEventListener("change", () => this._toggleFile(file.path, checkbox.checked, checkbox));
const name = document.createElement("span");
// Once a .gpx/.fit is cached, its converted GeoJSON is the thing that's
// actually shown on the map from here on (see GpxStore#geojson) — the
// name reflects that (matching the real "<path>.geojson" cache file on
// disk) rather than still reading as a plain, un-converted .gpx/.fit.
// A direct .geojson upload already ends in .geojson, so it's left
// alone. It's an <a>, not a <span>: clicking it downloads that GeoJSON
// (?download=1) — the only way to get it out of the app, since the
// original .gpx/.fit is never deleted but also never re-shown once
// converted. An <a> nested in a <label> doesn't also toggle the
// checkbox on click (unlike a plain element), so this doesn't fight
// the row's own toggle-on-map behavior.
const displayName = file.cached && !file.name.toLowerCase().endsWith(".geojson") ? `${file.name}.geojson` : file.name;
const name = document.createElement("a");
name.className = "gpx-tree__file-name";
name.textContent = file.name;
name.title = file.name;
name.href = `${gpxFileUrl(file.path)}?download=1`;
name.textContent = displayName;
name.title = `Download ${displayName}`;
label.appendChild(checkbox);
(file.kinds || []).forEach((kind) => label.appendChild(this._kindIcon(kind)));
if (file.cached) label.appendChild(this._cachedIcon());