diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs
index 2a2403b8..131b0306 100644
--- a/docs/astro.config.mjs
+++ b/docs/astro.config.mjs
@@ -48,7 +48,7 @@ export default defineConfig({
label: 'Authentication',
link: '/use/authentication/'
}, {
- label: 'Create a trail',
+ label: 'Create/Edit a trail',
link: '/use/create-a-trail/'
},
{
diff --git a/docs/src/content/docs/use/create-a-trail.md b/docs/src/content/docs/use/create-a-trail.md
index ca4fd441..47ffbc51 100644
--- a/docs/src/content/docs/use/create-a-trail.md
+++ b/docs/src/content/docs/use/create-a-trail.md
@@ -1,25 +1,21 @@
---
-title: Create a trail
-description: How to create a trail by uploading or drawing a trail using Valhalla
+title: Create or edit a trail
+description: How to create or edit a trail by uploading or drawing a trail using Valhalla
---
## What is a trail?
In wanderer, a trail is a digital route that includes GPS data and descriptive metadata like name, difficulty, category, photos, and waypoints. Trails can be explored by others and searched in the app.
-
-
## Create a trail
To start, click the button in the top right corner.
-
-
-## Step 1: Pick a route
+### Step 1: Pick a route
Each trail must begin with a route. There are two ways to provide one:
-### Upload a file
+#### Upload a file
Click the **Upload file** button to select a GPS file. Accepted formats are **GPX**, **FIT**, **TCX**, or **KML**.
@@ -28,22 +24,20 @@ After uploading:
- The map centers on the route
- Elevation profile and speed (if available) are rendered
- Distance, elevation gain/loss, and other metadata are extracted
-- The form fields on the left will be partially prefilled with data that extracted from the file
+- The form fields on the left will be partially prefilled with data extracted from the file
-### Draw a route
+#### Draw a route
Click the **Draw a route** button to manually define a route on the map. While in drawing mode:
-- Click on the map to place waypoints
-- wanderer will automatically route between points using the [Valhalla routing engine](https://github.com/valhalla/valhalla)
-- You can drag points to reposition them
-- The anchor list next to the map shows start, intermediate, and finish points with segment distance and elevation stats
-- Hover an item in the anchor list to highlight its marker on the map
-- Reorder intermediate anchors from the list to adjust the route sequence
+- Click on the map to place route anchors
+- wanderer will automatically route between anchors using the [Valhalla routing engine](https://github.com/valhalla/valhalla)
+- You can drag anchors to reposition them
- Use the top-left menu to change routing mode (e.g. walking, cycling)
-- To remove a point, click on it and then click the red trash icon
+- Use the waypoint button (location marker icon) in the route editing toolbar to show or hide existing waypoint markers on the map. Hiding them also disables right-clicking to create new waypoints.
+- To remove an anchor, click on it and then click the red trash icon
-If you disable Valhalla routing, straight lines will be used between points instead.
+If you disable Valhalla routing, straight lines will be used between anchors instead.
To finish drawing, click **Stop drawing**.
@@ -51,11 +45,18 @@ To finish drawing, click **Stop drawing**.
wanderer uses a public, donation-financed Valhalla server by default. Please consider supporting it at [https://www.fossgis.de/verein/spenden/](https://www.fossgis.de/verein/spenden/).
:::
+#### Trail anchor list
+While drawing or editing a route, the anchor list shows the route's start, intermediate, and finish anchors in order. It helps you inspect and adjust the structure of the route without relying only on the map:
-## Step 2: Fill out trail details
+- Each segment shows distance and elevation stats for the route section that follows the anchor.
+- Hover an anchor in the list to highlight its marker on the map.
+- Drag intermediate anchors in the list to reorder the route sequence.
+- Delete an anchor from the list to remove it from the route.
-### Basic Info
+### Step 2: Fill out trail details
+
+#### Basic Info
- **Name** – Required. Every trail needs a name.
- **Location** – Autofilled if available in the uploaded file.
@@ -66,7 +67,7 @@ To finish drawing, click **Stop drawing**.
- **Difficulty** – Select the trail's difficulty (e.g. Easy, Moderate, Hard)
- **Category** – Choose the activity type (e.g. Hiking, Cycling)
-### Visibility
+#### Visibility
Toggle the **Private** switch if you do not want the trail to be visible to others. When set to private, only you will be able to view and access this trail.
@@ -74,26 +75,23 @@ Toggle the **Private** switch if you do not want the trail to be visible to othe
Creating a public trail will automatically publish that trail to all your followers.
:::
-
-## Step 3: Add Waypoints
+### Step 3: Add Waypoints
Waypoints are points of interest along the trail.
- Click **+ Add Waypoint** to add one manually. It will appear centered on the map and can be dragged to another location.
+- When you are not editing the route, click on the map to open a popup with a **Create waypoint** button at that location.
+- While drawing or editing the route, right-click on the map to open the same popup without placing a route anchor. This works only while waypoint markers are visible (see the waypoint toggle in the route editing toolbar).
- Each waypoint can have a name, description, icon, and photos.
- Use Font Awesome icons for map markers. You can browse them at [fontawesome.com](https://fontawesome.com/search?q=share&o=r&m=free).
Alternatively, click **From Photos** to upload photos with GPS metadata. Waypoints will be created automatically based on the photo locations.
-
-
-## Step 4: Add Photos & Videos
+### Step 4: Add Photos & Videos
You can attach photos and videos to the trail itself. These will be shown in the trail's detail view. If you upload more than one, you can select one to be the trail’s thumbnail in the overview.
-
-
-## Step 5: Add to Summit Book
+### Step 5: Add to Summit Book
If you've completed this trail yourself, you can log a summit book entry.
@@ -103,8 +101,21 @@ If you've completed this trail yourself, you can log a summit book entry.
To learn more about summit logs visit the [dedicated section](/use/summit-logs) of the documentation.
-
-
-## Step 6: Save the trail
+### Step 6: Save the trail
When you're done, click to persist your trail to the database. This will also re-index it for search and display it in your trail list.
+
+## Edit an existing trail
+
+Open a trail and choose **Edit** from its menu. If the trail already has route data, the editor starts in drawing mode so you can continue adjusting the existing route immediately.
+
+Route editing works like drawing a new route, with a few differences:
+
+- Click **Stop editing** to leave drawing mode. This protects the route from accidental changes when you click the map and restores left-clicking the map to create waypoints. Metadata, photos, waypoints, summit entries, and lists can be edited regardless of whether drawing mode is active.
+- Click **Edit route** to return to route editing mode later.
+- Existing waypoints remain visible while editing the route. Use the waypoint toggle in the route editing toolbar to hide them if they get in the way (this also disables right-click waypoint creation).
+- Left-click the map to add or extend route anchors.
+- Right-click the map to create a waypoint at that location without placing a route anchor.
+- Use **Reset route** if you want to discard the current route and upload or draw a new one.
+
+Saving an edited trail updates its route data, metadata, waypoints, photos, and search index.
diff --git a/web/src/lib/components/trail/map_with_elevation_maplibre.svelte b/web/src/lib/components/trail/map_with_elevation_maplibre.svelte
index 4da60518..831db92b 100644
--- a/web/src/lib/components/trail/map_with_elevation_maplibre.svelte
+++ b/web/src/lib/components/trail/map_with_elevation_maplibre.svelte
@@ -37,6 +37,7 @@
markers?: M.Marker[];
map?: M.Map | null;
drawing?: boolean;
+ displayWaypoints?: boolean;
showElevation?: boolean;
showInfoPopup?: boolean;
showGrid?: boolean;
@@ -65,6 +66,7 @@
onmoveend?: (map: M.Map) => void;
onzoom?: (map: M.Map) => void;
onclick?: (event: M.MapMouseEvent & Object) => void;
+ oncontextmenu?: (event: M.MapMouseEvent & Object) => void;
onUnclusteredClick?: (
event: M.MapMouseEvent & Object,
trail: Trail,
@@ -81,6 +83,7 @@
markers = $bindable([]),
map = $bindable(),
drawing = false,
+ displayWaypoints = true,
showElevation = true,
showInfoPopup = false,
showGrid = false,
@@ -101,6 +104,7 @@
onmoveend,
onzoom,
onclick,
+ oncontextmenu,
onUnclusteredClick,
oninit,
autoGeolocateOnDrawing = false,
@@ -190,8 +194,9 @@
});
$effect(() => {
waypoints;
+ displayWaypoints;
untrack(() => {
- showWaypoints();
+ syncWaypointMarkers();
refreshElevationProfile();
});
});
@@ -668,7 +673,7 @@
if (showElevation) {
epc?.showProfile();
}
- showWaypoints();
+ syncWaypointMarkers();
if (trail.id && gpxDataMap[trail.id]) {
addCaretLayer(gpxDataMap[trail.id]);
}
@@ -698,7 +703,6 @@
if (!map) {
return;
}
- hideWaypoints();
activeTrail ??= 0;
map.getCanvas().style.cursor = "crosshair";
if (trails[activeTrail]) {
@@ -714,7 +718,7 @@
if (!map) {
return;
}
- showWaypoints();
+ syncWaypointMarkers();
map.getCanvas().style.cursor = "inherit";
if (activeTrail !== null && trails[activeTrail] && !clusterTrails) {
@@ -792,7 +796,7 @@
}
function showWaypoints() {
- if (!map || drawing) {
+ if (!map) {
return;
}
@@ -816,6 +820,14 @@
});
}
+ function syncWaypointMarkers() {
+ if (displayWaypoints) {
+ showWaypoints();
+ } else {
+ hideWaypoints();
+ }
+ }
+
function hideWaypoints() {
if (!map) {
return;
@@ -1015,6 +1027,10 @@
onclick?.(e);
});
+ map.on("contextmenu", (e) => {
+ oncontextmenu?.(e);
+ });
+
map.on("load", () => {
layerManager.init();
initMap(true);
@@ -1022,7 +1038,7 @@
mapLoaded = true;
});
- showWaypoints();
+ syncWaypointMarkers();
});
function geolocate() {
diff --git a/web/src/lib/components/trail/route_editor.svelte b/web/src/lib/components/trail/route_editor.svelte
index 65f2281e..0fc9cca0 100644
--- a/web/src/lib/components/trail/route_editor.svelte
+++ b/web/src/lib/components/trail/route_editor.svelte
@@ -23,6 +23,7 @@
onRecalculateElevationData: () => void;
onUndo: () => void;
onRedo: () => void;
+ showWaypoints?: boolean;
resetLabel?: string;
resetAriaLabel?: string;
}
@@ -37,6 +38,7 @@
onRecalculateElevationData,
onUndo,
onRedo,
+ showWaypoints = $bindable(true),
resetLabel = "reset",
resetAriaLabel = "reset-route",
}: Props = $props();
@@ -149,6 +151,15 @@
aria-label="recalculate elevation data"
onclick={async () => await togglePanels(false, false, !recalculateElevationData)}>
+