Compare commits

..

8 Commits
1.12 ... master

Author SHA1 Message Date
210f3fcafa Merge pull request '# HOTFIX' (#495) from update_map_config into master
Reviewed-on: #495
2025-10-23 16:12:45 +02:00
e7d67560f2 # HOTFIX
* fixes bug on netgis map client where importing a geometry would result in an error message
* THIS IS JUST A WORKAROUND AND HAS TO BE REPLACED BY A PROPER FIX FROM THE DEVS ASAP
2025-10-23 16:12:05 +02:00
b5e991fb95 Merge pull request '# Map layer update' (#494) from update_map_config into master
Reviewed-on: #494
2025-10-22 16:02:02 +02:00
d3a555d406 # Map layer update
* updates rp_dop layer from deprecated to newest
2025-10-22 16:00:35 +02:00
9a374f50de Merge pull request '# CSS bugfix' (#492) from fix_css_map_menu_bar_overlap into master
Reviewed-on: #492
2025-10-21 15:59:37 +02:00
ce63dd30bc # CSS bugfix
* fixes a rendering bug where the menu bar of the map client overlapped modal forms
2025-10-21 15:57:25 +02:00
e5db7f6b13 Merge pull request '# Small geometry processing' (#488) from 487_Small_geometry_processing into master
Reviewed-on: #488
2025-10-15 09:51:27 +02:00
442f3ceb37 # Small geometry processing
* changes SimpleGeomForm behaviour on small geometries (<1m²): These geometries will now be dismissed on processing
* adds a new info message in case of automatically removed geometries on saving
* updates tests
2025-10-15 09:50:59 +02:00
18 changed files with 8380 additions and 628 deletions

View File

@ -54,7 +54,7 @@ class CompensationWorkflowTestCase(BaseWorkflowTestCase):
post_data = { post_data = {
"identifier": test_id, "identifier": test_id,
"title": test_title, "title": test_title,
"geom": geom_json, "output": geom_json,
"intervention": self.intervention.id, "intervention": self.intervention.id,
} }
pre_creation_intervention_log_count = self.intervention.log.count() pre_creation_intervention_log_count = self.intervention.log.count()
@ -94,7 +94,7 @@ class CompensationWorkflowTestCase(BaseWorkflowTestCase):
post_data = { post_data = {
"identifier": test_id, "identifier": test_id,
"title": test_title, "title": test_title,
"geom": geom_json, "output": geom_json,
} }
pre_creation_intervention_log_count = self.intervention.log.count() pre_creation_intervention_log_count = self.intervention.log.count()
@ -150,7 +150,7 @@ class CompensationWorkflowTestCase(BaseWorkflowTestCase):
"title": new_title, "title": new_title,
"intervention": self.intervention.id, # just keep the intervention as it is "intervention": self.intervention.id, # just keep the intervention as it is
"comment": new_comment, "comment": new_comment,
"geom": geojson, "output": geojson,
} }
self.client_user.post(url, post_data) self.client_user.post(url, post_data)
self.compensation.refresh_from_db() self.compensation.refresh_from_db()

View File

@ -46,7 +46,7 @@ class EcoAccountWorkflowTestCase(BaseWorkflowTestCase):
post_data = { post_data = {
"identifier": test_id, "identifier": test_id,
"title": test_title, "title": test_title,
"geom": geom_json, "output": geom_json,
"surface": test_deductable_surface, "surface": test_deductable_surface,
"conservation_office": test_conservation_office.id "conservation_office": test_conservation_office.id
} }
@ -103,7 +103,7 @@ class EcoAccountWorkflowTestCase(BaseWorkflowTestCase):
"identifier": new_identifier, "identifier": new_identifier,
"title": new_title, "title": new_title,
"comment": new_comment, "comment": new_comment,
"geom": self.create_geojson(new_geometry), "output": self.create_geojson(new_geometry),
"surface": test_deductable_surface, "surface": test_deductable_surface,
"conservation_office": test_conservation_office.id "conservation_office": test_conservation_office.id
} }

View File

@ -27,7 +27,7 @@ from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
from konova.utils.message_templates import COMPENSATION_REMOVED_TEMPLATE, DATA_CHECKED_PREVIOUSLY_TEMPLATE, \ from konova.utils.message_templates import COMPENSATION_REMOVED_TEMPLATE, DATA_CHECKED_PREVIOUSLY_TEMPLATE, \
RECORDED_BLOCKS_EDIT, CHECK_STATE_RESET, FORM_INVALID, PARAMS_INVALID, IDENTIFIER_REPLACED, \ RECORDED_BLOCKS_EDIT, CHECK_STATE_RESET, FORM_INVALID, PARAMS_INVALID, IDENTIFIER_REPLACED, \
COMPENSATION_ADDED_TEMPLATE, DO_NOT_FORGET_TO_SHARE, GEOMETRY_SIMPLIFIED COMPENSATION_ADDED_TEMPLATE, DO_NOT_FORGET_TO_SHARE, GEOMETRY_SIMPLIFIED, GEOMETRIES_IGNORED_TEMPLATE
@login_required @login_required
@ -103,11 +103,19 @@ def new_view(request: HttpRequest, intervention_id: str = None):
) )
) )
messages.success(request, COMPENSATION_ADDED_TEMPLATE.format(comp.identifier)) messages.success(request, COMPENSATION_ADDED_TEMPLATE.format(comp.identifier))
if geom_form.geometry_simplified: if geom_form.has_geometry_simplified():
messages.info( messages.info(
request, request,
GEOMETRY_SIMPLIFIED GEOMETRY_SIMPLIFIED
) )
num_ignored_geometries = geom_form.get_num_geometries_ignored()
if num_ignored_geometries > 0:
messages.info(
request,
GEOMETRIES_IGNORED_TEMPLATE.format(num_ignored_geometries)
)
return redirect("compensation:detail", id=comp.id) return redirect("compensation:detail", id=comp.id)
else: else:
messages.error(request, FORM_INVALID, extra_tags="danger",) messages.error(request, FORM_INVALID, extra_tags="danger",)
@ -179,11 +187,19 @@ def edit_view(request: HttpRequest, id: str):
if intervention_is_checked: if intervention_is_checked:
messages.info(request, CHECK_STATE_RESET) messages.info(request, CHECK_STATE_RESET)
messages.success(request, _("Compensation {} edited").format(comp.identifier)) messages.success(request, _("Compensation {} edited").format(comp.identifier))
if geom_form.geometry_simplified: if geom_form.has_geometry_simplified():
messages.info( messages.info(
request, request,
GEOMETRY_SIMPLIFIED GEOMETRY_SIMPLIFIED
) )
num_ignored_geometries = geom_form.get_num_geometries_ignored()
if num_ignored_geometries > 0:
messages.info(
request,
GEOMETRIES_IGNORED_TEMPLATE.format(num_ignored_geometries)
)
return redirect("compensation:detail", id=comp.id) return redirect("compensation:detail", id=comp.id)
else: else:
messages.error(request, FORM_INVALID, extra_tags="danger",) messages.error(request, FORM_INVALID, extra_tags="danger",)

View File

@ -23,7 +23,7 @@ from konova.forms import SimpleGeomForm
from konova.settings import ETS_GROUP, DEFAULT_GROUP, ZB_GROUP from konova.settings import ETS_GROUP, DEFAULT_GROUP, ZB_GROUP
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
from konova.utils.message_templates import CANCEL_ACC_RECORDED_OR_DEDUCTED, RECORDED_BLOCKS_EDIT, FORM_INVALID, \ from konova.utils.message_templates import CANCEL_ACC_RECORDED_OR_DEDUCTED, RECORDED_BLOCKS_EDIT, FORM_INVALID, \
IDENTIFIER_REPLACED, DO_NOT_FORGET_TO_SHARE, GEOMETRY_SIMPLIFIED IDENTIFIER_REPLACED, DO_NOT_FORGET_TO_SHARE, GEOMETRY_SIMPLIFIED, GEOMETRIES_IGNORED_TEMPLATE
@login_required @login_required
@ -84,11 +84,19 @@ def new_view(request: HttpRequest):
) )
) )
messages.success(request, _("Eco-Account {} added").format(acc.identifier)) messages.success(request, _("Eco-Account {} added").format(acc.identifier))
if geom_form.geometry_simplified: if geom_form.has_geometry_simplified():
messages.info( messages.info(
request, request,
GEOMETRY_SIMPLIFIED GEOMETRY_SIMPLIFIED
) )
num_ignored_geometries = geom_form.get_num_geometries_ignored()
if num_ignored_geometries > 0:
messages.info(
request,
GEOMETRIES_IGNORED_TEMPLATE.format(num_ignored_geometries)
)
return redirect("compensation:acc:detail", id=acc.id) return redirect("compensation:acc:detail", id=acc.id)
else: else:
messages.error(request, FORM_INVALID, extra_tags="danger",) messages.error(request, FORM_INVALID, extra_tags="danger",)
@ -156,11 +164,19 @@ def edit_view(request: HttpRequest, id: str):
# The data form takes the geom form for processing, as well as the performing user # The data form takes the geom form for processing, as well as the performing user
acc = data_form.save(request.user, geom_form) acc = data_form.save(request.user, geom_form)
messages.success(request, _("Eco-Account {} edited").format(acc.identifier)) messages.success(request, _("Eco-Account {} edited").format(acc.identifier))
if geom_form.geometry_simplified: if geom_form.has_geometry_simplified():
messages.info( messages.info(
request, request,
GEOMETRY_SIMPLIFIED GEOMETRY_SIMPLIFIED
) )
num_ignored_geometries = geom_form.get_num_geometries_ignored()
if num_ignored_geometries > 0:
messages.info(
request,
GEOMETRIES_IGNORED_TEMPLATE.format(num_ignored_geometries)
)
return redirect("compensation:acc:detail", id=acc.id) return redirect("compensation:acc:detail", id=acc.id)
else: else:
messages.error(request, FORM_INVALID, extra_tags="danger",) messages.error(request, FORM_INVALID, extra_tags="danger",)

View File

@ -46,7 +46,7 @@ class EmaWorkflowTestCase(BaseWorkflowTestCase):
post_data = { post_data = {
"identifier": test_id, "identifier": test_id,
"title": test_title, "title": test_title,
"geom": geom_json, "output": geom_json,
"conservation_office": test_conservation_office.id "conservation_office": test_conservation_office.id
} }
self.client_user.post(new_url, post_data) self.client_user.post(new_url, post_data)
@ -99,7 +99,7 @@ class EmaWorkflowTestCase(BaseWorkflowTestCase):
"identifier": new_identifier, "identifier": new_identifier,
"title": new_title, "title": new_title,
"comment": new_comment, "comment": new_comment,
"geom": self.create_geojson(new_geometry), "output": self.create_geojson(new_geometry),
"conservation_office": test_conservation_office.id "conservation_office": test_conservation_office.id
} }
self.client_user.post(url, post_data) self.client_user.post(url, post_data)

View File

@ -48,7 +48,7 @@ class NewEmaFormTestCase(BaseTestCase):
) )
geom_form_data = json.loads(geom_form_data) geom_form_data = json.loads(geom_form_data)
geom_form_data = { geom_form_data = {
"geom": json.dumps(geom_form_data) "output": json.dumps(geom_form_data)
} }
geom_form = SimpleGeomForm(geom_form_data) geom_form = SimpleGeomForm(geom_form_data)
@ -116,7 +116,7 @@ class EditEmaFormTestCase(BaseTestCase):
) )
geom_form_data = json.loads(geom_form_data) geom_form_data = json.loads(geom_form_data)
geom_form_data = { geom_form_data = {
"geom": json.dumps(geom_form_data) "output": json.dumps(geom_form_data)
} }
geom_form = SimpleGeomForm(geom_form_data) geom_form = SimpleGeomForm(geom_form_data)

View File

@ -24,7 +24,7 @@ from konova.forms.modals import RemoveModalForm
from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
from konova.utils.message_templates import RECORDED_BLOCKS_EDIT, IDENTIFIER_REPLACED, FORM_INVALID, \ from konova.utils.message_templates import RECORDED_BLOCKS_EDIT, IDENTIFIER_REPLACED, FORM_INVALID, \
DO_NOT_FORGET_TO_SHARE, GEOMETRY_SIMPLIFIED DO_NOT_FORGET_TO_SHARE, GEOMETRY_SIMPLIFIED, GEOMETRIES_IGNORED_TEMPLATE
@login_required @login_required
@ -84,11 +84,17 @@ def new_view(request: HttpRequest):
) )
) )
messages.success(request, _("EMA {} added").format(ema.identifier)) messages.success(request, _("EMA {} added").format(ema.identifier))
if geom_form.geometry_simplified: if geom_form.has_geometry_simplified():
messages.info( messages.info(
request, request,
GEOMETRY_SIMPLIFIED GEOMETRY_SIMPLIFIED
) )
num_ignored_geometries = geom_form.get_num_geometries_ignored()
if num_ignored_geometries > 0:
messages.info(
request,
GEOMETRIES_IGNORED_TEMPLATE.format(num_ignored_geometries)
)
return redirect("ema:detail", id=ema.id) return redirect("ema:detail", id=ema.id)
else: else:
@ -215,11 +221,19 @@ def edit_view(request: HttpRequest, id: str):
# The data form takes the geom form for processing, as well as the performing user # The data form takes the geom form for processing, as well as the performing user
ema = data_form.save(request.user, geom_form) ema = data_form.save(request.user, geom_form)
messages.success(request, _("EMA {} edited").format(ema.identifier)) messages.success(request, _("EMA {} edited").format(ema.identifier))
if geom_form.geometry_simplified: if geom_form.has_geometry_simplified():
messages.info( messages.info(
request, request,
GEOMETRY_SIMPLIFIED GEOMETRY_SIMPLIFIED
) )
num_ignored_geometries = geom_form.get_num_geometries_ignored()
if num_ignored_geometries > 0:
messages.info(
request,
GEOMETRIES_IGNORED_TEMPLATE.format(num_ignored_geometries)
)
return redirect("ema:detail", id=ema.id) return redirect("ema:detail", id=ema.id)
else: else:
messages.error(request, FORM_INVALID, extra_tags="danger",) messages.error(request, FORM_INVALID, extra_tags="danger",)

View File

@ -60,7 +60,7 @@ class InterventionWorkflowTestCase(BaseWorkflowTestCase):
post_data = { post_data = {
"identifier": test_id, "identifier": test_id,
"title": test_title, "title": test_title,
"geom": geom_json, "output": geom_json,
} }
response = self.client_user.post( response = self.client_user.post(
new_url, new_url,

View File

@ -62,7 +62,7 @@ class NewInterventionFormTestCase(BaseTestCase):
) )
geom_form_data = json.loads(geom_form_data) geom_form_data = json.loads(geom_form_data)
geom_form_data = { geom_form_data = {
"geom": json.dumps(geom_form_data) "output": json.dumps(geom_form_data)
} }
geom_form = SimpleGeomForm(geom_form_data) geom_form = SimpleGeomForm(geom_form_data)
@ -104,7 +104,7 @@ class EditInterventionFormTestCase(NewInterventionFormTestCase):
) )
geom_form_data = json.loads(geom_form_data) geom_form_data = json.loads(geom_form_data)
geom_form_data = { geom_form_data = {
"geom": json.dumps(geom_form_data) "output": json.dumps(geom_form_data)
} }
geom_form = SimpleGeomForm(geom_form_data) geom_form = SimpleGeomForm(geom_form_data)

View File

@ -23,7 +23,8 @@ from konova.forms.modals import RemoveModalForm
from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
from konova.utils.message_templates import DATA_CHECKED_PREVIOUSLY_TEMPLATE, RECORDED_BLOCKS_EDIT, \ from konova.utils.message_templates import DATA_CHECKED_PREVIOUSLY_TEMPLATE, RECORDED_BLOCKS_EDIT, \
CHECK_STATE_RESET, FORM_INVALID, IDENTIFIER_REPLACED, DO_NOT_FORGET_TO_SHARE, GEOMETRY_SIMPLIFIED CHECK_STATE_RESET, FORM_INVALID, IDENTIFIER_REPLACED, DO_NOT_FORGET_TO_SHARE, GEOMETRY_SIMPLIFIED, \
GEOMETRIES_IGNORED_TEMPLATE
@login_required @login_required
@ -88,11 +89,19 @@ def new_view(request: HttpRequest):
) )
) )
messages.success(request, _("Intervention {} added").format(intervention.identifier)) messages.success(request, _("Intervention {} added").format(intervention.identifier))
if geom_form.geometry_simplified: if geom_form.has_geometry_simplified():
messages.info( messages.info(
request, request,
GEOMETRY_SIMPLIFIED GEOMETRY_SIMPLIFIED
) )
num_ignored_geometries = geom_form.get_num_geometries_ignored()
if num_ignored_geometries > 0:
messages.info(
request,
GEOMETRIES_IGNORED_TEMPLATE.format(num_ignored_geometries)
)
return redirect("intervention:detail", id=intervention.id) return redirect("intervention:detail", id=intervention.id)
else: else:
messages.error(request, FORM_INVALID, extra_tags="danger",) messages.error(request, FORM_INVALID, extra_tags="danger",)
@ -236,11 +245,19 @@ def edit_view(request: HttpRequest, id: str):
messages.success(request, _("Intervention {} edited").format(intervention.identifier)) messages.success(request, _("Intervention {} edited").format(intervention.identifier))
if intervention_is_checked: if intervention_is_checked:
messages.info(request, CHECK_STATE_RESET) messages.info(request, CHECK_STATE_RESET)
if geom_form.geometry_simplified: if geom_form.has_geometry_simplified():
messages.info( messages.info(
request, request,
GEOMETRY_SIMPLIFIED GEOMETRY_SIMPLIFIED
) )
num_ignored_geometries = geom_form.get_num_geometries_ignored()
if num_ignored_geometries > 0:
messages.info(
request,
GEOMETRIES_IGNORED_TEMPLATE.format(num_ignored_geometries)
)
return redirect("intervention:detail", id=intervention.id) return redirect("intervention:detail", id=intervention.id)
else: else:
messages.error(request, FORM_INVALID, extra_tags="danger",) messages.error(request, FORM_INVALID, extra_tags="danger",)

View File

@ -25,8 +25,8 @@ class SimpleGeomForm(BaseForm):
""" A geometry form for rendering geometry read-only using a widget """ A geometry form for rendering geometry read-only using a widget
""" """
read_only = True read_only: bool = True
geometry_simplified = False _geometry_simplified: bool = False
output = JSONField( output = JSONField(
label=_("Geometry"), label=_("Geometry"),
help_text=_(""), help_text=_(""),
@ -34,6 +34,7 @@ class SimpleGeomForm(BaseForm):
required=False, required=False,
disabled=False, disabled=False,
) )
_num_geometries_ignored: int = 0
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.read_only = kwargs.pop("read_only", True) self.read_only = kwargs.pop("read_only", True)
@ -48,6 +49,7 @@ class SimpleGeomForm(BaseForm):
raise AttributeError raise AttributeError
geojson = self.instance.geometry.as_feature_collection(srid=DEFAULT_SRID_RLP) geojson = self.instance.geometry.as_feature_collection(srid=DEFAULT_SRID_RLP)
self._set_geojson_properties(geojson, title=self.instance.identifier or None)
geom = json.dumps(geojson) geom = json.dumps(geojson)
except AttributeError: except AttributeError:
# If no geometry exists for this form, we simply set the value to None and zoom to the maximum level # If no geometry exists for this form, we simply set the value to None and zoom to the maximum level
@ -61,7 +63,7 @@ class SimpleGeomForm(BaseForm):
is_valid = True is_valid = True
# Get geojson from form # Get geojson from form
geom = self.data["output"] geom = self.data.get("output", None)
if geom is None or len(geom) == 0: if geom is None or len(geom) == 0:
# empty geometry is a valid geometry # empty geometry is a valid geometry
self.cleaned_data["output"] = MultiPolygon(srid=DEFAULT_SRID_RLP).ewkt self.cleaned_data["output"] = MultiPolygon(srid=DEFAULT_SRID_RLP).ewkt
@ -100,7 +102,13 @@ class SimpleGeomForm(BaseForm):
is_valid &= False is_valid &= False
return is_valid return is_valid
is_valid &= self.__is_area_valid(g) is_area_valid = self.__is_area_valid(g)
if not is_area_valid:
# Geometries with an invalid size will not be saved to the db
# We assume these are malicious snippets which are not supposed to be in the geometry in the first place
self._num_geometries_ignored += 1
continue
g = Polygon.from_ewkt(g.ewkt) g = Polygon.from_ewkt(g.ewkt)
is_valid &= g.valid is_valid &= g.valid
if not g.valid: if not g.valid:
@ -147,15 +155,6 @@ class SimpleGeomForm(BaseForm):
""" """
is_area_valid = geom.area > 1 # > 1m² (SRID:25832) is_area_valid = geom.area > 1 # > 1m² (SRID:25832)
if not is_area_valid:
self.add_error(
"output",
_("Geometry must be greater than 1m². Currently is {}").format(
float(geom.area)
)
)
return is_area_valid return is_area_valid
def __simplify_geometry(self, geom, max_vert: int): def __simplify_geometry(self, geom, max_vert: int):
@ -208,13 +207,29 @@ class SimpleGeomForm(BaseForm):
if not is_vertices_num_valid: if not is_vertices_num_valid:
geometry.geom = self.__simplify_geometry(geometry.geom, max_vert=GEOM_MAX_VERTICES) geometry.geom = self.__simplify_geometry(geometry.geom, max_vert=GEOM_MAX_VERTICES)
geometry.save() geometry.save()
self.geometry_simplified = True self._geometry_simplified = True
# Start parcel update and geometry conflict checking procedure in a background process # Start parcel update and geometry conflict checking procedure in a background process
celery_update_parcels.delay(geometry.id) celery_update_parcels.delay(geometry.id)
celery_check_for_geometry_conflicts.delay(geometry.id) celery_check_for_geometry_conflicts.delay(geometry.id)
return geometry return geometry
def get_num_geometries_ignored(self):
""" Returns the number of geometries which had to be ignored for various reasons
Returns:
"""
return self._num_geometries_ignored
def has_geometry_simplified(self):
""" Returns whether the geometry has been simplified or not.
Returns:
"""
return self._geometry_simplified
def __flatten_geom_to_2D(self, geom): def __flatten_geom_to_2D(self, geom):
""" """
Enforces a given OGRGeometry from higher dimensions into 2D Enforces a given OGRGeometry from higher dimensions into 2D
@ -225,11 +240,12 @@ class SimpleGeomForm(BaseForm):
geom = gdal.OGRGeometry(g_wkt) geom = gdal.OGRGeometry(g_wkt)
return geom return geom
def _set_properties(self, geojson: dict, title: str): def _set_geojson_properties(self, geojson: dict, title: str = None):
""" Toggles the editable property of the geojson for proper handling in map client """ Toggles the editable property of the geojson for proper handling in map client
Args: Args:
geojson (dict): The GeoJson geojson (dict): The GeoJson
title (str): An alternative title for the geometry
Returns: Returns:
geojson (dict): The altered GeoJson geojson (dict): The altered GeoJson

View File

@ -288,4 +288,8 @@ Overwrites netgis.css attributes
Overwrites gradient used on default css of netgis map client Overwrites gradient used on default css of netgis map client
*/ */
background: var(--rlp-red) !important; background: var(--rlp-red) !important;
}
.netgis-menu{
z-index: 1 !important;
} }

View File

@ -124,6 +124,7 @@ class GeometryTestCase(BaseTestCase):
{ {
"type": "Feature", "type": "Feature",
"geometry": json.loads(p.json), "geometry": json.loads(p.json),
"properties": {}
} }
for p in polygons for p in polygons
] ]

View File

@ -83,6 +83,7 @@ EDITED_GENERAL_DATA = _("Edited general data")
# Geometry # Geometry
GEOMETRY_CONFLICT_WITH_TEMPLATE = _("Geometry conflict detected with {}") GEOMETRY_CONFLICT_WITH_TEMPLATE = _("Geometry conflict detected with {}")
GEOMETRY_SIMPLIFIED = _("The geometry contained more than {} vertices. It had to be simplified to match the allowed limit of {} vertices.").format(GEOM_MAX_VERTICES, GEOM_MAX_VERTICES) GEOMETRY_SIMPLIFIED = _("The geometry contained more than {} vertices. It had to be simplified to match the allowed limit of {} vertices.").format(GEOM_MAX_VERTICES, GEOM_MAX_VERTICES)
GEOMETRIES_IGNORED_TEMPLATE = _("The geometry contained {} parts which have been detected as invalid (e.g. too small to be valid). These parts have been removed. Please check the stored geometry.")
# INTERVENTION # INTERVENTION
INTERVENTION_HAS_REVOCATIONS_TEMPLATE = _("This intervention has {} revocations") INTERVENTION_HAS_REVOCATIONS_TEMPLATE = _("This intervention has {} revocations")

Binary file not shown.

View File

@ -45,7 +45,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-05-12 14:22+0200\n" "POT-Creation-Date: 2025-10-15 09:11+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -1298,13 +1298,13 @@ msgid "Compensation {} edited"
msgstr "Kompensation {} bearbeitet" msgstr "Kompensation {} bearbeitet"
#: compensation/views/compensation/compensation.py:196 #: compensation/views/compensation/compensation.py:196
#: compensation/views/eco_account/eco_account.py:173 ema/views/ema.py:232 #: compensation/views/eco_account/eco_account.py:173 ema/views/ema.py:238
#: intervention/views/intervention.py:253 #: intervention/views/intervention.py:253
msgid "Edit {}" msgid "Edit {}"
msgstr "Bearbeite {}" msgstr "Bearbeite {}"
#: compensation/views/compensation/report.py:35 #: compensation/views/compensation/report.py:35
#: compensation/views/eco_account/report.py:35 ema/views/report.py:35 #: compensation/views/eco_account/report.py:36 ema/views/report.py:35
#: intervention/views/report.py:35 #: intervention/views/report.py:35
msgid "Report {}" msgid "Report {}"
msgstr "Bericht {}" msgstr "Bericht {}"
@ -1325,7 +1325,7 @@ msgstr "Ökokonto {} bearbeitet"
msgid "Eco-account removed" msgid "Eco-account removed"
msgstr "Ökokonto entfernt" msgstr "Ökokonto entfernt"
#: ema/forms.py:42 ema/tests/unit/test_forms.py:27 ema/views/ema.py:102 #: ema/forms.py:42 ema/tests/unit/test_forms.py:27 ema/views/ema.py:108
msgid "New EMA" msgid "New EMA"
msgstr "Neue EMA hinzufügen" msgstr "Neue EMA hinzufügen"
@ -1361,11 +1361,11 @@ msgstr "EMAs - Übersicht"
msgid "EMA {} added" msgid "EMA {} added"
msgstr "EMA {} hinzugefügt" msgstr "EMA {} hinzugefügt"
#: ema/views/ema.py:217 #: ema/views/ema.py:223
msgid "EMA {} edited" msgid "EMA {} edited"
msgstr "EMA {} bearbeitet" msgstr "EMA {} bearbeitet"
#: ema/views/ema.py:256 #: ema/views/ema.py:262
msgid "EMA removed" msgid "EMA removed"
msgstr "EMA entfernt" msgstr "EMA entfernt"
@ -1815,10 +1815,6 @@ msgid "Only surfaces allowed. Points or lines must be buffered."
msgstr "" msgstr ""
"Nur Flächen erlaubt. Punkte oder Linien müssen zu Flächen gepuffert werden." "Nur Flächen erlaubt. Punkte oder Linien müssen zu Flächen gepuffert werden."
#: konova/forms/geometry_form.py:153
msgid "Geometry must be greater than 1m². Currently is {}m²"
msgstr "Geometrie muss größer als 1m² sein. Aktueller Flächeninhalt: {}m²"
#: konova/forms/modals/document_form.py:37 #: konova/forms/modals/document_form.py:37
msgid "When has this file been created? Important for photos." msgid "When has this file been created? Important for photos."
msgstr "Wann wurde diese Datei erstellt oder das Foto aufgenommen?" msgstr "Wann wurde diese Datei erstellt oder das Foto aufgenommen?"
@ -2266,24 +2262,33 @@ msgstr ""
"Die Geometrie enthielt mehr als {} Eckpunkte. Sie musste vereinfacht werden " "Die Geometrie enthielt mehr als {} Eckpunkte. Sie musste vereinfacht werden "
"um die Obergrenze von {} erlaubten Eckpunkten einzuhalten." "um die Obergrenze von {} erlaubten Eckpunkten einzuhalten."
#: konova/utils/message_templates.py:88 #: konova/utils/message_templates.py:86
msgid ""
"The geometry contained {} parts which have been detected as invalid (e.g. "
"too small to be valid). These parts have been removed. Please check the "
"stored geometry."
msgstr ""
"Die Geometrie enthielt {} invalide Bestandteile (z.B. unaussagekräftige Kleinstflächen)."
"Diese Bestandteile wurden automatisch entfernt. Bitte überprüfen Sie die angepasste Geometrie."
#: konova/utils/message_templates.py:89
msgid "This intervention has {} revocations" msgid "This intervention has {} revocations"
msgstr "Dem Eingriff liegen {} Widersprüche vor" msgstr "Dem Eingriff liegen {} Widersprüche vor"
#: konova/utils/message_templates.py:91 #: konova/utils/message_templates.py:92
msgid "Checked on {} by {}" msgid "Checked on {} by {}"
msgstr "Am {} von {} geprüft worden" msgstr "Am {} von {} geprüft worden"
#: konova/utils/message_templates.py:92 #: konova/utils/message_templates.py:93
msgid "Data has changed since last check on {} by {}" msgid "Data has changed since last check on {} by {}"
msgstr "" msgstr ""
"Daten wurden nach der letzten Prüfung geändert. Letzte Prüfung am {} durch {}" "Daten wurden nach der letzten Prüfung geändert. Letzte Prüfung am {} durch {}"
#: konova/utils/message_templates.py:93 #: konova/utils/message_templates.py:94
msgid "Current data not checked yet" msgid "Current data not checked yet"
msgstr "Momentane Daten noch nicht geprüft" msgstr "Momentane Daten noch nicht geprüft"
#: konova/utils/message_templates.py:96 #: konova/utils/message_templates.py:97
msgid "New token generated. Administrators need to validate." msgid "New token generated. Administrators need to validate."
msgstr "Neuer Token generiert. Administratoren sind informiert." msgstr "Neuer Token generiert. Administratoren sind informiert."
@ -2313,14 +2318,6 @@ msgstr "Home"
msgid "Log" msgid "Log"
msgstr "Log" msgstr "Log"
#: konova/views/map_proxy.py:84
msgid ""
"The external service is currently unavailable.<br>Please try again in a few "
"moments..."
msgstr ""
"Der externe Dienst ist zur Zeit nicht erreichbar.<br>Versuchen Sie es in ein "
"paar Sekunden nochmal."
#: konova/views/record.py:30 #: konova/views/record.py:30
msgid "{} unrecorded" msgid "{} unrecorded"
msgstr "{} entzeichnet" msgstr "{} entzeichnet"
@ -2377,17 +2374,19 @@ msgstr "Alle"
msgid "News" msgid "News"
msgstr "Neuigkeiten" msgstr "Neuigkeiten"
#: templates/400.html:7 #: templates/400.html:12
msgid "Request was invalid" msgid "Request was invalid"
msgstr "Anfrage fehlerhaft" msgstr "Anfrage fehlerhaft"
#: templates/400.html:10 #: templates/400.html:17
msgid "There seems to be a problem with the link you opened." msgid "There seems to be a problem with the link you opened."
msgstr "Es scheint ein Problem mit dem Link zu geben, den Sie geöffnet haben." msgstr "Es scheint ein Problem mit dem Link zu geben, den Sie geöffnet haben."
#: templates/400.html:11 #: templates/400.html:18
msgid "Make sure the URL is valid (no whitespaces, properly copied, ...)." msgid "Make sure the URL is valid (no whitespaces, properly copied, ...)."
msgstr "Stellen Sie sicher, dass die URL gültig ist (keine Leerzeichen, fehlerfrei kopiert, ...)." msgstr ""
"Stellen Sie sicher, dass die URL gültig ist (keine Leerzeichen, fehlerfrei "
"kopiert, ...)."
#: templates/404.html:7 #: templates/404.html:7
msgid "Not found" msgid "Not found"
@ -2401,11 +2400,11 @@ msgstr "Die angeforderten Daten existieren nicht."
msgid "Make sure the URL is valid (no whitespaces, ...)." msgid "Make sure the URL is valid (no whitespaces, ...)."
msgstr "Stellen Sie sicher, dass die URL gültig ist (keine Leerzeichen, ...)." msgstr "Stellen Sie sicher, dass die URL gültig ist (keine Leerzeichen, ...)."
#: templates/500.html:7 #: templates/500.html:12
msgid "Server Error" msgid "Server Error"
msgstr "" msgstr ""
#: templates/500.html:10 #: templates/500.html:17
msgid "Something happened. Admins have been informed. We are working on it!" msgid "Something happened. Admins have been informed. We are working on it!"
msgstr "" msgstr ""
"Irgendetwas ist passiert. Die Administratoren wurden informiert. Wir " "Irgendetwas ist passiert. Die Administratoren wurden informiert. Wir "

View File

@ -58,7 +58,7 @@
[ [
{ "id": "webatlas_farbe", "folder": "bg", "type": "WMS", "order": -1, "title": "WebatlasRP farbig", "attribution": "LVermGeo", "url": "https://maps.service24.rlp.de/gisserver/services/RP/RP_WebAtlasRP/MapServer/WmsServer?", "name": "RP_WebAtlasRP", "active": true}, { "id": "webatlas_farbe", "folder": "bg", "type": "WMS", "order": -1, "title": "WebatlasRP farbig", "attribution": "LVermGeo", "url": "https://maps.service24.rlp.de/gisserver/services/RP/RP_WebAtlasRP/MapServer/WmsServer?", "name": "RP_WebAtlasRP", "active": true},
{ "id": "webatlas_grau", "folder": "bg", "type": "WMS", "order": -1, "title": "WebatlasRP grau", "attribution": "LVermGeo", "url": "https://maps.service24.rlp.de/gisserver/services/RP/RP_ETRS_Gt/MapServer/WmsServer?", "name": "0", "active": false }, { "id": "webatlas_grau", "folder": "bg", "type": "WMS", "order": -1, "title": "WebatlasRP grau", "attribution": "LVermGeo", "url": "https://maps.service24.rlp.de/gisserver/services/RP/RP_ETRS_Gt/MapServer/WmsServer?", "name": "0", "active": false },
{ "id": "luftbilder", "folder": "bg", "type": "WMS", "order": -1, "title": "Luftbilder", "attribution": "LVermGeo", "url": "https://geo4.service24.rlp.de/wms/dop_basis.fcgi?", "name": "rp_dop", "active": false }, { "id": "luftbilder", "folder": "bg", "type": "WMS", "order": -1, "title": "Luftbilder", "attribution": "LVermGeo", "url": "https://geo4.service24.rlp.de/wms/rp_dop20.fcgi?", "name": "rp_dop20", "active": false },
{ "id": "basemap_farbe", "folder": "bg", "type": "WMS", "order": -1, "title": "BasemapDE farbig", "attribution": "BKG", "url": "https://sgx.geodatenzentrum.de/wms_basemapde?", "name": "de_basemapde_web_raster_farbe", "active": false }, { "id": "basemap_farbe", "folder": "bg", "type": "WMS", "order": -1, "title": "BasemapDE farbig", "attribution": "BKG", "url": "https://sgx.geodatenzentrum.de/wms_basemapde?", "name": "de_basemapde_web_raster_farbe", "active": false },
{ "id": "basemap_grau", "folder": "bg", "type": "WMS", "order": -1, "title": "BasemapDE grau", "attribution": "BKG", "url": "https://sgx.geodatenzentrum.de/wms_basemapde?", "name": "de_basemapde_web_raster_grau", "active": false }, { "id": "basemap_grau", "folder": "bg", "type": "WMS", "order": -1, "title": "BasemapDE grau", "attribution": "BKG", "url": "https://sgx.geodatenzentrum.de/wms_basemapde?", "name": "de_basemapde_web_raster_grau", "active": false },
{ "id": "dtk_farbe", "folder": "bg", "type": "WMS", "order": -1, "title": "DTK5 farbig", "attribution": "LVermGeo", "url": "https://geo4.service24.rlp.de/wms/dtk5_rp.fcgi?", "name": "rp_dtk5", "active": false }, { "id": "dtk_farbe", "folder": "bg", "type": "WMS", "order": -1, "title": "DTK5 farbig", "attribution": "LVermGeo", "url": "https://geo4.service24.rlp.de/wms/dtk5_rp.fcgi?", "name": "rp_dtk5", "active": false },

File diff suppressed because it is too large Load Diff