Add a "user overlay" tool: click the map, save a note

New map-corner "Add note" control (public/js/notes.js), mirroring
measure.js's click-to-place UX. Click the map, write a short note,
pick an existing .geojson layer file or name a new one — saved via a
new GpxStore#append_feature (grows the target file in place, unlike
save()'s always-disambiguate-the-filename behavior) through a new
POST /api/gpx/notes route.

No new rendering path: a note is just another point in a .geojson
file the Tracks panel's tree already lists, checkboxes, and pops up —
visibility toggling ("layers") comes for free from that existing
machinery, per-file, with no changes needed there.

Points only for now — a polygon mode would need gpx.js's point/line
split taught a third Polygon bucket first, or a saved polygon
wouldn't render back on reload (see TODO.adoc).

Covered by new tests: GpxStore#append_feature (create/append/missing-
path/filename-safety) and the /api/gpx/notes route (auth gate, create,
append, malformed/missing-geometry rejection, 404 on a missing
target). Full suite: 97 runs, 0 failures.
This commit is contained in:
randy committed 2026-09-09 10:18:50 +02:00
1 parent 5caf865fc8
commit aa2b96ac70
11 files changed
+437 -2

No files matched your search

+6 -1
View File
@@ -12,7 +12,7 @@ import {
POI_ICONS,
PARK4NIGHT_TAGS,
} from "/js/icons.js";
import { notifySidePanelOpen, onlyOneSidePanelOpen } from "/js/panels.js";
import { notifySidePanelOpen, onlyOneSidePanelOpen, onGpxStoreChanged } from "/js/panels.js";
import { formatActivityType } from "/js/track_profile.js";
import { isLoggedIn } from "/js/auth.js";
@@ -57,6 +57,11 @@ export class GpxPanelControl {
this._iconsReady = this._registerCategoryGlyphs();
this._visible.forEach((path) => this._addLayers(path));
});
// notes.js writes directly into the same GPX store (a hand-drawn note
// saved into a .geojson layer) — refresh so a newly created/grown file
// shows up in the tree without a manual reopen.
onGpxStoreChanged(() => this._loadTree());
}
// Registered once, always white, as plain (non-SDF) images: these used to