ajout connexion Liazo
This commit is contained in:
parent
b05cf14bf3
commit
b9df2de12a
9 changed files with 263 additions and 147 deletions
|
@ -1,2 +1,2 @@
|
||||||
[DB]
|
[DB]
|
||||||
path = /path/to/ipe.sqlite
|
axione_ipe_path = /path/to/ipe.sqlite
|
|
@ -0,0 +1,2 @@
|
||||||
|
from .axione import *
|
||||||
|
from .liazo import *
|
|
@ -1,8 +1,86 @@
|
||||||
# const AXIONE_ETAT_DEPLOYE =
|
from ipe_fetcher.model import AreaCoordinates, Building, FAIEligibilityStatus
|
||||||
# "DEPLOYE"
|
from ipe_fetcher.sqlite_connector.cursor import getCursorWithSpatialite
|
||||||
# const AXIONE_ETAT_DEPLOIEMENT = "EN COURS DE DEPLOIEMENT"
|
from os.path import exists
|
||||||
# const AXIONE_ETAT_ABANDONNE = "ABANDONNE"
|
|
||||||
# const AXIONE_ETAT_CIBLE = "CIBLE"
|
AXIONE_ETAT_DEPLOYE = "DEPLOYE"
|
||||||
# const AXIONE_ETAT_SIGNE = "SIGNE"
|
AXIONE_ETAT_DEPLOIEMENT = "EN COURS DE DEPLOIEMENT"
|
||||||
# const AXIONE_ETAT_RAD_DEPLOIEMENT = "RAD EN COURS DE DEPLOIEMENT"
|
AXIONE_ETAT_ABANDONNE = "ABANDONNE"
|
||||||
# const AXIONE_ETAT_RACCORDABLE_DEMANDE = "RACCORDABLE DEMANDE"
|
AXIONE_ETAT_CIBLE = "CIBLE"
|
||||||
|
AXIONE_ETAT_SIGNE = "SIGNE"
|
||||||
|
AXIONE_ETAT_RAD_DEPLOIEMENT = "RAD EN COURS DE DEPLOIEMENT"
|
||||||
|
AXIONE_ETAT_RACCORDABLE_DEMANDE = "RACCORDABLE DEMANDE"
|
||||||
|
|
||||||
|
|
||||||
|
class Axione:
|
||||||
|
def __init__(self, db_axione_ipe_path: str):
|
||||||
|
self.db_axione_ipe_path = db_axione_ipe_path
|
||||||
|
# Check at least that the file exists
|
||||||
|
if not exists(self.db_axione_ipe_path):
|
||||||
|
raise ValueError(f"File {self.db_axione_ipe_path} does not exist")
|
||||||
|
|
||||||
|
def getAreaBuildings(
|
||||||
|
self, areaCoordinates: AreaCoordinates, existing_buildings: dict
|
||||||
|
) -> dict:
|
||||||
|
cur = None
|
||||||
|
# Try to get cursor on Axone database
|
||||||
|
try:
|
||||||
|
cur = getCursorWithSpatialite(self.db_axione_ipe_path)
|
||||||
|
except Exception as err:
|
||||||
|
print("Error while connecting to DB: ", err)
|
||||||
|
raise "Could not get Axione data"
|
||||||
|
# Let's first see how big is the area we're about to query.
|
||||||
|
# If it's too big, abort the request to prevent a server DOS.
|
||||||
|
cur.execute(
|
||||||
|
"""
|
||||||
|
SELECT Area(BuildMBR(:swx,:swy,:nex,:ney,4326))
|
||||||
|
""",
|
||||||
|
areaCoordinates,
|
||||||
|
)
|
||||||
|
req_area = cur.fetchone()[0]
|
||||||
|
if req_area <= 0.08:
|
||||||
|
cur.execute(
|
||||||
|
"""
|
||||||
|
SELECT
|
||||||
|
X(ImmeubleGeoPoint),
|
||||||
|
Y(ImmeubleGeoPoint),
|
||||||
|
IdentifiantImmeuble,
|
||||||
|
EtatImmeuble,
|
||||||
|
NumeroVoieImmeuble,
|
||||||
|
TypeVoieImmeuble,
|
||||||
|
NomVoieImmeuble
|
||||||
|
FROM ipe
|
||||||
|
WHERE ROWID IN (
|
||||||
|
SELECT ROWID FROM SpatialIndex
|
||||||
|
WHERE f_table_name = 'ipe' AND
|
||||||
|
search_frame = BuildMBR(:swx, :swy, :nex, :ney, 4326))
|
||||||
|
""",
|
||||||
|
areaCoordinates,
|
||||||
|
)
|
||||||
|
if not existing_buildings:
|
||||||
|
existing_buildings = dict()
|
||||||
|
buildings = existing_buildings
|
||||||
|
for b in cur.fetchall():
|
||||||
|
etatImm = b[3]
|
||||||
|
idImm = b[2]
|
||||||
|
isEligible = etatImm == AXIONE_ETAT_DEPLOYE
|
||||||
|
aquilenetEligStatus = FAIEligibilityStatus(
|
||||||
|
isEligible=isEligible,
|
||||||
|
ftthStatus=etatImm,
|
||||||
|
reasonNotEligible=None if isEligible else "Pas encore deploye",
|
||||||
|
)
|
||||||
|
if buildings.get(idImm):
|
||||||
|
buildings[idImm]["aquilenetEligStatus"] = aquilenetEligStatus
|
||||||
|
else:
|
||||||
|
building = Building(
|
||||||
|
x=b[0],
|
||||||
|
y=b[1],
|
||||||
|
idImm=idImm,
|
||||||
|
numVoieImm=b[4],
|
||||||
|
typeVoieImm=b[5],
|
||||||
|
nomVoieImm=b[6],
|
||||||
|
aquilenetEligStatus=aquilenetEligStatus,
|
||||||
|
)
|
||||||
|
buildings[idImm] = building
|
||||||
|
return buildings
|
||||||
|
else:
|
||||||
|
raise ValueError("The requested area is too wide, please reduce it")
|
||||||
|
|
41
webapp/ipe_fetcher/liazo.py
Normal file
41
webapp/ipe_fetcher/liazo.py
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
import http.client as httplib
|
||||||
|
from ipe_fetcher.model import AreaCoordinates, Building, FAIEligibilityStatus
|
||||||
|
import json
|
||||||
|
|
||||||
|
class Liazo:
|
||||||
|
def __init__(self):
|
||||||
|
self.https_conn = httplib.HTTPSConnection("vador.fdn.fr")
|
||||||
|
|
||||||
|
def getAreaBuildings(
|
||||||
|
self, center_lat: float, center_lng: float, existing_buildings: dict
|
||||||
|
) -> dict:
|
||||||
|
c = self.https_conn
|
||||||
|
req = "/souscription/gps-batiments.cgi?etape=gps_batiments&lat1=%f&lat2=%f&lon1=%f&lon2=%f" % (center_lat-0.0011, center_lat+0.0011, center_lng-0.0022, center_lng+0.0022)
|
||||||
|
req = req.replace(" ", "%20")
|
||||||
|
print("Req FDN with: ", req)
|
||||||
|
c.request("GET", req)
|
||||||
|
r = c.getresponse()
|
||||||
|
if r.status < 200 or r.status >= 300:
|
||||||
|
print("Erreur de serveur chez FDN. Merci de nous faire remonter le numéro de téléphone qui provoque cette erreur")
|
||||||
|
return
|
||||||
|
d = r.read()
|
||||||
|
c.close()
|
||||||
|
v = json.loads(d.decode("utf-8"))
|
||||||
|
if not existing_buildings:
|
||||||
|
existing_buildings = dict()
|
||||||
|
buildings = existing_buildings
|
||||||
|
for building in v:
|
||||||
|
idImm=building.get('ref')
|
||||||
|
if not buildings.get(idImm):
|
||||||
|
|
||||||
|
building = Building(
|
||||||
|
y=building.get('lat'),
|
||||||
|
x=building.get('lon'),
|
||||||
|
idImm=idImm,
|
||||||
|
numVoieImm="",
|
||||||
|
typeVoieImm="",
|
||||||
|
nomVoieImm=""
|
||||||
|
)
|
||||||
|
print("add building ", building)
|
||||||
|
buildings[idImm] = building
|
||||||
|
return buildings
|
|
@ -3,7 +3,6 @@ from typing import TypedDict
|
||||||
|
|
||||||
class FAIEligibilityStatus(TypedDict):
|
class FAIEligibilityStatus(TypedDict):
|
||||||
isEligible: bool
|
isEligible: bool
|
||||||
ftthDeployer: str
|
|
||||||
ftthStatus: str
|
ftthStatus: str
|
||||||
reasonNotEligible: str
|
reasonNotEligible: str
|
||||||
|
|
||||||
|
@ -18,3 +17,10 @@ class Building(TypedDict):
|
||||||
aquilenetEligStatus: FAIEligibilityStatus
|
aquilenetEligStatus: FAIEligibilityStatus
|
||||||
ffdnEligStatus: FAIEligibilityStatus
|
ffdnEligStatus: FAIEligibilityStatus
|
||||||
othersEligStatus: FAIEligibilityStatus
|
othersEligStatus: FAIEligibilityStatus
|
||||||
|
|
||||||
|
|
||||||
|
class AreaCoordinates(TypedDict):
|
||||||
|
swx: float
|
||||||
|
swy: float
|
||||||
|
nex: float
|
||||||
|
ney: float
|
||||||
|
|
1
webapp/ipe_fetcher/sqlite_connector/__init__.py
Normal file
1
webapp/ipe_fetcher/sqlite_connector/__init__.py
Normal file
|
@ -0,0 +1 @@
|
||||||
|
# from .cursor import *
|
8
webapp/ipe_fetcher/sqlite_connector/cursor.py
Normal file
8
webapp/ipe_fetcher/sqlite_connector/cursor.py
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import sqlite3
|
||||||
|
|
||||||
|
def getCursorWithSpatialite(db_path: str = None) -> sqlite3.Cursor:
|
||||||
|
db = sqlite3.connect(db_path)
|
||||||
|
cur = db.cursor()
|
||||||
|
db.enable_load_extension(True)
|
||||||
|
cur.execute('SELECT load_extension("mod_spatialite")')
|
||||||
|
return cur
|
|
@ -4,30 +4,37 @@ from typing import TypedDict
|
||||||
import configparser
|
import configparser
|
||||||
import sqlite3
|
import sqlite3
|
||||||
import os
|
import os
|
||||||
|
from ipe_fetcher import Liazo,Axione
|
||||||
class Config(TypedDict):
|
class Config(TypedDict):
|
||||||
dbPath: str
|
axione_ipe_path: str
|
||||||
|
|
||||||
|
|
||||||
def parseConfig() -> Config:
|
def parseConfig() -> Config:
|
||||||
cfg_path = os.environ.get("CONFIG", "/etc/ftth-ipe-map/conf.ini")
|
cfg_path = os.environ.get("CONFIG", "/etc/ftth-ipe-map/conf.ini")
|
||||||
cfg = configparser.ConfigParser()
|
cfg = configparser.ConfigParser()
|
||||||
with open(cfg_path, "r") as f:
|
with open(cfg_path, "r") as f:
|
||||||
cfg.read_file(f)
|
cfg.read_file(f)
|
||||||
return {'dbPath':cfg.get("DB","path")}
|
return {"axione_ipe_path": cfg.get("DB", "axione_ipe_path")}
|
||||||
|
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
cfg:Config = parseConfig()
|
cfg: Config = parseConfig()
|
||||||
|
|
||||||
|
axione = Axione(cfg.get("axione_ipe_path"))
|
||||||
|
liazo = Liazo()
|
||||||
|
|
||||||
|
|
||||||
@app.route("/", methods=["GET"])
|
@app.route("/", methods=["GET"])
|
||||||
def getMap():
|
def getMap():
|
||||||
return render_template("map.html")
|
return render_template("map.html")
|
||||||
|
|
||||||
|
|
||||||
@app.route("/eligdata", methods=["GET"])
|
@app.route("/eligdata", methods=["GET"])
|
||||||
def getEligData():
|
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']:
|
for k in ["swx", "swy", "nex", "ney", "centerlat", "centerlng"]:
|
||||||
valid_args = valid_args and k in args
|
valid_args = valid_args and k in args
|
||||||
if valid_args:
|
if valid_args:
|
||||||
try:
|
try:
|
||||||
|
@ -35,43 +42,14 @@ def getEligData():
|
||||||
except ValueError:
|
except ValueError:
|
||||||
valid_args = False
|
valid_args = False
|
||||||
if valid_args:
|
if valid_args:
|
||||||
cur = cursorWithSpatialite()
|
buildings = dict()
|
||||||
# Let's first see how big is the area we're about to query.
|
try:
|
||||||
# If it's too big, abort the request to prevent a server DOS.
|
buildings = axione.getAreaBuildings(processed_args, buildings)
|
||||||
cur.execute('''
|
except ValueError as err:
|
||||||
SELECT Area(BuildMBR(:swx,:swy,:nex,:ney,4326))
|
print("Could not get Axione data for this area:", err)
|
||||||
''',processed_args)
|
|
||||||
req_area = cur.fetchone()[0]
|
buildings = liazo.getAreaBuildings(processed_args["centerlat"], processed_args["centerlng"], buildings)
|
||||||
if req_area <= 0.08:
|
|
||||||
cur.execute('''
|
return {"buildings": buildings}
|
||||||
SELECT
|
|
||||||
X(ImmeubleGeoPoint),
|
|
||||||
Y(ImmeubleGeoPoint),
|
|
||||||
IdentifiantImmeuble,
|
|
||||||
EtatImmeuble,
|
|
||||||
NumeroVoieImmeuble,
|
|
||||||
TypeVoieImmeuble,
|
|
||||||
NomVoieImmeuble
|
|
||||||
FROM ipe
|
|
||||||
WHERE ROWID IN (
|
|
||||||
SELECT ROWID FROM SpatialIndex
|
|
||||||
WHERE f_table_name = 'ipe' AND
|
|
||||||
search_frame = BuildMBR(:swx, :swy, :nex, :ney, 4326))
|
|
||||||
''',processed_args)
|
|
||||||
buildings = [ {
|
|
||||||
'x':b[0], 'y':b[1], 'idImm':b[2],
|
|
||||||
'etatImm':b[3], 'numVoieImm': b[4],
|
|
||||||
'typeVoieImm': b[5], 'nomVoieImm': b[6]
|
|
||||||
} for b in cur.fetchall()]
|
|
||||||
return { "buildings": buildings}
|
|
||||||
else:
|
|
||||||
return "The requested area is too wide, please reduce it", 400
|
|
||||||
else:
|
else:
|
||||||
return "Invalid bounding box coordinates", 400
|
return "Invalid bounding box coordinates", 400
|
||||||
|
|
||||||
def cursorWithSpatialite():
|
|
||||||
db = sqlite3.connect(cfg['dbPath'])
|
|
||||||
cur = db.cursor()
|
|
||||||
db.enable_load_extension(True)
|
|
||||||
cur.execute('SELECT load_extension("mod_spatialite")')
|
|
||||||
return cur
|
|
||||||
|
|
|
@ -1,118 +1,120 @@
|
||||||
const minZoomForRequest = 17;
|
const minZoomForRequest = 17;
|
||||||
let markers = [];
|
let markers = [];
|
||||||
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.
|
||||||
const params = new URLSearchParams(window.location.search);
|
const params = new URLSearchParams(window.location.search);
|
||||||
let x = parseFloat(params.get('x'));
|
let x = parseFloat(params.get('x'));
|
||||||
let y = parseFloat(params.get('y'));
|
let y = parseFloat(params.get('y'));
|
||||||
let z = parseInt(params.get('z'));
|
let z = parseInt(params.get('z'));
|
||||||
let map = L.map('map');
|
let map = L.map('map');
|
||||||
if(x && y && z) {
|
if (x && y && z) {
|
||||||
map.setView([y, x], z);
|
map.setView([y, x], z);
|
||||||
fetchEligData(map);
|
fetchEligData(map);
|
||||||
displayBtn(btn);
|
displayBtn(btn);
|
||||||
} else {
|
} else {
|
||||||
map.setView([46.710, 3.669], 6);
|
map.setView([46.710, 3.669], 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
L.tileLayer('https://{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png', {
|
||||||
|
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||||
|
}).addTo(map);
|
||||||
|
|
||||||
|
map.on("zoom", () => {
|
||||||
|
/* We only want to enable the search button when we reached a sufficient zoom level */
|
||||||
|
if (btn.disabled && map.getZoom() >= minZoomForRequest) {
|
||||||
|
displayBtn(btn);
|
||||||
}
|
}
|
||||||
|
if (!btn.disabled && map.getZoom() < minZoomForRequest) {
|
||||||
L.tileLayer('https://{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png', {
|
hideBtn(btn);
|
||||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
}
|
||||||
}).addTo(map);
|
});
|
||||||
|
return map;
|
||||||
map.on("zoom", () => {
|
|
||||||
/* We only want to enable the search button when we reached a sufficient zoom level */
|
|
||||||
if (btn.disabled && map.getZoom() >= minZoomForRequest) {
|
|
||||||
displayBtn(btn);
|
|
||||||
}
|
|
||||||
if (!btn.disabled && map.getZoom() < minZoomForRequest) {
|
|
||||||
hideBtn(btn);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return map;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function initAddrSearch(map) {
|
function initAddrSearch(map) {
|
||||||
const autocompleteOptions = {
|
const autocompleteOptions = {
|
||||||
debounceTime: 300,
|
debounceTime: 300,
|
||||||
search: async (query) => {
|
search: async (query) => {
|
||||||
if(query.length > 2) {
|
if (query.length > 2) {
|
||||||
const mapCenter = map.getCenter();
|
const mapCenter = map.getCenter();
|
||||||
const reqUri = `https://photon.komoot.io/api/?q=${encodeURI(query)}&lat=${mapCenter.lat}&lon=${mapCenter.lng}&limit=20&lang=fr`;
|
const reqUri = `https://photon.komoot.io/api/?q=${encodeURI(query)}&lat=${mapCenter.lat}&lon=${mapCenter.lng}&limit=20&lang=fr`;
|
||||||
const source = await fetch(reqUri);
|
const source = await fetch(reqUri);
|
||||||
const data = await source.json();
|
const data = await source.json();
|
||||||
return data.features;
|
return data.features;
|
||||||
} else {
|
} else {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
renderResult: (res, props) => {
|
renderResult: (res, props) => {
|
||||||
const p = res.properties;
|
const p = res.properties;
|
||||||
if(p.name && p.postcode && p.city && p.county && res.geometry.coordinates && res.geometry.coordinates.length === 2)
|
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>`;
|
return `<li ${props}>${p.name} - ${p.postcode} ${p.city}, ${p.county}</li>`;
|
||||||
else
|
else
|
||||||
return "";
|
return "";
|
||||||
},
|
},
|
||||||
onSubmit: async (res) => {
|
onSubmit: async (res) => {
|
||||||
const searchInput = document.getElementById('search-addr-autocomplete-input');
|
const searchInput = document.getElementById('search-addr-autocomplete-input');
|
||||||
const p = res.properties;
|
const p = res.properties;
|
||||||
searchInput.value = `${p.name} - ${p.postcode} ${p.city}, ${p.county}`;
|
searchInput.value = `${p.name} - ${p.postcode} ${p.city}, ${p.county}`;
|
||||||
// We already filtered out the result not having strictly 2 coordinates at item display
|
// 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);
|
map.setView([res.geometry.coordinates[1], res.geometry.coordinates[0]], 19);
|
||||||
fetchEligData(map);
|
fetchEligData(map);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const autocompleteAddr = new Autocomplete("#search-addr-autocomplete", autocompleteOptions);
|
const autocompleteAddr = new Autocomplete("#search-addr-autocomplete", autocompleteOptions);
|
||||||
return autocompleteAddr;
|
return autocompleteAddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateEligData(map, eligData) {
|
function updateEligData(map, eligData) {
|
||||||
markers.map(marker => map.removeLayer(marker));
|
markers.map(marker => map.removeLayer(marker));
|
||||||
let buildings = eligData.buildings;
|
let buildings = eligData.buildings;
|
||||||
markers = buildings.map(building => {
|
console.log(buildings)
|
||||||
const latlng = new L.latLng(building.y, building.x);
|
markers = Object.values(buildings).map(building => {
|
||||||
const addrImm = `${building.numVoieImm} ${building.typeVoieImm} ${building.nomVoieImm}`
|
const latlng = new L.latLng(building.y, building.x);
|
||||||
const marker = new L.marker(latlng)
|
const addrImm = `${building.numVoieImm} ${building.typeVoieImm} ${building.nomVoieImm}`
|
||||||
.bindPopup(`${addrImm}<br/>Etat: ${building.etatImm}<br/>Code Immeuble: ${building.idImm}`);
|
const marker = new L.marker(latlng)
|
||||||
map.addLayer(marker);
|
.bindPopup(`${addrImm}<br/>Etat: ${building.etatImm}<br/>Code Immeuble: ${building.idImm}`);
|
||||||
return marker
|
map.addLayer(marker);
|
||||||
});
|
return marker
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateUrl(map) {
|
function updateUrl(map) {
|
||||||
const c = map.getCenter();
|
const c = map.getCenter();
|
||||||
history.replaceState({}, "", encodeURI(`?x=${c.lng}&y=${c.lat}&z=${map.getZoom()}`));
|
history.replaceState({}, "", encodeURI(`?x=${c.lng}&y=${c.lat}&z=${map.getZoom()}`));
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchEligData(map) {
|
async function fetchEligData(map) {
|
||||||
const zoom = map.getZoom();
|
const zoom = map.getZoom();
|
||||||
if (zoom >= minZoomForRequest) {
|
if (zoom >= minZoomForRequest) {
|
||||||
const bounds = map.getBounds();
|
const mc = map.getCenter();
|
||||||
const sw = bounds.getSouthWest();
|
const bounds = map.getBounds();
|
||||||
const ne = bounds.getNorthEast();
|
const sw = bounds.getSouthWest();
|
||||||
const reqUri = encodeURI(`eligdata?swx=${sw.lng}&swy=${sw.lat}&nex=${ne.lng}&ney=${ne.lat}`);
|
const ne = bounds.getNorthEast();
|
||||||
const source = await fetch(reqUri);
|
const reqUri = encodeURI(`eligdata?swx=${sw.lng}&swy=${sw.lat}&nex=${ne.lng}&ney=${ne.lat}¢erlat=${mc.lat}¢erlng=${mc.lng}`);
|
||||||
const eligData = await source.json();
|
const source = await fetch(reqUri);
|
||||||
updateEligData(map, eligData);
|
const eligData = await source.json();
|
||||||
updateUrl(map);
|
updateEligData(map, eligData);
|
||||||
}
|
updateUrl(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 avant de lancer une recherche d'éligibilité.";
|
||||||
btn.onclick = () => fetchEligData(map);
|
btn.onclick = () => fetchEligData(map);
|
||||||
return btn;
|
return btn;
|
||||||
}
|
}
|
||||||
|
|
||||||
function displayBtn(btn) {
|
function displayBtn(btn) {
|
||||||
btn.disabled = false;
|
btn.disabled = false;
|
||||||
btn.title = "Rechercher les données d'éligibilité pour cette zone."
|
btn.title = "Rechercher les données d'éligibilité pour cette zone."
|
||||||
}
|
}
|
||||||
|
|
||||||
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.title = "Veuillez zoomer plus la carte avant de lancer une recherche d'éligibilité.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue