More fancyness, less bugs
|  | @ -11,7 +11,7 @@ import Svg from "../../Svg"; | |||
| import {SubstitutedTranslation} from "../../UI/SpecialVisualizations"; | ||||
| import {Utils} from "../../Utils"; | ||||
| import Combine from "../../UI/Base/Combine"; | ||||
| import {Browser} from "leaflet"; | ||||
| import {VariableUiElement} from "../../UI/Base/VariableUIElement"; | ||||
| 
 | ||||
| export default class LayerConfig { | ||||
| 
 | ||||
|  | @ -56,7 +56,8 @@ export default class LayerConfig { | |||
| 
 | ||||
|     tagRenderings: TagRenderingConfig []; | ||||
| 
 | ||||
|     constructor(json: LayerConfigJson, context?: string) { | ||||
|     constructor(json: LayerConfigJson, roamingRenderings: TagRenderingConfig[], | ||||
|                 context?: string) { | ||||
|         context = context + "." + json.id; | ||||
| 
 | ||||
|         this.id = json.id; | ||||
|  | @ -140,7 +141,7 @@ export default class LayerConfig { | |||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     public GenerateLeafletStyle(tags: any): | ||||
|     public GenerateLeafletStyle(tags: any, clickable: boolean): | ||||
|         { | ||||
|             color: string; | ||||
|             icon: { | ||||
|  | @ -149,7 +150,8 @@ export default class LayerConfig { | |||
|                 iconAnchor: [number, number]; | ||||
|                 iconSize: [number, number]; | ||||
|                 html: string; | ||||
|                 rotation: number; | ||||
|                 rotation: string; | ||||
|                 className?: string; | ||||
|             }; | ||||
|             weight: number; dashArray: number[] | ||||
|         } { | ||||
|  | @ -186,7 +188,7 @@ export default class LayerConfig { | |||
|         } | ||||
| 
 | ||||
|         const weight = rendernum(this.width, 5); | ||||
|         const rotation = rendernum(this.rotation, 0); | ||||
|         const rotation = render(this.rotation, "0deg"); | ||||
| 
 | ||||
| 
 | ||||
|         const iconW = num(iconSize[0]); | ||||
|  | @ -209,12 +211,14 @@ export default class LayerConfig { | |||
|             anchorH = iconH; | ||||
|         } | ||||
| 
 | ||||
|         let html = `<img src="${iconUrl}" style="width:100%;height:100%;rotate:${rotation}deg;display:block;" />`; | ||||
|          | ||||
|         let html = `<img src="${iconUrl}" style="width:100%;height:100%;rotate:${rotation};display:block;" />`; | ||||
|          | ||||
|         if (iconUrl.startsWith(Utils.assets_path)) { | ||||
|             const key = iconUrl.substr(Utils.assets_path.length); | ||||
|             html = new Combine([ | ||||
|                 (Svg.All[key] as string).replace(/stop-color:#000000/g, 'stop-color:' + color) | ||||
|             ]).SetStyle(`width:100%;height:100%;rotate:${rotation}deg;display:block;`).Render(); | ||||
|             ]).SetStyle(`width:100%;height:100%;rotate:${rotation};display:block;`).Render(); | ||||
|         } | ||||
|         return { | ||||
|             icon: | ||||
|  | @ -224,7 +228,8 @@ export default class LayerConfig { | |||
|                     iconAnchor: [anchorW, anchorH], | ||||
|                     popupAnchor: [0, 3 - anchorH], | ||||
|                     rotation: rotation, | ||||
|                     iconUrl: iconUrl | ||||
|                     iconUrl: iconUrl, | ||||
|                     className: clickable ? "leaflet-div-icon" : "leaflet-div-icon unclickable" | ||||
|                 }, | ||||
|             color: color, | ||||
|             weight: weight, | ||||
|  |  | |||
|  | @ -66,7 +66,8 @@ export interface LayerConfigJson { | |||
|      */ | ||||
|     iconSize?: string | TagRenderingConfigJson; | ||||
|     /** | ||||
|      * The rotation of an icon, useful for e.g. directions | ||||
|      * The rotation of an icon, useful for e.g. directions. | ||||
|      * Usage: as if it were a css property for 'rotate', thus has to end with 'deg', e.g. `90deg`, `{direction}deg`, `calc(90deg - {camera:direction}deg)`` | ||||
|      */ | ||||
|     rotation?: string | TagRenderingConfigJson; | ||||
| 
 | ||||
|  |  | |||
|  | @ -80,7 +80,7 @@ export default class LayoutConfig { | |||
|                 } else { | ||||
|                     throw "Unkown fixed layer " + layer; | ||||
|                 } | ||||
|             return new LayerConfig(layer, `${this.id}.layers[${i}]`); | ||||
|             return new LayerConfig(layer, this.roamingRenderings,`${this.id}.layers[${i}]`); | ||||
|         }); | ||||
|         this.hideFromOverview = json.hideFromOverview ?? false; | ||||
| 
 | ||||
|  |  | |||
|  | @ -14,6 +14,7 @@ import * as bike_cleaning from "../assets/layers/bike_cleaning/bike_cleaning.jso | |||
| import * as maps from "../assets/layers/maps/maps.json" | ||||
| import * as information_boards from "../assets/layers/information_board/information_board.json" | ||||
| import * as direction from "../assets/layers/direction/direction.json" | ||||
| import * as surveillance_camera from "../assets/layers/surveillance_cameras/surveillance_cameras.json" | ||||
| import LayerConfig from "./JSON/LayerConfig"; | ||||
| 
 | ||||
| export default class SharedLayers { | ||||
|  | @ -25,21 +26,22 @@ export default class SharedLayers { | |||
| 
 | ||||
|     private static getSharedLayers(){ | ||||
|         const sharedLayersList = [ | ||||
|             new LayerConfig(drinkingWater, "shared_layers"), | ||||
|             new LayerConfig(ghostbikes, "shared_layers"), | ||||
|             new LayerConfig(viewpoint, "shared_layers"), | ||||
|             new LayerConfig(bike_parking, "shared_layers"), | ||||
|             new LayerConfig(bike_repair_station, "shared_layers"), | ||||
|             new LayerConfig(bike_monitoring_station, "shared_layers"), | ||||
|             new LayerConfig(birdhides, "shared_layers"), | ||||
|             new LayerConfig(nature_reserve, "shared_layers"), | ||||
|             new LayerConfig(bike_cafes, "shared_layers"), | ||||
|             new LayerConfig(cycling_themed_objects, "shared_layers"), | ||||
|             new LayerConfig(bike_shops, "shared_layers"), | ||||
|             new LayerConfig(bike_cleaning, "shared_layers"), | ||||
|             new LayerConfig(maps, "shared_layers"), | ||||
|             new LayerConfig(direction, "shared_layers"), | ||||
|             new LayerConfig(information_boards, "shared_layers")  | ||||
|             new LayerConfig(drinkingWater,[], "shared_layers"), | ||||
|             new LayerConfig(ghostbikes,[], "shared_layers"), | ||||
|             new LayerConfig(viewpoint,[], "shared_layers"), | ||||
|             new LayerConfig(bike_parking,[], "shared_layers"), | ||||
|             new LayerConfig(bike_repair_station,[], "shared_layers"), | ||||
|             new LayerConfig(bike_monitoring_station,[], "shared_layers"), | ||||
|             new LayerConfig(birdhides,[], "shared_layers"), | ||||
|             new LayerConfig(nature_reserve,[], "shared_layers"), | ||||
|             new LayerConfig(bike_cafes,[], "shared_layers"), | ||||
|             new LayerConfig(cycling_themed_objects,[], "shared_layers"), | ||||
|             new LayerConfig(bike_shops,[], "shared_layers"), | ||||
|             new LayerConfig(bike_cleaning,[], "shared_layers"), | ||||
|             new LayerConfig(maps,[], "shared_layers"), | ||||
|             new LayerConfig(direction,[], "shared_layers"), | ||||
|             new LayerConfig(information_boards,[], "shared_layers"), | ||||
|             new LayerConfig(surveillance_camera,[], "shared_layers") | ||||
|         ]; | ||||
| 
 | ||||
|         const sharedLayers = new Map<string, LayerConfig>(); | ||||
|  |  | |||
|  | @ -129,88 +129,65 @@ export class FilteredLayer { | |||
| 
 | ||||
|         let self = this; | ||||
|         this._geolayer = L.geoJSON(data, { | ||||
|                 style: feature => | ||||
|                     self.layerDef.GenerateLeafletStyle(feature.properties), | ||||
|                 pointToLayer: function (feature, latLng) { | ||||
|                     // Point to layer converts the 'point' to a layer object - as the geojson layer natively cannot handle points
 | ||||
|                     // Click handling is done in the next step
 | ||||
|             style: feature => | ||||
|                 self.layerDef.GenerateLeafletStyle(feature.properties, self._showOnPopup !== undefined), | ||||
|             pointToLayer: function (feature, latLng) { | ||||
|                 // Point to layer converts the 'point' to a layer object - as the geojson layer natively cannot handle points
 | ||||
|                 // Click handling is done in the next step
 | ||||
| 
 | ||||
|                     const style = self.layerDef.GenerateLeafletStyle(feature.properties); | ||||
|                     let marker; | ||||
|                     if (style.icon === undefined) { | ||||
|                         marker = L.circle(latLng, { | ||||
|                             radius: 25, | ||||
|                             color: style.color | ||||
|                         }); | ||||
|                     } else if (style.icon.iconUrl.startsWith("$circle")) { | ||||
|                         marker = L.circle(latLng, { | ||||
|                             radius: 25, | ||||
|                             color: style.color | ||||
|                         }); | ||||
|                     } else { | ||||
|                         marker = L.marker(latLng, { | ||||
|                             icon: L.divIcon(style.icon) | ||||
|                         }); | ||||
|                     } | ||||
|                     return marker; | ||||
|                 }, | ||||
|                 onEachFeature: function (feature, layer: Layer) { | ||||
| 
 | ||||
|                     if (self._showOnPopup === undefined) { | ||||
|                         // No popup contents defined -> don't do anything
 | ||||
|                         return; | ||||
|                     } | ||||
| 
 | ||||
| 
 | ||||
|                     function openPopup(latlng: any) { | ||||
|                         if (layer.getPopup() === undefined | ||||
|                             && (window.screen.availHeight > 600 || window.screen.availWidth > 600) // We DON'T trigger this code on small screens! No need to create a popup
 | ||||
|                         ) { | ||||
|                             const popup = L.popup({ | ||||
|                                 autoPan: true, | ||||
|                                 closeOnEscapeKey: true, | ||||
|                             }, layer); | ||||
| 
 | ||||
|                             popup.setLatLng(latlng) | ||||
| 
 | ||||
|                             layer.bindPopup(popup); | ||||
|                             const eventSource = State.state.allElements.addOrGetElement(feature); | ||||
|                             const uiElement = self._showOnPopup(eventSource, feature); | ||||
|                             // We first render the UIelement (which'll still need an update later on...)
 | ||||
|                             // But at least it'll be visible already
 | ||||
|                             popup.setContent(uiElement.Render()); | ||||
|                             popup.openOn(State.state.bm.map); | ||||
|                             // popup.openOn(State.state.bm.map);
 | ||||
|                             // ANd we perform the pending update
 | ||||
|                             uiElement.Update(); | ||||
|                             // @ts-ignore
 | ||||
|                             popup.Update = () => { | ||||
|                                 uiElement.Update(); | ||||
|                             } | ||||
|                         } else { | ||||
|                             // @ts-ignore
 | ||||
|                             layer.getPopup().Update(); | ||||
|                         } | ||||
| 
 | ||||
| 
 | ||||
|                         // We set the element as selected...
 | ||||
|                         State.state.selectedElement.setData(feature); | ||||
| 
 | ||||
|                     } | ||||
| 
 | ||||
|                     layer.on("click", (e) => { | ||||
|                         // @ts-ignore
 | ||||
|                         openPopup(e.latlng); | ||||
|                         // We mark the event as consumed
 | ||||
|                         L.DomEvent.stop(e); | ||||
|                 const style = self.layerDef.GenerateLeafletStyle(feature.properties, self._showOnPopup !== undefined); | ||||
|                 let marker; | ||||
|                 if (style.icon === undefined) { | ||||
|                     marker = L.circle(latLng, { | ||||
|                         radius: 25, | ||||
|                         color: style.color | ||||
|                     }); | ||||
|                 } else if (style.icon.iconUrl.startsWith("$circle")) { | ||||
|                     marker = L.circle(latLng, { | ||||
|                         radius: 25, | ||||
|                         color: style.color | ||||
|                     }); | ||||
|                 } else { | ||||
|                     marker = L.marker(latLng, { | ||||
|                         icon: L.divIcon(style.icon) | ||||
|                     }); | ||||
| 
 | ||||
|                     if (feature.properties.id.replace(/\//g, "_") === Hash.Get().data) { | ||||
|                         const center = GeoOperations.centerpoint(feature).geometry.coordinates; | ||||
|                         openPopup({lat: center[1], lng: center[0]}) | ||||
|                     } | ||||
| 
 | ||||
|                 } | ||||
|                 return marker; | ||||
|             }, | ||||
|             onEachFeature: function (feature, layer: Layer) { | ||||
| 
 | ||||
|                 if (self._showOnPopup === undefined) { | ||||
|                     // No popup contents defined -> don't do anything
 | ||||
|                     return; | ||||
|                 } | ||||
|                 const popup = L.popup({ | ||||
|                     autoPan: true, | ||||
|                     closeOnEscapeKey: true, | ||||
|                 }, layer); | ||||
| 
 | ||||
|                 let uiElement: UIElement; | ||||
| 
 | ||||
|                 const eventSource = State.state.allElements.addOrGetElement(feature); | ||||
|                 uiElement = self._showOnPopup(eventSource, feature); | ||||
|                 popup.setContent(uiElement.Render()); | ||||
|                 layer.bindPopup(popup); | ||||
|                 // We first render the UIelement (which'll still need an update later on...)
 | ||||
|                 // But at least it'll be visible already
 | ||||
| 
 | ||||
| 
 | ||||
|                 layer.on("click", (e) => { | ||||
|                     // We set the element as selected...
 | ||||
|                     State.state.selectedElement.setData(feature); | ||||
|                     uiElement.Update(); | ||||
|                 }); | ||||
| 
 | ||||
|                 if (feature.properties.id.replace(/\//g, "_") === Hash.Get().data) { | ||||
|                     const center = GeoOperations.centerpoint(feature).geometry.coordinates; | ||||
|                     popup.setLatLng({lat: center[1], lng: center[0]}); | ||||
|                     popup.openOn(State.state.bm.map) | ||||
|                 } | ||||
| 
 | ||||
|             } | ||||
|         }); | ||||
| 
 | ||||
|         if (this.combinedIsDisplayed.data) { | ||||
|  |  | |||
|  | @ -82,7 +82,7 @@ export default class MetaTagging { | |||
|         }) | ||||
|     ) | ||||
|     private static isOpen = new SimpleMetaTagger( | ||||
|         ["_isOpen", "_isOpen:description"], "If 'opening_hours' is present, it will add the current state of the feature (being 'yes' or 'no", | ||||
|         ["_isOpen", "_isOpen:description"], "If 'opening_hours' is present, it will add the current state of the feature (being 'yes' or 'no')", | ||||
|         (feature => { | ||||
|             const tagsSource = State.state.allElements.addOrGetElement(feature); | ||||
|             tagsSource.addCallback(tags => { | ||||
|  | @ -123,16 +123,40 @@ export default class MetaTagging { | |||
|         }) | ||||
|     ) | ||||
| 
 | ||||
|     public static carriageWayWidth = new SimpleMetaTagger( | ||||
|         ["_width:needed","_width:needed:no_pedestrians", "_width:difference"], | ||||
|     private static directionSimplified = new SimpleMetaTagger( | ||||
|         ["_direction:simplified", "_direction:leftright"], "_direction:simplified turns 'camera:direction' and 'direction' into either 0, 45, 90, 135, 180, 225, 270 or 315, whichever is closest. _direction:leftright is either 'left' or 'right', which is left-looking on the map or 'right-looking' on the map", | ||||
|         (feature => { | ||||
|             const tags = feature.properties; | ||||
|             const direction = tags["camera:direction"] ?? tags["direction"]; | ||||
|             if (direction === undefined) { | ||||
|                 return; | ||||
|             } | ||||
|             let n = Number(direction); | ||||
|             if (isNaN(n)) { | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             // [22.5 -> 67.5] is sector 1
 | ||||
|             // [67.5 -> ] is sector 1
 | ||||
|             n = (n + 22.5) % 360; | ||||
|             n = Math.floor(n / 45); | ||||
|             tags["_direction:simplified"] = n; | ||||
|             tags["_direction:leftright"] = n <= 3 ? "right" : "left"; | ||||
| 
 | ||||
| 
 | ||||
|         }) | ||||
|     ) | ||||
| 
 | ||||
|     private static carriageWayWidth = new SimpleMetaTagger( | ||||
|         ["_width:needed", "_width:needed:no_pedestrians", "_width:difference"], | ||||
|         "Legacy for a specific project calculating the needed width for safe traffic on a road. Only activated if 'width:carriageway' is present", | ||||
|         (feature: any, index: number) => { | ||||
| 
 | ||||
|             const properties = feature.properties; | ||||
|             if(properties["width:carriageway"] === undefined){ | ||||
|             if (properties["width:carriageway"] === undefined) { | ||||
|                 return; | ||||
|             } | ||||
|              | ||||
| 
 | ||||
|             const carWidth = 2; | ||||
|             const cyclistWidth = 1.5; | ||||
|             const pedestrianWidth = 0.75; | ||||
|  | @ -239,7 +263,8 @@ export default class MetaTagging { | |||
|         MetaTagging.surfaceArea, | ||||
|         MetaTagging.country, | ||||
|         MetaTagging.isOpen, | ||||
|         MetaTagging.carriageWayWidth | ||||
|         MetaTagging.carriageWayWidth, | ||||
|         MetaTagging.directionSimplified | ||||
| 
 | ||||
|     ]; | ||||
| 
 | ||||
|  |  | |||
|  | @ -136,6 +136,7 @@ export class UpdateFromOverpass { | |||
|         const self = this; | ||||
|         window?.setTimeout( | ||||
|             function () { | ||||
|                 self.runningQuery.setData(false) | ||||
|                 self.update(state) | ||||
|             }, this.retries.data * 5000 | ||||
|         ) | ||||
|  |  | |||
|  | @ -56,8 +56,8 @@ export class Imgur { | |||
|             }, | ||||
|         }; | ||||
|         $.ajax(settings).done(function (response) { | ||||
|             const descr  : string= response.data.description; | ||||
|             const data : any = {}; | ||||
|             const descr: string = response.data.description ?? ""; | ||||
|             const data: any = {}; | ||||
|             for (const tag of descr.split("\n")) { | ||||
|                 const kv = tag.split(":"); | ||||
|                 const k = kv[0]; | ||||
|  |  | |||
							
								
								
									
										2
									
								
								State.ts
									
										
									
									
									
								
							
							
						
						|  | @ -23,7 +23,7 @@ export default class State { | |||
|     // The singleton of the global state
 | ||||
|     public static state: State; | ||||
| 
 | ||||
|     public static vNumber = "0.1.3-rc4"; | ||||
|     public static vNumber = "0.1.3-rc5"; | ||||
| 
 | ||||
|     // The user journey states thresholds when a new feature gets unlocked
 | ||||
|     public static userJourney = { | ||||
|  |  | |||
							
								
								
									
										4
									
								
								Svg.ts
									
										
									
									
									
								
							
							
						
						|  | @ -64,7 +64,7 @@ export default class Svg { | |||
|     public static crosshair_blue_svg() { return new FixedUiElement(Svg.crosshair_blue);} | ||||
|     public static crosshair_blue_ui() { return new FixedUiElement(Svg.crosshair_blue_img);} | ||||
| 
 | ||||
|     public static crosshair = " <!-- Created with Inkscape (http://www.inkscape.org/) -->  <svg    xmlns:dc=\"http://purl.org/dc/elements/1.1/\"    xmlns:cc=\"http://creativecommons.org/ns#\"    xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"    xmlns:svg=\"http://www.w3.org/2000/svg\"    xmlns=\"http://www.w3.org/2000/svg\"    xmlns:sodipodi=\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\"    xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\"    width=\"100\"    height=\"100\"    viewBox=\"0 0 26.458333 26.458334\"    version=\"1.1\"    id=\"svg8\"    inkscape:version=\"0.92.4 (5da689c313, 2019-01-14)\"    sodipodi:docname=\"crosshair.svg\">   <defs      id=\"defs2\" />   <sodipodi:namedview      id=\"base\"      pagecolor=\"#ffffff\"      bordercolor=\"#666666\"      borderopacity=\"1.0\"      inkscape:pageopacity=\"0.0\"      inkscape:pageshadow=\"2\"      inkscape:zoom=\"2\"      inkscape:cx=\"12.898245\"      inkscape:cy=\"23.072799\"      inkscape:document-units=\"px\"      inkscape:current-layer=\"layer1\"      showgrid=\"false\"      units=\"px\"      showguides=\"true\"      inkscape:guide-bbox=\"true\"      inkscape:window-width=\"1920\"      inkscape:window-height=\"1001\"      inkscape:window-x=\"0\"      inkscape:window-y=\"0\"      inkscape:window-maximized=\"1\">     <sodipodi:guide        position=\"13.229167,23.859748\"        orientation=\"1,0\"        id=\"guide815\"        inkscape:locked=\"false\" />     <sodipodi:guide        position=\"14.944824,13.229167\"        orientation=\"0,1\"        id=\"guide817\"        inkscape:locked=\"false\" />   </sodipodi:namedview>   <metadata      id=\"metadata5\">     <rdf:RDF>       <cc:Work          rdf:about=\"\">         <dc:format>image/svg+xml</dc:format>         <dc:type            rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\" />         <dc:title />       </cc:Work>     </rdf:RDF>   </metadata>   <g      inkscape:label=\"Layer 1\"      inkscape:groupmode=\"layer\"      id=\"layer1\"      transform=\"translate(0,-270.54165)\">     <circle        style=\"fill: none !important;fill-opacity:1;stroke:#555555;stroke-width:2.64583335;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.98823529\"        id=\"path815\"        cx=\"13.16302\"        cy=\"283.77081\"        r=\"8.8715391\" />     <path        style=\"fill: none !important;stroke:#555555;stroke-width:2.09723878;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.98823529\"        d=\"M 3.2841366,283.77082 H 1.0418969\"        id=\"path817\"        inkscape:connector-curvature=\"0\" />     <path        style=\"fill: none !important;stroke:#555555;stroke-width:2.11666679;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.98823529\"        d=\"M 25.405696,283.77082 H 23.286471\"        id=\"path817-3\"        inkscape:connector-curvature=\"0\" />     <path        style=\"fill: none !important;stroke:#555555;stroke-width:2.11666679;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.98823529\"        d=\"m 13.229167,295.9489 v -2.11763\"        id=\"path817-3-6\"        inkscape:connector-curvature=\"0\" />     <path        style=\"fill: none !important;stroke:#555555;stroke-width:2.11666668;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.98823529\"        d=\"m 13.229167,275.05759 v -3.44507\"        id=\"path817-3-6-7\"        inkscape:connector-curvature=\"0\" />     <circle        style=\"fill:#555555;fill-opacity:0.99004978;stroke:none;stroke-width:2.81138086;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"        id=\"path866\"        cx=\"13.229166\"        cy=\"283.77081\"        r=\"3.4070117\" />   </g> </svg> " | ||||
|     public static crosshair = " <svg    xmlns:dc=\"http://purl.org/dc/elements/1.1/\"    xmlns:cc=\"http://creativecommons.org/ns#\"    xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"    xmlns:svg=\"http://www.w3.org/2000/svg\"    xmlns=\"http://www.w3.org/2000/svg\"    id=\"svg8\"    version=\"1.1\"    viewBox=\"0 0 26.458333 26.458334\"    height=\"100\"    width=\"100\">   <defs      id=\"defs2\" />   <metadata      id=\"metadata5\">     <rdf:RDF>       <cc:Work          rdf:about=\"\">         <dc:format>image/svg+xml</dc:format>         <dc:type            rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\" />         <dc:title></dc:title>       </cc:Work>     </rdf:RDF>   </metadata>   <g      transform=\"translate(0,-270.54165)\"      id=\"layer1\">     <circle        r=\"8.8715391\"        cy=\"283.77081\"        cx=\"13.16302\"        id=\"path815\"        style=\"fill: none !important;fill-opacity:1;stroke:#000000;stroke-width:2.64583335;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.98823529\" />     <path        id=\"path817\"        d=\"M 3.2841366,283.77082 H 1.0418969\"        style=\"fill: none !important;stroke:#000000;stroke-width:2.09723878;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.98823529\" />     <path        id=\"path817-3\"        d=\"M 25.405696,283.77082 H 23.286471\"        style=\"fill: none !important;stroke:#000000;stroke-width:2.11666679;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.98823529\" />     <path        id=\"path817-3-6\"        d=\"m 13.229167,295.9489 v -2.11763\"        style=\"fill: none !important;stroke:#000000;stroke-width:2.11666679;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.98823529\" />     <path        id=\"path817-3-6-7\"        d=\"m 13.229167,275.05759 v -3.44507\"        style=\"fill: none !important;stroke:#000000;stroke-width:2.11666668;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.98823529\" />     <circle        r=\"3.4070117\"        cy=\"283.77081\"        cx=\"13.229166\"        id=\"path866\"        style=\"fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.81138086;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\" />   </g> </svg> " | ||||
|     public static crosshair_img = Img.AsImageElement(Svg.crosshair) | ||||
|     public static crosshair_svg() { return new FixedUiElement(Svg.crosshair);} | ||||
|     public static crosshair_ui() { return new FixedUiElement(Svg.crosshair_img);} | ||||
|  | @ -79,7 +79,7 @@ export default class Svg { | |||
|     public static direction_svg() { return new FixedUiElement(Svg.direction);} | ||||
|     public static direction_ui() { return new FixedUiElement(Svg.direction_img);} | ||||
| 
 | ||||
|     public static direction_gradient = " <svg    xmlns:dc=\"http://purl.org/dc/elements/1.1/\"    xmlns:cc=\"http://creativecommons.org/ns#\"    xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"    xmlns:svg=\"http://www.w3.org/2000/svg\"    xmlns=\"http://www.w3.org/2000/svg\"    xmlns:xlink=\"http://www.w3.org/1999/xlink\"    width=\"100\"    height=\"100\"    viewBox=\"0 0 100 100\"    version=\"1.1\"    id=\"svg8\">   <metadata      id=\"metadata8\">     <rdf:RDF>       <cc:Work          rdf:about=\"\">         <dc:format>image/svg+xml</dc:format>         <dc:type            rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\" />         <dc:title></dc:title>       </cc:Work>     </rdf:RDF>   </metadata>   <defs      id=\"defs6\">     <linearGradient        id=\"linearGradient820\">       <stop          id=\"stop816\"          offset=\"0\"          style=\"stop-color:#000000;stop-opacity:1;\" />       <stop          id=\"stop818\"          offset=\"1\"          style=\"stop-color:#000000;stop-opacity:0\" />     </linearGradient>     <radialGradient        gradientUnits=\"userSpaceOnUse\"        gradientTransform=\"matrix(1.5439431,-0.01852438,0.02075364,1.7297431,-28.198837,-42.329969)\"        r=\"28.883806\"        fy=\"53.828533\"        fx=\"49.787739\"        cy=\"53.828533\"        cx=\"49.787739\"        id=\"radialGradient828\"        xlink:href=\"#linearGradient820\" />   </defs>   <path      style=\"fill:url(#radialGradient828);fill-opacity:1;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1\"      d=\"M 49.787737,49.857275 20.830626,9.2566092 C 35.979158,-2.144159 60.514289,-3.8195259 78.598237,9.0063685 Z\"      id=\"path821\" /> </svg> " | ||||
|     public static direction_gradient = " <svg    xmlns:dc=\"http://purl.org/dc/elements/1.1/\"    xmlns:cc=\"http://creativecommons.org/ns#\"    xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"    xmlns:svg=\"http://www.w3.org/2000/svg\"    xmlns=\"http://www.w3.org/2000/svg\"    xmlns:xlink=\"http://www.w3.org/1999/xlink\"    xmlns:sodipodi=\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\"    xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\"    width=\"100\"    height=\"100\"    viewBox=\"0 0 100 100\"    version=\"1.1\"    id=\"svg8\"    sodipodi:docname=\"direction_gradient.svg\"    inkscape:version=\"0.92.4 (5da689c313, 2019-01-14)\">   <sodipodi:namedview      pagecolor=\"#ffffff\"      bordercolor=\"#666666\"      borderopacity=\"1\"      objecttolerance=\"10\"      gridtolerance=\"10\"      guidetolerance=\"10\"      inkscape:pageopacity=\"0\"      inkscape:pageshadow=\"2\"      inkscape:window-width=\"1920\"      inkscape:window-height=\"1001\"      id=\"namedview10\"      showgrid=\"false\"      showguides=\"true\"      inkscape:guide-bbox=\"true\"      inkscape:zoom=\"9.44\"      inkscape:cx=\"69.372244\"      inkscape:cy=\"85.073455\"      inkscape:window-x=\"0\"      inkscape:window-y=\"0\"      inkscape:window-maximized=\"1\"      inkscape:current-layer=\"svg8\">     <sodipodi:guide        position=\"50,117.79661\"        orientation=\"1,0\"        id=\"guide819\"        inkscape:locked=\"false\" />     <sodipodi:guide        position=\"57.627119,50\"        orientation=\"0,1\"        id=\"guide821\"        inkscape:locked=\"false\" />   </sodipodi:namedview>   <metadata      id=\"metadata8\">     <rdf:RDF>       <cc:Work          rdf:about=\"\">         <dc:format>image/svg+xml</dc:format>         <dc:type            rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\" />         <dc:title />       </cc:Work>     </rdf:RDF>   </metadata>   <defs      id=\"defs6\">     <linearGradient        id=\"linearGradient820\">       <stop          id=\"innercolor\"          offset=\"0\"          style=\"stop-color:#000000;stop-opacity:1;\" />       <stop          id=\"outercolor\"          offset=\"1\"          style=\"stop-color:#000000;stop-opacity:0\" />     </linearGradient>     <radialGradient        gradientUnits=\"userSpaceOnUse\"        gradientTransform=\"matrix(1.5439431,-0.01852438,0.02075364,1.7297431,-27.986574,-42.187244)\"        r=\"28.883806\"        fy=\"53.828533\"        fx=\"49.787739\"        cy=\"53.828533\"        cx=\"49.787739\"        id=\"radialGradient828\"        xlink:href=\"#linearGradient820\" />   </defs>   <path      style=\"fill:url(#radialGradient828);fill-opacity:1;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1\"      d=\"M 50,50 21.042889,9.3993342 C 36.191421,-2.001434 60.726552,-3.6768009 78.8105,9.1490935 Z\"      id=\"path821\"      inkscape:connector-curvature=\"0\" /> </svg> " | ||||
|     public static direction_gradient_img = Img.AsImageElement(Svg.direction_gradient) | ||||
|     public static direction_gradient_svg() { return new FixedUiElement(Svg.direction_gradient);} | ||||
|     public static direction_gradient_ui() { return new FixedUiElement(Svg.direction_gradient_img);} | ||||
|  |  | |||
|  | @ -29,6 +29,8 @@ export default class EditableTagRendering extends UIElement { | |||
| 
 | ||||
|         this._answer = new TagRenderingAnswer(tags, configuration); | ||||
|         this._answer.SetStyle("width:100%;") | ||||
|         this._question = this.GenerateQuestion(); | ||||
|         this.dumbMode = false; | ||||
| 
 | ||||
|         if (this._configuration.question !== undefined) { | ||||
|             if (State.state.featureSwitchUserbadge.data) { | ||||
|  | @ -66,7 +68,6 @@ export default class EditableTagRendering extends UIElement { | |||
|     InnerRender(): string { | ||||
| 
 | ||||
|         if (this._editMode.data) { | ||||
|             this._question = this.GenerateQuestion(); | ||||
|             return this._question.Render(); | ||||
|         } | ||||
|          | ||||
|  |  | |||
|  | @ -21,7 +21,7 @@ export class FeatureInfoBox extends UIElement { | |||
|         layerConfig: LayerConfig | ||||
|     ) { | ||||
|         super(); | ||||
|         if(layerConfig === undefined){ | ||||
|         if (layerConfig === undefined) { | ||||
|             throw "Undefined layerconfig" | ||||
|         } | ||||
|         this._tags = tags; | ||||
|  | @ -30,7 +30,7 @@ export class FeatureInfoBox extends UIElement { | |||
| 
 | ||||
|         this._title = layerConfig.title === undefined ? undefined : | ||||
|             new TagRenderingAnswer(tags, layerConfig.title) | ||||
|             .SetClass("featureinfobox-title"); | ||||
|                 .SetClass("featureinfobox-title"); | ||||
|         this._titleIcons = new Combine( | ||||
|             layerConfig.titleIcons.map(icon => new TagRenderingAnswer(tags, icon))) | ||||
|             .SetClass("featureinfobox-icons"); | ||||
|  |  | |||
|  | @ -102,7 +102,20 @@ export default class SpecialVisualizations { | |||
|         args: { name: string, defaultValue?: string, doc: string }[] | ||||
|     }[] = | ||||
| 
 | ||||
|         [ | ||||
|         [{ | ||||
|             funcName: "all_tags", | ||||
|             docs: "Prints all key-value pairs of the object - used for debugging", | ||||
|             args: [], | ||||
|             constr: ((tags: UIEventSource<any>) => { | ||||
|                 return new VariableUiElement(tags.map(tags => { | ||||
|                     const parts = []; | ||||
|                     for (const key in tags) { | ||||
|                         parts.push(key + "=" + tags[key]); | ||||
|                     } | ||||
|                     return parts.join("<br/>") | ||||
|                 })).SetStyle("border: 1px solid black; border-radius: 1em;padding:1em;display:block;") | ||||
|             }) | ||||
|         }, | ||||
|             { | ||||
|                 funcName: "image_carousel", | ||||
|                 docs: "Creates an image carousel for the given sources. An attempt will be made to guess what source is used. Supported: Wikidata identifiers, Wikipedia pages, Wikimedia categories, IMGUR (with attribution, direct links)", | ||||
|  | @ -170,21 +183,7 @@ export default class SpecialVisualizations { | |||
|                     return new VariableUiElement(source.map(data => data[neededValue] ?? "Loading...")); | ||||
|                 } | ||||
|             }, | ||||
|              | ||||
|             { | ||||
|                 funcName: "all_tags", | ||||
|                 docs: "Prints all key-value pairs of the object - used for debugging", | ||||
|                 args:[], | ||||
|                 constr: ((tags: UIEventSource<any>) => { | ||||
|                     return new VariableUiElement(tags.map(tags => { | ||||
|                         const parts = []; | ||||
|                         for (const key in tags) { | ||||
|                             parts.push(key+"="+tags[key]); | ||||
|                         } | ||||
|                         return parts.join("<br/>") | ||||
|                     })).SetStyle("border: 1px solid black; border-radius: 1em;padding:1em;display:block;") | ||||
|                 }) | ||||
|             } | ||||
| 
 | ||||
| 
 | ||||
|         ] | ||||
|     static HelpMessage: UIElement = SpecialVisualizations.GenHelpMessage(); | ||||
|  |  | |||
|  | @ -16,11 +16,11 @@ | |||
|   "tagRenderings": [], | ||||
|   "icon":  "./assets/svg/direction_gradient.svg", | ||||
|   "rotation": { | ||||
|     "render": "{camera:direction}", | ||||
|     "render": "{camera:direction}deg", | ||||
|     "mappings": [ | ||||
|       { | ||||
|         "if": "direction~*", | ||||
|         "then": "{direction}" | ||||
|         "then": "{direction}deg" | ||||
|       } | ||||
|     ] | ||||
|   }, | ||||
|  |  | |||
							
								
								
									
										379
									
								
								assets/layers/surveillance_cameras/surveillance_cameras.json
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,379 @@ | |||
| { | ||||
|   "id": "surveillance_cameras", | ||||
|   "name": { | ||||
|     "en": "Surveillance camera's", | ||||
|     "nl": "Bewakingscamera's" | ||||
|   }, | ||||
|   "minzoom": 12, | ||||
|   "overpassTags": { | ||||
|     "and": [ | ||||
|       "man_made=surveillance", | ||||
|       { | ||||
|         "or": [ | ||||
|           "surveillance:type=camera", | ||||
|           "surveillance:type=ALPR", | ||||
|           "surveillance:type=ANPR" | ||||
|         ] | ||||
|       } | ||||
|     ] | ||||
|   }, | ||||
|   "title": { | ||||
|     "render": { | ||||
|       "en": "Surveillance Camera", | ||||
|       "nl": "Bewakingscamera" | ||||
|     } | ||||
|   }, | ||||
|   "description": {}, | ||||
|   "tagRenderings": [ | ||||
|     "images", | ||||
|     { | ||||
|       "#": "Camera type: fixed; panning; dome", | ||||
|       "question": { | ||||
|         "en": "What kind of camera is this?", | ||||
|         "nl": "Wat voor soort camera is dit?" | ||||
|       }, | ||||
|       "mappings": [ | ||||
|         { | ||||
|           "if": { | ||||
|             "and": [ | ||||
|               "camera:type=fixed" | ||||
|             ] | ||||
|           }, | ||||
|           "then": { | ||||
|             "en": "A fixed (non-moving) camera", | ||||
|             "nl": "Een vaste camera" | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
|           "if": { | ||||
|             "and": [ | ||||
|               "camera:type=dome" | ||||
|             ] | ||||
|           }, | ||||
|           "then": { | ||||
|             "en": "A dome camera (which can turn)", | ||||
|             "nl": "Een dome (bolvormige camera die kan draaien)" | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
|           "if": { | ||||
|             "and": [ | ||||
|               "camera:type=panning" | ||||
|             ] | ||||
|           }, | ||||
|           "then": { | ||||
|             "en": "A panning camera", | ||||
|             "nl": "Een camera die (met een motor) van links naar rechts kan draaien" | ||||
|           } | ||||
|         } | ||||
|       ] | ||||
|     }, | ||||
|     { | ||||
|       "#": "direction. We don't ask this for a dome on a pole or ceiling as it has a 360° view", | ||||
|       "question": { | ||||
|         "en": "In which geographical direction does this camera film?", | ||||
|         "nl": "Naar welke geografische richting filmt deze camera?" | ||||
|       }, | ||||
|       "render": "Films to {camera:direction}", | ||||
|       "condition": { | ||||
|         "or": [ | ||||
|           "camera:type!=dome", | ||||
|           { | ||||
|             "and": [ | ||||
|               "camera:mount!=ceiling", | ||||
|               "camera:mount!=pole" | ||||
|             ] | ||||
|           } | ||||
|         ] | ||||
|       }, | ||||
|       "freeform": { | ||||
|         "key": "camera:direction", | ||||
|         "type": "direction" | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "#": "Operator", | ||||
|       "freeform": { | ||||
|         "key": "operator" | ||||
|       }, | ||||
|       "question": { | ||||
|         "en": "Who operates this CCTV?", | ||||
|         "nl": "Wie beheert deze bewakingscamera?" | ||||
|       }, | ||||
|       "render": { | ||||
|         "en": "Operated by {operator}", | ||||
|         "nl": "Beheer door {operator}" | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "#": "Surveillance type: public, outdoor, indoor", | ||||
|       "question": { | ||||
|         "en": "What kind of surveillance is this camera", | ||||
|         "nl": "Wat soort bewaking wordt hier uitgevoerd?" | ||||
|       }, | ||||
|       "mappings": [ | ||||
|         { | ||||
|           "if": { | ||||
|             "and": [ | ||||
|               "surveillance=public" | ||||
|             ] | ||||
|           }, | ||||
|           "then": { | ||||
|             "en": "A public area is surveilled, such as a street, a bridge, a square, a park, a train station, a public corridor or tunnel,...", | ||||
|             "nl": "Bewaking van de publieke ruilmte, dus een straat, een brug, een park, een plein, een stationsgebouw, een publiek toegankelijke gang of tunnel..." | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
|           "if": { | ||||
|             "and": [ | ||||
|               "surveillance=outdoor" | ||||
|             ] | ||||
|           }, | ||||
|           "then": { | ||||
|             "en": "An outdoor, yet private area is surveilled (e.g. a parking lot, a fuel station, courtyard, entrance, private driveway, ...)", | ||||
|             "nl": "Een buitenruimte met privaat karakter (zoals een privé-oprit, een parking, tankstation, ...)" | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
|           "if": { | ||||
|             "and": [ | ||||
|               "surveillance=indoor" | ||||
|             ] | ||||
|           }, | ||||
|           "then": { | ||||
|             "nl": "Een private binnenruimte wordt bewaakt, bv. een winkel, een parkeergarage, ...", | ||||
|             "en": "A private indoor area is surveilled, e.g. a shop, a private underground parking, ..." | ||||
|           } | ||||
|         } | ||||
|       ] | ||||
|     }, | ||||
|     { | ||||
|       "#": "Indoor camera? This isn't clear for 'public'-cameras", | ||||
|       "question": { | ||||
|         "en": "Is the public space surveilled by this camera an indoor or outdoor space?", | ||||
|         "nl": "Bevindt de bewaakte publieke ruimte camera zich binnen of buiten?" | ||||
|       }, | ||||
|       "condition": { | ||||
|         "and": [ | ||||
|           "surveillance:type=public" | ||||
|         ] | ||||
|       }, | ||||
|       "mappings": [ | ||||
|         { | ||||
|           "if": "indoor=yes", | ||||
|           "then": { | ||||
|             "en": "This camera is located indoors", | ||||
|             "nl": "Deze camera bevindt zich binnen" | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
|           "if": "indoor=no", | ||||
|           "then": { | ||||
|             "en": "This camera is located outdoors", | ||||
|             "nl": "Deze camera bevindt zich buiten" | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
|           "if": "indoor=", | ||||
|           "then": { | ||||
|             "en": "This camera is probably located outdoors", | ||||
|             "nl": "Deze camera bevindt zich waarschijnlijk buiten" | ||||
|           }, | ||||
|           "hideInAnswer": true | ||||
|         } | ||||
|       ] | ||||
|     }, | ||||
|     { | ||||
|       "#": "Level", | ||||
|       "question": { | ||||
|         "en": "On which level is this camera located?", | ||||
|         "nl": "Op welke verdieping bevindt deze camera zich?" | ||||
|       }, | ||||
|       "freeform": { | ||||
|         "key": "level", | ||||
|         "type": "nat" | ||||
|       }, | ||||
|       "condition": { | ||||
|         "or": [ | ||||
|           "indoor=yes", | ||||
|           "surveillance:type=ye" | ||||
|         ] | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "#": "Surveillance:zone", | ||||
|       "question": { | ||||
|         "en": "What exactly is surveilled here?", | ||||
|         "nl": "Wat wordt hier precies bewaakt?" | ||||
|       }, | ||||
|       "freeform": { | ||||
|         "key": "surveillance:zone" | ||||
|       }, | ||||
|       "render": { | ||||
|         "en": " Surveills a {surveillance:zone}", | ||||
|         "nl": "Bewaakt een {surveillance:zone}" | ||||
|       }, | ||||
|       "mappings": [ | ||||
|         { | ||||
|           "if": { | ||||
|             "and": [ | ||||
|               "surveillance:zone=parking" | ||||
|             ] | ||||
|           }, | ||||
|           "then": { | ||||
|             "en": "Surveills a parking", | ||||
|             "nl": "Bewaakt een parking" | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
|           "if": { | ||||
|             "and": [ | ||||
|               "surveillance:zone=traffic" | ||||
|             ] | ||||
|           }, | ||||
|           "then": { | ||||
|             "en": "Surveills the traffic", | ||||
|             "nl": "Bewaakt het verkeer" | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
|           "if": { | ||||
|             "and": [ | ||||
|               "surveillance:zone=entrance" | ||||
|             ] | ||||
|           }, | ||||
|           "then": { | ||||
|             "en": "Surveills an entrance", | ||||
|             "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": [ | ||||
|               "surveillance:zone=shop" | ||||
|             ] | ||||
|           }, | ||||
|           "then": { | ||||
|             "en": "Surveills a shop", | ||||
|             "nl": "Bewaakt een winkel" | ||||
|           } | ||||
|         } | ||||
|       ] | ||||
|     }, | ||||
|     { | ||||
|       "#": "camera:mount", | ||||
|       "question": { | ||||
|         "en": "How is this camera placed?", | ||||
|         "nl": "Hoe is deze camera geplaatst?" | ||||
|       }, | ||||
|       "freeform": { | ||||
|         "key": "camera:mount" | ||||
|       }, | ||||
|       "mappings": [ | ||||
|         { | ||||
|           "if": "camera:mount=wall", | ||||
|           "then": { | ||||
|             "en": "This camera is placed against a wall", | ||||
|             "nl": "Deze camera hangt aan een muur" | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
|           "if": "camera:mount=pole", | ||||
|           "then": { | ||||
|             "en": "This camera is placed one a pole", | ||||
|             "nl": "Deze camera staat op een paal" | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
|           "if": "camera:mount=ceiling", | ||||
|           "then": { | ||||
|             "en": "This camera is placed on the ceiling", | ||||
|             "nl": "Deze camera hangt aan het plafond" | ||||
|           } | ||||
|         } | ||||
|       ] | ||||
|     } | ||||
|   ], | ||||
|   "hideUnderlayingFeaturesMinPercentage": 0, | ||||
|   "icon": { | ||||
|     "render": "./assets/themes/surveillance_cameras/logo.svg", | ||||
|     "mappings": [ | ||||
|       { | ||||
|         "if": "camera:type=dome", | ||||
|         "then": "./assets/themes/surveillance_cameras/dome.svg" | ||||
|       }, | ||||
|       { | ||||
|         "if": "_direction:leftright=right", | ||||
|         "then": "./assets/themes/surveillance_cameras/cam_right.svg" | ||||
|       }, | ||||
|       { | ||||
|         "if": "_direction:leftright=left", | ||||
|         "then": "./assets/themes/surveillance_cameras/cam_left.svg" | ||||
|       } | ||||
|     ] | ||||
|   }, | ||||
|   "rotation": { | ||||
|     "render": "calc({camera:direction}deg + 90deg)", | ||||
|     "mappings": [ | ||||
|       { | ||||
|         "if": "camera:type=dome", | ||||
|         "then": "0" | ||||
|       }, | ||||
|       { | ||||
|         "if": "_direction:leftright=right", | ||||
|         "then": "calc({camera:direction}deg - 90deg)" | ||||
|       } | ||||
|     ] | ||||
|   }, | ||||
|   "width": { | ||||
|     "render": "8" | ||||
|   }, | ||||
|   "iconSize": { | ||||
|     "mappings": [ | ||||
|       { | ||||
|         "if": "camera:type=dome", | ||||
|         "then": "50,50,center" | ||||
|       }, | ||||
|       { | ||||
|         "if": "_direction:leftright~*", | ||||
|         "then": "100,35,center" | ||||
|       } | ||||
|     ], | ||||
|     "render": "50,50,center" | ||||
|   }, | ||||
|   "color": { | ||||
|     "render": "#f00" | ||||
|   }, | ||||
|   "presets": [ | ||||
|     { | ||||
|       "tags": [ | ||||
|         "man_made=surveillance", | ||||
|         "surveillance:type=camera" | ||||
|       ], | ||||
|       "title": "Surveillance camera" | ||||
|     } | ||||
|   ], | ||||
|   "wayHandling": 2 | ||||
| } | ||||
|  | @ -4,7 +4,7 @@ | |||
|   }, | ||||
|    | ||||
|   "osmlink": { | ||||
|     "render": "<a href='https://openstreetmap.org/{id}' target='_blank'><img src='data:image/svg+xml;base64,PHN2ZyBjbGFzcz0nb3NtLWxvZ28nIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgaGVpZ2h0PSIxMDBweCIgd2lkdGg9IjEwMHB4IiB2ZXJzaW9uPSIxLjEiIHZpZXdCb3g9IjAgMCA2NiA2NCI+CiAgICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC44NDksIC02MSkiIGZpbGw9IiM3ZWJjNmYiPgogICAgICAgIDxwYXRoIGQ9Ik0wLjg0OSw2MSBMNi40MTQsNzUuNjA5IEwwLjg0OSw5MC4yMTcgTDYuNDE0LDEwNC44MjYgTDAuODQ5LDExOS40MzUgTDQuMjY2LDEyMC43MzkgTDIyLjgzMSwxMDIuMTgzIEwyNi4xNjIsMTAyLjY5NiBMMzAuMjA1LDk4LjY1MiBDMjcuODE5LDk1Ljg4OCAyNi4wMzMsOTIuNTkgMjUuMDU3LDg4Ljk0OCBMMjYuOTUzLDg3LjM5MSBDMjYuNjI3LDg1Ljg3OSAyNi40NDksODQuMzEzIDI2LjQ0OSw4Mi43MDQgQzI2LjQ0OSw3NC42NyAzMC43MzQsNjcuNjExIDM3LjEzNiw2My42OTYgTDMwLjA2Niw2MSBMMTUuNDU3LDY2LjU2NSBMMC44NDksNjEgeiIvPgogICAgICAgIDxwYXRoIGQ9Ik00OC43MSw2NC42MTcgQzQ4LjQwNiw2NC42MTcgNDguMTA1LDY0LjYyOSA0Ny44MDUsNjQuNjQzIEM0Ny41Miw2NC42NTcgNDcuMjM0LDY0LjY3NyA0Ni45NTMsNjQuNzA0IEM0Ni43MjYsNjQuNzI2IDQ2LjQ5OSw2NC43NTMgNDYuMjc1LDY0Ljc4MyBDNDYuMDM5LDY0LjgxNCA0NS44MTEsNjQuODQ3IDQ1LjU3OSw2NC44ODcgQzQ1LjUwNiw2NC45IDQ1LjQzNCw2NC45MTcgNDUuMzYyLDY0LjkzIEM0NS4yMTYsNjQuOTU4IDQ1LjA3Miw2NC45ODcgNDQuOTI3LDY1LjAxNyBDNDQuODEyLDY1LjA0MiA0NC42OTQsNjUuMDYgNDQuNTc5LDY1LjA4NyBDNDQuNDQyLDY1LjExOSA0NC4zMDcsNjUuMTU2IDQ0LjE3LDY1LjE5MSBDNDMuOTQzLDY1LjI1IDQzLjcxNiw2NS4zMTUgNDMuNDkyLDY1LjM4MyBDNDMuMzIzLDY1LjQzMyA0My4xNTUsNjUuNDg0IDQyLjk4OCw2NS41MzkgQzQyLjgxOSw2NS41OTUgNDIuNjUsNjUuNjUyIDQyLjQ4Myw2NS43MTMgQzQyLjQ3NSw2NS43MTYgNDIuNDY2LDY1LjcxOSA0Mi40NTcsNjUuNzIyIEMzNS44MTksNjguMTU4IDMxLjAyMiw3NC4zNjkgMzAuNjQ5LDgxLjc3NCBDMzAuNjMzLDgyLjA4MyAzMC42MjIsODIuMzkxIDMwLjYyMiw4Mi43MDQgQzMwLjYyMiw4My4wMTQgMzAuNjMxLDgzLjMyMSAzMC42NDksODMuNjI2IEMzMC42NDksODMuNjI5IDMwLjY0OCw4My42MzIgMzAuNjQ5LDgzLjYzNSBDMzAuNjYyLDgzLjg2MiAzMC42ODEsODQuMDg4IDMwLjcwMSw4NC4zMTMgQzMxLjQ2Niw5My4wMzcgMzguMzc3LDk5Ljk0OCA0Ny4xMDEsMTAwLjcxMyBDNDcuMzI2LDEwMC43MzMgNDcuNTUyLDEwMC43NTQgNDcuNzc5LDEwMC43NjUgQzQ3Ljc4MiwxMDAuNzY1IDQ3Ljc4NSwxMDAuNzY1IDQ3Ljc4OCwxMDAuNzY1IEM0OC4wOTMsMTAwLjc4MyA0OC4zOTksMTAwLjc5MSA0OC43MDksMTAwLjc5MSBDNTMuNjM5LDEwMC43OTEgNTguMDk2LDk4LjgzMyA2MS4zNTMsOTUuNjUyIEM2MS41MzIsOTUuNDc3IDYxLjcxMiw5NS4zMDQgNjEuODgzLDk1LjEyMiBDNjEuOTEzLDk1LjA5IDYxLjk0MSw5NS4wNTggNjEuOTcsOTUuMDI2IEM2MS45OCw5NS4wMTUgNjEuOTg3LDk1LjAwMiA2MS45OTYsOTQuOTkxIEM2Mi4xMzIsOTQuODQ1IDYyLjI2Niw5NC42OTggNjIuMzk2LDk0LjU0OCBDNjIuNDQ5LDk0LjQ4NyA2Mi41MDEsOTQuNDI2IDYyLjU1Myw5NC4zNjUgQzYyLjU5NCw5NC4zMTYgNjIuNjM0LDk0LjI2NyA2Mi42NzUsOTQuMjE3IEM2Mi44MjEsOTQuMDQgNjIuOTYxLDkzLjg2MSA2My4xMDEsOTMuNjc4IEM2My4yNzksOTMuNDQ0IDYzLjQ1Niw5My4xOTkgNjMuNjIyLDkyLjk1NiBDNjMuOTU2LDkyLjQ3MSA2NC4yNjcsOTEuOTcgNjQuNTUzLDkxLjQ1MiBDNjQuNjYxLDkxLjI1NyA2NC43NTcsOTEuMDYgNjQuODU3LDkwLjg2MSBDNjQuODksOTAuNzk2IDY0LjkzLDkwLjczNSA2NC45NjIsOTAuNjcgQzY0Ljk4LDkwLjYzMyA2NC45OTYsOTAuNTk0IDY1LjAxNCw5MC41NTYgQzY1LjEyNSw5MC4zMjQgNjUuMjM0LDkwLjA5IDY1LjMzNiw4OS44NTIgQzY1LjM0OSw4OS44MiA2NS4zNjUsODkuNzg5IDY1LjM3OSw4OS43NTYgQzY1LjQ4LDg5LjUxNyA2NS41NzUsODkuMjcxIDY1LjY2Niw4OS4wMjYgQzY1LjY3OCw4OC45OTQgNjUuNjg5LDg4Ljk2MiA2NS43MDEsODguOTMgQzY1Ljc5Miw4OC42NzkgNjUuODgxLDg4LjQzIDY1Ljk2Miw4OC4xNzQgQzY1Ljk3LDg4LjE0OCA2NS45OCw4OC4xMjIgNjUuOTg4LDg4LjA5NiBDNjYuMDY5LDg3LjgzMiA2Ni4xNDQsODcuNTY0IDY2LjIxNCw4Ny4yOTYgQzY2LjIxOSw4Ny4yNzUgNjYuMjI2LDg3LjI1NSA2Ni4yMzEsODcuMjM1IEM2Ni4zMDEsODYuOTYyIDY2LjM2NSw4Ni42ODYgNjYuNDIzLDg2LjQwOSBDNjYuNDI2LDg2LjM5MSA2Ni40MjgsODYuMzc0IDY2LjQzMSw4Ni4zNTYgQzY2LjQ0NSw4Ni4yOTEgNjYuNDUzLDg2LjIyMyA2Ni40NjYsODYuMTU2IEM2Ni41MTEsODUuOTI1IDY2LjU1Miw4NS42OTUgNjYuNTg4LDg1LjQ2MSBDNjYuNjMyLDg1LjE2OSA2Ni42NzEsODQuODc4IDY2LjcwMSw4NC41ODMgQzY2LjcwMSw4NC41NzQgNjYuNzAxLDg0LjU2NSA2Ni43MDEsODQuNTU2IEM2Ni43MzEsODQuMjU4IDY2Ljc1NSw4My45NTUgNjYuNzcsODMuNjUyIEM2Ni43Nyw4My42NDYgNjYuNzcsODMuNjQxIDY2Ljc3LDgzLjYzNSBDNjYuNzg2LDgzLjMyNiA2Ni43OTcsODMuMDE3IDY2Ljc5Nyw4Mi43MDQgQzY2Ljc5Nyw3Mi42OSA1OC43MjMsNjQuNjE3IDQ4LjcxLDY0LjYxNyB6Ii8+CiAgICAgICAgPHBhdGggZD0iTTYyLjkzNiw5OS44MDkgQzU5LjA3NCwxMDMuMDI4IDU0LjExNSwxMDQuOTY1IDQ4LjcxLDEwNC45NjUgQzQ3LjEwMSwxMDQuOTY1IDQ1LjUzNSwxMDQuNzg3IDQ0LjAyMywxMDQuNDYxIEw0Mi40NjYsMTA2LjM1NyBDMzkuMDA3LDEwNS40MyAzNS44NTUsMTAzLjc4MSAzMy4xNzksMTAxLjU3NCBMMjguOTk2LDEwNS43NjUgTDI5LjUxLDEwOC44NjEgTDEzLjk1MywxMjQuNDI2IEwxNS40NTcsMTI1IEwzMC4wNjYsMTE5LjQzNSBMNDQuNjc1LDEyNSBMNTkuMjgzLDExOS40MzUgTDY0Ljg0OSwxMDQuODI2IEw2Mi45MzYsOTkuODA5IHoiLz4KICAgIDwvZz4KPC9zdmc+'/></a>", | ||||
|     "render": "<a href='https://openstreetmap.org/{id}' target='_blank'><img src='./assets/svg/osm-logo-us.svg'/></a>", | ||||
|     "mappings":[{ | ||||
|       "if": "id~=-", | ||||
|       "then": "<span class='alert'>Uploading...</alert>" | ||||
|  |  | |||
|  | @ -1,55 +1,17 @@ | |||
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||||
| <!-- Created with Inkscape (http://www.inkscape.org/) --> | ||||
| 
 | ||||
| <svg | ||||
|    xmlns:dc="http://purl.org/dc/elements/1.1/" | ||||
|    xmlns:cc="http://creativecommons.org/ns#" | ||||
|    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | ||||
|    xmlns:svg="http://www.w3.org/2000/svg" | ||||
|    xmlns="http://www.w3.org/2000/svg" | ||||
|    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | ||||
|    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | ||||
|    width="100" | ||||
|    height="100" | ||||
|    viewBox="0 0 26.458333 26.458334" | ||||
|    version="1.1" | ||||
|    id="svg8" | ||||
|    inkscape:version="0.92.4 (5da689c313, 2019-01-14)" | ||||
|    sodipodi:docname="crosshair.svg"> | ||||
|    version="1.1" | ||||
|    viewBox="0 0 26.458333 26.458334" | ||||
|    height="100" | ||||
|    width="100"> | ||||
|   <defs | ||||
|      id="defs2" /> | ||||
|   <sodipodi:namedview | ||||
|      id="base" | ||||
|      pagecolor="#ffffff" | ||||
|      bordercolor="#666666" | ||||
|      borderopacity="1.0" | ||||
|      inkscape:pageopacity="0.0" | ||||
|      inkscape:pageshadow="2" | ||||
|      inkscape:zoom="2" | ||||
|      inkscape:cx="12.898245" | ||||
|      inkscape:cy="23.072799" | ||||
|      inkscape:document-units="px" | ||||
|      inkscape:current-layer="layer1" | ||||
|      showgrid="false" | ||||
|      units="px" | ||||
|      showguides="true" | ||||
|      inkscape:guide-bbox="true" | ||||
|      inkscape:window-width="1920" | ||||
|      inkscape:window-height="1001" | ||||
|      inkscape:window-x="0" | ||||
|      inkscape:window-y="0" | ||||
|      inkscape:window-maximized="1"> | ||||
|     <sodipodi:guide | ||||
|        position="13.229167,23.859748" | ||||
|        orientation="1,0" | ||||
|        id="guide815" | ||||
|        inkscape:locked="false" /> | ||||
|     <sodipodi:guide | ||||
|        position="14.944824,13.229167" | ||||
|        orientation="0,1" | ||||
|        id="guide817" | ||||
|        inkscape:locked="false" /> | ||||
|   </sodipodi:namedview> | ||||
|   <metadata | ||||
|      id="metadata5"> | ||||
|     <rdf:RDF> | ||||
|  | @ -58,46 +20,40 @@ | |||
|         <dc:format>image/svg+xml</dc:format> | ||||
|         <dc:type | ||||
|            rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | ||||
|         <dc:title /> | ||||
|         <dc:title></dc:title> | ||||
|       </cc:Work> | ||||
|     </rdf:RDF> | ||||
|   </metadata> | ||||
|   <g | ||||
|      inkscape:label="Layer 1" | ||||
|      inkscape:groupmode="layer" | ||||
|      id="layer1" | ||||
|      transform="translate(0,-270.54165)"> | ||||
|      transform="translate(0,-270.54165)" | ||||
|      id="layer1"> | ||||
|     <circle | ||||
|        style="fill:none;fill-opacity:1;stroke:#555555;stroke-width:2.64583335;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.98823529" | ||||
|        id="path815" | ||||
|        r="8.8715391" | ||||
|        cy="283.77081" | ||||
|        cx="13.16302" | ||||
|        cy="283.77081" | ||||
|        r="8.8715391" /> | ||||
|        id="path815" | ||||
|        style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:2.64583335;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.98823529" /> | ||||
|     <path | ||||
|        style="fill:none;stroke:#555555;stroke-width:2.09723878;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.98823529" | ||||
|        d="M 3.2841366,283.77082 H 1.0418969" | ||||
|        id="path817" | ||||
|        inkscape:connector-curvature="0" /> | ||||
|        d="M 3.2841366,283.77082 H 1.0418969" | ||||
|        style="fill:none;stroke:#000000;stroke-width:2.09723878;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.98823529" /> | ||||
|     <path | ||||
|        style="fill:none;stroke:#555555;stroke-width:2.11666679;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.98823529" | ||||
|        d="M 25.405696,283.77082 H 23.286471" | ||||
|        id="path817-3" | ||||
|        inkscape:connector-curvature="0" /> | ||||
|        d="M 25.405696,283.77082 H 23.286471" | ||||
|        style="fill:none;stroke:#000000;stroke-width:2.11666679;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.98823529" /> | ||||
|     <path | ||||
|        style="fill:none;stroke:#555555;stroke-width:2.11666679;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.98823529" | ||||
|        d="m 13.229167,295.9489 v -2.11763" | ||||
|        id="path817-3-6" | ||||
|        inkscape:connector-curvature="0" /> | ||||
|        d="m 13.229167,295.9489 v -2.11763" | ||||
|        style="fill:none;stroke:#000000;stroke-width:2.11666679;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.98823529" /> | ||||
|     <path | ||||
|        style="fill:none;stroke:#555555;stroke-width:2.11666668;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.98823529" | ||||
|        d="m 13.229167,275.05759 v -3.44507" | ||||
|        id="path817-3-6-7" | ||||
|        inkscape:connector-curvature="0" /> | ||||
|        d="m 13.229167,275.05759 v -3.44507" | ||||
|        style="fill:none;stroke:#000000;stroke-width:2.11666668;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.98823529" /> | ||||
|     <circle | ||||
|        style="fill:#555555;fill-opacity:0.99004978;stroke:none;stroke-width:2.81138086;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" | ||||
|        id="path866" | ||||
|        cx="13.229166" | ||||
|        r="3.4070117" | ||||
|        cy="283.77081" | ||||
|        r="3.4070117" /> | ||||
|        cx="13.229166" | ||||
|        id="path866" | ||||
|        style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.81138086;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /> | ||||
|   </g> | ||||
| </svg> | ||||
|  |  | |||
| Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 2.4 KiB | 
|  | @ -6,11 +6,48 @@ | |||
|    xmlns:svg="http://www.w3.org/2000/svg" | ||||
|    xmlns="http://www.w3.org/2000/svg" | ||||
|    xmlns:xlink="http://www.w3.org/1999/xlink" | ||||
|    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | ||||
|    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | ||||
|    width="100" | ||||
|    height="100" | ||||
|    viewBox="0 0 100 100" | ||||
|    version="1.1" | ||||
|    id="svg8"> | ||||
|    id="svg8" | ||||
|    sodipodi:docname="direction_gradient.svg" | ||||
|    inkscape:version="0.92.4 (5da689c313, 2019-01-14)"> | ||||
|   <sodipodi:namedview | ||||
|      pagecolor="#ffffff" | ||||
|      bordercolor="#666666" | ||||
|      borderopacity="1" | ||||
|      objecttolerance="10" | ||||
|      gridtolerance="10" | ||||
|      guidetolerance="10" | ||||
|      inkscape:pageopacity="0" | ||||
|      inkscape:pageshadow="2" | ||||
|      inkscape:window-width="1920" | ||||
|      inkscape:window-height="1001" | ||||
|      id="namedview10" | ||||
|      showgrid="false" | ||||
|      showguides="true" | ||||
|      inkscape:guide-bbox="true" | ||||
|      inkscape:zoom="9.44" | ||||
|      inkscape:cx="69.372244" | ||||
|      inkscape:cy="85.073455" | ||||
|      inkscape:window-x="0" | ||||
|      inkscape:window-y="0" | ||||
|      inkscape:window-maximized="1" | ||||
|      inkscape:current-layer="svg8"> | ||||
|     <sodipodi:guide | ||||
|        position="50,117.79661" | ||||
|        orientation="1,0" | ||||
|        id="guide819" | ||||
|        inkscape:locked="false" /> | ||||
|     <sodipodi:guide | ||||
|        position="57.627119,50" | ||||
|        orientation="0,1" | ||||
|        id="guide821" | ||||
|        inkscape:locked="false" /> | ||||
|   </sodipodi:namedview> | ||||
|   <metadata | ||||
|      id="metadata8"> | ||||
|     <rdf:RDF> | ||||
|  | @ -19,7 +56,7 @@ | |||
|         <dc:format>image/svg+xml</dc:format> | ||||
|         <dc:type | ||||
|            rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | ||||
|         <dc:title></dc:title> | ||||
|         <dc:title /> | ||||
|       </cc:Work> | ||||
|     </rdf:RDF> | ||||
|   </metadata> | ||||
|  | @ -38,7 +75,7 @@ | |||
|     </linearGradient> | ||||
|     <radialGradient | ||||
|        gradientUnits="userSpaceOnUse" | ||||
|        gradientTransform="matrix(1.5439431,-0.01852438,0.02075364,1.7297431,-28.198837,-42.329969)" | ||||
|        gradientTransform="matrix(1.5439431,-0.01852438,0.02075364,1.7297431,-27.986574,-42.187244)" | ||||
|        r="28.883806" | ||||
|        fy="53.828533" | ||||
|        fx="49.787739" | ||||
|  | @ -49,6 +86,7 @@ | |||
|   </defs> | ||||
|   <path | ||||
|      style="fill:url(#radialGradient828);fill-opacity:1;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" | ||||
|      d="M 49.787737,49.857275 20.830626,9.2566092 C 35.979158,-2.144159 60.514289,-3.8195259 78.598237,9.0063685 Z" | ||||
|      id="path821" /> | ||||
|      d="M 50,50 21.042889,9.3993342 C 36.191421,-2.001434 60.726552,-3.6768009 78.8105,9.1490935 Z" | ||||
|      id="path821" | ||||
|      inkscape:connector-curvature="0" /> | ||||
| </svg> | ||||
|  |  | |||
| Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 2.8 KiB | 
|  | @ -7,25 +7,12 @@ | |||
|    xmlns="http://www.w3.org/2000/svg" | ||||
|    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | ||||
|    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | ||||
|    width="300" | ||||
|    height="300" | ||||
|    version="1.1" | ||||
|    id="svg6" | ||||
|    version="1.1" | ||||
|    height="210" | ||||
|    width="600" | ||||
|    sodipodi:docname="cam.svg" | ||||
|    inkscape:version="0.92.4 (5da689c313, 2019-01-14)"> | ||||
|   <metadata | ||||
|      id="metadata12"> | ||||
|     <rdf:RDF> | ||||
|       <cc:Work | ||||
|          rdf:about=""> | ||||
|         <dc:format>image/svg+xml</dc:format> | ||||
|         <dc:type | ||||
|            rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | ||||
|       </cc:Work> | ||||
|     </rdf:RDF> | ||||
|   </metadata> | ||||
|   <defs | ||||
|      id="defs10" /> | ||||
|   <sodipodi:namedview | ||||
|      pagecolor="#ffffff" | ||||
|      bordercolor="#666666" | ||||
|  | @ -37,19 +24,40 @@ | |||
|      inkscape:pageshadow="2" | ||||
|      inkscape:window-width="1920" | ||||
|      inkscape:window-height="1001" | ||||
|      id="namedview8" | ||||
|      id="namedview6" | ||||
|      showgrid="false" | ||||
|      inkscape:zoom="4.4500586" | ||||
|      inkscape:cx="52.470633" | ||||
|      inkscape:cy="172.70315" | ||||
|      showguides="true" | ||||
|      inkscape:guide-bbox="true" | ||||
|      inkscape:zoom="0.55625733" | ||||
|      inkscape:cx="680.78346" | ||||
|      inkscape:cy="482.50413" | ||||
|      inkscape:window-x="0" | ||||
|      inkscape:window-y="0" | ||||
|      inkscape:window-maximized="1" | ||||
|      inkscape:current-layer="svg6" /> | ||||
|      inkscape:current-layer="svg6"> | ||||
|     <sodipodi:guide | ||||
|        position="192.35701,251.68207" | ||||
|        orientation="1,0" | ||||
|        id="guide816" | ||||
|        inkscape:locked="false" /> | ||||
|   </sodipodi:namedview> | ||||
|   <metadata | ||||
|      id="metadata12"> | ||||
|     <rdf:RDF> | ||||
|       <cc:Work | ||||
|          rdf:about=""> | ||||
|         <dc:format>image/svg+xml</dc:format> | ||||
|         <dc:type | ||||
|            rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | ||||
|         <dc:title></dc:title> | ||||
|       </cc:Work> | ||||
|     </rdf:RDF> | ||||
|   </metadata> | ||||
|   <defs | ||||
|      id="defs10" /> | ||||
|   <path | ||||
|      d="m 19.550568,165.17983 25.64048,-7.77529 37.583972,53 -44.404278,15.19092 z M 27.853974,129.44943 251,66 c 5.83831,-1.483989 13.98665,-0.576204 16.78652,10.077906 0,0 13.16723,59.102364 19.90559,86.841004 2.37442,9.77433 -0.21672,13.95095 -6.93927,15.75524 L 103,230 Z" | ||||
|      style="fill:#000000;stroke:#ffffff;stroke-width:17.40477371;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" | ||||
|      id="path4" | ||||
|      inkscape:connector-curvature="0" | ||||
|      style="fill:#000000;stroke:#ffffff;stroke-width:15;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" | ||||
|      sodipodi:nodetypes="cccccccssccc" /> | ||||
|      d="m 275.84577,72.939087 31.07239,-1.014243 26.20685,70.688356 -54.3295,3.69054 z m 20.0366,-37.552344 269.15255,-4.09941 c 6.98913,0.09009 15.84901,3.554569 15.7875,16.336335 0,0 -2.99159,70.195112 -3.76963,103.307682 -0.27414,11.66795 -4.43254,15.57088 -12.5089,15.57422 l -214.63586,4.14367 z" | ||||
|      inkscape:connector-curvature="0" /> | ||||
| </svg> | ||||
| Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 2.1 KiB | 
							
								
								
									
										68
									
								
								assets/themes/surveillance_cameras/cam_right.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,68 @@ | |||
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||||
| <svg | ||||
|    xmlns:dc="http://purl.org/dc/elements/1.1/" | ||||
|    xmlns:cc="http://creativecommons.org/ns#" | ||||
|    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | ||||
|    xmlns:svg="http://www.w3.org/2000/svg" | ||||
|    xmlns="http://www.w3.org/2000/svg" | ||||
|    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | ||||
|    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | ||||
|    id="svg6" | ||||
|    version="1.1" | ||||
|    height="210" | ||||
|    width="600" | ||||
|    sodipodi:docname="cam_right.svg" | ||||
|    inkscape:version="0.92.4 (5da689c313, 2019-01-14)"> | ||||
|   <sodipodi:namedview | ||||
|      pagecolor="#ffffff" | ||||
|      bordercolor="#666666" | ||||
|      borderopacity="1" | ||||
|      objecttolerance="10" | ||||
|      gridtolerance="10" | ||||
|      guidetolerance="10" | ||||
|      inkscape:pageopacity="0" | ||||
|      inkscape:pageshadow="2" | ||||
|      inkscape:window-width="1920" | ||||
|      inkscape:window-height="1001" | ||||
|      id="namedview6" | ||||
|      showgrid="false" | ||||
|      showguides="true" | ||||
|      inkscape:guide-bbox="true" | ||||
|      inkscape:zoom="1.5733333" | ||||
|      inkscape:cx="159.31" | ||||
|      inkscape:cy="209.94521" | ||||
|      inkscape:window-x="0" | ||||
|      inkscape:window-y="0" | ||||
|      inkscape:window-maximized="1" | ||||
|      inkscape:current-layer="svg6"> | ||||
|     <sodipodi:guide | ||||
|        position="490.78006,256.1764" | ||||
|        orientation="1,0" | ||||
|        id="guide816" | ||||
|        inkscape:locked="false" /> | ||||
|     <sodipodi:guide | ||||
|        position="-154.49235,105.0548" | ||||
|        orientation="0,1" | ||||
|        id="guide817" | ||||
|        inkscape:locked="false" /> | ||||
|   </sodipodi:namedview> | ||||
|   <metadata | ||||
|      id="metadata12"> | ||||
|     <rdf:RDF> | ||||
|       <cc:Work | ||||
|          rdf:about=""> | ||||
|         <dc:format>image/svg+xml</dc:format> | ||||
|         <dc:type | ||||
|            rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | ||||
|         <dc:title /> | ||||
|       </cc:Work> | ||||
|     </rdf:RDF> | ||||
|   </metadata> | ||||
|   <defs | ||||
|      id="defs10" /> | ||||
|   <path | ||||
|      style="fill:#000000;stroke:#ffffff;stroke-width:14.99999809;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" | ||||
|      id="path4" | ||||
|      d="m 320.67971,63.887724 -31.22595,-0.646766 -25.27602,71.641802 54.62643,3.06524 z M 299.99723,26.240468 29.583962,25.366424 c -7.018953,0.175611 -15.866995,3.778632 -15.615761,16.674621 0,0 4.045287,70.790225 5.317545,104.191185 0.448302,11.76958 4.683081,15.65722 12.795492,15.56269 l 215.654182,1.57947 z" | ||||
|      inkscape:connector-curvature="0" /> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 2.3 KiB | 
							
								
								
									
										78
									
								
								assets/themes/surveillance_cameras/direction_360.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,78 @@ | |||
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||||
| <svg | ||||
|    xmlns:dc="http://purl.org/dc/elements/1.1/" | ||||
|    xmlns:cc="http://creativecommons.org/ns#" | ||||
|    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | ||||
|    xmlns:svg="http://www.w3.org/2000/svg" | ||||
|    xmlns="http://www.w3.org/2000/svg" | ||||
|    xmlns:xlink="http://www.w3.org/1999/xlink" | ||||
|    id="svg8" | ||||
|    version="1.1" | ||||
|    viewBox="0 0 100 100" | ||||
|    height="100" | ||||
|    width="100"> | ||||
|   <metadata | ||||
|      id="metadata8"> | ||||
|     <rdf:RDF> | ||||
|       <cc:Work | ||||
|          rdf:about=""> | ||||
|         <dc:format>image/svg+xml</dc:format> | ||||
|         <dc:type | ||||
|            rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | ||||
|         <dc:title></dc:title> | ||||
|       </cc:Work> | ||||
|     </rdf:RDF> | ||||
|   </metadata> | ||||
|   <defs | ||||
|      id="defs6"> | ||||
|     <linearGradient | ||||
|        id="linearGradient823"> | ||||
|       <stop | ||||
|          id="stop819" | ||||
|          offset="0" | ||||
|          style="stop-color:#55ff55;stop-opacity:1;" /> | ||||
|       <stop | ||||
|          id="stop821" | ||||
|          offset="1" | ||||
|          style="stop-color:#55ff55;stop-opacity:0;" /> | ||||
|     </linearGradient> | ||||
|     <linearGradient | ||||
|        id="linearGradient820"> | ||||
|       <stop | ||||
|          style="stop-color:#000000;stop-opacity:1;" | ||||
|          offset="0" | ||||
|          id="innercolor" /> | ||||
|       <stop | ||||
|          style="stop-color:#000000;stop-opacity:0" | ||||
|          offset="1" | ||||
|          id="outercolor" /> | ||||
|     </linearGradient> | ||||
|     <radialGradient | ||||
|        xlink:href="#linearGradient820" | ||||
|        id="radialGradient828" | ||||
|        cx="49.787739" | ||||
|        cy="53.828533" | ||||
|        fx="49.787739" | ||||
|        fy="53.828533" | ||||
|        r="28.883806" | ||||
|        gradientTransform="matrix(1.5439431,-0.01852438,0.02075364,1.7297431,-28.198837,-42.329969)" | ||||
|        gradientUnits="userSpaceOnUse" /> | ||||
|     <radialGradient | ||||
|        gradientUnits="userSpaceOnUse" | ||||
|        gradientTransform="matrix(1,0,0,0.99367722,0,0.31814846)" | ||||
|        r="50.261864" | ||||
|        fy="50.317799" | ||||
|        fx="50.211864" | ||||
|        cy="50.317799" | ||||
|        cx="50.211864" | ||||
|        id="radialGradient825" | ||||
|        xlink:href="#linearGradient823" /> | ||||
|   </defs> | ||||
|   <ellipse | ||||
|      ry="49.89407" | ||||
|      rx="50.211864" | ||||
|      cy="50.317799" | ||||
|      cx="50.211864" | ||||
|      id="path817" | ||||
|      style="fill:url(#radialGradient825);fill-opacity:1;stroke:#0f0000;stroke-width:0.1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.98823529" /> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 2.3 KiB | 
|  | @ -7,8 +7,8 @@ | |||
|    xmlns="http://www.w3.org/2000/svg" | ||||
|    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | ||||
|    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | ||||
|    width="300" | ||||
|    height="300" | ||||
|    width="100" | ||||
|    height="100" | ||||
|    version="1.1" | ||||
|    id="svg6" | ||||
|    sodipodi:docname="dome.svg" | ||||
|  | @ -21,6 +21,7 @@ | |||
|         <dc:format>image/svg+xml</dc:format> | ||||
|         <dc:type | ||||
|            rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | ||||
|         <dc:title></dc:title> | ||||
|       </cc:Work> | ||||
|     </rdf:RDF> | ||||
|   </metadata> | ||||
|  | @ -39,29 +40,42 @@ | |||
|      inkscape:window-height="1001" | ||||
|      id="namedview8" | ||||
|      showgrid="false" | ||||
|      inkscape:zoom="1.5733334" | ||||
|      inkscape:cx="-20.982269" | ||||
|      inkscape:cy="188.2981" | ||||
|      inkscape:zoom="11.313708" | ||||
|      inkscape:cx="52.167677" | ||||
|      inkscape:cy="58.44587" | ||||
|      inkscape:window-x="0" | ||||
|      inkscape:window-y="0" | ||||
|      inkscape:window-maximized="1" | ||||
|      inkscape:current-layer="svg6" /> | ||||
|      inkscape:current-layer="svg6" | ||||
|      showguides="true" | ||||
|      inkscape:guide-bbox="true"> | ||||
|     <sodipodi:guide | ||||
|        position="50.25,94.25" | ||||
|        orientation="1,0" | ||||
|        id="guide819" | ||||
|        inkscape:locked="false" /> | ||||
|     <sodipodi:guide | ||||
|        position="-9.9375,50" | ||||
|        orientation="0,1" | ||||
|        id="guide821" | ||||
|        inkscape:locked="false" /> | ||||
|   </sodipodi:namedview> | ||||
|   <path | ||||
|      style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" | ||||
|      d="M 34.759205,66.019166 H 262.93718 c 37.50409,0.111509 38.67272,47.104634 0,46.615174 H 34.759205 c -33.95631907,0.10039 -33.5365026,-46.998069 0,-46.615174 z" | ||||
|      style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:4.36474609;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" | ||||
|      d="m 11.439881,11.609325 h 76.341284 c 12.547715,0.03599 12.938695,15.219042 0,15.060906 H 11.439881 c -11.36071647,0.03243 -11.220258,-15.184617 0,-15.060906 z" | ||||
|      id="path818" | ||||
|      inkscape:connector-curvature="0" | ||||
|      sodipodi:nodetypes="ccccc" /> | ||||
|   <path | ||||
|      style="fill:#000000;fill-opacity:1;stroke:#ffffff;stroke-width:15;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" | ||||
|      d="M 49.750453,122.23061 249.19481,121.8402 C 248.9489,280.24546 49.140118,276.05333 49.750453,122.23061 Z" | ||||
|      style="fill:#000000;fill-opacity:1;stroke:#ffffff;stroke-width:4.36474609;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" | ||||
|      d="m 17.002109,29.775376 66.727903,0.0063 c -0.08223,51.179228 -66.932094,49.692075 -66.727903,-0.0063 z" | ||||
|      id="path823" | ||||
|      inkscape:connector-curvature="0" | ||||
|      sodipodi:nodetypes="ccc" /> | ||||
|   <g | ||||
|      id="g848" | ||||
|      transform="matrix(1.4204816,0,0,1.4204816,-61.951413,-40.990558)" | ||||
|      style="stroke-width:0.70398653"> | ||||
|      transform="matrix(0.47524917,0,0,0.45894372,-20.936465,-23.265017)" | ||||
|      style="stroke-width:1.86916912"> | ||||
|     <ellipse | ||||
|        ry="23.81991" | ||||
|        rx="24.494061" | ||||
|  |  | |||
| Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 3.3 KiB | 
|  | @ -40,7 +40,7 @@ | |||
|      id="namedview8" | ||||
|      showgrid="false" | ||||
|      inkscape:zoom="1.1125147" | ||||
|      inkscape:cx="-139.39327" | ||||
|      inkscape:cx="-288.60478" | ||||
|      inkscape:cy="92.396852" | ||||
|      inkscape:window-x="0" | ||||
|      inkscape:window-y="0" | ||||
|  | @ -49,11 +49,12 @@ | |||
|   <circle | ||||
|      style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" | ||||
|      id="path812" | ||||
|      cx="150.55981" | ||||
|      cx="-150.55981" | ||||
|      cy="149.44019" | ||||
|      r="148.76208" /> | ||||
|      r="148.76208" | ||||
|      transform="scale(-1,1)" /> | ||||
|   <path | ||||
|      d="m 40.704254,162.40461 21.579577,-6.49818 31.631474,44.29458 -37.37159,12.69576 z M 47.692578,132.54304 235.49705,79.515388 c 4.91364,-1.240239 11.77146,-0.481561 14.12789,8.422577 0,0 11.08182,49.394605 16.75297,72.577085 1.99836,8.16887 -0.18239,11.65946 -5.84024,13.16739 l -149.60059,42.89541 z" | ||||
|      d="m 260.41537,162.40461 -21.57957,-6.49818 -31.63148,44.29458 37.37159,12.69576 z M 253.42705,132.54304 65.622579,79.515388 c -4.91364,-1.240239 -11.77146,-0.481561 -14.12789,8.422577 0,0 -11.08182,49.394605 -16.75297,72.577085 -1.99836,8.16887 0.18239,11.65946 5.84024,13.16739 l 149.600591,42.89541 z" | ||||
|      id="path4" | ||||
|      inkscape:connector-curvature="0" | ||||
|      style="fill:#000000;stroke:#00ff00;stroke-width:15;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" | ||||
|  |  | |||
| Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB | 
|  | @ -28,353 +28,7 @@ | |||
|   "defaultBackgroundId": "Stadia.AlidadeSmoothDark", | ||||
|   "layers": [ | ||||
|     "direction", | ||||
|     { | ||||
|       "id": "cameras", | ||||
|       "name": { | ||||
|         "en": "Surveillance camera's", | ||||
|         "nl": "Bewakingscamera's" | ||||
|       }, | ||||
|       "minzoom": 12, | ||||
|       "overpassTags": { | ||||
|         "and": [ | ||||
|           "man_made=surveillance", | ||||
|           { | ||||
|             "or": [ | ||||
|               "surveillance:type=camera", | ||||
|               "surveillance:type=ALPR", | ||||
|               "surveillance:type=ANPR" | ||||
|             ] | ||||
|           } | ||||
|         ] | ||||
|       }, | ||||
|       "title": { | ||||
|         "render": { | ||||
|           "en": "Surveillance Camera", | ||||
|           "nl": "Bewakingscamera" | ||||
|         } | ||||
|       }, | ||||
|       "description": {}, | ||||
|       "tagRenderings": [ | ||||
|         "images", | ||||
|         { | ||||
|           "#": "Camera type: fixed; panning; dome", | ||||
|           "question": { | ||||
|             "en": "What kind of camera is this?", | ||||
|             "nl": "Wat voor soort camera is dit?" | ||||
|           }, | ||||
|           "mappings": [ | ||||
|             { | ||||
|               "if": { | ||||
|                 "and": [ | ||||
|                   "camera:type=fixed" | ||||
|                 ] | ||||
|               }, | ||||
|               "then": { | ||||
|                 "en": "A fixed (non-moving) camera", | ||||
|                 "nl": "Een vaste camera" | ||||
|               } | ||||
|             }, | ||||
|             { | ||||
|               "if": { | ||||
|                 "and": [ | ||||
|                   "camera:type=dome" | ||||
|                 ] | ||||
|               }, | ||||
|               "then": { | ||||
|                 "en": "A dome camera (which can turn)", | ||||
|                 "nl": "Een dome (bolvormige camera die kan draaien)" | ||||
|               } | ||||
|             }, | ||||
|             { | ||||
|               "if": { | ||||
|                 "and": [ | ||||
|                   "camera:type=panning" | ||||
|                 ] | ||||
|               }, | ||||
|               "then": { | ||||
|                 "en": "A panning camera", | ||||
|                 "nl": "Een camera die (met een motor) van links naar rechts kan draaien" | ||||
|               } | ||||
|             } | ||||
|           ] | ||||
|         }, | ||||
|         { | ||||
|           "#": "direction. We don't ask this for a dome on a pole or ceiling as it has a 360° view", | ||||
|           "question": { | ||||
|             "en": "In which geographical direction does this camera film?", | ||||
|             "nl": "Naar welke geografische richting filmt deze camera?" | ||||
|           }, | ||||
|           "render": "Films to {camera:direction}", | ||||
|           "condition": { | ||||
|             "not": { | ||||
|               "and": [ | ||||
|                 "camera:type=dome", | ||||
|                 { | ||||
|                   "or": [ | ||||
|                     "camera:mount=ceiling", | ||||
|                     "camera:mount=pole" | ||||
|                   ] | ||||
|                 } | ||||
|               ] | ||||
|             } | ||||
|           }, | ||||
|           "freeform": { | ||||
|             "key": "camera:direction", | ||||
|             "type": "direction" | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
|           "#": "Operator", | ||||
|           "freeform": { | ||||
|             "key": "operator" | ||||
|           }, | ||||
|           "question": { | ||||
|             "en": "Who operates this CCTV?", | ||||
|             "nl": "Wie beheert deze bewakingscamera?" | ||||
|           }, | ||||
|           "render": { | ||||
|             "en": "Operated by {operator}", | ||||
|             "nl": "Beheer door {operator}" | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
|           "#": "Surveillance type: public, outdoor, indoor", | ||||
|           "question": { | ||||
|             "en": "What kind of surveillance is this camera", | ||||
|             "nl": "Wat soort bewaking wordt hier uitgevoerd?" | ||||
|           }, | ||||
|           "mappings": [ | ||||
|             { | ||||
|               "if": { | ||||
|                 "and": [ | ||||
|                   "surveillance=public" | ||||
|                 ] | ||||
|               }, | ||||
|               "then": { | ||||
|                 "en": "A public area is surveilled, such as a street, a bridge, a square, a park, a train station, a public corridor or tunnel,...", | ||||
|                 "nl": "Bewaking van de publieke ruilmte, dus een straat, een brug, een park, een plein, een stationsgebouw, een publiek toegankelijke gang of tunnel..." | ||||
|               } | ||||
|             }, | ||||
|             { | ||||
|               "if": { | ||||
|                 "and": [ | ||||
|                   "surveillance=outdoor" | ||||
|                 ] | ||||
|               }, | ||||
|               "then": { | ||||
|                 "en": "An outdoor, yet private area is surveilled (e.g. a parking lot, a fuel station, courtyard, entrance, private driveway, ...)", | ||||
|                 "nl": "Een buitenruimte met privaat karakter (zoals een privé-oprit, een parking, tankstation, ...)" | ||||
|               } | ||||
|             }, | ||||
|             { | ||||
|               "if": { | ||||
|                 "and": [ | ||||
|                   "surveillance=indoor" | ||||
|                 ] | ||||
|               }, | ||||
|               "then": { | ||||
|                 "nl": "Een private binnenruimte wordt bewaakt, bv. een winkel, een parkeergarage, ...", | ||||
|                 "en": "A private indoor area is surveilled, e.g. a shop, a private underground parking, ..." | ||||
|               } | ||||
|             } | ||||
|           ] | ||||
|         }, | ||||
|         { | ||||
|           "#": "Indoor camera? This isn't clear for 'public'-cameras", | ||||
|           "question": { | ||||
|             "en": "Is the public space surveilled by this camera an indoor or outdoor space?", | ||||
|             "nl": "Bevindt de bewaakte publieke ruimte camera zich binnen of buiten?" | ||||
|           }, | ||||
|           "condition": { | ||||
|             "and": [ | ||||
|               "surveillance:type=public" | ||||
|             ] | ||||
|           }, | ||||
|           "mappings": [ | ||||
|             { | ||||
|               "if": "indoor=yes", | ||||
|               "then": { | ||||
|                 "en": "This camera is located indoors", | ||||
|                 "nl": "Deze camera bevindt zich binnen" | ||||
|               } | ||||
|             }, | ||||
|             { | ||||
|               "if": "indoor=no", | ||||
|               "then": { | ||||
|                 "en": "This camera is located outdoors", | ||||
|                 "nl": "Deze camera bevindt zich buiten" | ||||
|               } | ||||
|             }, | ||||
|             { | ||||
|               "if": "indoor=", | ||||
|               "then": { | ||||
|                 "en": "This camera is probably located outdoors", | ||||
|                 "nl": "Deze camera bevindt zich waarschijnlijk buiten" | ||||
|               }, | ||||
|               "hideInAnswer": true | ||||
|             } | ||||
|           ] | ||||
|         }, | ||||
|         { | ||||
|           "#": "Level", | ||||
|           "question": { | ||||
|             "en": "On which level is this camera located?", | ||||
|             "nl": "Op welke verdieping bevindt deze camera zich?" | ||||
|           }, | ||||
|           "freeform": { | ||||
|             "key": "level", | ||||
|             "type": "nat" | ||||
|           }, | ||||
|           "condition": { | ||||
|             "or": [ | ||||
|               "indoor=yes", | ||||
|               "surveillance:type=ye" | ||||
|             ] | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
|           "#": "Surveillance:zone", | ||||
|           "question": { | ||||
|             "en": "What exactly is surveilled here?", | ||||
|             "nl": "Wat wordt hier precies bewaakt?" | ||||
|           }, | ||||
|           "freeform": { | ||||
|             "key": "surveillance:zone" | ||||
|           }, | ||||
|           "render": { | ||||
|             "en": " Surveills a {surveillance:zone}", | ||||
|             "nl": "Bewaakt een {surveillance:zone}" | ||||
|           }, | ||||
|           "mappings": [ | ||||
|             { | ||||
|               "if": { | ||||
|                 "and": [ | ||||
|                   "surveillance:zone=parking" | ||||
|                 ] | ||||
|               }, | ||||
|               "then": { | ||||
|                 "en": "Surveills a parking", | ||||
|                 "nl": "Bewaakt een parking" | ||||
|               } | ||||
|             }, | ||||
|             { | ||||
|               "if": { | ||||
|                 "and": [ | ||||
|                   "surveillance:zone=traffic" | ||||
|                 ] | ||||
|               }, | ||||
|               "then": { | ||||
|                 "en": "Surveills the traffic", | ||||
|                 "nl": "Bewaakt het verkeer" | ||||
|               } | ||||
|             }, | ||||
|             { | ||||
|               "if": { | ||||
|                 "and": [ | ||||
|                   "surveillance:zone=entrance" | ||||
|                 ] | ||||
|               }, | ||||
|               "then": { | ||||
|                 "en": "Surveills an entrance", | ||||
|                 "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": [ | ||||
|                   "surveillance:zone=shop" | ||||
|                 ] | ||||
|               }, | ||||
|               "then": { | ||||
|                 "en": "Surveills a shop", | ||||
|                 "nl": "Bewaakt een winkel" | ||||
|               } | ||||
|             } | ||||
|           ] | ||||
|         }, | ||||
|         { | ||||
|           "#": "camera:mount", | ||||
|           "question": { | ||||
|             "en": "How is this camera placed?", | ||||
|             "nl": "Hoe is deze camera geplaatst?" | ||||
|           }, | ||||
|           "freeform": { | ||||
|             "key": "camera:mount" | ||||
|           }, | ||||
|           "mappings": [ | ||||
|             { | ||||
|               "if": "camera:mount=wall", | ||||
|               "then": { | ||||
|                 "en": "This camera is placed against a wall", | ||||
|                 "nl": "Deze camera hangt aan een muur" | ||||
|               } | ||||
|             }, | ||||
|             { | ||||
|               "if": "camera:mount=pole", | ||||
|               "then": { | ||||
|                 "en": "This camera is placed one a pole", | ||||
|                 "nl": "Deze camera staat op een paal" | ||||
|               } | ||||
|             }, | ||||
|             { | ||||
|               "if": "camera:mount=ceiling", | ||||
|               "then": { | ||||
|                 "en": "This camera is placed on the ceiling", | ||||
|                 "nl": "Deze camera hangt aan het plafond" | ||||
|               } | ||||
|             } | ||||
|           ] | ||||
|         } | ||||
|       ], | ||||
|       "hideUnderlayingFeaturesMinPercentage": 0, | ||||
|       "icon": { | ||||
|         "render": "./assets/themes/surveillance_cameras/cam.svg", | ||||
|         "mappings": [ | ||||
|           { | ||||
|             "if": "camera:type=dome", | ||||
|             "then": "./assets/themes/surveillance_cameras/dome.svg" | ||||
|           } | ||||
|         ] | ||||
|       }, | ||||
|       "width": { | ||||
|         "render": "8" | ||||
|       }, | ||||
|       "iconSize": { | ||||
|         "render": "50,50,center" | ||||
|       }, | ||||
|       "color": { | ||||
|         "render": "#f00" | ||||
|       }, | ||||
|       "presets": [ | ||||
|         { | ||||
|           "tags": ["man_made=surveillance","surveillance:type=camera"], | ||||
|           "title": "Surveillance camera" | ||||
|         } | ||||
|       ], | ||||
|       "wayHandling": 2 | ||||
|     } | ||||
|     "surveillance_cameras" | ||||
|   ], | ||||
|   "roamingRenderings": [] | ||||
| } | ||||
|  | @ -173,6 +173,10 @@ a { | |||
|     pointer-events: all; | ||||
| } | ||||
| 
 | ||||
| .unclickable { | ||||
|     pointer-events: none !important; | ||||
| } | ||||
| 
 | ||||
| .page-split { | ||||
|     display: flex; | ||||
|     height: 100%; | ||||
|  | @ -415,6 +419,7 @@ a { | |||
|     border: unset !important; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /****** ShareScreen *****/ | ||||
| 
 | ||||
| .literal-code { | ||||
|  |  | |||
|  | @ -21,7 +21,7 @@ | |||
|     "generate:layouts": "ts-node scripts/createLayouts.ts", | ||||
|     "optimize-images": "cd assets/generated/ &&  find -name '*.png' -exec optipng '{}' \\; && echo 'PNGs are optimized'", | ||||
|     "generate": "npm run generate:images && npm run generate:translations && npm run generate:layouts && npm run generate:editor-layer-index", | ||||
|     "build": "rm -rf dist/ npm run generate && parcel build --public-url ./ *.html assets/** assets/**/** assets/**/**/** vendor/* vendor/*/*", | ||||
|     "build": "rm -rf dist/ && npm run generate && parcel build --public-url ./ *.html assets/** assets/**/** assets/**/**/** vendor/* vendor/*/*", | ||||
|     "prepare-deploy": "npm run generate && npm run build && rm -rf .cache", | ||||
|     "deploy:staging": "npm run prepare-deploy && rm -rf /home/pietervdvn/git/pietervdvn.github.io/Staging/* && cp -r dist/* /home/pietervdvn/git/pietervdvn.github.io/Staging/ && cd /home/pietervdvn/git/pietervdvn.github.io/ && git add * && git commit -m 'New MapComplete Version' && git push && cd - && npm run clean", | ||||
|     "deploy:production": "npm run prepare-deploy && npm run optimize-images && rm -rf /home/pietervdvn/git/pietervdvn.github.io/MapComplete/* && cp -r dist/* /home/pietervdvn/git/pietervdvn.github.io/MapComplete/ && cd /home/pietervdvn/git/pietervdvn.github.io/ && git add * && git commit -m 'New MapComplete Version' && git push && cd - && npm run clean", | ||||
|  |  | |||
|  | @ -100,7 +100,7 @@ const alreadyWritten = [] | |||
| 
 | ||||
| function createIcon(iconPath: string, size: number, layout: LayoutConfig) { | ||||
|     let name = iconPath.split(".").slice(0, -1).join("."); | ||||
|     if (name.startsWith("../")) { | ||||
|     if (name.startsWith("./")) { | ||||
|         name = name.substr(2) | ||||
|     } | ||||
|     const newname = `${name}${size}.png` | ||||
|  | @ -151,7 +151,7 @@ function createManifest(layout: LayoutConfig, relativePath: string) { | |||
|         let path = layout.icon; | ||||
|         if (layout.icon.startsWith("<")) { | ||||
|             // THis is already the svg
 | ||||
|             path = "../assets/generated/" + layout.id + "_logo.svg" | ||||
|             path = "./assets/generated/" + layout.id + "_logo.svg" | ||||
|             writeFileSync(path, layout.icon) | ||||
|         } | ||||
|          | ||||
|  | @ -212,19 +212,19 @@ function createLandingPage(layout: LayoutConfig) { | |||
|     } | ||||
| 
 | ||||
|     const og = ` | ||||
|     <meta property="og:image" content="${ogImage ?? '../assets/svg/add.svg'}"> | ||||
|     <meta property="og:image" content="${ogImage ?? './assets/svg/add.svg'}"> | ||||
|     <meta property="og:title" content="${ogTitle}"> | ||||
|     <meta property="og:description" content="${ogDescr}">` | ||||
| 
 | ||||
|     let icon = layout.icon; | ||||
|     if (icon.startsWith("<?xml") || icon.startsWith("<svg")) { | ||||
|         // This already is an svg
 | ||||
|         icon = `../assets/generated/${layout.id}_icon.svg` | ||||
|         icon = `./assets/generated/${layout.id}_icon.svg` | ||||
|         writeFileSync(icon, layout.icon); | ||||
|     } | ||||
| 
 | ||||
|     let output = template | ||||
|         .replace(`../manifest.manifest`, `../${enc(layout.id)}.webmanifest`) | ||||
|         .replace(`./manifest.manifest`, `./${enc(layout.id)}.webmanifest`) | ||||
|         .replace("<!-- $$$OG-META -->", og) | ||||
|         .replace(/<title>.+?<\/title>/, `<title>${ogTitle}</title>`) | ||||
|         .replace("Loading MapComplete, hang on...", `Loading MapComplete theme <i>${ogTitle}</i>...`) | ||||
|  | @ -243,6 +243,11 @@ function createLandingPage(layout: LayoutConfig) { | |||
|     return output; | ||||
| } | ||||
| 
 | ||||
| const generatedDir = "./assets/generated"; | ||||
| if (! existsSync(generatedDir)) { | ||||
|     mkdirSync(generatedDir) | ||||
| } | ||||
| 
 | ||||
| const blacklist = ["", "test", ".", "..", "manifest", "index", "land", "preferences", "account", "openstreetmap"] | ||||
| const all = AllKnownLayouts.allSets; | ||||
| 
 | ||||
|  | @ -251,10 +256,7 @@ let wikiPage = "{|class=\"wikitable sortable\"\n" + | |||
|     "|-"; | ||||
| 
 | ||||
| 
 | ||||
| const generatedDir = "../assets/generated"; | ||||
| if (! existsSync(generatedDir)) { | ||||
|     mkdirSync(generatedDir) | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| for (const layoutName in all) { | ||||
|     if (blacklist.indexOf(layoutName.toLowerCase()) >= 0) { | ||||
|  |  | |||