forked from MapComplete/MapComplete
		
	Some cleanup of changesetHandler, add import source with reference to the note
This commit is contained in:
		
							parent
							
								
									7f222bce11
								
							
						
					
					
						commit
						5cefc4d25f
					
				
					 4 changed files with 129 additions and 55 deletions
				
			
		|  | @ -23,6 +23,7 @@ export default class CreateNewNodeAction extends OsmCreateAction { | |||
|     private meta: { changeType: "create" | "import"; theme: string; specialMotivation?: string }; | ||||
|     private readonly _reusePreviouslyCreatedPoint: boolean; | ||||
| 
 | ||||
|      | ||||
|     constructor(basicTags: Tag[], | ||||
|                 lat: number, lon: number, | ||||
|                 options: { | ||||
|  | @ -46,7 +47,7 @@ export default class CreateNewNodeAction extends OsmCreateAction { | |||
|         this.meta = { | ||||
|             theme: options.theme, | ||||
|             changeType: options.changeType, | ||||
| 
 | ||||
|             specialMotivation: options.specialMotivation | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | @ -67,6 +68,7 @@ export default class CreateNewNodeAction extends OsmCreateAction { | |||
|     } | ||||
| 
 | ||||
|     async CreateChangeDescriptions(changes: Changes): Promise<ChangeDescription[]> { | ||||
| 
 | ||||
|         if (this._reusePreviouslyCreatedPoint) { | ||||
| 
 | ||||
|             const key = this._lat + "," + this._lon | ||||
|  | @ -139,7 +141,7 @@ export default class CreateNewNodeAction extends OsmCreateAction { | |||
| 
 | ||||
|         locations.splice(index + 1, 0, [this._lon, this._lat]) | ||||
|         ids.splice(index + 1, 0, id) | ||||
| 
 | ||||
|          | ||||
|         // Allright, we have to insert a new point in the way
 | ||||
|         return [ | ||||
|             newPointChange, | ||||
|  |  | |||
|  | @ -43,6 +43,30 @@ export class ChangesetHandler { | |||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * If the metatags contain a special motivation of the format "<change-type>:node/-<number>", this method will rewrite this negative number to the actual ID | ||||
|      * The key is changed _in place_; true will be returned if a change has been applied | ||||
|      * @param extraMetaTags | ||||
|      * @param rewriteIds | ||||
|      * @private | ||||
|      */ | ||||
|     private static rewriteMetaTags(extraMetaTags: ChangesetTag[], rewriteIds: Map<string, string>) { | ||||
|         let hasChange = false; | ||||
|         for (const tag of extraMetaTags) { | ||||
|             const match = tag.key.match(/^([a-zA-Z0-9_]+):(node\/-[0-9])$/) | ||||
|             if (match == null) { | ||||
|                 continue | ||||
|             } | ||||
|             // This is a special motivation which has a negative ID -> we check for rewrites
 | ||||
|             const [_, reason, id] = match | ||||
|             if (rewriteIds.has(id)) { | ||||
|                 tag.key = reason + ":" + rewriteIds.get(id) | ||||
|                 hasChange = true | ||||
|             } | ||||
|         } | ||||
|         return hasChange | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * The full logic to upload a change to one or more elements. | ||||
|      * | ||||
|  | @ -81,7 +105,13 @@ export class ChangesetHandler { | |||
|                 openChangeset.setData(csId); | ||||
|                 const changeset = generateChangeXML(csId); | ||||
|                 console.trace("Opened a new changeset (openChangeset.data is undefined):", changeset); | ||||
|                 await this.AddChange(csId, changeset) | ||||
|                 const changes = await this.AddChange(csId, changeset) | ||||
|                 const hasSpecialMotivationChanges = ChangesetHandler.rewriteMetaTags(extraMetaTags, changes) | ||||
|                 if(hasSpecialMotivationChanges){ | ||||
|                     // At this point, 'extraMetaTags' will have changed - we need to set the tags again
 | ||||
|                     this.UpdateTags(csId, extraMetaTags) | ||||
|                 } | ||||
|                  | ||||
|             } catch (e) { | ||||
|                 console.error("Could not open/upload changeset due to ", e) | ||||
|                 openChangeset.setData(undefined) | ||||
|  | @ -91,6 +121,7 @@ export class ChangesetHandler { | |||
|             // Let's check!
 | ||||
|             const csId = openChangeset.data; | ||||
|             try { | ||||
| 
 | ||||
|                 const oldChangesetMeta = await this.GetChangesetMeta(csId) | ||||
|                 if (!oldChangesetMeta.open) { | ||||
|                     // Mark the CS as closed...
 | ||||
|  | @ -101,41 +132,11 @@ export class ChangesetHandler { | |||
|                     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
 | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 await this.UpdateTags(csId, extraMetaTags.map(csTag => <[string, string]>[csTag.key, csTag.value])) | ||||
| 
 | ||||
| 
 | ||||
|                 await this.AddChange( | ||||
|                 const rewritings = await this.AddChange( | ||||
|                     csId, | ||||
|                     generateChangeXML(csId)) | ||||
| 
 | ||||
|                 await this.RewriteTagsOf(extraMetaTags, rewritings, oldChangesetMeta) | ||||
| 
 | ||||
|             } catch (e) { | ||||
|                 console.warn("Could not upload, changeset is probably closed: ", e); | ||||
|  | @ -144,6 +145,74 @@ export class ChangesetHandler { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Updates the metatag of a changeset - | ||||
|      * @param extraMetaTags: new changeset tags to add/fuse with this changeset | ||||
|      * @param oldChangesetMeta: the metadata-object of the already existing changeset | ||||
|      * @constructor | ||||
|      * @private | ||||
|      */ | ||||
|     private async RewriteTagsOf(extraMetaTags: ChangesetTag[], | ||||
|                                 rewriteIds: Map<string, string>, | ||||
|                                 oldChangesetMeta: { | ||||
|                                     open: boolean, | ||||
|                                     id: number | ||||
|                                     uid: number, // User ID
 | ||||
|                                     changes_count: number, | ||||
|                                     tags: any | ||||
|                                 }) { | ||||
| 
 | ||||
|         const csId = oldChangesetMeta.id | ||||
| 
 | ||||
|         // Note: extraMetaTags is where all the tags are collected into
 | ||||
| 
 | ||||
|         // same as 'extraMetaTag', but indexed
 | ||||
|         // Note that updates to 'extraTagsById.get(<key>).value = XYZ' is shared with extraMetatags
 | ||||
|         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) | ||||
|             const existingValue = oldCsTags[key] | ||||
| 
 | ||||
|             if (newMetaTag !== undefined && newMetaTag.value === existingValue) { | ||||
|                 continue | ||||
|             } | ||||
|             if (newMetaTag === undefined) { | ||||
|                 extraMetaTags.push({ | ||||
|                     key: key, | ||||
|                     value: oldCsTags[key] | ||||
|                 }) | ||||
|                 continue | ||||
|             } | ||||
| 
 | ||||
|             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 this old key
 | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         ChangesetHandler.rewriteMetaTags(extraMetaTags, rewriteIds) | ||||
| 
 | ||||
|         await this.UpdateTags(csId, extraMetaTags) | ||||
| 
 | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     private handleIdRewrite(node: any, type: string): [string, string] { | ||||
|         const oldId = parseInt(node.attributes.old_id.value); | ||||
|         if (node.attributes.new_id === undefined) { | ||||
|  | @ -163,7 +232,6 @@ export class ChangesetHandler { | |||
|         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
 | ||||
|  | @ -176,7 +244,7 @@ export class ChangesetHandler { | |||
|         return result; | ||||
|     } | ||||
| 
 | ||||
|     private parseUploadChangesetResponse(response: XMLDocument): void { | ||||
|     private parseUploadChangesetResponse(response: XMLDocument): Map<string, string> { | ||||
|         const nodes = response.getElementsByTagName("node"); | ||||
|         const mappings = new Map<string, string>() | ||||
|         // @ts-ignore
 | ||||
|  | @ -196,6 +264,7 @@ export class ChangesetHandler { | |||
|             } | ||||
|         } | ||||
|         this.changes.registerIdRewrites(mappings) | ||||
|         return mappings | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|  | @ -205,7 +274,6 @@ export class ChangesetHandler { | |||
|             if (changesetId === undefined) { | ||||
|                 return; | ||||
|             } | ||||
|             console.log("closing changeset", changesetId); | ||||
|             self.auth.xhr({ | ||||
|                 method: 'PUT', | ||||
|                 path: '/api/0.6/changeset/' + changesetId + '/close', | ||||
|  | @ -232,15 +300,21 @@ export class ChangesetHandler { | |||
|         return csData.elements[0] | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /** | ||||
|      * Puts the specified tags onto the changesets as they are. | ||||
|      * This method will erase previously set tags | ||||
|      */ | ||||
|     private async UpdateTags( | ||||
|         csId: number, | ||||
|         tags: [string, string][]) { | ||||
|         tags: ChangesetTag[]) { | ||||
| 
 | ||||
|         console.trace("Updating tags of " + csId) | ||||
|         const self = this; | ||||
|         return new Promise<string>(function (resolve, reject) { | ||||
| 
 | ||||
|             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])}"/>`) | ||||
|             tags = Utils.NoNull(tags).filter(tag => tag.key !== undefined && tag.value !== undefined && tag.key !== "" && tag.value !== "") | ||||
|             const metadata = tags.map(kv => `<tag k="${kv.key}" v="${escapeHtml(kv.value)}"/>`) | ||||
| 
 | ||||
|             self.auth.xhr({ | ||||
|                 method: 'PUT', | ||||
|  | @ -258,7 +332,6 @@ export class ChangesetHandler { | |||
|                 } | ||||
|             }); | ||||
|         }) | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     private OpenChangeset( | ||||
|  | @ -306,7 +379,7 @@ export class ChangesetHandler { | |||
|      * Upload a changesetXML | ||||
|      */ | ||||
|     private AddChange(changesetId: number, | ||||
|                       changesetXML: string): Promise<number> { | ||||
|                       changesetXML: string): Promise<Map<string, string>> { | ||||
|         const self = this; | ||||
|         return new Promise(function (resolve, reject) { | ||||
|             self.auth.xhr({ | ||||
|  | @ -319,9 +392,9 @@ export class ChangesetHandler { | |||
|                     console.log("err", err); | ||||
|                     reject(err); | ||||
|                 } | ||||
|                 self.parseUploadChangesetResponse(response); | ||||
|                 const changes = self.parseUploadChangesetResponse(response); | ||||
|                 console.log("Uploaded changeset ", changesetId); | ||||
|                 resolve(changesetId); | ||||
|                 resolve(changes); | ||||
|             }); | ||||
|         }) | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue