diff --git a/envergo/geodata/admin.py b/envergo/geodata/admin.py index 87115898e..c7bb60c34 100644 --- a/envergo/geodata/admin.py +++ b/envergo/geodata/admin.py @@ -9,7 +9,7 @@ from envergo.geodata.forms import DepartmentForm from envergo.geodata.models import Department, Map, Parcel, Zone -from envergo.geodata.tasks import process_shapefile_map +from envergo.geodata.tasks import generate_map_preview, process_shapefile_map from envergo.geodata.utils import count_features, extract_shapefile @@ -60,7 +60,7 @@ def queryset(self, request, queryset): @admin.register(Map) -class MapAdmin(admin.ModelAdmin): +class MapAdmin(gis_admin.GISModelAdmin): form = MapForm list_display = [ "name", @@ -80,7 +80,7 @@ class MapAdmin(admin.ModelAdmin): "task_status", "import_error_msg", ] - actions = ["process"] + actions = ["process", "generate_preview"] exclude = ["task_id"] search_fields = ["name", "display_name"] list_filter = ["import_status", "map_type", "data_type", DepartmentsListFilter] @@ -161,6 +161,18 @@ def process(self, request, queryset): ) self.message_user(request, msg, level=messages.INFO) + @admin.action(description=_("Generate the simplified preview geometry")) + def generate_preview(self, request, queryset): + if queryset.count() > 1: + error = _("Please only select one map for this action.") + self.message_user(request, error, level=messages.ERROR) + return + + map = queryset[0] + generate_map_preview.delay(map.id) + msg = _("The map preview will be updated soon.") + self.message_user(request, msg, level=messages.INFO) + @admin.display(description=_("Extracted zones")) def zone_count(self, obj): count = Zone.objects.filter(map=obj).count() diff --git a/envergo/geodata/migrations/0003_map_geometry.py b/envergo/geodata/migrations/0003_map_geometry.py new file mode 100644 index 000000000..05b9b09b8 --- /dev/null +++ b/envergo/geodata/migrations/0003_map_geometry.py @@ -0,0 +1,20 @@ +# Generated by Django 4.2 on 2023-06-16 12:36 + +import django.contrib.gis.db.models.fields +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ("geodata", "0002_map_imported_zones"), + ] + + operations = [ + migrations.AddField( + model_name="map", + name="geometry", + field=django.contrib.gis.db.models.fields.MultiPolygonField( + geography=True, null=True, srid=4326, verbose_name="Simplified geometry" + ), + ), + ] diff --git a/envergo/geodata/models.py b/envergo/geodata/models.py index d364a663a..4a6affd95 100644 --- a/envergo/geodata/models.py +++ b/envergo/geodata/models.py @@ -180,7 +180,9 @@ class Map(models.Model): choices=DEPARTMENT_CHOICES, ), ) - + geometry = gis_models.MultiPolygonField( + _("Simplified geometry"), geography=True, null=True + ) created_at = models.DateTimeField(_("Date created"), default=timezone.now) expected_zones = models.IntegerField(_("Expected zones"), default=0) imported_zones = models.IntegerField(_("Imported zones"), null=True, blank=True) diff --git a/envergo/geodata/tasks.py b/envergo/geodata/tasks.py index 8a1e00c49..f4caa57ee 100644 --- a/envergo/geodata/tasks.py +++ b/envergo/geodata/tasks.py @@ -4,29 +4,36 @@ from config.celery_app import app from envergo.geodata.models import STATUSES, Map -from envergo.geodata.utils import process_shapefile +from envergo.geodata.utils import process_shapefile, simplify_map logger = logging.getLogger(__name__) @app.task(bind=True) +@transaction.atomic def process_shapefile_map(task, map_id): logger.info(f"Starting import on map {map_id}") map = Map.objects.get(pk=map_id) + + # Store the task data in the model, so we can display progression + # in the admin page. map.task_id = task.request.id map.import_error_msg = "" map.import_status = None map.save() - map.zones.all().delete() + # Proceed with the map import try: with transaction.atomic(): + map.zones.all().delete() process_shapefile(map, map.file, task) + map.geometry = simplify_map(map) except Exception as e: map.import_error_msg = f"Erreur d'import ({e})" logger.error(map.import_error_msg) + # Update the map status and metadata nb_imported_zones = map.zones.all().count() if map.expected_zones == nb_imported_zones: map.import_status = STATUSES.success @@ -38,3 +45,12 @@ def process_shapefile_map(task, map_id): map.task_id = None map.imported_zones = nb_imported_zones map.save() + + +@app.task(bind=True) +def generate_map_preview(task, map_id): + logger.info(f"Starting preview generation on map {map_id}") + + map = Map.objects.get(pk=map_id) + map.geometry = simplify_map(map) + map.save() diff --git a/envergo/geodata/utils.py b/envergo/geodata/utils.py index 7644336be..ae4be5032 100644 --- a/envergo/geodata/utils.py +++ b/envergo/geodata/utils.py @@ -9,9 +9,10 @@ import requests from django.contrib.gis.gdal import DataSource -from django.contrib.gis.geos import GEOSGeometry +from django.contrib.gis.geos import GEOSGeometry, MultiPolygon, Polygon from django.contrib.gis.utils.layermapping import LayerMapping from django.core.serializers import serialize +from django.db import connection from django.db.models import QuerySet from django.utils.translation import gettext_lazy as _ @@ -19,6 +20,8 @@ logger = logging.getLogger(__name__) +EPSG_WGS84 = 4326 + class CeleryDebugStream: """A sys.stdout proxy that also updates the celery task states. @@ -49,6 +52,8 @@ def write(self, msg): class CustomMapping(LayerMapping): + """A custom LayerMapping that allows to pass extra arguments to the generated model.""" + def __init__(self, *args, **kwargs): self.extra_kwargs = kwargs.pop("extra_kwargs") super().__init__(*args, **kwargs) @@ -127,8 +132,6 @@ def to_geojson(obj, geometry_field="geometry"): srid. """ - EPSG_WGS84 = 4326 - if isinstance(obj, (QuerySet, list)): geojson = serialize("geojson", obj, geometry_field=geometry_field) elif hasattr(obj, "geojson"): @@ -191,3 +194,47 @@ def merge_geometries(polygons): pass return merged + + +def simplify_map(map): + """Generates a simplified geometry for the entire map. + + This methods takes a map and generates a single polygon that is the union + of all the polygons in the map. + + We also simplify the polygon because this is for display purpose only. + + We use native postgis methods those operations, because it's way faster. + + As for simplification, we don't preserve topology (ST_Simplify instead of + ST_SimplifyPreserveTopology) because we want to be able to drop small + holes in the polygon. + + Because of that, we also have to call ST_MakeValid to avoid returning invalid + polygons.""" + + with connection.cursor() as cursor: + cursor.execute( + """ + SELECT + ST_AsText( + ST_MakeValid( + ST_Simplify( + ST_Union(z.geometry::geometry), + 0.0001 + ), + 'method=structure keepcollapsed=false' + ) + ) + AS polygon + FROM geodata_zone as z + WHERE z.map_id = %s + """, + [map.id], + ) + row = cursor.fetchone() + + polygon = GEOSGeometry(row[0], srid=EPSG_WGS84) + if isinstance(polygon, Polygon): + polygon = MultiPolygon(polygon) + return polygon diff --git a/envergo/moulinette/migrations/0005_contact_regulation_url.py b/envergo/moulinette/migrations/0005_contact_regulation_url.py new file mode 100644 index 000000000..ecd09307d --- /dev/null +++ b/envergo/moulinette/migrations/0005_contact_regulation_url.py @@ -0,0 +1,17 @@ +# Generated by Django 4.2 on 2023-06-22 12:40 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("moulinette", "0004_alter_contact_options"), + ] + + operations = [ + migrations.AddField( + model_name="contact", + name="regulation_url", + field=models.URLField(blank=True, verbose_name="Regulation URL"), + ), + ] diff --git a/envergo/moulinette/models.py b/envergo/moulinette/models.py index f25c9158e..3ed842e05 100644 --- a/envergo/moulinette/models.py +++ b/envergo/moulinette/models.py @@ -3,7 +3,7 @@ from django.contrib.gis.geos import Point from django.contrib.gis.measure import Distance as D from django.db import models -from django.db.models import F +from django.db.models import Case, F, When from django.db.models.functions import Cast from django.utils.translation import gettext_lazy as _ @@ -158,7 +158,7 @@ def __init__(self, data, raw_data): self.catalog["config"] = self.department.moulinette_config self.perimeters = self.get_perimeters() - self.criterions = self.get_criterions() + self.criterions_classes = self.get_criterions() # This is a clear case of circular references, since the Moulinette # holds references to the regulations it's computing, but regulations and @@ -251,7 +251,12 @@ def get_perimeters(self): Perimeter.objects.filter( map__zones__geometry__dwithin=(coords, F("activation_distance")) ) - .annotate(geometry=F("map__zones__geometry")) + .annotate( + geometry=Case( + When(map__geometry__isnull=False, then=F("map__geometry")), + default=F("map__zones__geometry"), + ) + ) .annotate(distance=Distance("map__zones__geometry", coords)) .order_by("distance", "map__name") .select_related("map", "contact") @@ -449,6 +454,7 @@ class Contact(models.Model): ) name = models.CharField(_("Name"), max_length=256) url = models.URLField(_("URL"), blank=True) + regulation_url = models.URLField(_("Regulation URL"), blank=True) address_md = models.TextField(_("Address")) address_html = models.TextField(_("Address HTML"), blank=True) diff --git a/envergo/moulinette/regulations/__init__.py b/envergo/moulinette/regulations/__init__.py index e1418ce9a..34be51392 100644 --- a/envergo/moulinette/regulations/__init__.py +++ b/envergo/moulinette/regulations/__init__.py @@ -1,4 +1,5 @@ import json +from abc import ABC from dataclasses import dataclass from enum import Enum from functools import cached_property @@ -21,18 +22,24 @@ def __str__(self): return self.text -class MoulinetteRegulation: - """Run the moulinette for a single regulation (e.g Loi sur l'eau).""" +class MoulinetteRegulation(ABC): + """Run the moulinette for a single regulation (e.g Loi sur l'eau). + This class is meant to be inherited to implement actual regulations. + """ + + # Implement this in subclasses criterion_classes = [] def __init__(self, moulinette): self.moulinette = moulinette self.moulinette.catalog.update(self.get_catalog_data()) + + # Instanciate the criterions self.criterions = [ - Criterion(moulinette) - for Criterion in self.criterion_classes - if Criterion in moulinette.criterions + perimeter.criterion(moulinette, perimeter) + for perimeter in moulinette.perimeters + if perimeter.criterion in self.criterion_classes ] def get_catalog_data(self): @@ -119,7 +126,11 @@ def _get_map(self): @dataclass class MapPolygon: - """Data that can be displayed and labeled on a leaflet map as a polygon.""" + """Data that can be displayed and labeled on a leaflet map as a polygon. + + A `MapPolygon is meant to represent a single entry on a map: + a polygon with a given color and label. + """ perimeters: list # List of `envergo.geofr.Perimeter` objects color: str @@ -185,7 +196,7 @@ def sources(self): return maps -class MoulinetteCriterion: +class MoulinetteCriterion(ABC): """Run a single moulinette check.""" # Prevent template engine to instanciate the class since we sometimes want @@ -198,9 +209,10 @@ class MoulinetteCriterion: # "Nomenclature réglementations & critères" document. CODES = ["soumis", "non_soumis", "action_requise", "non_concerne"] - def __init__(self, moulinette): + def __init__(self, moulinette, perimeter): self.moulinette = moulinette self.moulinette.catalog.update(self.get_catalog_data()) + self.perimeter = perimeter def get_catalog_data(self): """Get data to inject to the global catalog.""" diff --git a/envergo/moulinette/regulations/sage.py b/envergo/moulinette/regulations/sage.py index 3d014aeb3..850130111 100644 --- a/envergo/moulinette/regulations/sage.py +++ b/envergo/moulinette/regulations/sage.py @@ -368,3 +368,30 @@ def result(self): result = RESULTS.non_disponible return result + + def _get_map(self): + # Let's find the first map that we can display + perimeter = next( + ( + criterion.perimeter + for criterion in self.criterions + if criterion.perimeter.map.display_for_user + and criterion.perimeter.map.geometry + ), + None, + ) + if not perimeter: + return None + + map_polygons = [MapPolygon([perimeter], "red", "Sage")] + caption = "Le projet se situe dans le périmètre du Sage." + + map = Map( + center=self.catalog["coords"], + entries=map_polygons, + caption=caption, + truncate=False, + zoom=None, + ) + + return map diff --git a/envergo/pages/admin.py b/envergo/pages/admin.py index e69de29bb..bdb96777d 100644 --- a/envergo/pages/admin.py +++ b/envergo/pages/admin.py @@ -0,0 +1,10 @@ +from django.contrib import admin + +from envergo.pages.models import NewsItem + + +@admin.register(NewsItem) +class NewsItemAdmin(admin.ModelAdmin): + list_display = ["title", "created_at"] + search_fields = ["title", "content_md"] + fields = ["title", "content_md", "created_at"] diff --git a/envergo/pages/migrations/0001_initial.py b/envergo/pages/migrations/0001_initial.py new file mode 100644 index 000000000..6e181db26 --- /dev/null +++ b/envergo/pages/migrations/0001_initial.py @@ -0,0 +1,39 @@ +# Generated by Django 4.2 on 2023-04-25 08:29 + +from django.db import migrations, models +import django.utils.timezone + + +class Migration(migrations.Migration): + initial = True + + dependencies = [] + + operations = [ + migrations.CreateModel( + name="NewsItem", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("content_md", models.TextField(verbose_name="Content")), + ("content_html", models.TextField(verbose_name="Content HTML")), + ( + "created_at", + models.DateTimeField( + default=django.utils.timezone.now, verbose_name="Date created" + ), + ), + ], + options={ + "verbose_name": "News item", + "verbose_name_plural": "News items", + }, + ), + ] diff --git a/envergo/pages/migrations/0002_newsitem_title.py b/envergo/pages/migrations/0002_newsitem_title.py new file mode 100644 index 000000000..5deec9eb2 --- /dev/null +++ b/envergo/pages/migrations/0002_newsitem_title.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2 on 2023-05-22 08:00 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("pages", "0001_initial"), + ] + + operations = [ + migrations.AddField( + model_name="newsitem", + name="title", + field=models.CharField(default="", max_length=255, verbose_name="Title"), + preserve_default=False, + ), + ] diff --git a/envergo/pages/models.py b/envergo/pages/models.py index e69de29bb..7b2f7c8f1 100644 --- a/envergo/pages/models.py +++ b/envergo/pages/models.py @@ -0,0 +1,25 @@ +from django.db import models +from django.utils import timezone +from django.utils.translation import gettext_lazy as _ + +from envergo.utils.markdown import markdown_to_html + + +class NewsItem(models.Model): + """A news item to be displayed on the FAQ page.""" + + title = models.CharField(_("Title"), max_length=255) + content_md = models.TextField(_("Content")) + content_html = models.TextField(_("Content HTML")) + created_at = models.DateTimeField(_("Date created"), default=timezone.now) + + class Meta: + verbose_name = _("News item") + verbose_name_plural = _("News items") + + def __str__(self): + return self.title + + def save(self, *args, **kwargs): + self.content_html = markdown_to_html(self.content_md) + super().save(*args, **kwargs) diff --git a/envergo/pages/templatetags/pages.py b/envergo/pages/templatetags/pages.py index 3f5956dc8..7882d9831 100644 --- a/envergo/pages/templatetags/pages.py +++ b/envergo/pages/templatetags/pages.py @@ -16,39 +16,71 @@ def nav_link(route, label, aria_current=False): @register.simple_tag(takes_context=True) -def menu_item(context, route, label): - """Generate html for a main menu item.""" +def menu_item(context, route, label, subroutes=[]): + """Generate html for a main menu item. + + If you pass a list of subroutes, the menu item will be highlighted + if the current url is any on the main route or subroutes. + """ try: current_route = context.request.resolver_match.url_name except AttributeError: current_route = "" - aria_current = route == current_route + aria_current = route == current_route or current_route in subroutes return nav_link(route, label, aria_current) @register.simple_tag(takes_context=True) -def evalreq_menu(context): - """Generate html for the "Demander une évaluation" collapsible menu.""" - - link_route = "request_evaluation" - link_label = "Demander une évaluation manuelle" - +def sidemenu_item(context, route, label): try: current_route = context.request.resolver_match.url_name except AttributeError: current_route = "" - routes = [ + aria_current = route == current_route + url = reverse(route) + sidemenu_class = "fr-sidemenu__item--current" if aria_current else "" + aria_attr = 'aria-current="page"' if aria_current else "" + return mark_safe( + f""" +
  • + + {label} + +
  • + """ + ) + + +@register.simple_tag(takes_context=True) +def evalreq_menu(context): + """Generate html for the "Demander une évaluation" collapsible menu.""" + + link_route = "request_evaluation" + link_label = "Demander une évaluation manuelle" + subroutes = [ "request_eval_wizard_step_1", "request_eval_wizard_step_2", "request_eval_wizard_step_3", "request_success", ] + return menu_item(context, link_route, link_label, subroutes) - aria_current = 'aria-current="page"' if current_route in routes else "" - return nav_link(link_route, link_label, aria_current) + +@register.simple_tag(takes_context=True) +def faq_menu(context): + """Generate html for the "Faq" collapsible menu.""" + + link_route = "faq" + link_label = "Questions fréquentes" + subroutes = [ + "faq_loi_sur_leau", + "faq_natura_2000", + "faq_eval_env", + ] + return menu_item(context, link_route, link_label, subroutes) @register.simple_tag(takes_context=True) diff --git a/envergo/pages/urls.py b/envergo/pages/urls.py index d0417db44..b80fb871c 100644 --- a/envergo/pages/urls.py +++ b/envergo/pages/urls.py @@ -3,7 +3,7 @@ from django.views.generic import RedirectView, TemplateView from envergo.geodata.views import ParcelsExport -from envergo.pages.views import LegalMentionsView, Outlinks +from envergo.pages.views import LegalMentionsView, NewsFeed, NewsView, Outlinks urlpatterns = [ path( @@ -25,8 +25,40 @@ ), path( _("faq/"), - TemplateView.as_view(template_name="pages/faq.html"), - name="faq", + include( + [ + path( + "", + TemplateView.as_view(template_name="pages/faq/index.html"), + name="faq", + ), + path( + _("loi-sur-leau/"), + TemplateView.as_view(template_name="pages/faq/loi_sur_leau.html"), + name="faq_loi_sur_leau", + ), + path( + _("natura-2000/"), + TemplateView.as_view(template_name="pages/faq/natura_2000.html"), + name="faq_natura_2000", + ), + path( + _("eval-env/"), + TemplateView.as_view(template_name="pages/faq/eval_env.html"), + name="faq_eval_env", + ), + path( + _("envergo-news/"), + NewsView.as_view(), + name="faq_news", + ), + path( + _("envergo-news/feed/"), + NewsFeed(), + name="news_feed", + ), + ] + ), ), path( _("map/"), diff --git a/envergo/pages/views.py b/envergo/pages/views.py index ee37a025f..efdcaec7e 100644 --- a/envergo/pages/views.py +++ b/envergo/pages/views.py @@ -3,7 +3,13 @@ import requests from django.conf import settings from django.contrib import messages -from django.views.generic import TemplateView +from django.contrib.syndication.views import Feed +from django.urls import reverse +from django.utils.formats import date_format +from django.utils.html import mark_safe +from django.views.generic import ListView, TemplateView + +from envergo.pages.models import NewsItem class HomeView(TemplateView): @@ -60,3 +66,31 @@ def check_links(self): links.append({"label": label, "url": url, "status": req.status_code}) return links + + +class NewsView(ListView): + template_name = "pages/faq/news.html" + context_object_name = "news_items" + + def get_queryset(self): + return NewsItem.objects.all().order_by("-created_at") + + +class NewsFeed(Feed): + title = "Les actualités d'EnvErgo" + link = "/foire-aux-questions/envergo-news/feed/" + description = "Les nouveautés du projet EnvErgo" + + def items(self): + return NewsItem.objects.order_by("-created_at")[:10] + + def item_title(self, item): + return date_format(item.created_at, "DATE_FORMAT") + + def item_description(self, item): + return mark_safe(item.content_html) + + def item_link(self, item): + base_url = reverse("faq_news") + item_url = f"{base_url}#news-item-{item.id}" + return item_url diff --git a/envergo/static/js/libs/moulinette_result_maps.js b/envergo/static/js/libs/moulinette_result_maps.js index 4f6a5ba54..348e420ff 100644 --- a/envergo/static/js/libs/moulinette_result_maps.js +++ b/envergo/static/js/libs/moulinette_result_maps.js @@ -1,21 +1,21 @@ -(function(exports, L) { +(function (exports, L) { 'use strict'; /** * Initialize the leaflet maps for the moulinette result page. */ - const MapConfigurator = function(maps) { + const MapConfigurator = function (maps) { this.maps = maps; }; exports.MapConfigurator = MapConfigurator; - MapConfigurator.prototype.init = function() { + MapConfigurator.prototype.init = function () { for (const map in this.maps) { this.initMap(map); }; }; - MapConfigurator.prototype.initMap = function(mapId) { + MapConfigurator.prototype.initMap = function (mapId) { const mapData = this.maps[mapId]; const center = mapData.center; @@ -43,16 +43,22 @@ marker.addTo(map); // Display all polygons + const bounds = L.latLngBounds(); for (const polygonId in mapData.polygons) { const polygon = mapData.polygons[polygonId]; const polygonJson = L.geoJSON( polygon['polygon'], { style: { color: polygon['color'], fillColor: polygon['color'] } }); + bounds.extend(polygonJson.getBounds()); polygonJson.addTo(map); } + if (mapData["zoom"] === null) { + map.fitBounds(bounds); + } + // Display the legend const legend = L.control({ position: 'bottomright' }); - legend.onAdd = function(map) { + legend.onAdd = function (map) { const div = L.DomUtil.create('div', 'info legend'); for (const polygonId in mapData.polygons) { const polygon = mapData.polygons[polygonId]; @@ -72,7 +78,7 @@ // Upon page printing, the map container width is reduced, so we need to // make sure the map displays correctly with the new size. - window.matchMedia('print').addEventListener("change", function(query) { + window.matchMedia('print').addEventListener("change", function (query) { if (query.matches) { map.invalidateSize(); } @@ -83,7 +89,7 @@ })(this, L); -window.addEventListener('load', function() { +window.addEventListener('load', function () { var MAPS = window.MAPS || {}; var configurator = new MapConfigurator(MAPS); configurator.init(); diff --git a/envergo/static/sass/project.scss b/envergo/static/sass/project.scss index 5f84984d7..3c9c9ea6b 100644 --- a/envergo/static/sass/project.scss +++ b/envergo/static/sass/project.scss @@ -15,6 +15,9 @@ html.nojs .js { display: none !important; } +/** + * Useful components + */ .alert-debug { background-color: $white; border-color: $mint-green; @@ -27,6 +30,22 @@ html.nojs .js { color: $red; } +/** + * Update some margins for paragraphs and lists + */ +article { + --li-bottom: .5rem; + --text-spacing: 0 0 1rem; + + ul { + margin-bottom: 1rem; + } + + li p { + margin-bottom: .5rem; + } +} + .probability { text-transform: uppercase; font-weight: bold; @@ -240,17 +259,6 @@ nav#evaluation-summary { section.regulation { - --li-bottom: .5rem; - --text-spacing: 0 0 1rem; - - ul { - margin-bottom: 1rem; - } - - li p { - margin-bottom: .5rem; - } - h2 { display: flex; align-items: center; @@ -679,14 +687,10 @@ button[data-fr-js-collapse-button="true"] { } // Don't force a 16:9 ratio on images -.fr-content-media__img::before { - content: none; -} - -.fr-content-media__img img, -.fr-content-media__img svg { - position: unset; - object-fit: unset; +.fr-content-media { + .fr-responsive-img { + aspect-ratio: unset; + } } // Remove double margins below images with captions diff --git a/envergo/templates/_header.html b/envergo/templates/_header.html index 23d31679c..d3bffbeb9 100644 --- a/envergo/templates/_header.html +++ b/envergo/templates/_header.html @@ -51,7 +51,7 @@
  • {% evalreq_menu %}
  • -
  • {% menu_item 'faq' "Questions fréquentes" %}
  • +
  • {% faq_menu %}
  • {% evaluation_menu %}
  • diff --git a/envergo/templates/base.html b/envergo/templates/base.html index b88b3996a..a55938b72 100644 --- a/envergo/templates/base.html +++ b/envergo/templates/base.html @@ -26,6 +26,11 @@ href="{% static '@gouvfr/dsfr/dist/favicon/favicon.ico' %}" type="image/x-icon"> + + {% block css %} {% compress css %} Pour en savoir plus…

    - Consultez notre page d'information sur la Loi sur l'eau + Consultez notre page d'information ou contactez l'équipe EnvErgo.

    diff --git a/envergo/templates/moulinette/base_result.html b/envergo/templates/moulinette/base_result.html index 1c9efdc9f..ec1ecae7b 100644 --- a/envergo/templates/moulinette/base_result.html +++ b/envergo/templates/moulinette/base_result.html @@ -36,7 +36,7 @@

    Saisissez les caractéristiques de votre projet

    Pour en savoir plus…

    - Consultez notre page d'information sur la Loi sur l'eau + Consultez notre page d'information ou contactez l'équipe EnvErgo.

    {% endblock %} diff --git a/envergo/templates/moulinette/eval_body_action_requise.html b/envergo/templates/moulinette/eval_body_action_requise.html index 99deeaa25..841ab77aa 100644 --- a/envergo/templates/moulinette/eval_body_action_requise.html +++ b/envergo/templates/moulinette/eval_body_action_requise.html @@ -54,6 +54,10 @@

    Comment l'instruction du dossier Loi sur l'eau se déroule-t-e Le délai d'instruction d'un dossier de déclaration Loi sur l'eau est de 2 mois, extensible en cas de demande de compléments.

    +

    + Consultez notre article décrivant l'instruction Loi sur l'eau. +

    +

    Consultez notre article décrivant l'instruction Loi sur l'eau.

    diff --git a/envergo/templates/moulinette/loi_sur_leau/result_action_requise.html b/envergo/templates/moulinette/loi_sur_leau/result_action_requise.html index 618e9a6f1..094ba3a41 100644 --- a/envergo/templates/moulinette/loi_sur_leau/result_action_requise.html +++ b/envergo/templates/moulinette/loi_sur_leau/result_action_requise.html @@ -65,6 +65,10 @@

    Comment l'instruction du dossier Loi sur l'eau se déroule-t-elle ?

    Le délai d'instruction d'un dossier de déclaration Loi sur l'eau est de 2 mois, extensible en cas de demande de compléments.

    +

    + Consultez notre article décrivant l'instruction Loi sur l'eau. +

    +

    Consultez notre article décrivant l'instruction Loi sur l'eau.

    diff --git a/envergo/templates/moulinette/loi_sur_leau/result_non_soumis.html b/envergo/templates/moulinette/loi_sur_leau/result_non_soumis.html index fd8c54eaa..14e461a1f 100644 --- a/envergo/templates/moulinette/loi_sur_leau/result_non_soumis.html +++ b/envergo/templates/moulinette/loi_sur_leau/result_non_soumis.html @@ -1,5 +1,5 @@

    Le projet n’est pas soumis à la Loi sur l’eau.

    - Consultez notre page d'information sur la Loi sur l'eau. + Consultez notre page d'information sur la Loi sur l'eau.

    diff --git a/envergo/templates/moulinette/loi_sur_leau/result_soumis.html b/envergo/templates/moulinette/loi_sur_leau/result_soumis.html index 1bfc81c38..3e6994b09 100644 --- a/envergo/templates/moulinette/loi_sur_leau/result_soumis.html +++ b/envergo/templates/moulinette/loi_sur_leau/result_soumis.html @@ -53,6 +53,10 @@

    Comment l'instruction du dossier Loi sur l'eau se déroule-t-elle ?

    Le délai d'instruction d'un dossier de déclaration Loi sur l'eau est de 2 mois, extensible en cas de demande de compléments.

    +

    + Consultez notre article décrivant l'instruction Loi sur l'eau. +

    +

    Consultez notre article décrivant l'instruction Loi sur l'eau.

    diff --git a/envergo/templates/moulinette/natura2000/result_iota_a_verifier.html b/envergo/templates/moulinette/natura2000/result_iota_a_verifier.html index a1bd95b00..623e1db67 100644 --- a/envergo/templates/moulinette/natura2000/result_iota_a_verifier.html +++ b/envergo/templates/moulinette/natura2000/result_iota_a_verifier.html @@ -49,7 +49,7 @@

    Comment l'instruction de l'évaluation des incidences Natura 2000 se dérou

    - Consultez notre article décrivant l'instruction Loi sur l'eau. + Consultez notre article décrivant l'instruction Loi sur l'eau.

    Sanctions en cas d'omission

    diff --git a/envergo/templates/moulinette/natura2000/result_soumis.html b/envergo/templates/moulinette/natura2000/result_soumis.html index f28277dfd..e8a112066 100644 --- a/envergo/templates/moulinette/natura2000/result_soumis.html +++ b/envergo/templates/moulinette/natura2000/result_soumis.html @@ -170,7 +170,7 @@

    Comment l'instruction se déroule-t-elle ?

    - Consultez notre article décrivant l'instruction Loi sur l'eau. + Consultez notre article décrivant l'instruction Loi sur l'eau.

    {% elif moulinette.loi_sur_leau.result == 'action_requise' %} diff --git a/envergo/templates/pages/faq/eval_env.html b/envergo/templates/pages/faq/eval_env.html new file mode 100644 index 000000000..504934ae4 --- /dev/null +++ b/envergo/templates/pages/faq/eval_env.html @@ -0,0 +1,41 @@ +{% extends "pages/faq/index.html" %} + +{% load static %} + +{% block title %}Questions fréquentes : Évaluation environnementale{% endblock %} + +{% block faq_content %} +

    Questions fréquentes : Évaluation environnementale

    + +

    Évaluation environnementale

    + +
    + +
    +

    + +

    + +
    +

    Bla bla bla

    +
    +
    + +
    +{% endblock %} + +{% block extra_js %} + + + +{% endblock %} diff --git a/envergo/templates/pages/faq/index.html b/envergo/templates/pages/faq/index.html new file mode 100644 index 000000000..6f227d905 --- /dev/null +++ b/envergo/templates/pages/faq/index.html @@ -0,0 +1,92 @@ +{% extends "base.html" %} + +{% load static pages %} + +{% block title %}Questions fréquentes{% endblock %} + +{% block content %} +
    +
    + +
    + +
    + + {% block faq_content %} +

    Questions fréquentes

    + +

    + Consultez les réponses aux questions fréquentes sur les réglementations environnementales prises en compte par EnvErgo. +

    + +
    + +
    + +
    + +
    + +
    +
    + + {% endblock %} +
    +
    + +{% endblock %} diff --git a/envergo/templates/pages/faq.html b/envergo/templates/pages/faq/loi_sur_leau.html similarity index 78% rename from envergo/templates/pages/faq.html rename to envergo/templates/pages/faq/loi_sur_leau.html index 4cd6ab83f..b1fc79ad2 100644 --- a/envergo/templates/pages/faq.html +++ b/envergo/templates/pages/faq/loi_sur_leau.html @@ -1,18 +1,16 @@ -{% extends "base.html" %} +{% extends "pages/faq/index.html" %} {% load static %} -{% block title %}Questions fréquentes{% endblock %} - -{% block article %} -

    Questions fréquentes

    - +{% block title %}Questions fréquentes : Loi sur l'eau{% endblock %} +{% block faq_content %} +

    Questions fréquentes : Loi sur l'eau

    - La Loi sur l'eau encadre tous les projets qui risquent d'impacter l'eau et les milieux aquatiques. + La Loi sur l'eau encadre tous les projets qui risquent d'impacter l'eau et les + milieux aquatiques. Retrouvez ici les questions les plus fréquemment posées + quant à l'application de la Loi sur l'eau aux projets de construction et d'aménagement.

    -
    -

    -

    La Loi sur l'eau encadre tous les projets qui risquent d'impacter les milieux aquatiques.

    @@ -31,27 +28,22 @@

    l'eau.

    - La liste décrivant les projets soumis à la Loi sur l'eau se situe dans - - l'article R.214-1 du Code de l'Environnement - , aussi appelée - - nomenclature « IOTA » (pour Installations, Ouvrages, Travaux, Activités) - . + La liste décrivant les projets soumis à la Loi sur l'eau se situe dans l'article R.214-1 du + Code de + l'Environnement, aussi appelée nomenclature + « IOTA » (pour Installations, Ouvrages, Travaux, Activités).

    Les impacts sur les milieux aquatiques y sont répartis en plusieurs rubriques :

    -
    • modification du ruissellement d'eaux pluviales ;
    • construction en zone inondable par un cours d'eau ;
    • assèchement ou destruction de zones humides ;
    • impact sur un cours d'eau, en milieu marin, forage, etc.
    -

    Pour chaque rubrique il y a deux seuils d'impact :

    • Le seuil (D), pour Déclaration ;
    • @@ -65,79 +57,71 @@

    -

    - -
    - +

    - En première approche, le simulateur EnvErgo vous permet en quelques clics de vérifier si votre projet est soumis à la Loi sur l'eau, ainsi qu'à d'autres réglementations environnementales (Natura 2000…). + S’il s’agit d’un projet d’aménagement ou de construction, le simulateur EnvErgo vous permet en quelques clics de vérifier si le projet est soumis à la Loi sur l'eau — ainsi qu’aux autres réglementations environnementales (Natura 2000, évaluation environnementale…). C'est un service public numérique gratuit, fourni par le Ministère de la Transition Écologique. Il fonctionne pour l'instant en Loire-Atlantique, dans le Morbihan et en Vendée, et sera prochainement étendu à un territoire plus large.

    -

    Pour déterminer avec certitude si votre projet est soumis à la Loi sur l'eau, il est conseillé :

    -
    • De se rapprocher d'un bureau d'études disposant d'une expertise « dossier Loi sur l'eau ».

      -

      - Les échanges vous permettront de confirmer si votre projet de construction est soumis à la Loi sur l'eau, - et s'il y a lieu de constituer un dossier à déposer à l'administration. -

      +

      Le bureau d’études environnemental vous permet :

      +
        +
      • + d’évaluer si votre projet de construction ou d’aménagement est soumis à la Loi sur l'eau ou à d’autres règlementations environnementales ; +
      • +
      • de vous accompagner dans la réduction des impacts de votre projet ;
      • +
      • et de constituer les dossiers à déposer à l'administration.
      • +
    • -
    • De demander une évaluation Loi sur l'eau au service EnvErgo

      -

      Vous pouvez demander une évaluation de votre projet, qui sera réalisée manuellement par l'équipe d'EnvErgo — disponible sur la totalité du territoire français.

      -

      Enfin, n'hésitez pas à contacter l'équipe EnvErgo pour toute question complémentaire.

      - +
    • -
    • De se rapprocher du service qui instruit les dossiers Loi sur l'eau

      Pour cela, contactez la DDT(M) (Direction Départementale des Territoires et de la Mer) de votre département.

    • -
    -

    -

    Vous devez obligatoirement déposer un dossier de déclaration Loi sur l'eau, en plus de la demande de permis de - construire. + construire ou d'aménager.

    @@ -145,40 +129,31 @@

    de la Mer).

    - Il est à déposer au guichet unique de l'environnement du département où se situe le projet. - - Le dépôt peut se faire numériquement, via une procédure en ligne. - + Il est à déposer au guichet unique de l'environnement du département où + se situe le projet. Le dépôt peut se faire numériquement, via une procédure en ligne.

    -

    Il suit une procédure d'instruction spécifique, distincte de la demande de permis de construire, avec ses délais propres.

    -

    Son appellation « Déclaration » ne signifie pas qu'il s'agit d'une procédure déclarative sans obligation associée. Au contraire, elle déclenche une véritable instruction sur le fond du projet, qui peut aboutir :

    -
    • à un accord ;
    • -
    • à un accord sous conditions, sous la forme d'un arrêté de prescriptions particulières qui devront être respectées ;
    • -
    • à un refus, sous la forme d'un arrêté d'opposition à la déclaration.
    -

    -

    -

    - -
    +

    Les procédures Loi sur l'eau sont des procédures spécifiques, à effectuer en plus de la demande de permis de construire ou d'aménager.

    -

    Si votre projet est soumis à la Loi sur l'eau, il vous faut donc bien articuler les deux procédures d'instruction (Permis de construire ou d'aménager / Loi sur l'eau) qui peuvent s'influencer l'une l'autre.

    -

    - Dans le formulaire de demande de permis de construire hors maison individuelle ou permis d'aménager - ( - - Cerfa 13409 - - ), le + Dans le formulaire de demande de permis de construire hors maison individuelle ou permis d'aménager (Cerfa + 13409), le cadre n°8 sert à informer le service urbanisme des démarches menées au titre de la Loi sur l'eau.

    -
    • La première case du cadre n°8 doit être cochée si votre projet est soumis à Déclaration au titre de la nomenclature IOTA : -
      @@ -277,40 +240,34 @@

    • -
    • La deuxième case du cadre n°8 doit être cochée si votre projet est soumis à Autorisation au titre de la nomenclature IOTA, qui correspond à un niveau d'impact plus élevé que celui de la Déclaration.
    -

    Le service urbanisme qui étudie votre demande est en droit de vous demander des pièces complémentaires, pour déterminer si vous avez déposé ou non un dossier Loi sur l'eau pour votre projet.

    -
    -

    - -
    +

    Vous ne pouvez pas démarrer les travaux avant d'avoir reçu une réponse de la préfecture.

    S'il s'avère que le projet est réalisé sans autorisation du préfet, le responsable s'expose à des sanctions administratives et pénales pouvant comprendre une - obligation de remettre le terrain en son état initial, avec une astreinte jusqu'à 1500 € par + obligation de remettre le terrain en son état initial, avec une astreinte jusqu'à 1 500 € par jour.

    -

    Toutefois, dans certains cas, le récepissé de déclaration mentionne explicitement la possibilité de démarrer les travaux. @@ -325,7 +282,6 @@

    Quelles sont les conséquences en cas d'omission ?

    -

    Votre demande de permis de construire peut être rejetée si vous n'avez pas déposé de dossier Loi sur @@ -344,24 +300,23 @@

    S'il s'avère que le projet est réalisé sans autorisation du préfet, le responsable s'expose à des sanctions administratives et pénales, qui peuvent aller jusqu'à :

    -

    -

    -

    @@ -381,34 +335,26 @@

    Une procédure d’Autorisation Environnementale dure en moyenne de 9 à 12 mois.

    La demande est à déposer au guichet unique de l'environnement du département où - se situe le projet. - - Le dépôt peut se faire numériquement, via une procédure en ligne. - + se situe le projet. Le dépôt peut se faire numériquement, via une procédure en ligne.

    - Retrouvez plus d’informations sur la procédure à ce lien. - + rel="noopener">Retrouvez plus d’informations sur la procédure à ce lien.

    -

    - {% endblock %} - {% block extra_js %} - {% endblock %} diff --git a/envergo/templates/pages/faq/natura_2000.html b/envergo/templates/pages/faq/natura_2000.html new file mode 100644 index 000000000..fc64c5101 --- /dev/null +++ b/envergo/templates/pages/faq/natura_2000.html @@ -0,0 +1,309 @@ +{% extends "pages/faq/index.html" %} + +{% load static %} + +{% block title %}Questions fréquentes : Natura 2000{% endblock %} +{% block faq_content %} +

    Questions fréquentes : Natura 2000

    +

    + Natura 2000 est un dispositif réglementaire visant la protection d'espèces animales et végétales fragiles, et de leur habitat. + Retrouvez ici les questions les plus fréquemment posées quant à l'application du dispositif Natura 2000 aux projets de construction et d'aménagement. +

    +
    +
    +

    + +

    +
    +

    + Natura 2000 est un dispositif européen visant à la protection d’espèces animales et végétales fragiles, + et de leurs habitats. +

    +

    En France, il consiste en :

    +
      +
    • + un ensemble d’aires protégées – les sites Natura 2000 – qui abritent une faune et une flore à protéger ; +
    • +
    • + un dispositif réglementaire — l’évaluation des incidences Natura 2000 — qui s’applique aux projets pouvant avoir des impacts sur ces sites protégés ; + ainsi qu’à certains projets aux impacts potentiellement importants, même hors des sites Natura 2000. +
    • +
    +

    La France compte près de 1 800 sites Natura 2000, couvrant près de 13 % du territoire terrestre métropolitain.

    +

    Ces sites Natura 2000 sont répartis en deux catégories :

    +
      +
    • + les zones spéciales de conservation (ZSC), à protéger car ils abritent certaines espèces fragiles (faune ou flore) ; +
    • +
    • + les zones de protection spéciale (ZPS) qui concernent des espèces d’oiseaux vulnérables, et les lieux de leur survie ou de leur reproduction. +
    • +
    +

    + Les textes réglementaires Natura 2000 sont conçus pour que les projets menés dans ces sites garantissent la préservation à long terme des espèces et des habitats. +

    +
    +
    +
    +

    + +

    +
    +

    + Les projets concernés par le dispositif Natura 2000 sont listés dans plusieurs textes réglementaires s’appliquant au niveau national, départemental, ou à l’échelle d’une façade maritime. +

    +

    Ces textes sont les suivants :

    +
      +
    • +

      + à l’échelle nationale, la « liste nationale » fixée par l'article R.414-19 du code de l'environnement. +
      + Elle concerne les projets déjà encadrés administrativement. Par exemple, tout projet soumis à la Loi sur l’eau, à examen au cas par cas, ou à étude d’impact, est concerné. +
      + Elle s’applique à ces projets même s’ils se situent hors d’un site Natura 2000. +

      +
    • +
    • +

      + une « liste locale 1 » à l’échelle du département ou de la région, fixée par arrêté préfectoral. +
      + Elle reprend les points de la liste nationale, mais prend en compte les spécificités locales et s’applique uniquement à des projets qui se situent à l’intérieur ou à proximité d’un site Natura 2000. +

      +
    • +
    • +

      + une « liste locale 2 », à l’échelle départementale ou régionale également. +
      + Cette liste concerne des types de projets qui peuvent être très variés, différentes des listes nationale et locale 1 ; + elle est établie selon les spécificités des sites Natura 2000 du territoire. +
      + Cette liste établit ce qu’on appelle le « régime propre » de Natura 2000, qui est plus restrictif que les listes ci-dessus. +

      +
    • +
    +

    + Si un projet est concerné par l’une des listes Natura 2000, il lui est imposé de mener une étude préalable + — l’évaluation des incidences Natura 2000 — et de la soumettre à l’administration. +

    +
    +
    +
    +

    + +

    +
    +

    + S’il s’agit d’un projet d’aménagement ou de construction, le simulateur EnvErgo vous permet en quelques clics de vérifier si le projet est soumis à Natura 2000 — ainsi qu’aux autres réglementations environnementales (Loi sur l’eau, évaluation environnementale…). + C'est un service public numérique gratuit, fourni par le Ministère de la Transition Écologique. + Il fonctionne pour l'instant en Loire-Atlantique, dans le Morbihan et en Vendée, et sera prochainement étendu à un territoire plus large. +

    +

    De façon générale, un projet peut être soumis à EIN :

    +
      +
    • + s’il est soumis à une procédure administrative de type déclaration ou autorisation, par exemple Loi sur l’eau (IOTA) ou Installation classée (ICPE), + même s’il se situe hors d’un site Natura 2000. +
    • +
    • ou s’il se situe dans un site Natura 2000 et est concerné par les listes locales du département concerné.
    • +
    +

    + Pour déterminer avec certitude si votre projet est soumis à évaluation des incidences Natura 2000 (EIN), il est conseillé : +

    +
      +
    • +

      + De contacter l’animateur du site Natura 2000 concerné, dès la conception du projet +

      +

      + Chaque site Natura 2000 dispose d’une structure en charge de son « animation », + dont le rôle est de vous informer quant aux obligations de protection du lieu, + et de vous accompagner pour concilier les exigences du projet avec la minimisation de ses impacts sur le site. +

      +

      + La liste des animateurs est publiée sur les sites internet des préfectures dans chaque département. +

      +

      En l’absence d’un animateur, vous pouvez vous rapprocher de la DDT(M) du site concerné.

      +
    • +
    • +

      + D’avoir recours aux formulaires simplifiés d’évaluation des incidences +

      +

      + Ces formulaires sont élaborés dans chaque département pour accompagner la réflexion du porteur + sur les impacts du projet mentionnés dans les listes locales Natura 2000. + Ils sont disponibles sur les sites internet des préfectures. +

      +

      + Ils permettent d’évaluer, le plus tôt possible dans la conception de son projet, + si certains impacts devront faire l’objet d’une évaluation avancée, + et d’un travail rapproché entre le porteur et ses maîtres d’œuvre, l’animateur du site, et les services de l’État. +

      +
    • +
    • +

      + De se rapprocher d'un bureau d'études disposant d'une expertise environnementale +

      +

      Le bureau d’études environnemental vous permet :

      +
        +
      • + d’évaluer si votre projet de construction ou d’aménagement est soumis à évaluation des incidences Natura 2000 ou à d’autres règlementations environnementales ; +
      • +
      • de vous accompagner dans la réduction des impacts de votre projet ;
      • +
      • et de constituer les dossiers à déposer à l'administration.
      • +
      +
    • +
    +
    +
    +
    +

    + +

    +
    +

    + Oui. Si le projet est déjà soumis à une procédure administrative, par exemple Loi sur l’eau, examen au cas par cas, déclaration au titre des installations classées (ICPE), + l’EIN est obligatoire, même si le projet est hors d’un site Natura 2000. +

    +

    + Par ailleurs, dans certains départements, la seule proximité à un site est motif d’entrée en procédure. + En effet, des impacts sur un site protégé peuvent être induits par le projet (bruit, effluents, activité humaine…), même s’il n’est pas strictement dans le périmètre. +

    +

    + Le simulateur EnvErgo, pour déterminer si un projet de construction ou d’aménagement est soumis à Natura 2000, + prend en compte les listes locales et la doctrine DDT(M) de chaque département. +

    +
    +
    +
    +

    + +

    +
    +

    + + + Vous devez obligatoirement déposer une évaluation des incidences Natura 2000, + en plus de la demande de permis de construire ou d’aménager. + +

    +

    L’administration à qui déposer le dossier d’EIN dépend des autres procédures auxquelles est soumis le dossier :

    +
      +
    • + Si le projet est également soumis à autre une procédure administrative (par exemple Loi sur l’eau, examen au cas par cas, ou au titre des installations classées), l’EIN est attachée au dossier déposé à la DDT(M) ; +
    • +
    • sinon l’EIN est jointe à la demande de permis de construire ou d’aménager déposée en mairie.
    • +
    +

    + Le simulateur EnvErgo permet de déterminer à la fois si votre projet est soumis à EIN, + et la procédure associée pour déposer le dossier. +

    +
    +
    +
    +

    + +

    +
    +

    + Quand l’évaluation des incidences Natura 2000 est jointe à une demande d’autorisation (dossier Loi sur l'eau ou demande de PC ou de PA), + ce qui est le cas le plus fréquent pour un projet de construction ou d'aménagement, + l'EIN est instruite en même temps que celle-ci, de façon transparente pour le porteur de projet. +

    +

    La présence d'une EIN ne modifie pas le délai de la demande de rattachement :

    +
      +
    • 2 mois pour un dossier de déclaration Loi sur l’eau ;
    • +
    • 2 mois pour une demande de permis de construire ;
    • +
    • 3 mois pour une demande de permis d’aménager.
    • +
    +

    + De façon transparente pour le porteur de projet, l’EIN est transmise au service en charge de la biodiversité, au sein de la DDT(M) du département concerné ; + c’est lui qui en mène l’instruction. +

    +

    + Le service instructeur peut vous demander des compléments + si le dossier n’apparaît pas suffisamment explicite ou si des mesures d’atténuation des incidences semblent manquer. +

    +
    +
    +
    +

    + +

    +
    +

    + Votre demande de permis de construire ou d’aménager peut être rejetée + si vous n'avez pas réalisé et déposé d’évaluation des incidences Natura 2000 et que vous y étiez tenu. +

    +

    + Un contrôle par la police de l’environnement peut avoir lieu avant, pendant les travaux, ou après la réalisation du projet. + Une tierce partie (riverain, association, collectivité) peut déclencher un recours auprès de l’administration. +

    +

    S'il s'avère que le projet est réalisé :

    +
      +
    • sans évaluation des incidences alors qu’il y était soumis,
    • +
    • sans avoir obtenu l'accord pour la déclaration ou l’autorisation associée,
    • +
    • ou sans tenir compte des prescriptions éventuelles de celui-ci,
    • +
    +

    le responsable s'expose à des sanctions administratives et pénales, qui peuvent aller jusqu'à :

    + +
    +
    +
    +{% endblock %} +{% block extra_js %} + + +{% endblock %} diff --git a/envergo/templates/pages/faq/news.html b/envergo/templates/pages/faq/news.html new file mode 100644 index 000000000..079948d7b --- /dev/null +++ b/envergo/templates/pages/faq/news.html @@ -0,0 +1,20 @@ +{% extends "pages/faq/index.html" %} + +{% load static %} + +{% block title %}Les dernières évolutions d'EnvErgo{% endblock %} + +{% block faq_content %} +

    Les dernières évolutions d'EnvErgo

    +

    Suivez ici l'actualité du projet EnvErgo.

    + + {% for item in news_items %} + +
    +

    + {{ item.title }} – {{ item.created_at|date:"DATE_FORMAT" }} +

    + {{ item.content_html|safe }} +
    + {% endfor %} +{% endblock %} diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index 1104cba07..e5df40694 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-06-15 09:12+0000\n" +"POT-Creation-Date: 2023-06-22 14:31+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -93,8 +93,8 @@ msgid "Metadata" msgstr "Données Geo" #: envergo/analytics/models.py:20 envergo/evaluations/models.py:153 -#: envergo/evaluations/models.py:472 envergo/geodata/models.py:184 -#: envergo/geodata/models.py:224 +#: envergo/evaluations/models.py:472 envergo/geodata/models.py:186 +#: envergo/geodata/models.py:226 msgid "Date created" msgstr "Date de création" @@ -344,7 +344,7 @@ msgid "Evaluation file" msgstr "Fichier d'évaluation" #: envergo/evaluations/models.py:127 envergo/evaluations/models.py:416 -#: envergo/geodata/forms.py:79 +#: envergo/geodata/forms.py:79 envergo/moulinette/models.py:457 msgid "Address" msgstr "Adresse" @@ -381,7 +381,7 @@ msgstr "" "Apparaîtra dans le mail de rappel réglementaire. Utilisez du markdown simple " "(gras, italique, liens, retours à la ligne)." -#: envergo/evaluations/models.py:147 +#: envergo/evaluations/models.py:147 envergo/moulinette/models.py:461 msgid "Contact" msgstr "Contact" @@ -435,7 +435,7 @@ msgid "Probability" msgstr "Probabilité" #: envergo/evaluations/models.py:362 envergo/evaluations/models.py:370 -#: envergo/moulinette/models.py:70 +#: envergo/moulinette/models.py:72 msgid "Criterion" msgstr "Critère" @@ -448,8 +448,8 @@ msgstr "Description" msgid "Description (html)" msgstr " Description (html)" -#: envergo/evaluations/models.py:365 envergo/geodata/models.py:199 -#: envergo/moulinette/models.py:66 +#: envergo/evaluations/models.py:365 envergo/geodata/models.py:201 +#: envergo/moulinette/models.py:68 msgid "Map" msgstr "Carte" @@ -506,7 +506,7 @@ msgid "File" msgstr "Fichier" #: envergo/evaluations/models.py:568 envergo/geodata/models.py:158 -#: envergo/moulinette/models.py:63 +#: envergo/moulinette/models.py:65 envergo/moulinette/models.py:455 msgid "Name" msgstr "Nom" @@ -556,7 +556,7 @@ msgid "This file does not seem valid ({e})" msgstr "Ce fichier semble invalide ({e})" #: envergo/geodata/admin.py:42 envergo/geodata/models.py:174 -#: envergo/geodata/models.py:244 +#: envergo/geodata/models.py:246 msgid "Departments" msgstr "Départements" @@ -568,7 +568,7 @@ msgstr "" msgid "Extract and import a shapefile" msgstr "Extraire et importer le fichier shapefile" -#: envergo/geodata/admin.py:153 +#: envergo/geodata/admin.py:153 envergo/geodata/admin.py:167 msgid "Please only select one map for this action." msgstr "Merci de sélectionner une et une seule carte pour cette action." @@ -580,14 +580,22 @@ msgstr "" "minutes." #: envergo/geodata/admin.py:164 +msgid "Generate the simplified preview geometry" +msgstr "Générer la carte simplifiée" + +#: envergo/geodata/admin.py:173 +msgid "The map preview will be updated soon." +msgstr "La carte sera mise à jour incessamment." + +#: envergo/geodata/admin.py:176 msgid "Extracted zones" msgstr "Zones extraites" -#: envergo/geodata/admin.py:187 envergo/geodata/models.py:167 +#: envergo/geodata/admin.py:199 envergo/geodata/models.py:167 msgid "Data type" msgstr "Valeur carto" -#: envergo/geodata/admin.py:191 +#: envergo/geodata/admin.py:203 msgid "Data certainty" msgstr "Valeur carto" @@ -705,48 +713,52 @@ msgid "Select departments ids separated by commas" msgstr "" "Saisissez des numéros de départements séparés par des virgules, e.g « 44,56 »" -#: envergo/geodata/models.py:185 +#: envergo/geodata/models.py:184 +msgid "Simplified geometry" +msgstr "" + +#: envergo/geodata/models.py:187 msgid "Expected zones" msgstr "Nb de zones attendues" -#: envergo/geodata/models.py:186 +#: envergo/geodata/models.py:188 msgid "Imported zones" msgstr "Nb de zones importées" -#: envergo/geodata/models.py:188 +#: envergo/geodata/models.py:190 msgid "Import status" msgstr "Statut d'import" -#: envergo/geodata/models.py:191 +#: envergo/geodata/models.py:193 msgid "Celery task id" msgstr "Id de tâche Celery" -#: envergo/geodata/models.py:193 +#: envergo/geodata/models.py:195 msgid "Import error message" msgstr "Message d'erreur de l'import" -#: envergo/geodata/models.py:195 +#: envergo/geodata/models.py:197 msgid "Copy to staging?" msgstr "Copier en recette ?" -#: envergo/geodata/models.py:195 +#: envergo/geodata/models.py:197 msgid "Don't touch this please" msgstr "Réservé aux admins, merci de ne pas toucher svp." -#: envergo/geodata/models.py:200 +#: envergo/geodata/models.py:202 msgid "Maps" msgstr "Cartes" -#: envergo/geodata/models.py:227 +#: envergo/geodata/models.py:229 msgid "Zone" msgstr "Zone" -#: envergo/geodata/models.py:228 +#: envergo/geodata/models.py:230 msgid "Zones" msgstr "Zones" -#: envergo/geodata/models.py:235 envergo/geodata/models.py:243 -#: envergo/moulinette/forms/__init__.py:92 envergo/moulinette/models.py:88 +#: envergo/geodata/models.py:237 envergo/geodata/models.py:245 +#: envergo/moulinette/forms/__init__.py:92 envergo/moulinette/models.py:90 msgid "Department" msgstr "Département" @@ -758,7 +770,7 @@ msgstr "carte/" msgid "zone.geojson" msgstr "zone.geojson" -#: envergo/geodata/utils.py:77 +#: envergo/geodata/utils.py:82 msgid "No .shp file found in archive" msgstr "Aucun fichier .shp trouvé dans l'archive" @@ -796,38 +808,54 @@ msgstr "" "La surface impactée totale doit être au moins égale à celle des nouveaux " "impacts" -#: envergo/moulinette/models.py:72 +#: envergo/moulinette/models.py:74 msgid "Activation distance" msgstr "Distance d'activation (m)" -#: envergo/moulinette/models.py:76 +#: envergo/moulinette/models.py:78 envergo/moulinette/models.py:451 msgid "Perimeter" msgstr "Périmètre" -#: envergo/moulinette/models.py:77 +#: envergo/moulinette/models.py:79 msgid "Perimeters" msgstr "Périmètres" -#: envergo/moulinette/models.py:93 +#: envergo/moulinette/models.py:95 msgid "Is activated" msgstr "Est actif" -#: envergo/moulinette/models.py:94 +#: envergo/moulinette/models.py:96 msgid "Is the moulinette available for this department?" msgstr "Le simulateur est-il activé pour ce départemnent ?" -#: envergo/moulinette/models.py:97 +#: envergo/moulinette/models.py:99 msgid "DDT(M) contact email" msgstr "E-mail DDT(M) (rappel réglementaire)" -#: envergo/moulinette/models.py:114 +#: envergo/moulinette/models.py:116 msgid "Moulinette config" msgstr "Config moulinette" -#: envergo/moulinette/models.py:115 +#: envergo/moulinette/models.py:117 msgid "Moulinette configs" msgstr "Configs moulinette" +#: envergo/moulinette/models.py:456 +msgid "URL" +msgstr "" + +#: envergo/moulinette/models.py:458 +#, fuzzy +#| msgid "Address" +msgid "Address HTML" +msgstr "Adresse" + +#: envergo/moulinette/models.py:462 +#, fuzzy +#| msgid "Contact" +msgid "Contacts" +msgstr "Contact" + #: envergo/moulinette/regulations/evalenv.py:161 #: envergo/moulinette/regulations/natura2000.py:270 msgid "Le projet concerne-t-il un lotissement ?"