forked from MapComplete/MapComplete
		
	Restructuring
This commit is contained in:
		
							parent
							
								
									1af27106f9
								
							
						
					
					
						commit
						5d5cf67820
					
				
					 27 changed files with 220 additions and 247 deletions
				
			
		|  | @ -96,12 +96,12 @@ export class WelcomeMessage extends UIElement { | |||
|     constructor(layout: Layout, | ||||
|                 languagePicker: UIElement, | ||||
|                 osmConnection: OsmConnection) { | ||||
|         super(osmConnection.userDetails); | ||||
|         super(osmConnection?.userDetails); | ||||
|         this.languagePicker = languagePicker; | ||||
|         this.ListenTo(Locale.language); | ||||
|         this.osmConnection = osmConnection; | ||||
|         this.layout = layout; | ||||
|         this.userDetails = osmConnection.userDetails; | ||||
|         this.userDetails = osmConnection?.userDetails; | ||||
| 
 | ||||
|         this.description = layout.welcomeMessage; | ||||
|         this.plzLogIn = layout.gettingStartedPlzLogin; | ||||
|  | @ -110,9 +110,15 @@ export class WelcomeMessage extends UIElement { | |||
|     } | ||||
| 
 | ||||
|     InnerRender(): string { | ||||
| 
 | ||||
|         let loginStatus = ""; | ||||
|         if (this.userDetails !== undefined) { | ||||
|             loginStatus = (this.userDetails.data.loggedIn ? this.welcomeBack : this.plzLogIn).Render(); | ||||
|         } | ||||
| 
 | ||||
|         return "<span>" + | ||||
|             this.description.Render() + | ||||
|             (this.userDetails.data.loggedIn ? this.welcomeBack : this.plzLogIn).Render() + | ||||
|             loginStatus + | ||||
|             this.tail.Render() + | ||||
|             "<br/>" + | ||||
|             this.languagePicker.Render() + | ||||
|  |  | |||
|  | @ -1,6 +1,5 @@ | |||
| import {OsmConnection} from "./Logic/OsmConnection"; | ||||
| import {Changes} from "./Logic/Changes"; | ||||
| import {UIEventSource} from "./UI/UIEventSource"; | ||||
| import {Changes} from "./Logic/Osm/Changes"; | ||||
| 
 | ||||
| export class Helpers { | ||||
| 
 | ||||
|  |  | |||
|  | @ -6,25 +6,30 @@ import {ShareScreen} from "./UI/ShareScreen"; | |||
| import {FixedUiElement} from "./UI/Base/FixedUiElement"; | ||||
| import {CheckBox} from "./UI/Input/CheckBox"; | ||||
| import Combine from "./UI/Base/Combine"; | ||||
| import {OsmConnection} from "./Logic/OsmConnection"; | ||||
| import {Basemap} from "./Logic/Basemap"; | ||||
| import {UIEventSource} from "./UI/UIEventSource"; | ||||
| import {UIElement} from "./UI/UIElement"; | ||||
| import {MoreScreen} from "./UI/MoreScreen"; | ||||
| import {Tag} from "./Logic/TagsFilter"; | ||||
| import {FilteredLayer} from "./Logic/FilteredLayer"; | ||||
| import {FeatureInfoBox} from "./UI/FeatureInfoBox"; | ||||
| import {ElementStorage} from "./Logic/ElementStorage"; | ||||
| import {Preset} from "./UI/SimpleAddUI"; | ||||
| import {Changes} from "./Logic/Osm/Changes"; | ||||
| import {OsmConnection} from "./Logic/Osm/OsmConnection"; | ||||
| import {Basemap} from "./Logic/Leaflet/Basemap"; | ||||
| 
 | ||||
| export class InitUiElements { | ||||
| 
 | ||||
| 
 | ||||
|     static OnlyIf(featureSwitch: UIEventSource<string>, callback: () => void) { | ||||
|     static OnlyIf(featureSwitch: UIEventSource<boolean>, callback: () => void) { | ||||
|         featureSwitch.addCallback(() => { | ||||
| 
 | ||||
|             if (featureSwitch.data === "false") { | ||||
|                 return; | ||||
|             } | ||||
|             if (featureSwitch.data) { | ||||
|                 callback(); | ||||
|             } | ||||
|         }); | ||||
| 
 | ||||
|         if (featureSwitch.data !== "false") { | ||||
|         if (featureSwitch.data) { | ||||
|             callback(); | ||||
|         } | ||||
| 
 | ||||
|  | @ -33,7 +38,9 @@ export class InitUiElements { | |||
| 
 | ||||
|     private static CreateWelcomePane(layoutToUse: Layout, osmConnection: OsmConnection, bm: Basemap) { | ||||
| 
 | ||||
|         const welcome = new WelcomeMessage(layoutToUse, Locale.CreateLanguagePicker(layoutToUse, Translations.t.general.pickLanguage), osmConnection) | ||||
|         const welcome = new WelcomeMessage(layoutToUse, | ||||
|             Locale.CreateLanguagePicker(layoutToUse, Translations.t.general.pickLanguage), | ||||
|             osmConnection) | ||||
| 
 | ||||
|         const fullOptions = new TabbedComponent([ | ||||
|             {header: `<img src='${layoutToUse.icon}'>`, content: welcome}, | ||||
|  | @ -81,4 +88,74 @@ export class InitUiElements { | |||
| 
 | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     static InitLayers(layoutToUse: Layout, osmConnection: OsmConnection, | ||||
|                       changes: Changes, | ||||
|                       allElements: ElementStorage, | ||||
|                       bm: Basemap, | ||||
|                       fullScreenMessage: UIEventSource<UIElement>, | ||||
|                       selectedElement: UIEventSource<any>): { | ||||
|         minZoom: number | ||||
|         flayers: FilteredLayer[], | ||||
|         presets: Preset[] | ||||
|     } { | ||||
|         const addButtons:Preset[] | ||||
|             = []; | ||||
| 
 | ||||
|         const flayers: FilteredLayer[] = [] | ||||
| 
 | ||||
|         let minZoom = 0; | ||||
| 
 | ||||
|         for (const layer of layoutToUse.layers) { | ||||
| 
 | ||||
|             const generateInfo = (tagsES, feature) => { | ||||
| 
 | ||||
|                 return new FeatureInfoBox( | ||||
|                     feature, | ||||
|                     tagsES, | ||||
|                     layer.title, | ||||
|                     layer.elementsToShow, | ||||
|                     changes, | ||||
|                     osmConnection.userDetails | ||||
|                 ) | ||||
|             }; | ||||
| 
 | ||||
|             minZoom = Math.max(minZoom, layer.minzoom); | ||||
| 
 | ||||
|             const flayer = FilteredLayer.fromDefinition(layer, bm, allElements, changes, osmConnection.userDetails, selectedElement, generateInfo); | ||||
| 
 | ||||
|             for (const preset of layer.presets ?? []) { | ||||
| 
 | ||||
|                 if (preset.icon === undefined) { | ||||
|                     const tags = {}; | ||||
|                     for (const tag of preset.tags) { | ||||
|                         const k = tag.key; | ||||
|                         if (typeof (k) === "string") { | ||||
|                             tags[k] = tag.value; | ||||
|                         } | ||||
|                     } | ||||
|                     preset.icon = layer.style(tags)?.icon?.iconUrl; | ||||
|                 } | ||||
| 
 | ||||
|                 const addButton = { | ||||
|                     name: preset.title, | ||||
|                     description: preset.description, | ||||
|                     icon: preset.icon, | ||||
|                     tags: preset.tags, | ||||
|                     layerToAddTo: flayer | ||||
|                 } | ||||
|                 addButtons.push(addButton); | ||||
|             } | ||||
|             flayers.push(flayer); | ||||
|         } | ||||
| 
 | ||||
|          | ||||
|          | ||||
|         return { | ||||
|             minZoom: minZoom, | ||||
|             flayers: flayers, | ||||
|             presets: addButtons | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										6
									
								
								Logic/Bounds.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								Logic/Bounds.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,6 @@ | |||
| export interface Bounds { | ||||
|     north: number, | ||||
|     east: number, | ||||
|     south: number, | ||||
|     west: number | ||||
| } | ||||
|  | @ -1,9 +1,9 @@ | |||
| import {Basemap} from "./Basemap"; | ||||
| import {Overpass} from "./Overpass"; | ||||
| import {Or, TagsFilter} from "./TagsFilter"; | ||||
| import {UIEventSource} from "../UI/UIEventSource"; | ||||
| import {FilteredLayer} from "./FilteredLayer"; | ||||
| 
 | ||||
| import {Bounds} from "./Bounds"; | ||||
| import {Overpass} from "./Osm/Overpass"; | ||||
| import {Basemap} from "./Leaflet/Basemap"; | ||||
| 
 | ||||
| export class LayerUpdater { | ||||
|     private _map: Basemap; | ||||
|  | @ -14,7 +14,7 @@ export class LayerUpdater { | |||
|     /** | ||||
|      * The previous bounds for which the query has been run | ||||
|      */ | ||||
|     private previousBounds: { north: number, east: number, south: number, west: number }; | ||||
|     private previousBounds: Bounds; | ||||
| 
 | ||||
|     private _overpass: Overpass; | ||||
|     private _minzoom: number; | ||||
|  | @ -93,10 +93,21 @@ export class LayerUpdater { | |||
|         if (this.runningQuery.data) { | ||||
|             console.log("Still running a query, skip"); | ||||
|         } | ||||
|         var bbox = this.buildBboxFor(); | ||||
|          | ||||
|         const bounds = this._map.map.getBounds(); | ||||
| 
 | ||||
|         const diff =0.07; | ||||
| 
 | ||||
|         const n = bounds.getNorth() + diff; | ||||
|         const e = bounds.getEast() +  diff; | ||||
|         const s = bounds.getSouth() - diff; | ||||
|         const w = bounds.getWest() -  diff; | ||||
| 
 | ||||
|         this.previousBounds = {north: n, east: e, south: s, west: w}; | ||||
|          | ||||
|         this.runningQuery.setData(true); | ||||
|         const self = this; | ||||
|         this._overpass.queryGeoJson(bbox, | ||||
|         this._overpass.queryGeoJson(this.previousBounds, | ||||
|             function (data) { | ||||
|                 self.handleData(data) | ||||
|             }, | ||||
|  | @ -107,19 +118,7 @@ export class LayerUpdater { | |||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     private buildBboxFor(): string { | ||||
|         const b = this._map.map.getBounds(); | ||||
|         const diff =0.07; | ||||
|     | ||||
|         const n = b.getNorth() + diff; | ||||
|         const e = b.getEast() +  diff; | ||||
|         const s = b.getSouth() - diff; | ||||
|         const w = b.getWest() -  diff; | ||||
| 
 | ||||
|         this.previousBounds = {north: n, east: e, south: s, west: w}; | ||||
| 
 | ||||
|         return "[bbox:" + s + "," + w + "," + n + "," + e + "]"; | ||||
|     } | ||||
| 
 | ||||
|     private IsInBounds(): boolean { | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| import L from "leaflet" | ||||
| import {UIEventSource} from "../UI/UIEventSource"; | ||||
| import {UIElement} from "../UI/UIElement"; | ||||
| import {UIEventSource} from "../../UI/UIEventSource"; | ||||
| import {UIElement} from "../../UI/UIElement"; | ||||
| 
 | ||||
| 
 | ||||
| export class BaseLayers { | ||||
|  | @ -1,8 +1,8 @@ | |||
| import {Basemap} from "./Basemap"; | ||||
| import {UIEventSource} from "../UI/UIEventSource"; | ||||
| import {UIElement} from "../UI/UIElement"; | ||||
| import L from "leaflet"; | ||||
| import {Helpers} from "../Helpers"; | ||||
| import {UIEventSource} from "../../UI/UIEventSource"; | ||||
| import {UIElement} from "../../UI/UIElement"; | ||||
| import {Helpers} from "../../Helpers"; | ||||
| 
 | ||||
| export class GeoLocationHandler extends UIElement { | ||||
| 
 | ||||
|  | @ -1,7 +1,7 @@ | |||
| import {Basemap} from "./Basemap"; | ||||
| import L from "leaflet"; | ||||
| import {UIEventSource} from "../UI/UIEventSource"; | ||||
| import {UIElement} from "../UI/UIElement"; | ||||
| import {UIEventSource} from "../../UI/UIEventSource"; | ||||
| import {UIElement} from "../../UI/UIElement"; | ||||
| 
 | ||||
| /** | ||||
|  * The stray-click-hanlders adds a marker to the map if no feature was clicked. | ||||
|  | @ -2,11 +2,11 @@ | |||
|  * Handles all changes made to OSM. | ||||
|  * Needs an authenticator via OsmConnection | ||||
|  */ | ||||
| import {UIEventSource} from "../../UI/UIEventSource"; | ||||
| import {OsmConnection} from "./OsmConnection"; | ||||
| import {OsmNode, OsmObject} from "./OsmObject"; | ||||
| import {ElementStorage} from "./ElementStorage"; | ||||
| import {UIEventSource} from "../UI/UIEventSource"; | ||||
| import {And, Tag, TagsFilter} from "./TagsFilter"; | ||||
| import {And, Tag, TagsFilter} from "../TagsFilter"; | ||||
| import {ElementStorage} from "../ElementStorage"; | ||||
| 
 | ||||
| export class Changes { | ||||
| 
 | ||||
|  | @ -261,11 +261,4 @@ console.log("Received change",key, value) | |||
|         }); | ||||
|     } | ||||
|      | ||||
|     public asQuestions(qs : QuestionDefinition[]){ | ||||
|         let ls = []; | ||||
|         for (var i in qs){ | ||||
|             ls.push(new Question(this, qs[i])); | ||||
|         }  | ||||
|         return ls; | ||||
|     } | ||||
| } | ||||
|  | @ -1,7 +1,5 @@ | |||
| import * as $ from "jquery" | ||||
| import {UIEventSource} from "../UI/UIEventSource"; | ||||
| import {Basemap} from "./Basemap"; | ||||
| 
 | ||||
| import {Basemap} from "../Leaflet/Basemap"; | ||||
| import $ from "jquery" | ||||
| export class Geocoding { | ||||
| 
 | ||||
|     private static readonly host = "https://nominatim.openstreetmap.org/search?"; | ||||
							
								
								
									
										9
									
								
								Logic/Osm/Notes.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								Logic/Osm/Notes.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | |||
| import {Bounds} from "../Bounds"; | ||||
| 
 | ||||
| export class Notes { | ||||
| 
 | ||||
| 
 | ||||
|     queryGeoJson(bounds: Bounds, continuation: ((any) => void), onFail: ((reason) => void)): void { | ||||
| 
 | ||||
|     } | ||||
| } | ||||
|  | @ -1,6 +1,6 @@ | |||
| // @ts-ignore
 | ||||
| import osmAuth from "osm-auth"; | ||||
| import {UIEventSource} from "../UI/UIEventSource"; | ||||
| import {UIEventSource} from "../../UI/UIEventSource"; | ||||
| 
 | ||||
| export class UserDetails { | ||||
| 
 | ||||
|  | @ -26,7 +26,6 @@ export class OsmConnection { | |||
|         this.auth = new osmAuth({ | ||||
|             oauth_consumer_key: 'hivV7ec2o49Two8g9h8Is1VIiVOgxQ1iYexCbvem', | ||||
|             oauth_secret: 'wDBRTCem0vxD7txrg1y6p5r8nvmz8tAhET7zDASI', | ||||
|             oauth_token: oauth_token.data, | ||||
|             singlepage: true, | ||||
|             landing: window.location.href, | ||||
|             auto: true // show a login form if the user is not authenticated and
 | ||||
|  | @ -1,11 +1,11 @@ | |||
| /** | ||||
|  * Helps in uplaoding, by generating the rigth title, decription and by adding the tag to the changeset | ||||
|  */ | ||||
| import {UIEventSource} from "../UI/UIEventSource"; | ||||
| import {ImageUploadFlow} from "../UI/ImageUploadFlow"; | ||||
| import {Changes} from "./Changes"; | ||||
| import {UIEventSource} from "../../UI/UIEventSource"; | ||||
| import {ImageUploadFlow} from "../../UI/ImageUploadFlow"; | ||||
| import {UserDetails} from "./OsmConnection"; | ||||
| import {SlideShow} from "../UI/SlideShow"; | ||||
| import {SlideShow} from "../../UI/SlideShow"; | ||||
| 
 | ||||
| export class OsmImageUploadHandler { | ||||
|     private _tags: UIEventSource<any>; | ||||
|  | @ -1,11 +1,11 @@ | |||
| import {TagsFilter} from "./TagsFilter"; | ||||
| import * as OsmToGeoJson from "osmtogeojson"; | ||||
| import * as $ from "jquery"; | ||||
| 
 | ||||
| 
 | ||||
| /** | ||||
|  * Interfaces overpass to get all the latest data | ||||
|  */ | ||||
| import {Bounds} from "../Bounds"; | ||||
| import {TagsFilter} from "../TagsFilter"; | ||||
| import $ from "jquery" | ||||
| import * as OsmToGeoJson from "osmtogeojson"; | ||||
| 
 | ||||
| export class Overpass { | ||||
|     private _filter: TagsFilter | ||||
|     public static testUrl: string = null | ||||
|  | @ -14,7 +14,8 @@ export class Overpass { | |||
|         this._filter = filter | ||||
|     } | ||||
| 
 | ||||
|     public buildQuery(bbox: string): string { | ||||
|      | ||||
|     private buildQuery(bbox: string): string { | ||||
|         const filters = this._filter.asOverpass() | ||||
|         let filter = "" | ||||
|         for (const filterOr of filters) { | ||||
|  | @ -25,8 +26,9 @@ export class Overpass { | |||
|         return "https://overpass-api.de/api/interpreter?data=" + encodeURIComponent(query) | ||||
|     } | ||||
|      | ||||
|     queryGeoJson(bbox: string, continuation: ((any) => void), onFail: ((reason) => void)): void { | ||||
|         let query = this.buildQuery(bbox) | ||||
|     queryGeoJson(bounds: Bounds, continuation: ((any) => void), onFail: ((reason) => void)): void { | ||||
|          | ||||
|         let query = this.buildQuery( "[bbox:" + bounds.south + "," + bounds.west + "," + bounds.north + "," + bounds.east + "]") | ||||
| 
 | ||||
|         if(Overpass.testUrl !== null){ | ||||
|             console.log("Using testing URL") | ||||
|  | @ -55,8 +55,8 @@ export class Regex extends TagsFilter { | |||
| 
 | ||||
| 
 | ||||
| export class Tag extends TagsFilter { | ||||
|     public key: string | RegExp | ||||
|     public value: string | RegExp | ||||
|     public key: string | ||||
|     public value: string  | ||||
|     public invertValue: boolean | ||||
| 
 | ||||
|     constructor(key: string | RegExp, value: string | RegExp, invertValue = false) { | ||||
|  | @ -69,7 +69,9 @@ export class Tag extends TagsFilter { | |||
|         } | ||||
| 
 | ||||
|         super() | ||||
|         // @ts-ignore
 | ||||
|         this.key = key | ||||
|         // @ts-ignore
 | ||||
|         this.value = value | ||||
|         this.invertValue = invertValue | ||||
|     } | ||||
|  | @ -107,10 +109,14 @@ export class Tag extends TagsFilter { | |||
|     } | ||||
| 
 | ||||
|     asOverpass(): string[] { | ||||
|         // @ts-ignore
 | ||||
|         const keyIsRegex = this.key instanceof RegExp | ||||
|         // @ts-ignore
 | ||||
|         const key = keyIsRegex ? (this.key as RegExp).source : this.key | ||||
| 
 | ||||
|         // @ts-ignore
 | ||||
|         const valIsRegex = this.value instanceof RegExp | ||||
|         // @ts-ignore
 | ||||
|         const val = valIsRegex ? (this.value as RegExp).source : this.value | ||||
| 
 | ||||
|         const regexKeyPrefix = keyIsRegex ? '~' : '' | ||||
|  |  | |||
|  | @ -1,10 +1,6 @@ | |||
| import {UIElement} from "./UIElement"; | ||||
| import {UIEventSource} from "./UIEventSource"; | ||||
| import {QuestionPicker} from "./QuestionPicker"; | ||||
| import {OsmImageUploadHandler} from "../Logic/OsmImageUploadHandler"; | ||||
| import {ImageCarousel} from "./Image/ImageCarousel"; | ||||
| import {Changes} from "../Logic/Changes"; | ||||
| import {UserDetails} from "../Logic/OsmConnection"; | ||||
| import {VerticalCombine} from "./Base/VerticalCombine"; | ||||
| import {TagRenderingOptions} from "../Customizations/TagRendering"; | ||||
| import {OsmLink} from "../Customizations/Questions/OsmLink"; | ||||
|  | @ -12,6 +8,8 @@ import {WikipediaLink} from "../Customizations/Questions/WikipediaLink"; | |||
| import {And} from "../Logic/TagsFilter"; | ||||
| import {TagDependantUIElement, TagDependantUIElementConstructor} from "../Customizations/UIElementConstructor"; | ||||
| import Translations from "./i18n/Translations"; | ||||
| import {Changes} from "../Logic/Osm/Changes"; | ||||
| import {UserDetails} from "../Logic/Osm/OsmConnection"; | ||||
| 
 | ||||
| export class FeatureInfoBox extends UIElement { | ||||
| 
 | ||||
|  | @ -33,7 +31,6 @@ export class FeatureInfoBox extends UIElement { | |||
| 
 | ||||
| 
 | ||||
|     private _infoboxes: TagDependantUIElement[]; | ||||
|     private _questions: QuestionPicker; | ||||
| 
 | ||||
|     private _oneSkipped = Translations.t.general.oneSkippedQuestion.Clone(); | ||||
|     private _someSkipped = Translations.t.general.skippedQuestions.Clone(); | ||||
|  |  | |||
|  | @ -4,11 +4,11 @@ import {UIEventSource} from "../UIEventSource"; | |||
| import {SlideShow} from "../SlideShow"; | ||||
| import {FixedUiElement} from "../Base/FixedUiElement"; | ||||
| import {VerticalCombine} from "../Base/VerticalCombine"; | ||||
| import {Changes} from "../../Logic/Changes"; | ||||
| import {VariableUiElement} from "../Base/VariableUIElement"; | ||||
| import {ConfirmDialog} from "../ConfirmDialog"; | ||||
| import {UserDetails} from "../../Logic/OsmConnection"; | ||||
| import {TagDependantUIElement, TagDependantUIElementConstructor} from "../../Customizations/UIElementConstructor"; | ||||
| import {Changes} from "../../Logic/Osm/Changes"; | ||||
| import {UserDetails} from "../../Logic/Osm/OsmConnection"; | ||||
| 
 | ||||
| export class ImageCarouselConstructor implements TagDependantUIElementConstructor{ | ||||
|     IsKnown(properties: any): boolean { | ||||
|  |  | |||
|  | @ -1,10 +1,9 @@ | |||
| import {TagDependantUIElement, TagDependantUIElementConstructor} from "../../Customizations/UIElementConstructor"; | ||||
| import {ImageCarousel} from "./ImageCarousel"; | ||||
| import {OsmImageUploadHandler} from "../../Logic/OsmImageUploadHandler"; | ||||
| import {UIEventSource} from "../UIEventSource"; | ||||
| import {Changes} from "../../Logic/Changes"; | ||||
| import {UserDetails} from "../../Logic/OsmConnection"; | ||||
| import {ImageUploadFlow} from "../ImageUploadFlow"; | ||||
| import {Changes} from "../../Logic/Osm/Changes"; | ||||
| import {OsmImageUploadHandler} from "../../Logic/Osm/OsmImageUploadHandler"; | ||||
| 
 | ||||
| export class ImageCarouselWithUploadConstructor implements TagDependantUIElementConstructor{ | ||||
|     IsKnown(properties: any): boolean { | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| import {UIElement} from "./UIElement"; | ||||
| import {UIEventSource} from "./UIEventSource"; | ||||
| import {Changes} from "../Logic/Changes"; | ||||
| import {Changes} from "../Logic/Osm/Changes"; | ||||
| 
 | ||||
| export class PendingChanges extends UIElement { | ||||
|     private _pendingChangesCount: UIEventSource<number>; | ||||
|  |  | |||
|  | @ -1,47 +0,0 @@ | |||
| import {UIElement} from "./UIElement"; | ||||
| import {Question} from "../Logic/Question"; | ||||
| import {UIEventSource} from "./UIEventSource"; | ||||
| 
 | ||||
| export class QuestionPicker extends UIElement { | ||||
|     private readonly _questions: Question[]; | ||||
|     private readonly tags: any; | ||||
|     private source: UIEventSource<any>; | ||||
| 
 | ||||
|     constructor(questions: Question[], | ||||
|                 tags: UIEventSource<any>) { | ||||
|         super(tags); | ||||
|         this._questions = questions; | ||||
|         this.tags = tags.data; | ||||
|         this.source = tags; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     protected InnerRender(): string { | ||||
| 
 | ||||
|         let t = this.tags; | ||||
|         let highestPriority = Number.MIN_VALUE; | ||||
|         let highestQ: Question; | ||||
|         for (const q of this._questions) { | ||||
|              | ||||
|             if (!q.Applicable(t)) { | ||||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
|             const priority = q.question.severity; | ||||
|             if (priority > highestPriority) { | ||||
|                 highestPriority = priority; | ||||
|                 highestQ = q; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         if (highestQ === undefined) { | ||||
|             return "Er zijn geen vragen meer!"; | ||||
|         } | ||||
| 
 | ||||
|         return "<div class='question'>" + | ||||
|             highestQ.CreateHtml(this.source).Render() + | ||||
|             "</div>"; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -1,13 +1,13 @@ | |||
| import {UIElement} from "./UIElement"; | ||||
| import {TextField} from "./Input/TextField"; | ||||
| import {UIEventSource} from "./UIEventSource"; | ||||
| import {FixedUiElement} from "./Base/FixedUiElement"; | ||||
| import {Geocoding} from "../Logic/Geocoding"; | ||||
| import {Basemap} from "../Logic/Basemap"; | ||||
| import {VariableUiElement} from "./Base/VariableUIElement"; | ||||
| import Translation from "./i18n/Translation"; | ||||
| import Locale from "./i18n/Locale"; | ||||
| import {UIEventSource} from "./UIEventSource"; | ||||
| import {UIElement} from "./UIElement"; | ||||
| import Translation from "./i18n/Translation"; | ||||
| import {VariableUiElement} from "./Base/VariableUIElement"; | ||||
| import {FixedUiElement} from "./Base/FixedUiElement"; | ||||
| import {TextField} from "./Input/TextField"; | ||||
| import {Geocoding} from "../Logic/Osm/Geocoding"; | ||||
| import Translations from "./i18n/Translations"; | ||||
| import {Basemap} from "../Logic/Leaflet/Basemap"; | ||||
| 
 | ||||
| 
 | ||||
| export class SearchAndGo extends UIElement { | ||||
|  |  | |||
|  | @ -2,17 +2,17 @@ import {UIElement} from "./UIElement"; | |||
| import {UIEventSource} from "./UIEventSource"; | ||||
| import {Tag} from "../Logic/TagsFilter"; | ||||
| import {FilteredLayer} from "../Logic/FilteredLayer"; | ||||
| import {Changes} from "../Logic/Changes"; | ||||
| import {FixedUiElement} from "./Base/FixedUiElement"; | ||||
| import {Button} from "./Base/Button"; | ||||
| import {UserDetails} from "../Logic/OsmConnection"; | ||||
| import Translations from "./i18n/Translations"; | ||||
| import Combine from "./Base/Combine"; | ||||
| import {SubtleButton} from "./Base/SubtleButton"; | ||||
| import {VerticalCombine} from "./Base/VerticalCombine"; | ||||
| import Locale from "./i18n/Locale"; | ||||
| import {Changes} from "../Logic/Osm/Changes"; | ||||
| import {UserDetails} from "../Logic/Osm/OsmConnection"; | ||||
| 
 | ||||
| interface Preset { | ||||
| export interface Preset { | ||||
|     description: string | UIElement, | ||||
|     name: string | UIElement, | ||||
|     icon: string, | ||||
|  | @ -133,6 +133,11 @@ export class SimpleAddUI extends UIElement { | |||
| 
 | ||||
|         let header: UIElement = Translations.t.general.add.header; | ||||
| 
 | ||||
|          | ||||
|         if(this._userDetails === undefined){ | ||||
|             return header.Render(); | ||||
|         } | ||||
|          | ||||
|         if (!this._userDetails.data.loggedIn) { | ||||
|             return new Combine([header, Translations.t.general.add.pleaseLogin]).Render() | ||||
|         } | ||||
|  |  | |||
|  | @ -1,11 +1,11 @@ | |||
| import {UIElement} from "./UIElement"; | ||||
| import {UserDetails} from "../Logic/OsmConnection"; | ||||
| import {UIEventSource} from "./UIEventSource"; | ||||
| import {Basemap} from "../Logic/Basemap"; | ||||
| 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 {Basemap} from "../Logic/Leaflet/Basemap"; | ||||
| 
 | ||||
| /** | ||||
|  * Handles and updates the user badge | ||||
|  |  | |||
|  | @ -136,12 +136,12 @@ export default class Translations { | |||
|                     }), | ||||
|                     yes: new T({ | ||||
|                         en: "This parking has room for cargo bikes", | ||||
|                         nl: "Deze parking is overdekt (er is een afdak)", | ||||
|                         nl: "Deze parking heeft plaats voor bakfietsen", | ||||
|                         fr: "TODO: fr" | ||||
|                     }), | ||||
|                     designated: new T({ | ||||
|                         en: "This parking has designated (official) spots for cargo bikes.", | ||||
|                         nl: "Deze parking is overdekt (er is een afdak)", | ||||
|                         nl: "Er zijn speciale plaatsen voorzien voor bakfietsen", | ||||
|                         fr: "TODO: fr" | ||||
|                     }), | ||||
|                     no: new T({ | ||||
|  |  | |||
							
								
								
									
										109
									
								
								index.ts
									
										
									
									
									
								
							
							
						
						
									
										109
									
								
								index.ts
									
										
									
									
									
								
							|  | @ -1,20 +1,14 @@ | |||
| import {OsmConnection} from "./Logic/OsmConnection"; | ||||
| import {Changes} from "./Logic/Changes"; | ||||
| import {ElementStorage} from "./Logic/ElementStorage"; | ||||
| import {UIEventSource} from "./UI/UIEventSource"; | ||||
| import {UserBadge} from "./UI/UserBadge"; | ||||
| import {Basemap, BaseLayers} from "./Logic/Basemap"; | ||||
| import {PendingChanges} from "./UI/PendingChanges"; | ||||
| import {CenterMessageBox} from "./UI/CenterMessageBox"; | ||||
| import {Helpers} from "./Helpers"; | ||||
| import {Tag, TagUtils} from "./Logic/TagsFilter"; | ||||
| import {FilteredLayer} from "./Logic/FilteredLayer"; | ||||
| import {TagUtils} from "./Logic/TagsFilter"; | ||||
| import {LayerUpdater} from "./Logic/LayerUpdater"; | ||||
| import {UIElement} from "./UI/UIElement"; | ||||
| import {FullScreenMessageBoxHandler} from "./UI/FullScreenMessageBoxHandler"; | ||||
| import {FeatureInfoBox} from "./UI/FeatureInfoBox"; | ||||
| import {GeoLocationHandler} from "./Logic/GeoLocationHandler"; | ||||
| import {StrayClickHandler} from "./Logic/StrayClickHandler"; | ||||
| import {SimpleAddUI} from "./UI/SimpleAddUI"; | ||||
| import {VariableUiElement} from "./UI/Base/VariableUIElement"; | ||||
| import {SearchAndGo} from "./UI/SearchAndGo"; | ||||
|  | @ -22,7 +16,7 @@ import {AllKnownLayouts} from "./Customizations/AllKnownLayouts"; | |||
| import {CheckBox} from "./UI/Input/CheckBox"; | ||||
| import Translations from "./UI/i18n/Translations"; | ||||
| import Locale from "./UI/i18n/Locale"; | ||||
| import {Layout, WelcomeMessage} from "./Customizations/Layout"; | ||||
| import {Layout} from "./Customizations/Layout"; | ||||
| import {DropDown} from "./UI/Input/DropDown"; | ||||
| import {FixedUiElement} from "./UI/Base/FixedUiElement"; | ||||
| import {LayerSelection} from "./UI/LayerSelection"; | ||||
|  | @ -31,10 +25,12 @@ import {Img} from "./UI/Img"; | |||
| import {QueryParameters} from "./Logic/QueryParameters"; | ||||
| import {Utils} from "./Utils"; | ||||
| import {LocalStorageSource} from "./Logic/LocalStorageSource"; | ||||
| import {Button} from "./UI/Base/Button"; | ||||
| import {TabbedComponent} from "./UI/Base/TabbedComponent"; | ||||
| import {ShareScreen} from "./UI/ShareScreen"; | ||||
| import {InitUiElements} from "./InitUiElements"; | ||||
| import {StrayClickHandler} from "./Logic/Leaflet/StrayClickHandler"; | ||||
| import {BaseLayers, Basemap} from "./Logic/Leaflet/Basemap"; | ||||
| import {GeoLocationHandler} from "./Logic/Leaflet/GeoLocationHandler"; | ||||
| import {OsmConnection} from "./Logic/Osm/OsmConnection"; | ||||
| import {Changes} from "./Logic/Osm/Changes"; | ||||
| 
 | ||||
| 
 | ||||
| // --------------------- Special actions based on the parameters -----------------
 | ||||
|  | @ -112,12 +108,18 @@ const lat = QueryParameters.GetQueryParameter("lat", undefined) | |||
| const lon = QueryParameters.GetQueryParameter("lon", undefined) | ||||
|     .syncWith(LocalStorageSource.Get("lon")); | ||||
| 
 | ||||
| const featureSwitchUserbadge = QueryParameters.GetQueryParameter("fs-userbadge", ""+layoutToUse.enableUserBadge); | ||||
| const featureSwitchSearch = QueryParameters.GetQueryParameter("fs-search", ""+layoutToUse.enableSearch); | ||||
| const featureSwitchWelcomeMessage = QueryParameters.GetQueryParameter("fs-welcome-message", "true"); | ||||
| const featureSwitchLayers = QueryParameters.GetQueryParameter("fs-layers", ""+layoutToUse.enableLayers); | ||||
| const featureSwitchAddNew = QueryParameters.GetQueryParameter("fs-add-new", ""+layoutToUse.enableAdd); | ||||
| const featureSwitchIframe = QueryParameters.GetQueryParameter("fs-iframe", "false"); | ||||
| function featSw(key: string, deflt: boolean): UIEventSource<boolean> { | ||||
|     return QueryParameters.GetQueryParameter("fs-userbadge", "" + deflt).map((str) => { | ||||
|         return str !== "false"; | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| const featureSwitchUserbadge = featSw("fs-userbadge", layoutToUse.enableUserBadge); | ||||
| const featureSwitchSearch = featSw("fs-search", layoutToUse.enableSearch); | ||||
| const featureSwitchLayers = featSw("fs-layers", layoutToUse.enableLayers); | ||||
| const featureSwitchAddNew = featSw("fs-add-new", layoutToUse.enableAdd); | ||||
| const featureSwitchWelcomeMessage = featSw("fs-welcome-message", true); | ||||
| const featureSwitchIframe = featSw("fs-iframe", false); | ||||
| 
 | ||||
| 
 | ||||
| const locationControl = new UIEventSource<{ lat: number, lon: number, zoom: number }>({ | ||||
|  | @ -148,8 +150,8 @@ window.setLanguage = function (language: string) { | |||
| } | ||||
| 
 | ||||
| Locale.language.addCallback((currentLanguage) => { | ||||
|     console.log("REsetting languate to", layoutToUse.supportedLanguages[0]) | ||||
|     if (layoutToUse.supportedLanguages.indexOf(currentLanguage) < 0) { | ||||
|         console.log("Resetting languate to", layoutToUse.supportedLanguages[0], "as", currentLanguage, " is unsupported") | ||||
|         // The current language is not supported -> switch to a supported one
 | ||||
|         Locale.language.setData(layoutToUse.supportedLanguages[0]); | ||||
|     } | ||||
|  | @ -181,63 +183,10 @@ const bm = new Basemap("leafletDiv", locationControl, new VariableUiElement( | |||
| 
 | ||||
| 
 | ||||
| // ------------- Setup the layers -------------------------------
 | ||||
| const addButtons: { | ||||
|     name: string | UIElement, | ||||
|     description: string | UIElement, | ||||
|     icon: string, | ||||
|     tags: Tag[], | ||||
|     layerToAddTo: FilteredLayer | ||||
| }[] | ||||
|     = []; | ||||
| 
 | ||||
| const flayers: FilteredLayer[] = [] | ||||
| const layerSetup = InitUiElements.InitLayers(layoutToUse, osmConnection, changes, allElements, bm, fullScreenMessage, selectedElement); | ||||
| 
 | ||||
| let minZoom = 0; | ||||
| 
 | ||||
| for (const layer of layoutToUse.layers) { | ||||
| 
 | ||||
|     const generateInfo = (tagsES, feature) => { | ||||
| 
 | ||||
|         return new FeatureInfoBox( | ||||
|             feature, | ||||
|             tagsES, | ||||
|             layer.title, | ||||
|             layer.elementsToShow, | ||||
|             changes, | ||||
|             osmConnection.userDetails | ||||
|         ) | ||||
|     }; | ||||
| 
 | ||||
|     minZoom = Math.max(minZoom, layer.minzoom); | ||||
| 
 | ||||
|     const flayer = FilteredLayer.fromDefinition(layer, bm, allElements, changes, osmConnection.userDetails, selectedElement, generateInfo); | ||||
| 
 | ||||
|     for (const preset of layer.presets ?? []) { | ||||
| 
 | ||||
|         if (preset.icon === undefined) { | ||||
|             const tags = {}; | ||||
|             for (const tag of preset.tags) { | ||||
|                 const k = tag.key; | ||||
|                 if (typeof (k) === "string") { | ||||
|                     tags[k] = tag.value; | ||||
|                 } | ||||
|             } | ||||
|             preset.icon = layer.style(tags)?.icon?.iconUrl; | ||||
|         } | ||||
| 
 | ||||
|         const addButton = { | ||||
|             name: preset.title, | ||||
|             description: preset.description, | ||||
|             icon: preset.icon, | ||||
|             tags: preset.tags, | ||||
|             layerToAddTo: flayer | ||||
|         } | ||||
|         addButtons.push(addButton); | ||||
|     } | ||||
|     flayers.push(flayer); | ||||
| } | ||||
| 
 | ||||
| const layerUpdater = new LayerUpdater(bm, minZoom, flayers); | ||||
| const layerUpdater = new LayerUpdater(bm, layerSetup.minZoom, layerSetup.flayers); | ||||
| 
 | ||||
| 
 | ||||
| // --------------- Setting up layer selection ui --------
 | ||||
|  | @ -249,9 +198,9 @@ const openFilterButton = ` | |||
| 
 | ||||
| let baseLayerOptions =  BaseLayers.baseLayers.map((layer) => {return {value: layer, shown: layer.name}}); | ||||
| const backgroundMapPicker = new Combine([new DropDown(`Background map`, baseLayerOptions, bm.CurrentLayer), openFilterButton]); | ||||
| const layerSelection = new Combine([`<p class="filter__label">Maplayers</p>`, new LayerSelection(flayers)]); | ||||
| const layerSelection = new Combine([`<p class="filter__label">Maplayers</p>`, new LayerSelection(layerSetup.flayers)]); | ||||
| let layerControl = backgroundMapPicker; | ||||
| if (flayers.length > 1) { | ||||
| if (layerSetup.flayers.length > 1) { | ||||
|     layerControl = new Combine([layerSelection, backgroundMapPicker]); | ||||
| } | ||||
| 
 | ||||
|  | @ -283,7 +232,7 @@ InitUiElements.OnlyIf(featureSwitchAddNew, () => { | |||
|                 selectedElement, | ||||
|                 layerUpdater.runningQuery, | ||||
|                 osmConnection.userDetails, | ||||
|                 addButtons); | ||||
|                 layerSetup.presets); | ||||
|         } | ||||
|     ); | ||||
| }); | ||||
|  | @ -342,17 +291,17 @@ new FullScreenMessageBoxHandler(fullScreenMessage, () => { | |||
| }).update(); | ||||
| 
 | ||||
| InitUiElements.OnlyIf(featureSwitchWelcomeMessage, () => { | ||||
|     InitUiElements.InitWelcomeMessage(layoutToUse, osmConnection, bm, fullScreenMessage) | ||||
|     InitUiElements.InitWelcomeMessage(layoutToUse, | ||||
|         featureSwitchUserbadge.data ? osmConnection : undefined, bm, fullScreenMessage) | ||||
| }); | ||||
| 
 | ||||
| if ((window != window.top && featureSwitchWelcomeMessage.data === "false") || featureSwitchIframe.data !== "false") { | ||||
|     console.log("WELCOME? ",featureSwitchWelcomeMessage.data) | ||||
| if ((window != window.top && !featureSwitchWelcomeMessage.data) || featureSwitchIframe.data) { | ||||
|     new FixedUiElement(`<a href='${window.location}' target='_blank'><span class='iframe-escape'><img src='assets/pop-out.svg'></span></a>`).AttachTo("top-right") | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| new CenterMessageBox( | ||||
|     minZoom, | ||||
|     layerSetup.minZoom, | ||||
|     centerMessage, | ||||
|     osmConnection, | ||||
|     locationControl, | ||||
|  |  | |||
							
								
								
									
										24
									
								
								test.ts
									
										
									
									
									
								
							
							
						
						
									
										24
									
								
								test.ts
									
										
									
									
									
								
							|  | @ -1,24 +0,0 @@ | |||
| import {FeatureInfoBox} from "./UI/FeatureInfoBox"; | ||||
| import {TagRenderingOptions} from "./Customizations/TagRendering"; | ||||
| import {Changes} from "./Logic/Changes"; | ||||
| import {UIEventSource} from "./UI/UIEventSource"; | ||||
| import {OsmConnection} from "./Logic/OsmConnection"; | ||||
| import {ElementStorage} from "./Logic/ElementStorage"; | ||||
| import {Tag} from "./Logic/TagsFilter"; | ||||
| import FixedText from "./Customizations/Questions/FixedText"; | ||||
| import {FixedUiElement} from "./UI/Base/FixedUiElement"; | ||||
| 
 | ||||
| const osm = new OsmConnection(true); | ||||
| const changes = new Changes("test", osm, new ElementStorage()); | ||||
| 
 | ||||
| const tags = new UIEventSource<any>({name: "<b>ESCAPEE <h3>"}); | ||||
| const x = new TagRenderingOptions( | ||||
|     { | ||||
|         mappings: [ | ||||
|             {k: null, txt: "Test: {name}"} | ||||
|         ] | ||||
|     } | ||||
| ); | ||||
| 
 | ||||
| new FeatureInfoBox(undefined, tags, new FixedText(new FixedUiElement("{name}")), [x], changes, osm.userDetails) | ||||
|     .AttachTo("maindiv"); | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue