From 73d20b1cbcc4c3f49fd1ee9e04ff237c47992057 Mon Sep 17 00:00:00 2001 From: Christian Beutel <> Date: Fri, 12 Sep 2025 17:48:41 +0200 Subject: [PATCH] reverses waypoint relation --- db/integrations/komoot/komoot.go | 46 +++++++------- db/integrations/strava/strava.go | 39 ++++++------ db/migrations/1757689107_updated_waypoints.go | 62 +++++++++++++++++++ .../1757689185_migrate_waypoint_trails.go | 34 ++++++++++ db/migrations/1757690946_updated_trails.go | 44 +++++++++++++ .../components/trail/trail_info_panel.svelte | 2 +- .../components/trail/trail_timeline.svelte | 2 +- web/src/lib/models/api/trail_schema.ts | 2 - web/src/lib/models/api/waypoint_schema.ts | 13 ++-- web/src/lib/models/trail.ts | 6 +- web/src/lib/models/waypoint.ts | 4 +- web/src/lib/stores/trail_store.ts | 45 +++++--------- web/src/lib/util/gpx_util.ts | 4 +- web/src/routes/api/v1/trail/+server.ts | 2 +- web/src/routes/api/v1/trail/[id]/+server.ts | 4 +- .../lists/[[handle]]/[[id]]/+page.svelte | 2 +- .../map/trail/[handle]/[id]/+page.svelte | 2 +- .../trail/[handle]/[id]/print/+page.svelte | 6 +- web/src/routes/trail/edit/[id]/+page.svelte | 34 +++++----- 19 files changed, 238 insertions(+), 115 deletions(-) create mode 100644 db/migrations/1757689107_updated_waypoints.go create mode 100644 db/migrations/1757689185_migrate_waypoint_trails.go create mode 100644 db/migrations/1757690946_updated_trails.go diff --git a/db/integrations/komoot/komoot.go b/db/integrations/komoot/komoot.go index a2041d5a..51b62ee8 100644 --- a/db/integrations/komoot/komoot.go +++ b/db/integrations/komoot/komoot.go @@ -205,27 +205,27 @@ func syncTrailWithTours(app core.App, k *KomootApi, i KomootIntegration, user st app.Logger().Warn(fmt.Sprintf("Unable to generate GPX for tour '%s': %v", tour.Name, err)) continue } - wpIds, err := createWaypointsFromTour(app, detailedTour, user) - if err != nil { - app.Logger().Warn(fmt.Sprintf("Unable to create waypoints for tour '%s': %v", tour.Name, err)) - continue - } - err = createTrailFromTour(app, k, detailedTour, gpx, actor, wpIds) + trailid, err := createTrailFromTour(app, k, detailedTour, gpx, actor) if err != nil { app.Logger().Warn(fmt.Sprintf("Unable to create trail for tour '%s': %v", tour.Name, err)) continue } + err = createWaypointsFromTour(app, detailedTour, user, trailid) + if err != nil { + app.Logger().Warn(fmt.Sprintf("Unable to create waypoints for tour '%s': %v", tour.Name, err)) + continue + } } return hasNewTours, nil } -func createTrailFromTour(app core.App, k *KomootApi, detailedTour *DetailedKomootTour, gpx *filesystem.File, actor string, wpIds []string) error { +func createTrailFromTour(app core.App, k *KomootApi, detailedTour *DetailedKomootTour, gpx *filesystem.File, actor string) (string, error) { trailid := security.RandomStringWithAlphabet(core.DefaultIdLength, core.DefaultIdAlphabet) collection, err := app.FindCollectionByNameOrId("trails") if err != nil { - return err + return "", err } record := core.NewRecord(collection) @@ -251,12 +251,12 @@ func createTrailFromTour(app core.App, k *KomootApi, detailedTour *DetailedKomoo if len(detailedTour.Embedded.CoverImages.Embedded.Items) > 0 { photos, err = fetchRoutePhotos(k, detailedTour) if err != nil { - return err + return "", err } } else { photo, err := fetchPhoto(detailedTour.MapImage.Src, "", "") if err != nil { - return err + return "", err } photos = append(photos, photo) } @@ -281,7 +281,6 @@ func createTrailFromTour(app core.App, k *KomootApi, detailedTour *DetailedKomoo "lon": detailedTour.StartPoint.Lng, "difficulty": diffculty, "category": categoryId, - "waypoints": wpIds, "author": actor, }) @@ -293,13 +292,13 @@ func createTrailFromTour(app core.App, k *KomootApi, detailedTour *DetailedKomoo } if err := app.Save(record); err != nil { - return err + return "", err } if detailedTour.Type == "tour_recorded" { collection, err := app.FindCollectionByNameOrId("summit_logs") if err != nil { - return err + return "", err } summitLogRecord := core.NewRecord(collection) @@ -313,25 +312,23 @@ func createTrailFromTour(app core.App, k *KomootApi, detailedTour *DetailedKomoo "trail": trailid, }) if err := app.Save(summitLogRecord); err != nil { - return err + return "", err } } - return nil + return trailid, nil } -func createWaypointsFromTour(app core.App, tour *DetailedKomootTour, user string) ([]string, error) { +func createWaypointsFromTour(app core.App, tour *DetailedKomootTour, user string, trailid string) error { collection, err := app.FindCollectionByNameOrId("waypoints") if err != nil { - return nil, err + return err } - wpIds := make([]string, len(tour.Embedded.Timeline.Embedded.Items)) - - for i, wp := range tour.Embedded.Timeline.Embedded.Items { + for _, wp := range tour.Embedded.Timeline.Embedded.Items { photos, err := fetchWaypointPhotos(wp) if err != nil { - return nil, err + return err } record := core.NewRecord(collection) @@ -358,6 +355,7 @@ func createWaypointsFromTour(app core.App, tour *DetailedKomootTour, user string "icon": "circle", "author": user, "distance_from_start": 0, + "trail": trailid, }) if photos != nil { @@ -365,13 +363,11 @@ func createWaypointsFromTour(app core.App, tour *DetailedKomootTour, user string } if err := app.Save(record); err != nil { - return nil, err + return err } - - wpIds[i] = record.Id } - return wpIds, nil + return nil } func fetchRoutePhotos(k *KomootApi, tour *DetailedKomootTour) ([]*filesystem.File, error) { diff --git a/db/integrations/strava/strava.go b/db/integrations/strava/strava.go index e291ea9d..974af4f0 100644 --- a/db/integrations/strava/strava.go +++ b/db/integrations/strava/strava.go @@ -251,17 +251,16 @@ func syncTrailsWithRoutes(app core.App, accessToken string, user string, actor s app.Logger().Warn(fmt.Sprintf("Unable to fetch GPX for route '%s': %v", route.Name, err)) continue } - wpIds, err := createWaypointsFromRoute(app, route, user) - if err != nil { - app.Logger().Warn(fmt.Sprintf("Unable to create waypoints for route '%s': %v", route.Name, err)) - continue - } - err = createTrailFromRoute(app, route, gpx, actor, wpIds) + trailid, err := createTrailFromRoute(app, route, gpx, actor) if err != nil { app.Logger().Warn(fmt.Sprintf("Unable to create trail for route '%s': %v", route.Name, err)) continue } - + err = createWaypointsFromRoute(app, route, user, trailid) + if err != nil { + app.Logger().Warn(fmt.Sprintf("Unable to create waypoints for route '%s': %v", route.Name, err)) + continue + } } return hasNewRoutes, nil @@ -305,10 +304,12 @@ func fetchRouteGPX(route StravaRoute, accessToken string) (*filesystem.File, err return gpxFile, nil } -func createTrailFromRoute(app core.App, route StravaRoute, gpx *filesystem.File, actor string, wpIds []string) error { +func createTrailFromRoute(app core.App, route StravaRoute, gpx *filesystem.File, actor string) (string, error) { + trailid := security.RandomStringWithAlphabet(core.DefaultIdLength, core.DefaultIdAlphabet) + collection, err := app.FindCollectionByNameOrId("trails") if err != nil { - return err + return "", err } record := core.NewRecord(collection) @@ -337,6 +338,7 @@ func createTrailFromRoute(app core.App, route StravaRoute, gpx *filesystem.File, } record.Load(map[string]any{ + "id": trailid, "name": route.Name, "description": route.Description, "public": !route.Private, @@ -348,7 +350,6 @@ func createTrailFromRoute(app core.App, route StravaRoute, gpx *filesystem.File, "external_id": route.IDStr, "lat": lat, "lon": lon, - "waypoints": wpIds, "difficulty": "easy", "category": category, "author": actor, @@ -359,20 +360,18 @@ func createTrailFromRoute(app core.App, route StravaRoute, gpx *filesystem.File, } if err := app.Save(record); err != nil { - return err + return "", err } - return nil + return trailid, err } -func createWaypointsFromRoute(app core.App, route StravaRoute, user string) ([]string, error) { +func createWaypointsFromRoute(app core.App, route StravaRoute, user string, trailid string) error { collection, err := app.FindCollectionByNameOrId("waypoints") if err != nil { - return nil, err + return err } - wpIds := make([]string, len(route.Waypoints)) - for i, wp := range route.Waypoints { record := core.NewRecord(collection) @@ -383,13 +382,15 @@ func createWaypointsFromRoute(app core.App, route StravaRoute, user string) ([]s record.Set("icon", "circle") record.Set("author", user) record.Set("distance_from_start", wp.DistanceIntoRoute) + record.Set("trail", trailid) - app.Save(record) + if err := app.Save(record); err != nil { + return err + } - wpIds[i] = record.Id } - return wpIds, nil + return nil } func syncTrailsWithActivities(app core.App, accessToken string, user string, actor string, activities []StravaActivity) (bool, error) { diff --git a/db/migrations/1757689107_updated_waypoints.go b/db/migrations/1757689107_updated_waypoints.go new file mode 100644 index 00000000..14e9e99c --- /dev/null +++ b/db/migrations/1757689107_updated_waypoints.go @@ -0,0 +1,62 @@ +package migrations + +import ( + "encoding/json" + + "github.com/pocketbase/pocketbase/core" + m "github.com/pocketbase/pocketbase/migrations" +) + +func init() { + m.Register(func(app core.App) error { + collection, err := app.FindCollectionByNameOrId("goeo2ubp103rzp9") + if err != nil { + return err + } + + // update collection data + if err := json.Unmarshal([]byte(`{ + "listRule": "author = @request.auth.id || trail.author.user ?= @request.auth.id || trail.public ?= true || trail.trail_share_via_trail.actor.user ?= @request.auth.id\n|| \n(trail.trail_link_share_via_trail.token != \"\" && trail.trail_link_share_via_trail.token = @request.query.share)", + "viewRule": "author = @request.auth.id || trail.author.user ?= @request.auth.id || trail.public ?= true || trail.trail_share_via_trail.actor.user ?= @request.auth.id\n|| \n(trail.trail_link_share_via_trail.token != \"\" && trail.trail_link_share_via_trail.token = @request.query.share)" + }`), &collection); err != nil { + return err + } + + // add field + if err := collection.Fields.AddMarshaledJSONAt(9, []byte(`{ + "cascadeDelete": true, + "collectionId": "e864strfxo14pm4", + "hidden": false, + "id": "relation2993194383", + "maxSelect": 1, + "minSelect": 0, + "name": "trail", + "presentable": false, + "required": true, + "system": false, + "type": "relation" + }`)); err != nil { + return err + } + + return app.Save(collection) + }, func(app core.App) error { + collection, err := app.FindCollectionByNameOrId("goeo2ubp103rzp9") + if err != nil { + return err + } + + // update collection data + if err := json.Unmarshal([]byte(`{ + "listRule": "author = @request.auth.id || trails_via_waypoints.author.user ?= @request.auth.id || trails_via_waypoints.public ?= true || \n(@collection.trail_share.trail.id ?= trails_via_waypoints.id && @collection.trail_share.actor.user ?= @request.auth.id)\n|| \n(@collection.trail_link_share.token != \"\" && @collection.trail_link_share.trail.waypoints.id ?= id)", + "viewRule": "author = @request.auth.id || trails_via_waypoints.author.user ?= @request.auth.id || trails_via_waypoints.public ?= true || \n(@collection.trail_share.trail.id ?= trails_via_waypoints.id && @collection.trail_share.actor.user ?= @request.auth.id)\n|| \n(@collection.trail_link_share.token != \"\" && @collection.trail_link_share.trail.waypoints.id ?= id)" + }`), &collection); err != nil { + return err + } + + // remove field + collection.Fields.RemoveById("relation2993194383") + + return app.Save(collection) + }) +} diff --git a/db/migrations/1757689185_migrate_waypoint_trails.go b/db/migrations/1757689185_migrate_waypoint_trails.go new file mode 100644 index 00000000..e92d2d1a --- /dev/null +++ b/db/migrations/1757689185_migrate_waypoint_trails.go @@ -0,0 +1,34 @@ +package migrations + +import ( + "github.com/pocketbase/dbx" + "github.com/pocketbase/pocketbase/core" + m "github.com/pocketbase/pocketbase/migrations" +) + +func init() { + m.Register(func(app core.App) error { + wps, err := app.FindAllRecords("waypoints") + if err != nil { + return err + } + + for _, wp := range wps { + trail, err := app.FindFirstRecordByFilter("trails", "waypoints ?~ {:id}", dbx.Params{"id": wp.Id}) + if err != nil { + continue + } + wp.Set("trail", trail.Id) + err = app.UnsafeWithoutHooks().Save(wp) + if err != nil { + return err + } + } + + return nil + }, func(app core.App) error { + // add down queries... + + return nil + }) +} diff --git a/db/migrations/1757690946_updated_trails.go b/db/migrations/1757690946_updated_trails.go new file mode 100644 index 00000000..d0cdeea7 --- /dev/null +++ b/db/migrations/1757690946_updated_trails.go @@ -0,0 +1,44 @@ +package migrations + +import ( + "github.com/pocketbase/pocketbase/core" + m "github.com/pocketbase/pocketbase/migrations" +) + +func init() { + m.Register(func(app core.App) error { + collection, err := app.FindCollectionByNameOrId("e864strfxo14pm4") + if err != nil { + return err + } + + // remove field + collection.Fields.RemoveById("ppq2sist") + + return app.Save(collection) + }, func(app core.App) error { + collection, err := app.FindCollectionByNameOrId("e864strfxo14pm4") + if err != nil { + return err + } + + // add field + if err := collection.Fields.AddMarshaledJSONAt(16, []byte(`{ + "cascadeDelete": false, + "collectionId": "goeo2ubp103rzp9", + "hidden": false, + "id": "ppq2sist", + "maxSelect": 2147483647, + "minSelect": 0, + "name": "waypoints", + "presentable": false, + "required": false, + "system": false, + "type": "relation" + }`)); err != nil { + return err + } + + return app.Save(collection) + }) +} diff --git a/web/src/lib/components/trail/trail_info_panel.svelte b/web/src/lib/components/trail/trail_info_panel.svelte index 47ebdb4c..d674441b 100644 --- a/web/src/lib/components/trail/trail_info_panel.svelte +++ b/web/src/lib/components/trail/trail_info_panel.svelte @@ -658,7 +658,7 @@

{$_("start")}

- {#each trail.expand?.waypoints ?? [] as wp, i} + {#each trail.expand?.waypoints_via_trail ?? [] as wp, i}