From c75a6fcac36875f76cac8cd24f2b9d1a5b512ff1 Mon Sep 17 00:00:00 2001 From: Joaquim Nallar Date: Tue, 26 Nov 2024 11:12:09 +0100 Subject: [PATCH] feat: Add territory part on home page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ajout d'une carte territoire ainsi que la liste des espèces sur celui-ci. L'affichage de cette carte est en mailles. --- atlas/atlasAPI.py | 7 +- atlas/atlasRoutes.py | 11 +++ .../vmObservationsMaillesRepository.py | 97 +++++++++++++++++++ .../repositories/vmTaxonsRepository.py | 37 +++++++ atlas/static/mapAreas.js | 84 ++++++++-------- atlas/static/mapHome.js | 47 ++++++++- atlas/templates/home/_main.html | 5 + atlas/templates/home/territory.html | 27 ++++++ docs/changelog.rst | 1 + 9 files changed, 271 insertions(+), 45 deletions(-) create mode 100644 atlas/templates/home/territory.html diff --git a/atlas/atlasAPI.py b/atlas/atlasAPI.py index b239c338..24fe1415 100644 --- a/atlas/atlasAPI.py +++ b/atlas/atlasAPI.py @@ -94,7 +94,12 @@ def getObservationsGenericApi(cd_ref: int): [type]: [description] """ session = db.session - if current_app.config["AFFICHAGE_MAILLE"]: + if current_app.config["AFFICHAGE_TERRITOIRE_OBS"]: + observations = vmObservationsMaillesRepository.getObservationsMaillesTerritorySpecies( + session, + cd_ref, + ) + elif current_app.config["AFFICHAGE_MAILLE"]: observations = vmObservationsMaillesRepository.getObservationsMaillesChilds( session, cd_ref, diff --git a/atlas/atlasRoutes.py b/atlas/atlasRoutes.py index fb26de7f..dcd41770 100644 --- a/atlas/atlasRoutes.py +++ b/atlas/atlasRoutes.py @@ -158,6 +158,13 @@ def indexMedias(image): ) +def get_territory_mailles_obs(connection): + current_app.logger.debug("start AFFICHAGE_TERRITORY") + observations = vmObservationsMaillesRepository.territoryObservationsMailles(connection) + current_app.logger.debug("end AFFICHAGE_TERRITORY") + return observations + + @main.route("/", methods=["GET", "POST"]) def index(): session = db.session @@ -180,6 +187,8 @@ def index(): current_app.config["ATTR_MAIN_PHOTO"], ) current_app.logger.debug("end AFFICHAGE_PRECIS") + elif current_app.config["AFFICHAGE_TERRITOIRE_OBS"]: + observations = get_territory_mailles_obs(connection) else: observations = [] @@ -204,11 +213,13 @@ def index(): else: lastDiscoveries = [] + listTaxons = vmTaxonsRepository.getTaxonsTerritory(connection) connection.close() session.close() return render_template( "templates/home/_main.html", + listTaxons=listTaxons, observations=observations, mostViewTaxon=mostViewTaxon, customStatMedias=customStatMedias, diff --git a/atlas/modeles/repositories/vmObservationsMaillesRepository.py b/atlas/modeles/repositories/vmObservationsMaillesRepository.py index 58b65a42..45a45afc 100644 --- a/atlas/modeles/repositories/vmObservationsMaillesRepository.py +++ b/atlas/modeles/repositories/vmObservationsMaillesRepository.py @@ -5,9 +5,65 @@ from atlas.modeles.entities.vmObservations import VmObservationsMailles from atlas.modeles.entities.tMaillesTerritoire import TMaillesTerritoire +from atlas.modeles.entities.vmTaxons import VmTaxons from atlas.modeles.utils import deleteAccent, findPath +def getObservationsMaillesTerritorySpecies(session, cd_ref): + """ + Retourne les mailles et le nombre d'observation par maille pour un taxon et ses enfants + sous forme d'un geojson + """ + query = func.atlas.find_all_taxons_childs(cd_ref) + taxons_ids = session.scalars(query).all() + taxons_ids.append(cd_ref) + + query = ( + session.query( + VmObservationsMailles.id_maille, + TMaillesTerritoire.geojson_maille, + func.max(VmObservationsMailles.annee).label("last_obs_year"), + func.sum(VmObservationsMailles.nbr).label("obs_nbr"), + VmObservationsMailles.type_code, + VmTaxons.cd_ref, + VmTaxons.nom_vern, + VmTaxons.lb_nom, + ) + .join( + TMaillesTerritoire, + TMaillesTerritoire.id_maille == VmObservationsMailles.id_maille, + ) + .join( + VmTaxons, + VmTaxons.cd_ref == VmObservationsMailles.cd_ref, + ) + .filter(VmObservationsMailles.cd_ref == any_(taxons_ids)) + .group_by( + VmObservationsMailles.id_maille, + TMaillesTerritoire.geojson_maille, + VmObservationsMailles.type_code, + VmTaxons.cd_ref, + VmTaxons.nom_vern, + VmTaxons.lb_nom, + ) + ) + + return FeatureCollection( + [ + Feature( + id=o.id_maille, + geojson_maille=json.loads(o.geojson_maille), + id_maille=o.id_maille, + type_code=o.type_code, + nb_observations=int(o.obs_nbr), + last_observation=o.last_obs_year, + cd_ref=o.cd_ref, + taxon=format_taxon_name(o), + ) + for o in query.all() + ] + ) + def format_taxon_name(observation): if observation.nom_vern: inter = observation.nom_vern.split(",") @@ -65,6 +121,47 @@ def getObservationsMaillesChilds(session, cd_ref, year_min=None, year_max=None): ) +def territoryObservationsMailles(connection): + sql = """ +SELECT obs.cd_ref, obs.id_maille, obs.nbr,-- obs.annee, obs.id_observations, + tax.lb_nom, tax.nom_vern, tax.group2_inpn, + medias.url, medias.chemin, medias.id_media, + m.geojson_4326 AS geom, + m.type_code +FROM atlas.vm_observations_mailles obs + JOIN atlas.vm_taxons tax ON tax.cd_ref = obs.cd_ref + JOIN (SELECT DISTINCT id_area, geojson_4326, type_code from atlas.vm_cor_area_synthese) m ON m.id_area=obs.id_maille + LEFT JOIN atlas.vm_medias medias + ON medias.cd_ref = obs.cd_ref AND medias.id_type = 1 + GROUP BY obs.cd_ref, obs.id_maille, obs.nbr, + tax.lb_nom, tax.nom_vern, tax.group2_inpn, + medias.url, medias.chemin, medias.id_media, + m.geojson_4326, + m.type_code + """ + + observations = connection.execute(text(sql)) + obsList = list() + for o in observations: + if o.nom_vern: + inter = o.nom_vern.split(",") + taxon = inter[0] + " | " + o.lb_nom + "" + else: + taxon = "" + o.lb_nom + "" + temp = { + "id_maille": o.id_maille, + "type_code": o.type_code, + "cd_ref": o.cd_ref, + "nb_observations": o.nbr, + "taxon": taxon, + "geojson_maille": json.loads(o.geom), + "group2_inpn": deleteAccent(o.group2_inpn), + "pathImg": findPath(o), + } + obsList.append(temp) + return obsList + + # last observation for index.html def lastObservationsMailles(connection, mylimit, idPhoto): sql = """ diff --git a/atlas/modeles/repositories/vmTaxonsRepository.py b/atlas/modeles/repositories/vmTaxonsRepository.py index 664d88f1..ce1fe3ab 100644 --- a/atlas/modeles/repositories/vmTaxonsRepository.py +++ b/atlas/modeles/repositories/vmTaxonsRepository.py @@ -6,6 +6,43 @@ from atlas.modeles import utils +def getTaxonsTerritory(connection): + sql = """ + SELECT DISTINCT + o.cd_ref, max(date_part('year'::text, o.dateobs)) as last_obs, + COUNT(o.id_observation) AS nb_obs, t.nom_complet_html, t.nom_vern, + t.group2_inpn, t.patrimonial, t.protection_stricte, + m.url, m.chemin, m.id_media + FROM atlas.vm_observations o + JOIN atlas.vm_taxons t ON t.cd_ref=o.cd_ref + LEFT JOIN atlas.vm_medias m ON m.cd_ref=o.cd_ref AND m.id_type={} + GROUP BY o.cd_ref, t.nom_vern, t.nom_complet_html, t.group2_inpn, + t.patrimonial, t.protection_stricte, m.url, m.chemin, m.id_media + ORDER BY nb_obs DESC + """.format( + current_app.config["ATTR_MAIN_PHOTO"] + ) + req = connection.execute(text(sql)) + taxonCommunesList = list() + nbObsTotal = 0 + for r in req: + temp = { + "nom_complet_html": r.nom_complet_html, + "nb_obs": r.nb_obs, + "nom_vern": r.nom_vern, + "cd_ref": r.cd_ref, + "last_obs": r.last_obs, + "group2_inpn": utils.deleteAccent(r.group2_inpn), + "patrimonial": r.patrimonial, + "protection_stricte": r.protection_stricte, + "path": utils.findPath(r), + "id_media": r.id_media, + } + taxonCommunesList.append(temp) + nbObsTotal = nbObsTotal + r.nb_obs + return {"taxons": taxonCommunesList, "nbObsTotal": nbObsTotal} + + # With distinct the result in a array not an object, 0: lb_nom, 1: nom_vern def getTaxonsCommunes(connection, insee): sql = """ diff --git a/atlas/static/mapAreas.js b/atlas/static/mapAreas.js index dced16dc..58abbd6b 100644 --- a/atlas/static/mapAreas.js +++ b/atlas/static/mapAreas.js @@ -113,31 +113,31 @@ function displayObsGridBaseUrl() { // display observation on click function displayObsTaxon(insee, cd_ref) { - $.ajax({ - url: - configuration.URL_APPLICATION + - "/api/observations/" + - insee + - "/" + - cd_ref, - dataType: "json", - beforeSend: function() { - $("#loadingGif").show(); - $("#loadingGif").attr( - "src", - configuration.URL_APPLICATION + "/static/images/loading.svg" - ); - } - }).done(function(observations) { - $("#loadingGif").hide(); - map.removeLayer(currentLayer); + $.ajax({ + url: + configuration.URL_APPLICATION + + "/api/observations/" + + insee + + "/" + + cd_ref, + dataType: "json", + beforeSend: function() { + $("#loadingGif").show(); + $("#loadingGif").attr( + "src", + configuration.URL_APPLICATION + "/static/images/loading.svg" + ); + } + }).done(function(observations) { + $("#loadingGif").hide(); + map.removeLayer(currentLayer); clearOverlays() - if (configuration.AFFICHAGE_MAILLE) { - displayMailleLayerLastObs(observations); - } else { - displayMarkerLayerPointCommune(observations); - } - }); + if (configuration.AFFICHAGE_MAILLE) { + displayMailleLayerLastObs(observations); + } else { + displayMarkerLayerPointCommune(observations); + } + }); } @@ -162,31 +162,29 @@ function displayObsTaxonMaille(areaCode, cd_ref) { }); } -function refreshObsArea() { - $("#taxonList ul").on("click", "#taxonListItem", function () { +function refreshObsArea(elem) { + $(this) + .siblings() + .removeClass("current"); + $(this).addClass("current"); + if (configuration.AFFICHAGE_MAILLE) { + displayObsTaxonMaille(elem.currentTarget.getAttribute("area-code"), elem.currentTarget.getAttribute("cdref")); + } else { + displayObsTaxon(elem.currentTarget.getAttribute("area-code"), elem.currentTarget.getAttribute("cdref")); + } + const name = elem.currentTarget.querySelector("#name").innerHTML; + $("#titleMap").fadeOut(500, function () { $(this) - .siblings() - .removeClass("current"); - $(this).addClass("current"); - if (configuration.AFFICHAGE_MAILLE) { - displayObsTaxonMaille($(this).attr("area-code"), $(this).attr("cdRef")); - } else { - displayObsTaxon($(this).attr("area-code"), $(this).attr("cdRef")); - } - var name = $(this) - .find("#name") - .html(); - $("#titleMap").fadeOut(500, function () { - $(this) - .html("Observations du taxon : " + name) - .fadeIn(500); - }); + .html("Observations du taxon : " + name) + .fadeIn(500); }); } $(document).ready(function () { $("#loaderSpinner").hide(); if (configuration.INTERACTIVE_MAP_LIST) { - refreshObsArea(); + $("#taxonList ul").on("click", "#taxonListItem", elem => { + refreshObsArea(elem); + }); } }); diff --git a/atlas/static/mapHome.js b/atlas/static/mapHome.js index b2b56204..1540fb99 100644 --- a/atlas/static/mapHome.js +++ b/atlas/static/mapHome.js @@ -15,7 +15,7 @@ $('#map').click(function(){ $(function(){ - if (configuration.AFFICHAGE_MAILLE){ + if (configuration.AFFICHAGE_MAILLE || configuration.AFFICHAGE_TERRITOIRE_OBS){ // display maille layer displayMailleLayerLastObs(observations); @@ -71,6 +71,51 @@ $(function(){ }); +function displayObsTaxonMaille(cd_ref) { + $.ajax({ + url: `${configuration.URL_APPLICATION}/api/observations/${cd_ref}`, + dataType: "json", + beforeSend: function () { + $("#loaderSpinner").show(); + } + }).done(function (observations) { + $("#loaderSpinner").hide(); + map.removeLayer(currentLayer); + clearOverlays() + const geojsonMaille = generateGeoJsonMailleLastObs(observations, true); + + displayMailleLayerFicheEspece(geojsonMaille); + }); +} + +function refreshTerritoryArea(elem) { + $(this) + .siblings() + .removeClass("current"); + $(this).addClass("current"); + if (configuration.AFFICHAGE_TERRITOIRE_OBS) { + displayObsTaxonMaille(elem.currentTarget.getAttribute("cdref")); + } + const name = $(this) + .find("#name") + .html(); + $("#titleMap").fadeOut(500, function () { + $(this) + .html("Observations du taxon : " + name) + .fadeIn(500); + }); +} + +$(document).ready(function () { + $("#loaderSpinner").hide(); + if (configuration.INTERACTIVE_MAP_LIST) { + $("#taxonList").on("click", "#taxonListItem", function (elem) { + refreshTerritoryArea(elem); + }); + } +}); + + // Generate legends and check configuration to choose which to display (Maille ou Point) htmlLegendMaille = "       Maille comportant au moins une observation

" + diff --git a/atlas/templates/home/_main.html b/atlas/templates/home/_main.html index 3c8c4b5b..971cd41a 100644 --- a/atlas/templates/home/_main.html +++ b/atlas/templates/home/_main.html @@ -60,6 +60,11 @@ {% include 'templates/home/lastObs.html' %} {% endif %} + {% if configuration.AFFICHAGE_TERRITOIRE_OBS %} + + {% include 'templates/home/territory.html' %} + {% endif %} + {% if configuration.AFFICHAGE_NOUVELLES_ESPECES %} {% include 'templates/home/newSpecies.html' %} diff --git a/atlas/templates/home/territory.html b/atlas/templates/home/territory.html new file mode 100644 index 00000000..4dfac5b7 --- /dev/null +++ b/atlas/templates/home/territory.html @@ -0,0 +1,27 @@ +{% block territory_obs %} + {% block additionalHeaderAssets %} + + + {% endblock %} + +
+
+
+

+ {{ configuration.TEXT_SPECIES_OBS }} {{ listTaxons['taxons'] | length }} + {{ 'espèces' if listTaxons | length > 1 else 'espèce' }} +

+
+
+ +
+
+
+
+ {% include 'templates/core/listTaxons.html' %} +
+ +
+
+
+{% endblock %} diff --git a/docs/changelog.rst b/docs/changelog.rst index 1cb38c87..bc180139 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -9,6 +9,7 @@ CHANGELOG - Ajout du lien "Données personelles" dans le pied de page (#527 @juggler31) - Suppression du support des installations sans TaxHub +- Ajout d'une carte territoire dans la page d'acceuil ainsi que la liste de toutes les espèces sur celui-ci. 🐛 **Corrections**