diff --git a/Logic/Actors/UpdateTagsFromOsmAPI.ts b/Logic/Actors/UpdateTagsFromOsmAPI.ts new file mode 100644 index 0000000..cdf0863 --- /dev/null +++ b/Logic/Actors/UpdateTagsFromOsmAPI.ts @@ -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, 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(tags)) + } else { + // We merge + console.warn("merging by OSM API UPDATE") + allElements.addOrGetById(id, tags) + } + }) + }) + + } + + +} \ No newline at end of file diff --git a/Logic/ElementStorage.ts b/Logic/ElementStorage.ts index 553d305..88e4ab1 100644 --- a/Logic/ElementStorage.ts +++ b/Logic/ElementStorage.ts @@ -23,34 +23,43 @@ export class ElementStorage { */ addOrGetElement(feature: any): UIEventSource { const elementId = feature.properties.id; - if (this._elements.has(elementId)) { - const es = this._elements.get(elementId); - if (es.data == feature.properties) { - // Reference comparison gives the same object! we can just return the event source - return es; - } + const newProperties = feature.properties; - const keptKeys = es.data; - // The element already exists - // We add all the new keys to the old keys - let somethingChanged = false; - for (const k in feature.properties) { - const v = feature.properties[k]; - if (keptKeys[k] !== v) { - keptKeys[k] = v; - somethingChanged = true; - } - } - if (somethingChanged) { - es.ping(); - } + const es = this.addOrGetById(elementId, newProperties) - return es; - } else { - const eventSource = new UIEventSource(feature.properties, "tags of " + feature.properties.id); - this._elements.set(feature.properties.id, eventSource); + // 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; + } + + addOrGetById(elementId: string, newProperties: any): UIEventSource { + if (!this._elements.has(elementId)) { + const eventSource = new UIEventSource(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; + // The element already exists + // We use the new feature to overwrite all the properties in the already existing eventsource + let somethingChanged = false; + for (const k in newProperties) { + const v = newProperties[k]; + if (keptKeys[k] !== v) { + keptKeys[k] = v; + somethingChanged = true; + } + } + if (somethingChanged) { + es.ping(); + } + return es; } getEventSourceById(elementId): UIEventSource { diff --git a/Logic/SimpleMetaTagger.ts b/Logic/SimpleMetaTagger.ts index 7a059a2..833566e 100644 --- a/Logic/SimpleMetaTagger.ts +++ b/Logic/SimpleMetaTagger.ts @@ -7,6 +7,7 @@ import {Utils} from "../Utils"; import opening_hours from "opening_hours"; import {UIElement} from "../UI/UIElement"; import Combine from "../UI/Base/Combine"; +import UpdateTagsFromOsmAPI from "./Actors/UpdateTagsFromOsmAPI"; export default class SimpleMetaTagger { 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( new Combine([ "

", metatag.keys.join(", "), "

", diff --git a/State.ts b/State.ts index 7fd9997..9da68bd 100644 --- a/State.ts +++ b/State.ts @@ -18,6 +18,7 @@ import LayerConfig from "./Customizations/JSON/LayerConfig"; import TitleHandler from "./Logic/Actors/TitleHandler"; import PendingChangesUploader from "./Logic/Actors/PendingChangesUploader"; import {Relation} from "./Logic/Osm/ExtractRelations"; +import UpdateTagsFromOsmAPI from "./Logic/Actors/UpdateTagsFromOsmAPI"; /** * 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 UpdateTagsFromOsmAPI(this.selectedElement.map(el => el?.properties?.id), this.allElements) }