From 89d4a6bcceca09b2a992d3822c20e2c4be819708 Mon Sep 17 00:00:00 2001 From: pietervdvn Date: Wed, 20 Oct 2021 00:09:40 +0200 Subject: [PATCH] Add robustness when run via console, formatting --- Logic/Actors/AvailableBaseLayers.ts | 4 +- Logic/Actors/BackgroundLayerResetter.ts | 6 + Logic/Actors/PendingChangesUploader.ts | 5 + Logic/Actors/SelectedElementTagsUpdater.ts | 142 ++++++++++++--------- Logic/Actors/TitleHandler.ts | 4 + Logic/ImageProviders/AllImageProviders.ts | 6 +- Logic/ImageProviders/ImgurUploader.ts | 3 +- Logic/Osm/Changes.ts | 3 +- Logic/Osm/OsmObject.ts | 6 +- Logic/State/FeatureSwitchState.ts | 3 +- Logic/UIEventSource.ts | 3 + 11 files changed, 118 insertions(+), 67 deletions(-) diff --git a/Logic/Actors/AvailableBaseLayers.ts b/Logic/Actors/AvailableBaseLayers.ts index ce77e46d7d..89a5435e6a 100644 --- a/Logic/Actors/AvailableBaseLayers.ts +++ b/Logic/Actors/AvailableBaseLayers.ts @@ -23,11 +23,11 @@ export default class AvailableBaseLayers { private static implementation: AvailableBaseLayersObj static AvailableLayersAt(location: UIEventSource): UIEventSource { - return AvailableBaseLayers.implementation.AvailableLayersAt(location); + return AvailableBaseLayers.implementation?.AvailableLayersAt(location) ?? new UIEventSource([]); } static SelectBestLayerAccordingTo(location: UIEventSource, preferedCategory: UIEventSource): UIEventSource { - return AvailableBaseLayers.implementation.SelectBestLayerAccordingTo(location, preferedCategory); + return AvailableBaseLayers.implementation?.SelectBestLayerAccordingTo(location, preferedCategory) ?? new UIEventSource(undefined); } diff --git a/Logic/Actors/BackgroundLayerResetter.ts b/Logic/Actors/BackgroundLayerResetter.ts index d193d81329..60666c53d6 100644 --- a/Logic/Actors/BackgroundLayerResetter.ts +++ b/Logic/Actors/BackgroundLayerResetter.ts @@ -2,6 +2,7 @@ import {UIEventSource} from "../UIEventSource"; import BaseLayer from "../../Models/BaseLayer"; import AvailableBaseLayers from "./AvailableBaseLayers"; import Loc from "../../Models/Loc"; +import {Utils} from "../../Utils"; /** * Sets the current background layer to a layer that is actually available @@ -12,6 +13,11 @@ export default class BackgroundLayerResetter { location: UIEventSource, availableLayers: UIEventSource, defaultLayerId: string = undefined) { + + if(Utils.runningFromConsole){ + return + } + defaultLayerId = defaultLayerId ?? AvailableBaseLayers.osmCarto.id; // Change the baselayer back to OSM if we go out of the current range of the layer diff --git a/Logic/Actors/PendingChangesUploader.ts b/Logic/Actors/PendingChangesUploader.ts index bd1e93fd68..675491467f 100644 --- a/Logic/Actors/PendingChangesUploader.ts +++ b/Logic/Actors/PendingChangesUploader.ts @@ -1,6 +1,7 @@ import {Changes} from "../Osm/Changes"; import Constants from "../../Models/Constants"; import {UIEventSource} from "../UIEventSource"; +import {Utils} from "../../Utils"; export default class PendingChangesUploader { @@ -30,6 +31,10 @@ export default class PendingChangesUploader { } }); + if(Utils.runningFromConsole){ + return; + } + document.addEventListener('mouseout', e => { // @ts-ignore if (!e.toElement && !e.relatedTarget) { diff --git a/Logic/Actors/SelectedElementTagsUpdater.ts b/Logic/Actors/SelectedElementTagsUpdater.ts index 35d725c313..765c9ee19d 100644 --- a/Logic/Actors/SelectedElementTagsUpdater.ts +++ b/Logic/Actors/SelectedElementTagsUpdater.ts @@ -9,6 +9,13 @@ import {OsmConnection} from "../Osm/OsmConnection"; export default class SelectedElementTagsUpdater { + private static readonly metatags = new Set(["timestamp", + "version", + "changeset", + "user", + "uid", + "id"] ) + constructor(state: { selectedElement: UIEventSource, allElements: ElementStorage, @@ -18,15 +25,15 @@ export default class SelectedElementTagsUpdater { state.osmConnection.isLoggedIn.addCallbackAndRun(isLoggedIn => { - if(isLoggedIn){ + if (isLoggedIn) { SelectedElementTagsUpdater.installCallback(state) return true; } }) } - - private static installCallback(state: { + + public static installCallback(state: { selectedElement: UIEventSource, allElements: ElementStorage, changes: Changes, @@ -36,80 +43,99 @@ export default class SelectedElementTagsUpdater { state.selectedElement.addCallbackAndRunD(s => { let id = s.properties?.id - + const backendUrl = state.osmConnection._oauth_config.url - if(id.startsWith(backendUrl)){ + if (id.startsWith(backendUrl)) { id = id.substring(backendUrl.length) } - - if(!(id.startsWith("way") || id.startsWith("node") || id.startsWith("relation"))){ + + if (!(id.startsWith("way") || id.startsWith("node") || id.startsWith("relation"))) { // This object is _not_ from OSM, so we skip it! return; } - - if(id.indexOf("-") >= 0){ + + if (id.indexOf("-") >= 0) { // This is a new object return; } - - OsmObject.DownloadPropertiesOf(id).then(tags => { - SelectedElementTagsUpdater.applyUpdate(state, tags, id) - }).catch(e => { - console.error("Could not update tags of ", id, "due to", e) + OsmObject.DownloadPropertiesOf(id).then(latestTags => { + SelectedElementTagsUpdater.applyUpdate(state, latestTags, id) }) + }); } - private static applyUpdate(state: { - selectedElement: UIEventSource, - allElements: ElementStorage, - changes: Changes, - osmConnection: OsmConnection - }, latestTags: any, id: string + public static applyUpdate(state: { + selectedElement: UIEventSource, + allElements: ElementStorage, + changes: Changes, + osmConnection: OsmConnection + }, latestTags: any, id: string ) { - const pendingChanges = state.changes.pendingChanges.data - .filter(change => change.type +"/"+ change.id === id) - .filter(change => change.tags !== undefined); - - for (const pendingChange of pendingChanges) { - const tagChanges = pendingChange.tags; - for (const tagChange of tagChanges) { - const key = tagChange.k - const v = tagChange.v - if (v === undefined || v === "") { - delete latestTags[key] - } else { - latestTags[key] = v + try { + + const pendingChanges = state.changes.pendingChanges.data + .filter(change => change.type + "/" + change.id === id) + .filter(change => change.tags !== undefined); + + for (const pendingChange of pendingChanges) { + const tagChanges = pendingChange.tags; + for (const tagChange of tagChanges) { + const key = tagChange.k + const v = tagChange.v + if (v === undefined || v === "") { + delete latestTags[key] + } else { + latestTags[key] = v + } } } - } - // With the changes applied, we merge them onto the upstream object - let somethingChanged = false; - const currentTagsSource = state.allElements.getEventSourceById(id); - const currentTags = currentTagsSource.data - for (const key in latestTags) { - let osmValue = latestTags[key] - - if(typeof osmValue === "number"){ - osmValue = ""+osmValue - } - - const localValue = currentTags[key] - if (localValue !== osmValue) { - console.log("Local value for ", key ,":", localValue, "upstream", osmValue) - somethingChanged = true; - currentTags[key] = osmValue - } - } - if (somethingChanged) { - console.log("Detected upstream changes to the object when opening it, updating...") - currentTagsSource.ping() - }else{ - console.debug("Fetched latest tags for ", id, "but detected no changes") - } + // With the changes applied, we merge them onto the upstream object + let somethingChanged = false; + const currentTagsSource = state.allElements.getEventSourceById(id); + const currentTags = currentTagsSource.data + for (const key in latestTags) { + let osmValue = latestTags[key] + if (typeof osmValue === "number") { + osmValue = "" + osmValue + } + + const localValue = currentTags[key] + if (localValue !== osmValue) { + console.log("Local value for ", key, ":", localValue, "upstream", osmValue) + somethingChanged = true; + currentTags[key] = osmValue + } + } + + for (const currentKey in currentTags) { + if (currentKey.startsWith("_")) { + continue + } + if(this.metatags.has(currentKey)){ + continue + } + if (currentKey in latestTags) { + continue + } + console.log("Removing key as deleted upstream", currentKey) + delete currentTags[currentKey] + somethingChanged = true + } + + + if (somethingChanged) { + console.log("Detected upstream changes to the object when opening it, updating...") + currentTagsSource.ping() + } else { + console.debug("Fetched latest tags for ", id, "but detected no changes") + } + } catch (e) { + console.error("Updating the tags of selected element ", id, "failed due to", e) + } } diff --git a/Logic/Actors/TitleHandler.ts b/Logic/Actors/TitleHandler.ts index 91ec89b0c8..d3d2f78fb2 100644 --- a/Logic/Actors/TitleHandler.ts +++ b/Logic/Actors/TitleHandler.ts @@ -5,6 +5,7 @@ import TagRenderingAnswer from "../../UI/Popup/TagRenderingAnswer"; import Combine from "../../UI/Base/Combine"; import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig"; import {ElementStorage} from "../ElementStorage"; +import {Utils} from "../../Utils"; export default class TitleHandler { constructor(state : { @@ -38,6 +39,9 @@ export default class TitleHandler { currentTitle.addCallbackAndRunD(title => { + if(Utils.runningFromConsole){ + return + } document.title = title }) } diff --git a/Logic/ImageProviders/AllImageProviders.ts b/Logic/ImageProviders/AllImageProviders.ts index 745c367d45..5d428f2628 100644 --- a/Logic/ImageProviders/AllImageProviders.ts +++ b/Logic/ImageProviders/AllImageProviders.ts @@ -21,11 +21,13 @@ export default class AllImageProviders { ) ] + + public static defaultKeys = [].concat(AllImageProviders.ImageAttributionSource.map(provider => provider.defaultKeyPrefixes)) private static _cache: Map> = new Map>() - public static LoadImagesFor(tags: UIEventSource, tagKey?: string): UIEventSource { + public static LoadImagesFor(tags: UIEventSource, tagKey?: string[]): UIEventSource { if (tags.data.id === undefined) { return undefined; } @@ -44,7 +46,7 @@ export default class AllImageProviders { let prefixes = imageProvider.defaultKeyPrefixes if(tagKey !== undefined){ - prefixes = [...prefixes, tagKey] + prefixes = tagKey } const singleSource = imageProvider.GetRelevantUrls(tags, { diff --git a/Logic/ImageProviders/ImgurUploader.ts b/Logic/ImageProviders/ImgurUploader.ts index b8addab5a5..10bf436098 100644 --- a/Logic/ImageProviders/ImgurUploader.ts +++ b/Logic/ImageProviders/ImgurUploader.ts @@ -27,7 +27,8 @@ export default class ImgurUploader { files, function (url) { console.log("File saved at", url); - self.success.setData([...self.success.data, url]); + self.success.data.push(url) + self.success.ping(); self._handleSuccessUrl(url); }, function () { diff --git a/Logic/Osm/Changes.ts b/Logic/Osm/Changes.ts index 6c90cccbb3..7faa234947 100644 --- a/Logic/Osm/Changes.ts +++ b/Logic/Osm/Changes.ts @@ -97,6 +97,7 @@ export class Changes { console.log("Is already uploading... Abort") return; } + console.log("Uploading changes due to: ", flushreason) this.isUploading.setData(true) this.flushChangesAsync() @@ -287,7 +288,7 @@ export class Changes { v = undefined; } - const oldV = obj.type[k] + const oldV = obj.tags[k] if (oldV === v) { continue; } diff --git a/Logic/Osm/OsmObject.ts b/Logic/Osm/OsmObject.ts index 91b4b6e89e..5d21f7d147 100644 --- a/Logic/Osm/OsmObject.ts +++ b/Logic/Osm/OsmObject.ts @@ -66,7 +66,9 @@ export abstract class OsmObject { const url = `${OsmObject.backendURL}api/0.6/${id}`; const rawData = await Utils.downloadJsonCached(url, 1000) - return rawData.elements[0].tags + const tags = rawData.elements[0].tags + console.log("Tags are", tags) + return tags } static async DownloadObjectAsync(id: string): Promise { @@ -263,7 +265,7 @@ export abstract class OsmObject { continue; } const v = this.tags[key]; - if (v !== "") { + if (v !== "" && v !== undefined) { tags += ' \n' } } diff --git a/Logic/State/FeatureSwitchState.ts b/Logic/State/FeatureSwitchState.ts index 215c819f85..2315280ca5 100644 --- a/Logic/State/FeatureSwitchState.ts +++ b/Logic/State/FeatureSwitchState.ts @@ -5,6 +5,7 @@ import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig"; import {UIEventSource} from "../UIEventSource"; import {QueryParameters} from "../Web/QueryParameters"; import Constants from "../../Models/Constants"; +import {Utils} from "../../Utils"; export default class FeatureSwitchState { @@ -137,7 +138,7 @@ export default class FeatureSwitchState { let testingDefaultValue = false; - if (this.featureSwitchApiURL.data !== "osm-test" && + if (this.featureSwitchApiURL.data !== "osm-test" && !Utils.runningFromConsole && (location.hostname === "localhost" || location.hostname === "127.0.0.1")) { testingDefaultValue = true } diff --git a/Logic/UIEventSource.ts b/Logic/UIEventSource.ts index 77431441f9..0e802ad8cd 100644 --- a/Logic/UIEventSource.ts +++ b/Logic/UIEventSource.ts @@ -286,6 +286,9 @@ export class UIEventSource { } public stabilized(millisToStabilize): UIEventSource { + if(Utils.runningFromConsole){ + return this; + } const newSource = new UIEventSource(this.data);