feat(journey): make the linked trips' GPX tracks a switch, off by default

#1260 drew the GPX tracks of every trip behind a journey onto its map, with
nothing to switch off — the reasoning being that a route imported into a
linked trip is part of the journey's story. For a trip carrying a season of
recorded drives it is instead a map nobody asked for, drawn from places that
never became an entry.

So it becomes a journey-level setting, owner-only like the other Journey
Settings, and it starts off: a journal should show what its author put in it,
and #1260's set is everything the linked trips happen to contain. The switch
gates the request, not just the rendering — the endpoint ships full unthinned
geometry, which is megabytes fetched on every journey open for a map nobody
wanted.

`journeyTracks()` itself is deliberately untouched, so TREK Studio keeps the
set its saved books were laid out with.

Also fixes what the reporter's screenshot actually shows: JourneyMap fed track
coordinates into `fitBounds`, so one drive across a country zoomed the journey
map out until the entries were specks. Tracks now only frame the map when
there is nothing else to frame, which is what JourneyMapGL already did — the
same journey used to open at two different zooms depending on the renderer.

Closes #2194

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S5VwmiBQ9sPCJwfmpv64r3
This commit is contained in:
Claude
2026-09-02 12:01:14 +00:00
committed by Maurice
parent 5e5fe288d8
commit b7f9c1e8ae
31 changed files with 211 additions and 13 deletions
@@ -356,6 +356,30 @@ describe('updateJourney', () => {
expect(result).not.toBeNull();
expect(result!.status).toBe('active');
});
it('JOURNEY-SVC-021d: trip GPX tracks are off until the owner switches them on (#2194)', () => {
const { user } = createUser(testDb);
const journey = createJourney(testDb, user.id, { title: 'Norway' });
// #1260 drew the linked trips' tracks unconditionally; they are opt-in now.
expect(svc.updateJourney(journey.id, user.id, {})!.show_trip_tracks).toBe(0);
// A JS boolean has to survive the trip into an INTEGER column —
// better-sqlite3 refuses to bind one, so this would throw uncoerced.
expect(svc.updateJourney(journey.id, user.id, { show_trip_tracks: true })!.show_trip_tracks).toBe(1);
expect(svc.updateJourney(journey.id, user.id, { show_trip_tracks: false })!.show_trip_tracks).toBe(0);
});
it('JOURNEY-SVC-021e: an editor cannot switch the trip tracks on (#2194)', () => {
const { user } = createUser(testDb);
const { user: editor } = createUser(testDb, { username: 'tracks-editor' });
const journey = createJourney(testDb, user.id, { title: 'Norway' });
testDb.prepare("INSERT INTO journey_contributors (journey_id, user_id, role, added_at) VALUES (?, ?, 'editor', 0)")
.run(journey.id, editor.id);
// Journey-level settings stay owner-only, same as title and status.
expect(svc.updateJourney(journey.id, editor.id, { show_trip_tracks: true })).toBeNull();
});
});
describe('deleteJourney', () => {