diff --git a/.gitignore b/.gitignore index 31d2e625f..f19052022 100644 --- a/.gitignore +++ b/.gitignore @@ -39,6 +39,7 @@ atlas/static/custom/templates/footer.html atlas/static/custom/templates/introduction.html atlas/static/custom/templates/credits.html atlas/static/custom/templates/mentions-legales.html +atlas/static/custom/templates/areas.html data/ref/emprise_territoire.* data/ref/communes.dbf diff --git a/atlas/atlasAPI.py b/atlas/atlasAPI.py index 8f0c478ef..80505abea 100644 --- a/atlas/atlasAPI.py +++ b/atlas/atlasAPI.py @@ -9,6 +9,7 @@ vmObservationsMaillesRepository, vmMedias, vmCommunesRepository, + vmAreasRepository, ) api = Blueprint("api", __name__) @@ -33,6 +34,41 @@ def searchCommuneAPI(): session.close() return jsonify(results) + +@api.route("/area", methods=["GET"]) +def search_area(): + """ + Enables to filter areas on their name or code + """ + session = utils.loadSession() + search = request.args.get("search") + type_code = request.args.get("type") + limit = request.args.get("limit", 50) + results = vmAreasRepository.search_area_by_type(session=session, + search=search, + type_code=type_code, + filter_type_codes=current_app.config['AREAS_LIST'], + limit=limit) + session.close() + return jsonify(results) + + +@api.route("/area/geom", methods=["GET"]) +def get_areas_geom(): + """ + Returns the geometries of areas + """ + session = utils.loadSession() + limit = request.args.get("limit", 50) + type_code = request.args.get("type") + results = vmAreasRepository.get_areas_geometries(session=session, + type_code=type_code, + filter_type_codes=current_app.config['AREAS_LIST'], + limit=limit) + session.close() + return jsonify(results) + + if not current_app.config['AFFICHAGE_MAILLE']: @api.route("/observationsMailleAndPoint/", methods=["GET"]) def getObservationsMailleAndPointAPI(cd_ref): @@ -104,23 +140,25 @@ def getObservationsGenericApi(cd_ref: int): if not current_app.config['AFFICHAGE_MAILLE']: - @api.route("/observations//", methods=["GET"]) - def getObservationsCommuneTaxonAPI(insee, cd_ref): - connection = utils.engine.connect() - observations = vmObservationsRepository.getObservationTaxonCommune( - connection, insee, cd_ref + @api.route("/observations//", methods=["GET"]) + def getObservationsCommuneTaxonAPI(area_code, cd_ref): + session = utils.loadSession() + # Use generic area function to get every type of area + observations = vmAreasRepository.get_areas_observations_by_cd_ref( + session, area_code, cd_ref ) - connection.close() + session.close() return jsonify(observations) -@api.route("/observationsMaille//", methods=["GET"]) -def getObservationsCommuneTaxonMailleAPI(insee, cd_ref): - connection = utils.engine.connect() - observations = vmObservationsMaillesRepository.getObservationsTaxonCommuneMaille( - connection, insee, cd_ref +@api.route("/observationsMaille//", methods=["GET"]) +def getObservationsCommuneTaxonMailleAPI(area_code, cd_ref): + session = utils.loadSession() + # Use generic area function to get every type of area + observations = vmAreasRepository.get_areas_grid_observations_by_cd_ref( + session, area_code, cd_ref ) - connection.close() + session.close() return jsonify(observations) @@ -158,4 +196,4 @@ def test(): current_app.config["ATTR_OTHER_PHOTO"], ) connection.close() - return jsonify(photos) \ No newline at end of file + return jsonify(photos) diff --git a/atlas/atlasRoutes.py b/atlas/atlasRoutes.py index 34179127a..5c8d60e67 100644 --- a/atlas/atlasRoutes.py +++ b/atlas/atlasRoutes.py @@ -20,6 +20,7 @@ from atlas.env import config from atlas.modeles.entities import vmTaxons, vmCommunes from atlas.modeles.repositories import ( + vmAreasRepository, vmOrganismsRepository, vmTaxonsRepository, vmObservationsRepository, @@ -204,7 +205,11 @@ def index(): if current_app.config["AFFICHAGE_STAT_GLOBALES"]: stat = vmObservationsRepository.statIndex(connection) else: - stat = [] + stat = {} + + if current_app.config["GLOBAL_GEO_STATS"]: + area_types = [geo["TYPE"] for geo in current_app.config["GLOBAL_GEO_STATS"]] + stat['geo'] = vmAreasRepository.stats(session, area_types) if current_app.config["AFFICHAGE_RANG_STAT"]: current_app.logger.debug("start customStat") @@ -352,6 +357,45 @@ def ficheCommune(insee): ) +@main.route("/area/", methods=["GET"]) +def area_sheet(id_area): + """ + Generates the AreaSheet html + """ + session = utils.loadSession() + + listTaxons = vmAreasRepository.get_area_taxa(session, id_area=id_area) + area = vmAreasRepository.get_area_from_id(session, id_area=id_area) + if current_app.config["AFFICHAGE_MAILLE"]: + observations = vmAreasRepository.last_observations_area_maille( + session, current_app.config["NB_LAST_OBS"], id_area + ) + else: + observations = vmAreasRepository.get_areas_observations( + session, current_app.config["NB_LAST_OBS"], id_area + ) + + surroundingAreas = vmAreasRepository.get_surrounding_areas(session=session, + id_area=id_area, + filter_type_codes=current_app.config['AREAS_LIST']) + + observers = vmAreasRepository.get_observers_area(session, id_area=id_area) + + session.close() + + return render_template( + "templates/areaSheet/_main.html", + sheetType="area", + surroundingAreas=surroundingAreas, + listTaxons=listTaxons, + areaInfos=area, + observations=observations, + observers=observers, + DISPLAY_EYE_ON_LIST=True, + insee=id_area, + ) + + @main.route("/liste/", methods=["GET", "POST"]) def ficheRangTaxonomie(cd_ref): session = utils.loadSession() diff --git a/atlas/configuration/config_schema.py b/atlas/configuration/config_schema.py index c81435deb..d9d803f41 100644 --- a/atlas/configuration/config_schema.py +++ b/atlas/configuration/config_schema.py @@ -112,6 +112,11 @@ class MapConfig(Schema): load_default={"fill": False, "fillColor": "#020202", "fillOpacity": 0.3} ) +class GeoStat(Schema): + NAME = fields.String() + TYPE = fields.String() + PICTO = fields.String() + class AtlasConfig(Schema): class Meta: @@ -131,6 +136,7 @@ class Meta: AFFICHAGE_LOGOS_HOME = fields.Boolean(load_default=True) AFFICHAGE_FOOTER = fields.Boolean(load_default=True) AFFICHAGE_STAT_GLOBALES = fields.Boolean(load_default=True) + GLOBAL_GEO_STATS = fields.List(fields.Nested(GeoStat), load_default=[]) AFFICHAGE_DERNIERES_OBS = fields.Boolean(load_default=True) AFFICHAGE_EN_CE_MOMENT = fields.Boolean(load_default=True) AFFICHAGE_RANG_STAT = fields.Boolean(load_default=True) @@ -209,6 +215,10 @@ class Meta: # (no need to restart the atlas service when updating templates) # Defaults to False to have the best performance in production TEMPLATES_AUTO_RELOAD = fields.Boolean(load_default=False) + # Enable the search on other areas + EXTENDED_AREAS = fields.Boolean(load_default=False) + # Restricts the search (/area) and the /area/geom API + AREAS_LIST = fields.List(fields.String, load_default=[]) @validates_schema def validate_url_taxhub(self, data, **kwargs): diff --git a/atlas/messages.pot b/atlas/messages.pot index e8a6e205e..9f3202e58 100644 --- a/atlas/messages.pot +++ b/atlas/messages.pot @@ -1,14 +1,14 @@ # Translations template for PROJECT. -# Copyright (C) 2021 ORGANIZATION +# Copyright (C) 2022 ORGANIZATION # This file is distributed under the same license as the PROJECT project. -# FIRST AUTHOR , 2021. +# FIRST AUTHOR , 2022. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2021-12-02 15:28+0100\n" +"POT-Creation-Date: 2022-10-11 15:29+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -164,10 +164,14 @@ msgstr "" msgid "check.species.sheet" msgstr "" -#: templates/core/extended_areas_search.html:13 +#: templates/core/extended_areas_search.html:12 msgid "search.other.zones.type" msgstr "" +#: templates/core/extended_areas_search.html:23 +msgid "search" +msgstr "" + #: templates/core/listTaxons.html:14 msgid "filter.species" msgstr "" @@ -201,12 +205,12 @@ msgstr "" msgid "loading" msgstr "" -#: templates/core/navbar.html:34 templates/home/globalStats.html:28 +#: templates/core/navbar.html:34 templates/home/globalStats.html:30 #: templates/photoGalery/_main.html:76 msgid "search.species" msgstr "" -#: templates/core/navbar.html:47 templates/home/globalStats.html:47 +#: templates/core/navbar.html:47 templates/home/globalStats.html:49 msgid "search.city" msgstr "" @@ -214,12 +218,12 @@ msgstr "" msgid "back.to.home" msgstr "" -#: templates/core/sideBar.html:25 templates/home/globalStats.html:59 +#: templates/core/sideBar.html:25 templates/home/globalStats.html:61 #: templates/photoGalery/_main.html:5 templates/photoGalery/_main.html:50 msgid "gallery.title" msgstr "" -#: templates/core/statHierarchy.html:12 templates/home/globalStats.html:21 +#: templates/core/statHierarchy.html:12 templates/home/globalStats.html:23 #: templates/home/taxoRank.html:28 templates/organismSheet/statsInfos.html:21 msgid "species" msgstr "" @@ -268,31 +272,35 @@ msgstr "" msgid "display.city.infos" msgstr "" +#: templates/home/geoStats.html:22 +msgid "search.for" +msgstr "" + #: templates/home/globalStats.html:4 msgid "home.insomefigures" msgstr "" -#: templates/home/globalStats.html:13 +#: templates/home/globalStats.html:14 msgid "home.seelatestobs" msgstr "" -#: templates/home/globalStats.html:39 templates/speciesSheet/map.html:20 +#: templates/home/globalStats.html:41 templates/speciesSheet/map.html:20 #: templates/speciesSheet/otherInformations.html:10 #: templates/speciesSheet/otherInformations.html:14 msgid "municipalities" msgstr "" -#: templates/home/globalStats.html:39 templates/speciesSheet/map.html:20 +#: templates/home/globalStats.html:41 templates/speciesSheet/map.html:20 #: templates/speciesSheet/otherInformations.html:10 #: templates/speciesSheet/otherInformations.html:14 msgid "municipality" msgstr "" -#: templates/home/globalStats.html:58 +#: templates/home/globalStats.html:60 msgid "photos" msgstr "" -#: templates/home/globalStats.html:58 +#: templates/home/globalStats.html:60 msgid "photo" msgstr "" diff --git a/atlas/modeles/entities/vmAreas.py b/atlas/modeles/entities/vmAreas.py index 765b3c9e2..ba2d3d0ec 100644 --- a/atlas/modeles/entities/vmAreas.py +++ b/atlas/modeles/entities/vmAreas.py @@ -47,16 +47,11 @@ class VmCorAreaObservation(Base): __table__ = Table( "vm_cor_area_observation", metadata, - Column("id_observation", Integer()), + Column("id_observation", Integer(), primary_key=True), Column("id_area", Integer()), schema="atlas", autoload=True, autoload_with=engine, extend_existing=True, - primary_key=False, ) - __mapper_args__ = {"primary_key": [__table__.c.id_observation, __table__.c.id_area]} - observation = relationship( - "VmObservations", foreign_keys=[__table__.c.id_observation] - ) - area = relationship("VmAreas", foreign_keys=[__table__.c.id_area]) + diff --git a/atlas/modeles/repositories/vmAreasRepository.py b/atlas/modeles/repositories/vmAreasRepository.py index ccef9bb4b..93491ce99 100644 --- a/atlas/modeles/repositories/vmAreasRepository.py +++ b/atlas/modeles/repositories/vmAreasRepository.py @@ -5,6 +5,7 @@ from datetime import datetime from flask import current_app +from geojson import Feature, FeatureCollection from sqlalchemy import or_, and_, case from sqlalchemy.sql.expression import func @@ -21,43 +22,44 @@ from atlas.modeles.entities.vmTaxref import VmTaxref -def area_types(session): - query = session.query( - VmBibAreasTypes.id_type, - VmBibAreasTypes.type_code, - VmBibAreasTypes.type_name, - VmBibAreasTypes.type_desc, - ) - return query.all() +def filter_by_type_codes(query, type_codes=[]): + if len(type_codes) > 0: + query = query.filter(VmBibAreasTypes.type_code.in_(type_codes)) + return query -def get_id_area(session, type_code, area_code): - try: - query = ( - session.query(VmAreas.id_area) - .join(VmBibAreasTypes, VmBibAreasTypes.id_type == VmAreas.id_type) - .filter( - and_( - VmAreas.area_code.ilike(area_code), - VmBibAreasTypes.type_code.ilike(type_code), - ) - ) +def get_area_from_id(session, id_area): + """ + Get area info from an id + """ + query = ( + session.query( + VmAreas.id_area, + VmAreas.area_name, + VmAreas.area_code, + VmAreas.area_geojson, + VmBibAreasTypes.type_name, ) - current_app.logger.debug(" query: {}".format(query)) - result = query.one() - return result.id_area - except Exception as e: - current_app.logger.error(" error {}".format(e)) + .filter(VmAreas.id_area == id_area) + .join(VmBibAreasTypes, VmBibAreasTypes.id_type == VmAreas.id_type) + ) + + result = query.first() + return { + "areaId": result.id_area, + "areaName": result.area_name, + "areaCode": str(result.area_code), + "areaGeoJson": json.loads(result.area_geojson), + "typeName": result.type_name, + } def last_observations_area_maille(session, myLimit, idArea): + """ + Gets the last observations for a specific area + """ q_last_obs = ( session.query( - # VmObservations.cd_ref.label("cd_ref"), - # VmObservations.dateobs.label("dateobs"), - # VmTaxons.lb_nom.label("lb_nom"), - # VmTaxons.nom_vern.label("nom_vern"), - # VmObservations.the_geom_point.label("the_geom_point"), VmObservations.cd_ref, VmObservations.dateobs, VmTaxons.lb_nom, @@ -85,9 +87,7 @@ def last_observations_area_maille(session, myLimit, idArea): q_last_obs.c.lb_nom, q_last_obs.c.cd_ref, q_last_obs.c.nom_vern, - func.st_asgeojson(TGrid.the_geom).label( - "geojson_maille" - ), + func.st_asgeojson(TGrid.the_geom).label("geojson_maille"), ) .join(q_last_obs, q_last_obs.c.the_geom_point.st_intersects(TGrid.the_geom)) .group_by( @@ -122,24 +122,22 @@ def last_observations_area_maille(session, myLimit, idArea): "id_maille": o.id_maille, } obsList.append(temp) - current_app.logger.debug( - " end loop: {}".format(datetime.now()) - ) + current_app.logger.debug(" end loop: {}".format(datetime.now())) return obsList -def get_observers_area(session, idArea): +def get_observers_area(session, id_area): q_list_observers = ( session.query( - func.trim( - func.unnest(func.string_to_array(VmObservations.observateurs, ",")) - ).label("observateurs") + func.trim(func.unnest(func.string_to_array(VmObservations.observateurs, ","))).label( + "observateurs" + ) ) .join( VmCorAreaObservation, VmObservations.id_observation == VmCorAreaObservation.id_observation, ) - .filter(VmCorAreaObservation.id_area == idArea) + .filter(VmCorAreaObservation.id_area == id_area) ).subquery() query = session.query(q_list_observers.c.observateurs).group_by( @@ -148,63 +146,133 @@ def get_observers_area(session, idArea): return query.all() -def search_area_by_type(session, search, type_code, limit=50): - query = ( - session.query( - VmAreas.area_code, - func.concat(VmAreas.area_name, " - [code ", VmAreas.area_code, "]"), - ) - .join(VmBibAreasTypes, VmBibAreasTypes.id_type == VmAreas.id_type) - .filter( - and_(VmBibAreasTypes.type_code == type_code), - ( - or_( - VmAreas.area_name.ilike("%" + search + "%"), - VmAreas.area_code.ilike("%" + search + "%"), - ) - ), +def search_area_by_type(session, search=None, type_code=None, filter_type_codes=[], limit=50): + """ + Filter out the areas by the provided params: + + Args: + session: the db session + search (str): to be able to filter against the name and the area_code + filter_type_codes (list): to exclude area codes + limit (int): restricts the number of objects returns + """ + query = session.query( + VmAreas.id_area, + VmBibAreasTypes.type_name, + VmAreas.area_code, + func.concat("(", VmBibAreasTypes.type_name, ") ", VmAreas.area_name), + ).join(VmBibAreasTypes, VmBibAreasTypes.id_type == VmAreas.id_type) + + if search is not None: + search = search.lower() + query = query.filter( + or_( + VmAreas.area_name.ilike("%" + search + "%"), + VmAreas.area_code.ilike("%" + search + "%"), + ) ) - ) - print(limit) + + if type_code is not None: + query = filter_by_type_codes(query, type_codes=[type_code]) + else: + query = filter_by_type_codes(query, type_codes=filter_type_codes) + query = query.limit(limit) current_app.logger.debug(" query {}".format(query)) - - areaList = list() + areaList = [] for r in query.all(): - temp = {"label": r[1], "value": r[0]} + temp = {"type_name": r.type_name, "label": r[-1], "value": r.id_area} areaList.append(temp) return areaList -def get_areas_observations(session, id_area): +def get_areas_geometries(session, type_code=None, filter_type_codes=[], limit=50): + """ + Returns a Feature collection of all the areas + + Args: + session: the db session + type_code (str): filter out by a type_code + filter_type_codes (list): ignores the codes provided in this list + limit (int): restricts the number of objects returns + + Returns: + FeatureCollection: the geometries as geojson + """ + query = session.query( + VmAreas.area_name, + VmAreas.id_area, + VmAreas.area_geojson, + VmAreas.area_code, + VmBibAreasTypes.type_code, + VmBibAreasTypes.type_name, + ).join(VmBibAreasTypes, VmBibAreasTypes.id_type == VmAreas.id_type) + if type_code is not None: + filter_type_codes.append(type_code) + + query = filter_by_type_codes(query, type_codes=filter_type_codes) + + query = query.order_by(VmBibAreasTypes.type_code).limit(limit) + return FeatureCollection( + [ + Feature( + id=r.id_area, + geometry=json.loads(r.area_geojson), + properties={ + "id_area": r.id_area, + "area_name": r.area_name, + "area_code": r.area_code, + "type_code": r.type_code, + "type_name": r.type_name, + }, + ) + for r in query.all() + ] + ) + + +def get_areas_observations(session, limit, id_area): + """ + For a provided area_code and cd_ref, computes the observations in + this area + """ query = ( - session.query( - VmObservations.id_observation, - VmTaxref.nom_vern, - VmTaxref.lb_nom, - VmTaxref.group2_inpn, - VmObservations.dateobs, - VmObservations.observateurs, - func.st_asgeojson(VmObservations.the_geom_point).label("geometry"), - ) - .join(VmTaxref, VmTaxref.cd_nom == VmObservations.cd_ref) - .join( - VmCorAreaObservation, - VmObservations.id_observation == VmCorAreaObservation.id_observation, + ( + session.query( + VmObservations.id_observation, + VmObservations.diffusion_level, + VmTaxref.nom_vern, + VmTaxref.lb_nom, + VmTaxref.group2_inpn, + VmObservations.dateobs, + VmObservations.observateurs, + func.st_asgeojson(VmObservations.the_geom_point).label("geometry"), + ) + .join(VmTaxref, VmTaxref.cd_nom == VmObservations.cd_ref) + .join( + VmCorAreaObservation, + VmObservations.id_observation == VmCorAreaObservation.id_observation, + ) + .filter(VmCorAreaObservation.id_area == id_area) ) - .filter(VmCorAreaObservation.id_area == id_area) - ).all() + .limit(limit) + .all() + ) result = [] for r in query: temp = r._asdict() - temp["geometry"] = json.loads(r.geometry or "{}") + temp["geojson_point"] = json.loads(r.geometry or "{}") temp["dateobs"] = str(r.dateobs) temp["group2_inpn"] = utils.deleteAccent(r.group2_inpn) result.append(temp) return result -def get_areas_observations_by_cdnom(session, id_area): +def get_areas_observations_by_cd_ref(session, area_code, cd_ref): + """ + For a provided area_code and cd_ref, computes grid observations in + this area + """ req = ( session.query( VmObservations.id_observation, @@ -220,36 +288,37 @@ def get_areas_observations_by_cdnom(session, id_area): VmCorAreaObservation, VmObservations.id_observation == VmCorAreaObservation.id_observation, ) - .filter(VmCorAreaObservation.id_area == id_area) + .join(VmAreas, VmAreas.id_area == VmCorAreaObservation.id_area) + .filter(VmAreas.area_code == area_code, VmObservations.cd_ref == cd_ref) ).all() result = [] for r in req: temp = r._asdict() - temp["geometry"] = json.loads(r.geometry or "{}") + temp["geojson_point"] = json.loads(r.geometry or "{}") temp["dateobs"] = str(r.dateobs) temp["group2_inpn"] = utils.deleteAccent(r.group2_inpn) result.append(temp) return result -def get_areas_grid_observations_by_cdnom(session, id_area, cd_nom): +def get_areas_grid_observations_by_cd_ref(session, area_code, cd_ref): + """ + For a provided area_code and cd_ref, computes the observations in + this area + """ query = ( session.query( TGrid.id_maille, func.extract("year", VmObservations.dateobs).label("annee"), - func.st_asgeojson(TGrid.the_geom, 4326).label( - "geojson_maille" - ), + func.st_asgeojson(TGrid.the_geom, 4326).label("geojson_maille"), ) .join(VmAreas, VmAreas.the_geom.st_intersects(VmObservations.the_geom_point)) .join(TGrid, TGrid.the_geom.st_intersects(VmObservations.the_geom_point)) - .filter(and_(VmObservations.cd_ref == cd_nom, VmAreas.area_code == id_area)) + .filter(and_(VmObservations.cd_ref == cd_ref, VmAreas.area_code == area_code)) .order_by(TGrid.id_maille) ) - current_app.logger.debug( - " QUERY: {}".format(query) - ) + current_app.logger.debug(" QUERY: {}".format(query)) tabObs = list() for o in query.all(): temp = { @@ -264,6 +333,13 @@ def get_areas_grid_observations_by_cdnom(session, id_area, cd_nom): def get_area_taxa(session, id_area): + """ + Returns the list of taxa observed in the area defined by id_area + + Args: + session: the db session + id_area (int): the id of the area + """ query = ( session.query( VmTaxons.cd_ref, @@ -316,9 +392,18 @@ def get_area_taxa(session, id_area): return {"taxons": result, "nbObsTotal": nbObsTotal} -def get_surrounding_areas(session, id_area): +def get_surrounding_areas(session, id_area, filter_type_codes=[]): + """ + Returns the areas around the given id_area + + Args: + session: the db session + id_area (int): the id of the area + """ subquery = ( - session.query(VmAreas.the_geom).filter(VmAreas.id_area == id_area).subquery() + session.query(VmAreas.id_type, VmAreas.the_geom) + .filter(VmAreas.id_area == id_area) + .subquery() ) query = ( @@ -330,7 +415,32 @@ def get_surrounding_areas(session, id_area): VmBibAreasTypes.type_name, ) .join(VmBibAreasTypes, VmAreas.id_type == VmBibAreasTypes.id_type) - .filter(and_(VmAreas.the_geom.st_intersects(subquery.c.the_geom))) + .filter( + and_( + VmAreas.id_area != id_area, + VmAreas.the_geom.st_intersects(subquery.c.the_geom.st_buffer(0)), + ) + ) ) + query = filter_by_type_codes(query, type_codes=filter_type_codes) return query.all() + + +def stats(session, type_codes): + """ + Return the total number of area for each type_code provided + + Args: + session: the db session + type_codes (list): list of strings of each type code + """ + sums = [] + for type_code in type_codes: + # Use a case to be able to select a sum of each type + sums.append( + func.sum(case((VmBibAreasTypes.type_code == type_code, 1), else_=0)).label(type_code) + ) + + query = session.query(*sums).join(VmAreas, VmBibAreasTypes.id_type == VmAreas.id_type) + return query.first()._asdict() diff --git a/atlas/static/custom/templates/areas.html.sample b/atlas/static/custom/templates/areas.html.sample new file mode 100644 index 000000000..49741a486 --- /dev/null +++ b/atlas/static/custom/templates/areas.html.sample @@ -0,0 +1,141 @@ +{% extends "templates/core/layout.html" %} {% block title %} {{ +_('atlas.presentation') }} {% endblock %} {% block additionalHeaderAssets %} + +{% endblock %} {% block content %} +
+
+

Zones

+
+
+
+
+
+
+
+
+ Loading... +
+
+
+
+
+
+
+ +{% endblock %} {% block additionalFooterAssets %} + + +{% endblock %} diff --git a/atlas/static/main.js b/atlas/static/main.js index 92fb2f89f..2d0edc660 100644 --- a/atlas/static/main.js +++ b/atlas/static/main.js @@ -23,7 +23,7 @@ if (window.innerWidth <= 800 && presentationText) { presentationText.hidden = true; } -autocompleteSearch = function(inputID, urlDestination, nbProposal) { +autocompleteSearch = function(inputID, urlDestination, nbProposal, type) { $(inputID).autocomplete({ source: function(request, response) { var searchUrl; @@ -33,7 +33,7 @@ autocompleteSearch = function(inputID, urlDestination, nbProposal) { searchUrl = "/api/searchCommune"; } else { - searchUrl = "/api/searchArea/"+urlDestination; + searchUrl = "/api/area"; } $(inputID) .attr("loading", "true") @@ -45,7 +45,7 @@ autocompleteSearch = function(inputID, urlDestination, nbProposal) { ); $.get( configuration.URL_APPLICATION + searchUrl, - { search: request.term, limit: nbProposal }, + { search: request.term, limit: nbProposal, type: type }, function(results) { response(results.slice(0, nbProposal)); $(inputID) @@ -95,7 +95,6 @@ $("#searchCommunesStat").focus(function() { autocompleteSearch("#searchCommunesStat", "commune", 10); }); - // child list display var childList = $("#childList"); $("#buttonChild").click(function() { diff --git a/atlas/static/mapAreas.js b/atlas/static/mapAreas.js index 66e00b73f..f859125c7 100644 --- a/atlas/static/mapAreas.js +++ b/atlas/static/mapAreas.js @@ -102,11 +102,7 @@ function displayObsPreciseBaseUrl(areaCode, cd_ref) { } function displayObsGridBaseUrl() { - if (sheetType === 'commune') { - return configuration.URL_APPLICATION + "/api/observationsMaille/" - } else { - return configuration.URL_APPLICATION + "/api/observationsMaille/area/" - } + return configuration.URL_APPLICATION + "/api/observationsMaille/" } // display observation on click diff --git a/atlas/templates/areaSheet/surrounding_areas.html b/atlas/templates/areaSheet/surrounding_areas.html index 4244e0d32..f6d8b9ce5 100644 --- a/atlas/templates/areaSheet/surrounding_areas.html +++ b/atlas/templates/areaSheet/surrounding_areas.html @@ -16,10 +16,10 @@ #}
    {% for area in surroundingAreas %} -
  • +
  • {{ area.type_name }}
    {{ area.area_name }} - + {{ _('check.area.sheet') }}
  • diff --git a/atlas/templates/core/extended_areas_search.html b/atlas/templates/core/extended_areas_search.html index 10d9312d0..f4f610dfe 100644 --- a/atlas/templates/core/extended_areas_search.html +++ b/atlas/templates/core/extended_areas_search.html @@ -9,36 +9,32 @@ +{% endblock %} +{% block additionalFooterAssets %} + {% endblock %} \ No newline at end of file diff --git a/atlas/templates/core/listTaxons.html b/atlas/templates/core/listTaxons.html index 031b613a1..f5a2451f1 100644 --- a/atlas/templates/core/listTaxons.html +++ b/atlas/templates/core/listTaxons.html @@ -18,7 +18,7 @@
      {% for taxon in listTaxons.taxons %} -
    • {{ taxon.group2_inpn }} diff --git a/atlas/templates/home/geoStats.html b/atlas/templates/home/geoStats.html new file mode 100644 index 000000000..7a793bb4c --- /dev/null +++ b/atlas/templates/home/geoStats.html @@ -0,0 +1,40 @@ +{% block geoStats %} +{% for geo in configuration.GLOBAL_GEO_STATS %} +
      +
      + +

      {{ stat.geo[geo.TYPE] | pretty }}

      +

      {{ geo.NAME }}

      + +
      +
      +{% endfor %} +{% endblock %} + +{% block additionalFooterAssets %} + +{% endblock %} diff --git a/atlas/templates/home/globalStats.html b/atlas/templates/home/globalStats.html index cc054d5e0..76767b034 100644 --- a/atlas/templates/home/globalStats.html +++ b/atlas/templates/home/globalStats.html @@ -61,6 +61,7 @@

      {{ _('gallery.title') }}

    + {% include 'templates/home/geoStats.html' %} diff --git a/atlas/translations/en/LC_MESSAGES/messages.mo b/atlas/translations/en/LC_MESSAGES/messages.mo index e015369d1..8c723e674 100644 Binary files a/atlas/translations/en/LC_MESSAGES/messages.mo and b/atlas/translations/en/LC_MESSAGES/messages.mo differ diff --git a/atlas/translations/en/LC_MESSAGES/messages.po b/atlas/translations/en/LC_MESSAGES/messages.po index 5491365ed..0b434f608 100644 --- a/atlas/translations/en/LC_MESSAGES/messages.po +++ b/atlas/translations/en/LC_MESSAGES/messages.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2021-12-02 15:28+0100\n" +"POT-Creation-Date: 2022-10-11 15:29+0200\n" "PO-Revision-Date: 2021-07-12 12:12+0200\n" "Last-Translator: FULL NAME \n" "Language: en\n" @@ -174,10 +174,14 @@ msgstr "Species sheet" msgid "check.species.sheet" msgstr "View species sheet" -#: templates/core/extended_areas_search.html:13 +#: templates/core/extended_areas_search.html:12 msgid "search.other.zones.type" msgstr "Search other area type" +#: templates/core/extended_areas_search.html:23 +msgid "search" +msgstr "Search" + #: templates/core/listTaxons.html:14 msgid "filter.species" msgstr "Filter species" @@ -211,12 +215,12 @@ msgstr "Latest observations within" msgid "loading" msgstr "Loading..." -#: templates/core/navbar.html:34 templates/home/globalStats.html:28 +#: templates/core/navbar.html:34 templates/home/globalStats.html:30 #: templates/photoGalery/_main.html:76 msgid "search.species" msgstr "Search by species" -#: templates/core/navbar.html:47 templates/home/globalStats.html:47 +#: templates/core/navbar.html:47 templates/home/globalStats.html:49 msgid "search.city" msgstr "Search by municipality" @@ -224,12 +228,12 @@ msgstr "Search by municipality" msgid "back.to.home" msgstr "Back home" -#: templates/core/sideBar.html:25 templates/home/globalStats.html:59 +#: templates/core/sideBar.html:25 templates/home/globalStats.html:61 #: templates/photoGalery/_main.html:5 templates/photoGalery/_main.html:50 msgid "gallery.title" msgstr "Photos gallery" -#: templates/core/statHierarchy.html:12 templates/home/globalStats.html:21 +#: templates/core/statHierarchy.html:12 templates/home/globalStats.html:23 #: templates/home/taxoRank.html:28 templates/organismSheet/statsInfos.html:21 msgid "species" msgstr "Species" @@ -278,31 +282,35 @@ msgstr "This taxon has a protected status" msgid "display.city.infos" msgstr "Display municipality information" +#: templates/home/geoStats.html:22= +msgid "search.for" +msgstr "Search for" + #: templates/home/globalStats.html:4 msgid "home.insomefigures" msgstr "In some figures" -#: templates/home/globalStats.html:13 +#: templates/home/globalStats.html:14 msgid "home.seelatestobs" msgstr "See latest observations" -#: templates/home/globalStats.html:39 templates/speciesSheet/map.html:20 +#: templates/home/globalStats.html:41 templates/speciesSheet/map.html:20 #: templates/speciesSheet/otherInformations.html:10 #: templates/speciesSheet/otherInformations.html:14 msgid "municipalities" msgstr "Municipalities" -#: templates/home/globalStats.html:39 templates/speciesSheet/map.html:20 +#: templates/home/globalStats.html:41 templates/speciesSheet/map.html:20 #: templates/speciesSheet/otherInformations.html:10 #: templates/speciesSheet/otherInformations.html:14 msgid "municipality" msgstr "Municipality" -#: templates/home/globalStats.html:58 +#: templates/home/globalStats.html:60 msgid "photos" msgstr "Photos" -#: templates/home/globalStats.html:58 +#: templates/home/globalStats.html:60 msgid "photo" msgstr "Photo" diff --git a/atlas/translations/fr/LC_MESSAGES/messages.mo b/atlas/translations/fr/LC_MESSAGES/messages.mo index 5c7e65a2e..85add81e4 100644 Binary files a/atlas/translations/fr/LC_MESSAGES/messages.mo and b/atlas/translations/fr/LC_MESSAGES/messages.mo differ diff --git a/atlas/translations/fr/LC_MESSAGES/messages.po b/atlas/translations/fr/LC_MESSAGES/messages.po index 7c622a2b7..a062a9205 100644 --- a/atlas/translations/fr/LC_MESSAGES/messages.po +++ b/atlas/translations/fr/LC_MESSAGES/messages.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2021-12-02 15:28+0100\n" +"POT-Creation-Date: 2022-10-11 15:29+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language: fr\n" @@ -176,10 +176,14 @@ msgstr "Fiche espèce" msgid "check.species.sheet" msgstr "Voir la fiche espèce" -#: templates/core/extended_areas_search.html:13 +#: templates/core/extended_areas_search.html:12 msgid "search.other.zones.type" msgstr "Recherche par autre type de zones" +#: templates/core/extended_areas_search.html:23 +msgid "search" +msgstr "Recherche" + #: templates/core/listTaxons.html:14 msgid "filter.species" msgstr "Filtrer les espèces" @@ -213,12 +217,12 @@ msgstr "Dernière observation en " msgid "loading" msgstr "Chargement..." -#: templates/core/navbar.html:34 templates/home/globalStats.html:28 +#: templates/core/navbar.html:34 templates/home/globalStats.html:30 #: templates/photoGalery/_main.html:76 msgid "search.species" msgstr "Recherche par espèce" -#: templates/core/navbar.html:47 templates/home/globalStats.html:47 +#: templates/core/navbar.html:47 templates/home/globalStats.html:49 msgid "search.city" msgstr "Recherche par commune" @@ -226,12 +230,12 @@ msgstr "Recherche par commune" msgid "back.to.home" msgstr "Retour à l'accueil" -#: templates/core/sideBar.html:25 templates/home/globalStats.html:59 +#: templates/core/sideBar.html:25 templates/home/globalStats.html:61 #: templates/photoGalery/_main.html:5 templates/photoGalery/_main.html:50 msgid "gallery.title" msgstr "Galerie photos" -#: templates/core/statHierarchy.html:12 templates/home/globalStats.html:21 +#: templates/core/statHierarchy.html:12 templates/home/globalStats.html:23 #: templates/home/taxoRank.html:28 templates/organismSheet/statsInfos.html:21 msgid "species" msgstr "Espèces" @@ -280,31 +284,35 @@ msgstr "Ce taxon a un statut de protection" msgid "display.city.infos" msgstr "Afficher les informations de la commune" +#: templates/home/geoStats.html:22 +msgid "search.for" +msgstr "Recherche par" + #: templates/home/globalStats.html:4 msgid "home.insomefigures" msgstr "En quelques chiffres" -#: templates/home/globalStats.html:13 +#: templates/home/globalStats.html:14 msgid "home.seelatestobs" msgstr "Voir les dernières observations" -#: templates/home/globalStats.html:39 templates/speciesSheet/map.html:20 +#: templates/home/globalStats.html:41 templates/speciesSheet/map.html:20 #: templates/speciesSheet/otherInformations.html:10 #: templates/speciesSheet/otherInformations.html:14 msgid "municipalities" msgstr "Communes" -#: templates/home/globalStats.html:39 templates/speciesSheet/map.html:20 +#: templates/home/globalStats.html:41 templates/speciesSheet/map.html:20 #: templates/speciesSheet/otherInformations.html:10 #: templates/speciesSheet/otherInformations.html:14 msgid "municipality" msgstr "Commune" -#: templates/home/globalStats.html:58 +#: templates/home/globalStats.html:60 msgid "photos" msgstr "Photos" -#: templates/home/globalStats.html:58 +#: templates/home/globalStats.html:60 msgid "photo" msgstr "Photo" diff --git a/atlas/translations/it/LC_MESSAGES/messages.mo b/atlas/translations/it/LC_MESSAGES/messages.mo index 6acf44c7d..548dc741a 100644 Binary files a/atlas/translations/it/LC_MESSAGES/messages.mo and b/atlas/translations/it/LC_MESSAGES/messages.mo differ diff --git a/atlas/translations/it/LC_MESSAGES/messages.po b/atlas/translations/it/LC_MESSAGES/messages.po index 1e95e4b8b..bdb8d3238 100644 --- a/atlas/translations/it/LC_MESSAGES/messages.po +++ b/atlas/translations/it/LC_MESSAGES/messages.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2021-12-02 15:28+0100\n" +"POT-Creation-Date: 2022-10-11 15:29+0200\n" "PO-Revision-Date: 2021-07-19 09:53+0200\n" "Last-Translator: FULL NAME \n" "Language: it\n" @@ -175,10 +175,15 @@ msgstr "Scheda specie" msgid "check.species.sheet" msgstr "Vedere la scheda delle specie" -#: templates/core/extended_areas_search.html:13 +#: templates/core/extended_areas_search.html:12 msgid "search.other.zones.type" msgstr "Cerca per altro tipo di zone" +#: templates/core/extended_areas_search.html:23 +#, fuzzy +msgid "search" +msgstr "Ricerca per comune" + #: templates/core/listTaxons.html:14 msgid "filter.species" msgstr "Filtrare le species" @@ -212,12 +217,12 @@ msgstr "Ultime osservazioni " msgid "loading" msgstr "Caricamento in corso..." -#: templates/core/navbar.html:34 templates/home/globalStats.html:28 +#: templates/core/navbar.html:34 templates/home/globalStats.html:30 #: templates/photoGalery/_main.html:76 msgid "search.species" msgstr "Cerca per species" -#: templates/core/navbar.html:47 templates/home/globalStats.html:47 +#: templates/core/navbar.html:47 templates/home/globalStats.html:49 msgid "search.city" msgstr "Ricerca per comune" @@ -225,12 +230,12 @@ msgstr "Ricerca per comune" msgid "back.to.home" msgstr "Tornare a Home" -#: templates/core/sideBar.html:25 templates/home/globalStats.html:59 +#: templates/core/sideBar.html:25 templates/home/globalStats.html:61 #: templates/photoGalery/_main.html:5 templates/photoGalery/_main.html:50 msgid "gallery.title" msgstr "Galleria di foto" -#: templates/core/statHierarchy.html:12 templates/home/globalStats.html:21 +#: templates/core/statHierarchy.html:12 templates/home/globalStats.html:23 #: templates/home/taxoRank.html:28 templates/organismSheet/statsInfos.html:21 msgid "species" msgstr "Contanti" @@ -279,31 +284,36 @@ msgstr "Questo taxon ha uno status di protezione" msgid "display.city.infos" msgstr "Visualizza le informazioni del comune" +#: templates/home/geoStats.html:22 +#, fuzzy +msgid "search.for" +msgstr "" + #: templates/home/globalStats.html:4 msgid "home.insomefigures" msgstr "In pochi numeri" -#: templates/home/globalStats.html:13 +#: templates/home/globalStats.html:14 msgid "home.seelatestobs" msgstr "Guarda le ultime osservazioni" -#: templates/home/globalStats.html:39 templates/speciesSheet/map.html:20 +#: templates/home/globalStats.html:41 templates/speciesSheet/map.html:20 #: templates/speciesSheet/otherInformations.html:10 #: templates/speciesSheet/otherInformations.html:14 msgid "municipalities" msgstr "Comuni" -#: templates/home/globalStats.html:39 templates/speciesSheet/map.html:20 +#: templates/home/globalStats.html:41 templates/speciesSheet/map.html:20 #: templates/speciesSheet/otherInformations.html:10 #: templates/speciesSheet/otherInformations.html:14 msgid "municipality" msgstr "Comune" -#: templates/home/globalStats.html:58 +#: templates/home/globalStats.html:60 msgid "photos" msgstr "Immagini" -#: templates/home/globalStats.html:58 +#: templates/home/globalStats.html:60 msgid "photo" msgstr "Foto" diff --git a/data/atlas_with_extended_areas.sql b/data/atlas/14.atlas.vm_cor_area_observation.sql similarity index 77% rename from data/atlas_with_extended_areas.sql rename to data/atlas/14.atlas.vm_cor_area_observation.sql index e6decccf6..a26b6561f 100644 --- a/data/atlas_with_extended_areas.sql +++ b/data/atlas/14.atlas.vm_cor_area_observation.sql @@ -7,9 +7,7 @@ DROP MATERIALIZED VIEW IF EXISTS atlas.vm_bib_areas_types CASCADE; CREATE MATERIALIZED VIEW atlas.vm_bib_areas_types AS SELECT t.id_type, t.type_code, t.type_name, t.type_desc -FROM ref_geo.bib_areas_types t -WHERE - type_code IN ('M10', 'COM', 'ZNIEFF1', 'ZNIEFF2'); +FROM ref_geo.bib_areas_types t; CREATE INDEX ON atlas.vm_bib_areas_types(id_type); CREATE INDEX ON atlas.vm_bib_areas_types(type_code); @@ -32,9 +30,11 @@ FROM ref_geo.l_areas a JOIN atlas.vm_bib_areas_types t ON t.id_type = a.id_type + JOIN atlas.t_layer_territoire tlt + ON st_intersects(st_transform(a.geom, 4326) , tlt.the_geom) WHERE enable = TRUE AND - type_code IN ('M10', 'COM', 'ZNIEFF1', 'ZNIEFF2') + t.type_code NOT IN ('M1', 'M5', 'M10', 'COM') WITH DATA; CREATE UNIQUE INDEX vm_l_areas_id_area_idx @@ -53,16 +53,10 @@ CREATE INDEX vm_l_areas_area_name_idx DROP MATERIALIZED VIEW IF EXISTS atlas.vm_cor_area_observation; CREATE MATERIALIZED VIEW atlas.vm_cor_area_observation AS -SELECT cas.id_synthese AS id_observation, cas.id_area -FROM - synthese.cor_area_synthese cas - JOIN atlas.vm_l_areas la ON cas.id_area = la.id_area; +SELECT o.id_observation, + la.id_area + FROM atlas.vm_observations o + JOIN atlas.vm_l_areas la ON st_intersects(o.the_geom_point, la.the_geom) +WITH DATA; CREATE UNIQUE INDEX ON atlas.vm_cor_area_observation(id_observation, id_area); - -GRANT SELECT ON TABLE atlas.vm_bib_areas_types TO my_reader_user; -GRANT SELECT ON TABLE atlas.vm_l_areas TO my_reader_user; -GRANT SELECT ON TABLE atlas.vm_cor_area_observation TO my_reader_user; - - - diff --git a/data/atlas/14.grant.sql b/data/atlas/15.grant.sql similarity index 90% rename from data/atlas/14.grant.sql rename to data/atlas/15.grant.sql index 42e26451b..196d1e1a7 100644 --- a/data/atlas/14.grant.sql +++ b/data/atlas/15.grant.sql @@ -38,3 +38,6 @@ GRANT EXECUTE ON FUNCTION atlas.find_all_taxons_childs(integer) TO my_reader_use GRANT SELECT ON TABLE atlas.bib_taxref_rangs TO my_reader_user; GRANT SELECT ON TABLE atlas.t_mailles_territoire TO my_reader_user; GRANT SELECT ON TABLE atlas.vm_cor_taxon_organism TO my_reader_user; +GRANT SELECT ON TABLE atlas.vm_bib_areas_types TO my_reader_user; +GRANT SELECT ON TABLE atlas.vm_l_areas TO my_reader_user; +GRANT SELECT ON TABLE atlas.vm_cor_area_observation TO my_reader_user; diff --git a/install_db.sh b/install_db.sh index 04fd0fa9c..0b3ea7d44 100755 --- a/install_db.sh +++ b/install_db.sh @@ -413,6 +413,11 @@ if ! database_exists $db_name -f data/atlas/12.atlas.t_mailles_territoire.sql \ -v type_maille=$type_maille &>> log/install_db.log echo "[$(date +'%H:%M:%S')] Passed - Duration : $((($SECONDS-$time_temp)/60))m$((($SECONDS-$time_temp)%60))s" + + echo "[$(date +'%H:%M:%S')] Creating atlas.vm_l_areas, atlas.vm_bib_areas_types, atlas.vm_cor_area_observation ..." + export PGPASSWORD=$owner_atlas_pass;psql -d $db_name -U $owner_atlas -h $db_host \ + -f atlas/14.atlas.vm_cor_area_observation.sql &>> log/install_db.log + echo "[$(date +'%H:%M:%S')] Passed - Duration : $((($SECONDS-$time_temp)/60))m$((($SECONDS-$time_temp)%60))s" fi # FR: Création de la vue matérialisée vm_mailles_observations (nombre d'observations par maille et par taxon) # EN: Creation of the materialized view vm_meshes_observations (number of observations per mesh and per taxon)