From 6c8c3b138d2bf1c847481a4cdd822423f498a1b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Baylac-Jacqu=C3=A9?= Date: Mon, 21 Feb 2022 17:21:21 +0100 Subject: [PATCH] webapp: fetch eligibility data on backend We fetch the eligibility data from the backend for the area the user is currently viewing. We don't want to trigger the search when the user is zoomed out, it could be heavy on the backend CPU. Hence, we trigger the fetch after the user searched for his real address or reached a good-enough zoom level. The backend is currently returning a dummy answer. --- webapp/main.py | 14 ++++++++++- webapp/static/style.css | 10 +++++++- webapp/templates/app.js | 51 +++++++++++++++++++++++++++------------ webapp/templates/map.html | 2 ++ 4 files changed, 60 insertions(+), 17 deletions(-) diff --git a/webapp/main.py b/webapp/main.py index 56b0e6b..1d7efd5 100644 --- a/webapp/main.py +++ b/webapp/main.py @@ -1,7 +1,19 @@ -from flask import Flask, render_template +from flask import Flask, request, render_template app = Flask(__name__) @app.route("/", methods=['GET']) def getMap(): return render_template("map.html") + +@app.route("/eligdata", methods=['GET']) +def getEligData(): + args = request.args + if 'swx' in args and 'swy' in args and \ + 'nex' in args and 'ney' in args: + return { "buildings": [ + {"x": args['swx'], "y":args['swy'], "label": "dummy elig val" }, + {"x": args['nex'], "y":args['ney'], "label": "dummy elig val 2" } + ]} + else: + return "Missing coordinates", 400 diff --git a/webapp/static/style.css b/webapp/static/style.css index 306c72a..e9d8711 100644 --- a/webapp/static/style.css +++ b/webapp/static/style.css @@ -11,5 +11,13 @@ body { #search-addr-autocomplete { display: float; top: 0; - z-index: 1; + z-index: 2; +} + +#btn-load-elig-data { + top: 4em; + right: 0; + position: fixed; + z-index: 1; + padding: .5em; } diff --git a/webapp/templates/app.js b/webapp/templates/app.js index 7d8c98f..65a2160 100644 --- a/webapp/templates/app.js +++ b/webapp/templates/app.js @@ -1,16 +1,15 @@ +let markers = []; function initMap() { let map = L.map('map').setView([46.710, 3.669], 6); L.tileLayer('https://{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png', { attribution: '© OpenStreetMap contributors' }).addTo(map); - L.marker([51.5, -0.09]).addTo(map) - .bindPopup('A pretty CSS3 popup.
Easily customizable.') - .openPopup(); return map; } function initAddrSearch(map) { const autocompleteOptions = { + debounceTime: 300, search: async (query) => { if(query.length > 2) { const mapCenter = map.getCenter(); @@ -22,27 +21,49 @@ function initAddrSearch(map) { return []; } }, - onSubmit: (res) => { - const searchInput = document.getElementById('search-addr-autocomplete-input'); - const p = res.properties; - searchInput.value = `${p.name} - ${p.postcode} ${p.city}, ${p.county}`; - console.log("moving to"); - console.log(res.geometry.coordinates); - // We already filtered out the result not having strictly 2 coordinates at item display - map.setView([res.geometry.coordinates[1],res.geometry.coordinates[0]], 19) - }, - debounceTime: 300, renderResult: (res, props) => { const p = res.properties; if(p.name && p.postcode && p.city && p.county && res.geometry.coordinates && res.geometry.coordinates.length === 2) return `
  • ${p.name} - ${p.postcode} ${p.city}, ${p.county}
  • `; else return ""; + }, + onSubmit: async (res) => { + const searchInput = document.getElementById('search-addr-autocomplete-input'); + const p = res.properties; + searchInput.value = `${p.name} - ${p.postcode} ${p.city}, ${p.county}`; + // We already filtered out the result not having strictly 2 coordinates at item display + map.setView([res.geometry.coordinates[1],res.geometry.coordinates[0]], 19); + fetchEligData(map); } }; const autocompleteAddr = new Autocomplete("#search-addr-autocomplete", autocompleteOptions); return autocompleteAddr; } -let map = initMap(); -let addrSearch = initAddrSearch(map); +function updateEligData(map, eligData) { + markers.map(marker => map.removeLayer(marker)); + let buildings = eligData.buildings; + markers = buildings.map(building => { + const latlng = new L.latLng(building.y, building.x); + const marker = new L.marker(latlng).bindPopup(building.label); + map.addLayer(marker); + return marker + }); +} + +async function fetchEligData(map) { + const bounds = map.getBounds(); + const sw = bounds.getSouthWest(); + const ne = bounds.getNorthEast(); + const zoom = map.getZoom(); + const reqUri = encodeURI(`/eligdata?swx=${sw.lng}&swy=${sw.lat}&nex=${ne.lng}&ney=${ne.lat}`); + const source = await fetch(reqUri); + const eligData = await source.json(); + updateEligData(map, eligData); +} + +const map = initMap(); +const addrSearch = initAddrSearch(map); + +document.getElementById("btn-load-elig-data").onclick = fetchEligData; diff --git a/webapp/templates/map.html b/webapp/templates/map.html index 38871d3..0398e7f 100644 --- a/webapp/templates/map.html +++ b/webapp/templates/map.html @@ -27,6 +27,8 @@ autocapitalize="off" placeholder="Votre Adresse"/>