From 9cd83af941f6ba3bddffdf6646a07e678d55d31e Mon Sep 17 00:00:00 2001 From: pietervdvn Date: Wed, 16 Feb 2022 00:56:48 +0100 Subject: [PATCH] Add 'upload GPX-trace to OSM' code, small improvements to gps_track-layer --- Logic/GeoOperations.ts | 2 +- Logic/Osm/OsmConnection.ts | 81 ++++++++++++++++++- UI/Popup/LoginButton.ts | 1 - .../gps_location_history.json | 15 +++- assets/tagRenderings/questions.json | 5 +- 5 files changed, 98 insertions(+), 6 deletions(-) diff --git a/Logic/GeoOperations.ts b/Logic/GeoOperations.ts index 9c0bad52c..c05ca387c 100644 --- a/Logic/GeoOperations.ts +++ b/Logic/GeoOperations.ts @@ -340,7 +340,7 @@ export class GeoOperations { return turf.lineIntersect(feature, otherFeature).features.map(p => <[number, number]>p.geometry.coordinates) } - public static AsGpx(feature, generatedWithLayer?: LayerConfig) { + public static AsGpx(feature, generatedWithLayer?: LayerConfig) : string{ const metadata = {} const tags = feature.properties diff --git a/Logic/Osm/OsmConnection.ts b/Logic/Osm/OsmConnection.ts index 2ff689f40..b7e296d42 100644 --- a/Logic/Osm/OsmConnection.ts +++ b/Logic/Osm/OsmConnection.ts @@ -9,6 +9,7 @@ import Img from "../../UI/Base/Img"; import {Utils} from "../../Utils"; import {OsmObject} from "./OsmObject"; import {Changes} from "./Changes"; +import {GeoOperations} from "../GeoOperations"; export default class UserDetails { @@ -30,10 +31,13 @@ export default class UserDetails { export class OsmConnection { public static readonly oauth_configs = { + "osm": { oauth_consumer_key: 'hivV7ec2o49Two8g9h8Is1VIiVOgxQ1iYexCbvem', oauth_secret: 'wDBRTCem0vxD7txrg1y6p5r8nvmz8tAhET7zDASI', url: "https://www.openstreetmap.org" + // OAUTH 1.0 application + // https://www.openstreetmap.org/user/Pieter%20Vander%20Vennet/oauth_clients/7404 }, "osm-test": { oauth_consumer_key: 'Zgr7EoKb93uwPv2EOFkIlf3n9NLwj5wbyfjZMhz2', @@ -312,7 +316,82 @@ export class OsmConnection { }) } - + + public async uploadGpxTrack(geojson: any, options: { + description: string, + visibility: "private" | "public" | "trackable" | "identifiable", + filename?: string + /** + * Some words to give some properties; + * + * Note: these are called 'tags' on the wiki, but I opted to name them 'labels' instead as they aren't "key=value" tags, but just words. + */ + labels: string[] + }): Promise<{ id: number }> { + const gpx = GeoOperations.AsGpx(geojson) + if (this._dryRun.data) { + console.warn("Dryrun enabled - not actually uploading GPX ", gpx) + return new Promise<{ id: number }>((ok, error) => { + window.setTimeout(() => ok({id: Math.floor(Math.random() * 1000)}), Math.random() * 5000) + }); + } + + const contents = { + "file": gpx, + "description": options.description, + "tags": options.labels.join(","), + "visibility": options.visibility + } + + const extras = { + "file": "; filename=\""+options.filename+"\"\r\nContent-Type: application/gpx+xml" + } + + const auth = this.auth; + const boundary ="987654" + + var body = "" + for (var key in contents) { + body += "--" + boundary + "\r\n" + body += "Content-Disposition: form-data; name=\"" + key + "\"" + if(extras[key] !== undefined){ + body += extras[key] + } + body += "\r\n\r\n" + body += contents[key] + "\r\n" + } + body += "--" + boundary + "--\r\n" + + + return new Promise((ok, error) => { + auth.xhr({ + method: 'POST', + path: `/api/0.6/gpx/create`, + options: { + header: + { + "Content-Type": "multipart/form-data; boundary=" + boundary, + "Content-Length": body.length + } + }, + content: body + + }, function ( + err, + response: string) { + console.log("RESPONSE IS", response) + if (err !== null) { + error(err) + } else { + const parsed = JSON.parse(response) + console.log("Uploaded GPX track", parsed) + ok({id: parsed}) + } + }) + }) + + } + public addCommentToNode(id: number | string, text: string): Promise { if (this._dryRun.data) { console.warn("Dryrun enabled - not actually adding comment ", text, "to note ", id) diff --git a/UI/Popup/LoginButton.ts b/UI/Popup/LoginButton.ts index dd16d6411..ecf859daf 100644 --- a/UI/Popup/LoginButton.ts +++ b/UI/Popup/LoginButton.ts @@ -28,7 +28,6 @@ export class LoginToggle extends VariableUiElement { const login = new LoginButton(text, state) super( state.osmConnection.loadingStatus.map(osmConnectionState => { - console.trace("Current osm state is ", osmConnectionState) if(osmConnectionState === "loading"){ return loading } diff --git a/assets/layers/gps_location_history/gps_location_history.json b/assets/layers/gps_location_history/gps_location_history.json index 056ce5980..42c531546 100644 --- a/assets/layers/gps_location_history/gps_location_history.json +++ b/assets/layers/gps_location_history/gps_location_history.json @@ -1,11 +1,22 @@ { "id": "gps_location_history", "description": "Meta layer which contains the previous locations of the user as single points. This is mainly for technical reasons, e.g. to keep match the distance to the modified object", - "minzoom": 0, + "minzoom": 1, + "name": { + "en": "Location history as points", + "nl": "Locatiegeschiedenis als punten" + }, "source": { "osmTags": "user:location=yes", "#": "Cache is disabled here as these points are kept seperately", "maxCacheAge": 0 }, - "mapRendering": null + "shownByDefault": false, + "mapRendering":[ + { + "location": ["point","centroid"], + "icon": "square:red", + "iconSize": "5,5,center" + } + ] } \ No newline at end of file diff --git a/assets/tagRenderings/questions.json b/assets/tagRenderings/questions.json index 18eff119c..dca93cc94 100644 --- a/assets/tagRenderings/questions.json +++ b/assets/tagRenderings/questions.json @@ -9,6 +9,9 @@ "export_as_gpx": { "render": "{export_as_gpx()}" }, + "export_as_geojson": { + "render": "{export_as_geojson()}" + }, "wikipedia": { "render": "{wikipedia():max-height:25rem}", "question": { @@ -828,4 +831,4 @@ } ] } -} \ No newline at end of file +}