Merge branch 'master' into 138_New_map_client

# Conflicts:
#	konova/models/geometry.py
#	konova/urls.py
#	locale/de/LC_MESSAGES/django.mo
#	locale/de/LC_MESSAGES/django.po
pull/166/head
mpeltriaux 2 years ago
commit c0595760ab

@ -132,6 +132,7 @@ class InterventionAPISerializerV1(AbstractModelAPISerializerV1,
id__in=payments
)
obj.payments.set(payments)
obj.send_data_to_egon()
return obj
def create_model_from_json(self, json_model, user):
@ -197,7 +198,7 @@ class InterventionAPISerializerV1(AbstractModelAPISerializerV1,
obj.legal.save()
obj.save()
obj.mark_as_edited(user)
obj.mark_as_edited(user, edit_comment="API update")
celery_update_parcels.delay(obj.geometry.id)

@ -75,7 +75,10 @@ class AbstractModelAPISerializerV1(AbstractModelAPISerializer):
Returns:
"""
if json_str is None or len(json_str) == 0:
if json_str is None:
return None
json_str = str(json_str)
if len(json_str) == 0:
return None
code = KonovaCode.objects.get(
atom_id=json_str,

@ -65,24 +65,23 @@ class KonovaCode(models.Model):
ret_val += ", " + self.parent.long_name
return ret_val
def add_children(self):
def add_children(self, order_by: str = "long_name"):
""" Adds all children (resurcively until leaf) as .children to the KonovaCode
Returns:
code (KonovaCode): The manipulated KonovaCode instance
"""
if self.is_leaf:
return None
return self
children = KonovaCode.objects.filter(
code_lists__in=self.code_lists.all(),
parent=self
).order_by(
"long_name"
order_by
)
self.children = children
for child in children:
child.add_children()
child.add_children(order_by)
return self

@ -17,7 +17,8 @@ from codelist.models import KonovaCode
from codelist.settings import CODELIST_BIOTOPES_ID, CODELIST_COMPENSATION_ACTION_ID, CODELIST_BIOTOPES_EXTRA_CODES_ID, \
CODELIST_COMPENSATION_ACTION_DETAIL_ID
from compensation.models import CompensationDocument, EcoAccountDocument
from intervention.inputs import CompensationActionTreeCheckboxSelectMultiple
from intervention.inputs import CompensationActionTreeCheckboxSelectMultiple, \
CompensationStateTreeRadioSelect
from konova.contexts import BaseContext
from konova.forms import BaseModalForm, NewDocumentModalForm, RemoveModalForm
from konova.models import DeadlineType
@ -128,6 +129,7 @@ class EditPaymentModalForm(NewPaymentForm):
payment.comment = self.cleaned_data.get("comment", None)
payment.save()
self.instance.mark_as_edited(self.user, self.request, edit_comment=PAYMENT_EDITED)
self.instance.send_data_to_egon()
return payment
@ -155,22 +157,12 @@ class NewStateModalForm(BaseModalForm):
What has been on this area before changes/compensations have been applied and what will be the result ('after')?
"""
biotope_type = forms.ModelChoiceField(
biotope_type = forms.ChoiceField(
label=_("Biotope Type"),
label_suffix="",
required=True,
help_text=_("Select the biotope type"),
queryset=KonovaCode.objects.filter(
is_archived=False,
is_leaf=True,
code_lists__in=[CODELIST_BIOTOPES_ID],
),
widget=autocomplete.ModelSelect2(
url="codes-biotope-autocomplete",
attrs={
"data-placeholder": _("Biotope Type"),
}
),
widget=CompensationStateTreeRadioSelect(),
)
biotope_extra = forms.ModelMultipleChoiceField(
label=_("Biotope additional type"),
@ -208,6 +200,16 @@ class NewStateModalForm(BaseModalForm):
super().__init__(*args, **kwargs)
self.form_title = _("New state")
self.form_caption = _("Insert data for the new state")
choices = KonovaCode.objects.filter(
code_lists__in=[CODELIST_BIOTOPES_ID],
is_archived=False,
is_leaf=True,
).values_list("id", flat=True)
choices = [
(choice, choice)
for choice in choices
]
self.fields["biotope_type"].choices = choices
def save(self, is_before_state: bool = False):
state = self.instance.add_state(self, is_before_state)
@ -270,8 +272,9 @@ class EditCompensationStateModalForm(NewStateModalForm):
self.state = kwargs.pop("state", None)
super().__init__(*args, **kwargs)
self.form_title = _("Edit state")
biotope_type_id = self.state.biotope_type.id if self.state.biotope_type else None
form_data = {
"biotope_type": self.state.biotope_type,
"biotope_type": biotope_type_id,
"biotope_extra": self.state.biotope_type_details.all(),
"surface": self.state.surface,
}
@ -279,7 +282,8 @@ class EditCompensationStateModalForm(NewStateModalForm):
def save(self, is_before_state: bool = False):
state = self.state
state.biotope_type = self.cleaned_data.get("biotope_type", None)
biotope_type_id = self.cleaned_data.get("biotope_type", None)
state.biotope_type = KonovaCode.objects.get(id=biotope_type_id)
state.biotope_type_details.set(self.cleaned_data.get("biotope_extra", []))
state.surface = self.cleaned_data.get("surface", None)
state.save()

@ -8,6 +8,8 @@ Created on: 16.11.21
import shutil
from django.contrib import messages
from codelist.models import KonovaCode
from user.models import User, Team
from django.db import models, transaction
from django.db.models import QuerySet, Sum
@ -142,8 +144,10 @@ class AbstractCompensation(BaseObject, GeoReferencedMixin):
"""
form_data = form.cleaned_data
with transaction.atomic():
biotope_type_id = form_data["biotope_type"]
code = KonovaCode.objects.get(id=biotope_type_id)
state = CompensationState.objects.create(
biotope_type=form_data["biotope_type"],
biotope_type=code,
surface=form_data["surface"],
)
state_additional_types = form_data["biotope_extra"]

@ -124,7 +124,7 @@
</div>
</div>
<div class="row">
{% include 'konova/includes/parcels.html' %}
{% include 'konova/includes/parcels/parcels.html' %}
</div>
<div class="row">
{% include 'konova/includes/comment_card.html' %}

@ -106,7 +106,7 @@
</div>
</div>
<div class="row">
{% include 'konova/includes/parcels.html' %}
{% include 'konova/includes/parcels/parcels.html' %}
</div>
<div class="row">
{% include 'konova/includes/comment_card.html' %}

@ -40,7 +40,7 @@
</div>
</div>
<div class="row">
{% include 'konova/includes/parcels.html' %}
{% include 'konova/includes/parcels/parcels.html' %}
</div>
<div class="row">
{% include 'konova/includes/report/qrcodes.html' %}

@ -53,7 +53,7 @@
</div>
</div>
<div class="row">
{% include 'konova/includes/parcels.html' %}
{% include 'konova/includes/parcels/parcels.html' %}
</div>
<div class="row">
{% include 'konova/includes/report/qrcodes.html' %}

@ -92,7 +92,7 @@
</div>
</div>
<div class="row">
{% include 'konova/includes/parcels.html' %}
{% include 'konova/includes/parcels/parcels.html' %}
</div>
<div class="row">
{% include 'konova/includes/comment_card.html' %}

@ -40,7 +40,7 @@
</div>
</div>
<div class="row">
{% include 'konova/includes/parcels.html' %}
{% include 'konova/includes/parcels/parcels.html' %}
</div>
<div class="row">
{% include 'konova/includes/report/qrcodes.html' %}

@ -1,6 +1,6 @@
from django import forms
from codelist.models import KonovaCode
from codelist.settings import CODELIST_COMPENSATION_ACTION_ID
from codelist.settings import CODELIST_COMPENSATION_ACTION_ID, CODELIST_BIOTOPES_ID
class DummyFilterInput(forms.HiddenInput):
@ -38,7 +38,17 @@ class TreeCheckboxSelectMultiple(forms.CheckboxSelectMultiple):
""" Provides multiple selection of parent-child data
"""
template_name = "konova/widgets/checkbox-tree-select.html"
template_name = "konova/widgets/tree/checkbox/checkbox-tree-select.html"
class meta:
abstract = True
class TreeRadioSelect(forms.RadioSelect):
""" Provides single selection of parent-child data
"""
template_name = "konova/widgets/tree/radio/radio-tree-select.html"
class meta:
abstract = True
@ -68,6 +78,30 @@ class KonovaCodeTreeCheckboxSelectMultiple(TreeCheckboxSelectMultiple):
return context
class KonovaCodeTreeRadioSelect(TreeRadioSelect):
""" Provides single selection of KonovaCode
"""
filter = None
def __init__(self, *args, **kwargs):
self.code_list = kwargs.pop("code_list", None)
self.filter = kwargs.pop("filter", {})
super().__init__(*args, **kwargs)
def get_context(self, name, value, attrs):
context = super().get_context(name, value, attrs)
codes = KonovaCode.objects.filter(
**self.filter,
)
codes = [
parent_code.add_children()
for parent_code in codes
]
context["codes"] = codes
return context
class CompensationActionTreeCheckboxSelectMultiple(KonovaCodeTreeCheckboxSelectMultiple):
""" Provides multiple selection of CompensationActions
@ -79,4 +113,31 @@ class CompensationActionTreeCheckboxSelectMultiple(KonovaCodeTreeCheckboxSelectM
self.filter = {
"code_lists__in": [CODELIST_COMPENSATION_ACTION_ID],
"parent": None,
}
}
class CompensationStateTreeRadioSelect(KonovaCodeTreeRadioSelect):
""" Provides single selection of CompensationState
"""
filter = None
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.filter = {
"code_lists__in": [CODELIST_BIOTOPES_ID],
"parent": None,
"is_archived": False,
}
def get_context(self, name, value, attrs):
context = super().get_context(name, value, attrs)
codes = KonovaCode.objects.filter(
**self.filter,
)
codes = [
parent_code.add_children("short_name")
for parent_code in codes
]
context["codes"] = codes
return context

@ -145,7 +145,6 @@ class Intervention(BaseObject, ShareableObjectMixin, RecordableObjectMixin, Chec
def set_recorded(self, user: User) -> UserActionLogEntry:
log_entry = super().set_recorded(user)
self.add_log_entry_to_compensations(log_entry)
self.send_data_to_egon()
return log_entry
def add_log_entry_to_compensations(self, log_entry: UserActionLogEntry):
@ -183,6 +182,8 @@ class Intervention(BaseObject, ShareableObjectMixin, RecordableObjectMixin, Chec
intervention=self,
)
self.mark_as_edited(user, form.request, edit_comment=PAYMENT_ADDED)
self.send_data_to_egon()
return pay
def add_revocation(self, form):
@ -347,6 +348,7 @@ class Intervention(BaseObject, ShareableObjectMixin, RecordableObjectMixin, Chec
with transaction.atomic():
payment.delete()
self.mark_as_edited(user, request=form.request, edit_comment=PAYMENT_REMOVED)
self.send_data_to_egon()
class InterventionDocument(AbstractDocument):

@ -139,7 +139,7 @@
</div>
</div>
<div class="row">
{% include 'konova/includes/parcels.html' %}
{% include 'konova/includes/parcels/parcels.html' %}
</div>
<div class="row">
{% include 'konova/includes/comment_card.html' %}

@ -99,7 +99,7 @@
</div>
</div>
<div class="row">
{% include 'konova/includes/parcels.html' %}
{% include 'konova/includes/parcels/parcels.html' %}
</div>
<div class="row">
{% include 'konova/includes/report/qrcodes.html' %}

@ -156,10 +156,20 @@ class EgonGmlBuilder:
def build_gml(self):
comp_type, comp_type_code = self._gen_kompensationsArt()
payment_date = self.intervention.payments.first().due_on
if payment_date is not None:
payment = self.intervention.payments.first()
payment_date = None
if payment is not None:
payment_date = payment.due_on
payment_date = payment_date.strftime(DEFAULT_DATE_FORMAT)
cons_office = self.intervention.responsible.conservation_office
reg_office = self.intervention.responsible.registration_office
law = self.intervention.legal.laws.first()
process_type = self.intervention.legal.process_type
handler = self.intervention.responsible.handler
reg_date = self.intervention.legal.registration_date
bind_date = self.intervention.legal.binding_date
xml_dict = {
"wfs:FeatureCollection": {
"@xmlns:wfs": "http://www.opengis.net/wfs",
@ -174,12 +184,12 @@ class EgonGmlBuilder:
"oneo:azZulassungsstelle": self.intervention.responsible.registration_file_number,
"oneo:bemerkungZulassungsstelle": None,
"oneo:eintragungsstelle": {
"@xlink:href": f"http://register.naturschutz.rlp.de/repository/services/referenzliste/907/{self.intervention.responsible.conservation_office.atom_id}",
"#text": self.intervention.responsible.conservation_office.long_name
"@xlink:href": f"http://register.naturschutz.rlp.de/repository/services/referenzliste/907/{cons_office.atom_id if cons_office else None}",
"#text": cons_office.long_name if cons_office else None
},
"oneo:zulassungsstelle": {
"@xlink:href": f"http://register.naturschutz.rlp.de/repository/services/referenzliste/1053/{self.intervention.responsible.registration_office.atom_id}",
"#text": self.intervention.responsible.registration_office.long_name
"@xlink:href": f"http://register.naturschutz.rlp.de/repository/services/referenzliste/1053/{reg_office.atom_id if reg_office else None}",
"#text": reg_office.long_name if reg_office else None
},
"oneo:ersatzzahlung": self._sum_all_payments(),
"oneo:kompensationsart": {
@ -187,20 +197,20 @@ class EgonGmlBuilder:
"#text": comp_type
},
"oneo:verfahrensrecht": {
"@xlink:href": f"http://register.naturschutz.rlp.de/repository/services/referenzliste/1048/{self.intervention.legal.laws.first().atom_id}",
"#text": self.intervention.legal.laws.first().short_name
"@xlink:href": f"http://register.naturschutz.rlp.de/repository/services/referenzliste/1048/{law.atom_id if law else None}",
"#text": law.short_name if law else None
},
"oneo:verfahrenstyp": {
"@xlink:href": f"http://register.naturschutz.rlp.de/repository/services/referenzliste/44382/{self.intervention.legal.process_type.atom_id}",
"#text": self.intervention.legal.process_type.long_name,
"@xlink:href": f"http://register.naturschutz.rlp.de/repository/services/referenzliste/44382/{process_type.atom_id if process_type else None}",
"#text": process_type.long_name if process_type else None,
},
"oneo:eingreifer": {
"oneo:Eingreifer": {
"oneo:art": {
"@xlink:href": f"http://register.naturschutz.rlp.de/repository/services/referenzliste/1053/{self.intervention.responsible.handler.type.atom_id}",
"#text": self.intervention.responsible.handler.type.long_name,
"@xlink:href": f"http://register.naturschutz.rlp.de/repository/services/referenzliste/1053/{handler.type.atom_id if handler.type else None}",
"#text": handler.type.long_name if handler.type else None,
},
"oneo:bemerkung": self.intervention.responsible.handler.detail,
"oneo:bemerkung": handler.detail if handler else None,
}
},
"oneo:erfasser": {
@ -212,8 +222,8 @@ class EgonGmlBuilder:
"oneo:zulassung": {
"oneo:Zulassungstermin": {
"oneo:bauBeginn": payment_date,
"oneo:erlass": self.intervention.legal.registration_date.strftime(DEFAULT_DATE_FORMAT),
"oneo:rechtsKraft": self.intervention.legal.binding_date.strftime(DEFAULT_DATE_FORMAT),
"oneo:erlass": reg_date.strftime(DEFAULT_DATE_FORMAT) if reg_date else None,
"oneo:rechtsKraft": bind_date.strftime(DEFAULT_DATE_FORMAT) if bind_date else None,
}
},
"oneo:geometrie": {

@ -266,14 +266,11 @@ def detail_view(request: HttpRequest, id: str):
instance=intervention,
)
parcels = intervention.get_underlying_parcels()
context = {
"obj": intervention,
"compensations": compensations,
"has_access": is_data_shared,
"geom_form": geom_form,
"parcels": parcels,
"is_default_member": in_group(_user, DEFAULT_GROUP),
"is_zb_member": in_group(_user, ZB_GROUP),
"is_ets_member": in_group(_user, ETS_GROUP),

@ -118,32 +118,38 @@ class Geometry(BaseResource):
_now = timezone.now()
underlying_parcels = []
for result in fetched_parcels:
fetched_parcel = result[typename]
parcel_properties = result["properties"]
# There could be parcels which include the word 'Flur',
# which needs to be deleted and just keep the numerical values
## THIS CAN BE REMOVED IN THE FUTURE, WHEN 'Flur' WON'T OCCUR ANYMORE!
flr_val = fetched_parcel["ave:flur"].replace("Flur ", "")
flr_val = parcel_properties["flur"].replace("Flur ", "")
district = District.objects.get_or_create(
key=fetched_parcel["ave:kreisschl"],
name=fetched_parcel["ave:kreis"],
key=parcel_properties["kreisschl"],
name=parcel_properties["kreis"],
)[0]
municipal = Municipal.objects.get_or_create(
key=fetched_parcel["ave:gmdschl"],
name=fetched_parcel["ave:gemeinde"],
key=parcel_properties["gmdschl"],
name=parcel_properties["gemeinde"],
district=district,
)[0]
parcel_group = ParcelGroup.objects.get_or_create(
key=fetched_parcel["ave:gemaschl"],
name=fetched_parcel["ave:gemarkung"],
key=parcel_properties["gemaschl"],
name=parcel_properties["gemarkung"],
municipal=municipal,
)[0]
flrstck_nnr = parcel_properties['flstnrnen']
if not flrstck_nnr:
flrstck_nnr = None
flrstck_zhlr = parcel_properties['flstnrzae']
if not flrstck_zhlr:
flrstck_zhlr = None
parcel_obj = Parcel.objects.get_or_create(
district=district,
municipal=municipal,
parcel_group=parcel_group,
flr=flr_val,
flrstck_nnr=fetched_parcel['ave:flstnrnen'],
flrstck_zhlr=fetched_parcel['ave:flstnrzae'],
flrstck_nnr=flrstck_nnr,
flrstck_zhlr=flrstck_zhlr,
)[0]
parcel_obj.district = district
parcel_obj.updated_on = _now
@ -151,6 +157,7 @@ class Geometry(BaseResource):
underlying_parcels.append(parcel_obj)
# Update the linked parcels
self.parcels.clear()
self.parcels.set(underlying_parcels)
# Set the calculated_on intermediate field, so this related data will be found on lookups
@ -171,7 +178,6 @@ class Geometry(BaseResource):
Returns:
parcels (QuerySet): The related parcels as queryset
"""
parcels = self.parcels.filter(
parcelintersection__calculated_on__isnull=False,
).prefetch_related(
@ -183,6 +189,17 @@ class Geometry(BaseResource):
return parcels
def count_underlying_parcels(self):
""" Getter for number of underlying parcels
Returns:
"""
num_parcels = self.parcels.filter(
parcelintersection__calculated_on__isnull=False,
).count()
return num_parcels
def as_feature_collection(self, srid=DEFAULT_SRID_RLP):
""" Returns a FeatureCollection structure holding all polygons of the MultiPolygon as single features
@ -211,7 +228,6 @@ class Geometry(BaseResource):
return geojson
class GeometryConflict(UuidModel):
"""
Geometry conflicts model

@ -652,10 +652,21 @@ class GeoReferencedMixin(models.Model):
Returns:
parcels (Iterable): An empty list or a Queryset
"""
result = []
if self.geometry is not None:
return self.geometry.get_underlying_parcels()
else:
return []
result = self.geometry.get_underlying_parcels()
return result
def count_underlying_parcels(self):
""" Getter for number of underlying parcels
Returns:
"""
result = 0
if self.geometry is not None:
result = self.geometry.count_underlying_parcels()
return result
def set_geometry_conflict_message(self, request: HttpRequest):
if self.geometry is None:

@ -262,4 +262,13 @@ Similar to bootstraps 'shadow-lg'
padding-left: 2em;
}
*/
*/
.collapse-icn > i{
transition: all 0.3s ease;
}
.collapsed .collapse-icn > i{
transform: rotate(-90deg);
}
.tree-label.badge{
font-size: 90%;
}

@ -0,0 +1,22 @@
{% load l10n i18n %}
{% for parcel in parcels %}
{% if forloop.last and next_page %}
<tr hx-get="{% url 'geometry-parcels-content' geom_id next_page %}"
hx-trigger="intersect once"
hx-swap="afterend">
<td>{{parcel.parcel_group.name|default_if_none:"-"}}</td>
<td>{{parcel.parcel_group.key|default_if_none:"-"}}</td>
<td>{{parcel.flr|default_if_none:"-"|unlocalize}}</td>
<td>{{parcel.flrstck_zhlr|default_if_none:"-"|unlocalize}}</td>
<td>{{parcel.flrstck_nnr|default_if_none:"-"|unlocalize}}</td>
</tr>
{% else %}
<tr>
<td>{{parcel.parcel_group.name|default_if_none:"-"}}</td>
<td>{{parcel.parcel_group.key|default_if_none:"-"}}</td>
<td>{{parcel.flr|default_if_none:"-"|unlocalize}}</td>
<td>{{parcel.flrstck_zhlr|default_if_none:"-"|unlocalize}}</td>
<td>{{parcel.flrstck_nnr|default_if_none:"-"|unlocalize}}</td>
</tr>
{% endif %}
{% endfor %}

@ -5,6 +5,11 @@
{% trans 'Parcels can not be calculated, since no geometry is given.' %}
</article>
{% else %}
<div>
<h4 class="">
<span class="badge rlp-r">{{num_parcels}}</span>
{% trans 'Parcels found' %}</h4>
</div>
<table id="upper-spatial-table" class="table table-hover">
<thead>
<tr>
@ -37,16 +42,7 @@
</tr>
</thead>
<tbody>
{% for parcel in parcels %}
<tr>
<td>{{parcel.parcel_group.name|default_if_none:"-"}}</td>
<td>{{parcel.parcel_group.key|default_if_none:"-"}}</td>
<td>{{parcel.flr|default_if_none:"-"|unlocalize}}</td>
<td>{{parcel.flrstck_zhlr|default_if_none:"-"|unlocalize}}</td>
<td>{{parcel.flrstck_nnr|default_if_none:"-"|unlocalize}}</td>
</tr>
{% endfor %}
{% include 'konova/includes/parcels/parcel_table_content.html' %}
</tbody>
</table>
{% endif %}

@ -2,18 +2,23 @@
{% for code in codes %}
<div class="ml-4 tree-element">
<label class="tree-label" role="{% if not code.is_leaf%}button{% endif %}" for="input_{{code.pk|unlocalize}}" id="{{code.pk|unlocalize}}" data-toggle="collapse" data-target="#children_{{code.pk|unlocalize}}" aria-expanded="true" aria-controls="children_{{code.pk|unlocalize}}">
<label class="tree-label collapsed" role="{% if not code.is_leaf%}button{% endif %}" for="input_{{code.pk|unlocalize}}" id="{{code.pk|unlocalize}}" data-toggle="collapse" data-target="#children_{{code.pk|unlocalize}}" aria-expanded="true" aria-controls="children_{{code.pk|unlocalize}}">
{% if code.is_leaf%}
<input class="tree-input" id="input_{{code.pk|unlocalize}}" name="{{ widget.name }}" type="checkbox" value="{{code.pk|unlocalize}}" {% if code.pk|unlocalize in widget.value %}checked{% endif %}/>
{% else %}
{% fa5_icon 'angle-right' %}
<span class="collapse-icn">
{% fa5_icon 'angle-down' %}
</span>
{% endif %}
{% if code.short_name %}
({{code.short_name}})
{% endif %}
{{code.long_name}}
</label>
{% if not code.is_leaf %}
<div id="children_{{code.pk|unlocalize}}" data-toggle="collapse" class="collapse tree-element-children">
{% with code.children as codes %}
{% include 'konova/widgets/checkbox-tree-select-content.html' %}
{% include 'konova/widgets/tree/checkbox/checkbox-tree-select-content.html' %}
{% endwith %}
</div>
{% endif %}

@ -5,7 +5,7 @@
</div>
<div id="tree-root">
{% include 'konova/widgets/checkbox-tree-select-content.html' %}
{% include 'konova/widgets/tree/checkbox/checkbox-tree-select-content.html' %}
</div>
<script>
@ -47,9 +47,12 @@
}
);
if(val.length > 0){
// Hide everything
allTreeElements.hide()
// Now show again everything matching the query
allTreeElementsContain.show()
}else{
// Show everything if no query exists
allTreeElements.show()
}
}

@ -0,0 +1,25 @@
{% load l10n fontawesome_5 %}
{% for code in codes %}
<div class="ml-4 tree-element">
<label class="tree-label collapsed" role="{% if not code.is_leaf%}button{% endif %}" for="input_{{code.pk|unlocalize}}" id="{{code.pk|unlocalize}}" data-toggle="collapse" data-target="#children_{{code.pk|unlocalize}}" aria-expanded="true" aria-controls="children_{{code.pk|unlocalize}}">
{% if code.is_leaf%}
<input class="tree-input" id="input_{{code.pk|unlocalize}}" name="{{ widget.name }}" type="radio" value="{{code.pk|unlocalize}}" {% if code.pk|unlocalize in widget.value %}checked{% endif %}/>
{% else %}
<span class="collapse-icn">
{% fa5_icon 'angle-down' %}
</span>
{% endif %}
{% if code.short_name %}
({{code.short_name}})
{% endif %}
{{code.long_name}}
</label>
{% if not code.is_leaf %}
<div id="children_{{code.pk|unlocalize}}" data-toggle="collapse" class="collapse tree-element-children">
{% with code.children as codes %}
{% include 'konova/widgets/tree/radio/radio-tree-select-content.html' %}
{% endwith %}
</div>
{% endif %}
</div>
{% endfor %}

@ -0,0 +1,62 @@
{% load i18n %}
<div class="ml-4 mb-4">
<input id="tree-search-input" class="form-control" type="text" placeholder="{% trans 'Search' %}"/>
</div>
<div id="tree-root">
{% include 'konova/widgets/tree/radio/radio-tree-select-content.html' %}
</div>
<script>
function toggleSelectedCssClass(element){
element = $(element);
var cssClass = "badge rlp-r"
// Find all already tagged input elements and reset them to be untagged
var allTaggedInputs = $("#tree-root").find(".badge.rlp-r")
allTaggedInputs.removeClass(cssClass)
// Find all parents of selected element
var parentElements = element.parents(".tree-element-children")
// Tag parents of element
var parentLabels = parentElements.siblings(".tree-label");
parentLabels.addClass(cssClass);
}
function changeHandler(event){
toggleSelectedCssClass(this);
}
function searchInputHandler(event){
var elem = $(this);
var val = elem.val()
var allTreeElements = $(".tree-element")
var allTreeElementsContain = $(".tree-element").filter(function(){
var reg = new RegExp(val, "i");
return reg.test($(this).text());
}
);
if(val.length > 0){
// Hide everything
allTreeElements.hide()
// Now show again everything matching the query
allTreeElementsContain.show()
}else{
// Show everything if no query exists
allTreeElements.show()
}
}
// Add event listener on search input
$("#tree-search-input").keyup(searchInputHandler)
// Add event listener on changed checkboxes
$(".tree-input").change(changeHandler);
// initialize all pre-checked checkboxes (e.g. on an edit form)
var preCheckedElements = $(".tree-input:checked");
preCheckedElements.each(function (index, element){
toggleSelectedCssClass(element);
})
</script>

@ -24,7 +24,7 @@ from konova.autocompletes import EcoAccountAutocomplete, \
ShareTeamAutocomplete, HandlerCodeAutocomplete
from konova.settings import SSO_SERVER, SSO_PUBLIC_KEY, SSO_PRIVATE_KEY, DEBUG
from konova.sso.sso import KonovaSSOClient
from konova.views import logout_view, home_view, get_geom_parcels, map_client_proxy_view
from konova.views import logout_view, home_view, get_geom_parcels, get_geom_parcels_content, map_client_proxy_view
sso_client = KonovaSSOClient(SSO_SERVER, SSO_PUBLIC_KEY, SSO_PRIVATE_KEY)
urlpatterns = [
@ -40,7 +40,8 @@ urlpatterns = [
path('cl/', include("codelist.urls")),
path('analysis/', include("analysis.urls")),
path('api/', include("api.urls")),
path('geom/<id>/parcels', get_geom_parcels, name="geometry-parcels"),
path('geom/<id>/parcels/', get_geom_parcels, name="geometry-parcels"),
path('geom/<id>/parcels/<int:page>', get_geom_parcels_content, name="geometry-parcels-content"),
path('client/proxy', map_client_proxy_view, name="map-client-proxy"),
# Autocomplete paths for all apps

@ -5,12 +5,13 @@ Contact: michel.peltriaux@sgdnord.rlp.de
Created on: 17.12.21
"""
import json
from abc import abstractmethod
from json import JSONDecodeError
from time import sleep
import requests
import xmltodict
from django.contrib.gis.db.models.functions import AsGML, Transform
from django.contrib.gis.db.models.functions import AsGML, Transform, MakeValid
from requests.auth import HTTPDigestAuth
from konova.settings import DEFAULT_SRID_RLP, PARCEL_WFS_USER, PARCEL_WFS_PW, PROXIES
@ -90,7 +91,7 @@ class ParcelWFSFetcher(AbstractWFSFetcher):
).annotate(
transformed=Transform(srid=filter_srid, expression="geom")
).annotate(
gml=AsGML('transformed')
gml=AsGML(MakeValid('transformed'))
).first().gml
spatial_filter = f"<Filter><{geometry_operation}><PropertyName>{self.geometry_property_name}</PropertyName>{geom_gml}</{geometry_operation}></Filter>"
return spatial_filter
@ -115,7 +116,7 @@ class ParcelWFSFetcher(AbstractWFSFetcher):
geometry_operation,
filter_srid
)
_filter = f'<wfs:GetFeature service="WFS" version="{self.version}" xmlns:wfs="http://www.opengis.net/wfs/2.0" xmlns:fes="http://www.opengis.net/fes/2.0" xmlns:myns="http://www.someserver.com/myns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs/2.0 http://schemas.opengis.net/wfs/2.0.0/wfs.xsd" count="{self.count}" startindex="{start_index}"><wfs:Query typeNames="{typenames}">{spatial_filter}</wfs:Query></wfs:GetFeature>'
_filter = f'<wfs:GetFeature service="WFS" version="{self.version}" xmlns:wfs="http://www.opengis.net/wfs/2.0" xmlns:fes="http://www.opengis.net/fes/2.0" xmlns:myns="http://www.someserver.com/myns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs/2.0 http://schemas.opengis.net/wfs/2.0.0/wfs.xsd" count="{self.count}" startindex="{start_index}" outputFormat="application/json; subtype=geojson"><wfs:Query typeNames="{typenames}">{spatial_filter}</wfs:Query></wfs:GetFeature>'
return _filter
def get_features(self,
@ -139,7 +140,7 @@ class ParcelWFSFetcher(AbstractWFSFetcher):
Returns:
features (list): A list of returned features
"""
features = []
found_features = []
while start_index is not None:
post_body = self._create_post_data(
spatial_operator,
@ -155,19 +156,11 @@ class ParcelWFSFetcher(AbstractWFSFetcher):
)
content = response.content.decode("utf-8")
content = xmltodict.parse(content)
collection = content.get(
"wfs:FeatureCollection",
{},
)
# Check if collection is an exception and does not contain the requested data
if len(collection) == 0:
exception = content.get(
"ows:ExceptionReport",
{}
)
if len(exception) > 0 and rerun_on_exception:
try:
# Check if collection is an exception and does not contain the requested data
content = json.loads(content)
except JSONDecodeError as e:
if rerun_on_exception:
# Wait a second before another try
sleep(1)
self.get_features(
@ -177,22 +170,21 @@ class ParcelWFSFetcher(AbstractWFSFetcher):
start_index,
rerun_on_exception=False
)
members = collection.get(
"wfs:member",
None,
)
if members is not None:
if len(members) > 1:
# extend feature list with found list of new feature members
features += members
else:
# convert single found feature member into list and extent feature list
features += [members]
e.msg += content
raise e
fetched_features = content.get(
"features",
{},
)
if collection.get("@next", None) is not None:
start_index += self.count
else:
found_features += fetched_features
if len(fetched_features) < self.count:
# The response was not 'full', so we got everything to fetch
start_index = None
else:
# If a 'full' response returned, there might be more to fetch. Increase the start_index!
start_index += self.count
return features
return found_features

@ -113,12 +113,12 @@ def get_geom_parcels(request: HttpRequest, id: str):
id (str): The geometry's id
Returns:
A rendered piece of HTML
"""
# HTTP code 286 states that the HTMX should stop polling for updates
# https://htmx.org/docs/#polling
status_code = 286
template = "konova/includes/parcel_table.html"
template = "konova/includes/parcels/parcel_table_frame.html"
geom = get_object_or_404(Geometry, id=id)
parcels = geom.get_underlying_parcels()
geos_geom = geom.geom
@ -136,9 +136,20 @@ def get_geom_parcels(request: HttpRequest, id: str):
parcels = parcels.order_by("-municipal", "flr", "flrstck_zhlr", "flrstck_nnr")
municipals = parcels.order_by("municipal").distinct("municipal").values("municipal__id")
municipals = Municipal.objects.filter(id__in=municipals)
rpp = 100
num_all_parcels = parcels.count()
parcels = parcels[:rpp]
next_page = 1
if len(parcels) < rpp:
next_page = None
context = {
"num_parcels": num_all_parcels,
"parcels": parcels,
"municipals": municipals,
"geom_id": str(id),
"next_page": next_page,
}
html = render_to_string(template, context, request)
return HttpResponse(html, status=status_code)
@ -146,6 +157,49 @@ def get_geom_parcels(request: HttpRequest, id: str):
return HttpResponse(None, status=404)
@login_required
def get_geom_parcels_content(request: HttpRequest, id: str, page: int):
""" Getter for infinite scroll of HTMX
Returns parcels of a specific page/slice of the found parcel set.
Implementation of infinite scroll htmx example: https://htmx.org/examples/infinite-scroll/
Args:
request (HttpRequest): The incoming request
id (str): The geometry's id
page (int): The requested page number
Returns:
A rendered piece of HTML
"""
if page < 0:
raise AssertionError("Parcel page can not be negative")
# HTTP code 286 states that the HTMX should stop polling for updates
# https://htmx.org/docs/#polling
status_code = 286
template = "konova/includes/parcels/parcel_table_content.html"
geom = get_object_or_404(Geometry, id=id)
parcels = geom.get_underlying_parcels()
parcels = parcels.order_by("-municipal", "flr", "flrstck_zhlr", "flrstck_nnr")
rpp = 100
from_p = rpp * (page-1)
to_p = rpp * (page)
next_page = page + 1
parcels = parcels[from_p:to_p]
if len(parcels) < rpp:
next_page = None
context = {
"parcels": parcels,
"geom_id": str(id),
"next_page": next_page,
}
html = render_to_string(template, context, request)
return HttpResponse(html, status=status_code)
def get_404_view(request: HttpRequest, exception=None):
""" Returns a 404 handling view

Binary file not shown.

@ -3,9 +3,9 @@
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#: compensation/filters.py:123 compensation/forms/modalForms.py:36
#: compensation/forms/modalForms.py:47 compensation/forms/modalForms.py:63
#: compensation/forms/modalForms.py:358 compensation/forms/modalForms.py:466
#: compensation/filters.py:123 compensation/forms/modalForms.py:37
#: compensation/forms/modalForms.py:48 compensation/forms/modalForms.py:64
#: compensation/forms/modalForms.py:362 compensation/forms/modalForms.py:470
#: intervention/forms/forms.py:54 intervention/forms/forms.py:174
#: intervention/forms/forms.py:186 intervention/forms/modalForms.py:150
#: intervention/forms/modalForms.py:163 intervention/forms/modalForms.py:176
@ -26,7 +26,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-04-20 09:51+0200\n"
"POT-Creation-Date: 2022-05-11 13:41+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -97,7 +97,7 @@ msgstr ""
#: analysis/templates/analysis/reports/includes/eco_account/amount.html:3
#: analysis/templates/analysis/reports/includes/intervention/amount.html:3
#: analysis/templates/analysis/reports/includes/old_data/amount.html:3
#: compensation/forms/modalForms.py:450
#: compensation/forms/modalForms.py:454
#: compensation/templates/compensation/detail/eco_account/includes/deductions.html:34
#: intervention/templates/intervention/detail/includes/deductions.html:31
msgid "Amount"
@ -215,7 +215,7 @@ msgstr "Abbuchungen"
#: analysis/templates/analysis/reports/includes/eco_account/deductions.html:9
#: analysis/templates/analysis/reports/includes/eco_account/deductions.html:11
#: compensation/forms/modalForms.py:195
#: compensation/forms/modalForms.py:187
#: compensation/templates/compensation/detail/compensation/includes/states-after.html:36
#: compensation/templates/compensation/detail/compensation/includes/states-before.html:36
#: compensation/templates/compensation/detail/eco_account/includes/states-after.html:36
@ -248,7 +248,7 @@ msgid "Compensation"
msgstr "Kompensation"
#: analysis/templates/analysis/reports/includes/intervention/compensated_by.html:21
#: compensation/forms/modalForms.py:76
#: compensation/forms/modalForms.py:77
msgid "Payment"
msgstr "Zahlung"
@ -354,8 +354,8 @@ msgstr "Aussagekräftiger Titel"
msgid "Compensation XY; Location ABC"
msgstr "Kompensation XY; Flur ABC"
#: compensation/forms/forms.py:57 compensation/forms/modalForms.py:62
#: compensation/forms/modalForms.py:357 compensation/forms/modalForms.py:465
#: compensation/forms/forms.py:57 compensation/forms/modalForms.py:63
#: compensation/forms/modalForms.py:361 compensation/forms/modalForms.py:469
#: compensation/templates/compensation/detail/compensation/includes/actions.html:35
#: compensation/templates/compensation/detail/compensation/includes/deadlines.html:34
#: compensation/templates/compensation/detail/compensation/includes/documents.html:34
@ -373,7 +373,7 @@ msgstr "Kompensation XY; Flur ABC"
msgid "Comment"
msgstr "Kommentar"
#: compensation/forms/forms.py:59 compensation/forms/modalForms.py:467
#: compensation/forms/forms.py:59 compensation/forms/modalForms.py:471
#: intervention/forms/forms.py:200
msgid "Additional comment"
msgstr "Zusätzlicher Kommentar"
@ -479,70 +479,70 @@ msgstr "Ökokonto XY; Flur ABC"
msgid "Edit Eco-Account"
msgstr "Ökokonto bearbeiten"
#: compensation/forms/modalForms.py:37
#: compensation/forms/modalForms.py:38
msgid "in Euro"
msgstr "in Euro"
#: compensation/forms/modalForms.py:46
#: compensation/forms/modalForms.py:47
#: intervention/templates/intervention/detail/includes/payments.html:31
msgid "Due on"
msgstr "Fällig am"
#: compensation/forms/modalForms.py:49
#: compensation/forms/modalForms.py:50
msgid "Due on which date"
msgstr "Zahlung wird an diesem Datum erwartet"
#: compensation/forms/modalForms.py:64 compensation/forms/modalForms.py:359
#: compensation/forms/modalForms.py:65 compensation/forms/modalForms.py:363
#: intervention/forms/modalForms.py:177 konova/forms.py:462
msgid "Additional comment, maximum {} letters"
msgstr "Zusätzlicher Kommentar, maximal {} Zeichen"
#: compensation/forms/modalForms.py:77
#: compensation/forms/modalForms.py:78
msgid "Add a payment for intervention '{}'"
msgstr "Neue Ersatzzahlung zu Eingriff '{}' hinzufügen"
#: compensation/forms/modalForms.py:97
#: compensation/forms/modalForms.py:98
msgid "If there is no date you can enter, please explain why."
msgstr "Falls Sie kein Datum angeben können, erklären Sie bitte weshalb."
#: compensation/forms/modalForms.py:116
#: compensation/forms/modalForms.py:117
#: intervention/templates/intervention/detail/includes/payments.html:59
msgid "Edit payment"
msgstr "Zahlung bearbeiten"
#: compensation/forms/modalForms.py:159 compensation/forms/modalForms.py:171
#: compensation/forms/modalForms.py:161
msgid "Biotope Type"
msgstr "Biotoptyp"
#: compensation/forms/modalForms.py:162
#: compensation/forms/modalForms.py:164
msgid "Select the biotope type"
msgstr "Biotoptyp wählen"
#: compensation/forms/modalForms.py:176 compensation/forms/modalForms.py:188
#: compensation/forms/modalForms.py:168 compensation/forms/modalForms.py:180
msgid "Biotope additional type"
msgstr "Zusatzbezeichnung"
#: compensation/forms/modalForms.py:179
#: compensation/forms/modalForms.py:171
msgid "Select an additional biotope type"
msgstr "Zusatzbezeichnung wählen"
#: compensation/forms/modalForms.py:198 intervention/forms/modalForms.py:366
#: compensation/forms/modalForms.py:190 intervention/forms/modalForms.py:366
msgid "in m²"
msgstr ""
#: compensation/forms/modalForms.py:209
#: compensation/forms/modalForms.py:201
msgid "New state"
msgstr "Neuer Zustand"
#: compensation/forms/modalForms.py:210
#: compensation/forms/modalForms.py:202
msgid "Insert data for the new state"
msgstr "Geben Sie die Daten des neuen Zustandes ein"
#: compensation/forms/modalForms.py:217 konova/forms.py:229
#: compensation/forms/modalForms.py:219 konova/forms.py:229
msgid "Object removed"
msgstr "Objekt entfernt"
#: compensation/forms/modalForms.py:272
#: compensation/forms/modalForms.py:274
#: compensation/templates/compensation/detail/compensation/includes/states-after.html:62
#: compensation/templates/compensation/detail/compensation/includes/states-before.html:62
#: compensation/templates/compensation/detail/eco_account/includes/states-after.html:62
@ -552,15 +552,15 @@ msgstr "Objekt entfernt"
msgid "Edit state"
msgstr "Zustand bearbeiten"
#: compensation/forms/modalForms.py:329
#: compensation/forms/modalForms.py:333
msgid "Deadline Type"
msgstr "Fristart"
#: compensation/forms/modalForms.py:332
#: compensation/forms/modalForms.py:336
msgid "Select the deadline type"
msgstr "Fristart wählen"
#: compensation/forms/modalForms.py:341
#: compensation/forms/modalForms.py:345
#: compensation/templates/compensation/detail/compensation/includes/deadlines.html:31
#: compensation/templates/compensation/detail/eco_account/includes/deadlines.html:31
#: ema/templates/ema/detail/includes/deadlines.html:31
@ -568,30 +568,30 @@ msgstr "Fristart wählen"
msgid "Date"
msgstr "Datum"
#: compensation/forms/modalForms.py:344
#: compensation/forms/modalForms.py:348
msgid "Select date"
msgstr "Datum wählen"
#: compensation/forms/modalForms.py:371
#: compensation/forms/modalForms.py:375
msgid "New deadline"
msgstr "Neue Frist"
#: compensation/forms/modalForms.py:372
#: compensation/forms/modalForms.py:376
msgid "Insert data for the new deadline"
msgstr "Geben Sie die Daten der neuen Frist ein"
#: compensation/forms/modalForms.py:385
#: compensation/forms/modalForms.py:389
#: compensation/templates/compensation/detail/compensation/includes/deadlines.html:59
#: compensation/templates/compensation/detail/eco_account/includes/deadlines.html:57
#: ema/templates/ema/detail/includes/deadlines.html:57
msgid "Edit deadline"
msgstr "Frist/Termin bearbeiten"
#: compensation/forms/modalForms.py:413
#: compensation/forms/modalForms.py:417
msgid "Action Type"
msgstr "Maßnahmentyp"
#: compensation/forms/modalForms.py:416
#: compensation/forms/modalForms.py:420
msgid ""
"An action can consist of multiple different action types. All the selected "
"action types are expected to be performed according to the amount and unit "
@ -601,35 +601,35 @@ msgstr ""
"hier gewählten Einträge sollen mit der weiter unten angegebenen Einheit und "
"Menge umgesetzt werden. "
#: compensation/forms/modalForms.py:421 compensation/forms/modalForms.py:433
#: compensation/forms/modalForms.py:425 compensation/forms/modalForms.py:437
msgid "Action Type detail"
msgstr "Zusatzmerkmal"
#: compensation/forms/modalForms.py:424
#: compensation/forms/modalForms.py:428
msgid "Select the action type detail"
msgstr "Zusatzmerkmal wählen"
#: compensation/forms/modalForms.py:438
#: compensation/forms/modalForms.py:442
msgid "Unit"
msgstr "Einheit"
#: compensation/forms/modalForms.py:441
#: compensation/forms/modalForms.py:445
msgid "Select the unit"
msgstr "Einheit wählen"
#: compensation/forms/modalForms.py:453
#: compensation/forms/modalForms.py:457
msgid "Insert the amount"
msgstr "Menge eingeben"
#: compensation/forms/modalForms.py:478
#: compensation/forms/modalForms.py:482
msgid "New action"
msgstr "Neue Maßnahme"
#: compensation/forms/modalForms.py:479
#: compensation/forms/modalForms.py:483
msgid "Insert data for the new action"
msgstr "Geben Sie die Daten der neuen Maßnahme ein"
#: compensation/forms/modalForms.py:503
#: compensation/forms/modalForms.py:507
#: compensation/templates/compensation/detail/compensation/includes/actions.html:68
#: compensation/templates/compensation/detail/eco_account/includes/actions.html:67
#: ema/templates/ema/detail/includes/actions.html:65
@ -1150,17 +1150,17 @@ msgid "Compensation {} edited"
msgstr "Kompensation {} bearbeitet"
#: compensation/views/compensation.py:182 compensation/views/eco_account.py:173
#: ema/views.py:240 intervention/views.py:335
#: ema/views.py:240 intervention/views.py:334
msgid "Edit {}"
msgstr "Bearbeite {}"
#: compensation/views/compensation.py:261 compensation/views/eco_account.py:359
#: ema/views.py:194 intervention/views.py:539
#: ema/views.py:194 intervention/views.py:538
msgid "Log"
msgstr "Log"
#: compensation/views/compensation.py:605 compensation/views/eco_account.py:727
#: ema/views.py:558 intervention/views.py:685
#: ema/views.py:558 intervention/views.py:684
msgid "Report {}"
msgstr "Bericht {}"
@ -1181,32 +1181,32 @@ msgid "Eco-account removed"
msgstr "Ökokonto entfernt"
#: compensation/views/eco_account.py:380 ema/views.py:282
#: intervention/views.py:638
#: intervention/views.py:637
msgid "{} unrecorded"
msgstr "{} entzeichnet"
#: compensation/views/eco_account.py:380 ema/views.py:282
#: intervention/views.py:638
#: intervention/views.py:637
msgid "{} recorded"
msgstr "{} verzeichnet"
#: compensation/views/eco_account.py:804 ema/views.py:628
#: intervention/views.py:436
#: intervention/views.py:435
msgid "{} has already been shared with you"
msgstr "{} wurde bereits für Sie freigegeben"
#: compensation/views/eco_account.py:809 ema/views.py:633
#: intervention/views.py:441
#: intervention/views.py:440
msgid "{} has been shared with you"
msgstr "{} ist nun für Sie freigegeben"
#: compensation/views/eco_account.py:816 ema/views.py:640
#: intervention/views.py:448
#: intervention/views.py:447
msgid "Share link invalid"
msgstr "Freigabelink ungültig"
#: compensation/views/eco_account.py:839 ema/views.py:663
#: intervention/views.py:471
#: intervention/views.py:470
msgid "Share settings updated"
msgstr "Freigabe Einstellungen aktualisiert"
@ -1310,9 +1310,9 @@ msgstr "Datum Zulassung bzw. Satzungsbeschluss"
#: intervention/templates/intervention/detail/view.html:100
#: intervention/templates/intervention/report/report.html:83
msgid "Binding on"
msgstr "Datum Bestandskraft"
msgstr "Datum Bestandskraft bzw. Rechtskraft"
#: intervention/forms/forms.py:211 intervention/views.py:95
#: intervention/forms/forms.py:211 intervention/views.py:97
msgid "New intervention"
msgstr "Neuer Eingriff"
@ -1520,7 +1520,7 @@ msgstr "Widersprüche liegen vor"
#: intervention/utils/quality.py:76
msgid "Binding date"
msgstr "Datum Bestandskraft"
msgstr "Datum Bestandskraft bzw. Rechtskraft"
#: intervention/utils/quality.py:79
msgid "Laws"
@ -1532,27 +1532,27 @@ msgstr ""
"Kein Ausgleich jeglicher Art gefunden (Kompensation, Ersatzzahlung, "
"Abbuchung)"
#: intervention/views.py:52
#: intervention/views.py:54
msgid "Interventions - Overview"
msgstr "Eingriffe - Übersicht"
#: intervention/views.py:85
#: intervention/views.py:87
msgid "Intervention {} added"
msgstr "Eingriff {} hinzugefügt"
#: intervention/views.py:323
#: intervention/views.py:322
msgid "Intervention {} edited"
msgstr "Eingriff {} bearbeitet"
#: intervention/views.py:359
#: intervention/views.py:358
msgid "{} removed"
msgstr "{} entfernt"
#: intervention/views.py:492
#: intervention/views.py:491
msgid "Check performed"
msgstr "Prüfung durchgeführt"
#: intervention/views.py:643
#: intervention/views.py:642
msgid "There are errors on this intervention:"
msgstr "Es liegen Fehler in diesem Eingriff vor:"
@ -1582,7 +1582,7 @@ msgid "Search for file number"
msgstr "Nach Aktenzeichen suchen"
#: konova/filters/mixins.py:85
#: konova/templates/konova/includes/parcel_table.html:13
#: konova/templates/konova/includes/parcels/parcel_table_frame.html:18
msgid "District"
msgstr "Kreis"
@ -1595,7 +1595,7 @@ msgid "Search for parcel gmrkng"
msgstr "Nach Gemarkung suchen"
#: konova/filters/mixins.py:111
#: konova/templates/konova/includes/parcel_table.html:34
#: konova/templates/konova/includes/parcels/parcel_table_frame.html:39
msgid "Parcel"
msgstr "Flur"
@ -1604,7 +1604,7 @@ msgid "Search for parcel"
msgstr "Nach Flur suchen"
#: konova/filters/mixins.py:124
#: konova/templates/konova/includes/parcel_table.html:35
#: konova/templates/konova/includes/parcels/parcel_table_frame.html:40
msgid "Parcel counter"
msgstr "Flurstückzähler"
@ -1613,7 +1613,7 @@ msgid "Search for parcel counter"
msgstr "Nach Flurstückzähler suchen"
#: konova/filters/mixins.py:138
#: konova/templates/konova/includes/parcel_table.html:36
#: konova/templates/konova/includes/parcels/parcel_table_frame.html:41
msgid "Parcel number"
msgstr "Flurstücknenner"
@ -1752,33 +1752,37 @@ msgstr ""
msgid "English"
msgstr ""
#: konova/templates/konova/includes/parcel_table.html:5
#: konova/templates/konova/includes/parcels/parcel_table_frame.html:5
msgid "Parcels can not be calculated, since no geometry is given."
msgstr ""
"Flurstücke können nicht berechnet werden, da keine Geometrie eingegeben "
"wurde."
#: konova/templates/konova/includes/parcel_table.html:11
#: konova/templates/konova/includes/parcels/parcel_table_frame.html:11
msgid "Parcels found"
msgstr "Flurstücke"
#: konova/templates/konova/includes/parcels/parcel_table_frame.html:16
msgid "Municipal"
msgstr "Gemeinde"
#: konova/templates/konova/includes/parcel_table.html:12
#: konova/templates/konova/includes/parcels/parcel_table_frame.html:17
msgid "Municipal key"
msgstr "Gemeindeschlüssel"
#: konova/templates/konova/includes/parcel_table.html:14
#: konova/templates/konova/includes/parcels/parcel_table_frame.html:19
msgid "District key"
msgstr "Kreisschlüssel"
#: konova/templates/konova/includes/parcel_table.html:32
#: konova/templates/konova/includes/parcels/parcel_table_frame.html:37
msgid "Parcel group"
msgstr "Gemarkung"
#: konova/templates/konova/includes/parcel_table.html:33
#: konova/templates/konova/includes/parcels/parcel_table_frame.html:38
msgid "Parcel group key"
msgstr "Gemarkungsschlüssel"
#: konova/templates/konova/includes/parcels.html:7
#: konova/templates/konova/includes/parcels/parcels.html:7
msgid "Spatial reference"
msgstr "Raumreferenz"
@ -1808,11 +1812,6 @@ msgstr "Im Browser öffnen"
msgid "View in LANIS"
msgstr "In LANIS öffnen"
#: konova/templates/konova/widgets/checkbox-tree-select.html:4
#: templates/generic_index.html:56
msgid "Search"
msgstr "Suchen"
#: konova/templates/konova/widgets/generate-content-input.html:6
msgid "Generate new"
msgstr "Neu generieren"
@ -1825,6 +1824,12 @@ msgstr "In Zwischenablage kopieren"
msgid "Copied to clipboard"
msgstr "In Zwischenablage kopiert"
#: konova/templates/konova/widgets/tree/checkbox/checkbox-tree-select.html:4
#: konova/templates/konova/widgets/tree/radio/radio-tree-select.html:4
#: templates/generic_index.html:56
msgid "Search"
msgstr "Suchen"
#: konova/utils/mailer.py:68 konova/utils/mailer.py:137
msgid "{} - Shared access removed"
msgstr "{} - Zugriff entzogen"
@ -2484,7 +2489,7 @@ msgid ""
msgstr ""
"\n"
" Diese Daten sind noch nicht veröffentlicht und/oder haben das "
"Bestandskraftdatum noch nicht erreicht. Sie können daher aktuell nicht "
"Bestands-/Rechtskraftdatum noch nicht erreicht. Sie können daher aktuell nicht "
"eingesehen werden. Schauen Sie zu einem späteren Zeitpunkt wieder vorbei. \n"
" "
@ -4245,6 +4250,9 @@ msgstr ""
msgid "Unable to connect to qpid with SASL mechanism %s"
msgstr ""
#~ msgid "Show more..."
#~ msgstr "Mehr anzeigen..."
#~ msgid "Kreis"
#~ msgstr "Kreis"

Loading…
Cancel
Save