diff --git a/Logic/Osm/Changes.ts b/Logic/Osm/Changes.ts index de7c5dc0e0..9da36b048a 100644 --- a/Logic/Osm/Changes.ts +++ b/Logic/Osm/Changes.ts @@ -7,6 +7,7 @@ import FeatureSource from "../FeatureSource/FeatureSource"; import {TagsFilter} from "../Tags/TagsFilter"; import {Tag} from "../Tags/Tag"; import {OsmConnection} from "./OsmConnection"; +import {LocalStorageSource} from "../Web/LocalStorageSource"; /** * Handles all changes made to OSM. @@ -24,8 +25,13 @@ export class Changes implements FeatureSource { /** * All the pending changes */ - public readonly pending: UIEventSource<{ elementId: string, key: string, value: string }[]> = - new UIEventSource<{ elementId: string; key: string; value: string }[]>([]); + public readonly pending: UIEventSource<{ elementId: string, key: string, value: string }[]> = LocalStorageSource.GetParsed("pending-changes", []) + + /** + * All the pending new objects to upload + * @private + */ + private readonly newObjects: UIEventSource<{ id: number, lat: number, lon: number }[]> = LocalStorageSource.GetParsed("newObjects", []) /** * Adds a change to the pending changes @@ -82,8 +88,7 @@ export class Changes implements FeatureSource { if (flushreason !== undefined) { console.log(flushreason) } - this.uploadAll([], this.pending.data); - this.pending.setData([]); + this.uploadAll(); } /** @@ -93,12 +98,12 @@ export class Changes implements FeatureSource { */ public createElement(basicTags: Tag[], lat: number, lon: number) { console.log("Creating a new element with ", basicTags) - const osmNode = new OsmNode(Changes._nextId); + const newId = Changes._nextId; Changes._nextId--; - const id = "node/" + osmNode.id; - osmNode.lat = lat; - osmNode.lon = lon; + const id = "node/" + newId; + + const properties = {id: id}; const geojson = { @@ -135,22 +140,32 @@ export class Changes implements FeatureSource { properties["_backend"] = State.state.osmConnection.userDetails.data.backend } - // this.uploadAll([osmNode], changes); + + this.newObjects.data.push({id: newId, lat: lat, lon: lon}) + this.pending.data.push(...changes) + this.pending.ping(); + this.newObjects.ping(); return geojson; } private uploadChangesWithLatestVersions( - knownElements: OsmObject[], newElements: OsmObject[], pending: { elementId: string; key: string; value: string }[]) { + knownElements: OsmObject[]) { const knownById = new Map(); - knownElements.forEach(knownElement => { knownById.set(knownElement.type + "/" + knownElement.id, knownElement) }) + const newElements: OsmNode [] = this.newObjects.data.map(spec => { + const newElement = new OsmNode(spec.id); + newElement.lat = spec.lat; + newElement.lon = spec.lon; + return newElement + }) + // Here, inside the continuation, we know that all 'neededIds' are loaded in 'knownElements', which maps the ids onto the elements // We apply the changes on them - for (const change of pending) { + for (const change of this.pending.data) { if (parseInt(change.elementId.split("/")[1]) < 0) { // This is a new element - we should apply this on one of the new elements for (const newElement of newElements) { @@ -217,17 +232,19 @@ export class Changes implements FeatureSource { changes += ""; return changes; + }, + () => { + console.log("Upload successfull!") + this.newObjects.setData([]) + this.pending.setData([]); }); }; - private uploadAll( - newElements: OsmObject[], - pending: { elementId: string; key: string; value: string }[] - ) { + private uploadAll() { const self = this; - + const pending = this.pending.data; let neededIds: string[] = []; for (const change of pending) { const id = change.elementId; @@ -240,8 +257,7 @@ export class Changes implements FeatureSource { neededIds = Utils.Dedup(neededIds); OsmObject.DownloadAll(neededIds).addCallbackAndRunD(knownElements => { - console.log("KnownElements:", knownElements) - self.uploadChangesWithLatestVersions(knownElements, newElements, pending) + self.uploadChangesWithLatestVersions(knownElements) }) } diff --git a/Logic/Osm/ChangesetHandler.ts b/Logic/Osm/ChangesetHandler.ts index ef9f5f717c..98d45a790c 100644 --- a/Logic/Osm/ChangesetHandler.ts +++ b/Logic/Osm/ChangesetHandler.ts @@ -27,7 +27,7 @@ export class ChangesetHandler { } } - private static parseUploadChangesetResponse(response: XMLDocument, allElements: ElementStorage) { + private static parseUploadChangesetResponse(response: XMLDocument, allElements: ElementStorage) : void{ const nodes = response.getElementsByTagName("node"); // @ts-ignore for (const node of nodes) { @@ -69,7 +69,8 @@ export class ChangesetHandler { public UploadChangeset( layout: LayoutConfig, allElements: ElementStorage, - generateChangeXML: (csid: string) => string) { + generateChangeXML: (csid: string) => string, + whenDone : (csId: string) => void) { if (this.userDetails.data.csCount == 0) { // The user became a contributor! @@ -80,6 +81,7 @@ export class ChangesetHandler { if (this._dryRun) { const changesetXML = generateChangeXML("123456"); console.log(changesetXML); + whenDone("123456") return; } @@ -93,8 +95,7 @@ export class ChangesetHandler { console.log(changeset); self.AddChange(csId, changeset, allElements, - () => { - }, + whenDone, (e) => { console.error("UPLOADING FAILED!", e) } @@ -107,14 +108,13 @@ export class ChangesetHandler { csId, generateChangeXML(csId), allElements, - () => { - }, + whenDone, (e) => { console.warn("Could not upload, changeset is probably closed: ", e); // Mark the CS as closed... this.currentChangeset.setData(""); // ... and try again. As the cs is closed, no recursive loop can exist - self.UploadChangeset(layout, allElements, generateChangeXML); + self.UploadChangeset(layout, allElements, generateChangeXML, whenDone); } ) @@ -244,7 +244,6 @@ export class ChangesetHandler { }, function (err, response) { if (response === undefined) { console.log("err", err); - alert("Could not upload change (opening failed). Please file a bug report") return; } else { continuation(response); @@ -265,7 +264,7 @@ export class ChangesetHandler { private AddChange(changesetId: string, changesetXML: string, allElements: ElementStorage, - continuation: ((changesetId: string, idMapping: any) => void), + continuation: ((changesetId: string) => void), onFail: ((changesetId: string, reason: string) => void) = undefined) { this.auth.xhr({ method: 'POST', @@ -280,9 +279,9 @@ export class ChangesetHandler { } return; } - const mapping = ChangesetHandler.parseUploadChangesetResponse(response, allElements); + ChangesetHandler.parseUploadChangesetResponse(response, allElements); console.log("Uploaded changeset ", changesetId); - continuation(changesetId, mapping); + continuation(changesetId); }); } diff --git a/Logic/Osm/OsmConnection.ts b/Logic/Osm/OsmConnection.ts index decc8a09cb..cba332447f 100644 --- a/Logic/Osm/OsmConnection.ts +++ b/Logic/Osm/OsmConnection.ts @@ -110,8 +110,9 @@ export class OsmConnection { public UploadChangeset( layout: LayoutConfig, allElements: ElementStorage, - generateChangeXML: (csid: string) => string) { - this.changesetHandler.UploadChangeset(layout, allElements, generateChangeXML); + generateChangeXML: (csid: string) => string, + whenDone: (csId: string) => void) { + this.changesetHandler.UploadChangeset(layout, allElements, generateChangeXML, whenDone); } public GetPreference(key: string, prefix: string = "mapcomplete-"): UIEventSource { diff --git a/Logic/Osm/OsmObject.ts b/Logic/Osm/OsmObject.ts index e8f2047591..09ee7137c7 100644 --- a/Logic/Osm/OsmObject.ts +++ b/Logic/Osm/OsmObject.ts @@ -5,7 +5,8 @@ import {UIEventSource} from "../UIEventSource"; export abstract class OsmObject { - protected static backendURL = "https://www.openstreetmap.org/" + private static defaultBackend = "https://www.openstreetmap.org/" + protected static backendURL = OsmObject.defaultBackend; private static polygonFeatures = OsmObject.constructPolygonFeatures() private static objectCache = new Map>(); private static referencingWaysCache = new Map>(); @@ -37,15 +38,15 @@ export abstract class OsmObject { } static DownloadObject(id: string, forceRefresh: boolean = false): UIEventSource { - let src : UIEventSource; + let src: UIEventSource; if (OsmObject.objectCache.has(id)) { src = OsmObject.objectCache.get(id) - if(forceRefresh){ + if (forceRefresh) { src.setData(undefined) - }else{ + } else { return src; } - }else{ + } else { src = new UIEventSource(undefined) } const splitted = id.split("/"); @@ -157,7 +158,7 @@ export abstract class OsmObject { const minlat = bounds[1][0] const maxlat = bounds[0][0]; const url = `${OsmObject.backendURL}api/0.6/map.json?bbox=${minlon},${minlat},${maxlon},${maxlat}` - Utils.downloadJson(url).then( data => { + Utils.downloadJson(url).then(data => { const elements: any[] = data.elements; const objects = OsmObject.ParseObjects(elements) callback(objects); @@ -291,6 +292,7 @@ export abstract class OsmObject { self.LoadData(element) self.SaveExtraData(element, nodes); + const meta = { "_last_edit:contributor": element.user, "_last_edit:contributor:uid": element.uid, @@ -299,6 +301,11 @@ export abstract class OsmObject { "_version_number": element.version } + if (OsmObject.backendURL !== OsmObject.defaultBackend) { + self.tags["_backend"] = OsmObject.backendURL + meta["_backend"] = OsmObject.backendURL; + } + continuation(self, meta); } ); diff --git a/Logic/Web/LocalStorageSource.ts b/Logic/Web/LocalStorageSource.ts index 050b124591..a89d2a5569 100644 --- a/Logic/Web/LocalStorageSource.ts +++ b/Logic/Web/LocalStorageSource.ts @@ -4,6 +4,22 @@ import {UIEventSource} from "../UIEventSource"; * UIEventsource-wrapper around localStorage */ export class LocalStorageSource { + + static GetParsed(key: string, defaultValue : any){ + return LocalStorageSource.Get(key).map( + str => { + if(str === undefined){ + return defaultValue + } + try{ + return JSON.parse(str) + }catch{ + return defaultValue + } + }, [], + value => JSON.stringify(value) + ) + } static Get(key: string, defaultValue: string = undefined): UIEventSource { try { diff --git a/Models/Constants.ts b/Models/Constants.ts index 79bcb5ca0a..33a52c40f6 100644 --- a/Models/Constants.ts +++ b/Models/Constants.ts @@ -2,7 +2,7 @@ import { Utils } from "../Utils"; export default class Constants { - public static vNumber = "0.8.3d"; + public static vNumber = "0.8.4"; // The user journey states thresholds when a new feature gets unlocked public static userJourney = { diff --git a/assets/tagRenderings/icons.json b/assets/tagRenderings/icons.json index e0bde24dad..5dbe8856a3 100644 --- a/assets/tagRenderings/icons.json +++ b/assets/tagRenderings/icons.json @@ -59,8 +59,12 @@ "render": "", "mappings": [ { - "if": "id~=-", - "then": "Uploading..." + "if": "id~.*/-.*", + "then": "" + }, + { + "if": "_backend~*", + "then": "" } ], "condition": "id~(node|way|relation)/[0-9]*"