forked from MapComplete/MapComplete
		
	Fixes, surveillance cams v0.1
This commit is contained in:
		
							parent
							
								
									b329bbbdb3
								
							
						
					
					
						commit
						ba44024dd9
					
				
					 10 changed files with 137 additions and 65 deletions
				
			
		|  | @ -15,10 +15,11 @@ import * as benches from "../assets/themes/benches/benches.json"; | |||
| import * as charging_stations from "../assets/themes/charging_stations/charging_stations.json" | ||||
| import * as widths from "../assets/themes/widths/width.json" | ||||
| import * as drinking_water from "../assets/themes/drinking_water/drinking_water.json" | ||||
| import LayerConfig from "./JSON/LayerConfig"; | ||||
| import SharedLayers from "./SharedLayers"; | ||||
| import * as surveillance_cameras from "../assets/themes/surveillance_cameras/surveillance_cameras.json" | ||||
| import * as personal from "../assets/themes/personalLayout/personalLayout.json" | ||||
| import LayerConfig from "./JSON/LayerConfig"; | ||||
| import LayoutConfig from "./JSON/LayoutConfig"; | ||||
| import SharedLayers from "./SharedLayers"; | ||||
| 
 | ||||
| export class AllKnownLayouts { | ||||
| 
 | ||||
|  | @ -60,6 +61,7 @@ export class AllKnownLayouts { | |||
|         new LayoutConfig(widths), | ||||
|         new LayoutConfig(buurtnatuur), | ||||
|         new LayoutConfig(bike_monitoring_stations), | ||||
|         new LayoutConfig(surveillance_cameras) | ||||
|     ]; | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -442,7 +442,7 @@ export class InitUiElements { | |||
|         State.state.layerUpdater = new UpdateFromOverpass(State.state); | ||||
| 
 | ||||
|         State.state.availableBackgroundLayers = new AvailableBaseLayers(State.state).availableEditorLayers; | ||||
|         const queryParam = QueryParameters.GetQueryParameter("background", State.state.layoutToUse.data.defaultBackgroundId); | ||||
|         const queryParam = QueryParameters.GetQueryParameter("background", State.state.layoutToUse.data.defaultBackgroundId, "The id of the background layer to start with"); | ||||
| 
 | ||||
|         queryParam.addCallbackAndRun((selectedId: string) => { | ||||
|             const available = State.state.availableBackgroundLayers.data; | ||||
|  | @ -483,7 +483,7 @@ export class InitUiElements { | |||
|             const flayer: FilteredLayer = FilteredLayer.fromDefinition(layer, generateInfo); | ||||
|             flayers.push(flayer); | ||||
| 
 | ||||
|             QueryParameters.GetQueryParameter("layer-" + layer.id, "true") | ||||
|             QueryParameters.GetQueryParameter("layer-" + layer.id, "true", "Wehter or not layer "+layer.id+" is shown") | ||||
|                 .map<boolean>((str) => str !== "false", [], (b) => b.toString()) | ||||
|                 .syncWith( | ||||
|                     flayer.isDisplayed | ||||
|  |  | |||
|  | @ -5,20 +5,22 @@ import {UIEventSource} from "../UIEventSource"; | |||
| 
 | ||||
| export class QueryParameters { | ||||
| 
 | ||||
|     private static order: string [] = ["layout","test","z","lat","lon"]; | ||||
|     private static order: string [] = ["layout", "test", "z", "lat", "lon"]; | ||||
|     private static knownSources = {}; | ||||
|     private static initialized = false; | ||||
|     private static defaults = {} | ||||
| 
 | ||||
|     private static addOrder(key){ | ||||
|         if(this.order.indexOf(key) < 0){ | ||||
|     private static documentation = {} | ||||
| 
 | ||||
|     private static addOrder(key) { | ||||
|         if (this.order.indexOf(key) < 0) { | ||||
|             this.order.push(key) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private static init() { | ||||
| 
 | ||||
|         if(this.initialized){ | ||||
|         if (this.initialized) { | ||||
|             return; | ||||
|         } | ||||
|         this.initialized = true; | ||||
|  | @ -63,6 +65,7 @@ export class QueryParameters { | |||
|         if(!this.initialized){ | ||||
|             this.init(); | ||||
|         } | ||||
|         QueryParameters.documentation[key] = documentation; | ||||
|         if (deflt !== undefined) { | ||||
|             QueryParameters.defaults[key] = deflt; | ||||
|         } | ||||
|  | @ -76,4 +79,12 @@ export class QueryParameters { | |||
|         return source; | ||||
|     } | ||||
| 
 | ||||
|     public static GenerateQueryParameterDocs(): string { | ||||
|         const docs = []; | ||||
|         for (const key in QueryParameters.documentation) { | ||||
|             docs.push("**" + key + "**: " + QueryParameters.documentation[key] + " (default value: _" + QueryParameters.defaults[key] + "_)") | ||||
|         } | ||||
|         return docs.join("\n\n"); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										46
									
								
								README.md
									
										
									
									
									
								
							
							
						
						
									
										46
									
								
								README.md
									
										
									
									
									
								
							|  | @ -103,7 +103,7 @@ A theme has translations into the preset.json (`assets/themes/themename/themenam | |||
| 
 | ||||
| 1. Modify `"language"` to contain the new language, e.g. `"language": "nl"` becomes `"language": ["nl", "en"]` | ||||
| 2. Add extra strings to the texts. If it used to be a single-language theme, one can replace the strings, e.g.: `"description": "Welcome to Open Bookcase Map"` to `"description": {"en": "Welcome to Open Bookcase Map", "nl": "Welkom bij de OpenBoekenruilkastenKaart", "fr": "Bienvenue sûr la carte des petites bibliotheques"}`. If the correct language is not found, it'll fallback to another supported language. | ||||
| 3. If you notice missing translations in the core of MapComplete, fork this project, open [the file containing all translations](https://github.com/pietervdvn/MapComplete/blob/master/UI/i18n/Translations.ts), add add a language string there | ||||
| 3. If you notice missing translations in the core of MapComplete, fork this project, open [the file containing all translations](https://github.com/pietervdvn/MapComplete/blob/master/assets/translations.json), add add a language string there | ||||
| 4. Send a pull request to update the languages, I'll gladly add it! It doesn't have to be a complete translation from the start ;) | ||||
| 
 | ||||
| ### Adding your theme to the repository | ||||
|  | @ -165,6 +165,50 @@ Whenever a change is made -even adding a single tag- the change is uploaded into | |||
| 
 | ||||
| Note that changesets are closed automatically after one hour of inactivity, so we don't have to worry about closing them.  | ||||
| 
 | ||||
| ### Query parameters | ||||
| 
 | ||||
| By adding extra query parameters, more options are available to influence: | ||||
| 
 | ||||
| **test**: If true, 'dryrun' mode is activated. The app will behave as normal, except that changes to OSM will be printed onto the console instead of actually uploaded to osm.org (default value: _false_) | ||||
| 
 | ||||
| **layout**: The layout to load into MapComplete (default value: _bookcases_) | ||||
| 
 | ||||
| **userlayout**: undefined (default value: _false_) | ||||
| 
 | ||||
| **layer-control-toggle**: Wether or not the layer control is shown (default value: _false_) | ||||
| 
 | ||||
| **tab**: The tab that is shown in the welcome-message. 0 = the explanation of the theme,1 = OSM-credits, 2 = sharescreen, 3 = more themes, 4 = about mapcomplete (user must be logged in and have >200 changesets) (default value: _0_) | ||||
| 
 | ||||
| **z**: The initial/current zoom level (default value: _1_) | ||||
| 
 | ||||
| **lat**: The initial/current latitude (default value: _0_) | ||||
| 
 | ||||
| **lon**: The initial/current longitude of the app (default value: _0_) | ||||
| 
 | ||||
| **fs-userbadge**: Disables/Enables the userbadge (and thus disables login capabilities) (default value: _true_) | ||||
| 
 | ||||
| **fs-search**: Disables/Enables the search bar (default value: _true_) | ||||
| 
 | ||||
| **fs-layers**: Disables/Enables the layer control (default value: _true_) | ||||
| 
 | ||||
| **fs-add-new**: Disables/Enables the 'add new feature'-popup. (A theme without presets might not have it in the first place) (default value: _true_) | ||||
| 
 | ||||
| **fs-welcome-message**: undefined (default value: _true_) | ||||
| 
 | ||||
| **fs-iframe**: Disables/Enables the iframe-popup (default value: _false_) | ||||
| 
 | ||||
| **fs-more-quests**: Disables/Enables the 'More Quests'-tab in the welcome message (default value: _true_) | ||||
| 
 | ||||
| **fs-share-screen**: Disables/Enables the 'Share-screen'-tab in the welcome message (default value: _true_) | ||||
| 
 | ||||
| **fs-geolocation**: Disables/Enables the geolocation button (default value: _true_) | ||||
| 
 | ||||
| **oauth_token**: Used to complete the login (default value: _undefined_) | ||||
| 
 | ||||
| **background**: The id of the background layer to start with (default value: _undefined_) | ||||
| 
 | ||||
| **layer-bookcases**: Wehter or not layer bookcases is shown (default value: _true_) index.ts:104:8 | ||||
| 
 | ||||
| # Privacy | ||||
| 
 | ||||
| Privacy is important, we try to leak as little information as possible. | ||||
|  |  | |||
							
								
								
									
										46
									
								
								State.ts
									
										
									
									
									
								
							
							
						
						
									
										46
									
								
								State.ts
									
										
									
									
									
								
							|  | @ -115,10 +115,10 @@ export default class State { | |||
|     public layoutDefinition: string; | ||||
|     public installedThemes: UIEventSource<{ layout: LayoutConfig; definition: string }[]>; | ||||
| 
 | ||||
|     public layerControlIsOpened: UIEventSource<boolean> = QueryParameters.GetQueryParameter("layer-control-toggle", "false") | ||||
|     public layerControlIsOpened: UIEventSource<boolean> = QueryParameters.GetQueryParameter("layer-control-toggle", "false", "Wether or not the layer control is shown") | ||||
|         .map<boolean>((str) => str !== "false", [], b => "" + b) | ||||
| 
 | ||||
|     public welcomeMessageOpenedTab = QueryParameters.GetQueryParameter("tab", "0").map<number>( | ||||
|     public welcomeMessageOpenedTab = QueryParameters.GetQueryParameter("tab", "0", `The tab that is shown in the welcome-message. 0 = the explanation of the theme,1 = OSM-credits, 2 = sharescreen, 3 = more themes, 4 = about mapcomplete (user must be logged in and have >${State.userJourney.mapCompleteHelpUnlock} changesets)`).map<number>( | ||||
|         str => isNaN(Number(str)) ? 0 : Number(str), [], n => "" + n | ||||
|     ); | ||||
| 
 | ||||
|  | @ -138,11 +138,11 @@ export default class State { | |||
|             }) | ||||
|         } | ||||
|         this.zoom = asFloat( | ||||
|             QueryParameters.GetQueryParameter("z", "" + layoutToUse.startZoom) | ||||
|             QueryParameters.GetQueryParameter("z", "" + layoutToUse.startZoom, "The initial/current zoom level") | ||||
|             .syncWith(LocalStorageSource.Get("zoom"))); | ||||
|         this.lat = asFloat(QueryParameters.GetQueryParameter("lat", "" + layoutToUse.startLat) | ||||
|         this.lat = asFloat(QueryParameters.GetQueryParameter("lat", "" + layoutToUse.startLat, "The initial/current latitude") | ||||
|             .syncWith(LocalStorageSource.Get("lat"))); | ||||
|         this.lon = asFloat(QueryParameters.GetQueryParameter("lon", "" + layoutToUse.startLon) | ||||
|         this.lon = asFloat(QueryParameters.GetQueryParameter("lon", "" + layoutToUse.startLon, "The initial/current longitude of the app") | ||||
|             .syncWith(LocalStorageSource.Get("lon"))); | ||||
| 
 | ||||
| 
 | ||||
|  | @ -165,8 +165,8 @@ export default class State { | |||
|         }); | ||||
| 
 | ||||
| 
 | ||||
|         function featSw(key: string, deflt: (layout: LayoutConfig) => boolean, documentation?: string): UIEventSource<boolean> { | ||||
|             const queryParameterSource = QueryParameters.GetQueryParameter(key, undefined); | ||||
|         function featSw(key: string, deflt: (layout: LayoutConfig) => boolean, documentation: string): UIEventSource<boolean> { | ||||
|             const queryParameterSource = QueryParameters.GetQueryParameter(key, undefined, documentation); | ||||
|             // I'm so sorry about someone trying to decipher this
 | ||||
| 
 | ||||
|             // It takes the current layout, extracts the default value for this query paramter. A query parameter event source is then retreived and flattened
 | ||||
|  | @ -180,20 +180,30 @@ export default class State { | |||
| 
 | ||||
| 
 | ||||
|         this.featureSwitchUserbadge = featSw("fs-userbadge", (layoutToUse) => layoutToUse?.enableUserBadge ?? true, | ||||
|             "Disables the userbadge (and thus disables login capabilities)"); | ||||
|         this.featureSwitchSearch = featSw("fs-search", (layoutToUse) => layoutToUse?.enableSearch ?? true); | ||||
|         this.featureSwitchLayers = featSw("fs-layers", (layoutToUse) => layoutToUse?.enableLayers ?? true); | ||||
|         this.featureSwitchAddNew = featSw("fs-add-new", (layoutToUse) => layoutToUse?.enableAddNewPoints ?? true); | ||||
|         this.featureSwitchWelcomeMessage = featSw("fs-welcome-message", () => true); | ||||
|         this.featureSwitchIframe = featSw("fs-iframe", () => false); | ||||
|         this.featureSwitchMoreQuests = featSw("fs-more-quests", (layoutToUse) => layoutToUse?.enableMoreQuests ?? true); | ||||
|         this.featureSwitchShareScreen = featSw("fs-share-screen", (layoutToUse) => layoutToUse?.enableShareScreen ?? true); | ||||
|         this.featureSwitchGeolocation = featSw("fs-geolocation", (layoutToUse) => layoutToUse?.enableGeolocation ?? true); | ||||
|             "Disables/Enables the user information pill (userbadge) at the top left. Disabling this disables logging in and thus disables editing all together, effectively putting MapComplete into read-only mode."); | ||||
|         this.featureSwitchSearch = featSw("fs-search", (layoutToUse) => layoutToUse?.enableSearch ?? true, | ||||
|             "Disables/Enables the search bar"); | ||||
|         this.featureSwitchLayers = featSw("fs-layers", (layoutToUse) => layoutToUse?.enableLayers ?? true, | ||||
|             "Disables/Enables the layer control"); | ||||
|         this.featureSwitchAddNew = featSw("fs-add-new", (layoutToUse) => layoutToUse?.enableAddNewPoints ?? true, | ||||
|             "Disables/Enables the 'add new feature'-popup. (A theme without presets might not have it in the first place)"); | ||||
|         this.featureSwitchWelcomeMessage = featSw("fs-welcome-message", () => true,  | ||||
|             "Disables/enables the help menu or welcome message"); | ||||
|         this.featureSwitchIframe = featSw("fs-iframe", () => false, | ||||
|             "Disables/Enables the iframe-popup"); | ||||
|         this.featureSwitchMoreQuests = featSw("fs-more-quests", (layoutToUse) => layoutToUse?.enableMoreQuests ?? true, | ||||
|             "Disables/Enables the 'More Quests'-tab in the welcome message"); | ||||
|         this.featureSwitchShareScreen = featSw("fs-share-screen", (layoutToUse) => layoutToUse?.enableShareScreen ?? true, | ||||
|             "Disables/Enables the 'Share-screen'-tab in the welcome message"); | ||||
|         this.featureSwitchGeolocation = featSw("fs-geolocation", (layoutToUse) => layoutToUse?.enableGeolocation ?? true, | ||||
|             "Disables/Enables the geolocation button"); | ||||
| 
 | ||||
|         const testParam = QueryParameters.GetQueryParameter("test", "false").data; | ||||
|         const testParam = QueryParameters.GetQueryParameter("test", "false", | ||||
|             "If true, 'dryrun' mode is activated. The app will behave as normal, except that changes to OSM will be printed onto the console instead of actually uploaded to osm.org").data; | ||||
|         this.osmConnection = new OsmConnection( | ||||
|             testParam === "true", | ||||
|             QueryParameters.GetQueryParameter("oauth_token", undefined), | ||||
|             QueryParameters.GetQueryParameter("oauth_token", undefined, | ||||
|                 "Used to complete the login"), | ||||
|             layoutToUse.id, | ||||
|             true | ||||
|         ); | ||||
|  |  | |||
|  | @ -42,6 +42,9 @@ export default class DeleteImage extends UIElement { | |||
|     } | ||||
| 
 | ||||
|     InnerRender(): string { | ||||
|         if(!State.state.featureSwitchUserbadge.data){ | ||||
|             return ""; | ||||
|         } | ||||
| 
 | ||||
|         const value = this.tags.data[this.key]; | ||||
|         if (value === undefined || value === "") { | ||||
|  |  | |||
|  | @ -52,6 +52,10 @@ export class ImageUploadFlow extends UIElement { | |||
| 
 | ||||
|     InnerRender(): string { | ||||
|          | ||||
|         if(!State.state.featureSwitchUserbadge.data){ | ||||
|             return ""; | ||||
|         } | ||||
| 
 | ||||
|         const t = Translations.t.image; | ||||
|         if (State.state.osmConnection.userDetails === undefined) { | ||||
|             return ""; // No user details -> logging in is probably disabled or smthing
 | ||||
|  |  | |||
|  | @ -9,25 +9,11 @@ import {SubstitutedTranslation} from "../SpecialVisualizations"; | |||
| export default class TagRenderingAnswer extends UIElement { | ||||
|     private _tags: UIEventSource<any>; | ||||
|     private _configuration: TagRenderingConfig; | ||||
|     private _content: UIElement; | ||||
| 
 | ||||
|     constructor(tags: UIEventSource<any>, configuration: TagRenderingConfig) { | ||||
|         super(tags); | ||||
|         this._tags = tags; | ||||
|         this._configuration = configuration; | ||||
|         const self = this; | ||||
|         tags.addCallbackAndRun(tags => { | ||||
|             if (tags === undefined) { | ||||
|                 self._content = undefined | ||||
|                 return; | ||||
|             } | ||||
|             const tr = this._configuration.GetRenderValue(tags); | ||||
|             if (tr === undefined) { | ||||
|                 self._content = undefined | ||||
|                 return | ||||
|             } | ||||
|             self._content = new SubstitutedTranslation(tr, self._tags) | ||||
|         }) | ||||
|     } | ||||
| 
 | ||||
|     InnerRender(): string { | ||||
|  | @ -36,10 +22,16 @@ export default class TagRenderingAnswer extends UIElement { | |||
|                 return ""; | ||||
|             } | ||||
|         } | ||||
|         if(this._content === undefined){ | ||||
| 
 | ||||
|         const tags = this._tags.data; | ||||
|         if (tags === undefined) { | ||||
|             return ""; | ||||
|         } | ||||
|         return this._content.Render(); | ||||
|         const tr = this._configuration.GetRenderValue(tags); | ||||
|         if (tr === undefined) { | ||||
|             return ""; | ||||
|         } | ||||
|         return new SubstitutedTranslation(tr, this._tags).Render(); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -156,8 +156,8 @@ | |||
|             "key": "surveillance:type" | ||||
|           }, | ||||
|           "render": { | ||||
|             "en": " Surveills a {surveillance:type}", | ||||
|             "nl": "Bewaakt een {surveillance:type}" | ||||
|             "en": " Surveills a {surveillance:zone}", | ||||
|             "nl": "Bewaakt een {surveillance:zone}" | ||||
|           }, | ||||
|           "mappings": [ | ||||
|             { | ||||
|  | @ -193,6 +193,28 @@ | |||
|                 "nl": "Bewaakt een ingang" | ||||
|               } | ||||
|             }, | ||||
|             { | ||||
|               "if": { | ||||
|                 "and": [ | ||||
|                   "surveillance:zone=corridor" | ||||
|                 ] | ||||
|               }, | ||||
|               "then": { | ||||
|                 "en": "Surveills a corridor", | ||||
|                 "nl": "Bewaakt een gang" | ||||
|               } | ||||
|             }, | ||||
|             { | ||||
|               "if": { | ||||
|                 "and": [ | ||||
|                   "surveillance:zone=public_transport_platform" | ||||
|                 ] | ||||
|               }, | ||||
|               "then": { | ||||
|                 "en": "Surveills a public tranport platform", | ||||
|                 "nl": "Bewaakt een perron of bushalte" | ||||
|               } | ||||
|             }, | ||||
|             { | ||||
|               "if": { | ||||
|                 "and": [ | ||||
							
								
								
									
										20
									
								
								index.ts
									
										
									
									
									
								
							
							
						
						
									
										20
									
								
								index.ts
									
										
									
									
									
								
							|  | @ -4,7 +4,6 @@ import {InitUiElements} from "./InitUiElements"; | |||
| import {QueryParameters} from "./Logic/Web/QueryParameters"; | ||||
| import {UIEventSource} from "./Logic/UIEventSource"; | ||||
| import * as $ from "jquery"; | ||||
| import SharedLayers from "./Customizations/SharedLayers"; | ||||
| import LayoutConfig from "./Customizations/JSON/LayoutConfig"; | ||||
| 
 | ||||
| let defaultLayout = "bookcases" | ||||
|  | @ -54,23 +53,7 @@ if (path !== "index.html" && path !== "") { | |||
|     defaultLayout = path.substr(0, path.length - 5); | ||||
|     console.log("Using layout", defaultLayout); | ||||
| } | ||||
| 
 | ||||
| // Run over all questsets. If a part of the URL matches a searched-for part in the layout, it'll take that as the default
 | ||||
| for (const k in AllKnownLayouts.allSets) { | ||||
|     const layout : LayoutConfig= AllKnownLayouts.allSets[k]; | ||||
|     const possibleParts = (layout.locationContains ?? []); | ||||
|     for (const locationMatch of possibleParts) { | ||||
|         if (locationMatch === "") { | ||||
|             continue | ||||
|         } | ||||
|         if (window.location.href.toLowerCase().indexOf(locationMatch.toLowerCase()) >= 0) { | ||||
|             defaultLayout = layout.name; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| defaultLayout = QueryParameters.GetQueryParameter("layout", defaultLayout).data; | ||||
| 
 | ||||
| defaultLayout = QueryParameters.GetQueryParameter("layout", defaultLayout,"The layout to load into MapComplete").data; | ||||
| let layoutToUse: LayoutConfig = AllKnownLayouts.allSets[defaultLayout.toLowerCase()] ?? AllKnownLayouts["all"]; | ||||
| 
 | ||||
| 
 | ||||
|  | @ -118,3 +101,4 @@ if (layoutFromBase64.startsWith("wiki:")) { | |||
|     InitUiElements.InitAll(layoutToUse, layoutFromBase64, testing, defaultLayout); | ||||
| } | ||||
| 
 | ||||
| // console.log(QueryParameters.GenerateQueryParameterDocs())
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue