API par coord et amélioration UI

This commit is contained in:
Johan Le Baut 2023-01-11 15:35:12 +01:00
parent 275238fa39
commit f2b749e6d3
9 changed files with 304 additions and 133 deletions

35
webapp/coordinates.py Normal file
View File

@ -0,0 +1,35 @@
import math
from ipe_fetcher import AreaCoordinates
def check_coordinates_area(coordinates: AreaCoordinates, max_area) -> AreaCoordinates:
swx = coordinates.get('swx')
swy = coordinates.get('swy')
nex = coordinates.get('nex')
ney = coordinates.get('ney')
x_interval = abs(nex - swx)
y_interval = abs(ney - swy)
area = x_interval * y_interval
if area <= max_area:
# We are within max area, use original coordinates
return coordinates
else:
# Decrease area size to max area while keeping x y ratio
new_x_interval = x_interval * math.sqrt(max_area / (x_interval * y_interval))
new_y_interval = y_interval * math.sqrt(max_area / (x_interval * y_interval))
return AreaCoordinates(
swx=(swx + nex - new_x_interval) / 2,
swy=(swy + ney - new_y_interval) / 2,
nex=(swx + nex + new_x_interval) / 2,
ney=(swy + ney + new_y_interval) / 2,
)
def check_coordinates_args(args):
processed_args = {}
for k in ["swx", "swy", "nex", "ney"]:
if k not in args:
raise ValueError(f"{k} not in args")
processed_args[k] = float(args[k])
return processed_args

View File

@ -1,9 +1,8 @@
from flask import Flask, request from flask import Flask, request
from ipe_fetcher import Axione
from eligibility_api.elig_api_exceptions import ApiParamException from eligibility_api.elig_api_exceptions import ApiParamException
from coordinates import check_coordinates_args, check_coordinates_area
from ipe_fetcher.axione import AXIONE_MAX_AREA, Axione
class EligibilityApiRoutes: class EligibilityApiRoutes:
def __init__(self, flask_app: Flask, axione_ipe: Axione): def __init__(self, flask_app: Flask, axione_ipe: Axione):
@ -19,3 +18,13 @@ class EligibilityApiRoutes:
raise ApiParamException("You need to specify path parameter 'refimmeuble'") raise ApiParamException("You need to specify path parameter 'refimmeuble'")
return self.axione_ipe.get_eligibilite_per_id_immeuble(refimmeuble) return self.axione_ipe.get_eligibilite_per_id_immeuble(refimmeuble)
@self.flask_app.route("/eligibilite/axione/coord", methods=["GET"])
def get_axione_eligibility_per_coordinates():
args = request.args
try:
processed_args = check_coordinates_args(args)
coordinates = check_coordinates_area(processed_args, AXIONE_MAX_AREA)
return self.axione_ipe.getAreaBuildings(coordinates, {})
except ValueError:
raise ApiParamException("You need to specify path parameters 'swx' 'swy' 'nex' 'ney'")

View File

@ -16,13 +16,13 @@ class Arcep:
@staticmethod @staticmethod
def _get_etat_priority(etat_imm): def _get_etat_priority(etat_imm):
if etat_imm == ARCEP_ETAT_DEPLOYE: if etat_imm == ARCEP_ETAT_DEPLOYE:
return 0 return 10
elif etat_imm == "en cours de deploiement": elif etat_imm == "en cours de deploiement":
return 1 return 11
elif etat_imm != "abandonne": elif etat_imm != "abandonne":
return 3 return 30
else: else:
return 4 return 31
def getAreaBuildings( def getAreaBuildings(

View File

@ -15,6 +15,9 @@ AXIONE_ETAT_RACCORDABLE_DEMANDE = "RACCORDABLE DEMANDE"
AXIONE_REFIMM_TABLE_NAME = "refimm" AXIONE_REFIMM_TABLE_NAME = "refimm"
AXIONE_MAX_AREA = 0.08
class Axione: class Axione:
def __init__(self, db_axione_ipe_path: str, db_name: str): def __init__(self, db_axione_ipe_path: str, db_name: str):
self.db_axione_ipe_path = db_axione_ipe_path self.db_axione_ipe_path = db_axione_ipe_path
@ -44,9 +47,9 @@ class Axione:
elif etat_imm == AXIONE_ETAT_RAD_DEPLOIEMENT: elif etat_imm == AXIONE_ETAT_RAD_DEPLOIEMENT:
return 3 return 3
elif etat_imm != AXIONE_ETAT_ABANDONNE: elif etat_imm != AXIONE_ETAT_ABANDONNE:
return 4 return 20
else: else:
return 5 return 21
def getAreaBuildings( def getAreaBuildings(
@ -68,7 +71,7 @@ class Axione:
areaCoordinates, areaCoordinates,
) )
req_area = cur.fetchone()[0] req_area = cur.fetchone()[0]
if req_area <= 0.08: if req_area <= AXIONE_MAX_AREA:
cur.execute( cur.execute(
f""" f"""
SELECT SELECT
@ -105,12 +108,14 @@ class Axione:
date_commandable = "" date_commandable = ""
# C'est bien déployé, cependant ce n'est pas encore commandable (donc bientôt et on a la date) # C'est bien déployé, cependant ce n'est pas encore commandable (donc bientôt et on a la date)
# On laisse isEligible = True, côté JS il faut regarder le statut pour laj l'affichage en conséquence # On laisse isEligible = True, côté JS il faut regarder le statut pour laj l'affichage en conséquence
if isEligible and date_debut: if isEligible and date_debut:
try: try:
date_formatted = datetime.strptime(date_debut, '%Y%m%d').date() date_formatted = datetime.strptime(date_debut, '%Y%m%d').date()
if date_formatted >= datetime.now().date(): if date_formatted >= datetime.now().date():
etatImm = AXIONE_ETAT_DEPLOYE_NON_COMMANDABLE etatImm = AXIONE_ETAT_DEPLOYE_NON_COMMANDABLE
date_commandable = date_formatted.strftime('%d/%m/%Y') date_commandable = date_formatted.strftime('%d/%m/%Y')
except ValueError as err: except ValueError as err:
print("Error while mainpulating DateDebutAcceptationCmdAcces from Axione DB: ", err) print("Error while mainpulating DateDebutAcceptationCmdAcces from Axione DB: ", err)

View File

@ -1,20 +1,29 @@
import http.client as httplib import http.client as httplib
from ipe_fetcher.model import AreaCoordinates, Building, FAIEligibilityStatus from ipe_fetcher.model import AreaCoordinates, Building, FAIEligibilityStatus
import json import json
import time
import traceback
class Liazo: class Liazo:
def __init__(self): def __init__(self):
self.https_conn = httplib.HTTPSConnection("vador.fdn.fr") pass
def getAreaBuildings( def getAreaBuildings(
self, narrow_coordinates: AreaCoordinates(), existing_buildings: dict self, narrow_coordinates: AreaCoordinates(), existing_buildings: dict
) -> dict: ) -> dict:
nc=narrow_coordinates nc=narrow_coordinates
c = self.https_conn c = httplib.HTTPSConnection("vador.fdn.fr")
req = "/souscription/gps-batiments.cgi?etape=gps_batiments&lat1=%f&lat2=%f&lon1=%f&lon2=%f" % (nc['swy'],nc['ney'],nc['swx'],nc['nex']) api_params = "etape=gps_batiments&lat1=%f&lat2=%f&lon1=%f&lon2=%f" % (nc['swy'], nc['ney'], nc['swx'], nc['nex'])
req = f"/souscription/gps-batiments.cgi?{api_params}"
req = req.replace(" ", "%20") req = req.replace(" ", "%20")
c.request("GET", req) r = None
r = c.getresponse() try:
c.request("GET", req)
r = c.getresponse()
except Exception:
print(f"Could not call Liazo API to get Buildings, params: {api_params}")
print(traceback.format_exc())
return existing_buildings
if r.status < 200 or r.status >= 300: if r.status < 200 or r.status >= 300:
print("Erreur de serveur chez FDN.") print("Erreur de serveur chez FDN.")
return existing_buildings return existing_buildings
@ -27,7 +36,7 @@ class Liazo:
for building in v: for building in v:
fdnEligStatus = FAIEligibilityStatus( fdnEligStatus = FAIEligibilityStatus(
isEligible=True, isEligible=True,
ftthStatus="DEPLOYE", # Pas de status donc on dit que c'est ok mais on check avec l'arcep si axione KO cote front ftthStatus="DEPLOYE", # Pas de status donc on dit que c'est ok mais on check avec l'arcep si axione KO cote front
reasonNotEligible=None, reasonNotEligible=None,
) )
idImm=building.get('ref') idImm=building.get('ref')
@ -49,7 +58,7 @@ class Liazo:
commune="", commune="",
bat_info="", bat_info="",
found_in = ["liazo"], found_in = ["liazo"],
etat_imm_priority=1, etat_imm_priority=4,
fdnEligStatus=fdnEligStatus, fdnEligStatus=fdnEligStatus,
aquilenetEligStatus=FAIEligibilityStatus(isEligible=False, reasonNotEligible="", ftthStatus=""), aquilenetEligStatus=FAIEligibilityStatus(isEligible=False, reasonNotEligible="", ftthStatus=""),
othersEligStatus=FAIEligibilityStatus(isEligible=False, reasonNotEligible="", ftthStatus=""), othersEligStatus=FAIEligibilityStatus(isEligible=False, reasonNotEligible="", ftthStatus=""),

View File

@ -7,7 +7,11 @@ from flask import Flask, request, render_template, redirect
from eligibility_api.elig_api_exceptions import FlaskExceptions from eligibility_api.elig_api_exceptions import FlaskExceptions
from eligibility_api.elig_api_routes import EligibilityApiRoutes from eligibility_api.elig_api_routes import EligibilityApiRoutes
from ipe_fetcher import Liazo, Axione, Arcep, AreaCoordinates from ipe_fetcher import Liazo, Axione, Arcep, AreaCoordinates
from coordinates import check_coordinates_area, check_coordinates_args
LIAZO_MAX_X_INTERVAL = 0.0022
LIAZO_MAX_Y_INTERVAL = 0.0011
LIAZO_MAX_AREA = LIAZO_MAX_X_INTERVAL * LIAZO_MAX_Y_INTERVAL
class Config(TypedDict): class Config(TypedDict):
axione_ipe_path: str axione_ipe_path: str
@ -50,43 +54,38 @@ def getEligData():
args = request.args args = request.args
valid_args = True valid_args = True
processed_args = {} processed_args = {}
for k in ["swx", "swy", "nex", "ney"]: try:
valid_args = valid_args and k in args processed_args = check_coordinates_args(args)
if valid_args: except ValueError:
try: valid_args = False
processed_args[k] = float(args[k])
except ValueError:
valid_args = False
if valid_args: if valid_args:
# Need to narrow coordinates for Liazo API call coordinates = check_coordinates_area(processed_args, LIAZO_MAX_AREA)
# computes center
centerx = (processed_args['swx'] + processed_args['nex']) / 2
centery = (processed_args['swy'] + processed_args['ney']) / 2
narrow_x = 0.0022
narrow_y = 0.0011
narrow_coordinates = AreaCoordinates(
swx=centerx - narrow_x,
swy=centery - narrow_y,
nex=centerx + narrow_x,
ney=centery + narrow_y,
)
buildings = dict() buildings = dict()
try: try:
buildings = arcep.getAreaBuildings(narrow_coordinates, buildings) buildings = arcep.getAreaBuildings(coordinates, buildings)
buildings = axione.getAreaBuildings(narrow_coordinates, buildings) buildings = axione.getAreaBuildings(coordinates, buildings)
except ValueError as err: except ValueError as err:
print("Could not get Axione data for this area:", err) print("Could not get Axione data for this area:", err)
buildings = liazo.getAreaBuildings(narrow_coordinates, buildings) buildings = liazo.getAreaBuildings(coordinates, buildings)
sorted_buildings = sorted(buildings.values(), key=lambda d: d.get('etat_imm_priority', 1), reverse=True)
return {"buildings": list(sorted_buildings)} return {"buildings": list(buildings.values())}
else: else:
return "Invalid bounding box coordinates", 400 return "Invalid bounding box coordinates", 400
@app.route("/eligdata/bounds", methods=["GET"])
def getEligDataBounds():
args = request.args
try:
processed_args = check_coordinates_args(args)
return {"bounds": check_coordinates_area(processed_args, LIAZO_MAX_AREA)}
except ValueError:
return "Invalid bounding box coordinates", 400
@app.route("/eligtest/ftth", methods=["GET"]) @app.route("/eligtest/ftth", methods=["GET"])
def testFtth(): def testFtth():
args = request.args args = request.args

View File

@ -15,8 +15,8 @@ body {
} }
#btn-load-elig-data { #btn-load-elig-data {
top: 4em; top: 10em;
right: 0; left: 1em;
position: fixed; position: fixed;
z-index: 1; z-index: 1;
padding: .5em; padding: .5em;
@ -37,4 +37,24 @@ body {
.nonDeployee { .nonDeployee {
display: inline; display: inline;
color: brown; color: brown;
}
.loader {
width: 48px;
height: 48px;
border: 5px solid #1787c2;
border-bottom-color: transparent;
border-radius: 50%;
display: inline-block;
box-sizing: border-box;
animation: rotation 1s linear infinite;
}
@keyframes rotation {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
} }

View File

@ -1,4 +1,4 @@
const minZoomForRequest = 17; const minZoomForRequest = 16;
const urlADSL = 'https://tools.aquilenet.fr/cgi-bin/recherchend.cgi' const urlADSL = 'https://tools.aquilenet.fr/cgi-bin/recherchend.cgi'
const urlTestFTTH = 'https://tools.aquilenet.fr/cgi-bin/test.cgi' const urlTestFTTH = 'https://tools.aquilenet.fr/cgi-bin/test.cgi'
@ -71,7 +71,30 @@ streetTypeConversion.set("zone d'aménagement différé", "zad")
streetTypeConversion.set("zone industrielle", "zi") streetTypeConversion.set("zone industrielle", "zi")
streetTypeConversion.set("zone", "zone") streetTypeConversion.set("zone", "zone")
let markers = []; let markers = new Map();
// Default search bounds
DEFAULT_MAX_LNG_INTERVAL = 0.0028
DEFAULT_MAX_LAT_INTERVAL = 0.0014
// Search bounds from server
server_max_lng_interval = undefined
server_max_lat_interval = undefined
function getRectangleCoord(map) {
max_lng_interval = DEFAULT_MAX_LNG_INTERVAL
max_lat_interval = DEFAULT_MAX_LAT_INTERVAL
if (server_max_lat_interval !== undefined && server_max_lng_interval !== undefined) {
max_lng_interval = server_max_lng_interval
max_lat_interval = server_max_lat_interval
}
let center = map.getCenter();
let corner1 = L.latLng(center.lat - (max_lat_interval / 2), center.lng - (max_lng_interval / 2));
let corner2 = L.latLng(center.lat + (max_lat_interval / 2), center.lng + (max_lng_interval / 2));
return [corner1, corner2]
}
function initMap(btn) { function initMap(btn) {
// Init map position/zoom. Potentially using what's in the URL search string. // Init map position/zoom. Potentially using what's in the URL search string.
@ -91,7 +114,8 @@ function initMap(btn) {
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors' attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map); }).addTo(map);
map.on("zoom", () => { map.on("zoom move", () => {
/* We only want to enable the search button when we reached a sufficient zoom level */ /* We only want to enable the search button when we reached a sufficient zoom level */
if (btn.disabled && map.getZoom() >= minZoomForRequest) { if (btn.disabled && map.getZoom() >= minZoomForRequest) {
displayBtn(btn); displayBtn(btn);
@ -100,9 +124,52 @@ function initMap(btn) {
hideBtn(btn); hideBtn(btn);
} }
}); });
map.on("zoomend moveend", () => {
if (map.getZoom() >= minZoomForRequest) {
fetchEligData(map);
}
});
return map; return map;
} }
async function initLimitsBox(map, btn) {
// Create box to show where data is fetched
const box = createRectangleBox(map);
await getServerBoxBounds(map, box);
box.addTo(map);
map.on("zoom move", () => {
box.setBounds(getRectangleCoord(map))
})
btn.addEventListener("click", () => {
getServerBoxBounds(map, box)
});
}
function createRectangleBox(map) {
return L.rectangle(getRectangleCoord(map), {color: "#ff7800", fillOpacity: 0.07, weight: 1});
}
// Ask server the narrowed area bounds that it will search in
async function getServerBoxBounds(map, box) {
const bounds = map.getBounds();
const sw = bounds.getSouthWest();
const ne = bounds.getNorthEast();
const reqUri = encodeURI(`eligdata/bounds?swx=${sw.lng}&swy=${sw.lat}&nex=${ne.lng}&ney=${ne.lat}`);
const resp = await fetch(reqUri);
if (resp.status != 200) {
return
}
const data = await resp.json();
server_max_lat_interval = data.bounds.ney - data.bounds.swy
server_max_lng_interval = data.bounds.nex - data.bounds.swx
box.setBounds(getRectangleCoord(map))
}
function initAddrSearch(map) { function initAddrSearch(map) {
const autocompleteOptions = { const autocompleteOptions = {
debounceTime: 300, debounceTime: 300,
@ -138,84 +205,84 @@ function initAddrSearch(map) {
} }
function updateEligData(map, eligData) { function updateEligData(map, eligData) {
if (markers) {
markers.map(marker => map.removeLayer(marker));
}
let buildings = eligData.buildings; let buildings = eligData.buildings;
markers = buildings.forEach(building => { buildings.forEach(building => {
const latlng = new L.latLng(building.y, building.x); if (! markers.has(building.idImm)) {
let addrImm = `${building.numVoieImm} ${building.typeVoieImm} ${building.nomVoieImm}` const latlng = new L.latLng(building.y, building.x);
if (building.bat_info != "") { let addrImm = `${building.numVoieImm} ${building.typeVoieImm} ${building.nomVoieImm}`
addrImm += ` (Bat ${building.bat_info})` if (building.bat_info != "") {
} addrImm += ` (Bat ${building.bat_info})`
let colorMarker = 'black' }
let messageElig = `` let colorMarker = 'black'
eligTestApi = `eligtest/ftth?idImm=${building.idImm}&codePostal=${building.codePostal}&axione=${building.aquilenetEligStatus.isEligible}&liazo=${building.fdnEligStatus.isEligible}` let messageElig = ``
// éligible chez Aquilenet, lien pour le test eligTestApi = `eligtest/ftth?idImm=${building.idImm}&codePostal=${building.codePostal}&axione=${building.aquilenetEligStatus.isEligible}&liazo=${building.fdnEligStatus.isEligible}`
if (building.aquilenetEligStatus.isEligible) { // éligible chez Aquilenet, lien pour le test
if (building.aquilenetEligStatus.isEligible) {
// Si fibre Axione déployé mais pas encore commandable // Si fibre Axione déployé mais pas encore commandable
if (building.aquilenetEligStatus.ftthStatus == "DEPLOYE MAIS NON COMMANDABLE") { if (building.aquilenetEligStatus.ftthStatus == "DEPLOYE MAIS NON COMMANDABLE") {
colorMarker = 'orange' colorMarker = 'orange'
messageElig = `<p class=deployeeAquilenet>Fibre deployée mais ne sera commandable qu\'à partir du ${building.aquilenetEligStatus.dateCommandable}</p>` messageElig = `<p class=deployeeAquilenet>Fibre deployée mais ne sera commandable qu\'à partir du ${building.aquilenetEligStatus.dateCommandable}</p>`
} else { } else {
messageElig = `<p class=deployeeAquilenet>Fibre deployée et disponible par Aquilenet !</p>` messageElig = `<p class=deployeeAquilenet>Fibre deployée et disponible par Aquilenet !</p>`
const zip = encodeURIComponent(building.codePostal); const zip = encodeURIComponent(building.codePostal);
const idImm = encodeURIComponent(building.idImm); const idImm = encodeURIComponent(building.idImm);
messageElig += `<br/><a href=${urlTestFTTH}?ftth=1&axione=1&adsltel=NOUVEAU&cp=${zip}&refimmeuble=${idImm}` + messageElig += `<br/><a href=${urlTestFTTH}?ftth=1&axione=1&adsltel=NOUVEAU&cp=${zip}&refimmeuble=${idImm}` +
`>Tester l'éligibilité</a>` `>Tester l'éligibilité</a>`
colorMarker = 'green' colorMarker = 'green'
} }
// pas de données Axione mais Kosc nous renvoie qque chose à cette adresse (fdnEligStatus) // pas de données Axione mais Kosc nous renvoie qque chose à cette adresse (fdnEligStatus)
// c'est peut être OK, on croise avec les données ARCEP (othersEligStatus) // c'est peut être OK, on croise avec les données ARCEP (othersEligStatus)
// Enfin on affiche un lien vers le test d'éligibilté KOSC à cette adresse // Enfin on affiche un lien vers le test d'éligibilté KOSC à cette adresse
} else if (building.fdnEligStatus.isEligible && building.othersEligStatus.isEligible) { } else if (building.fdnEligStatus.isEligible && building.othersEligStatus.isEligible) {
messageElig = `<p class=deployeeFDN>Fibre deployee mais pas chez Axione !` messageElig = `<p class=deployeeFDN>Fibre deployee mais pas chez Axione !`
messageElig += `<br/><a href=${eligTestApi}>Tester l'eligibilite par Kosc et Bouygues</a></p>` messageElig += `<br/><a href=${eligTestApi}>Tester l'eligibilite par Kosc et Bouygues</a></p>`
colorMarker = 'orange' colorMarker = 'orange'
// Pas de données Kosc ou Axione mais l'ARCEP nous dit qu'une fibre est déployée à cette adresse // Pas de données Kosc ou Axione mais l'ARCEP nous dit qu'une fibre est déployée à cette adresse
} else if (building.othersEligStatus.isEligible) { } else if (building.othersEligStatus.isEligible) {
messageElig = `<p class=deployeeAutres>Fibre deployee mais non eligible Aquilenet, desole :(</p>` messageElig = `<p class=deployeeAutres>Fibre deployee mais non eligible Aquilenet, desole :(</p>`
colorMarker = 'red' colorMarker = 'red'
// Pas de fibre il semblerait, proposer un test ADSL Aquilenet // Pas de fibre il semblerait, proposer un test ADSL Aquilenet
} else { } else {
messageElig = `<p class=nonDeployee>Fibre non deployee :(</p>` messageElig = `<p class=nonDeployee>Fibre non deployee :(</p>`
const zip = encodeURIComponent(building.codePostal); const zip = encodeURIComponent(building.codePostal);
const comm = encodeURIComponent(building.commune); const comm = encodeURIComponent(building.commune);
let convertType = streetTypeConversion.get(building.typeVoieImm.toLowerCase()); let convertType = streetTypeConversion.get(building.typeVoieImm.toLowerCase());
if (!convertType) { if (!convertType) {
convertType = building.typeVoieImm; convertType = building.typeVoieImm;
}
const street = encodeURIComponent(`${convertType} ${building.nomVoieImm}`)
const street_nb = encodeURIComponent(building.numVoieImm)
messageElig += `<br/><a href=${urlADSL}?zip=${zip}&city=${comm}&street=${street}&street_nb=${street_nb}&gps=&do=1&submit=Valider` +
`>Tester ADSL a cette adresse</a>`
if (building.othersEligStatus.reasonNotEligible != "") {
messageElig += `<br/><br/>Status general ARCEP: ${building.othersEligStatus.reasonNotEligible}`
}
} }
const street = encodeURIComponent(`${convertType} ${building.nomVoieImm}`) // Si pas d'éligibilité fibre, on affiche la raison si elle existe
const street_nb = encodeURIComponent(building.numVoieImm) if (building.aquilenetEligStatus.reasonNotEligible != "") {
messageElig += `<br/><a href=${urlADSL}?zip=${zip}&city=${comm}&street=${street}&street_nb=${street_nb}&gps=&do=1&submit=Valider` + messageElig += `<br/> Pour Aquilenet, raison non eligible: ${building.aquilenetEligStatus.reasonNotEligible}`
`>Tester ADSL a cette adresse</a>`
if (building.othersEligStatus.reasonNotEligible != "") {
messageElig += `<br/><br/>Status general ARCEP: ${building.othersEligStatus.reasonNotEligible}`
} }
var markerIcon = new L.Icon({
iconUrl: `static/icons/marker-icon-${colorMarker}.png`,
shadowUrl: 'static/vendor/images/marker-shadow.png',
iconSize: [25, 41],
iconAnchor: [12, 41],
popupAnchor: [1, -34],
shadowSize: [41, 41]
});
const marker = new L.marker(latlng, {
icon: markerIcon,
zIndexOffset: - building.etat_imm_priority
})
.bindPopup(`${addrImm}<br/>${building.codePostal} ${building.commune}` +
`<br/><br/>${messageElig}<br/><br/>Ref Immeuble: ${building.idImm}`, {
maxWidth: 560
});
map.addLayer(marker);
markers.set(building.idImm, marker)
} }
// Si pas d'éligibilité fibre, on affiche la raison si elle existe
if (building.aquilenetEligStatus.reasonNotEligible != "") {
messageElig += `<br/> Pour Aquilenet, raison non eligible: ${building.aquilenetEligStatus.reasonNotEligible}`
}
var markerIcon = new L.Icon({
iconUrl: `static/icons/marker-icon-${colorMarker}.png`,
shadowUrl: 'static/vendor/images/marker-shadow.png',
iconSize: [25, 41],
iconAnchor: [12, 41],
popupAnchor: [1, -34],
shadowSize: [41, 41]
});
const marker = new L.marker(latlng, {
icon: markerIcon
})
.bindPopup(`${addrImm}<br/>${building.codePostal} ${building.commune}` +
`<br/><br/>${messageElig}<br/><br/>Ref Immeuble: ${building.idImm}`, {
maxWidth: 560
});
map.addLayer(marker);
return marker
}); });
} }
@ -230,12 +297,17 @@ async function fetchEligData(map) {
const bounds = map.getBounds(); const bounds = map.getBounds();
const sw = bounds.getSouthWest(); const sw = bounds.getSouthWest();
const ne = bounds.getNorthEast(); const ne = bounds.getNorthEast();
const btn = document.getElementById("btn-load-elig-data"); let btn = document.getElementById("btn-load-elig-data");
waitBtn(btn); waitBtn(btn);
const reqUri = encodeURI(`eligdata?swx=${sw.lng}&swy=${sw.lat}&nex=${ne.lng}&ney=${ne.lat}`); const reqUri = encodeURI(`eligdata?swx=${sw.lng}&swy=${sw.lat}&nex=${ne.lng}&ney=${ne.lat}`);
const source = await fetch(reqUri); const resp = await fetch(reqUri);
const eligData = await source.json(); if (resp.status == 200) {
updateEligData(map, eligData); const eligData = await resp.json();
updateEligData(map, eligData);
} else {
error = await resp.text()
console.log(`Error could not get data from server: ${resp.status} ${error}`)
}
updateUrl(map); updateUrl(map);
displayBtn(btn); displayBtn(btn);
} }
@ -244,27 +316,50 @@ async function fetchEligData(map) {
function initBtn() { function initBtn() {
const btn = document.getElementById("btn-load-elig-data"); const btn = document.getElementById("btn-load-elig-data");
btn.disabled = true; btn.disabled = true;
btn.title = "Veuillez zoomer plus la carte avant de lancer une recherche d'éligibilité."; btn.title = "Veuillez zoomer plus la carte pour charger l'éligibilité.";
btn.onclick = () => fetchEligData(map);
return btn; return btn;
} }
function setBtnListener(btn, map) {
btn.onclick = () => {
// Reset markers when button is clicked
if (markers) {
for (let marker of markers.values()){
map.removeLayer(marker);
}
markers.clear();
}
fetchEligData(map);
}
}
function displayBtn(btn) { function displayBtn(btn) {
btn.classList.remove('loader');
btn.disabled = false; btn.disabled = false;
btn.title = "Rechercher les données d'éligibilité pour cette zone." btn.title = "Actualiser la recherche dans cette zone"
btn.innerHTML = "Actualiser";
} }
function hideBtn(btn) { function hideBtn(btn) {
btn.disabled = true; btn.disabled = true;
btn.title = "Veuillez zoomer plus la carte avant de lancer une recherche d'éligibilité."; btn.innerHTML = "Zoomez sur la carte";
btn.title = "Veuillez zoomer plus la carte afin de lancer la recherche d'éligibilité.";
} }
function waitBtn(btn) { function waitBtn(btn) {
btn.disabled = true; btn.disabled = true;
btn.innerHTML = "";
btn.title = "Chargement des batiments..."; btn.title = "Chargement des batiments...";
btn.classList.add('loader');
} }
// Init button and map
const btn = initBtn(); const btn = initBtn();
const map = initMap(btn); const map = initMap(btn);
const addrSearch = initAddrSearch(map); const addrSearch = initAddrSearch(map);
setBtnListener(btn, map);
// Init a limits box that shows area where data will be fetched
initLimitsBox(map, btn);

View File

@ -18,14 +18,13 @@
</head> </head>
<body> <body>
<button id="btn-load-elig-data" type="button" disabled>Zoomez sur la carte</button>
<div class="autocomplete" id="search-addr-autocomplete"> <div class="autocomplete" id="search-addr-autocomplete">
<input id="search-addr-autocomplete-input" class="autocomplete-input" <input id="search-addr-autocomplete-input" class="autocomplete-input"
spellcheck="false" autocorrect="off"t e autocomplete="off" spellcheck="false" autocorrect="off"t e autocomplete="off"
autocapitalize="off" placeholder="Votre Adresse"/> autocapitalize="off" placeholder="Votre Adresse"/>
<ul class="autocomplete-result-list"/> <ul class="autocomplete-result-list"/>
</div> </div>
<button id="btn-load-elig-data" type="button">Récupérer les données d'éligibilité
pour cette zone</button>
<div id="map"/> <div id="map"/>
<script> <script>
document.addEventListener("DOMContentLoaded", function(event) { document.addEventListener("DOMContentLoaded", function(event) {