Add scenic waypoints for drive legs (OSRM via-routing)
- Transport entries carry an optional ordered waypoints array of lat/lng/name points; /route attaches them to the ground leg the transport bridges, and /api/directions accepts a via param so the drawn road route detours through them - Day editor gains a geocoded "Scenic waypoints" list on transport entries; the map draws leg-coloured waypoint dots - Escape waypoint names in the Leaflet tooltip (stored-XSS fix flagged by security review: names are user-typed and Leaflet renders string tooltips as HTML)
This commit is contained in:
@@ -4,6 +4,7 @@ import { membership } from '../util/access.js';
|
||||
import { ENTRY_COLUMNS, attachParticipants } from '../util/entrySerialize.js';
|
||||
import { validateSegments } from '../util/segments.js';
|
||||
import { validateRental } from '../util/rental.js';
|
||||
import { validateWaypoints } from '../util/waypoints.js';
|
||||
import { autoTransportTitle } from '../util/autoTransport.js';
|
||||
|
||||
const ENTRY_TYPES = new Set(['flight', 'transport', 'activity', 'rental', 'stay', 'note']);
|
||||
@@ -208,6 +209,22 @@ function validateEntry(body, { partial, existing, memberIds }) {
|
||||
}
|
||||
}
|
||||
|
||||
// waypoints: transport-only scenic via-points (null or [] clears them).
|
||||
if (has('waypoints')) {
|
||||
const v = body.waypoints;
|
||||
if (v === null || (Array.isArray(v) && v.length === 0)) {
|
||||
fields.waypoints = null;
|
||||
} else {
|
||||
const effType = 'type' in fields ? fields.type : existing?.type;
|
||||
if (effType !== 'transport') {
|
||||
return { error: 'waypoints are only allowed on transport entries' };
|
||||
}
|
||||
const checked = validateWaypoints(v);
|
||||
if (checked.error) return { error: checked.error };
|
||||
fields.waypoints = JSON.stringify(checked.value);
|
||||
}
|
||||
}
|
||||
|
||||
return { fields, participants, hasParticipants: has('participants') };
|
||||
}
|
||||
|
||||
@@ -306,8 +323,8 @@ export default function entriesRoutes(db) {
|
||||
`INSERT INTO entries
|
||||
(trip_id, date, end_date, type, title, details, start_time, end_time,
|
||||
location_name, lat, lng, sort_order, price, paid_by, split_mode, segments, rental,
|
||||
transport_mode)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
||||
transport_mode, waypoints)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
||||
)
|
||||
.run(
|
||||
tripId,
|
||||
@@ -327,7 +344,8 @@ export default function entriesRoutes(db) {
|
||||
f.split_mode ?? 'equal',
|
||||
f.segments ?? null,
|
||||
f.rental ?? null,
|
||||
f.transport_mode ?? null
|
||||
f.transport_mode ?? null,
|
||||
f.waypoints ?? null
|
||||
);
|
||||
const id = Number(info.lastInsertRowid);
|
||||
// participants provided as an array -> store rows; null/absent -> all members.
|
||||
|
||||
Reference in New Issue
Block a user