forked from MapComplete/MapComplete
		
	Changesets are now kept open and reused to avoid tons of changesets to be created
This commit is contained in:
		
							parent
							
								
									0051c37494
								
							
						
					
					
						commit
						82f3525907
					
				
					 16 changed files with 162 additions and 270 deletions
				
			
		|  | @ -117,7 +117,7 @@ export class TagRendering extends UIElement implements TagDependantUIElement { | |||
| 
 | ||||
| 
 | ||||
|             let choiceSubbed = { | ||||
|                 k: choice.k.substituteValues(this.currentTags.data), | ||||
|                 k: choice.k?.substituteValues(this.currentTags.data), | ||||
|                 txt: choice.txt, | ||||
|                 priority: choice.priority | ||||
|             } | ||||
|  | @ -314,7 +314,7 @@ export class TagRendering extends UIElement implements TagDependantUIElement { | |||
|         const tags = TagUtils.proprtiesToKV(this._source.data); | ||||
| 
 | ||||
|         for (const oneOnOneElement of this._mapping) { | ||||
|             if (oneOnOneElement.k === null || oneOnOneElement.k.matches(tags)) { | ||||
|             if (oneOnOneElement.k === null || oneOnOneElement.k === undefined || oneOnOneElement.k.matches(tags)) { | ||||
|                 return true; | ||||
|             } | ||||
|         } | ||||
|  |  | |||
|  | @ -14,19 +14,6 @@ export class Changes { | |||
| 
 | ||||
|     private static _nextId = -1; // New assined ID's are negative
 | ||||
| 
 | ||||
|     private _pendingChanges: { elementId: string, key: string, value: string }[] = []; // Gets reset on uploadAll
 | ||||
|     private newElements: OsmObject[] = []; // Gets reset on uploadAll
 | ||||
| 
 | ||||
|     public readonly pendingChangesES = new UIEventSource<number>(this._pendingChanges.length); | ||||
|     public readonly isSaving = new UIEventSource(false); | ||||
| 
 | ||||
|     constructor( | ||||
|         state: State) { | ||||
| 
 | ||||
|         this.SetupAutoSave(state); | ||||
|         this.LastEffortSave(); | ||||
|     } | ||||
| 
 | ||||
|     addTag(elementId: string, tagsFilter : TagsFilter){ | ||||
|         if(tagsFilter instanceof  Tag){ | ||||
|             const tag = tagsFilter as Tag; | ||||
|  | @ -72,13 +59,10 @@ export class Changes { | |||
|         value = value.trim(); | ||||
| 
 | ||||
|         const eventSource = State.state.allElements.getElement(elementId); | ||||
| 
 | ||||
|         eventSource.data[key] = value; | ||||
|         | ||||
|         eventSource.ping(); | ||||
|         // We get the id from the event source, as that ID might be rewritten
 | ||||
|         this._pendingChanges.push({elementId: eventSource.data.id, key: key, value: value}); | ||||
|         this.pendingChangesES.setData(this._pendingChanges.length); | ||||
| 
 | ||||
|         this.uploadAll([], [{elementId: eventSource.data.id, key: key, value: value}]); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|  | @ -90,7 +74,6 @@ export class Changes { | |||
|     createElement(basicTags:Tag[], lat: number, lon: number) { | ||||
|         console.log("Creating a new element with ", basicTags) | ||||
|         const osmNode = new OsmNode(Changes._nextId); | ||||
|         this.newElements.push(osmNode); | ||||
|         Changes._nextId--; | ||||
| 
 | ||||
|         const id = "node/" + osmNode.id; | ||||
|  | @ -113,39 +96,25 @@ export class Changes { | |||
| 
 | ||||
|         // The basictags are COPIED, the id is included in the properties
 | ||||
|         // The tags are not yet written into the OsmObject, but this is applied onto a 
 | ||||
|         const changes = []; | ||||
|         for (const kv of basicTags) { | ||||
|             properties[kv.key] = kv.value; | ||||
|             if(typeof kv.value !== "string"){ | ||||
|                 throw "Invalid value" | ||||
|             if (typeof kv.value !== "string") { | ||||
|                 throw "Invalid value: don't use a regex in a preset" | ||||
|             } | ||||
|             this._pendingChanges.push({elementId: id, key: kv.key, value: kv.value}); | ||||
|             changes.push({elementId: id, key: kv.key, value: kv.value}) | ||||
|         } | ||||
|         this.pendingChangesES.setData(this._pendingChanges.length); | ||||
|         State.state.allElements.addOrGetElement(geojson).ping(); | ||||
| 
 | ||||
|         this.uploadAll([osmNode], changes); | ||||
|         return geojson; | ||||
|     } | ||||
| 
 | ||||
|     public uploadAll(optionalContinuation: (() => void) = undefined) { | ||||
|     private uploadAll( | ||||
|         newElements: OsmObject[], | ||||
|         pending: { elementId: string; key: string; value: string }[] | ||||
|     ) { | ||||
|         const self = this; | ||||
| 
 | ||||
|         this.isSaving.setData(true); | ||||
|         const optionalContinuationWrapped = function () { | ||||
|             self.isSaving.setData(false); | ||||
|             if (optionalContinuation) { | ||||
|                 optionalContinuation(); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         const pending: { elementId: string; key: string; value: string }[] = this._pendingChanges; | ||||
|         this._pendingChanges = []; | ||||
|         this.pendingChangesES.setData(this._pendingChanges.length); | ||||
| 
 | ||||
|         const newElements = this.newElements; | ||||
|         this.newElements = []; | ||||
| 
 | ||||
| 
 | ||||
|         const knownElements = {}; // maps string --> OsmObject
 | ||||
|         function DownloadAndContinue(neededIds, continuation: (() => void)) { | ||||
|             // local function which downloads all the objects one by one
 | ||||
|  | @ -174,7 +143,7 @@ export class Changes { | |||
|         for (const change of pending) { | ||||
|             const id = change.elementId; | ||||
|             if (parseFloat(id.split("/")[1]) < 0) { | ||||
|                 console.log("Detected a new element! Exciting!") | ||||
|                 // New element - we don't have to download this
 | ||||
|             } else { | ||||
|                 neededIds.push(id); | ||||
|             } | ||||
|  | @ -194,9 +163,7 @@ export class Changes { | |||
|                     } | ||||
| 
 | ||||
|                 } else { | ||||
|                     console.log(knownElements, change.elementId); | ||||
|                     knownElements[change.elementId].addTag(change.key, change.value); | ||||
|                     // note: addTag will flag changes with 'element.changed' internally
 | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|  | @ -213,18 +180,6 @@ export class Changes { | |||
|                 return; | ||||
|             } | ||||
| 
 | ||||
| 
 | ||||
|             const handleMapping = function (idMapping) { | ||||
|                 for (const oldId in idMapping) { | ||||
|                     const newId = idMapping[oldId]; | ||||
| 
 | ||||
|                     const element = State.state.allElements.getElement(oldId); | ||||
|                     element.data.id = newId; | ||||
|                     State.state.allElements.addElementById(newId, element); | ||||
|                     element.ping(); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             console.log("Beginning upload..."); | ||||
|             // At last, we build the changeset and upload
 | ||||
|             State.state.osmConnection.UploadChangeset( | ||||
|  | @ -266,89 +221,9 @@ export class Changes { | |||
| 
 | ||||
|                     return changes; | ||||
|                 }, | ||||
|                 handleMapping, | ||||
|                 optionalContinuationWrapped); | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     /* | ||||
|         * Registers an action that: | ||||
|         * -> Upload everything to OSM | ||||
|         * -> Asks the user not to close. The 'not to close' dialog should profide enough time to upload | ||||
|         * -> WHen uploading is done, the window is closed anyway | ||||
|          */ | ||||
|     private LastEffortSave() { | ||||
|         const self = this; | ||||
|         window.addEventListener("beforeunload", function (e) { | ||||
|             // Quickly save everyting!
 | ||||
|             if (self.pendingChangesES.data == 0) { | ||||
|                 return ""; | ||||
|             } | ||||
| 
 | ||||
|             self.uploadAll(function () { | ||||
|                 console.log("Uploaded changes during a last-effort save") | ||||
|                 window.close() | ||||
|             }); | ||||
|             var confirmationMessage = "Nog even geduld - je laatset wijzigingen worden opgeslaan!"; | ||||
| 
 | ||||
|             (e || window.event).returnValue = confirmationMessage; //Gecko + IE
 | ||||
|             return confirmationMessage;                            //Webkit, Safari, Chrome
 | ||||
|         }); | ||||
| 
 | ||||
| 
 | ||||
|         document.addEventListener('visibilitychange', () => { | ||||
|             if (document.visibilityState === "visible") { | ||||
|                 return; | ||||
|             } | ||||
|             if (this.pendingChangesES.data == 0) { | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             console.log("Uploading: loss of focus") | ||||
|             this.uploadAll(function () { | ||||
|                 console.log("Uploaded changes during a last-effort save (loss of focus)") | ||||
|                 window.close() | ||||
|             }); | ||||
|         }) | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     private SetupAutoSave(state: State) { | ||||
| 
 | ||||
|         const millisTillChangesAreSaved = state.secondsTillChangesAreSaved; | ||||
|         const saveAfterXMillis = state.saveTimeout.data; | ||||
|         const self = this; | ||||
|         this.pendingChangesES.addCallback(function () { | ||||
| 
 | ||||
|             var c = self.pendingChangesES.data; | ||||
|             if (c > 10) { | ||||
|                 millisTillChangesAreSaved.setData(0); | ||||
|                 self.uploadAll(() => { | ||||
|                     console.log("Uploaded changes: more then 10 pending changes") | ||||
|                 () => { | ||||
|                 }); | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             if (c > 0) { | ||||
|                 millisTillChangesAreSaved.setData(saveAfterXMillis); | ||||
|             } | ||||
| 
 | ||||
|         }); | ||||
| 
 | ||||
|         millisTillChangesAreSaved.addCallback((time) => { | ||||
|                 if (time <= 0 && self.pendingChangesES.data > 0) { | ||||
|                     self.uploadAll(() => { | ||||
|                         console.log("Saving changes: timer elapsed") | ||||
|                     }); | ||||
|                 } | ||||
|             } | ||||
|         ) | ||||
| 
 | ||||
|         Utils.DoEvery( | ||||
|             1000, | ||||
|             () => { | ||||
|                 millisTillChangesAreSaved | ||||
|                     .setData(millisTillChangesAreSaved.data - 1000) | ||||
|             }); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -1,5 +1,5 @@ | |||
| import {State} from "../../State"; | ||||
| import {UserDetails} from "./OsmConnection"; | ||||
| import {OsmConnection, UserDetails} from "./OsmConnection"; | ||||
| import {UIEventSource} from "../UIEventSource"; | ||||
| 
 | ||||
| export class ChangesetHandler { | ||||
|  | @ -8,10 +8,13 @@ export class ChangesetHandler { | |||
|     private userDetails: UIEventSource<UserDetails>; | ||||
|     private auth: any; | ||||
| 
 | ||||
|     constructor(dryRun: boolean, userDetails: UIEventSource<UserDetails>, auth) { | ||||
|     public currentChangeset: UIEventSource<string>; | ||||
| 
 | ||||
|     constructor(dryRun: boolean, osmConnection: OsmConnection, auth) { | ||||
|         this._dryRun = dryRun; | ||||
|         this.userDetails = userDetails; | ||||
|         this.userDetails = osmConnection.userDetails; | ||||
|         this.auth = auth; | ||||
|         this.currentChangeset = osmConnection.GetPreference("current-open-changeset"); | ||||
| 
 | ||||
|         if (dryRun) { | ||||
|             console.log("DRYRUN ENABLED"); | ||||
|  | @ -20,7 +23,6 @@ export class ChangesetHandler { | |||
| 
 | ||||
| 
 | ||||
|     public UploadChangeset(generateChangeXML: (csid: string) => string, | ||||
|                            handleMapping: (idMapping: any) => void, | ||||
|                            continuation: () => void) { | ||||
| 
 | ||||
|         if (this._dryRun) { | ||||
|  | @ -32,18 +34,53 @@ export class ChangesetHandler { | |||
|         } | ||||
| 
 | ||||
|         const self = this; | ||||
|         this.OpenChangeset( | ||||
|             function (csId) { | ||||
|                 var changesetXML = generateChangeXML(csId); | ||||
|                 self.AddChange(csId, changesetXML, | ||||
|                     function (csId, mapping) { | ||||
|                         self.CloseChangeset(csId, continuation); | ||||
|                         handleMapping(mapping); | ||||
|                     } | ||||
|                 ); | ||||
| 
 | ||||
|             } | ||||
|         ); | ||||
| 
 | ||||
|         if (this.currentChangeset.data === undefined || this.currentChangeset.data === "") { | ||||
|             // We have to open a new changeset
 | ||||
|             this.OpenChangeset((csId) => { | ||||
|                 this.currentChangeset.setData(csId); | ||||
|                 self.AddChange(csId, generateChangeXML(csId), | ||||
|                     () => { | ||||
|                     }, | ||||
|                     (e) => { | ||||
|                         console.error("UPLOADING FAILED!", e) | ||||
|                     } | ||||
|                 ) | ||||
|             }) | ||||
|         } else { | ||||
|             // There still exists an open changeset (or at least we hope so)
 | ||||
|             const csId = this.currentChangeset.data; | ||||
|             self.AddChange( | ||||
|                 csId, | ||||
|                 generateChangeXML(csId), | ||||
|                 () => { | ||||
|                 }, | ||||
|                 (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(generateChangeXML, continuation); | ||||
| 
 | ||||
|                 } | ||||
|             ) | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|         /* | ||||
|                 this.OpenChangeset( | ||||
|                     function (csId) { | ||||
|                         var changesetXML = generateChangeXML(csId); | ||||
|                         self.AddChange(csId, changesetXML, | ||||
|                             function (csId, mapping) { | ||||
|                                 self.CloseChangeset(csId, continuation); | ||||
|                                 handleMapping(mapping); | ||||
|                             } | ||||
|                         ); | ||||
|          | ||||
|                     } | ||||
|                 );*/ | ||||
| 
 | ||||
|         this.userDetails.data.csCount++; | ||||
|         this.userDetails.ping(); | ||||
|  | @ -77,7 +114,8 @@ export class ChangesetHandler { | |||
| 
 | ||||
|     private AddChange(changesetId: string, | ||||
|                       changesetXML: string, | ||||
|                       continuation: ((changesetId: string, idMapping: any) => void)) { | ||||
|                       continuation: ((changesetId: string, idMapping: any) => void), | ||||
|                       onFail: ((changesetId: string) => void) = undefined) { | ||||
|         this.auth.xhr({ | ||||
|             method: 'POST', | ||||
|             options: {header: {'Content-Type': 'text/xml'}}, | ||||
|  | @ -86,6 +124,9 @@ export class ChangesetHandler { | |||
|         }, function (err, response) { | ||||
|             if (response == null) { | ||||
|                 console.log("err", err); | ||||
|                 if (onFail) { | ||||
|                     onFail(changesetId); | ||||
|                 } | ||||
|                 return; | ||||
|             } | ||||
|             const mapping = ChangesetHandler.parseUploadChangesetResponse(response); | ||||
|  | @ -94,8 +135,16 @@ export class ChangesetHandler { | |||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     public CloseChangeset(changesetId: string, continuation: (() => void)) { | ||||
|         console.log("closing"); | ||||
|     public CloseChangeset(changesetId: string = undefined, continuation: (() => void) = () => { | ||||
|     }) { | ||||
|         if (changesetId === undefined) { | ||||
|             changesetId = this.currentChangeset.data; | ||||
|         } | ||||
|         if (changesetId === undefined) { | ||||
|             return; | ||||
|         } | ||||
|         console.log("closing changeset", changesetId); | ||||
|         this.currentChangeset.setData(""); | ||||
|         this.auth.xhr({ | ||||
|             method: 'PUT', | ||||
|             path: '/api/0.6/changeset/' + changesetId + '/close', | ||||
|  | @ -104,7 +153,7 @@ export class ChangesetHandler { | |||
| 
 | ||||
|                 console.log("err", err); | ||||
|             } | ||||
|             console.log("Closed changeset ", changesetId); | ||||
|             console.log("Closed changeset ", changesetId) | ||||
| 
 | ||||
|             if (continuation !== undefined) { | ||||
|                 continuation(); | ||||
|  | @ -114,17 +163,23 @@ export class ChangesetHandler { | |||
| 
 | ||||
|     public static parseUploadChangesetResponse(response: XMLDocument) { | ||||
|         const nodes = response.getElementsByTagName("node"); | ||||
|         const mapping = {}; | ||||
|         // @ts-ignore
 | ||||
|         for (const node of nodes) { | ||||
|             const oldId = parseInt(node.attributes.old_id.value); | ||||
|             const newId = parseInt(node.attributes.new_id.value); | ||||
|             if (oldId !== undefined && newId !== undefined && | ||||
|                 !isNaN(oldId) && !isNaN(newId)) { | ||||
|                 mapping["node/" + oldId] = "node/" + newId; | ||||
|                 if(oldId == newId){ | ||||
|                     continue; | ||||
|                 } | ||||
|                 console.log("Rewriting id: ", oldId, "-->", newId); | ||||
|                 const element = State.state.allElements.getElement("node/" + oldId); | ||||
|                 element.data.id = "node/" + newId; | ||||
|                 State.state.allElements.addElementById("node/" + newId, element); | ||||
|                 element.ping(); | ||||
| 
 | ||||
|             } | ||||
|         } | ||||
|         return mapping; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -29,7 +29,7 @@ export class OsmConnection { | |||
|      | ||||
|     private _onLoggedIn : ((userDetails: UserDetails) => void)[] = []; | ||||
| 
 | ||||
|     constructor(dryRun: boolean, oauth_token: UIEventSource<string>, singlePage: boolean = true) { | ||||
|     constructor(dryRun: boolean, oauth_token: UIEventSource<string>, singlePage: boolean = true, useDevServer:boolean = false) { | ||||
| 
 | ||||
|         let pwaStandAloneMode = false; | ||||
|         try { | ||||
|  | @ -50,7 +50,8 @@ export class OsmConnection { | |||
|                 oauth_consumer_key: 'hivV7ec2o49Two8g9h8Is1VIiVOgxQ1iYexCbvem', | ||||
|                 oauth_secret: 'wDBRTCem0vxD7txrg1y6p5r8nvmz8tAhET7zDASI', | ||||
|                 singlepage: false, | ||||
|                 auto: true | ||||
|                 auto: true, | ||||
|                 url: useDevServer ? "https://master.apis.dev.openstreetmap.org" : undefined | ||||
|             }); | ||||
|         } else { | ||||
| 
 | ||||
|  | @ -59,7 +60,8 @@ export class OsmConnection { | |||
|                 oauth_secret: 'wDBRTCem0vxD7txrg1y6p5r8nvmz8tAhET7zDASI', | ||||
|                 singlepage: true, | ||||
|                 landing: window.location.href, | ||||
|                 auto: true | ||||
|                 auto: true, | ||||
|                 url: useDevServer ? "https://master.apis.dev.openstreetmap.org" : undefined | ||||
|             }); | ||||
|         } | ||||
| 
 | ||||
|  | @ -70,7 +72,7 @@ export class OsmConnection { | |||
| 
 | ||||
|         this.preferencesHandler = new OsmPreferences(this.auth, this); | ||||
|          | ||||
|         this.changesetHandler = new ChangesetHandler(dryRun, this.userDetails, this.auth); | ||||
|         this.changesetHandler = new ChangesetHandler(dryRun, this, this.auth); | ||||
|         if (oauth_token.data !== undefined) { | ||||
|             console.log(oauth_token.data) | ||||
|             const self = this; | ||||
|  | @ -92,9 +94,8 @@ export class OsmConnection { | |||
| 
 | ||||
| 
 | ||||
|     public UploadChangeset(generateChangeXML: (csid: string) => string, | ||||
|                            handleMapping: (idMapping: any) => void, | ||||
|                            continuation: () => void) { | ||||
|         this.changesetHandler.UploadChangeset(generateChangeXML, handleMapping, continuation); | ||||
|         this.changesetHandler.UploadChangeset(generateChangeXML, continuation); | ||||
|     } | ||||
| 
 | ||||
|     public GetPreference(key: string, prefix: string = "mapcomplete-"): UIEventSource<string> { | ||||
|  |  | |||
|  | @ -39,7 +39,7 @@ export class OsmImageUploadHandler { | |||
|         return { | ||||
|             title: title, | ||||
|             description: description, | ||||
|             handleURL: function (url) { | ||||
|             handleURL: (url) => { | ||||
| 
 | ||||
|                 let key = "image"; | ||||
|                 if (tags["image"] !== undefined) { | ||||
|  | @ -54,10 +54,7 @@ export class OsmImageUploadHandler { | |||
|                 changes.addChange(tags.id, key, url); | ||||
|                 self._slideShow.MoveTo(-1); // set the last (thus newly added) image) to view
 | ||||
|             }, | ||||
|             allDone: function () { | ||||
|                 changes.uploadAll(function () { | ||||
|                     console.log("Writing changes...") | ||||
|                 }); | ||||
|             allDone: () => { | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  |  | |||
|  | @ -35,13 +35,10 @@ export class OsmPreferences { | |||
|         const source = new UIEventSource<string>(undefined); | ||||
|         this.longPreferences[prefix + key] = source; | ||||
| 
 | ||||
|         console.log("Loading long pref", prefix + key); | ||||
| 
 | ||||
|         const allStartWith = prefix + key + "-combined"; | ||||
|         // Gives the number of combined preferences
 | ||||
|         const length = this.GetPreference(allStartWith + "-length", ""); | ||||
| 
 | ||||
|         console.log("Getting long pref " + prefix + key); | ||||
|         const self = this; | ||||
|         source.addCallback(str => { | ||||
|             if (str === undefined || str === "") { | ||||
|  | @ -82,7 +79,7 @@ export class OsmPreferences { | |||
| 
 | ||||
|             source.setData(str); | ||||
|             source.ping(); | ||||
|             console.log("Long preference ", key, " has ", str.length, " chars"); | ||||
|             console.log("Long preference", key, "has", str.length, "chars"); | ||||
|         } | ||||
| 
 | ||||
|         length.addCallback(l => { | ||||
|  | @ -142,7 +139,7 @@ export class OsmPreferences { | |||
| 
 | ||||
|     private SetPreference(k: string, v: string) { | ||||
|         if (!this.userDetails.data.loggedIn) { | ||||
|             console.log("Not saving preference: user not logged in"); | ||||
|             console.log(`Not saving preference ${k}: user not logged in`); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|  | @ -163,7 +160,7 @@ export class OsmPreferences { | |||
|                     return; | ||||
|                 } | ||||
| 
 | ||||
|                 console.log("Preference removed!", result == "" ? "OK" : result); | ||||
|                 console.log("Preference ",k,"removed!"); | ||||
| 
 | ||||
|             }); | ||||
|             return; | ||||
|  | @ -177,12 +174,10 @@ export class OsmPreferences { | |||
|             content: v | ||||
|         }, function (error, result) { | ||||
|             if (error) { | ||||
|                 console.log("Could not set preference", error); | ||||
|                 console.log(`Could not set preference "${k}"'`, error); | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             console.log("Preference written!", result == "" ? "OK" : result); | ||||
| 
 | ||||
|             console.log(`Preference ${k} written!`); | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										13
									
								
								State.ts
									
										
									
									
									
								
							
							
						
						
									
										13
									
								
								State.ts
									
										
									
									
									
								
							|  | @ -24,7 +24,7 @@ export class State { | |||
|     // The singleton of the global state
 | ||||
|     public static state: State; | ||||
|      | ||||
|     public static vNumber = "0.0.7a ¿hablas español?"; | ||||
|     public static vNumber = "0.0.7b Less changesets"; | ||||
|      | ||||
|     // The user journey states thresholds when a new feature gets unlocked
 | ||||
|     public static userJourney = { | ||||
|  | @ -125,7 +125,7 @@ export class State { | |||
|     public installedThemes: UIEventSource<{ layout: Layout; definition: string }[]>; | ||||
| 
 | ||||
| 
 | ||||
|     constructor(layoutToUse: Layout) { | ||||
|     constructor(layoutToUse: Layout, useDevServer = false) { | ||||
|         const self = this; | ||||
|         this.layoutToUse.setData(layoutToUse) | ||||
|         this.locationControl = new UIEventSource<{ lat: number, lon: number, zoom: number }>({ | ||||
|  | @ -171,9 +171,12 @@ export class State { | |||
|         this.featureSwitchShareScreen = featSw("fs-share-screen", (layoutToUse) => layoutToUse?.enableShareScreen ?? true); | ||||
|         this.featureSwitchGeolocation = featSw("fs-geolocation", (layoutToUse) => layoutToUse?.enableGeolocation ?? true); | ||||
| 
 | ||||
|         const testParam = QueryParameters.GetQueryParameter("test", "false").data; | ||||
|         this.osmConnection = new OsmConnection( | ||||
|             QueryParameters.GetQueryParameter("test", "false").data === "true", | ||||
|             QueryParameters.GetQueryParameter("oauth_token", undefined) | ||||
|             testParam === "true", | ||||
|             QueryParameters.GetQueryParameter("oauth_token", undefined), | ||||
|             true, | ||||
|             testParam === "dev" | ||||
|         ); | ||||
| 
 | ||||
| 
 | ||||
|  | @ -237,7 +240,7 @@ export class State { | |||
| 
 | ||||
| 
 | ||||
|         this.allElements = new ElementStorage(); | ||||
|         this.changes = new Changes(this); | ||||
|         this.changes = new Changes(); | ||||
| 
 | ||||
|         if (State.runningFromConsole) { | ||||
|             console.warn("running from console - not initializing map. Assuming test.html"); | ||||
|  |  | |||
|  | @ -1,38 +0,0 @@ | |||
| import {UIElement} from "./UIElement"; | ||||
| import {State} from "../State"; | ||||
| import {UIEventSource} from "../Logic/UIEventSource"; | ||||
| 
 | ||||
| export class PendingChanges extends UIElement { | ||||
|     private _pendingChangesCount: UIEventSource<number>; | ||||
|     private _isSaving: UIEventSource<boolean>; | ||||
| 
 | ||||
|     constructor() { | ||||
|         super(State.state.changes.pendingChangesES); | ||||
|         this.ListenTo(State.state.changes.isSaving); | ||||
|         this.ListenTo(State.state.secondsTillChangesAreSaved); | ||||
|         this._pendingChangesCount = State.state.changes.pendingChangesES; | ||||
|         this._isSaving = State.state.changes.isSaving; | ||||
| 
 | ||||
|         this.onClick(() => { | ||||
|             State.state.changes.uploadAll(); | ||||
|         }) | ||||
|     } | ||||
| 
 | ||||
|     InnerRender(): string { | ||||
|         if (this._isSaving.data) { | ||||
|             return "<span class='alert'>Saving</span>"; | ||||
|         } | ||||
|         if (this._pendingChangesCount.data == 0) { | ||||
|             return ""; | ||||
|         } | ||||
| 
 | ||||
|         var restingSeconds =State.state.secondsTillChangesAreSaved.data / 1000; | ||||
|         var dots = ""; | ||||
|         while (restingSeconds > 0) { | ||||
|             dots += "."; | ||||
|             restingSeconds = restingSeconds - 1; | ||||
|         } | ||||
|         return "Saving "+this._pendingChangesCount.data; | ||||
|     }   | ||||
|      | ||||
| } | ||||
|  | @ -55,8 +55,8 @@ export class SimpleAddUI extends UIElement { | |||
|                 if (preset.icon !== undefined) { | ||||
| 
 | ||||
|                     if (typeof (preset.icon) !== "string") { | ||||
|                         icon = preset.icon.GetContent(Utils.MergeTags(preset.tags, {id:"node/-1"})); | ||||
|                         console.log("Preset icon is:", preset.icon, "--> ",icon); | ||||
|                         const tags = Utils.MergeTags(TagUtils.KVtoProperties(preset.tags), {id:"node/-1"}); | ||||
|                         icon = preset.icon.GetContent(tags); | ||||
|                     } else { | ||||
|                         icon = preset.icon; | ||||
|                     } | ||||
|  |  | |||
|  | @ -1,14 +1,11 @@ | |||
| import {UIElement} from "./UIElement"; | ||||
| import {UIEventSource} from "./UIEventSource"; | ||||
| import L from "leaflet"; | ||||
| import {FixedUiElement} from "./Base/FixedUiElement"; | ||||
| import {VariableUiElement} from "./Base/VariableUIElement"; | ||||
| import Translations from "./i18n/Translations"; | ||||
| import {UserDetails} from "../Logic/Osm/OsmConnection"; | ||||
| import {State} from "../State"; | ||||
| import {PendingChanges} from "./PendingChanges"; | ||||
| import {Utils} from "../Utils"; | ||||
| // @ts-ignore
 | ||||
| import {UIEventSource} from "../Logic/UIEventSource"; | ||||
| 
 | ||||
| /** | ||||
|  | @ -16,7 +13,6 @@ import {UIEventSource} from "../Logic/UIEventSource"; | |||
|  */ | ||||
| export class UserBadge extends UIElement { | ||||
|     private _userDetails: UIEventSource<UserDetails>; | ||||
|     private _pendingChanges: UIElement; | ||||
|     private _logout: UIElement; | ||||
|     private _homeButton: UIElement; | ||||
|     private _languagePicker: UIElement; | ||||
|  | @ -26,7 +22,6 @@ export class UserBadge extends UIElement { | |||
|     constructor() { | ||||
|         super(State.state.osmConnection.userDetails); | ||||
|         this._userDetails = State.state.osmConnection.userDetails; | ||||
|         this._pendingChanges = new PendingChanges(); | ||||
|         this._languagePicker = Utils.CreateLanguagePicker(); | ||||
|         this._loginButton = Translations.t.general.loginWithOpenStreetMap.Clone().onClick(() => State.state.osmConnection.AttemptLogin()); | ||||
|         this._logout = new FixedUiElement("<img src='assets/logout.svg' class='small-userbadge-icon' alt='logout'>") | ||||
|  | @ -116,7 +111,6 @@ export class UserBadge extends UIElement { | |||
|             messageSpan + | ||||
|             csCount + | ||||
|             this._logout.Render() + | ||||
|             this._pendingChanges.Render() + | ||||
|             this._languagePicker.Render() + | ||||
|             "</div>"; | ||||
| 
 | ||||
|  |  | |||
|  | @ -165,11 +165,21 @@ function createLandingPage(layout: Layout) { | |||
|     <meta property="og:title" content="${ogTitle}"> | ||||
|     <meta property="og:description" content="${ogDescr}">` | ||||
| 
 | ||||
|     return template | ||||
|     let output = template | ||||
|         .replace(`./manifest.manifest`, `./${enc(layout.name)}.webmanifest`) | ||||
|         .replace("<!-- $$$OG-META -->", og) | ||||
|         .replace(`<link rel="icon" href="assets/add.svg" sizes="any" type="image/svg+xml">`, | ||||
|             `<link rel="icon" href="${layout.icon}" sizes="any" type="image/svg+xml">`) | ||||
|             `<link rel="icon" href="${layout.icon}" sizes="any" type="image/svg+xml">`); | ||||
| 
 | ||||
|     try { | ||||
|         output = output | ||||
|             .replace(/<!-- DECORATION 0 START -->.*<!-- DECORATION 0 END -->/s, `<img src='${layout.icon}' width="100%" height="100%">`) | ||||
|             .replace(/<!-- DECORATION 1 START -->.*<!-- DECORATION 1 END -->/s, `<img src='${layout.icon}' width="100%" height="100%">`); | ||||
|     } catch (e) { | ||||
|         console.warn("Error while applying logo: ", e) | ||||
|     } | ||||
| 
 | ||||
|     return output; | ||||
| } | ||||
| 
 | ||||
| const blacklist = ["", "test", ".", "..", "manifest", "index", "land", "preferences", "account", "openstreetmap"] | ||||
|  |  | |||
							
								
								
									
										31
									
								
								index.html
									
										
									
									
									
								
							
							
						
						
									
										31
									
								
								index.html
									
										
									
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										1
									
								
								index.ts
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								index.ts
									
										
									
									
									
								
							|  | @ -23,7 +23,6 @@ TagRendering.injectFunction(); | |||
| 
 | ||||
| 
 | ||||
| // --------------------- Special actions based on the parameters -----------------
 | ||||
| 
 | ||||
| // @ts-ignore
 | ||||
| if (location.href.startsWith("http://buurtnatuur.be")) { | ||||
|     // Reload the https version. This is important for the 'locate me' button
 | ||||
|  |  | |||
|  | @ -57,5 +57,5 @@ function createTable(preferences: any) { | |||
|     el.AttachTo("maindiv"); | ||||
| } | ||||
| 
 | ||||
| connection._preferencesHandler.preferences.addCallback((prefs) => createTable(prefs)) | ||||
| connection.preferencesHandler.preferences.addCallback((prefs) => createTable(prefs)) | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										23
									
								
								test.ts
									
										
									
									
									
								
							
							
						
						
									
										23
									
								
								test.ts
									
										
									
									
									
								
							|  | @ -1,14 +1,19 @@ | |||
| import {OsmConnection} from "./Logic/Osm/OsmConnection"; | ||||
| import {UIEventSource} from "./Logic/UIEventSource"; | ||||
| import {ChangesetHandler} from "./Logic/Osm/ChangesetHandler"; | ||||
| import {State} from "./State"; | ||||
| import {LayerDefinition} from "./Customizations/LayerDefinition"; | ||||
| import {AllKnownLayouts} from "./Customizations/AllKnownLayouts"; | ||||
| import {Tag} from "./Logic/TagsFilter"; | ||||
| import {VariableUiElement} from "./UI/Base/VariableUIElement"; | ||||
| const bookcases = AllKnownLayouts.layoutsList[5]; | ||||
| State.state = new State(bookcases); | ||||
| 
 | ||||
| new VariableUiElement( | ||||
|     State.state.osmConnection.changesetHandler.currentChangeset | ||||
| ).AttachTo("maindiv"); | ||||
| 
 | ||||
| const conn = new OsmConnection(false, new UIEventSource<string>(""), false);  | ||||
| conn.AttemptLogin(); | ||||
| window.setTimeout(() => { | ||||
|     | ||||
| 
 | ||||
| const csHandler = conn.changesetHandler; | ||||
| 
 | ||||
| conn.OnLoggedIn((ud) => { | ||||
|      | ||||
|      | ||||
| }); | ||||
|     State.state.osmConnection.changesetHandler.CloseChangeset("89995035") | ||||
| }, 1000) | ||||
|  | @ -6,7 +6,6 @@ import {CustomLayoutFromJSON} from "../Customizations/JSON/CustomLayoutFromJSON" | |||
| import {And} from "../Logic/TagsFilter"; | ||||
| import Translation from "../UI/i18n/Translation"; | ||||
| import T from "./TestHelper"; | ||||
| import {Artwork} from "../Customizations/Layers/Artwork"; | ||||
| 
 | ||||
| 
 | ||||
| new T([ | ||||
|  | @ -32,8 +31,6 @@ new T([ | |||
|         equal(tr.txt, "Test value abc"); | ||||
| 
 | ||||
|     }], | ||||
|     ["JSONify artwork layer", () => { | ||||
|         const a = new Artwork(); | ||||
|         console.log(a.ToJson()) | ||||
|     ["Preset renders icon correctly", () => { | ||||
|     }] | ||||
| ]); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue