forked from MapComplete/MapComplete
		
	Add feature which loads the selected element from overpass to update the tags to the latest version
This commit is contained in:
		
							parent
							
								
									d7277838e4
								
							
						
					
					
						commit
						c6b4ba43fb
					
				
					 4 changed files with 91 additions and 25 deletions
				
			
		
							
								
								
									
										54
									
								
								Logic/Actors/UpdateTagsFromOsmAPI.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								Logic/Actors/UpdateTagsFromOsmAPI.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,54 @@
 | 
				
			||||||
 | 
					import {UIEventSource} from "../UIEventSource";
 | 
				
			||||||
 | 
					import {ElementStorage} from "../ElementStorage";
 | 
				
			||||||
 | 
					import {OsmObject, OsmObjectMeta} from "../Osm/OsmObject";
 | 
				
			||||||
 | 
					import SimpleMetaTagger from "../SimpleMetaTagger";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default class UpdateTagsFromOsmAPI {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static readonly metaTagger = new SimpleMetaTagger(
 | 
				
			||||||
 | 
					        ["_last_edit:contributor",
 | 
				
			||||||
 | 
					            "_last_edit:contributor:uid",
 | 
				
			||||||
 | 
					            "_last_edit:changeset",
 | 
				
			||||||
 | 
					            "_last_edit:timestamp",
 | 
				
			||||||
 | 
					            "_version_number"],
 | 
				
			||||||
 | 
					        "Information about the last edit of this object. \n\nIMPORTANT: this data is _only_ loaded when the popup is added. This means it should _not_ be used to render icons!",
 | 
				
			||||||
 | 
					        (feature: any, index: number, freshness: Date) => {/*Do nothing - this is only added for documentation reasons*/
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /***
 | 
				
			||||||
 | 
					     * This actor downloads the element from the OSM-API and updates the corresponding tags in the UI-updater.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    constructor(idToDownload: UIEventSource<string>, allElements: ElementStorage) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        idToDownload.addCallbackAndRun(id => {
 | 
				
			||||||
 | 
					            if (id === undefined) {
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            OsmObject.DownloadObject(id, (element: OsmObject, meta: OsmObjectMeta) => {
 | 
				
			||||||
 | 
					                console.log("Updating element from OSM-API: ", element)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                const tags = element.tags;
 | 
				
			||||||
 | 
					                tags["_last_edit:contributor"] = meta["_last_edit:contributor"]
 | 
				
			||||||
 | 
					                tags["_last_edit:contributor:uid"] = meta["_last_edit:contributor:uid"]
 | 
				
			||||||
 | 
					                tags["_last_edit:changeset"] = meta["_last_edit:changeset"]
 | 
				
			||||||
 | 
					                tags["_last_edit:timestamp"] = meta["_last_edit:timestamp"].toLocaleString()
 | 
				
			||||||
 | 
					                tags["_version_number"] = meta._version_number
 | 
				
			||||||
 | 
					                if (!allElements.has(id)) {
 | 
				
			||||||
 | 
					                    console.warn("Adding element by id")
 | 
				
			||||||
 | 
					                    allElements.addElementById(id, new UIEventSource<any>(tags))
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    // We merge
 | 
				
			||||||
 | 
					                    console.warn("merging by OSM API UPDATE")
 | 
				
			||||||
 | 
					                    allElements.addOrGetById(id, tags)
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -23,19 +23,34 @@ export class ElementStorage {
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    addOrGetElement(feature: any): UIEventSource<any> {
 | 
					    addOrGetElement(feature: any): UIEventSource<any> {
 | 
				
			||||||
        const elementId = feature.properties.id;
 | 
					        const elementId = feature.properties.id;
 | 
				
			||||||
        if (this._elements.has(elementId)) {
 | 
					        const newProperties = feature.properties;
 | 
				
			||||||
            const es = this._elements.get(elementId);
 | 
					
 | 
				
			||||||
            if (es.data == feature.properties) {
 | 
					        const es = this.addOrGetById(elementId, newProperties)
 | 
				
			||||||
                // Reference comparison gives the same object! we can just return the event source
 | 
					
 | 
				
			||||||
 | 
					        // At last, we overwrite the tag of the new feature to use the tags in the already existing event source
 | 
				
			||||||
 | 
					        feature.properties = es.data
 | 
				
			||||||
        return es;
 | 
					        return es;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    addOrGetById(elementId: string, newProperties: any): UIEventSource<any> {
 | 
				
			||||||
 | 
					        if (!this._elements.has(elementId)) {
 | 
				
			||||||
 | 
					            const eventSource = new UIEventSource<any>(newProperties, "tags of " + elementId);
 | 
				
			||||||
 | 
					            this._elements.set(elementId, eventSource);
 | 
				
			||||||
 | 
					            return eventSource;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const es = this._elements.get(elementId);
 | 
				
			||||||
 | 
					        if (es.data == newProperties) {
 | 
				
			||||||
 | 
					            // Reference comparison gives the same object! we can just return the event source
 | 
				
			||||||
 | 
					            return es;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        const keptKeys = es.data;
 | 
					        const keptKeys = es.data;
 | 
				
			||||||
        // The element already exists
 | 
					        // The element already exists
 | 
				
			||||||
            // We add all the new keys to the old keys
 | 
					        // We use the new feature to overwrite all the properties in the already existing eventsource
 | 
				
			||||||
        let somethingChanged = false;
 | 
					        let somethingChanged = false;
 | 
				
			||||||
            for (const k in feature.properties) {
 | 
					        for (const k in newProperties) {
 | 
				
			||||||
                const v = feature.properties[k];
 | 
					            const v = newProperties[k];
 | 
				
			||||||
            if (keptKeys[k] !== v) {
 | 
					            if (keptKeys[k] !== v) {
 | 
				
			||||||
                keptKeys[k] = v;
 | 
					                keptKeys[k] = v;
 | 
				
			||||||
                somethingChanged = true;
 | 
					                somethingChanged = true;
 | 
				
			||||||
| 
						 | 
					@ -44,13 +59,7 @@ export class ElementStorage {
 | 
				
			||||||
        if (somethingChanged) {
 | 
					        if (somethingChanged) {
 | 
				
			||||||
            es.ping();
 | 
					            es.ping();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					 | 
				
			||||||
        return es;
 | 
					        return es;
 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            const eventSource = new UIEventSource<any>(feature.properties, "tags of " + feature.properties.id);
 | 
					 | 
				
			||||||
            this._elements.set(feature.properties.id, eventSource);
 | 
					 | 
				
			||||||
            return eventSource;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    getEventSourceById(elementId): UIEventSource<any> {
 | 
					    getEventSourceById(elementId): UIEventSource<any> {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,6 +7,7 @@ import {Utils} from "../Utils";
 | 
				
			||||||
import opening_hours from "opening_hours";
 | 
					import opening_hours from "opening_hours";
 | 
				
			||||||
import {UIElement} from "../UI/UIElement";
 | 
					import {UIElement} from "../UI/UIElement";
 | 
				
			||||||
import Combine from "../UI/Base/Combine";
 | 
					import Combine from "../UI/Base/Combine";
 | 
				
			||||||
 | 
					import UpdateTagsFromOsmAPI from "./Actors/UpdateTagsFromOsmAPI";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class SimpleMetaTagger {
 | 
					export default class SimpleMetaTagger {
 | 
				
			||||||
    public readonly keys: string[];
 | 
					    public readonly keys: string[];
 | 
				
			||||||
| 
						 | 
					@ -330,7 +331,7 @@ export default class SimpleMetaTagger {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (const metatag of SimpleMetaTagger.metatags) {
 | 
					        for (const metatag of SimpleMetaTagger.metatags.concat(UpdateTagsFromOsmAPI.metaTagger)) {
 | 
				
			||||||
            subElements.push(
 | 
					            subElements.push(
 | 
				
			||||||
                new Combine([
 | 
					                new Combine([
 | 
				
			||||||
                    "<h3>", metatag.keys.join(", "), "</h3>",
 | 
					                    "<h3>", metatag.keys.join(", "), "</h3>",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										2
									
								
								State.ts
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								State.ts
									
										
									
									
									
								
							| 
						 | 
					@ -18,6 +18,7 @@ import LayerConfig from "./Customizations/JSON/LayerConfig";
 | 
				
			||||||
import TitleHandler from "./Logic/Actors/TitleHandler";
 | 
					import TitleHandler from "./Logic/Actors/TitleHandler";
 | 
				
			||||||
import PendingChangesUploader from "./Logic/Actors/PendingChangesUploader";
 | 
					import PendingChangesUploader from "./Logic/Actors/PendingChangesUploader";
 | 
				
			||||||
import {Relation} from "./Logic/Osm/ExtractRelations";
 | 
					import {Relation} from "./Logic/Osm/ExtractRelations";
 | 
				
			||||||
 | 
					import UpdateTagsFromOsmAPI from "./Logic/Actors/UpdateTagsFromOsmAPI";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Contains the global state: a bunch of UI-event sources
 | 
					 * Contains the global state: a bunch of UI-event sources
 | 
				
			||||||
| 
						 | 
					@ -252,6 +253,7 @@ export default class State {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        new TitleHandler(this.layoutToUse, this.selectedElement, this.allElements);
 | 
					        new TitleHandler(this.layoutToUse, this.selectedElement, this.allElements);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        new UpdateTagsFromOsmAPI(this.selectedElement.map(el => el?.properties?.id), this.allElements)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue