diff --git a/Layers/Bos.ts b/Layers/Bos.ts index 7e95e26..1398a94 100644 --- a/Layers/Bos.ts +++ b/Layers/Bos.ts @@ -26,7 +26,7 @@ export class Bos extends LayerDefinition { ]; this.maxAllowedOverlapPercentage = 10; - this.minzoom = 14; + this.minzoom = 13; this.questions = [Quests.nameOf(this.name), Quests.accessNatureReserve, Quests.operator]; this.style = this.generateStyleFunction(); this.elementsToShow = [ diff --git a/Layers/KnownSet.ts b/Layers/KnownSet.ts index 5deeb1e..70f1444 100644 --- a/Layers/KnownSet.ts +++ b/Layers/KnownSet.ts @@ -22,6 +22,7 @@ export class KnownSet { public startLat: number; static allSets : any = {}; + public welcomeTail: string; constructor( name: string, @@ -32,7 +33,8 @@ export class KnownSet { startLon: number, welcomeMessage: string, gettingStartedPlzLogin: string, - welcomeBackMessage: string + welcomeBackMessage: string, + welcomeTail: string = "" ) { this.title = title; this.startLon = startLon; @@ -43,6 +45,7 @@ export class KnownSet { this.welcomeMessage = welcomeMessage; this.gettingStartedPlzLogin = gettingStartedPlzLogin; this.welcomeBackMessage = welcomeBackMessage; + this.welcomeTail = welcomeTail; KnownSet.allSets[this.name] = this; } @@ -50,35 +53,49 @@ export class KnownSet { static groen = new KnownSet("groen", "Buurtnatuur", [new NatureReserves(), new Park(), new Bos()], - 14, - 51.2, - 3.2, - " \"logo\n" + - "\n" + - "

Buurtnatuur meten

\n" + - "\n" + - "\n" + - " Met deze tool willen we de natuur in Belgie beter inventariseren.
\n" + - " In welke natuurgebieden kan men terecht?
\n" + - " In welke bossen is het goed vertoeven?
\n" + - "

Natuur maakt immers gelukkig!

\n" + - "\n" + - "

De data komt van OpenStreetMap en je antwoorden worden daar ook opgeslaan. " + - "Omdat iedereen aan deze data bijdraagt, kunnen we geen garantie op correctheid bieden en heeft deze data geen juridische waarde

\n" + - "

Je privacy is belangrijk. We tellen wel hoeveel personen de website bezoeken. Om je niet dubbel te tellen wordt er één cookie bijgehouden waar geen persoonlijke informatie in staat. " + - "Als je inlogt, komt er een tweede cookie bij met je inloggegevens.

\n", - "

Wil je meehelpen?
\n" + - " Begin dan met een account\n" + + 10, + 50.8435, + 4.3688, +"\n" + + "
" + + "

Breng jouw buurtnatuur in kaart

" + + "Natuur maakt gelukkig. Aan de hand van deze website willen we de natuur dicht bij ons beter inventariseren. Met als doel meer mensen te laten genieten van toegankelijke natuur én te strijden voor meer natuur in onze buurten. \n" + + "" + + "

Samen kleuren we heel Vlaanderen en Brussel groen.

" + + "

Blijf op de hoogte van de resultaten van buurtnatuur.be: meld je aan voor e-mailupdates.

\n" + , + + "Begin meteen door een account te maken\n" + " te maken of\n" + - " in te loggen.

", - "Je bent aangemeld. Klik op een element om vragen te beantwoorden." + " in te loggen.
", + "", + + "

Tips

" + + + "" + + "" + + "

" + + "De oorspronkelijke data komt van OpenStreetMap en je antwoorden worden daar bewaard.
Omdat iedereen vrij kan meewerken aan dit project, kunnen we niet garanderen dat er geen fouten opduiken." + + "

" + + "Je privacy is belangrijk. We tellen wel hoeveel gebruikers deze website bezoeken. We plaatsen een cookie waar geen persoonlijke informatie in bewaard wordt. " + + "Als je inlogt, komt er een tweede cookie bij met je inloggegevens." + + "
" ); static openToiletMap = new KnownSet( "toilets", "Open Toilet Map", [new Toilets()], - 14, + 12, 51.2, 3.2, diff --git a/Logic/FilteredLayer.ts b/Logic/FilteredLayer.ts index 466bb57..3d66d03 100644 --- a/Logic/FilteredLayer.ts +++ b/Logic/FilteredLayer.ts @@ -171,7 +171,7 @@ export class FilteredLayer { let marker; if (style.icon === undefined) { marker = L.circle(latLng, { - radius: 50, + radius: 25, color: style.color }); diff --git a/Logic/Geocoding.ts b/Logic/Geocoding.ts index 75d620e..275ade1 100644 --- a/Logic/Geocoding.ts +++ b/Logic/Geocoding.ts @@ -1,17 +1,26 @@ import * as $ from "jquery" import {UIEventSource} from "../UI/UIEventSource"; +import {Basemap} from "./Basemap"; export class Geocoding { private static readonly host = "https://nominatim.openstreetmap.org/search?"; - static Search(query: string, currentLocation: UIEventSource<{ lat: number, lon: number }>, - handleResult: ((places: { display_name: string, lat: number, lon: number, boundingbox : number[] }[]) => void)) { + static Search(query: string, + basemap: Basemap, + handleResult: ((places: { display_name: string, lat: number, lon: number, boundingbox: number[] }[]) => void), + onFail: (() => void)) { + const b = basemap.map.getBounds(); + console.log(b); $.getJSON( - Geocoding.host + "format=json&accept-language=nl&q=" + query, + Geocoding.host + "format=json&limit=1&viewbox=" + + `${b.getEast()},${b.getNorth()},${b.getWest()},${b.getSouth()}`+ + "&accept-language=nl&q=" + query, function (data) { - handleResult(data); - }); + handleResult(data); + }).fail(() => { + onFail(); + }); } diff --git a/Logic/LayerUpdater.ts b/Logic/LayerUpdater.ts index b23e6b9..408d756 100644 --- a/Logic/LayerUpdater.ts +++ b/Logic/LayerUpdater.ts @@ -71,7 +71,8 @@ export class LayerUpdater { if (this.IsInBounds()) { return; } - if (this._map.map.getZoom() < this._minzoom) { + console.log("Zoom level: ",this._map.map.getZoom(), "Least needed zoom:", this._minzoom) + if (this._map.map.getZoom() < this._minzoom || this._map.Location.data.zoom < this._minzoom) { console.log("Not running query: zoom not sufficient"); return; } diff --git a/Logic/OsmConnection.ts b/Logic/OsmConnection.ts index ca10f13..1382ffd 100644 --- a/Logic/OsmConnection.ts +++ b/Logic/OsmConnection.ts @@ -79,7 +79,7 @@ export class OsmConnection { let data = self.userDetails.data; data.loggedIn = true; - console.log("Log incompleted, userinfo is ", userInfo); + console.log("Login completed, userinfo is ", userInfo); data.name = userInfo.getAttribute('display_name'); data.csCount = userInfo.getElementsByTagName("changesets")[0].getAttribute("count"); @@ -143,16 +143,22 @@ export class OsmConnection { }); } - public SetPreference(k:string, v:string){ + public SetPreference(k:string, v:string) { + + if (this.preferences.data[k] === v) { + return; + } + console.log("Updating preference", k, " to ", v); + this.preferences.data[k] = v; this.preferences.ping(); this.auth.xhr({ method: 'PUT', - path: '/api/0.6/user/preferences/'+k, - options: { header: { 'Content-Type': 'text/plain' } }, + path: '/api/0.6/user/preferences/' + k, + options: {header: {'Content-Type': 'text/plain'}}, content: v - },function(error, result) { - if(error){ + }, function (error, result) { + if (error) { console.log("Could not set preference", error); return; } diff --git a/Logic/Overpass.ts b/Logic/Overpass.ts index 30f3735..28efa0b 100644 --- a/Logic/Overpass.ts +++ b/Logic/Overpass.ts @@ -44,6 +44,11 @@ export class Overpass { console.log("Query failed") onFail(status); } + + if(json.elements === [] && json.remarks.indexOf("runtime error") > 0){ + console.log("Timeout or other runtime error"); + return; + } // @ts-ignore const geojson = OsmToGeoJson.default(json); continuation(geojson); diff --git a/UI/Base/CollapseButton.ts b/UI/Base/CollapseButton.ts new file mode 100644 index 0000000..752131e --- /dev/null +++ b/UI/Base/CollapseButton.ts @@ -0,0 +1,43 @@ +import {UIElement} from "../UIElement"; +import {UIEventSource} from "../UIEventSource"; + + +export class CollapseButton extends UIElement { + public isCollapsed = new UIEventSource(false); + + constructor(idToCollapse: string) { + super(undefined); + this.ListenTo(this.isCollapsed); + this.isCollapsed.addCallback((collapse) => { + const el = document.getElementById(idToCollapse); + if (el === undefined || el === null) { + console.log("Element not found") + return; + } + if (collapse) { + el.style.height = "3.5em"; + el.style.width = "15em"; + } else { + el.style.height = "auto"; + el.style.width = "auto"; + } + }); + + const self = this; + this.onClick(() => { + self.isCollapsed.setData(!self.isCollapsed.data); + }) + + } + + protected InnerRender(): string { + const up = './assets/arrow-up.svg'; + const down = './assets/arrow-down.svg'; + let arrow = up; + if (this.isCollapsed.data) { + arrow = down; + } + return `collapse`; + } + +} \ No newline at end of file diff --git a/UI/QuestionPicker.ts b/UI/QuestionPicker.ts index 16ecd57..0fb6252 100644 --- a/UI/QuestionPicker.ts +++ b/UI/QuestionPicker.ts @@ -36,7 +36,7 @@ export class QuestionPicker extends UIElement { if (highestQ === undefined) { - return ""; + return "Er zijn geen vragen meer!"; } return "
" + diff --git a/UI/SearchAndGo.ts b/UI/SearchAndGo.ts index d03e71a..a0d549a 100644 --- a/UI/SearchAndGo.ts +++ b/UI/SearchAndGo.ts @@ -1,16 +1,14 @@ import {UIElement} from "./UIElement"; import {TextField} from "./Base/TextField"; -import {VariableUiElement} from "./Base/VariableUIElement"; import {UIEventSource} from "./UIEventSource"; import {FixedUiElement} from "./Base/FixedUiElement"; import {Geocoding} from "../Logic/Geocoding"; import {Basemap} from "../Logic/Basemap"; -import {VerticalCombine} from "./Base/VerticalCombine"; export class SearchAndGo extends UIElement { - private _placeholder = new UIEventSource("Ga naar een locatie...") + private _placeholder = new UIEventSource("Zoek naar een locatie...") private _searchField = new TextField(this._placeholder); private _foundEntries = new UIEventSource([]); @@ -39,16 +37,24 @@ export class SearchAndGo extends UIElement { this._searchField.Clear(); this._placeholder.setData("Bezig met zoeken..."); const self = this; - Geocoding.Search(searchString, undefined, (result) => { + Geocoding.Search(searchString, this._map, (result) => { - const bb = result[0].boundingbox; - const bounds = [ - [bb[0], bb[2]], - [bb[1], bb[3]] - ] - self._map.map.fitBounds(bounds); - this._placeholder.setData("Ga naar locatie..."); - }); + if (result.length == 0) { + this._placeholder.setData("Niets gevonden"); + return; + } + + const bb = result[0].boundingbox; + const bounds = [ + [bb[0], bb[2]], + [bb[1], bb[3]] + ] + self._map.map.fitBounds(bounds); + this._placeholder.setData("Zoek naar een locatie..."); + }, + () => { + this._placeholder.setData("Niets gevonden: er ging iets mis"); + }); } diff --git a/UI/UIElement.ts b/UI/UIElement.ts index 2222dee..f1bb779 100644 --- a/UI/UIElement.ts +++ b/UI/UIElement.ts @@ -57,6 +57,7 @@ export abstract class UIElement { element.onclick = () => { self._onClick(); } + element.style.pointerEvents = "all"; element.style.cursor = "pointer"; } diff --git a/assets/arrow-down.svg b/assets/arrow-down.svg new file mode 100644 index 0000000..66a60a1 --- /dev/null +++ b/assets/arrow-down.svg @@ -0,0 +1,76 @@ + + + + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/assets/arrow-up.svg b/assets/arrow-up.svg new file mode 100644 index 0000000..14094c7 --- /dev/null +++ b/assets/arrow-up.svg @@ -0,0 +1,76 @@ + + + + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/index.css b/index.css index 4d4c5ca..6db4510 100644 --- a/index.css +++ b/index.css @@ -203,25 +203,46 @@ body { pointer-events: none; } - -#welcomeMessage { - display: inline-block; - max-width: 30em; - padding: 0; - padding-bottom: 1em; -} - #messagesboxmobilewrapper { display: none; /*Only shown on small screens*/ } +#welcomeMessage { + max-width: 35em; + padding: 0; + padding-top: 1em; + padding-bottom: 1em; +} + +#collapseButton { + position: absolute; + right: 0; + background-color: white; + margin: 1.5em; + border: 2px solid black; + border-radius: 2em; + padding: 0.5em; + display: inline-block; + width: 1em; + height: 1em; +} + +#collapseButton img { + width: 1em; + height: 1em; +} + + +#messagesbox-wrapper { +} + + #messagesbox { /*Only shown on big screens*/ padding: 2em; padding-top: 1em; padding-bottom: 1em; z-index: 5000; - transition: all 500ms linear; background-color: white; border-radius: 2em; pointer-events: all; @@ -229,6 +250,10 @@ body { @media only screen and (max-width: 600px) { + #messagesbox-wrapper { + display: none; + } + #messagesbox { display: none; } @@ -239,7 +264,7 @@ body { .leaflet-popup { /* Popups are hidden on mobile */ - display:none; + display: none; } #messagesboxmobilewrapper { @@ -525,6 +550,10 @@ body { /***************** Info box (box containing features and questions ******************/ +.leaflet-popup-content { + width: 25vw !important; +} + .featureinfobox { } diff --git a/index.html b/index.html index d50e48e..8e1ed55 100644 --- a/index.html +++ b/index.html @@ -30,7 +30,9 @@

-
+
+
+
diff --git a/index.ts b/index.ts index f10f468..bfae562 100644 --- a/index.ts +++ b/index.ts @@ -20,6 +20,7 @@ import {StrayClickHandler} from "./Logic/StrayClickHandler"; import {SimpleAddUI} from "./UI/SimpleAddUI"; import {VariableUiElement} from "./UI/Base/VariableUIElement"; import {SearchAndGo} from "./UI/SearchAndGo"; +import {CollapseButton} from "./UI/Base/CollapseButton"; let dryRun = false; @@ -129,6 +130,8 @@ const addButtons: { const flayers: FilteredLayer[] = [] +let minZoom = 0; + for (const layer of questSetToRender.layers) { const generateInfo = (tagsES) => { @@ -143,6 +146,8 @@ for (const layer of questSetToRender.layers) { ) }; + minZoom = Math.max(minZoom, layer.minzoom); + const flayer = layer.asLayer(bm, allElements, changes, osmConnection.userDetails, selectedElement, generateInfo); @@ -156,7 +161,7 @@ for (const layer of questSetToRender.layers) { flayers.push(flayer); } -const layerUpdater = new LayerUpdater(bm, questSetToRender.startzoom, flayers); +const layerUpdater = new LayerUpdater(bm, minZoom, flayers); // ------------------ Setup various UI elements ------------ @@ -207,6 +212,8 @@ new UserBadge(osmConnection.userDetails, pendingChanges, bm) new SearchAndGo(bm).AttachTo("searchbox"); +new CollapseButton("messagesbox") + .AttachTo("collapseButton"); var welcomeMessage = () => { return new VariableUiElement( osmConnection.userDetails.map((userdetails) => { @@ -215,7 +222,7 @@ var welcomeMessage = () => { login = questSetToRender.welcomeBackMessage; } return "
" + - questSetToRender.welcomeMessage + login + + questSetToRender.welcomeMessage + login + questSetToRender.welcomeTail+ "
"; }), function () { @@ -229,7 +236,7 @@ welcomeMessage().AttachTo("messagesbox"); var messageBox = new MessageBoxHandler(leftMessage, () => {selectedElement.setData(undefined)}); new CenterMessageBox( - questSetToRender.startzoom, + minZoom, centerMessage, osmConnection, locationControl,