| 
									
										
										
										
											2020-11-18 12:50:28 +01:00
										 |  |  | import escapeHtml from "escape-html"; | 
					
						
							| 
									
										
										
										
											2021-01-04 04:36:21 +01:00
										 |  |  | // @ts-ignore
 | 
					
						
							| 
									
										
										
										
											2020-08-27 11:11:20 +02:00
										 |  |  | import {OsmConnection, UserDetails} from "./OsmConnection"; | 
					
						
							| 
									
										
										
										
											2020-08-26 15:36:04 +02:00
										 |  |  | import {UIEventSource} from "../UIEventSource"; | 
					
						
							| 
									
										
										
										
											2020-08-30 01:13:18 +02:00
										 |  |  | import {ElementStorage} from "../ElementStorage"; | 
					
						
							| 
									
										
										
										
											2020-10-02 19:00:24 +02:00
										 |  |  | import State from "../../State"; | 
					
						
							| 
									
										
										
										
											2020-09-21 23:57:50 +02:00
										 |  |  | import Locale from "../../UI/i18n/Locale"; | 
					
						
							| 
									
										
										
										
											2021-01-02 19:09:49 +01:00
										 |  |  | import Constants from "../../Models/Constants"; | 
					
						
							| 
									
										
										
										
											2021-09-26 23:35:26 +02:00
										 |  |  | import {Changes} from "./Changes"; | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  | import {Utils} from "../../Utils"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export interface ChangesetTag { | 
					
						
							|  |  |  |     key: string, | 
					
						
							|  |  |  |     value: string | number, | 
					
						
							|  |  |  |     aggregate?: boolean | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-08-26 15:36:04 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | export class ChangesetHandler { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |     public readonly currentChangeset: UIEventSource<number>; | 
					
						
							| 
									
										
										
										
											2021-09-26 23:35:26 +02:00
										 |  |  |     private readonly allElements: ElementStorage; | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |     private osmConnection: OsmConnection; | 
					
						
							| 
									
										
										
										
											2021-09-26 23:35:26 +02:00
										 |  |  |     private readonly changes: Changes; | 
					
						
							| 
									
										
										
										
											2020-09-15 02:29:31 +02:00
										 |  |  |     private readonly _dryRun: boolean; | 
					
						
							|  |  |  |     private readonly userDetails: UIEventSource<UserDetails>; | 
					
						
							|  |  |  |     private readonly auth: any; | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |     private readonly backend: string; | 
					
						
							| 
									
										
										
										
											2020-08-26 15:36:04 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |     constructor(layoutName: string, dryRun: boolean, | 
					
						
							|  |  |  |                 osmConnection: OsmConnection, | 
					
						
							| 
									
										
										
										
											2021-09-26 23:35:26 +02:00
										 |  |  |                 allElements: ElementStorage, | 
					
						
							|  |  |  |                 changes: Changes, | 
					
						
							|  |  |  |                 auth) { | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |         this.osmConnection = osmConnection; | 
					
						
							| 
									
										
										
										
											2021-09-26 23:35:26 +02:00
										 |  |  |         this.allElements = allElements; | 
					
						
							|  |  |  |         this.changes = changes; | 
					
						
							| 
									
										
										
										
											2020-08-26 15:36:04 +02:00
										 |  |  |         this._dryRun = dryRun; | 
					
						
							| 
									
										
										
										
											2020-08-27 11:11:20 +02:00
										 |  |  |         this.userDetails = osmConnection.userDetails; | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |         this.backend = osmConnection._oauth_config.url | 
					
						
							| 
									
										
										
										
											2020-08-26 15:36:04 +02:00
										 |  |  |         this.auth = auth; | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |         this.currentChangeset = osmConnection.GetPreference("current-open-changeset-" + layoutName).map( | 
					
						
							|  |  |  |             str => { | 
					
						
							|  |  |  |                 const n = Number(str); | 
					
						
							|  |  |  |                 if (isNaN(n)) { | 
					
						
							|  |  |  |                     return undefined | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 return n | 
					
						
							|  |  |  |             }, [], n => "" + n | 
					
						
							|  |  |  |         ); | 
					
						
							| 
									
										
										
										
											2020-08-26 15:36:04 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (dryRun) { | 
					
						
							|  |  |  |             console.log("DRYRUN ENABLED"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-30 18:48:23 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * The full logic to upload a change to one or more elements. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * This method will attempt to reuse an existing, open changeset for this theme (or open one if none available). | 
					
						
							|  |  |  |      * Then, it will upload a changes-xml within this changeset (and leave the changeset open) | 
					
						
							|  |  |  |      * When upload is successfull, eventual id-rewriting will be handled (aka: don't worry about that) | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * If 'dryrun' is specified, the changeset XML will be printed to console instead of being uploaded | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2021-09-26 23:35:26 +02:00
										 |  |  |     public async UploadChangeset( | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |         generateChangeXML: (csid: number) => string, | 
					
						
							|  |  |  |         extraMetaTags: ChangesetTag[]): Promise<void> { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!extraMetaTags.some(tag => tag.key === "comment") || !extraMetaTags.some(tag => tag.key === "theme")) { | 
					
						
							|  |  |  |             throw "The meta tags should at least contain a `comment` and a `theme`" | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-19 18:28:30 +02:00
										 |  |  |         if (this.userDetails.data.csCount == 0) { | 
					
						
							| 
									
										
										
										
											2020-09-15 02:29:31 +02:00
										 |  |  |             // The user became a contributor!
 | 
					
						
							|  |  |  |             this.userDetails.data.csCount = 1; | 
					
						
							|  |  |  |             this.userDetails.ping(); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-08-26 15:36:04 +02:00
										 |  |  |         if (this._dryRun) { | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |             const changesetXML = generateChangeXML(123456); | 
					
						
							| 
									
										
										
										
											2021-11-09 01:49:07 +01:00
										 |  |  |             console.log("Metatags are", extraMetaTags) | 
					
						
							| 
									
										
										
										
											2020-08-26 15:36:04 +02:00
										 |  |  |             console.log(changesetXML); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |         if (this.currentChangeset.data === undefined) { | 
					
						
							| 
									
										
										
										
											2020-08-27 11:11:20 +02:00
										 |  |  |             // We have to open a new changeset
 | 
					
						
							| 
									
										
										
										
											2021-09-26 23:35:26 +02:00
										 |  |  |             try { | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |                 const csId = await this.OpenChangeset(extraMetaTags) | 
					
						
							| 
									
										
										
										
											2020-08-27 11:11:20 +02:00
										 |  |  |                 this.currentChangeset.setData(csId); | 
					
						
							| 
									
										
										
										
											2020-08-27 18:44:16 +02:00
										 |  |  |                 const changeset = generateChangeXML(csId); | 
					
						
							| 
									
										
										
										
											2021-09-26 23:35:26 +02:00
										 |  |  |                 console.log("Current changeset is:", changeset); | 
					
						
							|  |  |  |                 await this.AddChange(csId, changeset) | 
					
						
							|  |  |  |             } catch (e) { | 
					
						
							|  |  |  |                 console.error("Could not open/upload changeset due to ", e) | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |                 this.currentChangeset.setData(undefined) | 
					
						
							| 
									
										
										
										
											2021-09-26 23:35:26 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-08-27 11:11:20 +02:00
										 |  |  |         } else { | 
					
						
							|  |  |  |             // There still exists an open changeset (or at least we hope so)
 | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |             // Let's check!
 | 
					
						
							| 
									
										
										
										
											2020-08-27 11:11:20 +02:00
										 |  |  |             const csId = this.currentChangeset.data; | 
					
						
							| 
									
										
										
										
											2021-09-26 23:35:26 +02:00
										 |  |  |             try { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |                 const oldChangesetMeta = await this.GetChangesetMeta(csId) | 
					
						
							|  |  |  |                 if (!oldChangesetMeta.open) { | 
					
						
							|  |  |  |                     // Mark the CS as closed...
 | 
					
						
							|  |  |  |                     this.currentChangeset.setData(undefined); | 
					
						
							|  |  |  |                     // ... and try again. As the cs is closed, no recursive loop can exist  
 | 
					
						
							|  |  |  |                     await this.UploadChangeset(generateChangeXML, extraMetaTags) | 
					
						
							|  |  |  |                     return; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 const extraTagsById = new Map<string, ChangesetTag>() | 
					
						
							|  |  |  |                 for (const extraMetaTag of extraMetaTags) { | 
					
						
							|  |  |  |                     extraTagsById.set(extraMetaTag.key, extraMetaTag) | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 const oldCsTags = oldChangesetMeta.tags | 
					
						
							|  |  |  |                 for (const key in oldCsTags) { | 
					
						
							|  |  |  |                     const newMetaTag = extraTagsById.get(key) | 
					
						
							|  |  |  |                     if (newMetaTag === undefined) { | 
					
						
							|  |  |  |                         extraMetaTags.push({ | 
					
						
							|  |  |  |                             key: key, | 
					
						
							|  |  |  |                             value: oldCsTags[key] | 
					
						
							|  |  |  |                         }) | 
					
						
							|  |  |  |                     } else if (newMetaTag.aggregate) { | 
					
						
							|  |  |  |                         let n = Number(newMetaTag.value) | 
					
						
							|  |  |  |                         if (isNaN(n)) { | 
					
						
							|  |  |  |                             n = 0 | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                         let o = Number(oldCsTags[key]) | 
					
						
							|  |  |  |                         if (isNaN(o)) { | 
					
						
							|  |  |  |                             o = 0 | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                         // We _update_ the tag itself, as it'll be updated in 'extraMetaTags' straight away
 | 
					
						
							|  |  |  |                         newMetaTag.value = "" + (n + o) | 
					
						
							|  |  |  |                     } else { | 
					
						
							|  |  |  |                         // The old value is overwritten, thus we drop
 | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |                 await this.UpdateTags(csId, extraMetaTags.map(csTag => <[string, string]>[csTag.key, csTag.value])) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-26 23:35:26 +02:00
										 |  |  |                 await this.AddChange( | 
					
						
							|  |  |  |                     csId, | 
					
						
							|  |  |  |                     generateChangeXML(csId)) | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-26 23:35:26 +02:00
										 |  |  |             } catch (e) { | 
					
						
							|  |  |  |                 console.warn("Could not upload, changeset is probably closed: ", e); | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |                 this.currentChangeset.setData(undefined); | 
					
						
							| 
									
										
										
										
											2021-09-26 23:35:26 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-08-27 11:11:20 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-08-26 15:36:04 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  |     private handleIdRewrite(node: any, type: string): [string, string] { | 
					
						
							|  |  |  |         const oldId = parseInt(node.attributes.old_id.value); | 
					
						
							|  |  |  |         if (node.attributes.new_id === undefined) { | 
					
						
							|  |  |  |             // We just removed this point!
 | 
					
						
							|  |  |  |             const element = this.allElements.getEventSourceById("node/" + oldId); | 
					
						
							|  |  |  |             element.data._deleted = "yes" | 
					
						
							|  |  |  |             element.ping(); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const newId = parseInt(node.attributes.new_id.value); | 
					
						
							|  |  |  |         const result: [string, string] = [type + "/" + oldId, type + "/" + newId] | 
					
						
							|  |  |  |         if (!(oldId !== undefined && newId !== undefined && | 
					
						
							|  |  |  |             !isNaN(oldId) && !isNaN(newId))) { | 
					
						
							|  |  |  |             return undefined; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (oldId == newId) { | 
					
						
							|  |  |  |             return undefined; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         console.log("Rewriting id: ", type + "/" + oldId, "-->", type + "/" + newId); | 
					
						
							|  |  |  |         const element = this.allElements.getEventSourceById("node/" + oldId); | 
					
						
							|  |  |  |         if (element === undefined) { | 
					
						
							|  |  |  |             // Element to rewrite not found, probably a node or relation that is not rendered
 | 
					
						
							|  |  |  |             return undefined | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         element.data.id = type + "/" + newId; | 
					
						
							|  |  |  |         this.allElements.addElementById(type + "/" + newId, element); | 
					
						
							|  |  |  |         this.allElements.ContainingFeatures.set(type + "/" + newId, this.allElements.ContainingFeatures.get(type + "/" + oldId)) | 
					
						
							|  |  |  |         element.ping(); | 
					
						
							|  |  |  |         return result; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private parseUploadChangesetResponse(response: XMLDocument): void { | 
					
						
							|  |  |  |         const nodes = response.getElementsByTagName("node"); | 
					
						
							|  |  |  |         const mappings = new Map<string, string>() | 
					
						
							|  |  |  |         // @ts-ignore
 | 
					
						
							|  |  |  |         for (const node of nodes) { | 
					
						
							|  |  |  |             const mapping = this.handleIdRewrite(node, "node") | 
					
						
							|  |  |  |             if (mapping !== undefined) { | 
					
						
							|  |  |  |                 mappings.set(mapping[0], mapping[1]) | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const ways = response.getElementsByTagName("way"); | 
					
						
							|  |  |  |         // @ts-ignore
 | 
					
						
							|  |  |  |         for (const way of ways) { | 
					
						
							|  |  |  |             const mapping = this.handleIdRewrite(way, "way") | 
					
						
							|  |  |  |             if (mapping !== undefined) { | 
					
						
							|  |  |  |                 mappings.set(mapping[0], mapping[1]) | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         this.changes.registerIdRewrites(mappings) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-06-30 18:48:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |     private async CloseChangeset(changesetId: number = undefined): Promise<void> { | 
					
						
							| 
									
										
										
										
											2021-09-26 23:35:26 +02:00
										 |  |  |         const self = this | 
					
						
							|  |  |  |         return new Promise<void>(function (resolve, reject) { | 
					
						
							|  |  |  |             if (changesetId === undefined) { | 
					
						
							|  |  |  |                 changesetId = self.currentChangeset.data; | 
					
						
							| 
									
										
										
										
											2021-06-19 18:28:30 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-09-26 23:35:26 +02:00
										 |  |  |             if (changesetId === undefined) { | 
					
						
							|  |  |  |                 return; | 
					
						
							| 
									
										
										
										
											2021-06-19 18:28:30 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-09-26 23:35:26 +02:00
										 |  |  |             console.log("closing changeset", changesetId); | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |             self.currentChangeset.setData(undefined); | 
					
						
							| 
									
										
										
										
											2021-09-26 23:35:26 +02:00
										 |  |  |             self.auth.xhr({ | 
					
						
							|  |  |  |                 method: 'PUT', | 
					
						
							|  |  |  |                 path: '/api/0.6/changeset/' + changesetId + '/close', | 
					
						
							|  |  |  |             }, function (err, response) { | 
					
						
							|  |  |  |                 if (response == null) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     console.log("err", err); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 console.log("Closed changeset ", changesetId) | 
					
						
							|  |  |  |                 resolve() | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  |         }) | 
					
						
							| 
									
										
										
										
											2021-06-19 18:28:30 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-08-26 15:36:04 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |     private async GetChangesetMeta(csId: number): Promise<{ | 
					
						
							|  |  |  |         id: number, | 
					
						
							|  |  |  |         open: boolean, | 
					
						
							|  |  |  |         uid: number, | 
					
						
							|  |  |  |         changes_count: number, | 
					
						
							|  |  |  |         tags: any | 
					
						
							|  |  |  |     }> { | 
					
						
							|  |  |  |         const url = `${this.backend}/api/0.6/changeset/${csId}` | 
					
						
							|  |  |  |         const csData = await Utils.downloadJson(url) | 
					
						
							|  |  |  |         return csData.elements[0] | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private async UpdateTags( | 
					
						
							|  |  |  |         csId: number, | 
					
						
							|  |  |  |         tags: [string, string][]) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-26 23:35:26 +02:00
										 |  |  |         const self = this; | 
					
						
							|  |  |  |         return new Promise<string>(function (resolve, reject) { | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             tags = Utils.NoNull(tags).filter(([k, v]) => k !== undefined && v !== undefined && k !== "" && v !== "") | 
					
						
							|  |  |  |             const metadata = tags.map(kv => `<tag k="${kv[0]}" v="${escapeHtml(kv[1])}"/>`) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             self.auth.xhr({ | 
					
						
							|  |  |  |                 method: 'PUT', | 
					
						
							|  |  |  |                 path: '/api/0.6/changeset/' + csId, | 
					
						
							|  |  |  |                 options: {header: {'Content-Type': 'text/xml'}}, | 
					
						
							|  |  |  |                 content: [`<osm><changeset>`, | 
					
						
							|  |  |  |                     metadata, | 
					
						
							|  |  |  |                     `</changeset></osm>`].join("") | 
					
						
							|  |  |  |             }, function (err, response) { | 
					
						
							|  |  |  |                 if (response === undefined) { | 
					
						
							|  |  |  |                     console.log("err", err); | 
					
						
							|  |  |  |                     reject(err) | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     resolve(response); | 
					
						
							| 
									
										
										
										
											2021-09-26 23:35:26 +02:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |             }); | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private OpenChangeset( | 
					
						
							|  |  |  |         changesetTags: ChangesetTag[] | 
					
						
							|  |  |  |     ): Promise<number> { | 
					
						
							|  |  |  |         const self = this; | 
					
						
							|  |  |  |         return new Promise<number>(function (resolve, reject) { | 
					
						
							| 
									
										
										
										
											2020-09-30 22:22:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-26 23:35:26 +02:00
										 |  |  |             let path = window.location.pathname; | 
					
						
							|  |  |  |             path = path.substr(1, path.lastIndexOf("/")); | 
					
						
							|  |  |  |             const metadata = [ | 
					
						
							|  |  |  |                 ["created_by", `MapComplete ${Constants.vNumber}`], | 
					
						
							|  |  |  |                 ["language", Locale.language.data], | 
					
						
							|  |  |  |                 ["host", window.location.host], | 
					
						
							|  |  |  |                 ["path", path], | 
					
						
							| 
									
										
										
										
											2021-11-08 02:36:01 +01:00
										 |  |  |                 ["source", State.state.currentUserLocation.features.data.length > 0 ? "survey" : undefined], | 
					
						
							| 
									
										
										
										
											2021-09-26 23:35:26 +02:00
										 |  |  |                 ["imagery", State.state.backgroundLayer.data.id], | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |                 ...changesetTags.map(cstag => [cstag.key, cstag.value]) | 
					
						
							| 
									
										
										
										
											2021-09-26 23:35:26 +02:00
										 |  |  |             ] | 
					
						
							|  |  |  |                 .filter(kv => (kv[1] ?? "") !== "") | 
					
						
							|  |  |  |                 .map(kv => `<tag k="${kv[0]}" v="${escapeHtml(kv[1])}"/>`) | 
					
						
							|  |  |  |                 .join("\n") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             self.auth.xhr({ | 
					
						
							|  |  |  |                 method: 'PUT', | 
					
						
							|  |  |  |                 path: '/api/0.6/changeset/create', | 
					
						
							|  |  |  |                 options: {header: {'Content-Type': 'text/xml'}}, | 
					
						
							|  |  |  |                 content: [`<osm><changeset>`, | 
					
						
							|  |  |  |                     metadata, | 
					
						
							|  |  |  |                     `</changeset></osm>`].join("") | 
					
						
							|  |  |  |             }, function (err, response) { | 
					
						
							|  |  |  |                 if (response === undefined) { | 
					
						
							|  |  |  |                     console.log("err", err); | 
					
						
							|  |  |  |                     reject(err) | 
					
						
							|  |  |  |                 } else { | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |                     resolve(Number(response)); | 
					
						
							| 
									
										
										
										
											2021-07-13 00:40:27 +02:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2021-09-26 23:35:26 +02:00
										 |  |  |             }); | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-26 15:36:04 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-30 18:48:23 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Upload a changesetXML | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |     private AddChange(changesetId: number, | 
					
						
							|  |  |  |                       changesetXML: string): Promise<number> { | 
					
						
							| 
									
										
										
										
											2021-09-26 23:35:26 +02:00
										 |  |  |         const self = this; | 
					
						
							|  |  |  |         return new Promise(function (resolve, reject) { | 
					
						
							|  |  |  |             self.auth.xhr({ | 
					
						
							|  |  |  |                 method: 'POST', | 
					
						
							|  |  |  |                 options: {header: {'Content-Type': 'text/xml'}}, | 
					
						
							|  |  |  |                 path: '/api/0.6/changeset/' + changesetId + '/upload', | 
					
						
							|  |  |  |                 content: changesetXML | 
					
						
							|  |  |  |             }, function (err, response) { | 
					
						
							|  |  |  |                 if (response == null) { | 
					
						
							|  |  |  |                     console.log("err", err); | 
					
						
							|  |  |  |                     reject(err); | 
					
						
							| 
									
										
										
										
											2020-08-27 11:11:20 +02:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2021-09-26 23:35:26 +02:00
										 |  |  |                 self.parseUploadChangesetResponse(response); | 
					
						
							|  |  |  |                 console.log("Uploaded changeset ", changesetId); | 
					
						
							|  |  |  |                 resolve(changesetId); | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-26 15:36:04 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |