johan/add-api #7
9 changed files with 304 additions and 133 deletions
35
webapp/coordinates.py
Normal file
35
webapp/coordinates.py
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
|
||||||
|
import math
|
||||||
|
|
||||||
|
from ipe_fetcher import AreaCoordinates
|
||||||
|
def check_coordinates_area(coordinates: AreaCoordinates, max_area) -> AreaCoordinates:
|
||||||
johan.le.baut marked this conversation as resolved
|
|||||||
|
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
|
|
@ -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'")
|
|
@ -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(
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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=""),
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
@ -38,3 +38,23 @@ body {
|
||||||
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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
attribution: '© <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);
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in a new issue
We changed the function behaviour. Let's align the name with the new function.
Something like: