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.
This commit is contained in:
Félix Baylac-Jacqué 2022-02-21 17:21:21 +01:00
parent 8fbad8b7b1
commit 6c8c3b138d
4 changed files with 60 additions and 17 deletions

View file

@ -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

View file

@ -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;
}

View file

@ -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: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
L.marker([51.5, -0.09]).addTo(map)
.bindPopup('A pretty CSS3 popup.<br> 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 `<li ${props}>${p.name} - ${p.postcode} ${p.city}, ${p.county}</li>`;
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;

View file

@ -27,6 +27,8 @@
autocapitalize="off" placeholder="Votre Adresse"/>
<ul class="autocomplete-result-list"/>
</div>
<button id="btn-load-elig-data" type="button">Récupérer les données d'éligibilité
pour cette zone</button>
<div id="map"/>
<script>
document.addEventListener("DOMContentLoaded", function(event) {