Compare commits
62 Commits
4a16727da1
...
490_View_r
| Author | SHA1 | Date | |
|---|---|---|---|
| b5cf5c4446 | |||
| e49eed21da | |||
| 4c4d64cc3d | |||
| fbde03caec | |||
| 43eb598d3f | |||
| b7fac0ae03 | |||
| 447ba942b5 | |||
| c4cd40913d | |||
| a70434e2cc | |||
| 1ac73e4bbb | |||
| a16fc2eb91 | |||
| 644aa2e3cd | |||
| c14aff771e | |||
| e239736a72 | |||
| 21af4f2c57 | |||
| 765356d064 | |||
| 00bf03f58d | |||
| 3de97e2f6a | |||
| 00109b6bfd | |||
| 971e3f20c8 | |||
| efb76278b4 | |||
| e0b8922494 | |||
| bfdf82ac46 | |||
| 0ad0b02f95 | |||
| a407c86dfb | |||
| abfc48d79b | |||
| 43846e8d2f | |||
| 5e01d7ccda | |||
| 5b1af04d66 | |||
| 0d939c9e19 | |||
| 7d80875727 | |||
| 53d5e03a3f | |||
| 34a8ea4aec | |||
| 478d630d76 | |||
| 00e2178f3c | |||
| 8a984d0169 | |||
| f4e97db9ac | |||
| 95510cef36 | |||
| 225d4e8ce1 | |||
| ca7411b6c3 | |||
| 43f313a71e | |||
| 241db2f51d | |||
| dce61c4d7e | |||
| 17d817bbe1 | |||
| aec10ee0af | |||
| 6df47f1615 | |||
| e25d549a97 | |||
| 5e65b8f4dc | |||
| 22cddb9902 | |||
| c986bd0b92 | |||
| 1b6eea2c9e | |||
| 2c60d86177 | |||
| b7792ececc | |||
| cf6f188ef3 | |||
| f122778232 | |||
| bc2e901ca9 | |||
| 210f3fcafa | |||
| e7d67560f2 | |||
| b5e991fb95 | |||
| d3a555d406 | |||
| 9a374f50de | |||
| ce63dd30bc |
@@ -7,11 +7,8 @@ Created on: 21.01.22
|
||||
"""
|
||||
from django.urls import path, include
|
||||
|
||||
from api.views.method_views import generate_new_token_view
|
||||
|
||||
app_name = "api"
|
||||
|
||||
urlpatterns = [
|
||||
path("v1/", include("api.urls.v1.urls", namespace="v1")),
|
||||
path("token/generate", generate_new_token_view, name="generate-new-token"),
|
||||
]
|
||||
@@ -1,35 +0,0 @@
|
||||
"""
|
||||
Author: Michel Peltriaux
|
||||
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
|
||||
Contact: michel.peltriaux@sgdnord.rlp.de
|
||||
Created on: 27.01.22
|
||||
|
||||
"""
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.http import HttpRequest, JsonResponse
|
||||
|
||||
from api.models import APIUserToken
|
||||
|
||||
|
||||
@login_required
|
||||
def generate_new_token_view(request: HttpRequest):
|
||||
""" Handles request for fetching
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
|
||||
if request.method == "GET":
|
||||
token = APIUserToken()
|
||||
while APIUserToken.objects.filter(token=token.token).exists():
|
||||
token = APIUserToken()
|
||||
return JsonResponse(
|
||||
data={
|
||||
"gen_data": token.token
|
||||
}
|
||||
)
|
||||
else:
|
||||
raise NotImplementedError
|
||||
@@ -237,7 +237,11 @@ class EditEcoAccountForm(NewEcoAccountForm):
|
||||
|
||||
|
||||
class RemoveEcoAccountModalForm(RemoveModalForm):
|
||||
""" Form class
|
||||
|
||||
Provides a form for deleting eco accounts
|
||||
|
||||
"""
|
||||
def is_valid(self):
|
||||
super_valid = super().is_valid()
|
||||
has_deductions = self.instance.deductions.exists()
|
||||
|
||||
@@ -6,8 +6,10 @@ Created on: 18.08.22
|
||||
|
||||
"""
|
||||
from django import forms
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.utils.translation import pgettext_lazy as _con, gettext_lazy as _
|
||||
|
||||
from compensation.models import Payment
|
||||
from konova.forms.modals import RemoveModalForm, BaseModalForm
|
||||
from konova.utils import validators
|
||||
from konova.utils.message_templates import PAYMENT_EDITED
|
||||
@@ -103,7 +105,8 @@ class EditPaymentModalForm(NewPaymentForm):
|
||||
payment = None
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.payment = kwargs.pop("payment", None)
|
||||
payment_id = kwargs.pop("payment_id", None)
|
||||
self.payment = get_object_or_404(Payment, id=payment_id)
|
||||
super().__init__(*args, **kwargs)
|
||||
self.form_title = _("Edit payment")
|
||||
form_date = {
|
||||
@@ -133,8 +136,8 @@ class RemovePaymentModalForm(RemoveModalForm):
|
||||
payment = None
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
payment = kwargs.pop("payment", None)
|
||||
self.payment = payment
|
||||
payment_id = kwargs.pop("payment_id", None)
|
||||
self.payment = get_object_or_404(Payment, id=payment_id)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def save(self):
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
</td>
|
||||
<td class="align-middle">
|
||||
{% if deduction.intervention.recorded %}
|
||||
<em title="{% trans 'Recorded on' %} {{obj.recorded.timestamp}} {% trans 'by' %} {{obj.recorded.user}}" class='fas fa-bookmark registered-bookmark'></em>
|
||||
<em title="{% trans 'Recorded on' %} {{deduction.intervention.recorded.timestamp}} {% trans 'by' %} {{deduction.intervention.recorded.user}}" class='fas fa-bookmark registered-bookmark'></em>
|
||||
{% else %}
|
||||
<em title="{% trans 'Not recorded yet' %}" class='far fa-bookmark'></em>
|
||||
{% endif %}
|
||||
|
||||
@@ -6,11 +6,11 @@ Created on: 24.08.21
|
||||
|
||||
"""
|
||||
from django.urls import path
|
||||
from compensation.views.payment import *
|
||||
from compensation.views.payment import NewPaymentView, RemovePaymentView, EditPaymentView
|
||||
|
||||
app_name = "pay"
|
||||
urlpatterns = [
|
||||
path('<id>/new', new_payment_view, name='new'),
|
||||
path('<id>/remove/<payment_id>', payment_remove_view, name='remove'),
|
||||
path('<id>/edit/<payment_id>', payment_edit_view, name='edit'),
|
||||
path('<id>/new', NewPaymentView.as_view(), name='new'),
|
||||
path('<id>/remove/<payment_id>', RemovePaymentView.as_view(), name='remove'),
|
||||
path('<id>/edit/<payment_id>', EditPaymentView.as_view(), name='edit'),
|
||||
]
|
||||
|
||||
@@ -6,29 +6,26 @@ Created on: 19.08.22
|
||||
|
||||
"""
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.http import HttpRequest, JsonResponse
|
||||
from django.shortcuts import get_object_or_404, render, redirect
|
||||
from django.urls import reverse
|
||||
from django.shortcuts import get_object_or_404, redirect
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from compensation.forms.compensation import EditCompensationForm, NewCompensationForm
|
||||
from compensation.models import Compensation
|
||||
from compensation.tables.compensation import CompensationTable
|
||||
from intervention.models import Intervention
|
||||
from konova.decorators import shared_access_required, default_group_required, login_required_modal
|
||||
from konova.forms.modals import RemoveModalForm
|
||||
from konova.utils.message_templates import COMPENSATION_REMOVED_TEMPLATE, DATA_CHECKED_PREVIOUSLY_TEMPLATE, \
|
||||
from konova.utils.message_templates import DATA_CHECKED_PREVIOUSLY_TEMPLATE, \
|
||||
RECORDED_BLOCKS_EDIT, PARAMS_INVALID
|
||||
from konova.views.base import BaseIndexView, BaseIdentifierGeneratorView, BaseNewSpatialLocatedObjectFormView, \
|
||||
BaseEditSpatialLocatedObjectFormView
|
||||
from konova.views.identifier import AbstractIdentifierGeneratorView
|
||||
from konova.views.form import AbstractNewGeometryFormView, AbstractEditGeometryFormView
|
||||
from konova.views.index import AbstractIndexView
|
||||
from konova.views.detail import BaseDetailView
|
||||
from konova.views.remove import BaseRemoveModalFormView
|
||||
|
||||
|
||||
class CompensationIndexView(LoginRequiredMixin, BaseIndexView):
|
||||
class CompensationIndexView(LoginRequiredMixin, AbstractIndexView):
|
||||
_TAB_TITLE = _("Compensations - Overview")
|
||||
_INDEX_TABLE_CLS = CompensationTable
|
||||
|
||||
@@ -42,7 +39,7 @@ class CompensationIndexView(LoginRequiredMixin, BaseIndexView):
|
||||
return qs
|
||||
|
||||
|
||||
class NewCompensationFormView(BaseNewSpatialLocatedObjectFormView):
|
||||
class NewCompensationFormView(AbstractNewGeometryFormView):
|
||||
_FORM_CLS = NewCompensationForm
|
||||
_MODEL_CLS = Compensation
|
||||
_TEMPLATE = "compensation/form/view.html"
|
||||
@@ -59,7 +56,7 @@ class NewCompensationFormView(BaseNewSpatialLocatedObjectFormView):
|
||||
intervention = get_object_or_404(Intervention, id=intervention_id)
|
||||
return intervention.is_shared_with(user)
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
# User has to be an ets user
|
||||
return user.is_default_user()
|
||||
|
||||
@@ -82,18 +79,18 @@ class NewCompensationFormView(BaseNewSpatialLocatedObjectFormView):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
|
||||
class EditCompensationFormView(BaseEditSpatialLocatedObjectFormView):
|
||||
class EditCompensationFormView(AbstractEditGeometryFormView):
|
||||
_MODEL_CLS = Compensation
|
||||
_FORM_CLS = EditCompensationForm
|
||||
_TEMPLATE = "compensation/form/view.html"
|
||||
_REDIRECT_URL = "compensation:detail"
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
# User has to be a default user
|
||||
return user.is_default_user()
|
||||
|
||||
|
||||
class CompensationIdentifierGeneratorView(LoginRequiredMixin, BaseIdentifierGeneratorView):
|
||||
class CompensationIdentifierGeneratorView(LoginRequiredMixin, AbstractIdentifierGeneratorView):
|
||||
_MODEL_CLS = Compensation
|
||||
_REDIRECT_URL = "compensation:index"
|
||||
|
||||
@@ -170,5 +167,5 @@ class RemoveCompensationView(LoginRequiredMixin, BaseRemoveModalFormView):
|
||||
_FORM_CLS = RemoveModalForm
|
||||
_REDIRECT_URL = "compensation:index"
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_default_user()
|
||||
|
||||
@@ -10,10 +10,10 @@ from django.urls import reverse
|
||||
from compensation.models import Compensation
|
||||
from konova.sub_settings.django_settings import BASE_URL
|
||||
from konova.utils.qrcode import QrCode
|
||||
from konova.views.report import BaseReportView
|
||||
from konova.views.report import AbstractReportView
|
||||
|
||||
|
||||
class BaseCompensationReportView(BaseReportView):
|
||||
class BaseCompensationReportView(AbstractReportView):
|
||||
def _get_compensation_report_context(self, obj):
|
||||
# Order states by surface
|
||||
before_states = obj.before_states.all().order_by("-surface").prefetch_related("biotope_type")
|
||||
|
||||
@@ -5,31 +5,24 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||
Created on: 19.08.22
|
||||
|
||||
"""
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.http import HttpRequest
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
from django.urls import reverse
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from compensation.forms.eco_account import EditEcoAccountForm, NewEcoAccountForm, RemoveEcoAccountModalForm
|
||||
from compensation.models import EcoAccount
|
||||
from compensation.tables.eco_account import EcoAccountTable
|
||||
from konova.contexts import BaseContext
|
||||
from konova.decorators import shared_access_required, default_group_required, login_required_modal
|
||||
from konova.forms import SimpleGeomForm
|
||||
from konova.settings import ETS_GROUP
|
||||
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, \
|
||||
IDENTIFIER_REPLACED, GEOMETRY_SIMPLIFIED, GEOMETRIES_IGNORED_TEMPLATE
|
||||
from konova.views.base import BaseIndexView, BaseIdentifierGeneratorView, BaseNewSpatialLocatedObjectFormView, \
|
||||
BaseEditSpatialLocatedObjectFormView
|
||||
from konova.views.identifier import AbstractIdentifierGeneratorView
|
||||
from konova.views.form import AbstractNewGeometryFormView, AbstractEditGeometryFormView
|
||||
from konova.views.index import AbstractIndexView
|
||||
from konova.views.detail import BaseDetailView
|
||||
from konova.views.remove import BaseRemoveModalFormView
|
||||
|
||||
|
||||
class EcoAccountIndexView(LoginRequiredMixin, BaseIndexView):
|
||||
class EcoAccountIndexView(LoginRequiredMixin, AbstractIndexView):
|
||||
""" View class for indexing eco accounts
|
||||
|
||||
"""
|
||||
_INDEX_TABLE_CLS = EcoAccountTable
|
||||
_TAB_TITLE = _("Eco-account - Overview")
|
||||
|
||||
@@ -42,152 +35,53 @@ class EcoAccountIndexView(LoginRequiredMixin, BaseIndexView):
|
||||
return qs
|
||||
|
||||
|
||||
class NewEcoAccountFormView(BaseNewSpatialLocatedObjectFormView):
|
||||
class NewEcoAccountFormView(AbstractNewGeometryFormView):
|
||||
""" Form view class
|
||||
|
||||
Renders a form for new eco accounts
|
||||
|
||||
"""
|
||||
_FORM_CLS = NewEcoAccountForm
|
||||
_MODEL_CLS = EcoAccount
|
||||
_TEMPLATE = "compensation/form/view.html"
|
||||
_TAB_TITLE = _("New Eco-Account")
|
||||
_REDIRECT_URL = "compensation:acc:detail"
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
# User has to be a default user
|
||||
return user.is_default_user()
|
||||
|
||||
|
||||
class EditEcoAccountFormView(BaseEditSpatialLocatedObjectFormView):
|
||||
class EditEcoAccountFormView(AbstractEditGeometryFormView):
|
||||
""" Form view class
|
||||
|
||||
Renders a form for editing of eco accounts
|
||||
|
||||
"""
|
||||
_FORM_CLS = EditEcoAccountForm
|
||||
_MODEL_CLS = EcoAccount
|
||||
_TEMPLATE = "compensation/form/view.html"
|
||||
_REDIRECT_URL = "compensation:acc:detail"
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
# User has to be a default user
|
||||
return user.is_default_user()
|
||||
|
||||
|
||||
@login_required
|
||||
@default_group_required
|
||||
def new_view(request: HttpRequest):
|
||||
"""
|
||||
Renders a view for a new eco account creation
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
|
||||
Returns:
|
||||
class EcoAccountIdentifierGeneratorView(LoginRequiredMixin, AbstractIdentifierGeneratorView):
|
||||
""" View class for identifier generation on eco accounts
|
||||
|
||||
"""
|
||||
template = "compensation/form/view.html"
|
||||
data_form = NewEcoAccountForm(request.POST or None)
|
||||
geom_form = SimpleGeomForm(request.POST or None, read_only=False)
|
||||
if request.method == "POST":
|
||||
if data_form.is_valid() and geom_form.is_valid():
|
||||
generated_identifier = data_form.cleaned_data.get("identifier", None)
|
||||
acc = data_form.save(request.user, geom_form)
|
||||
if generated_identifier != acc.identifier:
|
||||
messages.info(
|
||||
request,
|
||||
IDENTIFIER_REPLACED.format(
|
||||
generated_identifier,
|
||||
acc.identifier
|
||||
)
|
||||
)
|
||||
messages.success(request, _("Eco-Account {} added").format(acc.identifier))
|
||||
if geom_form.has_geometry_simplified():
|
||||
messages.info(
|
||||
request,
|
||||
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)
|
||||
else:
|
||||
messages.error(request, FORM_INVALID, extra_tags="danger",)
|
||||
else:
|
||||
# For clarification: nothing in this case
|
||||
pass
|
||||
context = {
|
||||
"form": data_form,
|
||||
"geom_form": geom_form,
|
||||
TAB_TITLE_IDENTIFIER: _("New Eco-Account"),
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, template, context)
|
||||
|
||||
|
||||
class EcoAccountIdentifierGeneratorView(LoginRequiredMixin, BaseIdentifierGeneratorView):
|
||||
_MODEL_CLS = EcoAccount
|
||||
_REDIRECT_URL = "compensation:acc:index"
|
||||
|
||||
|
||||
@login_required
|
||||
@default_group_required
|
||||
@shared_access_required(EcoAccount, "id")
|
||||
def edit_view(request: HttpRequest, id: str):
|
||||
"""
|
||||
Renders a view for editing compensations
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
template = "compensation/form/view.html"
|
||||
# Get object from db
|
||||
acc = get_object_or_404(EcoAccount, id=id)
|
||||
if acc.is_recorded:
|
||||
messages.info(
|
||||
request,
|
||||
RECORDED_BLOCKS_EDIT
|
||||
)
|
||||
return redirect("compensation:acc:detail", id=id)
|
||||
|
||||
# Create forms, initialize with values from db/from POST request
|
||||
data_form = EditEcoAccountForm(request.POST or None, instance=acc)
|
||||
geom_form = SimpleGeomForm(request.POST or None, read_only=False, instance=acc)
|
||||
if request.method == "POST":
|
||||
data_form_valid = data_form.is_valid()
|
||||
geom_form_valid = geom_form.is_valid()
|
||||
if data_form_valid and geom_form_valid:
|
||||
# The data form takes the geom form for processing, as well as the performing user
|
||||
acc = data_form.save(request.user, geom_form)
|
||||
messages.success(request, _("Eco-Account {} edited").format(acc.identifier))
|
||||
if geom_form.has_geometry_simplified():
|
||||
messages.info(
|
||||
request,
|
||||
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)
|
||||
else:
|
||||
messages.error(request, FORM_INVALID, extra_tags="danger",)
|
||||
else:
|
||||
# For clarification: nothing in this case
|
||||
pass
|
||||
context = {
|
||||
"form": data_form,
|
||||
"geom_form": geom_form,
|
||||
TAB_TITLE_IDENTIFIER: _("Edit {}").format(acc.identifier),
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, template, context)
|
||||
|
||||
|
||||
class EcoAccountDetailView(BaseDetailView):
|
||||
""" Detail view class
|
||||
|
||||
Renders details of an eco account
|
||||
|
||||
"""
|
||||
_MODEL_CLS = EcoAccount
|
||||
_TEMPLATE = "compensation/detail/eco_account/view.html"
|
||||
|
||||
@@ -256,9 +150,14 @@ class EcoAccountDetailView(BaseDetailView):
|
||||
|
||||
|
||||
class RemoveEcoAccountView(LoginRequiredMixin, BaseRemoveModalFormView):
|
||||
""" Form view class
|
||||
|
||||
Renders a form for removing eco accounts
|
||||
|
||||
"""
|
||||
_MODEL_CLS = EcoAccount
|
||||
_FORM_CLS = RemoveEcoAccountModalForm
|
||||
_REDIRECT_URL = "compensation:acc:index"
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_default_user()
|
||||
|
||||
@@ -5,84 +5,38 @@ Contact: michel.peltriaux@sgdnord.rlp.de
|
||||
Created on: 09.08.21
|
||||
|
||||
"""
|
||||
from django.urls import reverse
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.http import HttpRequest
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
|
||||
from compensation.forms.modals.payment import NewPaymentForm, RemovePaymentModalForm, EditPaymentModalForm
|
||||
from compensation.models import Payment
|
||||
from intervention.models import Intervention
|
||||
from konova.decorators import default_group_required, shared_access_required
|
||||
from konova.utils.message_templates import PAYMENT_ADDED, PAYMENT_REMOVED, PAYMENT_EDITED
|
||||
from konova.views.modal import AbstractModalFormView
|
||||
|
||||
|
||||
@login_required
|
||||
@default_group_required
|
||||
@shared_access_required(Intervention, "id")
|
||||
def new_payment_view(request: HttpRequest, id: str):
|
||||
""" Renders a modal view for adding new payments
|
||||
class BasePaymentView(LoginRequiredMixin, AbstractModalFormView):
|
||||
_MODEL_CLS = Intervention
|
||||
_REDIRECT_URL = "intervention:detail"
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
id (str): The intervention's id for which a new payment shall be added
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
Returns:
|
||||
def _get_redirect_url(self, *args, **kwargs):
|
||||
url = super()._get_redirect_url(*args, **kwargs)
|
||||
return f"{url}#related_data"
|
||||
|
||||
"""
|
||||
intervention = get_object_or_404(Intervention, id=id)
|
||||
form = NewPaymentForm(request.POST or None, instance=intervention, request=request)
|
||||
return form.process_request(
|
||||
request,
|
||||
msg_success=PAYMENT_ADDED,
|
||||
redirect_url=reverse("intervention:detail", args=(id,)) + "#related_data"
|
||||
)
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_default_user()
|
||||
|
||||
|
||||
@login_required
|
||||
@default_group_required
|
||||
@shared_access_required(Intervention, "id")
|
||||
def payment_remove_view(request: HttpRequest, id: str, payment_id: str):
|
||||
""" Renders a modal view for removing payments
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
id (str): The intervention's id
|
||||
payment_id (str): The payment's id
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
intervention = get_object_or_404(Intervention, id=id)
|
||||
payment = get_object_or_404(Payment, id=payment_id)
|
||||
form = RemovePaymentModalForm(request.POST or None, instance=intervention, payment=payment, request=request)
|
||||
return form.process_request(
|
||||
request=request,
|
||||
msg_success=PAYMENT_REMOVED,
|
||||
redirect_url=reverse("intervention:detail", args=(payment.intervention_id,)) + "#related_data"
|
||||
)
|
||||
class NewPaymentView(BasePaymentView):
|
||||
_FORM_CLS = NewPaymentForm
|
||||
_MSG_SUCCESS = PAYMENT_ADDED
|
||||
|
||||
|
||||
@login_required
|
||||
@default_group_required
|
||||
@shared_access_required(Intervention, "id")
|
||||
def payment_edit_view(request: HttpRequest, id: str, payment_id: str):
|
||||
""" Renders a modal view for editing payments
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
id (str): The intervention's id
|
||||
payment_id (str): The payment's id
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
intervention = get_object_or_404(Intervention, id=id)
|
||||
payment = get_object_or_404(Payment, id=payment_id)
|
||||
form = EditPaymentModalForm(request.POST or None, instance=intervention, payment=payment, request=request)
|
||||
return form.process_request(
|
||||
request=request,
|
||||
msg_success=PAYMENT_EDITED,
|
||||
redirect_url=reverse("intervention:detail", args=(payment.intervention_id,)) + "#related_data"
|
||||
)
|
||||
class EditPaymentView(BasePaymentView):
|
||||
_MSG_SUCCESS = PAYMENT_EDITED
|
||||
_FORM_CLS = EditPaymentModalForm
|
||||
|
||||
class RemovePaymentView(BasePaymentView):
|
||||
_MSG_SUCCESS = PAYMENT_REMOVED
|
||||
_FORM_CLS = RemovePaymentModalForm
|
||||
|
||||
@@ -16,14 +16,14 @@ class NewEmaActionView(AbstractNewCompensationActionView):
|
||||
_MODEL_CLS = Ema
|
||||
_REDIRECT_URL = _EMA_ACCOUNT_DETAIL_URL_NAME
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_ets_user()
|
||||
|
||||
class EditEmaActionView(AbstractEditCompensationActionView):
|
||||
_MODEL_CLS = Ema
|
||||
_REDIRECT_URL = _EMA_ACCOUNT_DETAIL_URL_NAME
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_ets_user()
|
||||
|
||||
|
||||
@@ -31,5 +31,5 @@ class RemoveEmaActionView(AbstractRemoveCompensationActionView):
|
||||
_MODEL_CLS = Ema
|
||||
_REDIRECT_URL = _EMA_ACCOUNT_DETAIL_URL_NAME
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_ets_user()
|
||||
|
||||
@@ -14,7 +14,7 @@ class NewEmaDeadlineView(AbstractNewDeadlineView):
|
||||
_MODEL_CLS = Ema
|
||||
_REDIRECT_URL = _EMA_DETAIL_URL_NAME
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_ets_user()
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ class EditEmaDeadlineView(AbstractEditDeadlineView):
|
||||
_MODEL_CLS = Ema
|
||||
_REDIRECT_URL = _EMA_DETAIL_URL_NAME
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_ets_user()
|
||||
|
||||
|
||||
@@ -30,5 +30,5 @@ class RemoveEmaDeadlineView(AbstractRemoveDeadlineView):
|
||||
_MODEL_CLS = Ema
|
||||
_REDIRECT_URL = _EMA_DETAIL_URL_NAME
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_ets_user()
|
||||
|
||||
@@ -16,14 +16,14 @@ class NewEmaDocumentView(AbstractNewDocumentView):
|
||||
_FORM_CLS = NewEmaDocumentModalForm
|
||||
_REDIRECT_URL = "ema:detail"
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_ets_user()
|
||||
|
||||
class GetEmaDocumentView(AbstractGetDocumentView):
|
||||
_MODEL_CLS = Ema
|
||||
_DOCUMENT_CLS = EmaDocument
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_ets_user()
|
||||
|
||||
class RemoveEmaDocumentView(AbstractRemoveDocumentView):
|
||||
@@ -32,7 +32,7 @@ class RemoveEmaDocumentView(AbstractRemoveDocumentView):
|
||||
_FORM_CLS = RemoveEmaDocumentModalForm
|
||||
_REDIRECT_URL = "ema:detail"
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_ets_user()
|
||||
|
||||
class EditEmaDocumentView(AbstractEditDocumentView):
|
||||
@@ -41,5 +41,5 @@ class EditEmaDocumentView(AbstractEditDocumentView):
|
||||
_DOCUMENT_CLS = EmaDocument
|
||||
_REDIRECT_URL = "ema:detail"
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_ets_user()
|
||||
|
||||
@@ -12,13 +12,14 @@ from django.utils.translation import gettext_lazy as _
|
||||
from ema.forms import NewEmaForm, EditEmaForm
|
||||
from ema.models import Ema
|
||||
from ema.tables import EmaTable
|
||||
from konova.views.base import BaseIndexView, BaseIdentifierGeneratorView, BaseNewSpatialLocatedObjectFormView, \
|
||||
BaseEditSpatialLocatedObjectFormView
|
||||
from konova.views.identifier import AbstractIdentifierGeneratorView
|
||||
from konova.views.form import AbstractNewGeometryFormView, AbstractEditGeometryFormView
|
||||
from konova.views.index import AbstractIndexView
|
||||
from konova.views.detail import BaseDetailView
|
||||
from konova.views.remove import BaseRemoveModalFormView
|
||||
|
||||
|
||||
class EmaIndexView(LoginRequiredMixin, BaseIndexView):
|
||||
class EmaIndexView(LoginRequiredMixin, AbstractIndexView):
|
||||
_TAB_TITLE = _("EMAs - Overview")
|
||||
_INDEX_TABLE_CLS = EmaTable
|
||||
|
||||
@@ -31,35 +32,35 @@ class EmaIndexView(LoginRequiredMixin, BaseIndexView):
|
||||
return qs
|
||||
|
||||
|
||||
class NewEmaFormView(BaseNewSpatialLocatedObjectFormView):
|
||||
class NewEmaFormView(AbstractNewGeometryFormView):
|
||||
_FORM_CLS = NewEmaForm
|
||||
_MODEL_CLS = Ema
|
||||
_TEMPLATE = "ema/form/view.html"
|
||||
_TAB_TITLE = _("New EMA")
|
||||
_REDIRECT_URL = "ema:detail"
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
# User has to be an ets user
|
||||
return user.is_ets_user()
|
||||
|
||||
|
||||
class EditEmaFormView(BaseEditSpatialLocatedObjectFormView):
|
||||
class EditEmaFormView(AbstractEditGeometryFormView):
|
||||
_MODEL_CLS = Ema
|
||||
_FORM_CLS = EditEmaForm
|
||||
_TEMPLATE = "ema/form/view.html"
|
||||
_REDIRECT_URL = "ema:detail"
|
||||
_TAB_TITLE = _("Edit {}")
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
# User has to be an ets user
|
||||
return user.is_ets_user()
|
||||
|
||||
|
||||
class EmaIdentifierGeneratorView(LoginRequiredMixin, BaseIdentifierGeneratorView):
|
||||
class EmaIdentifierGeneratorView(LoginRequiredMixin, AbstractIdentifierGeneratorView):
|
||||
_MODEL_CLS = Ema
|
||||
_REDIRECT_URL = "ema:index"
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_ets_user()
|
||||
|
||||
|
||||
@@ -112,5 +113,5 @@ class RemoveEmaView(LoginRequiredMixin, BaseRemoveModalFormView):
|
||||
_MODEL_CLS = Ema
|
||||
_REDIRECT_URL = "ema:index"
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_ets_user()
|
||||
|
||||
@@ -14,5 +14,5 @@ from konova.views.log import AbstractLogView
|
||||
class EmaLogView(LoginRequiredMixin, AbstractLogView):
|
||||
_MODEL_CLS = Ema
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_ets_user()
|
||||
|
||||
@@ -16,5 +16,5 @@ class EmaResubmissionView(AbstractResubmissionView):
|
||||
_REDIRECT_URL = "ema:detail"
|
||||
action_url = "ema:resubmission-create"
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_ets_user()
|
||||
|
||||
@@ -17,5 +17,5 @@ class EmaShareFormView(AbstractShareFormView):
|
||||
_MODEL_CLS = Ema
|
||||
_REDIRECT_URL = "ema:detail"
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_ets_user()
|
||||
@@ -14,7 +14,7 @@ class NewEmaStateView(AbstractNewCompensationStateView):
|
||||
_MODEL_CLS = Ema
|
||||
_REDIRECT_URL = "ema:detail"
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_ets_user()
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ class EditEmaStateView(AbstractEditCompensationStateView):
|
||||
_MODEL_CLS = Ema
|
||||
_REDIRECT_URL = "ema:detail"
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_ets_user()
|
||||
|
||||
|
||||
@@ -30,5 +30,5 @@ class RemoveEmaStateView(AbstractRemoveCompensationStateView):
|
||||
_MODEL_CLS = Ema
|
||||
_REDIRECT_URL = "ema:detail"
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_ets_user()
|
||||
|
||||
22
intervention/forms/modals/remove.py
Normal file
22
intervention/forms/modals/remove.py
Normal file
@@ -0,0 +1,22 @@
|
||||
"""
|
||||
Author: Michel Peltriaux
|
||||
Created on: 08.11.25
|
||||
|
||||
"""
|
||||
from django.shortcuts import get_object_or_404
|
||||
|
||||
from compensation.models import Compensation
|
||||
from konova.forms.modals import RemoveModalForm
|
||||
|
||||
|
||||
class RemoveCompensationFromInterventionModalForm(RemoveModalForm):
|
||||
""" Specific form for removing a compensation from an intervention
|
||||
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
# The 'instance' that is pushed into the constructor by the generic base class points to the
|
||||
# intervention instead of the compensation, which shall be deleted. Therefore we need to fetch the compensation
|
||||
# and replace the instance parameter with that object
|
||||
instance = get_object_or_404(Compensation, id=kwargs.pop("comp_id"))
|
||||
kwargs["instance"] = instance
|
||||
super().__init__(*args, **kwargs)
|
||||
@@ -9,7 +9,7 @@ from django.urls import path
|
||||
|
||||
from intervention.autocomplete.intervention import InterventionAutocomplete
|
||||
from intervention.views.check import InterventionCheckView
|
||||
from intervention.views.compensation import remove_compensation_view
|
||||
from intervention.views.compensation import RemoveCompensationFromInterventionView
|
||||
from intervention.views.deduction import NewInterventionDeductionView, EditInterventionDeductionView, \
|
||||
RemoveInterventionDeductionView
|
||||
from intervention.views.document import NewInterventionDocumentView, GetInterventionDocumentView, \
|
||||
@@ -41,7 +41,7 @@ urlpatterns = [
|
||||
path('<id>/resub', InterventionResubmissionView.as_view(), name='resubmission-create'),
|
||||
|
||||
# Compensations
|
||||
path('<id>/compensation/<comp_id>/remove', remove_compensation_view, name='remove-compensation'),
|
||||
path('<id>/compensation/<comp_id>/remove', RemoveCompensationFromInterventionView.as_view(), name='remove-compensation'),
|
||||
|
||||
# Documents
|
||||
path('<id>/document/new/', NewInterventionDocumentView.as_view(), name='new-doc'),
|
||||
|
||||
@@ -10,16 +10,16 @@ from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from intervention.forms.modals.check import CheckModalForm
|
||||
from intervention.models import Intervention
|
||||
from konova.views.base import BaseModalFormView
|
||||
from konova.views.modal import AbstractModalFormView
|
||||
|
||||
|
||||
class InterventionCheckView(LoginRequiredMixin, BaseModalFormView):
|
||||
class InterventionCheckView(LoginRequiredMixin, AbstractModalFormView):
|
||||
_MODEL_CLS = Intervention
|
||||
_FORM_CLS = CheckModalForm
|
||||
_MSG_SUCCESS = _("Check performed")
|
||||
_REDIRECT_URL = "intervention:detail"
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_zb_user()
|
||||
|
||||
def _get_redirect_url(self, *args, **kwargs):
|
||||
|
||||
@@ -5,42 +5,36 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||
Created on: 19.08.22
|
||||
|
||||
"""
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.http import HttpRequest, Http404
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.urls import reverse
|
||||
|
||||
from compensation.models import Compensation
|
||||
from intervention.forms.modals.remove import RemoveCompensationFromInterventionModalForm
|
||||
from intervention.models import Intervention
|
||||
from konova.decorators import shared_access_required, login_required_modal
|
||||
from konova.forms.modals import RemoveModalForm
|
||||
from konova.utils.message_templates import COMPENSATION_REMOVED_TEMPLATE
|
||||
from konova.views.remove import BaseRemoveModalFormView
|
||||
|
||||
|
||||
@login_required_modal
|
||||
@login_required
|
||||
@shared_access_required(Intervention, "id")
|
||||
def remove_compensation_view(request: HttpRequest, id: str, comp_id: str):
|
||||
""" Renders a modal view for removing the compensation
|
||||
class RemoveCompensationFromInterventionView(LoginRequiredMixin, BaseRemoveModalFormView):
|
||||
_MODEL_CLS = Intervention
|
||||
_FORM_CLS = RemoveCompensationFromInterventionModalForm
|
||||
_MSG_SUCCESS = COMPENSATION_REMOVED_TEMPLATE
|
||||
_REDIRECT_URL = "intervention:detail"
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
id (str): The compensation's id
|
||||
def _user_has_shared_access(self, user, **kwargs):
|
||||
compensation_id = kwargs.get("comp_id", None)
|
||||
compensation = get_object_or_404(Compensation, id=compensation_id)
|
||||
return compensation.is_shared_with(user)
|
||||
|
||||
Returns:
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_default_user()
|
||||
|
||||
"""
|
||||
intervention = get_object_or_404(Intervention, id=id)
|
||||
try:
|
||||
comp = intervention.compensations.get(
|
||||
id=comp_id
|
||||
)
|
||||
except ObjectDoesNotExist:
|
||||
raise Http404("Unknown compensation")
|
||||
form = RemoveModalForm(request.POST or None, instance=comp, request=request)
|
||||
return form.process_request(
|
||||
request=request,
|
||||
msg_success=COMPENSATION_REMOVED_TEMPLATE.format(comp.identifier),
|
||||
redirect_url=reverse("intervention:detail", args=(id,)) + "#related_data",
|
||||
)
|
||||
def _get_msg_success(self, *args, **kwargs):
|
||||
compensation_id = kwargs.get("comp_id", None)
|
||||
compensation = get_object_or_404(Compensation, id=compensation_id)
|
||||
return self._MSG_SUCCESS.format(compensation.identifier)
|
||||
|
||||
def _get_redirect_url(self, *args, **kwargs):
|
||||
obj = kwargs.get("obj")
|
||||
return reverse(self._REDIRECT_URL, args=(obj.id,)) + "#related_data"
|
||||
|
||||
@@ -5,29 +5,22 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||
Created on: 19.08.22
|
||||
|
||||
"""
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.http import HttpRequest
|
||||
from django.shortcuts import get_object_or_404, render, redirect
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from intervention.forms.intervention import EditInterventionForm, NewInterventionForm
|
||||
from intervention.models import Intervention
|
||||
from intervention.tables import InterventionTable
|
||||
from konova.contexts import BaseContext
|
||||
from konova.decorators import default_group_required, shared_access_required
|
||||
from konova.forms import SimpleGeomForm
|
||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
||||
from konova.utils.message_templates import DATA_CHECKED_PREVIOUSLY_TEMPLATE, RECORDED_BLOCKS_EDIT, \
|
||||
CHECK_STATE_RESET, FORM_INVALID, GEOMETRY_SIMPLIFIED, GEOMETRIES_IGNORED_TEMPLATE
|
||||
from konova.views.base import BaseIndexView, BaseIdentifierGeneratorView, BaseNewSpatialLocatedObjectFormView, \
|
||||
BaseEditSpatialLocatedObjectFormView
|
||||
from konova.utils.message_templates import DATA_CHECKED_PREVIOUSLY_TEMPLATE
|
||||
from konova.views.identifier import AbstractIdentifierGeneratorView
|
||||
from konova.views.form import AbstractNewGeometryFormView, AbstractEditGeometryFormView
|
||||
from konova.views.index import AbstractIndexView
|
||||
from konova.views.detail import BaseDetailView
|
||||
from konova.views.remove import BaseRemoveModalFormView
|
||||
|
||||
|
||||
class InterventionIndexView(LoginRequiredMixin, BaseIndexView):
|
||||
class InterventionIndexView(LoginRequiredMixin, AbstractIndexView):
|
||||
_INDEX_TABLE_CLS = InterventionTable
|
||||
_TAB_TITLE = _("Interventions - Overview")
|
||||
|
||||
@@ -42,7 +35,7 @@ class InterventionIndexView(LoginRequiredMixin, BaseIndexView):
|
||||
return qs
|
||||
|
||||
|
||||
class NewInterventionFormView(BaseNewSpatialLocatedObjectFormView):
|
||||
class NewInterventionFormView(AbstractNewGeometryFormView):
|
||||
_MODEL_CLS = Intervention
|
||||
_FORM_CLS = NewInterventionForm
|
||||
_TEMPLATE = "intervention/form/view.html"
|
||||
@@ -50,7 +43,7 @@ class NewInterventionFormView(BaseNewSpatialLocatedObjectFormView):
|
||||
_TAB_TITLE = _("New intervention")
|
||||
|
||||
|
||||
class EditInterventionFormView(BaseEditSpatialLocatedObjectFormView):
|
||||
class EditInterventionFormView(AbstractEditGeometryFormView):
|
||||
_MODEL_CLS = Intervention
|
||||
_FORM_CLS = EditInterventionForm
|
||||
_TEMPLATE = "intervention/form/view.html"
|
||||
@@ -58,7 +51,7 @@ class EditInterventionFormView(BaseEditSpatialLocatedObjectFormView):
|
||||
_TAB_TITLE = _("Edit {}")
|
||||
|
||||
|
||||
class InterventionIdentifierGeneratorView(LoginRequiredMixin, BaseIdentifierGeneratorView):
|
||||
class InterventionIdentifierGeneratorView(LoginRequiredMixin, AbstractIdentifierGeneratorView):
|
||||
_MODEL_CLS = Intervention
|
||||
_REDIRECT_URL = "intervention:index"
|
||||
|
||||
@@ -117,69 +110,6 @@ class InterventionDetailView(BaseDetailView):
|
||||
}
|
||||
return context
|
||||
|
||||
|
||||
@login_required
|
||||
@default_group_required
|
||||
@shared_access_required(Intervention, "id")
|
||||
def edit_view(request: HttpRequest, id: str):
|
||||
"""
|
||||
Renders a view for editing interventions
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
template = "intervention/form/view.html"
|
||||
# Get object from db
|
||||
intervention = get_object_or_404(Intervention, id=id)
|
||||
if intervention.is_recorded:
|
||||
messages.info(
|
||||
request,
|
||||
RECORDED_BLOCKS_EDIT
|
||||
)
|
||||
return redirect("intervention:detail", id=id)
|
||||
|
||||
# Create forms, initialize with values from db/from POST request
|
||||
data_form = EditInterventionForm(request.POST or None, instance=intervention)
|
||||
geom_form = SimpleGeomForm(request.POST or None, read_only=False, instance=intervention)
|
||||
if request.method == "POST":
|
||||
if data_form.is_valid() and geom_form.is_valid():
|
||||
# The data form takes the geom form for processing, as well as the performing user
|
||||
# Save the current state of recorded|checked to inform the user in case of a status reset due to editing
|
||||
intervention_is_checked = intervention.checked is not None
|
||||
intervention = data_form.save(request.user, geom_form)
|
||||
messages.success(request, _("Intervention {} edited").format(intervention.identifier))
|
||||
if intervention_is_checked:
|
||||
messages.info(request, CHECK_STATE_RESET)
|
||||
if geom_form.has_geometry_simplified():
|
||||
messages.info(
|
||||
request,
|
||||
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)
|
||||
else:
|
||||
messages.error(request, FORM_INVALID, extra_tags="danger",)
|
||||
else:
|
||||
# For clarification: nothing in this case
|
||||
pass
|
||||
context = {
|
||||
"form": data_form,
|
||||
"geom_form": geom_form,
|
||||
TAB_TITLE_IDENTIFIER: _("Edit {}").format(intervention.identifier),
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, template, context)
|
||||
|
||||
class RemoveInterventionView(LoginRequiredMixin, BaseRemoveModalFormView):
|
||||
_MODEL_CLS = Intervention
|
||||
_REDIRECT_URL = "intervention:index"
|
||||
|
||||
@@ -10,10 +10,10 @@ from django.urls import reverse
|
||||
from intervention.models import Intervention
|
||||
from konova.sub_settings.django_settings import BASE_URL
|
||||
from konova.utils.qrcode import QrCode
|
||||
from konova.views.report import BaseReportView
|
||||
from konova.views.report import AbstractReportView
|
||||
|
||||
|
||||
class InterventionReportView(BaseReportView):
|
||||
class InterventionReportView(AbstractReportView):
|
||||
_TEMPLATE = 'intervention/report/report.html'
|
||||
_MODEL = Intervention
|
||||
|
||||
|
||||
@@ -15,17 +15,17 @@ from intervention.forms.modals.revocation import NewRevocationModalForm, EditRev
|
||||
from intervention.models import Intervention, RevocationDocument
|
||||
from konova.utils.documents import get_document
|
||||
from konova.utils.message_templates import DATA_UNSHARED, REVOCATION_EDITED, REVOCATION_REMOVED, REVOCATION_ADDED
|
||||
from konova.views.base import BaseModalFormView, BaseView
|
||||
from konova.views.modal import AbstractModalFormView, AbstractBaseView
|
||||
|
||||
|
||||
class BaseRevocationView(LoginRequiredMixin, BaseModalFormView):
|
||||
class BaseRevocationView(LoginRequiredMixin, AbstractModalFormView):
|
||||
_MODEL_CLS = Intervention
|
||||
_REDIRECT_URL = "intervention:detail"
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_default_user()
|
||||
|
||||
def _get_redirect_url(self, *args, **kwargs):
|
||||
@@ -48,7 +48,7 @@ class RemoveRevocationView(BaseRevocationView):
|
||||
_MSG_SUCCESS = REVOCATION_REMOVED
|
||||
|
||||
|
||||
class GetRevocationDocumentView(LoginRequiredMixin, BaseView):
|
||||
class GetRevocationDocumentView(LoginRequiredMixin, AbstractBaseView):
|
||||
_MODEL_CLS = RevocationDocument
|
||||
_REDIRECT_URL = "intervention:detail"
|
||||
|
||||
@@ -63,7 +63,7 @@ class GetRevocationDocumentView(LoginRequiredMixin, BaseView):
|
||||
return redirect("intervention:detail", id=doc.instance.id)
|
||||
return get_document(doc)
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_default_user()
|
||||
|
||||
def _user_has_shared_access(self, user, **kwargs):
|
||||
|
||||
@@ -35,6 +35,7 @@ class SimpleGeomForm(BaseForm):
|
||||
disabled=False,
|
||||
)
|
||||
_num_geometries_ignored: int = 0
|
||||
empty = False
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.read_only = kwargs.pop("read_only", True)
|
||||
@@ -49,11 +50,11 @@ class SimpleGeomForm(BaseForm):
|
||||
raise AttributeError
|
||||
|
||||
geojson = self.instance.geometry.as_feature_collection(srid=DEFAULT_SRID_RLP)
|
||||
self._set_geojson_properties(geojson, title=self.instance.identifier or None)
|
||||
geojson = self._set_geojson_properties(geojson, title=self.instance.identifier or None)
|
||||
geom = json.dumps(geojson)
|
||||
except AttributeError:
|
||||
# If no geometry exists for this form, we simply set the value to None and zoom to the maximum level
|
||||
geom = ""
|
||||
geom = json.dumps({})
|
||||
self.empty = True
|
||||
|
||||
self.initialize_form_field("output", geom)
|
||||
@@ -62,17 +63,17 @@ class SimpleGeomForm(BaseForm):
|
||||
super().is_valid()
|
||||
is_valid = True
|
||||
|
||||
# Get geojson from form
|
||||
geom = self.data.get("output", None)
|
||||
if geom is None or len(geom) == 0:
|
||||
# empty geometry is a valid geometry
|
||||
self.cleaned_data["output"] = MultiPolygon(srid=DEFAULT_SRID_RLP).ewkt
|
||||
return is_valid
|
||||
geom = json.loads(geom)
|
||||
# Make sure invalid geometry is properly rendered again to the user
|
||||
# Therefore: write submitted data back into form field
|
||||
# (does not matter whether we know if it is valid or invalid)
|
||||
submitted_data = self.data["output"]
|
||||
submitted_data = json.loads(submitted_data)
|
||||
submitted_data = self._set_geojson_properties(submitted_data)
|
||||
self.initialize_form_field("output", json.dumps(submitted_data))
|
||||
|
||||
# Write submitted data back into form field to make sure invalid geometry
|
||||
# will be rendered again on failed submit
|
||||
self.initialize_form_field("output", self.data["output"])
|
||||
# Get geojson from form for validity checking
|
||||
geom = self.data.get("output", json.dumps({}))
|
||||
geom = json.loads(geom)
|
||||
|
||||
# Initialize features list with empty MultiPolygon, so that an empty input will result in a
|
||||
# proper empty MultiPolygon object
|
||||
@@ -84,20 +85,23 @@ class SimpleGeomForm(BaseForm):
|
||||
"MultiPolygon",
|
||||
"MultiPolygon25D",
|
||||
]
|
||||
# Check validity for each feature of the geometry
|
||||
for feature in features_json:
|
||||
feature_geom = feature.get("geometry", feature)
|
||||
if feature_geom is None:
|
||||
# Fallback for rare cases where a feature does not contain any geometry
|
||||
continue
|
||||
|
||||
# Try to create a geometry object from the single feature
|
||||
feature_geom = json.dumps(feature_geom)
|
||||
g = gdal.OGRGeometry(feature_geom, srs=DEFAULT_SRID_RLP)
|
||||
|
||||
flatten_geometry = g.coord_dim > 2
|
||||
if flatten_geometry:
|
||||
geometry_has_unwanted_dimensions = g.coord_dim > 2
|
||||
if geometry_has_unwanted_dimensions:
|
||||
g = self.__flatten_geom_to_2D(g)
|
||||
|
||||
if g.geom_type not in accepted_ogr_types:
|
||||
geometry_type_is_accepted = g.geom_type not in accepted_ogr_types
|
||||
if geometry_type_is_accepted:
|
||||
self.add_error("output", _("Only surfaces allowed. Points or lines must be buffered."))
|
||||
is_valid &= False
|
||||
return is_valid
|
||||
@@ -109,27 +113,33 @@ class SimpleGeomForm(BaseForm):
|
||||
self._num_geometries_ignored += 1
|
||||
continue
|
||||
|
||||
# Whatever this geometry object is -> try to create a Polygon from it
|
||||
# The resulting polygon object automatically detects whether a valid polygon has been created or not
|
||||
g = Polygon.from_ewkt(g.ewkt)
|
||||
is_valid &= g.valid
|
||||
if not g.valid:
|
||||
self.add_error("output", g.valid_reason)
|
||||
return is_valid
|
||||
|
||||
# If the resulting polygon is just a single polygon, we add it to the list of properly casted features
|
||||
if isinstance(g, Polygon):
|
||||
features.append(g)
|
||||
elif isinstance(g, MultiPolygon):
|
||||
# The resulting polygon could be of type MultiPolygon (due to multiple surfaces)
|
||||
# If so, we extract all polygons from the MultiPolygon and extend the casted features list
|
||||
features.extend(list(g))
|
||||
|
||||
# Unionize all geometry features into one new MultiPolygon
|
||||
# Unionize all polygon features into one new MultiPolygon
|
||||
if features:
|
||||
form_geom = MultiPolygon(*features, srid=DEFAULT_SRID_RLP).unary_union
|
||||
else:
|
||||
# If no features have been processed, this indicates an empty geometry - so we store an empty geometry
|
||||
form_geom = MultiPolygon(srid=DEFAULT_SRID_RLP)
|
||||
|
||||
# Make sure to convert into a MultiPolygon. Relevant if a single Polygon is provided.
|
||||
form_geom = Geometry.cast_to_multipolygon(form_geom)
|
||||
|
||||
# Write unioned Multipolygon into cleaned data
|
||||
# Write unionized Multipolygon back into cleaned data
|
||||
if self.cleaned_data is None:
|
||||
self.cleaned_data = {}
|
||||
self.cleaned_data["output"] = form_geom.ewkt
|
||||
@@ -252,6 +262,8 @@ class SimpleGeomForm(BaseForm):
|
||||
"""
|
||||
features = geojson.get("features", [])
|
||||
for feature in features:
|
||||
if not feature.get("properties", None):
|
||||
feature["properties"] = {}
|
||||
feature["properties"]["editable"] = not self.read_only
|
||||
if title:
|
||||
feature["properties"]["title"] = title
|
||||
|
||||
@@ -10,6 +10,7 @@ import json
|
||||
from django.contrib.gis.db.models import MultiPolygonField
|
||||
from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
|
||||
from django.db import models, transaction
|
||||
from django.db.models import Q
|
||||
from django.utils import timezone
|
||||
from django.contrib.gis.geos import MultiPolygon
|
||||
|
||||
@@ -109,17 +110,26 @@ class Geometry(BaseResource):
|
||||
objs (list): The list of objects
|
||||
"""
|
||||
objs = []
|
||||
sets = [
|
||||
|
||||
# Some related data sets can be processed rather easily
|
||||
regular_sets = [
|
||||
self.intervention_set,
|
||||
self.compensation_set,
|
||||
self.ema_set,
|
||||
self.ecoaccount_set,
|
||||
]
|
||||
for _set in sets:
|
||||
for _set in regular_sets:
|
||||
set_objs = _set.filter(
|
||||
deleted=None
|
||||
)
|
||||
objs += set_objs
|
||||
|
||||
# ... but we need a special treatment for compensations, since they can be deleted directly OR inherit their
|
||||
# de-facto-deleted status from their deleted parent intervention
|
||||
comp_objs = self.compensation_set.filter(
|
||||
Q(deleted=None) & Q(intervention__deleted=None)
|
||||
)
|
||||
objs += comp_objs
|
||||
|
||||
return objs
|
||||
|
||||
def get_data_object(self):
|
||||
|
||||
@@ -677,12 +677,12 @@ class GeoReferencedMixin(models.Model):
|
||||
return request
|
||||
|
||||
instance_objs = []
|
||||
conflicts = self.geometry.conflicts_geometries.all()
|
||||
conflicts = self.geometry.conflicts_geometries.iterator()
|
||||
|
||||
for conflict in conflicts:
|
||||
instance_objs += conflict.affected_geometry.get_data_objects()
|
||||
|
||||
conflicts = self.geometry.conflicted_by_geometries.all()
|
||||
conflicts = self.geometry.conflicted_by_geometries.iterator()
|
||||
for conflict in conflicts:
|
||||
instance_objs += conflict.conflicting_geometry.get_data_objects()
|
||||
|
||||
|
||||
@@ -11,4 +11,4 @@ BASE_TITLE = "KSP - Kompensationsverzeichnis Service Portal"
|
||||
BASE_FRONTEND_TITLE = "Kompensationsverzeichnis Service Portal"
|
||||
TAB_TITLE_IDENTIFIER = "tab_title"
|
||||
HELP_LINK = "https://dienste.naturschutz.rlp.de/doku/doku.php?id=ksp2:start"
|
||||
IMPRESSUM_LINK = "https://naturschutz.rlp.de/index.php?q=impressum"
|
||||
IMPRESSUM_LINK = "https://naturschutz.rlp.de/ueber-uns/impressum"
|
||||
|
||||
@@ -20,6 +20,12 @@ ENTRY_REMOVE_MISSING_PERMISSION = _("Only conservation or registration office us
|
||||
MISSING_GROUP_PERMISSION = _("You need to be part of another user group.")
|
||||
CHECK_STATE_RESET = _("Status of Checked reset")
|
||||
|
||||
# USER | TEAM
|
||||
TEAM_ADDED = _("New team added")
|
||||
TEAM_EDITED = _("Team edited")
|
||||
TEAM_REMOVED = _("Team removed")
|
||||
TEAM_LEFT = _("Left Team")
|
||||
|
||||
# REMOVED
|
||||
GENERIC_REMOVED_TEMPLATE = _("{} removed")
|
||||
|
||||
|
||||
@@ -11,17 +11,17 @@ from compensation.forms.modals.compensation_action import NewCompensationActionM
|
||||
EditCompensationActionModalForm, RemoveCompensationActionModalForm
|
||||
from konova.utils.message_templates import COMPENSATION_STATE_ADDED, COMPENSATION_STATE_EDITED, \
|
||||
COMPENSATION_STATE_REMOVED
|
||||
from konova.views.base import BaseModalFormView
|
||||
from konova.views.modal import AbstractModalFormView
|
||||
|
||||
|
||||
class AbstractCompensationActionView(LoginRequiredMixin, BaseModalFormView):
|
||||
class AbstractCompensationActionView(LoginRequiredMixin, AbstractModalFormView):
|
||||
_MODEL_CLS = None
|
||||
_REDIRECT_URL = None
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_default_user()
|
||||
|
||||
def _get_redirect_url(self, *args, **kwargs):
|
||||
|
||||
@@ -5,37 +5,47 @@ Created on: 15.10.25
|
||||
"""
|
||||
from abc import abstractmethod
|
||||
|
||||
from bootstrap_modal_forms.mixins import is_ajax
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.http import HttpRequest, JsonResponse, HttpResponseRedirect
|
||||
from django.shortcuts import render, redirect, get_object_or_404
|
||||
from django.http import HttpRequest
|
||||
from django.shortcuts import redirect
|
||||
from django.urls import reverse
|
||||
from django.views import View
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from konova.contexts import BaseContext
|
||||
from konova.forms import BaseForm, SimpleGeomForm
|
||||
from konova.models import BaseObject
|
||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
||||
from konova.utils.general import check_user_is_in_any_group
|
||||
from konova.utils.message_templates import MISSING_GROUP_PERMISSION, DATA_UNSHARED, IDENTIFIER_REPLACED, \
|
||||
GEOMETRY_SIMPLIFIED, GEOMETRIES_IGNORED_TEMPLATE, RECORDED_BLOCKS_EDIT, FORM_INVALID
|
||||
from konova.utils.message_templates import MISSING_GROUP_PERMISSION, DATA_UNSHARED
|
||||
|
||||
|
||||
class BaseView(View):
|
||||
_TEMPLATE: str = "CHANGE_ME"
|
||||
_TAB_TITLE: str = "CHANGE_ME"
|
||||
_REDIRECT_URL: str = "CHANGE_ME"
|
||||
_REDIRECT_URL_ERROR: str = "home"
|
||||
class AbstractBaseView(View):
|
||||
""" An abstract base view
|
||||
|
||||
This class represents the root of all views on this project. It defines private variables which have to be used
|
||||
by inheriting classes for proper generic inheriting.
|
||||
|
||||
"""
|
||||
_TEMPLATE: str = "CHANGE_ME" # Path to template file
|
||||
_TAB_TITLE: str = "CHANGE_ME" # Title displayed on browser tab
|
||||
_REDIRECT_URL: str = "CHANGE_ME" # Default URL to redirect after processing (notation as django url "namespace:endpoint")
|
||||
_REDIRECT_URL_ERROR: str = "home" # Default URL to redirect in case of an error (same notation)
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
""" Dispatching requests before forwarding them into GET or POST endpoints.
|
||||
|
||||
Defines basic checks which need to be done before a user can get access to any view inheriting from
|
||||
this class.
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
*args ():
|
||||
**kwargs ():
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
request = check_user_is_in_any_group(request)
|
||||
|
||||
if not self._user_has_permission(request.user):
|
||||
if not self._user_has_permission(request.user, **kwargs):
|
||||
messages.info(request, MISSING_GROUP_PERMISSION)
|
||||
return redirect(reverse(self._REDIRECT_URL_ERROR))
|
||||
|
||||
@@ -46,379 +56,60 @@ class BaseView(View):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
@abstractmethod
|
||||
def _user_has_permission(self, user):
|
||||
""" Has to be implemented properly by inheriting classes
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
""" Checks whether the user has permission to get this view rendered.
|
||||
|
||||
If no specific check is needed, this method can be overwritten with a simple True returning.
|
||||
|
||||
Args:
|
||||
user ():
|
||||
user (User): The performing user
|
||||
**kwargs ():
|
||||
|
||||
Returns:
|
||||
|
||||
has_permission (bool): Whether the user has permission to see this view
|
||||
"""
|
||||
raise NotImplementedError("User permission not checked!")
|
||||
|
||||
@abstractmethod
|
||||
def _user_has_shared_access(self, user, **kwargs):
|
||||
""" Has to be implemented properly by inheriting classes
|
||||
""" Checks whether the user has shared access to this object.
|
||||
|
||||
If no shared-access-check is needed, this method can be overwritten with a simple True returning.
|
||||
|
||||
Args:
|
||||
user ():
|
||||
user (User): The performing user
|
||||
**kwargs ():
|
||||
|
||||
Returns:
|
||||
|
||||
has_shared_access (bool): Whether the user has shared access
|
||||
"""
|
||||
raise NotImplementedError("Shared access not checked!")
|
||||
|
||||
def _get_redirect_url(self, *args, **kwargs):
|
||||
return self._REDIRECT_URL
|
||||
""" Getter to construct a more specific, data dependant redirect URL
|
||||
|
||||
def _get_redirect_url_error(self, *args, **kwargs):
|
||||
return self._REDIRECT_URL_ERROR
|
||||
|
||||
class BaseModalFormView(BaseView):
|
||||
_TEMPLATE = "modal/modal_form.html"
|
||||
_MODEL_CLS = None
|
||||
_FORM_CLS = None
|
||||
_MSG_SUCCESS = None
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
def _user_has_shared_access(self, user, **kwargs):
|
||||
obj = get_object_or_404(self._MODEL_CLS, id=kwargs.get("id"))
|
||||
return obj.is_shared_with(user)
|
||||
|
||||
def get(self, request: HttpRequest, id: str, *args, **kwargs):
|
||||
obj = self._MODEL_CLS.objects.get(id=id)
|
||||
self._check_for_recorded_instance(obj)
|
||||
form = self._FORM_CLS(
|
||||
request.POST or None,
|
||||
request.FILES or None,
|
||||
instance=obj,
|
||||
request=request,
|
||||
**kwargs
|
||||
)
|
||||
context = {
|
||||
"form": form,
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, self._TEMPLATE, context)
|
||||
|
||||
def post(self, request: HttpRequest, id: str, *args, **kwargs):
|
||||
obj = self._MODEL_CLS.objects.get(id=id)
|
||||
self._check_for_recorded_instance(obj)
|
||||
form = self._FORM_CLS(
|
||||
request.POST or None,
|
||||
request.FILES or None,
|
||||
instance=obj,
|
||||
request=request,
|
||||
**kwargs
|
||||
)
|
||||
redirect_url = self._get_redirect_url(obj=obj)
|
||||
if form.is_valid():
|
||||
if not is_ajax(request.META):
|
||||
# Modal forms send one POST for checking on data validity. This can be used to return possible errors
|
||||
# on the form. A second POST (if no errors occurs) is sent afterward and needs to process the
|
||||
# saving/commiting of the data to the database. is_ajax() performs this check. The first request is
|
||||
# an ajax call, the second is a regular form POST.
|
||||
msg_success = self._get_msg_success(obj=obj, *args, **kwargs)
|
||||
form.save()
|
||||
messages.success(
|
||||
request,
|
||||
msg_success
|
||||
)
|
||||
return HttpResponseRedirect(redirect_url)
|
||||
else:
|
||||
context = {
|
||||
"form": form,
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, self._TEMPLATE, context)
|
||||
|
||||
def _get_redirect_url(self, *args, **kwargs):
|
||||
obj = kwargs.get("obj", None)
|
||||
assert obj is not None
|
||||
return reverse(self._REDIRECT_URL, args=(obj.id,))
|
||||
|
||||
def _get_msg_success(self, *args, **kwargs):
|
||||
return self._MSG_SUCCESS
|
||||
|
||||
def _check_for_recorded_instance(self, obj):
|
||||
""" Checks if the object on this view is recorded and runs some special logic if yes
|
||||
|
||||
If the instance is recorded, the view should provide some information about why the user can not edit anything.
|
||||
|
||||
There are situations where the form should be rendered regularly,
|
||||
e.g deduction forms for (recorded) eco accounts.
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
is_none = obj is None
|
||||
is_other_data_type = not isinstance(obj, BaseObject)
|
||||
|
||||
if is_none or is_other_data_type:
|
||||
# Do nothing
|
||||
return
|
||||
|
||||
if obj.is_recorded:
|
||||
self._block_form()
|
||||
|
||||
def _block_form(self):
|
||||
"""
|
||||
Overwrites template, providing no actions
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
self._TEMPLATE = "form/recorded_no_edit.html"
|
||||
|
||||
class BaseIndexView(BaseView):
|
||||
""" Base class for index views
|
||||
|
||||
"""
|
||||
_TEMPLATE = "generic_index.html"
|
||||
_INDEX_TABLE_CLS = None
|
||||
_REDIRECT_URL = "home"
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
def get(self, request: HttpRequest):
|
||||
qs = self._get_queryset()
|
||||
table = self._INDEX_TABLE_CLS(
|
||||
request=request,
|
||||
queryset=qs
|
||||
)
|
||||
context = {
|
||||
"table": table,
|
||||
TAB_TITLE_IDENTIFIER: self._TAB_TITLE,
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, self._TEMPLATE, context)
|
||||
|
||||
@abstractmethod
|
||||
def _get_queryset(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
# No specific permissions needed for opening base index view
|
||||
return True
|
||||
|
||||
def _user_has_shared_access(self, user, **kwargs):
|
||||
# No specific constraints for shared access of index views
|
||||
return True
|
||||
|
||||
|
||||
class BaseIdentifierGeneratorView(BaseView):
|
||||
_MODEL_CLS = None
|
||||
_REDIRECT_URL: str = "home"
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
def get(self, request: HttpRequest):
|
||||
tmp_obj = self._MODEL_CLS()
|
||||
identifier = tmp_obj.generate_new_identifier()
|
||||
while self._MODEL_CLS.objects.filter(identifier=identifier).exists():
|
||||
identifier = tmp_obj.generate_new_identifier()
|
||||
return JsonResponse(
|
||||
data={
|
||||
"gen_data": identifier
|
||||
}
|
||||
)
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
""" Should be overwritten in inheriting classes!
|
||||
|
||||
Args:
|
||||
user ():
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
return user.is_default_user()
|
||||
|
||||
def _user_has_shared_access(self, user, **kwargs):
|
||||
# No specific constraints for shared access
|
||||
return True
|
||||
|
||||
|
||||
class BaseFormView(BaseView):
|
||||
_MODEL_CLS = None
|
||||
_FORM_CLS = None
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
def _get_additional_context(self, **kwargs):
|
||||
"""
|
||||
By default the method simply returns the pre-defined redirect URL.
|
||||
|
||||
Args:
|
||||
*args ():
|
||||
**kwargs ():
|
||||
|
||||
Returns:
|
||||
|
||||
url (str): Reversed redirect url
|
||||
"""
|
||||
return {}
|
||||
return self._REDIRECT_URL
|
||||
|
||||
def _get_redirect_url_error(self, *args, **kwargs):
|
||||
""" Getter to construct a more specific, data dependant redirect URL in error cases
|
||||
|
||||
class BaseSpatialLocatedObjectFormView(LoginRequiredMixin, BaseFormView):
|
||||
_GEOMETRY_FORM_CLS = SimpleGeomForm
|
||||
By default the method simply returns the pre-defined redirect URL for errors.
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
Args:
|
||||
*args ():
|
||||
**kwargs ():
|
||||
|
||||
Returns:
|
||||
url (str): Reversed redirect url
|
||||
"""
|
||||
return self._REDIRECT_URL_ERROR
|
||||
|
||||
class BaseNewSpatialLocatedObjectFormView(BaseSpatialLocatedObjectFormView):
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
# User has to have default privilege to call this endpoint
|
||||
return user.is_default_user()
|
||||
|
||||
def _user_has_shared_access(self, user, **kwargs):
|
||||
# There is no shared access control since nothing exists yet
|
||||
return True
|
||||
|
||||
def get(self, request: HttpRequest, **kwargs):
|
||||
form: BaseForm = self._FORM_CLS(None, **kwargs, user=request.user)
|
||||
geom_form: SimpleGeomForm = self._GEOMETRY_FORM_CLS(None, user=request.user, read_only=False)
|
||||
|
||||
context = self._get_additional_context()
|
||||
context = BaseContext(request, additional_context=context).context
|
||||
context.update(
|
||||
{
|
||||
"form": form,
|
||||
"geom_form": geom_form,
|
||||
TAB_TITLE_IDENTIFIER: self._TAB_TITLE,
|
||||
}
|
||||
)
|
||||
return render(request, self._TEMPLATE, context)
|
||||
|
||||
def post(self, request: HttpRequest, **kwargs):
|
||||
form: BaseForm = self._FORM_CLS(request.POST or None, **kwargs, user=request.user)
|
||||
geom_form: SimpleGeomForm = self._GEOMETRY_FORM_CLS(request.POST or None, user=request.user, read_only=False)
|
||||
|
||||
if form.is_valid() and geom_form.is_valid():
|
||||
obj = form.save(request.user, geom_form)
|
||||
obj_redirect_url = reverse(self._REDIRECT_URL, args=(obj.id,))
|
||||
|
||||
generated_identifier = form.cleaned_data.get("identifier", None)
|
||||
|
||||
if generated_identifier != obj.identifier:
|
||||
messages.info(
|
||||
request,
|
||||
IDENTIFIER_REPLACED.format(
|
||||
generated_identifier,
|
||||
obj.identifier
|
||||
)
|
||||
)
|
||||
messages.success(request, _("{} added").format(obj.identifier))
|
||||
if geom_form.has_geometry_simplified():
|
||||
messages.info(
|
||||
request,
|
||||
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(obj_redirect_url)
|
||||
else:
|
||||
context = self._get_additional_context()
|
||||
messages.error(request, FORM_INVALID, extra_tags="danger",)
|
||||
|
||||
context = BaseContext(request, additional_context=context).context
|
||||
context.update(
|
||||
{
|
||||
"form": form,
|
||||
"geom_form": geom_form,
|
||||
TAB_TITLE_IDENTIFIER: self._TAB_TITLE,
|
||||
}
|
||||
)
|
||||
return render(request, self._TEMPLATE, context)
|
||||
|
||||
|
||||
class BaseEditSpatialLocatedObjectFormView(BaseSpatialLocatedObjectFormView):
|
||||
_TAB_TITLE = _("Edit {}")
|
||||
|
||||
def get(self, request: HttpRequest, id: str):
|
||||
obj = get_object_or_404(
|
||||
self._MODEL_CLS,
|
||||
id=id
|
||||
)
|
||||
obj_redirect_url = reverse(self._REDIRECT_URL, args=(obj.id,))
|
||||
|
||||
if obj.is_recorded:
|
||||
messages.info(
|
||||
request,
|
||||
RECORDED_BLOCKS_EDIT
|
||||
)
|
||||
return redirect(obj_redirect_url)
|
||||
|
||||
form: BaseForm = self._FORM_CLS(None, instance=obj, user=request.user)
|
||||
geom_form: SimpleGeomForm = self._GEOMETRY_FORM_CLS(None, instance=obj, read_only=False)
|
||||
|
||||
context = self._get_additional_context()
|
||||
context = BaseContext(request, additional_context=context).context
|
||||
context.update(
|
||||
{
|
||||
"form": form,
|
||||
"geom_form": geom_form,
|
||||
TAB_TITLE_IDENTIFIER: self._TAB_TITLE.format(obj.identifier),
|
||||
}
|
||||
)
|
||||
return render(request, self._TEMPLATE, context)
|
||||
|
||||
def post(self, request: HttpRequest, id: str):
|
||||
obj = get_object_or_404(
|
||||
self._MODEL_CLS,
|
||||
id=id
|
||||
)
|
||||
obj_redirect_url = reverse(self._REDIRECT_URL, args=(obj.id,))
|
||||
|
||||
form: BaseForm = self._FORM_CLS(request.POST or None, instance=obj, user=request.user)
|
||||
geom_form: SimpleGeomForm = self._GEOMETRY_FORM_CLS(request.POST or None, instance=obj, read_only=False)
|
||||
|
||||
if form.is_valid() and geom_form.is_valid():
|
||||
obj = form.save(request.user, geom_form)
|
||||
messages.success(request, _("{} edited").format(obj.identifier))
|
||||
|
||||
if geom_form.has_geometry_simplified():
|
||||
messages.info(
|
||||
request,
|
||||
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(obj_redirect_url)
|
||||
else:
|
||||
context = self._get_additional_context()
|
||||
messages.error(request, FORM_INVALID, extra_tags="danger",)
|
||||
|
||||
context = BaseContext(request, additional_context=context).context
|
||||
context.update(
|
||||
{
|
||||
"form": form,
|
||||
"geom_form": geom_form,
|
||||
TAB_TITLE_IDENTIFIER: self._TAB_TITLE.format(obj.identifier),
|
||||
}
|
||||
)
|
||||
return render(request, self._TEMPLATE, context)
|
||||
|
||||
def _user_has_shared_access(self, user, **kwargs):
|
||||
obj = get_object_or_404(self._MODEL_CLS, id=kwargs.get('id', None))
|
||||
return obj.is_shared_with(user)
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
return user.is_default_user()
|
||||
@@ -10,10 +10,10 @@ from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from compensation.forms.modals.deadline import NewDeadlineModalForm, EditDeadlineModalForm
|
||||
from konova.forms.modals import RemoveDeadlineModalForm
|
||||
from konova.utils.message_templates import DEADLINE_ADDED, DEADLINE_EDITED, DEADLINE_REMOVED
|
||||
from konova.views.base import BaseModalFormView
|
||||
from konova.views.modal import AbstractModalFormView
|
||||
|
||||
|
||||
class AbstractNewDeadlineView(LoginRequiredMixin, BaseModalFormView):
|
||||
class AbstractNewDeadlineView(LoginRequiredMixin, AbstractModalFormView):
|
||||
_MODEL_CLS = None
|
||||
_FORM_CLS = NewDeadlineModalForm
|
||||
_REDIRECT_URL = None
|
||||
@@ -25,11 +25,11 @@ class AbstractNewDeadlineView(LoginRequiredMixin, BaseModalFormView):
|
||||
def _get_redirect_url(self, *args, **kwargs):
|
||||
return super()._get_redirect_url(*args, **kwargs) + "#related_data"
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_default_user()
|
||||
|
||||
|
||||
class AbstractEditDeadlineView(LoginRequiredMixin, BaseModalFormView):
|
||||
class AbstractEditDeadlineView(LoginRequiredMixin, AbstractModalFormView):
|
||||
_MODEL_CLS = None
|
||||
_FORM_CLS = EditDeadlineModalForm
|
||||
_REDIRECT_URL = None
|
||||
@@ -41,11 +41,11 @@ class AbstractEditDeadlineView(LoginRequiredMixin, BaseModalFormView):
|
||||
def _get_redirect_url(self, *args, **kwargs):
|
||||
return super()._get_redirect_url(*args, **kwargs) + "#related_data"
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_default_user()
|
||||
|
||||
|
||||
class AbstractRemoveDeadlineView(LoginRequiredMixin, BaseModalFormView):
|
||||
class AbstractRemoveDeadlineView(LoginRequiredMixin, AbstractModalFormView):
|
||||
_MODEL_CLS = None
|
||||
_FORM_CLS = RemoveDeadlineModalForm
|
||||
_REDIRECT_URL = None
|
||||
@@ -57,5 +57,5 @@ class AbstractRemoveDeadlineView(LoginRequiredMixin, BaseModalFormView):
|
||||
def _get_redirect_url(self, *args, **kwargs):
|
||||
return super()._get_redirect_url(*args, **kwargs) + "#related_data"
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_default_user()
|
||||
|
||||
@@ -11,10 +11,10 @@ from django.urls import reverse
|
||||
from intervention.forms.modals.deduction import NewEcoAccountDeductionModalForm, EditEcoAccountDeductionModalForm, \
|
||||
RemoveEcoAccountDeductionModalForm
|
||||
from konova.utils.general import check_id_is_valid_uuid
|
||||
from konova.views.base import BaseModalFormView
|
||||
from konova.views.modal import AbstractModalFormView
|
||||
|
||||
|
||||
class AbstractDeductionView(BaseModalFormView):
|
||||
class AbstractDeductionView(AbstractModalFormView):
|
||||
_REDIRECT_URL = None
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
@@ -28,7 +28,7 @@ class AbstractDeductionView(BaseModalFormView):
|
||||
"""
|
||||
pass
|
||||
|
||||
def _user_has_permission(self, user) -> bool:
|
||||
def _user_has_permission(self, user, **kwargs) -> bool:
|
||||
"""
|
||||
|
||||
Args:
|
||||
|
||||
@@ -16,10 +16,10 @@ from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP
|
||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
||||
from konova.utils.general import check_id_is_valid_uuid
|
||||
from konova.utils.message_templates import DO_NOT_FORGET_TO_SHARE
|
||||
from konova.views.base import BaseView
|
||||
from konova.views.base import AbstractBaseView
|
||||
|
||||
|
||||
class BaseDetailView(LoginRequiredMixin, BaseView):
|
||||
class BaseDetailView(LoginRequiredMixin, AbstractBaseView):
|
||||
_MODEL_CLS = None
|
||||
|
||||
class Meta:
|
||||
@@ -42,7 +42,7 @@ class BaseDetailView(LoginRequiredMixin, BaseView):
|
||||
# Access to an entry's detail view is not restricted by the state of being-shared or not
|
||||
return True
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
# Detail views have no restrictions
|
||||
return True
|
||||
|
||||
|
||||
@@ -12,10 +12,10 @@ from django.shortcuts import get_object_or_404
|
||||
from konova.forms.modals import EditDocumentModalForm
|
||||
from konova.utils.documents import get_document
|
||||
from konova.utils.message_templates import DOCUMENT_ADDED, DOCUMENT_EDITED, DOCUMENT_REMOVED_TEMPLATE
|
||||
from konova.views.base import BaseModalFormView, BaseView
|
||||
from konova.views.modal import AbstractModalFormView, AbstractBaseView
|
||||
|
||||
|
||||
class AbstractNewDocumentView(LoginRequiredMixin, BaseModalFormView):
|
||||
class AbstractNewDocumentView(LoginRequiredMixin, AbstractModalFormView):
|
||||
_MODEL_CLS = None
|
||||
_FORM_CLS = None
|
||||
_REDIRECT_URL = None
|
||||
@@ -27,11 +27,11 @@ class AbstractNewDocumentView(LoginRequiredMixin, BaseModalFormView):
|
||||
def _get_redirect_url(self, *args, **kwargs):
|
||||
return super()._get_redirect_url(*args, **kwargs) + "#related_data"
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_default_user()
|
||||
|
||||
|
||||
class AbstractGetDocumentView(LoginRequiredMixin, BaseView):
|
||||
class AbstractGetDocumentView(LoginRequiredMixin, AbstractBaseView):
|
||||
_MODEL_CLS = None
|
||||
_DOCUMENT_CLS = None
|
||||
|
||||
@@ -58,7 +58,7 @@ class AbstractGetDocumentView(LoginRequiredMixin, BaseView):
|
||||
def post(self, request, id: str, doc_id: str):
|
||||
return self.get(request, id, doc_id)
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_default_user()
|
||||
|
||||
def _user_has_shared_access(self, user, **kwargs):
|
||||
@@ -68,7 +68,7 @@ class AbstractGetDocumentView(LoginRequiredMixin, BaseView):
|
||||
return obj.is_shared_with(user)
|
||||
|
||||
|
||||
class AbstractRemoveDocumentView(LoginRequiredMixin, BaseModalFormView):
|
||||
class AbstractRemoveDocumentView(LoginRequiredMixin, AbstractModalFormView):
|
||||
_MODEL_CLS = None
|
||||
_DOCUMENT_CLS = None
|
||||
_FORM_CLS = None
|
||||
@@ -80,7 +80,7 @@ class AbstractRemoveDocumentView(LoginRequiredMixin, BaseModalFormView):
|
||||
def _get_redirect_url(self, *args, **kwargs):
|
||||
return super()._get_redirect_url(*args, **kwargs) + "#related_data"
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_default_user()
|
||||
|
||||
def _get_msg_success(self, *args, **kwargs):
|
||||
@@ -90,7 +90,7 @@ class AbstractRemoveDocumentView(LoginRequiredMixin, BaseModalFormView):
|
||||
return self._MSG_SUCCESS.format(doc.title)
|
||||
|
||||
|
||||
class AbstractEditDocumentView(LoginRequiredMixin, BaseModalFormView):
|
||||
class AbstractEditDocumentView(LoginRequiredMixin, AbstractModalFormView):
|
||||
_MODEL_CLS = None
|
||||
_DOCUMENT_CLS = None
|
||||
_FORM_CLS = EditDocumentModalForm
|
||||
@@ -100,7 +100,7 @@ class AbstractEditDocumentView(LoginRequiredMixin, BaseModalFormView):
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_default_user()
|
||||
|
||||
def _get_redirect_url(self, *args, **kwargs):
|
||||
|
||||
282
konova/views/form.py
Normal file
282
konova/views/form.py
Normal file
@@ -0,0 +1,282 @@
|
||||
"""
|
||||
Author: Michel Peltriaux
|
||||
Created on: 12.12.25
|
||||
|
||||
"""
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.http import HttpRequest
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from konova.contexts import BaseContext
|
||||
from konova.forms import BaseForm, SimpleGeomForm
|
||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
||||
from konova.utils.message_templates import RECORDED_BLOCKS_EDIT, GEOMETRY_SIMPLIFIED, GEOMETRIES_IGNORED_TEMPLATE, \
|
||||
FORM_INVALID, IDENTIFIER_REPLACED
|
||||
from konova.views.base import AbstractBaseView
|
||||
|
||||
|
||||
class AbstractFormView(AbstractBaseView):
|
||||
""" Abstract base class for rendering form views
|
||||
|
||||
"""
|
||||
_MODEL_CLS = None
|
||||
_FORM_CLS = None
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
def _get_additional_context(self, **kwargs):
|
||||
""" Getter for additional data, which is needed to properly render the current view
|
||||
|
||||
Args:
|
||||
**kwargs ():
|
||||
|
||||
Returns:
|
||||
context (dict): Additional context data for rendering
|
||||
"""
|
||||
return {}
|
||||
|
||||
|
||||
class AbstractGeometryFormView(LoginRequiredMixin, AbstractFormView):
|
||||
""" Abstract base view for processing objects with spatial data
|
||||
|
||||
"""
|
||||
_GEOMETRY_FORM_CLS = SimpleGeomForm
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
|
||||
class AbstractNewGeometryFormView(AbstractGeometryFormView):
|
||||
""" Base view for creating new spatial data related to objects
|
||||
|
||||
"""
|
||||
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
# User has to have default privilege to call this endpoint
|
||||
return user.is_default_user()
|
||||
|
||||
def _user_has_shared_access(self, user, **kwargs):
|
||||
# There is no shared access control since nothing exists yet
|
||||
return True
|
||||
|
||||
def get(self, request: HttpRequest, *args, **kwargs):
|
||||
""" GET endpoint for rendering a form view where object data and spatial data are processed
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
**kwargs ():
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
# First initialize the regular object form and the geometry form based on request-bound data
|
||||
form: BaseForm = self._FORM_CLS(None, **kwargs, user=request.user)
|
||||
geom_form: SimpleGeomForm = self._GEOMETRY_FORM_CLS(None, user=request.user, read_only=False)
|
||||
|
||||
# Get some additional context and put everything into the rendering pipeline
|
||||
context = self._get_additional_context()
|
||||
context = BaseContext(request, additional_context=context).context
|
||||
context.update(
|
||||
{
|
||||
"form": form,
|
||||
"geom_form": geom_form,
|
||||
TAB_TITLE_IDENTIFIER: self._TAB_TITLE,
|
||||
}
|
||||
)
|
||||
return render(request, self._TEMPLATE, context)
|
||||
|
||||
def post(self, request: HttpRequest, *args, **kwargs):
|
||||
""" POST endpoint for processing object and spatial data provided by forms
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
**kwargs ():
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
# First initialize the regular object form and the geometry form based on request-bound data
|
||||
form: BaseForm = self._FORM_CLS(request.POST or None, **kwargs, user=request.user)
|
||||
geom_form: SimpleGeomForm = self._GEOMETRY_FORM_CLS(request.POST or None, user=request.user, read_only=False)
|
||||
|
||||
# Only continue if both forms are without errors
|
||||
if form.is_valid() and geom_form.is_valid():
|
||||
obj = form.save(request.user, geom_form)
|
||||
obj_redirect_url = reverse(self._REDIRECT_URL, args=(obj.id,))
|
||||
|
||||
generated_identifier = form.cleaned_data.get("identifier", None)
|
||||
|
||||
# There is a rare chance that an identifier has been taken already between sending the form and processing
|
||||
# the data. If the identifier can not be used anymore, we have to inform the user that another identifier
|
||||
# had to be generated
|
||||
if generated_identifier != obj.identifier:
|
||||
messages.info(
|
||||
request,
|
||||
IDENTIFIER_REPLACED.format(
|
||||
generated_identifier,
|
||||
obj.identifier
|
||||
)
|
||||
)
|
||||
messages.success(request, _("{} added").format(obj.identifier))
|
||||
# Very complex geometries have to be simplified automatically while processing the spatial data. If this
|
||||
# is the case, the user has to be informed. (They might want to check whether the stored geometry still
|
||||
# fits their needs)
|
||||
if geom_form.has_geometry_simplified():
|
||||
messages.info(
|
||||
request,
|
||||
GEOMETRY_SIMPLIFIED
|
||||
)
|
||||
|
||||
# If certain parts of the geometry do not pass the quality check (e.g. way too small and therefore more like
|
||||
# cutting errors) we need to inform the user that some parts have been removed/ignored while storing the
|
||||
# geometry
|
||||
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(obj_redirect_url)
|
||||
else:
|
||||
# Something was not properly entered on the forms, so we have to inform the user
|
||||
context = self._get_additional_context()
|
||||
messages.error(request, FORM_INVALID, extra_tags="danger",)
|
||||
|
||||
context = BaseContext(request, additional_context=context).context
|
||||
context.update(
|
||||
{
|
||||
"form": form,
|
||||
"geom_form": geom_form,
|
||||
TAB_TITLE_IDENTIFIER: self._TAB_TITLE,
|
||||
}
|
||||
)
|
||||
return render(request, self._TEMPLATE, context)
|
||||
|
||||
|
||||
class AbstractEditGeometryFormView(AbstractGeometryFormView):
|
||||
""" Base view for editing new spatial data related to objects
|
||||
|
||||
"""
|
||||
_TAB_TITLE = _("Edit {}")
|
||||
|
||||
def get(self, request: HttpRequest, id: str, *args, **kwargs):
|
||||
""" GET endpoint for rendering a form view where object data and spatial data are processed
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
id (str): The id of the object (not the geometry)
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
# First fetch the object identified by the id
|
||||
obj = get_object_or_404(
|
||||
self._MODEL_CLS,
|
||||
id=id
|
||||
)
|
||||
obj_redirect_url = reverse(self._REDIRECT_URL, args=(obj.id,))
|
||||
|
||||
# Check whether the object is recorded. If so - we can redirect the user and inform about the un-editability
|
||||
# of this entry
|
||||
if obj.is_recorded:
|
||||
messages.info(
|
||||
request,
|
||||
RECORDED_BLOCKS_EDIT
|
||||
)
|
||||
return redirect(obj_redirect_url)
|
||||
|
||||
# Seems like the object is not recorded. Good - initialize the forms based on the obj and request-bound data
|
||||
form: BaseForm = self._FORM_CLS(None, instance=obj, user=request.user)
|
||||
geom_form: SimpleGeomForm = self._GEOMETRY_FORM_CLS(None, instance=obj, read_only=False)
|
||||
|
||||
# Get additional context for rendering and put everything in the rendering pipeline
|
||||
context = self._get_additional_context()
|
||||
context = BaseContext(request, additional_context=context).context
|
||||
context.update(
|
||||
{
|
||||
"form": form,
|
||||
"geom_form": geom_form,
|
||||
TAB_TITLE_IDENTIFIER: self._TAB_TITLE.format(obj.identifier),
|
||||
}
|
||||
)
|
||||
return render(request, self._TEMPLATE, context)
|
||||
|
||||
def post(self, request: HttpRequest, id: str, *args, **kwargs):
|
||||
""" POST endpoint for processing object and spatial data provided by forms
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
id (str): The object's id
|
||||
*args ():
|
||||
**kwargs ():
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
obj = get_object_or_404(
|
||||
self._MODEL_CLS,
|
||||
id=id
|
||||
)
|
||||
obj_redirect_url = reverse(self._REDIRECT_URL, args=(obj.id,))
|
||||
|
||||
# If the object is recorded, we abort the processing directly and inform the user
|
||||
if obj.is_recorded:
|
||||
messages.info(
|
||||
request,
|
||||
RECORDED_BLOCKS_EDIT
|
||||
)
|
||||
return redirect(obj_redirect_url)
|
||||
|
||||
# Initialize forms with obj and request-bound data
|
||||
form: BaseForm = self._FORM_CLS(request.POST or None, instance=obj, user=request.user)
|
||||
geom_form: SimpleGeomForm = self._GEOMETRY_FORM_CLS(request.POST or None, instance=obj, read_only=False)
|
||||
|
||||
if form.is_valid() and geom_form.is_valid():
|
||||
obj = form.save(request.user, geom_form)
|
||||
messages.success(request, _("{} edited").format(obj.identifier))
|
||||
|
||||
# Very complex geometries have to be simplified automatically while processing the spatial data. If this
|
||||
# is the case, the user has to be informed. (They might want to check whether the stored geometry still
|
||||
# fits their needs)
|
||||
if geom_form.has_geometry_simplified():
|
||||
messages.info(
|
||||
request,
|
||||
GEOMETRY_SIMPLIFIED
|
||||
)
|
||||
|
||||
# If certain parts of the geometry do not pass the quality check (e.g. way too small and therefore more like
|
||||
# cutting errors) we need to inform the user that some parts have been removed/ignored while storing the
|
||||
# geometry
|
||||
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(obj_redirect_url)
|
||||
else:
|
||||
context = self._get_additional_context()
|
||||
messages.error(request, FORM_INVALID, extra_tags="danger",)
|
||||
|
||||
context = BaseContext(request, additional_context=context).context
|
||||
context.update(
|
||||
{
|
||||
"form": form,
|
||||
"geom_form": geom_form,
|
||||
TAB_TITLE_IDENTIFIER: self._TAB_TITLE.format(obj.identifier),
|
||||
}
|
||||
)
|
||||
return render(request, self._TEMPLATE, context)
|
||||
|
||||
def _user_has_shared_access(self, user, **kwargs):
|
||||
obj = get_object_or_404(self._MODEL_CLS, id=kwargs.get('id', None))
|
||||
return obj.is_shared_with(user)
|
||||
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_default_user()
|
||||
@@ -15,10 +15,10 @@ from konova.models import Geometry
|
||||
from konova.settings import GEOM_THRESHOLD_RECALCULATION_SECONDS
|
||||
from konova.sub_settings.lanis_settings import DEFAULT_SRID_RLP
|
||||
from konova.tasks import celery_update_parcels
|
||||
from konova.views.base import BaseView
|
||||
from konova.views.base import AbstractBaseView
|
||||
|
||||
|
||||
class GeomParcelsView(BaseView):
|
||||
class GeomParcelsView(AbstractBaseView):
|
||||
_TEMPLATE = "konova/includes/parcels/parcel_table_frame.html"
|
||||
|
||||
def get(self, request: HttpRequest, id: str):
|
||||
@@ -110,11 +110,11 @@ class GeomParcelsView(BaseView):
|
||||
def _user_has_shared_access(self, user, **kwargs):
|
||||
return True
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return True
|
||||
|
||||
|
||||
class GeomParcelsContentView(BaseView):
|
||||
class GeomParcelsContentView(AbstractBaseView):
|
||||
_TEMPLATE = "konova/includes/parcels/parcel_table_content.html"
|
||||
|
||||
def get(self, request: HttpRequest, id: str, page: int):
|
||||
@@ -160,5 +160,5 @@ class GeomParcelsContentView(BaseView):
|
||||
def _user_has_shared_access(self, user, **kwargs):
|
||||
return True
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return True
|
||||
|
||||
@@ -15,11 +15,11 @@ from compensation.models import EcoAccount, Compensation
|
||||
from intervention.models import Intervention
|
||||
from konova.contexts import BaseContext
|
||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
||||
from konova.views.base import BaseView
|
||||
from konova.views.base import AbstractBaseView
|
||||
from news.models import ServerMessage
|
||||
|
||||
|
||||
class HomeView(LoginRequiredMixin, BaseView):
|
||||
class HomeView(LoginRequiredMixin, AbstractBaseView):
|
||||
_TEMPLATE = "konova/home.html"
|
||||
|
||||
def get(self, request: HttpRequest):
|
||||
@@ -74,7 +74,7 @@ class HomeView(LoginRequiredMixin, BaseView):
|
||||
context = BaseContext(request, additional_context).context
|
||||
return render(request, self._TEMPLATE, context)
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
# No specific permission needed for home view
|
||||
return True
|
||||
|
||||
|
||||
55
konova/views/identifier.py
Normal file
55
konova/views/identifier.py
Normal file
@@ -0,0 +1,55 @@
|
||||
"""
|
||||
Author: Michel Peltriaux
|
||||
Created on: 12.12.25
|
||||
|
||||
"""
|
||||
from django.http import HttpRequest, JsonResponse
|
||||
|
||||
from konova.views.base import AbstractBaseView
|
||||
|
||||
|
||||
class AbstractIdentifierGeneratorView(AbstractBaseView):
|
||||
""" View class
|
||||
|
||||
Process a request for generating a new identifier
|
||||
|
||||
"""
|
||||
_MODEL_CLS = None
|
||||
_REDIRECT_URL: str = "home"
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
def get(self, request: HttpRequest):
|
||||
""" GET endpoint
|
||||
|
||||
Args:
|
||||
request ():
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
tmp_obj = self._MODEL_CLS()
|
||||
identifier = tmp_obj.generate_new_identifier()
|
||||
while self._MODEL_CLS.objects.filter(identifier=identifier).exists():
|
||||
identifier = tmp_obj.generate_new_identifier()
|
||||
return JsonResponse(
|
||||
data={
|
||||
"gen_data": identifier
|
||||
}
|
||||
)
|
||||
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
""" Should be overwritten in inheriting classes!
|
||||
|
||||
Args:
|
||||
user ():
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
return user.is_default_user()
|
||||
|
||||
def _user_has_shared_access(self, user, **kwargs):
|
||||
# No specific constraints for shared access
|
||||
return True
|
||||
65
konova/views/index.py
Normal file
65
konova/views/index.py
Normal file
@@ -0,0 +1,65 @@
|
||||
"""
|
||||
Author: Michel Peltriaux
|
||||
Created on: 12.12.25
|
||||
|
||||
"""
|
||||
from abc import abstractmethod
|
||||
|
||||
from django.http import HttpRequest
|
||||
from django.shortcuts import render
|
||||
|
||||
from konova.contexts import BaseContext
|
||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
||||
from konova.views.base import AbstractBaseView
|
||||
|
||||
|
||||
class AbstractIndexView(AbstractBaseView):
|
||||
""" Abstract base class for all index views
|
||||
|
||||
"""
|
||||
_TEMPLATE: str = "generic_index.html"
|
||||
_INDEX_TABLE_CLS = None
|
||||
_REDIRECT_URL: str = "home"
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
def get(self, request: HttpRequest, *args, **kwargs):
|
||||
""" GET endpoint for rendering index views
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
*args ():
|
||||
**kwargs ():
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
qs = self._get_queryset()
|
||||
table = self._INDEX_TABLE_CLS(
|
||||
request=request,
|
||||
queryset=qs
|
||||
)
|
||||
context = {
|
||||
"table": table,
|
||||
TAB_TITLE_IDENTIFIER: self._TAB_TITLE,
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, self._TEMPLATE, context)
|
||||
|
||||
@abstractmethod
|
||||
def _get_queryset(self):
|
||||
""" Generic getter for the queryset of objects which shall be processed on this view
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
# No specific permissions needed for opening base index view
|
||||
return True
|
||||
|
||||
def _user_has_shared_access(self, user, **kwargs):
|
||||
# No specific constraints for shared access of index views
|
||||
return True
|
||||
@@ -9,10 +9,10 @@ from django.shortcuts import get_object_or_404, render
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from konova.contexts import BaseContext
|
||||
from konova.views.base import BaseView
|
||||
from konova.views.base import AbstractBaseView
|
||||
|
||||
|
||||
class AbstractLogView(BaseView):
|
||||
class AbstractLogView(AbstractBaseView):
|
||||
_MODEL_CLS = None
|
||||
_TEMPLATE = "modal/modal_generic.html"
|
||||
|
||||
@@ -46,5 +46,5 @@ class AbstractLogView(BaseView):
|
||||
obj = get_object_or_404(self._MODEL_CLS, id=obj_id)
|
||||
return obj.is_shared_with(user)
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_default_user()
|
||||
|
||||
183
konova/views/modal.py
Normal file
183
konova/views/modal.py
Normal file
@@ -0,0 +1,183 @@
|
||||
"""
|
||||
Author: Michel Peltriaux
|
||||
Created on: 12.12.25
|
||||
|
||||
"""
|
||||
from bootstrap_modal_forms.mixins import is_ajax
|
||||
from django.contrib import messages
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.http import HttpRequest, HttpResponseRedirect
|
||||
from django.shortcuts import get_object_or_404, render
|
||||
from django.urls import reverse
|
||||
|
||||
from konova.contexts import BaseContext
|
||||
from konova.models import BaseObject
|
||||
from konova.views.base import AbstractBaseView
|
||||
|
||||
|
||||
class AbstractModalFormView(AbstractBaseView):
|
||||
""" Abstract base view providing logic to perform most modal form based view renderings
|
||||
|
||||
"""
|
||||
_TEMPLATE: str = "modal/modal_form.html"
|
||||
_MODEL_CLS = None
|
||||
_FORM_CLS = None
|
||||
_MSG_SUCCESS = None
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
def _user_has_shared_access(self, user, **kwargs):
|
||||
""" Checks whether the user has shared access to this object.
|
||||
|
||||
For objects inheriting from BaseObject class the method 'is_shared_with()' is a handy
|
||||
wrapper for checking shared access. For any other circumstances this method should be overwritten
|
||||
to provide custom shared-access-checking logic.
|
||||
|
||||
If no shared-access-check is needed, this method can be overwritten with a simple True returning.
|
||||
|
||||
Args:
|
||||
user (User): The performing user
|
||||
**kwargs ():
|
||||
|
||||
Returns:
|
||||
has_shared_access (bool): Whether the user has shared access
|
||||
"""
|
||||
obj = get_object_or_404(self._MODEL_CLS, id=kwargs.get("id"))
|
||||
return obj.is_shared_with(user)
|
||||
|
||||
def get(self, request: HttpRequest, *args, **kwargs):
|
||||
""" GET endpoint for rendering a view holding a modal form
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
*args ():
|
||||
**kwargs ():
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
# If there is an id provided as mapped parameter from the URL -> take it ...
|
||||
_id = kwargs.pop("id", None)
|
||||
try:
|
||||
# ... and try to resolve it into an object
|
||||
obj = self._MODEL_CLS.objects.get(id=_id)
|
||||
self._check_for_recorded_instance(obj)
|
||||
except ObjectDoesNotExist:
|
||||
# ... If there is none, maybe we are currently processing
|
||||
# the creation of a new object (therefore no id yet), so let's continue
|
||||
obj = None
|
||||
form = self._FORM_CLS(
|
||||
request.POST or None,
|
||||
request.FILES or None,
|
||||
instance=obj,
|
||||
request=request,
|
||||
**kwargs
|
||||
)
|
||||
context = {
|
||||
"form": form,
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, self._TEMPLATE, context)
|
||||
|
||||
def post(self, request: HttpRequest, *args, **kwargs):
|
||||
""" POST endpoint for processing form contents of a view
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
*args ():
|
||||
**kwargs ():
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
# If there is an id provided as mapped parameter from the URL take it ...
|
||||
_id = kwargs.pop("id", None)
|
||||
try:
|
||||
# ... and try to resolve it into a record
|
||||
obj = self._MODEL_CLS.objects.get(id=_id)
|
||||
self._check_for_recorded_instance(obj)
|
||||
except ObjectDoesNotExist:
|
||||
# ... If there is none, maybe we are currently processing
|
||||
# the creation of a new object (therefore no id yet), so let's continue
|
||||
obj = None
|
||||
form = self._FORM_CLS(
|
||||
request.POST or None,
|
||||
request.FILES or None,
|
||||
instance=obj,
|
||||
request=request,
|
||||
**kwargs
|
||||
)
|
||||
# Get now the redirect url and take specifics of the obj into account for that.
|
||||
# We do not do this after saving the form to avoid side effects due to possibly changed data
|
||||
redirect_url = self._get_redirect_url(obj=obj)
|
||||
if form.is_valid():
|
||||
# Modal forms send one POST for checking on data validity. This is used to evaluate possible errors
|
||||
# on the form. The second POST (if no errors have been found) is the 'proper' one,
|
||||
# which we want to process by saving/commiting of the data to the database.
|
||||
if not is_ajax(request.META):
|
||||
# Get now the success message and take specifics of the obj into account for that
|
||||
msg_success = self._get_msg_success(obj=obj, *args, **kwargs)
|
||||
form.save()
|
||||
messages.success(
|
||||
request,
|
||||
msg_success
|
||||
)
|
||||
return HttpResponseRedirect(redirect_url)
|
||||
else:
|
||||
context = {
|
||||
"form": form,
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, self._TEMPLATE, context)
|
||||
|
||||
def _get_redirect_url(self, *args, **kwargs):
|
||||
""" Getter to construct a more specific, data dependant redirect URL (if needed)
|
||||
|
||||
Args:
|
||||
*args ():
|
||||
**kwargs ():
|
||||
|
||||
Returns:
|
||||
url (str): Reversed redirect url
|
||||
"""
|
||||
obj = kwargs.get("obj", None)
|
||||
if obj:
|
||||
return reverse(self._REDIRECT_URL, args=(obj.id,))
|
||||
else:
|
||||
return reverse(self._REDIRECT_URL)
|
||||
|
||||
def _get_msg_success(self, *args, **kwargs):
|
||||
""" Getter to construct a more specific, data dependant success message
|
||||
|
||||
Args:
|
||||
*args ():
|
||||
**kwargs ():
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
return self._MSG_SUCCESS
|
||||
|
||||
def _check_for_recorded_instance(self, obj):
|
||||
""" Checks if the object on this view is recorded and runs some special logic if so
|
||||
|
||||
If the instance is recorded, the view should provide some information about why the user can not edit anything.
|
||||
This behaviour is only intended to mask any form for instances based on the BaseObject class.
|
||||
|
||||
There are situations where the form should be rendered regularly, despite the instance being recorded,
|
||||
e.g. for rendering deduction form contents on (recorded) eco accounts.
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
is_none = obj is None
|
||||
is_other_data_type = not isinstance(obj, BaseObject)
|
||||
|
||||
if is_none or is_other_data_type:
|
||||
# Do nothing
|
||||
return
|
||||
|
||||
if obj.is_recorded:
|
||||
# Replace default template with a blocking one
|
||||
self._TEMPLATE = "form/recorded_no_edit.html"
|
||||
@@ -7,15 +7,15 @@ Created on: 19.08.22
|
||||
"""
|
||||
from konova.forms.modals import RecordModalForm
|
||||
from konova.utils.message_templates import ENTRY_RECORDED, ENTRY_UNRECORDED
|
||||
from konova.views.base import BaseModalFormView
|
||||
from konova.views.modal import AbstractModalFormView
|
||||
|
||||
|
||||
class AbstractRecordView(BaseModalFormView):
|
||||
class AbstractRecordView(AbstractModalFormView):
|
||||
_MODEL_CLS = None
|
||||
_FORM_CLS = RecordModalForm
|
||||
_MSG_SUCCESS = None
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_ets_user()
|
||||
|
||||
def _get_msg_success(self, *args, **kwargs):
|
||||
|
||||
@@ -7,16 +7,15 @@ from django.urls import reverse
|
||||
|
||||
from konova.forms.modals import RemoveModalForm
|
||||
from konova.utils.message_templates import GENERIC_REMOVED_TEMPLATE
|
||||
from konova.views.base import BaseModalFormView
|
||||
from konova.views.modal import AbstractModalFormView
|
||||
|
||||
|
||||
class BaseRemoveModalFormView(BaseModalFormView):
|
||||
_MODEL_CLS = None
|
||||
class BaseRemoveModalFormView(AbstractModalFormView):
|
||||
_FORM_CLS = RemoveModalForm
|
||||
_MSG_SUCCESS = GENERIC_REMOVED_TEMPLATE
|
||||
_REDIRECT_URL = None
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_default_user()
|
||||
|
||||
def _get_redirect_url(self, *args, **kwargs):
|
||||
|
||||
@@ -13,10 +13,10 @@ from django.utils.translation import gettext_lazy as _
|
||||
from konova.contexts import BaseContext
|
||||
from konova.forms import SimpleGeomForm
|
||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
||||
from konova.views.base import BaseView
|
||||
from konova.views.base import AbstractBaseView
|
||||
|
||||
|
||||
class BaseReportView(BaseView):
|
||||
class AbstractReportView(AbstractBaseView):
|
||||
_TEMPLATE = None
|
||||
_TAB_TITLE = _("Report {}")
|
||||
_MODEL = None
|
||||
@@ -97,7 +97,7 @@ class BaseReportView(BaseView):
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
# Reports do not need specific permissions to be callable
|
||||
return True
|
||||
|
||||
|
||||
@@ -8,10 +8,10 @@ Created on: 19.08.22
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
|
||||
from konova.utils.message_templates import NEW_RESUBMISSION_CREATED
|
||||
from konova.views.base import BaseModalFormView
|
||||
from konova.views.modal import AbstractModalFormView
|
||||
|
||||
|
||||
class AbstractResubmissionView(LoginRequiredMixin, BaseModalFormView):
|
||||
class AbstractResubmissionView(LoginRequiredMixin, AbstractModalFormView):
|
||||
_MODEL_CLS = None
|
||||
_FORM_CLS = None
|
||||
_REDIRECT_URL = None
|
||||
@@ -20,7 +20,7 @@ class AbstractResubmissionView(LoginRequiredMixin, BaseModalFormView):
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_default_user()
|
||||
|
||||
def _check_for_recorded_instance(self, obj):
|
||||
|
||||
@@ -12,10 +12,11 @@ from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from intervention.forms.modals.share import ShareModalForm
|
||||
from konova.utils.message_templates import DATA_SHARE_SET
|
||||
from konova.views.base import BaseView, BaseModalFormView
|
||||
from konova.views.base import AbstractBaseView
|
||||
from konova.views.modal import AbstractModalFormView
|
||||
|
||||
|
||||
class AbstractShareByTokenView(LoginRequiredMixin, BaseView):
|
||||
class AbstractShareByTokenView(LoginRequiredMixin, AbstractBaseView):
|
||||
_MODEL_CLS = None
|
||||
_REDIRECT_URL = None
|
||||
|
||||
@@ -60,7 +61,7 @@ class AbstractShareByTokenView(LoginRequiredMixin, BaseView):
|
||||
)
|
||||
return redirect("home")
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
# No permissions are needed to get shared access via token
|
||||
return True
|
||||
|
||||
@@ -69,7 +70,7 @@ class AbstractShareByTokenView(LoginRequiredMixin, BaseView):
|
||||
return True
|
||||
|
||||
|
||||
class AbstractShareFormView(LoginRequiredMixin, BaseModalFormView):
|
||||
class AbstractShareFormView(LoginRequiredMixin, AbstractModalFormView):
|
||||
_MODEL_CLS = None
|
||||
_FORM_CLS = ShareModalForm
|
||||
_MSG_SUCCESS = DATA_SHARE_SET
|
||||
@@ -77,5 +78,5 @@ class AbstractShareFormView(LoginRequiredMixin, BaseModalFormView):
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_default_user()
|
||||
|
||||
@@ -12,10 +12,10 @@ from compensation.forms.modals.state import NewCompensationStateModalForm, EditC
|
||||
RemoveCompensationStateModalForm
|
||||
from konova.utils.message_templates import COMPENSATION_STATE_ADDED, COMPENSATION_STATE_EDITED, \
|
||||
COMPENSATION_STATE_REMOVED
|
||||
from konova.views.base import BaseModalFormView
|
||||
from konova.views.modal import AbstractModalFormView
|
||||
|
||||
|
||||
class AbstractCompensationStateView(LoginRequiredMixin, BaseModalFormView):
|
||||
class AbstractCompensationStateView(LoginRequiredMixin, AbstractModalFormView):
|
||||
_MODEL_CLS = None
|
||||
_FORM_CLS = None
|
||||
_REDIRECT_URL = None
|
||||
@@ -23,7 +23,7 @@ class AbstractCompensationStateView(LoginRequiredMixin, BaseModalFormView):
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_default_user()
|
||||
|
||||
def _get_redirect_url(self, *args, **kwargs):
|
||||
|
||||
Binary file not shown.
@@ -4,16 +4,16 @@
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#: compensation/filters/eco_account.py:21
|
||||
#: compensation/forms/modals/compensation_action.py:82
|
||||
#: compensation/forms/modals/deadline.py:52
|
||||
#: compensation/forms/modals/payment.py:24
|
||||
#: compensation/forms/modals/payment.py:35
|
||||
#: compensation/forms/modals/payment.py:52
|
||||
#: compensation/forms/modals/compensation_action.py:84
|
||||
#: compensation/forms/modals/deadline.py:53
|
||||
#: compensation/forms/modals/payment.py:26
|
||||
#: compensation/forms/modals/payment.py:37
|
||||
#: compensation/forms/modals/payment.py:54
|
||||
#: intervention/forms/intervention.py:57 intervention/forms/intervention.py:177
|
||||
#: intervention/forms/intervention.py:190
|
||||
#: intervention/forms/modals/revocation.py:21
|
||||
#: intervention/forms/modals/revocation.py:35
|
||||
#: intervention/forms/modals/revocation.py:48
|
||||
#: intervention/forms/modals/revocation.py:22
|
||||
#: intervention/forms/modals/revocation.py:36
|
||||
#: intervention/forms/modals/revocation.py:49
|
||||
#: konova/filters/mixins/file_number.py:17
|
||||
#: konova/filters/mixins/file_number.py:18
|
||||
#: konova/filters/mixins/geo_reference.py:25
|
||||
@@ -35,7 +35,7 @@
|
||||
#: konova/forms/modals/document_form.py:50
|
||||
#: konova/forms/modals/document_form.py:62
|
||||
#: konova/forms/modals/document_form.py:80
|
||||
#: konova/forms/modals/remove_form.py:23
|
||||
#: konova/forms/modals/remove_form.py:24
|
||||
#: konova/forms/modals/resubmission_form.py:22
|
||||
#: konova/forms/modals/resubmission_form.py:38 konova/forms/remove_form.py:25
|
||||
#: konova/tests/unit/test_forms.py:59 user/forms/modals/api_token.py:17
|
||||
@@ -45,7 +45,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-10-19 13:56+0200\n"
|
||||
"POT-Creation-Date: 2025-11-08 13:03+0100\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"
|
||||
@@ -127,7 +127,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/modals/compensation_action.py:66
|
||||
#: compensation/forms/modals/compensation_action.py:68
|
||||
#: compensation/templates/compensation/detail/eco_account/includes/deductions.html:34
|
||||
#: intervention/templates/intervention/detail/includes/deductions.html:31
|
||||
msgid "Amount"
|
||||
@@ -261,7 +261,7 @@ msgstr ""
|
||||
|
||||
#: analysis/templates/analysis/reports/includes/eco_account/deductions.html:14
|
||||
#: analysis/templates/analysis/reports/includes/eco_account/deductions.html:16
|
||||
#: compensation/forms/modals/state.py:59
|
||||
#: compensation/forms/modals/state.py:55
|
||||
#: 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
|
||||
@@ -296,7 +296,7 @@ msgid "Compensation"
|
||||
msgstr "Kompensation"
|
||||
|
||||
#: analysis/templates/analysis/reports/includes/intervention/compensated_by.html:21
|
||||
#: compensation/forms/modals/payment.py:65
|
||||
#: compensation/forms/modals/payment.py:67
|
||||
msgid "Payment"
|
||||
msgstr "Zahlung"
|
||||
|
||||
@@ -401,15 +401,15 @@ msgstr "Bezeichnung"
|
||||
msgid "An explanatory name"
|
||||
msgstr "Aussagekräftiger Titel"
|
||||
|
||||
#: compensation/forms/compensation.py:49 ema/forms.py:51 ema/forms.py:114
|
||||
#: compensation/forms/compensation.py:49 ema/forms.py:52 ema/forms.py:115
|
||||
#: ema/tests/unit/test_forms.py:31 ema/tests/unit/test_forms.py:85
|
||||
msgid "Compensation XY; Location ABC"
|
||||
msgstr "Kompensation XY; Flur ABC"
|
||||
|
||||
#: compensation/forms/compensation.py:56
|
||||
#: compensation/forms/modals/compensation_action.py:81
|
||||
#: compensation/forms/modals/deadline.py:51
|
||||
#: compensation/forms/modals/payment.py:51
|
||||
#: compensation/forms/modals/compensation_action.py:83
|
||||
#: compensation/forms/modals/deadline.py:52
|
||||
#: compensation/forms/modals/payment.py:53
|
||||
#: compensation/templates/compensation/detail/compensation/includes/actions.html:35
|
||||
#: compensation/templates/compensation/detail/compensation/includes/deadlines.html:39
|
||||
#: compensation/templates/compensation/detail/compensation/includes/documents.html:34
|
||||
@@ -420,7 +420,7 @@ msgstr "Kompensation XY; Flur ABC"
|
||||
#: ema/templates/ema/detail/includes/deadlines.html:39
|
||||
#: ema/templates/ema/detail/includes/documents.html:34
|
||||
#: intervention/forms/intervention.py:203
|
||||
#: intervention/forms/modals/revocation.py:47
|
||||
#: intervention/forms/modals/revocation.py:48
|
||||
#: intervention/templates/intervention/detail/includes/documents.html:39
|
||||
#: intervention/templates/intervention/detail/includes/payments.html:34
|
||||
#: intervention/templates/intervention/detail/includes/revocation.html:38
|
||||
@@ -431,7 +431,7 @@ msgid "Comment"
|
||||
msgstr "Kommentar"
|
||||
|
||||
#: compensation/forms/compensation.py:58
|
||||
#: compensation/forms/modals/compensation_action.py:83
|
||||
#: compensation/forms/modals/compensation_action.py:85
|
||||
#: intervention/forms/intervention.py:205
|
||||
#: konova/forms/modals/resubmission_form.py:39
|
||||
msgid "Additional comment"
|
||||
@@ -448,19 +448,18 @@ msgid "Select the intervention for which this compensation compensates"
|
||||
msgstr "Wählen Sie den Eingriff, für den diese Kompensation bestimmt ist"
|
||||
|
||||
#: compensation/forms/compensation.py:114
|
||||
#: compensation/views/compensation/compensation.py:161
|
||||
msgid "New compensation"
|
||||
msgstr "Neue Kompensation"
|
||||
|
||||
#: compensation/forms/compensation.py:179
|
||||
#: compensation/forms/compensation.py:178
|
||||
msgid ""
|
||||
"This intervention is currently recorded. You cannot add further "
|
||||
"compensations as long as it is recorded."
|
||||
msgstr ""
|
||||
"Dieser Eingriff ist derzeit verzeichnet. "
|
||||
"Sie können keine weiteren Kompensationen hinzufügen, so lange er verzeichnet ist."
|
||||
"Dieser Eingriff ist derzeit verzeichnet. Sie können keine weiteren "
|
||||
"Kompensationen hinzufügen, so lange er verzeichnet ist."
|
||||
|
||||
#: compensation/forms/compensation.py:202
|
||||
#: compensation/forms/compensation.py:201
|
||||
msgid "Edit compensation"
|
||||
msgstr "Bearbeite Kompensation"
|
||||
|
||||
@@ -483,7 +482,8 @@ msgid "When did the parties agree on this?"
|
||||
msgstr "Wann wurde dieses Ökokonto offiziell vereinbart?"
|
||||
|
||||
#: compensation/forms/eco_account.py:72
|
||||
#: compensation/views/eco_account/eco_account.py:93
|
||||
#: compensation/views/eco_account/eco_account.py:49
|
||||
#: compensation/views/eco_account/eco_account.py:118
|
||||
msgid "New Eco-Account"
|
||||
msgstr "Neues Ökokonto"
|
||||
|
||||
@@ -580,11 +580,11 @@ msgid ""
|
||||
"production?"
|
||||
msgstr "Optional: Handelt es sich um eine produktionsintegrierte Kompensation?"
|
||||
|
||||
#: compensation/forms/modals/compensation_action.py:29
|
||||
#: compensation/forms/modals/compensation_action.py:31
|
||||
msgid "Action Type"
|
||||
msgstr "Maßnahmentyp"
|
||||
|
||||
#: compensation/forms/modals/compensation_action.py:32
|
||||
#: compensation/forms/modals/compensation_action.py:34
|
||||
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 "
|
||||
@@ -594,162 +594,158 @@ msgstr ""
|
||||
"hier gewählten Einträge sollen mit der weiter unten angegebenen Einheit und "
|
||||
"Menge umgesetzt werden. "
|
||||
|
||||
#: compensation/forms/modals/compensation_action.py:37
|
||||
#: compensation/forms/modals/compensation_action.py:49
|
||||
#: compensation/forms/modals/compensation_action.py:39
|
||||
#: compensation/forms/modals/compensation_action.py:51
|
||||
msgid "Action Type detail"
|
||||
msgstr "Zusatzmerkmal"
|
||||
|
||||
#: compensation/forms/modals/compensation_action.py:40
|
||||
#: compensation/forms/modals/compensation_action.py:42
|
||||
msgid "Select the action type detail"
|
||||
msgstr "Zusatzmerkmal wählen"
|
||||
|
||||
#: compensation/forms/modals/compensation_action.py:54
|
||||
#: compensation/forms/modals/compensation_action.py:56
|
||||
msgid "Unit"
|
||||
msgstr "Einheit"
|
||||
|
||||
#: compensation/forms/modals/compensation_action.py:57
|
||||
#: compensation/forms/modals/compensation_action.py:59
|
||||
msgid "Select the unit"
|
||||
msgstr "Einheit wählen"
|
||||
|
||||
#: compensation/forms/modals/compensation_action.py:69
|
||||
#: compensation/forms/modals/compensation_action.py:71
|
||||
msgid "Insert the amount"
|
||||
msgstr "Menge eingeben"
|
||||
|
||||
#: compensation/forms/modals/compensation_action.py:94
|
||||
#: compensation/forms/modals/compensation_action.py:96
|
||||
#: compensation/tests/compensation/unit/test_forms.py:42
|
||||
msgid "New action"
|
||||
msgstr "Neue Maßnahme"
|
||||
|
||||
#: compensation/forms/modals/compensation_action.py:95
|
||||
#: compensation/forms/modals/compensation_action.py:97
|
||||
#: compensation/tests/compensation/unit/test_forms.py:43
|
||||
msgid "Insert data for the new action"
|
||||
msgstr "Geben Sie die Daten der neuen Maßnahme ein"
|
||||
|
||||
#: compensation/forms/modals/compensation_action.py:119
|
||||
#: compensation/forms/modals/compensation_action.py:122
|
||||
#: compensation/templates/compensation/detail/compensation/includes/actions.html:68
|
||||
#: compensation/templates/compensation/detail/eco_account/includes/actions.html:67
|
||||
#: compensation/tests/compensation/unit/test_forms.py:84
|
||||
#: compensation/tests/compensation/unit/test_forms.py:88
|
||||
#: ema/templates/ema/detail/includes/actions.html:65
|
||||
msgid "Edit action"
|
||||
msgstr "Maßnahme bearbeiten"
|
||||
|
||||
#: compensation/forms/modals/deadline.py:22
|
||||
#: compensation/forms/modals/deadline.py:23
|
||||
msgid "Deadline Type"
|
||||
msgstr "Fristart"
|
||||
|
||||
#: compensation/forms/modals/deadline.py:25
|
||||
#: compensation/forms/modals/deadline.py:26
|
||||
msgid "Select the deadline type"
|
||||
msgstr "Fristart wählen"
|
||||
|
||||
#: compensation/forms/modals/deadline.py:34
|
||||
#: compensation/forms/modals/deadline.py:35
|
||||
#: compensation/templates/compensation/detail/compensation/includes/deadlines.html:36
|
||||
#: compensation/templates/compensation/detail/eco_account/includes/deadlines.html:36
|
||||
#: ema/templates/ema/detail/includes/deadlines.html:36
|
||||
#: intervention/forms/modals/revocation.py:20
|
||||
#: intervention/forms/modals/revocation.py:21
|
||||
#: konova/forms/modals/resubmission_form.py:23
|
||||
msgid "Date"
|
||||
msgstr "Datum"
|
||||
|
||||
#: compensation/forms/modals/deadline.py:37
|
||||
#: compensation/forms/modals/deadline.py:38
|
||||
msgid "Select date"
|
||||
msgstr "Datum wählen"
|
||||
|
||||
#: compensation/forms/modals/deadline.py:53
|
||||
#: compensation/forms/modals/payment.py:53
|
||||
#: intervention/forms/modals/revocation.py:49
|
||||
#: compensation/forms/modals/deadline.py:54
|
||||
#: compensation/forms/modals/payment.py:55
|
||||
#: intervention/forms/modals/revocation.py:50
|
||||
#: konova/forms/modals/document_form.py:63
|
||||
msgid "Additional comment, maximum {} letters"
|
||||
msgstr "Zusätzlicher Kommentar, maximal {} Zeichen"
|
||||
|
||||
#: compensation/forms/modals/deadline.py:65
|
||||
#: compensation/forms/modals/deadline.py:66
|
||||
#: konova/tests/unit/test_deadline.py:29
|
||||
msgid "New deadline"
|
||||
msgstr "Neue Frist"
|
||||
|
||||
#: compensation/forms/modals/deadline.py:66
|
||||
#: compensation/forms/modals/deadline.py:67
|
||||
#: konova/tests/unit/test_deadline.py:30
|
||||
msgid "Insert data for the new deadline"
|
||||
msgstr "Geben Sie die Daten der neuen Frist ein"
|
||||
|
||||
#: compensation/forms/modals/deadline.py:78
|
||||
#: compensation/forms/modals/deadline.py:79
|
||||
#: konova/tests/unit/test_deadline.py:57
|
||||
msgid "Please explain this 'other' type of deadline."
|
||||
msgstr "Bitte erklären Sie um welchen 'sonstigen' Termin es sich handelt."
|
||||
|
||||
#: compensation/forms/modals/deadline.py:95
|
||||
#: compensation/forms/modals/deadline.py:97
|
||||
#: compensation/templates/compensation/detail/compensation/includes/deadlines.html:64
|
||||
#: compensation/templates/compensation/detail/eco_account/includes/deadlines.html:62
|
||||
#: ema/templates/ema/detail/includes/deadlines.html:62
|
||||
msgid "Edit deadline"
|
||||
msgstr "Frist/Termin bearbeiten"
|
||||
|
||||
#: compensation/forms/modals/payment.py:25
|
||||
#: compensation/forms/modals/payment.py:27
|
||||
msgid "in Euro"
|
||||
msgstr "in Euro"
|
||||
|
||||
#: compensation/forms/modals/payment.py:34
|
||||
#: compensation/forms/modals/payment.py:36
|
||||
#: intervention/templates/intervention/detail/includes/payments.html:31
|
||||
msgid "Due on"
|
||||
msgstr "Fällig am"
|
||||
|
||||
#: compensation/forms/modals/payment.py:38
|
||||
#: compensation/forms/modals/payment.py:40
|
||||
msgid "Due on which date"
|
||||
msgstr "Zahlung wird an diesem Datum erwartet"
|
||||
|
||||
#: compensation/forms/modals/payment.py:66
|
||||
#: compensation/forms/modals/payment.py:68
|
||||
msgid "Add a payment for intervention '{}'"
|
||||
msgstr "Neue Ersatzzahlung zu Eingriff '{}' hinzufügen"
|
||||
|
||||
#: compensation/forms/modals/payment.py:89
|
||||
#: compensation/forms/modals/payment.py:91
|
||||
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/modals/payment.py:108
|
||||
#: compensation/forms/modals/payment.py:111
|
||||
#: intervention/templates/intervention/detail/includes/payments.html:67
|
||||
msgid "Edit payment"
|
||||
msgstr "Zahlung bearbeiten"
|
||||
|
||||
#: compensation/forms/modals/state.py:33
|
||||
#: compensation/forms/modals/state.py:29
|
||||
msgid "Biotope Type"
|
||||
msgstr "Biotoptyp"
|
||||
|
||||
#: compensation/forms/modals/state.py:36
|
||||
#: compensation/forms/modals/state.py:32
|
||||
msgid "Select the biotope type"
|
||||
msgstr "Biotoptyp wählen"
|
||||
|
||||
#: compensation/forms/modals/state.py:40 compensation/forms/modals/state.py:52
|
||||
#: compensation/forms/modals/state.py:36 compensation/forms/modals/state.py:48
|
||||
msgid "Biotope additional type"
|
||||
msgstr "Zusatzbezeichnung"
|
||||
|
||||
#: compensation/forms/modals/state.py:43
|
||||
#: compensation/forms/modals/state.py:39
|
||||
msgid "Select an additional biotope type"
|
||||
msgstr "Zusatzbezeichnung wählen"
|
||||
|
||||
#: compensation/forms/modals/state.py:62
|
||||
#: compensation/forms/modals/state.py:58
|
||||
#: intervention/forms/modals/deduction.py:49
|
||||
msgid "in m²"
|
||||
msgstr ""
|
||||
|
||||
#: compensation/forms/modals/state.py:73
|
||||
#: compensation/tests/compensation/unit/test_forms.py:175
|
||||
#: compensation/forms/modals/state.py:71
|
||||
#: compensation/tests/compensation/unit/test_forms.py:179
|
||||
msgid "New state"
|
||||
msgstr "Neuer Zustand"
|
||||
|
||||
#: compensation/forms/modals/state.py:74
|
||||
#: compensation/tests/compensation/unit/test_forms.py:176
|
||||
#: compensation/forms/modals/state.py:72
|
||||
#: compensation/tests/compensation/unit/test_forms.py:180
|
||||
msgid "Insert data for the new state"
|
||||
msgstr "Geben Sie die Daten des neuen Zustandes ein"
|
||||
|
||||
#: compensation/forms/modals/state.py:91 konova/forms/modals/base_form.py:32
|
||||
msgid "Object removed"
|
||||
msgstr "Objekt entfernt"
|
||||
|
||||
#: compensation/forms/modals/state.py:146
|
||||
#: compensation/forms/modals/state.py:99
|
||||
#: 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
|
||||
#: compensation/templates/compensation/detail/eco_account/includes/states-before.html:62
|
||||
#: compensation/tests/compensation/unit/test_forms.py:236
|
||||
#: compensation/tests/compensation/unit/test_forms.py:260
|
||||
#: ema/templates/ema/detail/includes/states-after.html:60
|
||||
#: ema/templates/ema/detail/includes/states-before.html:60
|
||||
msgid "Edit state"
|
||||
@@ -945,7 +941,7 @@ msgstr "Öffentlicher Bericht"
|
||||
#: ema/templates/ema/detail/includes/controls.html:15
|
||||
#: intervention/templates/intervention/detail/includes/controls.html:15
|
||||
#: konova/forms/modals/resubmission_form.py:51
|
||||
#: konova/tests/unit/test_forms.py:302 konova/tests/unit/test_forms.py:316
|
||||
#: konova/tests/unit/test_forms.py:301 konova/tests/unit/test_forms.py:315
|
||||
#: templates/email/resubmission/resubmission.html:4
|
||||
msgid "Resubmission"
|
||||
msgstr "Wiedervorlage"
|
||||
@@ -1023,7 +1019,7 @@ msgstr "Erstellt"
|
||||
#: compensation/templates/compensation/detail/eco_account/includes/documents.html:61
|
||||
#: ema/templates/ema/detail/includes/documents.html:61
|
||||
#: intervention/templates/intervention/detail/includes/documents.html:70
|
||||
#: konova/forms/modals/document_form.py:141 konova/tests/unit/test_forms.py:118
|
||||
#: konova/forms/modals/document_form.py:143 konova/tests/unit/test_forms.py:118
|
||||
msgid "Edit document"
|
||||
msgstr "Dokument bearbeiten"
|
||||
|
||||
@@ -1236,7 +1232,7 @@ msgid "Recorded on"
|
||||
msgstr "Verzeichnet am"
|
||||
|
||||
#: compensation/templates/compensation/detail/eco_account/includes/deductions.html:65
|
||||
#: intervention/forms/modals/deduction.py:177
|
||||
#: intervention/forms/modals/deduction.py:178
|
||||
#: intervention/templates/intervention/detail/includes/deductions.html:60
|
||||
msgid "Edit Deduction"
|
||||
msgstr "Abbuchung bearbeiten"
|
||||
@@ -1296,49 +1292,37 @@ msgstr ""
|
||||
msgid "Responsible data"
|
||||
msgstr "Daten zu den verantwortlichen Stellen"
|
||||
|
||||
#: compensation/views/compensation/compensation.py:35
|
||||
#: compensation/views/compensation/compensation.py:32
|
||||
msgid "Compensations - Overview"
|
||||
msgstr "Kompensationen - Übersicht"
|
||||
|
||||
#: compensation/views/compensation/compensation.py:52
|
||||
#, fuzzy
|
||||
#| msgid "New compensation"
|
||||
#: compensation/views/compensation/compensation.py:49
|
||||
msgid "New Compensation"
|
||||
msgstr "Neue Kompensation"
|
||||
|
||||
#: compensation/views/compensation/compensation.py:208
|
||||
#: konova/utils/message_templates.py:40
|
||||
msgid "Compensation {} edited"
|
||||
msgstr "Kompensation {} bearbeitet"
|
||||
|
||||
#: compensation/views/compensation/compensation.py:231
|
||||
#: compensation/views/eco_account/eco_account.py:159 ema/views/ema.py:59
|
||||
#: intervention/views/intervention.py:59 intervention/views/intervention.py:179
|
||||
#: konova/views/base.py:239
|
||||
msgid "Edit {}"
|
||||
msgstr "Bearbeite {}"
|
||||
|
||||
#: compensation/views/eco_account/eco_account.py:32
|
||||
#: compensation/views/eco_account/eco_account.py:34
|
||||
msgid "Eco-account - Overview"
|
||||
msgstr "Ökokonten - Übersicht"
|
||||
|
||||
#: compensation/views/eco_account/eco_account.py:70
|
||||
#: compensation/views/eco_account/eco_account.py:95
|
||||
msgid "Eco-Account {} added"
|
||||
msgstr "Ökokonto {} hinzugefügt"
|
||||
|
||||
#: compensation/views/eco_account/eco_account.py:136
|
||||
#: compensation/views/eco_account/eco_account.py:161
|
||||
msgid "Eco-Account {} edited"
|
||||
msgstr "Ökokonto {} bearbeitet"
|
||||
|
||||
#: compensation/views/eco_account/eco_account.py:260
|
||||
msgid "Eco-account removed"
|
||||
msgstr "Ökokonto entfernt"
|
||||
#: compensation/views/eco_account/eco_account.py:184 ema/views/ema.py:51
|
||||
#: intervention/views/intervention.py:58 intervention/views/intervention.py:178
|
||||
#: konova/views/base.py:524
|
||||
msgid "Edit {}"
|
||||
msgstr "Bearbeite {}"
|
||||
|
||||
#: ema/forms.py:42 ema/tests/unit/test_forms.py:27 ema/views/ema.py:42
|
||||
#: ema/forms.py:43 ema/tests/unit/test_forms.py:27 ema/views/ema.py:38
|
||||
msgid "New EMA"
|
||||
msgstr "Neue EMA hinzufügen"
|
||||
|
||||
#: ema/forms.py:108 ema/tests/unit/test_forms.py:81
|
||||
#: ema/forms.py:109 ema/tests/unit/test_forms.py:81
|
||||
msgid "Edit EMA"
|
||||
msgstr "Bearbeite EMA"
|
||||
|
||||
@@ -1362,14 +1346,10 @@ msgstr ""
|
||||
msgid "Payment funded compensation"
|
||||
msgstr "Ersatzzahlungsmaßnahme"
|
||||
|
||||
#: ema/views/ema.py:26
|
||||
#: ema/views/ema.py:22
|
||||
msgid "EMAs - Overview"
|
||||
msgstr "EMAs - Übersicht"
|
||||
|
||||
#: ema/views/ema.py:138
|
||||
msgid "EMA removed"
|
||||
msgstr "EMA entfernt"
|
||||
|
||||
#: intervention/forms/intervention.py:49
|
||||
msgid "Construction XY; Location ABC"
|
||||
msgstr "Bauvorhaben XY; Flur ABC"
|
||||
@@ -1430,7 +1410,7 @@ msgstr "Datum Bestandskraft bzw. Rechtskraft"
|
||||
|
||||
#: intervention/forms/intervention.py:216
|
||||
#: intervention/tests/unit/test_forms.py:36
|
||||
#: intervention/views/intervention.py:51
|
||||
#: intervention/views/intervention.py:50
|
||||
msgid "New intervention"
|
||||
msgstr "Neuer Eingriff"
|
||||
|
||||
@@ -1452,7 +1432,7 @@ msgid "Run check"
|
||||
msgstr "Prüfung vornehmen"
|
||||
|
||||
#: intervention/forms/modals/check.py:36 konova/forms/modals/record_form.py:30
|
||||
#: konova/tests/unit/test_forms.py:155
|
||||
#: konova/tests/unit/test_forms.py:154
|
||||
msgid "The necessary control steps have been performed:"
|
||||
msgstr "Die notwendigen Kontrollschritte wurden durchgeführt:"
|
||||
|
||||
@@ -1496,26 +1476,26 @@ msgstr ""
|
||||
"Das Ökokonto {} hat für eine Abbuchung von {} m² nicht ausreichend "
|
||||
"Restfläche. Es stehen noch {} m² zur Verfügung."
|
||||
|
||||
#: intervention/forms/modals/revocation.py:22
|
||||
#: intervention/forms/modals/revocation.py:23
|
||||
msgid "Date of revocation"
|
||||
msgstr "Datum des Widerspruchs"
|
||||
|
||||
#: intervention/forms/modals/revocation.py:34
|
||||
#: intervention/forms/modals/revocation.py:35
|
||||
#: intervention/templates/intervention/detail/includes/revocation.html:35
|
||||
msgid "Document"
|
||||
msgstr "Dokument"
|
||||
|
||||
#: intervention/forms/modals/revocation.py:37
|
||||
#: intervention/forms/modals/revocation.py:38
|
||||
msgid "Must be smaller than 15 Mb"
|
||||
msgstr "Muss kleiner als 15 Mb sein"
|
||||
|
||||
#: intervention/forms/modals/revocation.py:62
|
||||
#: intervention/forms/modals/revocation.py:63
|
||||
#: intervention/templates/intervention/detail/includes/revocation.html:18
|
||||
#: intervention/tests/unit/test_forms.py:234
|
||||
msgid "Add revocation"
|
||||
msgstr "Widerspruch hinzufügen"
|
||||
|
||||
#: intervention/forms/modals/revocation.py:80
|
||||
#: intervention/forms/modals/revocation.py:82
|
||||
#: intervention/templates/intervention/detail/includes/revocation.html:69
|
||||
msgid "Edit revocation"
|
||||
msgstr "Widerspruch bearbeiten"
|
||||
@@ -1600,7 +1580,7 @@ msgid "Amount"
|
||||
msgstr "Betrag"
|
||||
|
||||
#: intervention/templates/intervention/detail/includes/payments.html:61
|
||||
#: konova/utils/message_templates.py:25
|
||||
#: konova/utils/message_templates.py:38
|
||||
msgid "This data is not shared with you"
|
||||
msgstr "Diese Daten sind für Sie nicht freigegeben"
|
||||
|
||||
@@ -1662,22 +1642,18 @@ msgstr ""
|
||||
"Kein Ausgleich jeglicher Art gefunden (Kompensation, Ersatzzahlung, "
|
||||
"Abbuchung)"
|
||||
|
||||
#: intervention/views/check.py:36
|
||||
#: intervention/views/check.py:19
|
||||
msgid "Check performed"
|
||||
msgstr "Prüfung durchgeführt"
|
||||
|
||||
#: intervention/views/intervention.py:33
|
||||
#: intervention/views/intervention.py:32
|
||||
msgid "Interventions - Overview"
|
||||
msgstr "Eingriffe - Übersicht"
|
||||
|
||||
#: intervention/views/intervention.py:154
|
||||
#: intervention/views/intervention.py:153
|
||||
msgid "Intervention {} edited"
|
||||
msgstr "Eingriff {} bearbeitet"
|
||||
|
||||
#: intervention/views/intervention.py:204
|
||||
msgid "{} removed"
|
||||
msgstr "{} entfernt"
|
||||
|
||||
#: konova/decorators.py:32
|
||||
msgid "You need to be staff to perform this action!"
|
||||
msgstr "Hierfür müssen Sie Mitarbeiter sein!"
|
||||
@@ -1794,11 +1770,11 @@ msgid ""
|
||||
"history"
|
||||
msgstr "Sucht nach Einträgen, an denen diese Person gearbeitet hat"
|
||||
|
||||
#: konova/forms/base_form.py:23 templates/form/collapsable/form.html:62
|
||||
#: konova/forms/base_form.py:19 templates/form/collapsable/form.html:62
|
||||
msgid "Save"
|
||||
msgstr "Speichern"
|
||||
|
||||
#: konova/forms/base_form.py:74
|
||||
#: konova/forms/base_form.py:69
|
||||
msgid "Not editable"
|
||||
msgstr "Nicht editierbar"
|
||||
|
||||
@@ -1812,6 +1788,10 @@ msgid "Only surfaces allowed. Points or lines must be buffered."
|
||||
msgstr ""
|
||||
"Nur Flächen erlaubt. Punkte oder Linien müssen zu Flächen gepuffert werden."
|
||||
|
||||
#: konova/forms/modals/base_form.py:32
|
||||
msgid "Object removed"
|
||||
msgstr "Objekt entfernt"
|
||||
|
||||
#: konova/forms/modals/document_form.py:37
|
||||
msgid "When has this file been created? Important for photos."
|
||||
msgstr "Wann wurde diese Datei erstellt oder das Foto aufgenommen?"
|
||||
@@ -1832,35 +1812,35 @@ msgstr "Dokument hinzugefügt"
|
||||
msgid "Confirm record"
|
||||
msgstr "Verzeichnen bestätigen"
|
||||
|
||||
#: konova/forms/modals/record_form.py:29 konova/tests/unit/test_forms.py:153
|
||||
#: konova/forms/modals/record_form.py:29 konova/tests/unit/test_forms.py:152
|
||||
msgid "Record data"
|
||||
msgstr "Daten verzeichnen"
|
||||
|
||||
#: konova/forms/modals/record_form.py:36 konova/tests/unit/test_forms.py:168
|
||||
#: konova/forms/modals/record_form.py:36 konova/tests/unit/test_forms.py:167
|
||||
msgid "Confirm unrecord"
|
||||
msgstr "Entzeichnen bestätigen"
|
||||
|
||||
#: konova/forms/modals/record_form.py:37 konova/tests/unit/test_forms.py:167
|
||||
#: konova/forms/modals/record_form.py:37 konova/tests/unit/test_forms.py:166
|
||||
msgid "Unrecord data"
|
||||
msgstr "Daten entzeichnen"
|
||||
|
||||
#: konova/forms/modals/record_form.py:38 konova/tests/unit/test_forms.py:170
|
||||
#: konova/forms/modals/record_form.py:38 konova/tests/unit/test_forms.py:169
|
||||
msgid "I, {} {}, confirm that this data must be unrecorded."
|
||||
msgstr ""
|
||||
"Ich, {} {}, bestätige, dass diese Daten wieder entzeichnet werden müssen."
|
||||
|
||||
#: konova/forms/modals/remove_form.py:22 konova/forms/remove_form.py:24
|
||||
#: konova/forms/modals/remove_form.py:23 konova/forms/remove_form.py:24
|
||||
#: user/forms/modals/api_token.py:16
|
||||
msgid "Confirm"
|
||||
msgstr "Bestätige"
|
||||
|
||||
#: konova/forms/modals/remove_form.py:32 konova/forms/remove_form.py:36
|
||||
#: konova/tests/unit/test_forms.py:209 konova/tests/unit/test_forms.py:261
|
||||
#: konova/forms/modals/remove_form.py:33 konova/forms/remove_form.py:36
|
||||
#: konova/tests/unit/test_forms.py:208 konova/tests/unit/test_forms.py:260
|
||||
msgid "Remove"
|
||||
msgstr "Löschen"
|
||||
|
||||
#: konova/forms/modals/remove_form.py:33 konova/tests/unit/test_forms.py:210
|
||||
#: konova/tests/unit/test_forms.py:262
|
||||
#: konova/forms/modals/remove_form.py:34 konova/tests/unit/test_forms.py:209
|
||||
#: konova/tests/unit/test_forms.py:261
|
||||
msgid "Are you sure?"
|
||||
msgstr "Sind Sie sicher?"
|
||||
|
||||
@@ -1869,7 +1849,7 @@ msgid "When do you want to be reminded?"
|
||||
msgstr "Wann wollen Sie erinnert werden?"
|
||||
|
||||
#: konova/forms/modals/resubmission_form.py:52
|
||||
#: konova/tests/unit/test_forms.py:303 konova/tests/unit/test_forms.py:317
|
||||
#: konova/tests/unit/test_forms.py:302 konova/tests/unit/test_forms.py:316
|
||||
msgid "Set your resubmission for this entry."
|
||||
msgstr "Setzen Sie eine Wiedervorlage für diesen Eintrag."
|
||||
|
||||
@@ -2094,14 +2074,42 @@ msgstr "Hierfür müssen Sie einer anderen Nutzergruppe angehören!"
|
||||
msgid "Status of Checked reset"
|
||||
msgstr "Status 'Geprüft' wurde zurückgesetzt"
|
||||
|
||||
#: konova/utils/message_templates.py:22
|
||||
#: konova/utils/message_templates.py:24
|
||||
msgid "New team added"
|
||||
msgstr "Neues Team hinzugefügt"
|
||||
|
||||
#: konova/utils/message_templates.py:25
|
||||
msgid "Team edited"
|
||||
msgstr "Team bearbeitet"
|
||||
|
||||
#: konova/utils/message_templates.py:26
|
||||
msgid "Team removed"
|
||||
msgstr "Team gelöscht"
|
||||
|
||||
#: konova/utils/message_templates.py:27
|
||||
msgid "Left Team"
|
||||
msgstr "Team verlassen"
|
||||
|
||||
#: konova/utils/message_templates.py:30
|
||||
msgid "{} removed"
|
||||
msgstr "{} entfernt"
|
||||
|
||||
#: konova/utils/message_templates.py:33
|
||||
msgid ""
|
||||
"Entry is recorded. To edit data, the entry first needs to be unrecorded."
|
||||
msgstr ""
|
||||
"Eintrag ist verzeichnet. Um Daten zu bearbeiten, muss der Eintrag erst "
|
||||
"entzeichnet werden."
|
||||
|
||||
#: konova/utils/message_templates.py:26
|
||||
#: konova/utils/message_templates.py:34
|
||||
msgid "{} recorded"
|
||||
msgstr "{} verzeichnet"
|
||||
|
||||
#: konova/utils/message_templates.py:35
|
||||
msgid "{} unrecorded"
|
||||
msgstr "{} entzeichnet"
|
||||
|
||||
#: konova/utils/message_templates.py:39
|
||||
msgid ""
|
||||
"Remember: This data has not been shared with you, yet. This means you can "
|
||||
"only read but can not edit or perform any actions like running a check or "
|
||||
@@ -2111,11 +2119,11 @@ msgstr ""
|
||||
"bedeutet, dass Sie nur lesenden Zugriff hierauf haben und weder bearbeiten, "
|
||||
"noch Prüfungen durchführen oder verzeichnen können."
|
||||
|
||||
#: konova/utils/message_templates.py:27
|
||||
#: konova/utils/message_templates.py:40
|
||||
msgid "Share settings updated"
|
||||
msgstr "Freigabe Einstellungen aktualisiert"
|
||||
|
||||
#: konova/utils/message_templates.py:28
|
||||
#: konova/utils/message_templates.py:41
|
||||
msgid ""
|
||||
"Do not forget to share your entry! Currently you are the only one having "
|
||||
"shared access."
|
||||
@@ -2123,15 +2131,15 @@ msgstr ""
|
||||
"Denken Sie daran Ihren Eintrag freizugeben! Aktuell haben nur Sie eine "
|
||||
"Freigabe hierauf."
|
||||
|
||||
#: konova/utils/message_templates.py:31
|
||||
#: konova/utils/message_templates.py:44
|
||||
msgid "Unsupported file type"
|
||||
msgstr "Dateiformat nicht unterstützt"
|
||||
|
||||
#: konova/utils/message_templates.py:32
|
||||
#: konova/utils/message_templates.py:45
|
||||
msgid "File too large"
|
||||
msgstr "Datei zu groß"
|
||||
|
||||
#: konova/utils/message_templates.py:35
|
||||
#: konova/utils/message_templates.py:48
|
||||
msgid ""
|
||||
"Action canceled. Eco account is recorded or deductions exist. Only "
|
||||
"conservation office member can perform this action."
|
||||
@@ -2139,119 +2147,123 @@ msgstr ""
|
||||
"Aktion abgebrochen. Ökokonto ist bereits verzeichnet oder Abbuchungen liegen "
|
||||
"vor. Nur Eintragungsstellennutzer können diese Aktion jetzt durchführen."
|
||||
|
||||
#: konova/utils/message_templates.py:38
|
||||
#: konova/utils/message_templates.py:51
|
||||
msgid "Compensation {} added"
|
||||
msgstr "Kompensation {} hinzugefügt"
|
||||
|
||||
#: konova/utils/message_templates.py:39
|
||||
#: konova/utils/message_templates.py:52
|
||||
msgid "Compensation {} removed"
|
||||
msgstr "Kompensation {} entfernt"
|
||||
|
||||
#: konova/utils/message_templates.py:41
|
||||
#: konova/utils/message_templates.py:53
|
||||
msgid "Compensation {} edited"
|
||||
msgstr "Kompensation {} bearbeitet"
|
||||
|
||||
#: konova/utils/message_templates.py:54
|
||||
msgid "Added compensation action"
|
||||
msgstr "Maßnahme hinzugefügt"
|
||||
|
||||
#: konova/utils/message_templates.py:42
|
||||
#: konova/utils/message_templates.py:55
|
||||
msgid "Added compensation state"
|
||||
msgstr "Zustand hinzugefügt"
|
||||
|
||||
#: konova/utils/message_templates.py:45
|
||||
#: konova/utils/message_templates.py:58
|
||||
msgid "State removed"
|
||||
msgstr "Zustand gelöscht"
|
||||
|
||||
#: konova/utils/message_templates.py:46
|
||||
#: konova/utils/message_templates.py:59
|
||||
msgid "State edited"
|
||||
msgstr "Zustand bearbeitet"
|
||||
|
||||
#: konova/utils/message_templates.py:47
|
||||
#: konova/utils/message_templates.py:60
|
||||
msgid "State added"
|
||||
msgstr "Zustand hinzugefügt"
|
||||
|
||||
#: konova/utils/message_templates.py:50
|
||||
#: konova/utils/message_templates.py:63
|
||||
msgid "Action added"
|
||||
msgstr "Maßnahme hinzugefügt"
|
||||
|
||||
#: konova/utils/message_templates.py:51
|
||||
#: konova/utils/message_templates.py:64
|
||||
msgid "Action edited"
|
||||
msgstr "Maßnahme bearbeitet"
|
||||
|
||||
#: konova/utils/message_templates.py:52
|
||||
#: konova/utils/message_templates.py:65
|
||||
msgid "Action removed"
|
||||
msgstr "Maßnahme entfernt"
|
||||
|
||||
#: konova/utils/message_templates.py:55
|
||||
#: konova/utils/message_templates.py:68
|
||||
msgid "Deduction added"
|
||||
msgstr "Abbuchung hinzugefügt"
|
||||
|
||||
#: konova/utils/message_templates.py:56
|
||||
#: konova/utils/message_templates.py:69
|
||||
msgid "Deduction edited"
|
||||
msgstr "Abbuchung bearbeitet"
|
||||
|
||||
#: konova/utils/message_templates.py:57
|
||||
#: konova/utils/message_templates.py:70
|
||||
msgid "Deduction removed"
|
||||
msgstr "Abbuchung entfernt"
|
||||
|
||||
#: konova/utils/message_templates.py:58
|
||||
#: konova/utils/message_templates.py:71
|
||||
msgid "Unknown deduction"
|
||||
msgstr "Unbekannte Abbuchung"
|
||||
|
||||
#: konova/utils/message_templates.py:61
|
||||
#: konova/utils/message_templates.py:74
|
||||
msgid "Deadline added"
|
||||
msgstr "Frist/Termin hinzugefügt"
|
||||
|
||||
#: konova/utils/message_templates.py:62
|
||||
#: konova/utils/message_templates.py:75
|
||||
msgid "Deadline edited"
|
||||
msgstr "Frist/Termin bearbeitet"
|
||||
|
||||
#: konova/utils/message_templates.py:63
|
||||
#: konova/utils/message_templates.py:76
|
||||
msgid "Deadline removed"
|
||||
msgstr "Frist/Termin gelöscht"
|
||||
|
||||
#: konova/utils/message_templates.py:66
|
||||
#: konova/utils/message_templates.py:79
|
||||
msgid "Payment added"
|
||||
msgstr "Zahlung hinzugefügt"
|
||||
|
||||
#: konova/utils/message_templates.py:67
|
||||
#: konova/utils/message_templates.py:80
|
||||
msgid "Payment edited"
|
||||
msgstr "Zahlung bearbeitet"
|
||||
|
||||
#: konova/utils/message_templates.py:68
|
||||
#: konova/utils/message_templates.py:81
|
||||
msgid "Payment removed"
|
||||
msgstr "Zahlung gelöscht"
|
||||
|
||||
#: konova/utils/message_templates.py:71
|
||||
#: konova/utils/message_templates.py:84
|
||||
msgid "Revocation added"
|
||||
msgstr "Widerspruch hinzugefügt"
|
||||
|
||||
#: konova/utils/message_templates.py:72
|
||||
#: konova/utils/message_templates.py:85
|
||||
msgid "Revocation edited"
|
||||
msgstr "Widerspruch bearbeitet"
|
||||
|
||||
#: konova/utils/message_templates.py:73
|
||||
#: konova/utils/message_templates.py:86
|
||||
msgid "Revocation removed"
|
||||
msgstr "Widerspruch entfernt"
|
||||
|
||||
#: konova/utils/message_templates.py:76
|
||||
#: konova/utils/message_templates.py:89
|
||||
msgid "Document '{}' deleted"
|
||||
msgstr "Dokument '{}' gelöscht"
|
||||
|
||||
#: konova/utils/message_templates.py:77
|
||||
#: konova/utils/message_templates.py:90
|
||||
msgid "Document added"
|
||||
msgstr "Dokument hinzugefügt"
|
||||
|
||||
#: konova/utils/message_templates.py:78
|
||||
#: konova/utils/message_templates.py:91
|
||||
msgid "Document edited"
|
||||
msgstr "Dokument bearbeitet"
|
||||
|
||||
#: konova/utils/message_templates.py:81
|
||||
#: konova/utils/message_templates.py:94
|
||||
msgid "Edited general data"
|
||||
msgstr "Allgemeine Daten bearbeitet"
|
||||
|
||||
#: konova/utils/message_templates.py:84
|
||||
#: konova/utils/message_templates.py:97
|
||||
msgid "Geometry conflict detected with {}"
|
||||
msgstr "Geometriekonflikt mit folgenden Einträgen erkannt: {}"
|
||||
|
||||
#: konova/utils/message_templates.py:85
|
||||
#: konova/utils/message_templates.py:98
|
||||
msgid ""
|
||||
"The geometry contained more than {} vertices. It had to be simplified to "
|
||||
"match the allowed limit of {} vertices."
|
||||
@@ -2259,7 +2271,7 @@ msgstr ""
|
||||
"Die Geometrie enthielt mehr als {} Eckpunkte. Sie musste vereinfacht werden "
|
||||
"um die Obergrenze von {} erlaubten Eckpunkten einzuhalten."
|
||||
|
||||
#: konova/utils/message_templates.py:86
|
||||
#: konova/utils/message_templates.py:99
|
||||
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 "
|
||||
@@ -2269,27 +2281,31 @@ msgstr ""
|
||||
"Kleinstflächen).Diese Bestandteile wurden automatisch entfernt. Bitte "
|
||||
"überprüfen Sie die angepasste Geometrie."
|
||||
|
||||
#: konova/utils/message_templates.py:89
|
||||
#: konova/utils/message_templates.py:102
|
||||
msgid "This intervention has {} revocations"
|
||||
msgstr "Dem Eingriff liegen {} Widersprüche vor"
|
||||
|
||||
#: konova/utils/message_templates.py:92
|
||||
#: konova/utils/message_templates.py:105
|
||||
msgid "Checked on {} by {}"
|
||||
msgstr "Am {} von {} geprüft worden"
|
||||
|
||||
#: konova/utils/message_templates.py:93
|
||||
#: konova/utils/message_templates.py:106
|
||||
msgid "Data has changed since last check on {} by {}"
|
||||
msgstr ""
|
||||
"Daten wurden nach der letzten Prüfung geändert. Letzte Prüfung am {} durch {}"
|
||||
|
||||
#: konova/utils/message_templates.py:94
|
||||
#: konova/utils/message_templates.py:107
|
||||
msgid "Current data not checked yet"
|
||||
msgstr "Momentane Daten noch nicht geprüft"
|
||||
|
||||
#: konova/utils/message_templates.py:97
|
||||
#: konova/utils/message_templates.py:110
|
||||
msgid "New token generated. Administrators need to validate."
|
||||
msgstr "Neuer Token generiert. Administratoren sind informiert."
|
||||
|
||||
#: konova/utils/message_templates.py:113
|
||||
msgid "Resubmission set"
|
||||
msgstr "Wiedervorlage gesetzt"
|
||||
|
||||
#: konova/utils/quality.py:32
|
||||
msgid "missing"
|
||||
msgstr "fehlend"
|
||||
@@ -2308,11 +2324,11 @@ msgstr ""
|
||||
"Dieses Datum ist unrealistisch. Geben Sie bitte das korrekte Datum ein "
|
||||
"(>1950)."
|
||||
|
||||
#: konova/views/base.py:209
|
||||
#: konova/views/base.py:483
|
||||
msgid "{} added"
|
||||
msgstr "{} hinzugefügt"
|
||||
|
||||
#: konova/views/base.py:281
|
||||
#: konova/views/base.py:600
|
||||
msgid "{} edited"
|
||||
msgstr "{} bearbeitet"
|
||||
|
||||
@@ -2324,26 +2340,10 @@ msgstr "Home"
|
||||
msgid "Log"
|
||||
msgstr "Log"
|
||||
|
||||
#: konova/views/record.py:30
|
||||
msgid "{} unrecorded"
|
||||
msgstr "{} entzeichnet"
|
||||
|
||||
#: konova/views/record.py:30
|
||||
msgid "{} recorded"
|
||||
msgstr "{} verzeichnet"
|
||||
|
||||
#: konova/views/record.py:35
|
||||
msgid "Errors found:"
|
||||
msgstr "Fehler gefunden:"
|
||||
|
||||
#: konova/views/report.py:21
|
||||
msgid "Report {}"
|
||||
msgstr "Bericht {}"
|
||||
|
||||
#: konova/views/resubmission.py:39
|
||||
msgid "Resubmission set"
|
||||
msgstr "Wiedervorlage gesetzt"
|
||||
|
||||
#: konova/views/share.py:46
|
||||
msgid "{} has already been shared with you"
|
||||
msgstr "{} wurde bereits für Sie freigegeben"
|
||||
@@ -2884,11 +2884,11 @@ msgstr ""
|
||||
"Falls die Geometrie nicht leer ist, werden die Flurstücke aktuell berechnet. "
|
||||
"Bitte laden Sie diese Seite in ein paar Augenblicken erneut..."
|
||||
|
||||
#: user/forms/modals/api_token.py:25
|
||||
#: user/forms/modals/api_token.py:26
|
||||
msgid "Generate API Token"
|
||||
msgstr "API Token generieren"
|
||||
|
||||
#: user/forms/modals/api_token.py:29
|
||||
#: user/forms/modals/api_token.py:30
|
||||
msgid ""
|
||||
"You are about to create a new API token. The existing one will not be usable "
|
||||
"afterwards."
|
||||
@@ -2896,7 +2896,7 @@ msgstr ""
|
||||
"Wenn Sie fortfahren, generieren Sie einen neuen API Token. Ihren "
|
||||
"existierenden werden Sie dann nicht länger nutzen können."
|
||||
|
||||
#: user/forms/modals/api_token.py:31
|
||||
#: user/forms/modals/api_token.py:32
|
||||
msgid "A new token needs to be validated by an administrator!"
|
||||
msgstr "Neue Tokens müssen durch Administratoren freigeschaltet werden!"
|
||||
|
||||
@@ -3066,7 +3066,7 @@ msgid "Manage teams"
|
||||
msgstr ""
|
||||
|
||||
#: user/templates/user/index.html:53 user/templates/user/team/index.html:19
|
||||
#: user/views/views.py:134
|
||||
#: user/views/teams.py:36
|
||||
msgid "Teams"
|
||||
msgstr ""
|
||||
|
||||
@@ -3122,41 +3122,33 @@ msgstr "Token noch nicht freigeschaltet"
|
||||
msgid "Valid until"
|
||||
msgstr "Läuft ab am"
|
||||
|
||||
#: user/views/api_token.py:34
|
||||
#: user/views/api_token.py:36
|
||||
msgid "User API token"
|
||||
msgstr "API Nutzer Token"
|
||||
|
||||
#: user/views/views.py:31
|
||||
#: user/views/users.py:26
|
||||
msgid "User settings"
|
||||
msgstr "Einstellungen"
|
||||
|
||||
#: user/views/views.py:44
|
||||
#: user/views/users.py:39
|
||||
msgid "User notifications"
|
||||
msgstr "Benachrichtigungen"
|
||||
|
||||
#: user/views/views.py:64
|
||||
#: user/views/users.py:59
|
||||
msgid "Notifications edited"
|
||||
msgstr "Benachrichtigungen bearbeitet"
|
||||
|
||||
#: user/views/views.py:152
|
||||
msgid "New team added"
|
||||
msgstr "Neues Team hinzugefügt"
|
||||
#~ msgid "Eco-account removed"
|
||||
#~ msgstr "Ökokonto entfernt"
|
||||
|
||||
#: user/views/views.py:167
|
||||
msgid "Team edited"
|
||||
msgstr "Team bearbeitet"
|
||||
#~ msgid "EMA removed"
|
||||
#~ msgstr "EMA entfernt"
|
||||
|
||||
#: user/views/views.py:182
|
||||
msgid "Team removed"
|
||||
msgstr "Team gelöscht"
|
||||
#~ msgid "Errors found:"
|
||||
#~ msgstr "Fehler gefunden:"
|
||||
|
||||
#: user/views/views.py:197
|
||||
msgid "You are not a member of this team"
|
||||
msgstr "Sie sind kein Mitglied dieses Teams"
|
||||
|
||||
#: user/views/views.py:204
|
||||
msgid "Left Team"
|
||||
msgstr "Team verlassen"
|
||||
#~ msgid "You are not a member of this team"
|
||||
#~ msgstr "Sie sind kein Mitglied dieses Teams"
|
||||
|
||||
#~ msgid "EMA {} added"
|
||||
#~ msgstr "EMA {} hinzugefügt"
|
||||
|
||||
@@ -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_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_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 },
|
||||
@@ -188,6 +188,7 @@
|
||||
{
|
||||
"title": "Ebene hinzufügen",
|
||||
"preview": true,
|
||||
"editable": true,
|
||||
"wms_options": [ "https://sgx.geodatenzentrum.de/wms_topplus_open" ],
|
||||
"wfs_options": [ "http://213.139.159.34:80/geoserver/uesg/wfs" ],
|
||||
"wfs_proxy": "/client/proxy?",
|
||||
|
||||
2
templates/map/client/dist/netgis.min.css
vendored
2
templates/map/client/dist/netgis.min.css
vendored
File diff suppressed because one or more lines are too long
119
templates/map/client/dist/netgis.min.js
vendored
119
templates/map/client/dist/netgis.min.js
vendored
@@ -13,7 +13,7 @@ netgis.Attribution.prototype.add=function(a){for(var b=0;b<this.items.length;b++
|
||||
netgis.Attribution.prototype.onContextUpdate=function(a){this.initConfig(a.detail.context.config);this.update()};netgis.Attribution.prototype.onContextUpdate_01=function(a){config.attribution&&config.attribution.prefix&&this.items.push(config.attribution.prefix);this.layers=[];for(var b=0;b<a.layers.length;b++){var c=a.layers[b];c.attribution&&0<c.attribution.length&&(this.layers[c.id]=c.attribution)}for(b=0;b<a.layers.length;b++)if(c=a.layers[b],c.active)this.onLayerShow({id:c.id})};
|
||||
netgis.Attribution.prototype.onLayerShow=function(a){if(a=this.layers[a.id]){for(var b=0;b<this.items.length;b++)if(this.items[b]===a)return;this.items.push(a);this.update()}};netgis.Attribution.prototype.onLayerHide=function(a){if(a=this.layers[a.id]){for(var b=0;b<this.items.length;b++)if(this.items[b]===a){this.items.splice(b,1);break}this.update()}};
|
||||
netgis.Attribution.prototype.onEditLayerChange=function(a){a=a.detail.geojson.area;for(var b=0;b<this.items.length;b++)if(-1<this.items[b].search("Zeichnungsfl\u00e4che: ")){this.items.splice(b,1);break}this.appendix=a&&0<a?"<b>Zeichnungsfl\u00e4che: "+netgis.util.formatArea(a,!0)+"</b>":null;this.update()};netgis=netgis||{};netgis.Client=function(a,b){b||(b={});a=this.initLegacyConfig(b,a);this.container=this.initContainer(a);this.debug=!1;netgis.util.isString(b)?netgis.util.isJSON(b,!1)?(b=JSON.parse(b),this.init(this.container,b)):(this.showLoader(!0),netgis.util.request(b,this.onConfigResponse.bind(this))):this.init(this.container,b)};netgis.Client.Config={loading_text:"Geoportal Client wird geladen..."};netgis.Client.Output={id:"netgis-storage"};
|
||||
netgis.Client.prototype.init=function(a,b){this.config=b;this.initParams(b);this.initConfig(b);this.initElements(a);this.initEvents();this.initModules(b);this.initOutput(b);a=new netgis.ContextMenu;a.attachTo(this.container);this.modules.contextmenu=a;this.popup=new netgis.Popup;this.popup.attachTo(this.container)};
|
||||
netgis.Client.prototype.init=function(a,b){this.config=b;this.initParams(b);this.initConfig(b);this.initElements(a);this.initEvents();this.initModules(b);this.initOutput(b)};
|
||||
netgis.Client.prototype.initLegacyConfig=function(a,b){var c=netgis.config;if(!c)return b;c.MAP_CONTAINER_ID&&(b=c.MAP_CONTAINER_ID);a.modules||(a.modules={menu:!0,map:!0,controls:!0,attribution:!0,legend:!0,layertree:!0,info:!0,searchplace:!0,geolocation:!0});a.map||(a.map={});!c.INITIAL_CENTER_X&&0!==c.INITIAL_CENTER_X||!c.INITIAL_CENTER_Y&&0!==c.INITIAL_CENTER_Y||(a.map.center=[c.INITIAL_CENTER_X,c.INITIAL_CENTER_Y]);a.map.scalebar=!0;c.INITIAL_SCALE&&(a.map.scale=c.INITIAL_SCALE);c.MAP_SCALES&&
|
||||
(a.map.scales=c.MAP_SCALES);c.MAP_EXTENT&&(a.map.extent=c.MAP_EXTENT);c.MAX_HISTORY&&(a.map.max_view_history=c.MAX_HISTORY);a.attribution={prefix:"GeoPortal"};c.MAP_PROJECTIONS&&(a.projections=c.MAP_PROJECTIONS);c.MAP_PROJECTION&&(a.map.projection=c.MAP_PROJECTION);a.controls={buttons:[{id:"zoom_in",icon:"<i class='fas fa-plus'></i>",title:"Zoom +"},{id:"zoom_out",icon:"<i class='fas fa-minus'></i>",title:"Zoom -"},{id:"geolocation",icon:"<i class='fas fa-crosshairs'></i>",title:"Ger\u00e4testandort"},
|
||||
{id:"zoom_home",icon:"<i class='fas fa-home'></i>",title:"Anfangsausdehung"},{id:"legend",icon:"<i class='fas fa-bars'></i>",title:"Legende"}]};a.folders||(a.folders=[{id:"bg",title:"Hintergrund",parent:null,radio:!0}]);a.layers||(a.layers=[]);if(c.URL_BACKGROUND_HYBRID){var d=c.URL_BACKGROUND_HYBRID;-1!==d.indexOf("{x}")||-1!==d.indexOf("{y}")&&-1!==d.indexOf("{-y}")||-1!==d.indexOf("{z}")||(d+="/{z}/{x}/{-y}.jpeg");d={id:"bg_hybrid",active:!0,folder:"bg",order:1,title:"Hybrid",type:"TMS",url:d,
|
||||
@@ -38,10 +38,7 @@ this.loaderTimeout=null}.bind(this),600)):(this.loader.classList.remove("netgis-
|
||||
netgis.Client.prototype.isMobile=function(){return netgis.util.isMobile(this.container)};netgis.Client.prototype.onConfigResponse=function(a){a=JSON.parse(a);this.init(this.container,a);this.showLoader(!1)};netgis.Client.prototype.requestContextWMC=function(a,b){if(-1<a.indexOf("{id}"))if(b)a=netgis.util.replace(a,"{id}",b);else{console.warn("No WMC id set in config for url",a);return}(new netgis.WMC(this.config)).requestContext(a,this.onContextResponseWMC.bind(this));this.showLoader(!0)};
|
||||
netgis.Client.prototype.onContextResponseWMC=function(a){console.info("WMC Response:",a);for(var b=0;b<a.config.layers.length;b++)this.config.layers.push(a.config.layers[b]);a.config.map.bbox&&(this.config.map.bbox=a.config.map.bbox);netgis.util.invoke(this.container,netgis.Events.CLIENT_CONTEXT_RESPONSE,{context:a});this.showLoader(!1)};
|
||||
netgis.Client.prototype.onContextResponseLayer=function(a){var b=JSON.parse(a);console.info("Layer Response:",b);a=new netgis.WMC;b=b.wms.srv[0];a=a.parseServiceLayer(b.id.toString(),b,null,b.layer[0],null);this.config.layers.push(a);netgis.util.invoke(this.container,netgis.Events.MAP_LAYER_CREATE,a)};netgis.Client.prototype.requestContextOWS=function(a){console.info("Request OWS:",a);netgis.util.request(a,this.onContextResponseOWS.bind(this))};
|
||||
netgis.Client.prototype.onContextResponseOWS=function(a){a=JSON.parse(a);console.info("OWS Response:",a);a=netgis.OWS.read(a,this);console.info("OWS Config:",a)};netgis.Client.prototype.onIconbarIconClick=function(a){switch(a.detail.id){case "home":a=this.config.layers;for(var b=0;b<a.length;b++){var c=a[b],d=c.id;!0===c.active?(this.modules.map.addLayer(d,c),this.modules.layertree.tree.setItemChecked(d,!0)):(this.modules.map.removeLayer(d),this.modules.layertree.tree.setItemChecked(d,!1))}}};
|
||||
netgis.Client.prototype.onIconbarItemClick=function(a){a=a.detail;for(var b=this.config.layers,c=0;c<b.length;c++){var d=b[c],e=d.id;"background"!==d.folder&&(e===a.id?(this.modules.map.addLayer(e,d),this.modules.layertree.tree.setItemChecked(e,!0)):(this.modules.map.removeLayer(e),this.modules.layertree.tree.setItemChecked(e,!1)))}};
|
||||
netgis.Client.prototype.onSwitcherButtonClick=function(a){a=a.detail;for(var b=this.config.switcher.buttons,c=this.config.layers,d=0;d<b.length;d++){var e=b[d].id;if(e===a.id)for(var f=0;f<c.length;f++){var g=c[f];g.id===e&&(this.modules.map.addLayer(e,g),this.modules.layertree.tree.setItemChecked(e,!0))}else this.modules.map.removeLayer(e),this.modules.layertree.tree.setItemChecked(e,!1)}0===this.modules.switcher.getIndex(a.id)&&this.modules.switcher.shift(1,0)};
|
||||
netgis.Client.prototype.onGeolocationToggle=function(a){this.modules.map.setGeolocMarkerVisible(a.detail.on)};netgis.Client.prototype.onGeolocationChange=function(a){a=a.detail;this.modules.map.zoomLonLat(a.lon,a.lat,this.config.geolocation.zoom);this.modules.map.setGeolocMarkerLonLat(a.lon,a.lat)};netgis.Client.prototype.onMapEditLayerChange=function(a){a=JSON.stringify(a.detail.geojson);this.output.value=a};
|
||||
netgis.Client.prototype.onContextResponseOWS=function(a){a=JSON.parse(a);console.info("OWS Response:",a);a=netgis.OWS.read(a,this);console.info("OWS Config:",a)};netgis.Client.prototype.onMapEditLayerChange=function(a){a=JSON.stringify(a.detail.geojson);this.output.value=a};
|
||||
netgis.Client.handleCommand=function(a,b){var c=b.split(":");b=c[0];switch(b.toUpperCase()){case netgis.Commands.PLUGIN:b=c[1];if(!b){console.error("missing second command parameter id",c);break}netgis.util.invoke(a,netgis.Events.PLUGIN_TOGGLE,{id:b});break;case netgis.Commands.LAYERTREE:netgis.util.isMobile()?netgis.util.invoke(a,netgis.Events.LAYERTREE_TOGGLE,{on:!0}):netgis.util.invoke(a,netgis.Events.LAYERTREE_TOGGLE,null);break;case netgis.Commands.SEARCHPLACE:netgis.util.isMobile()?netgis.util.invoke(a,
|
||||
netgis.Events.SEARCHPLACE_TOGGLE,{on:!0}):netgis.util.invoke(a,netgis.Events.SEARCHPLACE_TOGGLE,null);break;case netgis.Commands.SEARCHPARCEL:netgis.util.isMobile()?netgis.util.invoke(a,netgis.Events.SEARCHPARCEL_TOGGLE,{on:!0}):netgis.util.invoke(a,netgis.Events.SEARCHPARCEL_TOGGLE,null);break;case netgis.Commands.TOOLBOX:netgis.util.isMobile()?netgis.util.invoke(a,netgis.Events.TOOLBOX_TOGGLE,{on:!0}):netgis.util.invoke(a,netgis.Events.TOOLBOX_TOGGLE,null);break;case netgis.Commands.LEGEND:netgis.util.isMobile()?
|
||||
netgis.util.invoke(a,netgis.Events.LEGEND_TOGGLE,{on:!0}):netgis.util.invoke(a,netgis.Events.LEGEND_TOGGLE,null);break;case netgis.Commands.VIEW_PREV:netgis.util.invoke(a,netgis.Events.MAP_VIEW_PREV,null);break;case netgis.Commands.VIEW_NEXT:netgis.util.invoke(a,netgis.Events.MAP_VIEW_NEXT,null);break;case netgis.Commands.VIEW:netgis.util.invoke(a,netgis.Events.CLIENT_SET_MODE,{mode:netgis.Modes.VIEW});break;case netgis.Commands.ZOOM_BOX:netgis.util.invoke(a,netgis.Events.CLIENT_SET_MODE,{mode:netgis.Modes.ZOOM_BOX});
|
||||
@@ -94,19 +91,19 @@ netgis.Export.prototype.onExportEnd=function(a){this.modal.hide()};netgis=netgis
|
||||
netgis.Geolocation.prototype.setActive=function(a,b){var c=this.config.geolocation;a?navigator.geolocation?(this.watch=navigator.geolocation.watchPosition(this.onPositionChange.bind(this),this.onPositionError.bind(this),{timeout:c&&c.timeout?1E3*c.timeout:1E4,maximumAge:0,enableHighAccuracy:!0}),b||netgis.util.invoke(this.container,netgis.Events.GEOLOCATION_TOGGLE_ACTIVE,{on:!0})):this.error("Geolocation not supported by this device!"):(this.watch&&(navigator.geolocation.clearWatch(this.watch),this.watch=
|
||||
null),b||netgis.util.invoke(this.container,netgis.Events.GEOLOCATION_TOGGLE_ACTIVE,{on:!1}));this.active=a};netgis.Geolocation.prototype.isActive=function(){return this.active};netgis.Geolocation.prototype.error=function(a){console.error(a);this.watch&&(navigator.geolocation.clearWatch(this.watch),this.watch=null);netgis.util.invoke(this.container,netgis.Events.GEOLOCATION_TOGGLE_ACTIVE,{on:!1})};netgis.Geolocation.prototype.onActiveChange=function(a){this.setActive(a.currentTarget.checked)};
|
||||
netgis.Geolocation.prototype.onCenterChange=function(a){};netgis.Geolocation.prototype.onPositionChange=function(a){netgis.util.invoke(this.container,netgis.Events.GEOLOCATION_CHANGE,{lon:a.coords.longitude,lat:a.coords.latitude,center:this.center})};netgis.Geolocation.prototype.onPositionError=function(a){this.error("Geolocation: "+a.message+" ("+a.code+")")};netgis.Geolocation.prototype.onGeolocToggleActive=function(a){a.target!==this.container&&this.setActive(a.detail.on)};
|
||||
netgis.Geolocation.prototype.onGeolocToggleCenter=function(a){a.target!==this.container&&(this.center=a.detail.on)};netgis=netgis||{};netgis.Import=function(a){this.config=a;this.initElements(a);this.initSections(a);this.initPreview()};netgis.Import.Config={title:"Import Layer",preview:!0,wms_options:[],wfs_options:[],wfs_proxy:"",geopackage_lib:"/libs/geopackage/4.2.3/",geoportal_tab:!0,geoportal_search_url:"",geoportal_autocomplete:!0};
|
||||
netgis.Geolocation.prototype.onGeolocToggleCenter=function(a){a.target!==this.container&&(this.center=a.detail.on)};netgis=netgis||{};netgis.Import=function(a){this.config=a;this.initElements(a);this.initSections(a);this.initPreview()};netgis.Import.Config={title:"Import Layer",preview:!0,editable:!0,wms_options:[],wfs_options:[],wfs_proxy:"",geopackage_lib:"/libs/geopackage/4.2.3/",geoportal_tab:!0,geoportal_search_url:"",geoportal_autocomplete:!0};
|
||||
netgis.Import.prototype.initElements=function(a){a=a["import"];this.modal=new netgis.Modal(a.title?a.title:"Import");this.modal.container.classList.add("netgis-import");var b="WMS WFS GeoJSON GML GeoPackage Spatialite Shapefile".split(" ");a.geoportal_tab&&b.unshift("Geoportal");this.tabs=new netgis.Tabs(b);this.tabs.container.style.position="absolute";this.tabs.container.style.left="0mm";this.tabs.container.style.right="0mm";this.tabs.container.style.top="12mm";this.tabs.container.style.bottom="0mm";
|
||||
this.tabs.attachTo(this.modal.content)};
|
||||
netgis.Import.prototype.initSections=function(a){this.sections={};var b=0;a["import"]&&!0===a["import"].geoportal_tab&&(this.sections.geoportal=this.tabs.getContentSection(b),b+=1,this.sections.geoportal.classList.add("netgis-geoportal"),this.geoportalSearch=new netgis.Search("Thema, Schlagwort..."),this.geoportalSearch.container.addEventListener(netgis.Events.SEARCH_CHANGE,this.onGeoportalSearchChange.bind(this)),this.geoportalSearch.container.addEventListener(netgis.Events.SEARCH_CLEAR,this.onGeoportalSearchClear.bind(this)),
|
||||
this.geoportalSearch.attachTo(this.sections.geoportal),a=document.createElement("span"),a.innerHTML="Suche im Datenkatalog:",this.geoportalSearch.label.insertBefore(a,this.geoportalSearch.label.firstChild),this.geoportalLoader=document.createElement("div"),this.geoportalLoader.className="netgis-loader netgis-text-a netgis-hide",this.geoportalLoader.innerHTML="<i class='fas fa-cog'></i>",this.sections.geoportal.appendChild(this.geoportalLoader),this.geoportalResults=new netgis.Tree,this.geoportalResults.container.addEventListener(netgis.Events.TREE_ITEM_CHANGE,
|
||||
this.onGeoportalTreeItemChange.bind(this)),this.geoportalResults.attachTo(this.sections.geoportal),this.geoportalSubmit=this.addButton(this.sections.geoportal,"<i class='netgis-icon fas fa-check'></i><span>Hinzuf\u00fcgen<span class='netgis-count'></span></span>",this.onGeoportalSubmit.bind(this)));this.sections.wms=this.tabs.getContentSection(b);b+=1;this.addInputText(this.sections.wms,"WMS-URL:",this.config["import"].wms_options);this.addButton(this.sections.wms,"<i class='netgis-icon fas fa-cloud-download-alt'></i><span>Dienst laden</span>",
|
||||
this.onWMSLoadClick.bind(this));this.addInputText(this.sections.wms,"Bezeichnung:");this.addInputSelect(this.sections.wms,"Ebene:");this.addInputSelect(this.sections.wms,"Format:");this.addButton(this.sections.wms,"<i class='netgis-icon fas fa-check'></i><span>Hinzuf\u00fcgen</span>",this.onWMSAcceptClick.bind(this));this.showDetailsWMS(!1);this.sections.wfs=this.tabs.getContentSection(b);b+=1;this.addInputText(this.sections.wfs,"WFS-URL:",this.config["import"].wfs_options);this.addButton(this.sections.wfs,
|
||||
"<i class='netgis-icon fas fa-cloud-download-alt'></i><span>Dienst laden</span>",this.onWFSLoadClick.bind(this));this.addInputText(this.sections.wfs,"Bezeichnung:");this.addInputSelect(this.sections.wfs,"Ebene:");this.addInputSelect(this.sections.wfs,"Format:");this.addButton(this.sections.wfs,"<i class='netgis-icon fas fa-check'></i><span>Hinzuf\u00fcgen</span>",this.onWFSAcceptClick.bind(this));this.showDetailsWFS(!1);this.sections.geojson=this.tabs.getContentSection(b);b+=1;this.addInputFile(this.sections.geojson,
|
||||
"GeoJSON-Datei:",".geojson,.json");this.addText(this.sections.geojson,"<h3>Unterst\u00fctzte Koordinatensysteme:</h3><ul><li>Web Mercator (EPSG:3857)</li><li>WGS84 / Lon-Lat (EPSG:4326)</li><li>ETRS89 / UTM Zone 32N (EPSG:25832)</li></ul>");this.addButton(this.sections.geojson,"<i class='netgis-icon fas fa-check'></i><span>Datei laden</span>",this.onGeoJSONAcceptClick.bind(this));this.sections.gml=this.tabs.getContentSection(b);b+=1;this.addInputFile(this.sections.gml,"GML-Datei:",".gml,.xml");this.addText(this.sections.gml,
|
||||
"<h3>Unterst\u00fctzte Koordinatensysteme:</h3><ul><li>Web Mercator (EPSG:3857)</li><li>WGS84 / Lon-Lat (EPSG:4326)</li><li>ETRS89 / UTM Zone 32N (EPSG:25832)</li></ul>");this.addButton(this.sections.gml,"<i class='netgis-icon fas fa-check'></i><span>Datei laden</span>",this.onGMLAcceptClick.bind(this));this.sections.geopackage=this.tabs.getContentSection(b);b+=1;this.addInputFile(this.sections.geopackage,"GeoPackage-Datei:",".gpkg");this.addText(this.sections.geopackage,"<h3>Unterst\u00fctzte Koordinatensysteme:</h3><ul><li>Web Mercator (EPSG:3857)</li><li>WGS84 / Lon-Lat (EPSG:4326)</li><li>ETRS89 / UTM Zone 32N (EPSG:25832)</li></ul>");
|
||||
this.addButton(this.sections.geopackage,"<i class='netgis-icon fas fa-check'></i><span>Datei laden</span>",this.onGeoPackageAcceptClick.bind(this));this.sections.spatialite=this.tabs.getContentSection(b);b+=1;this.addInputFile(this.sections.spatialite,"Spatialite-Datei:",".sqlite");this.addText(this.sections.spatialite,"<h3>Unterst\u00fctzte Koordinatensysteme:</h3><ul><li>Web Mercator (EPSG:3857)</li><li>WGS84 / Lon-Lat (EPSG:4326)</li><li>ETRS89 / UTM Zone 32N (EPSG:25832)</li></ul>");this.addButton(this.sections.spatialite,
|
||||
"<i class='netgis-icon fas fa-check'></i><span>Datei laden</span>",this.onSpatialiteAcceptClick.bind(this));this.sections.shapefile=this.tabs.getContentSection(b);this.addInputFile(this.sections.shapefile,"Shapefile-Zip-Datei:",".zip");this.addText(this.sections.shapefile,"<h3>Unterst\u00fctzte Koordinatensysteme:</h3><ul><li>Web Mercator (EPSG:3857)</li><li>WGS84 / Lon-Lat (EPSG:4326)</li><li>ETRS89 / UTM Zone 32N (EPSG:25832)</li></ul>");this.addButton(this.sections.shapefile,"<i class='netgis-icon fas fa-check'></i><span>Datei laden</span>",
|
||||
this.onShapefileAcceptClick.bind(this))};
|
||||
netgis.Import.prototype.initSections=function(a){this.sections={};var b=0;a["import"]&&!0===a["import"].geoportal_tab&&(this.sections.geoportal=this.tabs.getContentSection(b),b+=1,this.sections.geoportal.classList.add("netgis-geoportal"),this.geoportalSearch=new netgis.Search("Thema, Schlagwort..."),this.geoportalSearch.autocomplete=a["import"].geoportal_autocomplete,this.geoportalSearch.container.addEventListener(netgis.Events.SEARCH_CHANGE,this.onGeoportalSearchChange.bind(this)),this.geoportalSearch.container.addEventListener(netgis.Events.SEARCH_CLEAR,
|
||||
this.onGeoportalSearchClear.bind(this)),this.geoportalSearch.attachTo(this.sections.geoportal),a=document.createElement("span"),a.innerHTML="Suche im Datenkatalog:",this.geoportalSearch.label.insertBefore(a,this.geoportalSearch.label.firstChild),a=document.createElement("button"),a.innerHTML="Suchen",a.className="netgis-color-a netgis-hover-c netgis-round netgis-shadow",a.setAttribute("type","button"),a.addEventListener("click",this.onGeoportalSearchButtonClick.bind(this)),this.geoportalSearch.label.appendChild(a),
|
||||
this.geoportalLoader=document.createElement("div"),this.geoportalLoader.className="netgis-loader netgis-text-a netgis-hide",this.geoportalLoader.innerHTML="<i class='fas fa-cog'></i>",this.sections.geoportal.appendChild(this.geoportalLoader),this.geoportalResults=new netgis.Tree,this.geoportalResults.container.addEventListener(netgis.Events.TREE_ITEM_CHANGE,this.onGeoportalTreeItemChange.bind(this)),this.geoportalResults.attachTo(this.sections.geoportal),this.geoportalSubmit=this.addButton(this.sections.geoportal,
|
||||
"<i class='netgis-icon fas fa-check'></i><span>Hinzuf\u00fcgen<span class='netgis-count'></span></span>",this.onGeoportalSubmit.bind(this)));this.sections.wms=this.tabs.getContentSection(b);b+=1;this.addInputText(this.sections.wms,"WMS-URL:",this.config["import"].wms_options);this.addButton(this.sections.wms,"<i class='netgis-icon fas fa-cloud-download-alt'></i><span>Dienst laden</span>",this.onWMSLoadClick.bind(this));this.addInputText(this.sections.wms,"Bezeichnung:");this.addInputSelect(this.sections.wms,
|
||||
"Ebene:");this.addInputSelect(this.sections.wms,"Format:");this.addButton(this.sections.wms,"<i class='netgis-icon fas fa-check'></i><span>Hinzuf\u00fcgen</span>",this.onWMSAcceptClick.bind(this));this.showDetailsWMS(!1);this.sections.wfs=this.tabs.getContentSection(b);b+=1;this.addInputText(this.sections.wfs,"WFS-URL:",this.config["import"].wfs_options);this.addButton(this.sections.wfs,"<i class='netgis-icon fas fa-cloud-download-alt'></i><span>Dienst laden</span>",this.onWFSLoadClick.bind(this));
|
||||
this.addInputText(this.sections.wfs,"Bezeichnung:");this.addInputSelect(this.sections.wfs,"Ebene:");this.addInputSelect(this.sections.wfs,"Format:");this.addButton(this.sections.wfs,"<i class='netgis-icon fas fa-check'></i><span>Hinzuf\u00fcgen</span>",this.onWFSAcceptClick.bind(this));this.showDetailsWFS(!1);this.sections.geojson=this.tabs.getContentSection(b);b+=1;this.addInputFile(this.sections.geojson,"GeoJSON-Datei:",".geojson,.json");this.addText(this.sections.geojson,"<h3>Unterst\u00fctzte Koordinatensysteme:</h3><ul><li>Web Mercator (EPSG:3857)</li><li>WGS84 / Lon-Lat (EPSG:4326)</li><li>ETRS89 / UTM Zone 32N (EPSG:25832)</li></ul>");
|
||||
this.addButton(this.sections.geojson,"<i class='netgis-icon fas fa-check'></i><span>Datei laden</span>",this.onGeoJSONAcceptClick.bind(this));this.sections.gml=this.tabs.getContentSection(b);b+=1;this.addInputFile(this.sections.gml,"GML-Datei:",".gml,.xml");this.addText(this.sections.gml,"<h3>Unterst\u00fctzte Koordinatensysteme:</h3><ul><li>Web Mercator (EPSG:3857)</li><li>WGS84 / Lon-Lat (EPSG:4326)</li><li>ETRS89 / UTM Zone 32N (EPSG:25832)</li></ul>");this.addButton(this.sections.gml,"<i class='netgis-icon fas fa-check'></i><span>Datei laden</span>",
|
||||
this.onGMLAcceptClick.bind(this));this.sections.geopackage=this.tabs.getContentSection(b);b+=1;this.addInputFile(this.sections.geopackage,"GeoPackage-Datei:",".gpkg");this.addText(this.sections.geopackage,"<h3>Unterst\u00fctzte Koordinatensysteme:</h3><ul><li>Web Mercator (EPSG:3857)</li><li>WGS84 / Lon-Lat (EPSG:4326)</li><li>ETRS89 / UTM Zone 32N (EPSG:25832)</li></ul>");this.addButton(this.sections.geopackage,"<i class='netgis-icon fas fa-check'></i><span>Datei laden</span>",this.onGeoPackageAcceptClick.bind(this));
|
||||
this.sections.spatialite=this.tabs.getContentSection(b);b+=1;this.addInputFile(this.sections.spatialite,"Spatialite-Datei:",".sqlite");this.addText(this.sections.spatialite,"<h3>Unterst\u00fctzte Koordinatensysteme:</h3><ul><li>Web Mercator (EPSG:3857)</li><li>WGS84 / Lon-Lat (EPSG:4326)</li><li>ETRS89 / UTM Zone 32N (EPSG:25832)</li></ul>");this.addButton(this.sections.spatialite,"<i class='netgis-icon fas fa-check'></i><span>Datei laden</span>",this.onSpatialiteAcceptClick.bind(this));this.sections.shapefile=
|
||||
this.tabs.getContentSection(b);this.addInputFile(this.sections.shapefile,"Shapefile-Zip-Datei:",".zip");this.addText(this.sections.shapefile,"<h3>Unterst\u00fctzte Koordinatensysteme:</h3><ul><li>Web Mercator (EPSG:3857)</li><li>WGS84 / Lon-Lat (EPSG:4326)</li><li>ETRS89 / UTM Zone 32N (EPSG:25832)</li></ul>");this.addButton(this.sections.shapefile,"<i class='netgis-icon fas fa-check'></i><span>Datei laden</span>",this.onShapefileAcceptClick.bind(this))};
|
||||
netgis.Import.prototype.initPreview=function(){this.preview=new netgis.Modal("Vorschau");this.preview.attachTo(this.modal.content);this.previewMapContainer=document.createElement("div");this.previewMapContainer.className="netgis-preview-map";this.preview.content.appendChild(this.previewMapContainer);if(ol){var a=this.config.map;a={projection:a.projection,center:a.centerLonLat?ol.proj.fromLonLat(a.centerLonLat):a.center,zoom:a.zoom};this.previewMap=new ol.Map({target:this.previewMapContainer,view:new ol.View(a),
|
||||
pixelRatio:1,moveTolerance:3,controls:[]});this.previewMap.getView().padding=[10,10,10,10];this.previewMap.addLayer(new ol.layer.Tile({source:new ol.source.OSM}))}this.previewTree=new netgis.Tree;this.previewTree.container.classList.add("netgis-preview-tree");this.previewTree.attachTo(this.preview.content);this.previewTree.container.addEventListener(netgis.Events.TREE_ITEM_CHANGE,this.onPreviewTreeItemChange.bind(this));this.previewSubmit=document.createElement("button");this.previewSubmit.setAttribute("type",
|
||||
"button");this.previewSubmit.className="netgis-import-submit netgis-button netgis-center netgis-color-a netgis-hover-c netgis-shadow";this.previewSubmit.innerHTML="<i class='netgis-icon fas fa-check'></i><span>Hinzuf\u00fcgen</span>";this.previewSubmit.addEventListener("click",this.onPreviewSubmitClick.bind(this));this.preview.content.appendChild(this.previewSubmit)};
|
||||
@@ -137,16 +134,17 @@ netgis.Import.prototype.onSpatialiteAcceptClick=function(a){if(a=this.sections.s
|
||||
netgis.Import.prototype.onSpatialiteLoad=function(a){var b=a.target;a=b.result;var c="import_"+netgis.util.getTimeStamp(!0);b=b.title;a={id:c,folder:null,active:!0,order:this.getLayerOrder(),style:this.config.styles["import"],title:b,type:netgis.LayerTypes.SPATIALITE,data:a};this.submitImportLayer(a)};
|
||||
netgis.Import.prototype.onShapefileAcceptClick=function(a){if(a=this.sections.shapefile.getElementsByTagName("input")[0].files[0]){var b=new FileReader;b.title=a.name;b.onload=this.onShapefileLoad.bind(this);b.readAsArrayBuffer(a)}else alert("No file selected!")};
|
||||
netgis.Import.prototype.onShapefileLoad=function(a){var b=a.target;a=b.result;var c="import_"+netgis.util.getTimeStamp(!0);b=b.title;a={id:c,folder:null,active:!0,order:this.getLayerOrder(),style:this.config.styles["import"],title:b,type:netgis.LayerTypes.SHAPEFILE,data:a};this.submitImportLayer(a)};
|
||||
netgis.Import.prototype.onImportPreviewFeatures=function(a){var b=a.detail,c=b.layer;this.previewTree.clear();a=this.previewMap.getLayers().getArray();for(var d=1;d<a.length;d++)this.previewMap.removeLayer(a[d]);if(ol){a=config.styles["import"];a=new ol.style.Style({fill:new ol.style.Fill({color:a.fill}),stroke:new ol.style.Stroke({color:a.stroke,width:a.width})});c.setStyle(a);this.previewMap.addLayer(c);var e=this.previewTree.addFolder(null,b.id,b.title);a=c.getSource().getFeatures();if(0===a.length){var f=
|
||||
this;c.getSource().on("addfeature",function(a){f.featureLoadTimeout&&window.clearTimeout(f.featureLoadTimeout);f.featureLoadTimeout=window.setTimeout(function(){var a=c.getSource().getFeatures();f.updatePreviewFeatures(a,e,c,b);f.featureLoadTimeout=null},100)})}else this.updatePreviewFeatures(a,e,c,b)}else console.error("import preview only supported with OL map renderer",c)};
|
||||
netgis.Import.prototype.onImportPreviewFeatures=function(a){var b=a.detail,c=b.layer;this.previewTree.clear();a=this.previewMap.getLayers().getArray();for(var d=1;d<a.length;d++)this.previewMap.removeLayer(a[d]);if(ol){a=this.config.styles["import"];a=new ol.style.Style({fill:new ol.style.Fill({color:a.fill}),stroke:new ol.style.Stroke({color:a.stroke,width:a.width})});c.setStyle(a);this.previewMap.addLayer(c);var e=this.previewTree.addFolder(null,b.id,b.title);a=c.getSource().getFeatures();if(0===
|
||||
a.length){var f=this;c.getSource().on("addfeature",function(a){f.featureLoadTimeout&&window.clearTimeout(f.featureLoadTimeout);f.featureLoadTimeout=window.setTimeout(function(){var a=c.getSource().getFeatures();f.updatePreviewFeatures(a,e,c,b);f.featureLoadTimeout=null},100)})}else this.updatePreviewFeatures(a,e,c,b)}else console.error("import preview only supported with OL map renderer",c)};
|
||||
netgis.Import.prototype.updatePreviewFeatures=function(a,b,c,d){for(var e=0;e<a.length;e++){var f=a[e],g=f.getId(),h=f.getProperties();g||(g=e+1,f.setId(g));var k=null,l;for(l in h)switch(l.toLowerCase()){case "name":k=h[l];break;case "title":k=h[l];break;case "id":k=h[l];break;case "gid":k=h[l];break;case "oid":k=h[l];break;case "objectid":k=h[l]}k||(k=g);h=f.getGeometry();if(h instanceof ol.geom.Polygon||h instanceof ol.geom.MultiPolygon)k+=" ("+netgis.util.formatArea(h.getArea())+")";else if(h instanceof
|
||||
ol.geom.LineString)k+=" ("+netgis.util.formatArea(h.getLength())+")";else if(h instanceof ol.geom.MultiLineString){f=0;h=h.getLineStrings();for(var m=0;m<h.length;m++)f+=h[m].getLength();k+=" ("+netgis.util.formatArea(f)+")"}this.previewTree.addCheckbox(b,g,"Feature "+k,!0)}this.previewTree.setFolderOpen(d.id,!0);this.previewTree.updateFolderChecks();this.preview.show();this.previewMap.updateSize();this.previewMap.getView().fit(c.getSource().getExtent())};
|
||||
netgis.Import.prototype.onPreviewSubmitClick=function(a){var b=this.previewTree.container.getElementsByClassName("netgis-folder")[0];a=b.getAttribute("data-id");b=b.getElementsByTagName("span")[0].innerText;for(var c=this.previewTree.container.getElementsByTagName("input"),d=this.previewMap.getLayers().getArray()[1].getSource(),e=[],f=1;f<c.length;f++){var g=c[f];g.checked&&(g=g.getAttribute("data-id"),g=d.getFeatureById(g),e.push(g))}c=(new ol.format.GeoJSON).writeFeaturesObject(e);d=this.previewMap.getView().getProjection().getCode();
|
||||
c.crs={type:"name",properties:{name:"urn:ogc:def:crs:"+d.replace(":","::")}};a={id:a,folder:null,active:!0,order:this.getLayerOrder(),style:this.config.styles["import"],title:b,type:netgis.LayerTypes.GEOJSON,data:c};this.config.layers.push(a);netgis.util.invoke(this.preview.container,netgis.Events.IMPORT_LAYER_ACCEPT,a);this.preview.hide();this.modal.hide()};
|
||||
c.crs={type:"name",properties:{name:"urn:ogc:def:crs:"+d.replace(":","::")}};a={id:a,folder:null,active:!0,editable:this.config["import"]&&!0===this.config["import"].editable,order:this.getLayerOrder(),style:this.config.styles["import"],title:b,type:netgis.LayerTypes.GEOJSON,data:c};this.config.layers.push(a);netgis.util.invoke(this.preview.container,netgis.Events.IMPORT_LAYER_ACCEPT,a);this.preview.hide();this.modal.hide()};
|
||||
netgis.Import.prototype.onPreviewTreeItemChange=function(a){a=a.detail;var b=this.previewMap.getLayers().getArray()[1].getSource().getFeatureById(a.id);a.checked?b.setStyle(null):b.setStyle(new ol.style.Style({}))};netgis.Import.prototype.onGeoportalSearchKeyUp=function(a){switch(a.keyCode){case 13:break;case 27:break;default:this.onGeoportalSearchChange()}};
|
||||
netgis.Import.prototype.onGeoportalSearchChange=function(a){a=a.detail.query;if(0<a.length){this.geoportalLoader.classList.remove("netgis-hide");a=netgis.util.replace(a," ",",");var b=this.config["import"].geoportal_search_url;b=netgis.util.replace(b,"{query}",window.encodeURIComponent(a));netgis.util.request(b,this.onGeoportalSearchResponse.bind(this));this.geoportalSearch.showClearButton(!0)}};netgis.Import.prototype.onGeoportalSearchClear=function(a){this.geoportalResults.clear()};
|
||||
netgis.Import.prototype.onGeoportalSearchResponse=function(a){function b(a){if(a&&a.layer)for(var c=0;c<a.layer.length;c++)b(a.layer[c]);else a&&e.push(a);return e.length}a=JSON.parse(a);this.geoportalResults.clear();this.geoportalDataRaw=a=a.wms.srv;this.geoportalData=[];for(var c=0;c<a.length;c++){var d=a[c];var e=[];var f=b(d);f=this.geoportalResults.addFolder(null,c,d.title+" ("+f+")");f.setAttribute("title",d["abstract"]);for(var g=0;g<e.length;g++)this.geoportalResults.addCheckbox(f,g,e[g].title);
|
||||
d.children=e;this.geoportalData.push(d)}this.geoportalLoader.classList.add("netgis-hide")};netgis.Import.prototype.onGeoportalTreeItemChange=function(a){a=this.geoportalResults.container.getElementsByClassName("netgis-item");for(var b=0,c=0;c<a.length;c++)a[c].getElementsByTagName("input")[0].checked&&(b+=1);this.geoportalSubmit.getElementsByClassName("netgis-count")[0].innerHTML=0===b?"":" ("+b+")"};
|
||||
d.children=e;this.geoportalData.push(d)}this.geoportalLoader.classList.add("netgis-hide")};netgis.Import.prototype.onGeoportalSearchButtonClick=function(a){this.geoportalSearch.onInputTimeout()};
|
||||
netgis.Import.prototype.onGeoportalTreeItemChange=function(a){a=this.geoportalResults.container.getElementsByClassName("netgis-item");for(var b=0,c=0;c<a.length;c++)a[c].getElementsByTagName("input")[0].checked&&(b+=1);this.geoportalSubmit.getElementsByClassName("netgis-count")[0].innerHTML=0===b?"":" ("+b+")"};
|
||||
netgis.Import.prototype.onGeoportalSubmit=function(a){a=this.geoportalResults.container.getElementsByClassName("netgis-item");for(var b=0,c=0;c<a.length;c++){var d=a[c],e=d.getElementsByTagName("input")[0];if(e.checked){b+=1;e=e.getAttribute("data-id");d=d.parentNode.parentNode.parentNode.getAttribute("data-id");var f=this.geoportalData[d],g=f.children[e],h=f.title;f=f.getMapUrl;var k=g.name;g=g.title;d="geoportal_"+d;e=d+"_"+e;netgis.util.invoke(this.sections.geoportal,netgis.Events.IMPORT_GEOPORTAL_SUBMIT,
|
||||
{folder:{id:d,title:h},layer:{id:e,url:f,name:k,title:g}})}}0<b&&this.modal.hide()};netgis=netgis||{};netgis.Info=function(a){this.config=a;this.queryLayers={};this.popup=new netgis.Popup;this.popup.setHeader("Abfrage");this.initConfig(a)};netgis.Info.Config={default_format:"text/plain",proxy:""};netgis.Info.prototype.initConfig=function(a){a=a.layers;for(var b=a.length-1;0<=b;b--){var c=a[b];!0===c.active&&this.isLayerQueryable(c)?this.queryLayers[c.id]=c:this.queryLayers[c.id]&&delete this.queryLayers[c.id]}};
|
||||
netgis.Info.prototype.attachTo=function(a){this.popup.attachTo(a);a.addEventListener(netgis.Events.CLIENT_CONTEXT_RESPONSE,this.onClientContextResponse.bind(this));a.addEventListener(netgis.Events.CLIENT_SET_MODE,this.onClientSetMode.bind(this));a.addEventListener(netgis.Events.MAP_LAYER_TOGGLE,this.onMapLayerToggle.bind(this));a.addEventListener(netgis.Events.MAP_LAYER_CREATE,this.onMapLayerCreate.bind(this));a.addEventListener(netgis.Events.MAP_LAYER_DELETE,this.onMapLayerDelete.bind(this));a.addEventListener(netgis.Events.IMPORT_LAYER_ACCEPT,
|
||||
@@ -154,24 +152,24 @@ this.onImportLayerAccept.bind(this));a.addEventListener(netgis.Events.IMPORT_GEO
|
||||
netgis.Info.prototype.addSection=function(a,b,c){this.popup.addContent([!0===c?"<details open='open'>":"<details>","<summary class='netgis-button netgis-noselect netgis-clip-text netgis-color-d netgis-hover-text-a netgis-hover-d'>",a,"</summary><div class='netgis-border-d'>",b,"</div></details>"].join(""))};netgis.Info.prototype.onClientContextResponse=function(a){this.initConfig(a.detail.context.config)};netgis.Info.prototype.onClientSetMode=function(a){this.popup.hide()};
|
||||
netgis.Info.prototype.onMapLayerToggle=function(a){var b=a.detail;a=b.id;if(b.on){b=this.config.layers;for(var c=null,d=0;d<b.length;d++)if(b[d].id===a){c=b[d];break}c&&this.isLayerQueryable(c)&&(this.queryLayers[a]=c)}else delete this.queryLayers[a]};netgis.Info.prototype.onMapLayerCreate=function(a){a=a.detail;this.isLayerQueryable(a)&&(this.queryLayers[a.id]=a)};netgis.Info.prototype.onMapLayerDelete=function(a){delete this.queryLayers[a.detail.id]};
|
||||
netgis.Info.prototype.onImportLayerAccept=function(a){a=a.detail;this.isLayerQueryable(a)&&(this.queryLayers[a.id]=a)};netgis.Info.prototype.onImportGeoportalSubmit=function(a){};
|
||||
netgis.Info.prototype.onMapClick=function(a){a=a.detail;if(a.mode===netgis.Modes.SEARCH_PARCEL)this.popup.clearContent(),this.popup.hide();else if(a.mode===netgis.Modes.VIEW){var b=this.config.info;this.popup.container!==a.overlay&&this.popup.attachTo(a.overlay);this.popup.clearContent();var c=0,d;for(d in this.queryLayers){var e=this.queryLayers[d];if(a.info&&a.info[d]){var f=a.info[d];b.proxy&&0<b.proxy.length&&(f=b.proxy+f);netgis.util.request(f,this.onLayerResponseWMS.bind(this),{title:e.title});
|
||||
netgis.Info.prototype.onMapClick=function(a){a=a.detail;if(a.mode===netgis.Modes.SEARCH_PARCEL)this.popup.clearContent(),this.popup.hide();else if(a.mode===netgis.Modes.VIEW){var b=this.config.info;this.popup.container!==a.overlay&&this.popup.attachTo(a.overlay);this.popup.clearContent();var c=0,d;for(d in this.queryLayers){var e=this.queryLayers[d];if(a.info&&a.info[d]){var f=a.info[d];b&&b.proxy&&0<b.proxy.length&&(f=b.proxy+f);netgis.util.request(f,this.onLayerResponseWMS.bind(this),{title:e.title});
|
||||
c+=1}else{if(!e.query_url||""===e.query_url)switch(e.type){case netgis.LayerTypes.WMS:case netgis.LayerTypes.WMST:f=e.url;var g=["SERVICE=WMS","VERSION=1.1.1","REQUEST=GetFeatureInfo","STYLES=","LAYERS="+window.encodeURIComponent(e.name),"QUERY_LAYERS="+window.encodeURIComponent(e.name),"BBOX="+a.view.bbox.join(","),"SRS="+a.view.projection,"WIDTH="+a.view.width,"HEIGHT="+a.view.height,"X="+Math.round(a.pixel[0]),"Y="+Math.round(a.pixel[1]),"INFO_FORMAT="+(b&&b.default_format?b.default_format:"text/plain")];
|
||||
f=f+(-1===f.indexOf("?")?"?":"")+g.join("&");b.proxy&&0<b.proxy.length&&(f=b.proxy+f);netgis.util.request(f,this.onLayerResponseWMS.bind(this),{title:e.title});c+=1}(f=e.query_url)&&""!==f&&(f=netgis.util.replace(f,"{bbox}",a.view.bbox.join(",")),f=netgis.util.replace(f,"{proj}",a.view.projection),f=netgis.util.replace(f,"{width}",a.view.width),f=netgis.util.replace(f,"{height}",a.view.height),f=netgis.util.replace(f,"{x}",a.coords[0]),f=netgis.util.replace(f,"{y}",a.coords[1]),f=netgis.util.replace(f,
|
||||
"{px}",a.pixel[0]),f=netgis.util.replace(f,"{py}",a.pixel[1]),f=netgis.util.replace(f,"{lon}",a.lon),f=netgis.util.replace(f,"{lat}",a.lat),b.proxy&&0<b.proxy.length&&(f=b.proxy+f),netgis.util.request(f,this.onLayerResponseWMS.bind(this),{title:e.title}),c+=1)}}0<c?(this.popup.showLoader(),this.popup.show()):this.popup.hide()}};
|
||||
f=f+(-1===f.indexOf("?")?"?":"")+g.join("&");b&&b.proxy&&0<b.proxy.length&&(f=b.proxy+f);netgis.util.request(f,this.onLayerResponseWMS.bind(this),{title:e.title});c+=1}(f=e.query_url)&&""!==f&&(f=netgis.util.replace(f,"{bbox}",a.view.bbox.join(",")),f=netgis.util.replace(f,"{proj}",a.view.projection),f=netgis.util.replace(f,"{width}",a.view.width),f=netgis.util.replace(f,"{height}",a.view.height),f=netgis.util.replace(f,"{x}",a.coords[0]),f=netgis.util.replace(f,"{y}",a.coords[1]),f=netgis.util.replace(f,
|
||||
"{px}",a.pixel[0]),f=netgis.util.replace(f,"{py}",a.pixel[1]),f=netgis.util.replace(f,"{lon}",a.lon),f=netgis.util.replace(f,"{lat}",a.lat),b&&b.proxy&&0<b.proxy.length&&(f=b.proxy+f),netgis.util.request(f,this.onLayerResponseWMS.bind(this),{title:e.title}),c+=1)}}0<c?(this.popup.showLoader(),this.popup.show()):this.popup.hide()}};
|
||||
netgis.Info.prototype.onMapFeatureClick=function(a){var b=a.detail,c=b.properties;if(b.mode===netgis.Modes.SEARCH_PARCEL)this.popup.clearContent(),this.popup.hide();else{a=null;var d=[],e="geometry fill fill-opacity stroke stroke-opacity stroke-width styleUrl".split(" ");for(g in c)if(!(-1<e.indexOf(g))){var f=c[g];d.push([g,f]);a||("name"===g&&""!==f?a=f:"title"===g&&""!==f?a=f:"id"===g&&f&&(a=f))}!a&&b.id&&(a=b.id);a=a?'Feature "'+a+'"':"Feature";"geolocation"===b.id&&((a=this.config.geolocation.marker_title)&&
|
||||
""!==a||(a="Geolocation"),d.push(["L\u00e4ngengrad (Lon.)",b.lon]),d.push(["Breitengrad (Lat.)",b.lat]));b=[];if(0<d.length){b.push("<table>");for(c=0;c<d.length;c++){f=d[c];var g=f[0];f=f[1];b.push("<tr class='netgis-hover-d'>");b.push("<th>"+g+"</th>");b.push("<td>"+f+"</td>");b.push("</tr>")}b.push("</table>")}else b.push("<i>Keine Eigenschaften vorhanden...</i>");b=b.join("");this.addSection(a,b,!1);!this.popup.isVisible()&&this.popup.show()}};
|
||||
netgis.Info.prototype.onLayerResponseWMS=function(a,b,c){b=b.title;if(c=c.getResponseHeader("Content-Type"))switch(c.split(";")[0]){case "text/plain":a="<pre>"+a+"</pre>"}this.popup.hideLoader();this.addSection(b,a,!1)};netgis=netgis||{};netgis.LayerID={EDITABLE:"editable-layer",NON_EDITABLE:"non-editable-layer"};netgis=netgis||{};netgis.LayerTree=function(a){this.config=a;this.importFolder=null;this.initElements(a);this.initFolders();this.initConfig(a)};netgis.LayerTree.Config={open:!1,title:"Layers",buttons:[]};netgis.LayerTree.Folders=[];
|
||||
netgis.Info.prototype.onLayerResponseWMS=function(a,b,c){b=b.title;if(c=c.getResponseHeader("Content-Type"))switch(c.split(";")[0]){case "text/plain":a="<pre>"+a+"</pre>"}this.popup.hideLoader();this.addSection(b,a,!1)};netgis=netgis||{};netgis.LayerID={EDITABLE:"editable-layer",NON_EDITABLE:"non-editable-layer"};netgis=netgis||{};netgis.LayerTree=function(a){this.config=a;this.importFolder=null;this.initElements(a);this.initFolders();this.initConfig(a)};netgis.LayerTree.Config={open:!1,title:"Layers",draggable:!1,buttons:[]};netgis.LayerTree.Folders=[];
|
||||
netgis.LayerTree.prototype.initElements=function(a){a=a.layertree;this.panel=new netgis.Panel("Layers");this.tree=new netgis.Tree(a.draggable);this.tree.attachTo(this.panel.content);this.tree.container.addEventListener(netgis.Events.TREE_ITEM_CHANGE,this.onTreeItemChange.bind(this));this.tree.container.addEventListener(netgis.Events.TREE_ITEM_SLIDER_CHANGE,this.onTreeItemSliderChange.bind(this));this.tree.container.addEventListener(netgis.Events.TREE_ITEM_ORDER_CHANGE,this.onTreeItemOrderChange.bind(this));
|
||||
!0===a.draggable&&(this.panel.content.addEventListener("dragover",this.onDragOver.bind(this)),this.panel.content.addEventListener("drop",this.onDragDrop.bind(this)))};
|
||||
netgis.LayerTree.prototype.initFolders=function(){this.editFolder=this.tree.addFolder(null,"edit-folder","Zeichnung",!0,!0);this.tree.addCheckbox(this.editFolder,netgis.LayerID.EDITABLE,"Editierbar");this.tree.setItemChecked(netgis.LayerID.EDITABLE,!0);this.tree.addCheckbox(this.editFolder,netgis.LayerID.NON_EDITABLE,"Nicht-Editierbar");this.tree.setItemChecked(netgis.LayerID.NON_EDITABLE,!0);this.editFolder.classList.add("netgis-hide")};
|
||||
netgis.LayerTree.prototype.initConfig=function(a,b){var c=a.layertree;c&&c.title&&this.panel.setTitle(c.title);var d=a.folders,e={};if(d){for(var f=0;f<d.length;f++){var g=d[f],h=this.tree.addFolder(null,g.id,g.title,b,!1,g.draggable);e[g.id]=h;!0===g.open&&this.tree.setFolderOpen(g.id,!0)}for(f=0;f<d.length;f++)g=d[f],h=g.id,g=g.parent,-1===g&&(g=null),""===g&&(g=null),g&&this.tree.setFolderParent(e[h],e[g])}if(b=a.layers)for(f=0;f<b.length;f++){var k=b[f];g=e[k.folder]?e[k.folder]:null;h=k.id?k.id:
|
||||
f.toString();var l=!1;if(g)for(var m=0;m<d.length;m++){var n=d[m];n.id===k.folder&&(l=n.radio)}m=k.title;n='<i class="fas fa-mouse-pointer" title="Ebene ist abfragbar"></i>';a.layertree&&a.layertree.query_icon&&(n=a.layertree.query_icon);(!0===k.query||k.query_url&&""!==k.query_url)&&n&&""!==n&&(m+='<span class="netgis-right">'+n+"</span>");h=!0===l?this.tree.addRadioButton(g,h,m,k.active,this.createDefaultDetails(k,!0,!1)):this.tree.addCheckbox(g,h,m,k.active,!1,this.createDefaultDetails(k,!0,!0));
|
||||
h.addEventListener("contextmenu",this.onTreeItemMenu.bind(this));!0===k.hidden&&h.classList.add("netgis-hide")}this.tree.updateFolderChecks();if(c&&c.buttons)for(a=a.layertree.buttons,f=0;f<a.length;f++)d=a[f],this.tree.addButton(null,d.id,d.title,this.onTreeButtonClick.bind(this));c&&!0===c.open&&this.panel.show()};
|
||||
f.toString();var l=!1;if(g)for(var m=0;m<d.length;m++){var n=d[m];n.id===k.folder&&(l=n.radio)}m=k.title;n='<i class="fas fa-mouse-pointer" title="Ebene ist abfragbar"></i>';a.layertree&&a.layertree.query_icon&&(n=a.layertree.query_icon);(!0===k.query||k.query_url&&""!==k.query_url)&&n&&""!==n&&(m+='<span class="netgis-right">'+n+"</span>");n=k.removable;h=!0===l?this.tree.addRadioButton(g,h,m,k.active,this.createDefaultDetails(k,!0,n)):this.tree.addCheckbox(g,h,m,k.active,!1,this.createDefaultDetails(k,
|
||||
!0,n));h.addEventListener("contextmenu",this.onTreeItemMenu.bind(this));!0===k.hidden&&h.classList.add("netgis-hide")}this.tree.updateFolderChecks();if(c&&c.buttons)for(a=a.layertree.buttons,f=0;f<a.length;f++)d=a[f],this.tree.addButton(null,d.id,d.title,this.onTreeButtonClick.bind(this));c&&!0===c.open&&this.panel.show()};
|
||||
netgis.LayerTree.prototype.attachTo=function(a){this.panel.attachTo(a);a.addEventListener(netgis.Events.CLIENT_CONTEXT_RESPONSE,this.onClientContextResponse.bind(this));a.addEventListener(netgis.Events.LAYERTREE_TOGGLE,this.onLayerTreeToggle.bind(this));a.addEventListener(netgis.Events.MAP_LAYER_CREATE,this.onMapLayerCreate.bind(this));a.addEventListener(netgis.Events.MAP_LAYER_TOGGLE,this.onMapLayerToggle.bind(this));a.addEventListener(netgis.Events.IMPORT_LAYER_ACCEPT,this.onImportLayerAccept.bind(this));
|
||||
a.addEventListener(netgis.Events.IMPORT_GEOPORTAL_SUBMIT,this.onImportGeoportalSubmit.bind(this));a.addEventListener(netgis.Events.CONTEXTMENU_SLIDER_CHANGE,this.onContextMenuSliderChange.bind(this));a.addEventListener(netgis.Events.MAP_EDIT_LAYER_LOADED,this.onMapEditLayerChange.bind(this));a.addEventListener(netgis.Events.MAP_EDIT_LAYER_CHANGE,this.onMapEditLayerChange.bind(this))};
|
||||
netgis.LayerTree.prototype.createDefaultDetails=function(a,b,c){var d=[];!0===b&&d.push({title:"<i class='netgis-icon fas fa-eye-slash'></i> Transparenz:",type:"slider",val:a.transparency?Math.round(100*a.transparency):0});!0===c&&d.push({title:"<i class='netgis-icon fas fa-times'></i> Entfernen",type:"button",callback:this.onTreeItemDeleteClick.bind(this)});return d};
|
||||
netgis.LayerTree.prototype.onTreeItemChange=function(a){var b=a.detail;netgis.util.invoke(a.target,netgis.Events.MAP_LAYER_TOGGLE,{id:b.id,on:b.checked})};netgis.LayerTree.prototype.onClientContextResponse=function(a){this.initConfig(a.detail.context.config,!0)};netgis.LayerTree.prototype.onLayerTreeToggle=function(a){this.panel.toggle()};netgis.LayerTree.prototype.onTreeButtonClick=function(a){a=a.currentTarget;var b=a.getAttribute("data-id");netgis.Client.handleCommand(a,b)};
|
||||
netgis.LayerTree.prototype.onMapLayerCreate=function(a){this.addLayerItem(a.detail,null)};netgis.LayerTree.prototype.onMapLayerToggle=function(a){a=a.detail;this.tree.setItemChecked(a.id,a.on,!0);this.tree.updateFolderChecks()};netgis.LayerTree.prototype.onImportLayerAccept=function(a){a=a.detail;this.importFolder||(this.importFolder=this.tree.addFolder(null,"_import","Import",!0,!1));this.addLayerItem(a,this.importFolder);this.tree.updateFolderChecks()};
|
||||
netgis.LayerTree.prototype.onMapLayerCreate=function(a){this.addLayerItem(a.detail,null)};netgis.LayerTree.prototype.onMapLayerToggle=function(a){a=a.detail;this.tree.setItemChecked(a.id,a.on,!0);this.tree.updateFolderChecks()};netgis.LayerTree.prototype.onImportLayerAccept=function(a){a=a.detail;!0!==a.editable&&(this.importFolder||(this.importFolder=this.tree.addFolder(null,"_import","Import",!0,!1)),this.addLayerItem(a,this.importFolder),this.tree.updateFolderChecks())};
|
||||
netgis.LayerTree.prototype.addLayerItem=function(a,b){var c=a.title,d='<i class="fas fa-mouse-pointer" title="Ebene ist abfragbar"></i>';config.layertree&&config.layertree.query_icon&&(d=config.layertree.query_icon);(!0===a.query||a.query_url&&""!==a.query_url)&&d&&""!==d&&(c+='<span class="netgis-right">'+d+"</span>");this.tree.addCheckbox(b,a.id,c,!0,!0,this.createDefaultDetails(a,!0,!0)).addEventListener("contextmenu",this.onTreeItemMenu.bind(this))};
|
||||
netgis.LayerTree.prototype.onImportGeoportalSubmit=function(a){a=a.detail;var b=a.folder.id,c=this.tree.getFolder(b);c||(c=this.tree.addFolder(null,b,a.folder.title,!0,!1));var d=a.layer.id;b={id:d,folder:b,title:a.layer.title,active:!0,type:netgis.LayerTypes.WMS,url:a.layer.url,name:a.layer.name,order:1E4,transparency:0};this.config.layers.push(b);this.tree.addCheckbox(c,d,a.layer.title,!1,!1,this.createDefaultDetails(b,!0,!0));this.tree.setItemChecked(d,!0,!1)};
|
||||
netgis.LayerTree.prototype.onTreeItemMenu=function(a){a.preventDefault();return!1};netgis.LayerTree.prototype.onContextMenuSliderChange=function(a){var b=a.detail;a=.01*b.val;var c=null;0===b.id.indexOf("layer_trans_")&&(c=b.id.split("layer_trans_")[1]);b=this.config.layers;for(var d=0;d<b.length;d++){var e=b[d];if(e.id===c){e.transparency=a;break}}netgis.util.invoke(this.tree.container,netgis.Events.MAP_LAYER_TRANSPARENCY,{id:c,transparency:a})};
|
||||
@@ -264,11 +262,11 @@ netgis.Map.prototype.gmlParseCoordinates=function(a,b){a=a.split(" ");for(var c=
|
||||
netgis.Map.prototype.createLayerGeoPackage=function(a){var b=new ol.layer.Vector({source:new ol.source.Vector({features:[]})}),c=this;a=new Uint8Array(a);window.GeoPackage.setSqljsWasmLocateFile(function(a){return c.config["import"].geopackage_lib+a});window.GeoPackage.GeoPackageAPI.open(a).then(function(a){for(var d=[],f=new ol.format.GeoJSON,g=a.getFeatureTables(),h=0;h<g.length;h++)for(var k=a.queryForGeoJSONFeaturesInTable(g[h]),l=0;l<k.length;l++){var m=f.readGeometry(k[l].geometry,{featureProjection:c.view.getProjection()});
|
||||
m=new ol.Feature({geometry:m});d.push(m)}b.getSource().addFeatures(d)});return b};
|
||||
netgis.Map.prototype.createLayerSpatialite=function(a){var b=new ol.layer.Vector({source:new ol.source.Vector({features:[]})}),c=this;window.initSqlJs().then(function(d){var e=[],f=new Uint8Array(a);d=new d.Database(f);var g=d.exec("SELECT name FROM sqlite_schema WHERE type = 'table' \n\t\t\t\t\tAND name NOT LIKE 'sqlite_%' \n\t\t\t\t\tAND name NOT LIKE 'sql_%' \n\t\t\t\t\tAND name NOT LIKE 'idx_%' \n\t\t\t\t\tAND name NOT LIKE 'spatial_ref_sys%' \n\t\t\t\t\tAND name NOT LIKE 'spatialite_%' \n\t\t\t\t\tAND name NOT LIKE 'geometry_columns%' \n\t\t\t\t\tAND name NOT LIKE 'views_%' \n\t\t\t\t\tAND name NOT LIKE 'virts_%' \n\t\t\t\t\tAND name NOT LIKE 'SpatialIndex' \n\t\t\t\t\tAND name NOT LIKE 'KNN%' \n\t\t\t\t\tAND name NOT LIKE 'ElementaryGeometries' \n\t\t\t\t;");f=
|
||||
g[0].values;for(var h=0;h<f.length;h++){g=d.exec("SELECT * FROM "+f[h][0]);var k=g[0];g=null;for(var l=0;l<k.columns.length;l++){if("geometry"===k.columns[l].toLowerCase()){g=l;break}if("geom"===k.columns[l].toLowerCase()){g=l;break}}if(null!==g)for(k=k.values,l=0;l<k.length;l++){var m=k[l][g],n=new Uint8Array(m.length-43-1+5);n[0]=m[1];n[1]=m[39];n[2]=m[40];n[3]=m[41];n[4]=m[42];for(var p=m.length-43-1,q=0;q<p;q++)n[5+q]=m[43+q];m=(new ol.format.WKB).readGeometry(n,{featureProjection:c.view.getProjection()});
|
||||
g[0].values;for(var h=0;h<f.length;h++){g=d.exec("SELECT * FROM "+f[h][0]);var k=g[0];g=null;for(var l=0;l<k.columns.length;l++){if("geometry"===k.columns[l].toLowerCase()){g=l;break}if("geom"===k.columns[l].toLowerCase()){g=l;break}}if(null!==g)for(k=k.values,l=0;l<k.length;l++){var m=k[l][g],n=new Uint8Array(m.length-43-1+5);n[0]=m[1];n[1]=m[39];n[2]=m[40];n[3]=m[41];n[4]=m[42];for(var q=m.length-43-1,p=0;p<q;p++)n[5+p]=m[43+p];m=(new ol.format.WKB).readGeometry(n,{featureProjection:c.view.getProjection()});
|
||||
e.push(new ol.Feature({geometry:m}))}}b.getSource().addFeatures(e)});return b};netgis.Map.prototype.createLayerShapefile=function(a){var b=new ol.layer.Vector({source:new ol.source.Vector({features:[]})}),c=this;shp(a).then(function(a){var d=new ol.format.GeoJSON;d.readProjection(a);a=d.readFeatures(a,{featureProjection:c.view.getProjection()});b.getSource().addFeatures(a)});return b};
|
||||
netgis.Map.prototype.createLayerWKT=function(a){for(var b=new ol.format.WKT,c=[],d=0;d<a.length;d++){var e=a[d],f=b.readGeometry(e.geometry),g=e.properties;g.geometry=f;g.wkt=e.geometry;f=new ol.Feature(g);f.setId(e.id);c.push(f)}return new ol.layer.Vector({source:new ol.source.Vector({features:c})})};
|
||||
netgis.Map.prototype.createLayerWFS=function(a,b,c,d,e,f){"?"!==a[a.length-1]&&(a+="?");a+="service=WFS&version=1.1.0&request=GetFeature";c||(c=this.view.getProjection().getCode());d=d?netgis.util.replace(d," ","+"):"application/json";var g=new ol.source.Vector({format:new ol.format.GeoJSON,strategy:ol.loadingstrategy.bbox,loader:function(h,k,n,p,q){h=a+"&typename="+b+"&srsname="+c+"&bbox="+h.join(",")+","+c+"&outputFormat="+d;var l=new XMLHttpRequest;l.open("GET",h);e&&f&&l.setRequestHeader("Authorization",
|
||||
"Basic "+window.btoa(e+":"+f));l.onerror=function(){console.error("WFS request error");q()};l.onload=function(){if(200===l.status){g.clear();var a=g.getFormat().readFeatures(l.responseText);g.addFeatures(a);p(a)}else console.error("WFS request status",l.status),q()};l.send()}}),h=new ol.layer.Vector({source:g}),k=this;g.on("featuresloadstart",function(a){k.removeSnapLayer(h)});g.on("featuresloadend",function(a){window.setTimeout(function(){k.addSnapLayer(h)},10)});return h};
|
||||
netgis.Map.prototype.createLayerWFS=function(a,b,c,d,e,f){"?"!==a[a.length-1]&&(a+="?");a+="service=WFS&version=1.1.0&request=GetFeature";c||(c=this.view.getProjection().getCode());d=d?netgis.util.replace(d," ","+"):"application/json";var g=new ol.source.Vector({format:new ol.format.GeoJSON,strategy:ol.loadingstrategy.bbox,loader:function(h,k,n,q,p){h=a+"&typename="+b+"&srsname="+c+"&bbox="+h.join(",")+","+c+"&outputFormat="+d;var l=new XMLHttpRequest;l.open("GET",h);e&&f&&l.setRequestHeader("Authorization",
|
||||
"Basic "+window.btoa(e+":"+f));l.onerror=function(){console.error("WFS request error");p()};l.onload=function(){if(200===l.status){g.clear();var a=g.getFormat().readFeatures(l.responseText);g.addFeatures(a);q(a)}else console.error("WFS request status",l.status),p()};l.send()}}),h=new ol.layer.Vector({source:g}),k=this;g.on("featuresloadstart",function(a){k.removeSnapLayer(h)});g.on("featuresloadend",function(a){window.setTimeout(function(){k.addSnapLayer(h)},10)});return h};
|
||||
netgis.Map.prototype.createLayerVectorTiles=function(a,b,c,d){return new ol.layer.VectorTile({extent:b,source:new ol.source.VectorTile({format:new ol.format.MVT,overlaps:!0,url:a,minZoom:c,maxZoom:d})})};
|
||||
netgis.Map.prototype.createLayerKML=function(a){var b=new ol.layer.Vector({source:new ol.source.Vector({features:[]})}),c=this;netgis.util.request(a,function(a){a=(new ol.format.KML).readFeatures(a,{featureProjection:c.view.getProjection()});for(var d=0;d<a.length;d++){var f=a[d],g=f.getProperties(),h={fill:"rgba( 127, 127, 127, 0.5 )",stroke:"rgba( 127, 127, 127, 1.0 )",radius:5,width:3},k;for(k in g){var l=g[k];switch(k){case "fill":h.fill=l;break;case "fill-opacity":h["fill-opacity"]=l;break;case "stroke":h.stroke=
|
||||
l;break;case "stroke-opacity":h["stroke-opacity"]=l;break;case "stroke-width":h.width=l}}h["fill-opacity"]&&(g=netgis.util.hexToRGB(h.fill),g="rgba("+g.join(",")+","+h["fill-opacity"]+")",h.fill=g);h["stroke-opacity"]&&(g=netgis.util.hexToRGB(h.stroke),g="rgba("+g.join(",")+","+h["stroke-opacity"]+")",h.stroke=g);h=new ol.style.Style({image:new ol.style.Circle({radius:h.radius,fill:new ol.style.Fill({color:h.stroke})}),fill:new ol.style.Fill({color:h.fill}),stroke:new ol.style.Stroke({color:h.stroke,
|
||||
@@ -287,10 +285,10 @@ netgis.Map.prototype.zoomFeature=function(a,b){a=this.layers[a].getSource().getF
|
||||
netgis.Map.prototype.addViewHistory=function(a,b){if(0<this.viewHistory.length){var c=this.viewHistory[this.viewHistory.length-1],d=!0;10<Math.abs(a[0]-c.center[0])&&(d=!1);10<Math.abs(a[1]-c.center[1])&&(d=!1);.1<Math.abs(b-c.zoom)&&(d=!1);if(!0===d)return}this.viewHistory.push({center:a,zoom:b});this.viewHistory.length>this.viewHistoryMax&&this.viewHistory.shift();this.viewIndex=this.viewHistory.length-1};
|
||||
netgis.Map.prototype.gotoViewHistory=function(a){if(!(1>this.viewHistory.length)){var b=this.viewHistory.length-1;0>a&&(a=b);a>b&&(a=0);a!==this.viewIndex&&(b=this.viewHistory[a],this.viewIndex=a,this.viewFromHistory=!0,this.view.setCenter(b.center),this.view.setZoom(b.zoom))}};netgis.Map.prototype.setPadding=function(a,b,c,d){var e=this.paddingBuffer;this.view.padding=[a+e,b+e,c+e,d+e]};
|
||||
netgis.Map.prototype.exportImage=function(a,b,c,d,e){var f=this,g=this.container,h=this.map,k=this.config["export"],l=new Image;l.onload=function(){var m=document.createElement("div");m.style.position="fixed";m.style.top="0px";m.style.left="0px";m.style.width=b+"px";m.style.height=c+"px";m.style.background="white";m.style.zIndex=-1;m.style.opacity=0;m.style.pointerEvents="none";g.appendChild(m);h.setTarget(m);h.once("rendercomplete",function(){var n=document.createElement("canvas");n.width=b;n.height=
|
||||
c;var p=n.getContext("2d");p.webkitImageSmoothingEnabled=!1;p.mozImageSmoothingEnabled=!1;p.imageSmoothingEnabled=!1;Array.prototype.forEach.call(document.querySelectorAll(".ol-layer canvas"),function(a){if(0<a.width){var b=a.parentNode.style.opacity;p.globalAlpha=""===b?1:Number(b);b=a.style.transform.match(/^matrix\(([^\(]*)\)$/)[1].split(",").map(Number);CanvasRenderingContext2D.prototype.setTransform.apply(p,b);p.drawImage(a,0,0)}});p.drawImage(l,0,0);p.fillStyle="#fff";p.fillRect(0,n.height-
|
||||
30,140,30);p.fillStyle="#000";p.font="4mm sans-serif";p.fillText(netgis.util.getTimeStamp(),10,n.height-10);var q=document.createElement("a");switch(a){case "pdf":e=e?e:0;var r=297-e-e,t=210-e-e,u=n.width/n.height;if(!d){var v=r;r=t;t=v}if(n.height>n.width){var w=t;v=w*u;v>r&&(v=r,w=v/u)}else v=r,w=v/u,w>t&&(w=t,v=w*u);u=new jsPDF(d?"l":"p");var x=e;x+=(r-v)/2;r=e;r+=(t-w)/2;u.addImage(n.toDataURL("image/png,1.0",1),"PNG",x,r,v,w);u.setFillColor(255,255,255);u.rect(x,r+w-11,80,11,"F");u.setFontSize(8);
|
||||
u.text("Datum: "+netgis.util.getTimeStamp(),x+2,r+w-2-4);u.text("Quelle: "+window.location.href,x+2,r+w-2);n=u.output("bloburl",{filename:k.default_filename+".pdf"});window.open(n,"_blank");break;case "jpeg":window.navigator.msSaveBlob?window.navigator.msSaveBlob(n.msToBlob(),k.default_filename+".jpg"):(q.setAttribute("download",k.default_filename+".jpg"),q.setAttribute("href",n.toDataURL("image/jpeg",1)),q.click());break;case "png":window.navigator.msSaveBlob?window.navigator.msSaveBlob(n.msToBlob(),
|
||||
k.default_filename+".png"):(q.setAttribute("download",k.default_filename+".png"),q.setAttribute("href",n.toDataURL("image/png",1)),q.click());break;case "gif":q.setAttribute("download",k.default_filename+".gif"),t=new GIF({workerScript:k.gif_worker,quality:1}),t.addFrame(n),t.on("finished",function(a){q.setAttribute("href",window.URL.createObjectURL(a));q.click()}),t.render()}h.setTarget(g);g.removeChild(m);netgis.util.invoke(f.container,netgis.Events.EXPORT_END,null)});h.renderSync()};l.src=k.logo};
|
||||
c;var q=n.getContext("2d");q.webkitImageSmoothingEnabled=!1;q.mozImageSmoothingEnabled=!1;q.imageSmoothingEnabled=!1;Array.prototype.forEach.call(document.querySelectorAll(".ol-layer canvas"),function(a){if(0<a.width){var b=a.parentNode.style.opacity;q.globalAlpha=""===b?1:Number(b);b=a.style.transform.match(/^matrix\(([^\(]*)\)$/)[1].split(",").map(Number);CanvasRenderingContext2D.prototype.setTransform.apply(q,b);q.drawImage(a,0,0)}});q.drawImage(l,0,0);q.fillStyle="#fff";q.fillRect(0,n.height-
|
||||
30,140,30);q.fillStyle="#000";q.font="4mm sans-serif";q.fillText(netgis.util.getTimeStamp(),10,n.height-10);var p=document.createElement("a");switch(a){case "pdf":e=e?e:0;var r=297-e-e,v=210-e-e,t=n.width/n.height;if(!d){var w=r;r=v;v=w}if(n.height>n.width){var u=v;w=u*t;w>r&&(w=r,u=w/t)}else w=r,u=w/t,u>v&&(u=v,w=u*t);t=new jsPDF(d?"l":"p");var x=e;x+=(r-w)/2;r=e;r+=(v-u)/2;t.addImage(n.toDataURL("image/png,1.0",1),"PNG",x,r,w,u);t.setFillColor(255,255,255);t.rect(x,r+u-11,80,11,"F");t.setFontSize(8);
|
||||
t.text("Datum: "+netgis.util.getTimeStamp(),x+2,r+u-2-4);t.text("Quelle: "+window.location.href,x+2,r+u-2);n=t.output("bloburl",{filename:k.default_filename+".pdf"});window.open(n,"_blank");break;case "jpeg":window.navigator.msSaveBlob?window.navigator.msSaveBlob(n.msToBlob(),k.default_filename+".jpg"):(p.setAttribute("download",k.default_filename+".jpg"),p.setAttribute("href",n.toDataURL("image/jpeg",1)),p.click());break;case "png":window.navigator.msSaveBlob?window.navigator.msSaveBlob(n.msToBlob(),
|
||||
k.default_filename+".png"):(p.setAttribute("download",k.default_filename+".png"),p.setAttribute("href",n.toDataURL("image/png",1)),p.click());break;case "gif":p.setAttribute("download",k.default_filename+".gif"),v=new GIF({workerScript:k.gif_worker,quality:1}),v.addFrame(n),v.on("finished",function(a){p.setAttribute("href",window.URL.createObjectURL(a));p.click()}),v.render()}h.setTarget(g);g.removeChild(m);netgis.util.invoke(f.container,netgis.Events.EXPORT_END,null)});h.renderSync()};l.src=k.logo};
|
||||
netgis.Map.prototype.exportFeatures=function(a){var b=this.editLayer.getSource().getFeatures();!0===a&&(a=this.nonEditLayer.getSource().getFeatures(),b=b.concat(a));b=(new ol.format.GeoJSON).writeFeaturesObject(b,{featureProjection:this.view.getProjection(),dataProjection:"EPSG:4326"});a=this.config["export"].default_filename+".geojson";b.name=a;netgis.util.downloadJSON(b,a);netgis.util.invoke(this.container,netgis.Events.EXPORT_END,null)};netgis.Map.prototype.onClientContextResponse=function(a){this.initConfig(a.detail.context.config)};
|
||||
netgis.Map.prototype.onEditLayerLoaded=function(a){a=a.detail.geojson;var b=new ol.format.GeoJSON;b.readProjection(a);a=b.readFeatures(a,{featureProjection:this.view.getProjection().getCode()});var c=this,d=a.slice();window.setTimeout(function(){c.zoomFeatures(d)},10);b=[];for(var e=0;e<a.length;e++){var f=a[e];!0===f.getProperties().editable&&b.push(f)}for(e=0;e<b.length;e++)a.splice(a.indexOf(b[e]),1);this.editEventsSilent=!0;this.editLayer.getSource().addFeatures(b);this.nonEditLayer.getSource().addFeatures(a);
|
||||
this.editEventsSilent=!1};netgis.Map.prototype.onClientSetMode=function(a){this.setMode(a.detail.mode)};netgis.Map.prototype.onPanelResize=function(a){this.setPadding(0,0,0,a.detail.width);this.redrawVectorLayers()};
|
||||
@@ -307,7 +305,8 @@ d,b,a)};netgis.Map.prototype.onPointerLeave=function(a){this.hoverFeature&&(this
|
||||
netgis.Map.prototype.onPointerClick=function(a){var b=a.pixel;a=a.coordinate;this.popupOverlay.setPosition(a);var c={resolution:this.view.getResolution(),projection:this.view.getProjection().getCode(),bbox:this.view.calculateExtent(this.map.getSize()),width:this.map.getSize()[0],height:this.map.getSize()[1]},d=ol.proj.toLonLat(a,this.view.getProjection()),e={};for(g in this.layers){var f=this.layers[g].getSource();f.getFeatureInfoUrl&&(e[g]=f.getFeatureInfoUrl(a,c.resolution,c.projection,{INFO_FORMAT:"text/html"}))}var g=
|
||||
{mode:this.mode,pixel:b,coords:a,lon:d[0],lat:d[1],overlay:this.popupOverlay.getElement(),view:c,info:e};this.mode===netgis.Modes.VIEW&&netgis.util.invoke(this.container,netgis.Events.MAP_CLICK,g);var h=[],k=this;this.map.forEachFeatureAtPixel(b,function(a,b){b&&b!==k.nonEditLayer&&b!==k.boundsLayer&&b!==k.measureLayer&&b!==k.previewLayer&&(-1<k.sketchFeatures.indexOf(a)||h.push({feature:a,layer:b}))});g=!0;this.mode===netgis.Modes.VIEW&&(g=!1);this.mode===netgis.Modes.MEASURE_LINE&&(g=!1);this.mode===
|
||||
netgis.Modes.MEASURE_AREA&&(g=!1);this.mode===netgis.Modes.DRAW_POINTS&&(g=!1);this.mode===netgis.Modes.DRAW_LINES&&(g=!1);this.mode===netgis.Modes.DRAW_POLYGONS&&(g=!1);this.mode===netgis.Modes.CUT_FEATURES_DRAW&&(g=!1);g&&(0<h.length&&!1===this.selectMultiple&&(this.selectedFeatures=[]),0===h.length&&!1===this.selectMultiple&&(this.selectedFeatures=[]),!0===this.selectReset&&(this.selectedFeatures=[],this.selectReset=!1),this.mode===netgis.Modes.BUFFER_FEATURES_DYNAMIC&&this.updateBufferFeaturesSketch(this.bufferFeaturesRadius,
|
||||
this.bufferFeaturesSegments));for(c=0;c<h.length;c++)d=h[c],g&&(e=this.selectedFeatures.indexOf(d.feature),-1<e?this.selectedFeatures.splice(e,1):this.selectedFeatures.push(d.feature)),this.onFeatureClick(d.feature,d.layer,b,a);this.redrawVectorLayers()};netgis.Map.prototype.onContainerClick=function(a){if(2===a.detail)this.onDoubleClick(a)};
|
||||
this.bufferFeaturesSegments));for(c=0;c<h.length;c++)if(d=h[c],g&&(e=this.selectedFeatures.indexOf(d.feature),-1<e?this.selectedFeatures.splice(e,1):this.selectedFeatures.push(d.feature)),e=!1,this.mode===netgis.Modes.VIEW&&(e=!0),this.mode===netgis.Modes.DELETE_FEATURES&&(e=!0),this.mode===netgis.Modes.BUFFER_FEATURES_DYNAMIC&&(e=!0),this.mode===netgis.Modes.CUT_FEATURES&&(e=!0),this.mode===netgis.Modes.SEARCH_PARCEL&&(e=!0),e)this.onFeatureClick(d.feature,d.layer,b,a);this.redrawVectorLayers()};
|
||||
netgis.Map.prototype.onContainerClick=function(a){if(2===a.detail)this.onDoubleClick(a)};
|
||||
netgis.Map.prototype.onDoubleClick=function(a){switch(this.mode){case netgis.Modes.MEASURE_LINE:this.interactions[netgis.Modes.MEASURE_LINE]&&this.interactions[netgis.Modes.MEASURE_LINE][2].finishDrawing();break;case netgis.Modes.MEASURE_AREA:this.interactions[netgis.Modes.MEASURE_AREA]&&this.interactions[netgis.Modes.MEASURE_AREA][2].finishDrawing();break;case netgis.Modes.DRAW_LINES:this.interactions[netgis.Modes.DRAW_LINES]&&this.interactions[netgis.Modes.DRAW_LINES][0].finishDrawing();break;case netgis.Modes.DRAW_POLYGONS:this.interactions[netgis.Modes.DRAW_POLYGONS]&&
|
||||
this.interactions[netgis.Modes.DRAW_POLYGONS][0].finishDrawing();break;case netgis.Modes.CUT_FEATURES_DRAW:this.interactions[netgis.Modes.CUT_FEATURES_DRAW]&&this.interactions[netgis.Modes.CUT_FEATURES_DRAW][0].finishDrawing()}};
|
||||
netgis.Map.prototype.onRightClick=function(a){switch(this.mode){case netgis.Modes.MEASURE_LINE:this.interactions[netgis.Modes.MEASURE_LINE]&&this.interactions[netgis.Modes.MEASURE_LINE][2].finishDrawing();break;case netgis.Modes.MEASURE_AREA:this.interactions[netgis.Modes.MEASURE_AREA]&&this.interactions[netgis.Modes.MEASURE_AREA][2].finishDrawing();break;case netgis.Modes.DRAW_LINES:this.interactions[netgis.Modes.DRAW_LINES]&&this.interactions[netgis.Modes.DRAW_LINES][0].finishDrawing();break;case netgis.Modes.DRAW_POLYGONS:this.interactions[netgis.Modes.DRAW_POLYGONS]&&
|
||||
@@ -319,9 +318,9 @@ netgis.Map.prototype.onKeyUp=function(a){a=a.keyCode||a.which;switch(this.mode){
|
||||
!1,!0===this.config.tools.select_multi_reset&&(this.selectReset=!0))};
|
||||
netgis.Map.prototype.onFeatureEnter=function(a,b,c,d){if(b){switch(this.mode){case netgis.Modes.VIEW:this.container.classList.add("netgis-clickable");break;case netgis.Modes.DELETE_FEATURES:case netgis.Modes.BUFFER_FEATURES:case netgis.Modes.BUFFER_FEATURES_DYNAMIC:case netgis.Modes.CUT_FEATURES:this.container.classList.add("netgis-clickable");a.setStyle(this.styleHover.bind(this));break;case netgis.Modes.SEARCH_PARCEL:this.container.classList.add("netgis-clickable"),a.setStyle(this.styleHover.bind(this))}netgis.util.invoke(this.container,
|
||||
netgis.Events.MAP_FEATURE_ENTER,{pixel:c,coords:d,layer:b.get("id"),properties:a.getProperties()})}};netgis.Map.prototype.onFeatureHover=function(a,b,c,d){};
|
||||
netgis.Map.prototype.onFeatureClick=function(a,b,c,d){var e=ol.proj.toLonLat(d,this.view.getProjection());c={pixel:c,coords:d,lon:e[0],lat:e[1],overlay:this.popupOverlay.getElement(),layer:b.get("id"),id:a.getId(),properties:a.getProperties(),mode:this.mode};netgis.util.invoke(this.container,netgis.Events.MAP_FEATURE_CLICK,c);switch(this.mode){case netgis.Modes.DELETE_FEATURES:b.getSource().removeFeature(a);this.onFeatureLeave(a,b);netgis.util.invoke(this.container,netgis.Events.CLIENT_SET_MODE,{mode:netgis.Modes.VIEW});
|
||||
break;case netgis.Modes.BUFFER_FEATURES:case netgis.Modes.BUFFER_FEATURES_EDIT:this.onFeatureLeave(a,b);this.selectMultiple?netgis.util.invoke(this.container,netgis.Events.CLIENT_SET_MODE,{mode:netgis.Modes.BUFFER_FEATURES}):netgis.util.invoke(this.container,netgis.Events.CLIENT_SET_MODE,{mode:netgis.Modes.BUFFER_FEATURES_EDIT});break;case netgis.Modes.BUFFER_FEATURES_DYNAMIC:this.updateBufferFeaturesSketch(this.bufferFeaturesRadius,this.bufferFeaturesSegments);break;case netgis.Modes.CUT_FEATURES:if(a.getGeometry()instanceof
|
||||
ol.geom.Point)this.onFeatureLeave(a,b);else this.selectMultiple||netgis.util.invoke(this.container,netgis.Events.CLIENT_SET_MODE,{mode:netgis.Modes.CUT_FEATURES_DRAW})}};
|
||||
netgis.Map.prototype.onFeatureClick=function(a,b,c,d){if(this.mode!==netgis.Modes.SEARCH_PARCEL||"searchparcel_districts"===b.get("id")||"searchparcel_fields"===b.get("id")||"searchparcel_parcels"===b.get("id")){var e=ol.proj.toLonLat(d,this.view.getProjection());c={pixel:c,coords:d,lon:e[0],lat:e[1],overlay:this.popupOverlay.getElement(),layer:b.get("id"),id:a.getId(),properties:a.getProperties(),mode:this.mode};netgis.util.invoke(this.container,netgis.Events.MAP_FEATURE_CLICK,c);switch(this.mode){case netgis.Modes.DELETE_FEATURES:b.getSource().removeFeature(a);
|
||||
this.onFeatureLeave(a,b);netgis.util.invoke(this.container,netgis.Events.CLIENT_SET_MODE,{mode:netgis.Modes.VIEW});break;case netgis.Modes.BUFFER_FEATURES:case netgis.Modes.BUFFER_FEATURES_EDIT:this.onFeatureLeave(a,b);this.selectMultiple?netgis.util.invoke(this.container,netgis.Events.CLIENT_SET_MODE,{mode:netgis.Modes.BUFFER_FEATURES}):netgis.util.invoke(this.container,netgis.Events.CLIENT_SET_MODE,{mode:netgis.Modes.BUFFER_FEATURES_EDIT});break;case netgis.Modes.BUFFER_FEATURES_DYNAMIC:this.updateBufferFeaturesSketch(this.bufferFeaturesRadius,
|
||||
this.bufferFeaturesSegments);break;case netgis.Modes.CUT_FEATURES:if(a.getGeometry()instanceof ol.geom.Point)this.onFeatureLeave(a,b);else this.selectMultiple||netgis.util.invoke(this.container,netgis.Events.CLIENT_SET_MODE,{mode:netgis.Modes.CUT_FEATURES_DRAW})}}};
|
||||
netgis.Map.prototype.onFeatureLeave=function(a,b,c,d){netgis.util.invoke(this.container,netgis.Events.MAP_FEATURE_LEAVE,{pixel:c,coords:d,layer:b?b.get("id"):null,properties:a.getProperties()});switch(this.mode){case netgis.Modes.DELETE_FEATURES:case netgis.Modes.BUFFER_FEATURES:case netgis.Modes.BUFFER_FEATURES_DYNAMIC:case netgis.Modes.CUT_FEATURES:case netgis.Modes.CUT_FEATURES_DRAW:this.container.classList.remove("netgis-clickable");a.setStyle(null);break;case netgis.Modes.SEARCH_PARCEL:this.container.classList.remove("netgis-clickable"),
|
||||
a.setStyle(null)}};netgis.Map.prototype.onEditLayerAdd=function(a){this.editEventsSilent||this.updateEditOutput();this.snapFeatures.push(a.feature)};netgis.Map.prototype.onEditLayerRemove=function(a){this.editEventsSilent||this.updateEditOutput();this.snapFeatures.remove(a.feature)};netgis.Map.prototype.onEditLayerChange=function(a){this.editEventsSilent||this.updateEditOutput()};
|
||||
netgis.Map.prototype.onCopyFeatureToEdit=function(a){a=a.detail;var b=this.layers[a.source].getSource().getFeatureById(a.id);b?this.editLayer.getSource().getFeatureById(a.id)||(b.setStyle(void 0),this.selectedFeatures=[],this.editLayer.getSource().addFeature(b)):console.error("feature to copy not found",a)};netgis.Map.prototype.onGeolocToggleActive=function(a){a.detail.on?this.geolocLayer.setVisible(!0):this.geolocLayer.setVisible(!1)};
|
||||
@@ -331,14 +330,15 @@ d.intersects(g)&&(d=d.intersection(g))}c=c.write(d);a.setGeometry(c)}var h=this.
|
||||
netgis.Map.prototype.onDrawBufferChange=function(a){a=a.detail;this.drawBufferRadius=a.radius;this.drawBufferSegments=a.segments;this.updateDrawBufferPreview()};netgis.Map.prototype.onBufferChange=function(a){a=a.detail;this.updateBufferFeaturesSketch(a.radius,a.segments);this.bufferFeaturesRadius=a.radius;this.bufferFeaturesSegments=a.segments};
|
||||
netgis.Map.prototype.updateBufferFeaturesSketch=function(a,b){var c=this.selectedFeatures,d=this.editLayer.getSource();this.clearSketchFeatures();for(var e=0;e<c.length;e++){var f=this.createBufferFeature(this.selectedFeatures[e].getGeometry(),a,b);d.addFeature(f);this.sketchFeatures.push(f)}};netgis.Map.prototype.onBufferAccept=function(a){a=this.selectedFeatures;for(var b=this.editLayer.getSource(),c=0;c<a.length;c++)b.removeFeature(a[c]);this.sketchFeatures=[];this.selectedFeatures=[]};
|
||||
netgis.Map.prototype.onCutFeaturesDrawEnd=function(a){a=a.feature;for(var b=0;b<this.selectedFeatures.length;b++){var c=this.selectedFeatures[b];if(c)if(this.onFeatureLeave(c,null),c.getGeometry()instanceof ol.geom.Point)console.error("trying to cut a point feature",c);else{var d=new jsts.io.OL3Parser,e=d.read(c.getGeometry()),f=d.read(a.getGeometry());e=e.difference(f);d=d.write(e);d=new ol.Feature({geometry:d});e=this.editLayer.getSource();e.removeFeature(c);e.addFeature(d)}}this.selectedFeatures=
|
||||
[];this.editEventsSilent=!0;this.splitMultiPolygons(this.editLayer);this.editEventsSilent=!1;this.updateEditOutput();netgis.util.invoke(this.container,netgis.Events.CLIENT_SET_MODE,{mode:netgis.Modes.VIEW})};netgis.Map.prototype.onImportLayerAccept=function(a){a=a.detail;a=this.addLayer(a.id,a);var b=a.getSource();b instanceof ol.source.Vector&&0<b.getFeatures().length&&this.view.fit(a.getSource().getExtent(),{duration:600})};netgis.Map.prototype.onImportGeoportalSubmit=function(a){};
|
||||
[];this.editEventsSilent=!0;this.splitMultiPolygons(this.editLayer);this.editEventsSilent=!1;this.updateEditOutput();netgis.util.invoke(this.container,netgis.Events.CLIENT_SET_MODE,{mode:netgis.Modes.VIEW})};
|
||||
netgis.Map.prototype.onImportLayerAccept=function(a){a=a.detail;a.editable?(a=this.createLayerGeoJSON(a.data),a=a.getSource(),this.editLayer.getSource().addFeatures(a.getFeatures())):(a=this.addLayer(a.id,a),a=a.getSource());a instanceof ol.source.Vector&&0<a.getFeatures().length&&this.view.fit(a.getExtent(),{duration:600})};netgis.Map.prototype.onImportGeoportalSubmit=function(a){};
|
||||
netgis.Map.prototype.onImportLayerPreview=function(a){a=a.detail;var b=this.createLayer(a),c=this.view.getProjection().getCode();netgis.util.invoke(this.container,netgis.Events.IMPORT_LAYER_PREVIEW_FEATURES,{id:a.id,title:a.title,layer:b,proj:c})};netgis.Map.prototype.onSearchParcelReset=function(a){(a=this.config.searchparcel.districts_service.min_zoom)&&this.view.setZoom(a)};netgis.Map.prototype.onSearchParcelItemEnter=function(a){a=a.detail.id;this.layers.searchparcel_parcels.getSource().getFeatureById(a).setStyle(this.styleHover.bind(this))};
|
||||
netgis.Map.prototype.onSearchParcelItemLeave=function(a){a=a.detail.id;this.layers.searchparcel_parcels.getSource().getFeatureById(a).setStyle(null)};netgis.Map.prototype.onSearchParcelItemClick=function(a){this.zoomFeature("searchparcel_parcels",a.detail.id)};netgis.Map.prototype.onSearchParcelItemImport=function(a){};netgis.Map.prototype.onDrawPointsUpdateGeom=function(a,b,c){b?b.setCoordinates(a):b=new ol.geom.Point(a);return b};
|
||||
netgis.Map.prototype.onDrawLinesUpdateGeom=function(a,b,c){b?b.setCoordinates(a):b=new ol.geom.LineString(a);this.drawError=!this.isGeomInsideLayer(this.boundsLayer,b);return b};
|
||||
netgis.Map.prototype.onDrawPolygonsUpdateGeom=function(a,b,c){b?(a=[a[0].concat([a[0][0]])],b.setCoordinates(a)):b=new ol.geom.Polygon(a);c=!0;if(4>a[0].length)for(var d=0;d<a[0].length;d++){if(!this.isPointInsideLayer(this.boundsLayer,a[0][d])){c=!1;break}}else c=this.isGeomInsideLayer(this.boundsLayer,b);this.drawError=!c;return b};
|
||||
netgis.Map.prototype.onDrawPointsEnd=function(a){if(this.boundsLayer){var b=a.feature,c=this.editLayer;this.isPointInsideLayer(this.boundsLayer,b.getGeometry().getCoordinates())||window.setTimeout(function(){c.getSource().removeFeature(b)},10)}};netgis.Map.prototype.onDrawLinesEnd=function(a){if(this.boundsLayer){var b=a.feature,c=this.editLayer;this.isGeomInsideLayer(this.boundsLayer,b.getGeometry())||window.setTimeout(function(){c.getSource().removeFeature(b)},10)}};
|
||||
netgis.Map.prototype.onDrawPolygonsEnd=function(a){if(this.boundsLayer){var b=a.feature,c=this.editLayer;this.isGeomInsideLayer(this.boundsLayer,b.getGeometry())||window.setTimeout(function(){c.getSource().removeFeature(b)},10)}};netgis.Map.prototype.onExportBegin=function(a){a=a.detail;switch(a.format){case "geojson":this.exportFeatures(a.nonEdits);break;default:this.exportImage(a.format,a.width,a.height,a.landscape,a.padding)}};
|
||||
netgis.Map.prototype.onScalebarSelectChange=function(a){netgis.util.invoke(this.scalebarSelect,netgis.Events.MAP_ZOOM_SCALE,{scale:this.scalebarSelect.value,anim:!0})};netgis.Map.prototype.onTimeSliderShow=function(a){};netgis.Map.prototype.onTimeSliderHide=function(a){};netgis.Map.prototype.onTimeSliderSelect=function(a){a=a.detail;console.info("Time Slider Select:",a);this.layers[a.layer].getSource().updateParams({TIME:a.time})};netgis=netgis||{};netgis.Menu=function(a){this.config=a;this.initElements();this.initConfig(a)};netgis.Menu.Config={header:"<a href='.' target='_self'>NetGIS Client</a>",items:[],compact:!0};
|
||||
netgis.Map.prototype.onScalebarSelectChange=function(a){netgis.util.invoke(this.scalebarSelect,netgis.Events.MAP_ZOOM_SCALE,{scale:this.scalebarSelect.value,anim:!0})};netgis.Map.prototype.onTimeSliderShow=function(a){};netgis.Map.prototype.onTimeSliderHide=function(a){};netgis.Map.prototype.onTimeSliderSelect=function(a){a=a.detail;this.layers[a.layer].getSource().updateParams({TIME:a.time})};netgis=netgis||{};netgis.Menu=function(a){this.config=a;this.initElements();this.initConfig(a)};netgis.Menu.Config={header:"<a href='.' target='_self'>NetGIS Client</a>",items:[],compact:!0};
|
||||
netgis.Menu.prototype.initElements=function(){this.container=document.createElement("nav");this.container.className="netgis-menu netgis-noselect netgis-color-a netgis-gradient-a netgis-shadow-large";this.toggle=document.createElement("button");this.toggle.setAttribute("type","button");this.toggle.addEventListener("click",this.onToggleClick.bind(this));this.toggle.className="netgis-menu-toggle netgis-hover-c";this.toggle.innerHTML="<i class='fas fa-bars'></i>";this.container.appendChild(this.toggle)};
|
||||
netgis.Menu.prototype.initConfig=function(a){var b=a.menu;if(b&&(b.header&&this.addHeader(b.header),!0===b.compact&&this.container.classList.add("netgis-compact"),b.items)){b=b.items;for(var c=0;c<b.length;c++){var d=b[c];if(d.items){var e=d.items;if("scales"===d.id)for(var f=this.getScaleItems(),g=0;g<f.length;g++)e.push(f[g]);this.addDropdown(d.title,e)}else if(d.url&&0<d.url.length)this.addLink(d.url,d.title);else if(d.options)if("scales"===d.options){e={0:"1:X"};for(g=0;g<a.map.scales.length;g++)e[a.map.scales[g]]=
|
||||
"1:"+a.map.scales[g];var h=a.map.default_scale;this.addSelect(d.id,d.title,e,h).options[0].classList.add("netgis-hide")}else{e=d.options;if(d.value)h=d.value;else for(var k in e){h=k;break}this.addSelect(d.id,d.title,e,h)}else this.addButton(d.id,d.title)}}};netgis.Menu.prototype.attachTo=function(a){a.appendChild(this.container);a.addEventListener(netgis.Events.MAP_VIEW_CHANGE,this.onMapViewChange.bind(this))};
|
||||
@@ -359,10 +359,7 @@ netgis.Modal.prototype.initEvents=function(){};netgis.Modal.prototype.attachTo=f
|
||||
netgis.Modal.prototype.addHeader=function(a,b,c){var d=document.createElement("button");d.className="netgis-button netgis-clip-text netgis-color-c netgis-gradient-a";d.innerHTML="<span>"+b+"</span><i class='netgis-icon fas fa-times'></i>";d.setAttribute("type","button");c&&(d.onclick=c);a&&a.appendChild(d);return d};netgis.Modal.prototype.onHeaderClick=function(a){this.hide()};netgis.Modal.prototype.onContainerClick=function(a){a.target===this.container&&this.hide()};netgis=netgis||{};
|
||||
netgis.Modes=Object.freeze({VIEW:"view",ZOOM_BOX:"zoom-box",MEASURE_LINE:"measure-line",MEASURE_AREA:"measure-area",DRAW_POINTS:"draw-points",DRAW_LINES:"draw-lines",DRAW_POLYGONS:"draw-polygons",MODIFY_FEATURES:"modify-features",DELETE_FEATURES:"delete-features",BUFFER_FEATURES:"buffer-features",BUFFER_FEATURES_EDIT:"buffer-features-edit",BUFFER_FEATURES_DYNAMIC:"buffer-features-dynamic",CUT_FEATURES:"cut-features",CUT_FEATURES_DRAW:"cut-features-draw",CUT_FEATURES_DYNAMIC:"cut-features-dynamic",SEARCH_PARCEL:"search-parcel"});netgis=netgis||{};netgis.Modules={menu:!0,layertree:!0,map:!0,controls:!0,attribution:!0,legend:!0,geolocation:!0,info:!0,searchplace:!0,searchparcel:!0,toolbox:!0,"import":!0,"export":!0,timeslider:!0};netgis=netgis||{};
|
||||
netgis.OWS=function(){return{read:function(a,b){console.info("OWS READ:",a);console.info("OWS PROPS:",a.properties);a=a.features;for(b=0;b<a.length;b++){var c=a[b];console.info("OWS FEATURE:",b,c);var d=c;c=d.properties;switch(d.type){case "Feature":d=c.minScaleDenominator;var e=c.maxScaleDenominator;console.info("TITLE:",c.title,"FOLDER:",c.folder);console.info("MIN/MAX SCALE:",d,e);c=c.offerings;for(d=0;d<c.length;d++){e=c[d];console.info("OFFERING:",d,e);var f=e,g=f.code;e=f.content;switch(g){case "http://www.opengis.net/spec/owc-atom/1.0/req/kml":for(f=
|
||||
0;f<e.length;f++)switch(g=e[f],g.type){case "application/vnd.google-earth.kml+xml":break;default:console.error("OWS: unknown offering content type '"+g.type+"'",g)}break;default:console.error("OWS: unknown offering code '"+g+"'",f)}}break;default:console.error("OWS: unknown feature type '"+d.type+"'",d)}}}}}();netgis=netgis||{};
|
||||
netgis.OWS=function(){return{read:function(a,b){b={layers:[],folders:[]};netgis.util.isDefined(a.properties)&&(b.bbox=a.properties.bbox);a=a.features;for(var c=0;c<a.length;c++){var d=a[c];if("Feature"===d.type){var e=d.properties;e=e.folder;var f=!1;for(d=0;d<b.folders.length;d++)if(b.folders[d].id===e){f=!0;break}if(!f){d=e.split("/");e=[];for(f=0;f<d.length;f++){var g=d[f];0<g.length&&e.push(g)}var h=-1;for(f=0;f<e.length;f++){g=e[f];var k="/"+e.slice(0,f+1).join("/"),l=!1;for(d=0;d<b.folders.length;d++)if(b.folders[d].path===
|
||||
k){h=d;l=!0;break}l||(d=b.folders.length,b.folders.push({title:g,parent:h,path:k}),h=d)}}}}for(c=0;c<a.length;c++)if(d=a[c],"Feature"===d.type){e=d.properties;f=-1;for(d=0;d<b.folders.length;d++)if(b.folders[d].path===e.folder){f=d;break}d=e.offerings;for(g=0;g<d.length;g++)switch(h=d[g],k=h.operations,h.code){case "http://www.opengis.net/spec/owc-geojson/1.0/req/wms":b.layers.push({folder:f,type:netgis.LayerTypes.WMS,url:k[0].href,title:e.title,attribution:e.rights,active:e.active});break;case "http://www.opengis.net/spec/owc-geojson/1.0/req/xyz":h=
|
||||
k[0];b.layers.push({folder:f,type:netgis.LayerTypes.XYZ,url:h.href,title:e.title,attribution:e.rights,active:e.active});break;case "http://www.opengis.net/spec/owc-geojson/1.0/req/osm":h=k[0],b.layers.push({folder:f,type:netgis.LayerTypes.XYZ,url:h.href,title:e.title,attribution:e.rights,active:e.active})}}return b}}}();netgis.OWS.Config={url:""};netgis=netgis||{};netgis.Panel=function(a){this.initElements(a);this.initEvents()};netgis.Panel.prototype.initElements=function(a){var b=document.createElement("section");b.className="netgis-panel netgis-resize-right netgis-color-e netgis-shadow";this.content=document.createElement("div");b.appendChild(this.content);this.header=this.addHeader(b,a,this.onHeaderClick.bind(this));this.container=b};netgis.Panel.prototype.initEvents=function(){this.resizeObserver=(new ResizeObserver(this.onResize.bind(this))).observe(this.container)};
|
||||
0;f<e.length;f++)switch(g=e[f],g.type){case "application/vnd.google-earth.kml+xml":break;default:console.error("OWS: unknown offering content type '"+g.type+"'",g)}break;default:console.error("OWS: unknown offering code '"+g+"'",f)}}break;default:console.error("OWS: unknown feature type '"+d.type+"'",d)}}}}}();netgis=netgis||{};netgis.Panel=function(a){this.initElements(a);this.initEvents()};netgis.Panel.prototype.initElements=function(a){var b=document.createElement("section");b.className="netgis-panel netgis-resize-right netgis-color-e netgis-shadow";this.content=document.createElement("div");b.appendChild(this.content);this.header=this.addHeader(b,a,this.onHeaderClick.bind(this));this.container=b};netgis.Panel.prototype.initEvents=function(){this.resizeObserver=(new ResizeObserver(this.onResize.bind(this))).observe(this.container)};
|
||||
netgis.Panel.prototype.attachTo=function(a){a.appendChild(this.container);a.addEventListener(netgis.Events.PANEL_TOGGLE,this.onPanelToggle.bind(this))};netgis.Panel.prototype.addHeader=function(a,b,c){var d=document.createElement("button");d.className="netgis-button netgis-clip-text netgis-color-c netgis-gradient-a netgis-shadow";d.innerHTML="<span>"+b+"</span><i class='netgis-icon fas fa-times'></i>";d.setAttribute("type","button");c&&(d.onclick=c);a&&a.appendChild(d);return d};
|
||||
netgis.Panel.prototype.show=function(){this.container.classList.contains("netgis-show")||(this.container.classList.add("netgis-show"),netgis.util.invoke(this.container,netgis.Events.PANEL_TOGGLE,{container:this.container,visible:!0,width:this.container.getBoundingClientRect().width}))};
|
||||
netgis.Panel.prototype.hide=function(){this.container.classList.contains("netgis-show")&&(this.container.classList.remove("netgis-show"),netgis.util.invoke(this.container,netgis.Events.PANEL_TOGGLE,{container:this.container,visible:!1}))};
|
||||
@@ -381,16 +378,16 @@ netgis.Popup.prototype.show=function(){this.container.classList.add("netgis-show
|
||||
netgis.Popup.prototype.hideLoader=function(){this.loader.parentNode===this.content&&this.content.removeChild(this.loader)};
|
||||
netgis.Popup.prototype.setPosition=function(a,b){var c=this.container.parentNode.getBoundingClientRect(),d=this.arrow.getBoundingClientRect();a>c.width-d.width&&(a=c.width-d.width);a<d.width&&(a=d.width);switch(this.options.direction){default:case "down":this.container.style.left=a+"px";this.container.style.top=b+"px";break;case "right":this.container.style.right=c.width-a+"px",this.container.style.top=b+"px"}this.content.style.left="";a=this.content.getBoundingClientRect();0>a.x?this.content.style.left=
|
||||
-a.x+"px":a.x+a.width>c.width&&(this.content.style.left=-(a.x+a.width-c.width)+"px")};netgis.Popup.prototype.setHeader=function(a){this.closer.getElementsByTagName("span")[0].innerHTML=a};netgis.Popup.prototype.setContent=function(a){this.wrapper.innerHTML=a};netgis.Popup.prototype.clearContent=function(){this.wrapper.innerHTML=""};netgis.Popup.prototype.addContent=function(a){this.wrapper.innerHTML+=a};netgis.Popup.prototype.onDocumentPointerDown=function(a){};
|
||||
netgis.Popup.prototype.onPointerDown=function(a){a.stopPropagation()};netgis.Popup.prototype.onCloserClick=function(a){this.hide()};netgis=netgis||{};netgis.Search=function(a){this.debounce=400;this.initElements(a);this.initEvents()};
|
||||
netgis.Search.prototype.initElements=function(a){var b=document.createElement("div");b.className="netgis-search";this.container=b;var c=document.createElement("label");b.appendChild(c);this.label=c;var d=document.createElement("input");d.className="netgis-round netgis-shadow";d.setAttribute("type","text");d.setAttribute("placeholder",a);c.appendChild(d);this.input=d;a=document.createElement("button");a.setAttribute("type","button");a.innerHTML="<i class='fas fa-search'></i>";c.appendChild(a);this.button=
|
||||
a;a=document.createElement("button");a.setAttribute("type","button");a.className="netgis-hide";a.innerHTML="<i class='fas fa-times'></i>";c.appendChild(a);this.closer=a;c=document.createElement("ul");b.appendChild(c);this.results=c};
|
||||
netgis.Popup.prototype.onPointerDown=function(a){a.stopPropagation()};netgis.Popup.prototype.onCloserClick=function(a){this.hide()};netgis=netgis||{};netgis.Search=function(a){this.debounce=400;this.autocomplete=!0;this.initElements(a);this.initEvents()};
|
||||
netgis.Search.prototype.initElements=function(a){var b=document.createElement("div");b.className="netgis-search";this.container=b;var c=document.createElement("label");b.appendChild(c);this.label=c;var d=document.createElement("input");d.className="netgis-round netgis-shadow";d.setAttribute("type","text");d.setAttribute("placeholder",a);c.appendChild(d);this.input=d;a=document.createElement("button");a.setAttribute("type","button");a.innerHTML="<i class='fas fa-search'></i>";a.className="netgis-no-background";
|
||||
c.appendChild(a);this.button=a;a=document.createElement("button");a.setAttribute("type","button");a.className="netgis-hide netgis-no-background";a.innerHTML="<i class='fas fa-times'></i>";c.appendChild(a);this.closer=a;c=document.createElement("ul");b.appendChild(c);this.results=c};
|
||||
netgis.Search.prototype.initEvents=function(){this.input.addEventListener("change",this.onInputChange.bind(this));this.input.addEventListener("keydown",this.onInputKeyDown.bind(this));this.input.addEventListener("keyup",this.onInputKeyUp.bind(this));this.button.addEventListener("click",this.onButtonClick.bind(this));this.closer.addEventListener("click",this.onCloserClick.bind(this))};netgis.Search.prototype.attachTo=function(a){a.appendChild(this.container)};netgis.Search.prototype.show=function(){this.container.classList.remove("netgis-hide")};
|
||||
netgis.Search.prototype.hide=function(){this.container.classList.add("netgis-hide")};netgis.Search.prototype.toggle=function(){this.container.classList.toggle("netgis-hide")};netgis.Search.prototype.isVisible=function(){return!this.container.classList.contains("netgis-hide")};netgis.Search.prototype.minimize=function(){this.container.classList.remove("netgis-color-e","netgis-shadow");this.input.classList.add("netgis-shadow")};
|
||||
netgis.Search.prototype.maximize=function(){this.container.classList.add("netgis-color-e","netgis-shadow");this.input.classList.remove("netgis-shadow")};netgis.Search.prototype.focus=function(){this.input.focus()};netgis.Search.prototype.setTitle=function(a){this.input.setAttribute("placeholder",a)};
|
||||
netgis.Search.prototype.addResult=function(a,b){var c=document.createElement("li"),d=document.createElement("button");d.className="netgis-button netgis-clip-text netgis-color-e netgis-hover-a";d.innerHTML=a;d.setAttribute("type","button");d.setAttribute("title",d.innerText);d.setAttribute("data-result",b);d.addEventListener("click",this.onResultClick.bind(this));c.appendChild(d);0===this.results.childNodes.length&&this.showClearButton(!0);this.results.appendChild(c);this.maximize();return c};
|
||||
netgis.Search.prototype.clearResults=function(){this.results.innerHTML="";this.minimize();netgis.util.invoke(this.container,netgis.Events.SEARCH_CLEAR,null)};netgis.Search.prototype.clearAll=function(){this.clearResults();this.lastQuery=null;this.input.value="";this.showClearButton(!1)};netgis.Search.prototype.requestSearch=function(a){this.lastQuery&&this.lastQuery===a||(this.lastQuery=a,netgis.util.invoke(this.container,netgis.Events.SEARCH_CHANGE,{query:a}))};
|
||||
netgis.Search.prototype.showClearButton=function(a){!1===a?(this.button.classList.remove("netgis-hide"),this.closer.classList.add("netgis-hide")):(this.button.classList.add("netgis-hide"),this.closer.classList.remove("netgis-hide"))};netgis.Search.prototype.onInputKeyDown=function(a){if(13===a.keyCode)return a.preventDefault(),!1};
|
||||
netgis.Search.prototype.onInputKeyUp=function(a){switch(a.keyCode){case 13:a=this.results.getElementsByTagName("button");0<a.length&&a[0].click();break;case 27:this.clearAll();break;default:this.onInputChange()}};netgis.Search.prototype.onInputChange=function(a){this.timeout&&window.clearTimeout(this.timeout);this.timeout=window.setTimeout(this.onInputTimeout.bind(this),this.debounce)};
|
||||
netgis.Search.prototype.onInputKeyUp=function(a){switch(a.keyCode){case 13:if(this.autocomplete)a=this.results.getElementsByTagName("button"),0<a.length&&a[0].click();else this.onInputTimeout();break;case 27:this.clearAll();break;default:if(this.autocomplete)this.onInputChange()}};netgis.Search.prototype.onInputChange=function(a){this.timeout&&window.clearTimeout(this.timeout);this.timeout=window.setTimeout(this.onInputTimeout.bind(this),this.debounce)};
|
||||
netgis.Search.prototype.onInputTimeout=function(){var a=this.input.value;a=a.trim();0<a.length?this.requestSearch(a):this.clearAll()};netgis.Search.prototype.onButtonClick=function(a){this.input.focus()};netgis.Search.prototype.onCloserClick=function(a){this.clearAll();this.input.focus()};netgis.Search.prototype.onResultClick=function(a){a=a.currentTarget;var b=a.getAttribute("data-result");netgis.util.invoke(a,netgis.Events.SEARCH_SELECT,{item:a,data:b})};netgis=netgis||{};netgis.SearchParcel=function(a){this.config=a;this.districtsLayerID="searchparcel_districts";this.fieldsLayerID="searchparcel_fields";this.parcelsLayerID="searchparcel_parcels";this.selected={};this.initElements();this.initEvents();this.initConfig(a)};
|
||||
netgis.SearchParcel.Config={open:!1,name_url:"./proxy.php?https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_alkis/gem_search.php?placename={q}",parcel_url:"./proxy.php?https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_alkis/flur_search.php?gmk_gmn={district}&fln={field}&fsn_zae={parcelA}&fsn_nen={parcelB}&export=json",districts_service:{type:"WFS",url:"http://geo5.service24.rlp.de/wfs/verwaltungsgrenzen_rp.fcgi?",name:"vermkv:gemarkungen_rlp",format:"application/json; subtype=geojson",
|
||||
min_zoom:12},fields_service:{url:"http://geo5.service24.rlp.de/wfs/verwaltungsgrenzen_rp.fcgi?",name:"vermkv:fluren_rlp",filter_property:"gmkgnr"}};
|
||||
@@ -452,19 +449,19 @@ c.addEventListener("click",this.onHeaderButtonClick.bind(this));c.className="net
|
||||
netgis.Tabs.prototype.setActiveTab=function(a){for(var b=this.header.getElementsByClassName("netgis-button"),c=this.content.getElementsByTagName("section"),d=0;d<b.length;d++){var e=b[d],f=c[d];d===a?(e.classList.add("netgis-color-e"),e.classList.add("netgis-text-a"),e.classList.add("netgis-bar-a"),e.classList.add("netgis-active"),e.scrollIntoView({behavior:"smooth"}),f.classList.remove("netgis-hide"),f.scrollTop=0):(e.classList.remove("netgis-color-e"),e.classList.remove("netgis-text-a"),e.classList.remove("netgis-bar-a"),
|
||||
e.classList.remove("netgis-active"),f.classList.add("netgis-hide"))}};netgis.Tabs.prototype.getContentSection=function(a){return this.content.getElementsByTagName("section")[a]};netgis.Tabs.prototype.appendContent=function(a,b){this.content.getElementsByTagName("section")[a].appendChild(b)};
|
||||
netgis.Tabs.prototype.updateHeaderScroll=function(){for(var a=0,b=this.header.getElementsByTagName("button"),c=0;c<b.length;c++){var d=b[c];a+=d.getBoundingClientRect().width;d.classList.contains("netgis-active")&&d.scrollIntoView()}b=this.header.getBoundingClientRect().width;a>b?this.container.classList.add("netgis-scroll"):this.container.classList.remove("netgis-scroll")};
|
||||
netgis.Tabs.prototype.onHeaderButtonClick=function(a){a=a.currentTarget;for(var b=this.header.getElementsByClassName("netgis-button"),c=0,d=0;d<b.length;d++)if(b[d]===a){c=d;break}this.setActiveTab(c)};netgis=netgis||{};netgis.TimeSlider=function(a){this.config=a;this.insertTop=!0;this.initElements();for(a=1900;2E3>=a;a++);var b=this;window.setTimeout(function(){b.container.scrollLeft=0},1)};netgis.TimeSlider.Config={};
|
||||
netgis.Tabs.prototype.onHeaderButtonClick=function(a){a=a.currentTarget;for(var b=this.header.getElementsByClassName("netgis-button"),c=0,d=0;d<b.length;d++)if(b[d]===a){c=d;break}this.setActiveTab(c)};netgis=netgis||{};netgis.TimeSlider=function(a){this.config=a;this.insertTop=!0;this.initElements();var b=this;window.setTimeout(function(){b.container.scrollLeft=0},1)};netgis.TimeSlider.Config={};
|
||||
netgis.TimeSlider.prototype.initElements=function(){this.container=document.createElement("section");this.container.className="netgis-timeslider netgis-footer netgis-noselect netgis-color-e netgis-hide";document.addEventListener("pointermove",this.onPointerMove.bind(this));document.addEventListener("pointerup",this.onPointerUp.bind(this));this.header=document.createElement("button");this.header.className="netgis-header netgis-button netgis-clip-text netgis-color-a netgis-hover-c netgis-shadow";this.header.innerHTML=
|
||||
"<i class='netgis-icon fas fa-clock'></i><span>TimeSlider</span><i class='netgis-icon fas fa-times'></i>";this.header.setAttribute("type","button");this.header.addEventListener("click",this.onHeaderClick.bind(this));this.container.appendChild(this.header);this.wrapper=document.createElement("div");this.wrapper.className="netgis-wrapper";this.wrapper.addEventListener("pointerdown",this.onPointerDown.bind(this));this.container.appendChild(this.wrapper);this.table=document.createElement("table");this.wrapper.appendChild(this.table);
|
||||
this.top=document.createElement("tr");this.table.appendChild(this.top);this.bottom=document.createElement("tr")};netgis.TimeSlider.prototype.attachTo=function(a){a.appendChild(this.container);a.addEventListener(netgis.Events.TIMESLIDER_SHOW,this.onTimeSliderShow.bind(this));a.addEventListener(netgis.Events.TIMESLIDER_HIDE,this.onTimeSliderHide.bind(this))};
|
||||
netgis.TimeSlider.prototype.setVisible=function(a){a?(this.container.classList.remove("netgis-hide"),this.container.parentNode.classList.add("netgis-footer")):(this.container.classList.add("netgis-hide"),this.container.parentNode.classList.remove("netgis-footer"))};netgis.TimeSlider.prototype.setTitle=function(a){this.header.getElementsByTagName("span")[0].innerHTML=a};netgis.TimeSlider.prototype.clearTimeSteps=function(){this.top.innerHTML=""};
|
||||
netgis.TimeSlider.prototype.addTimeStep=function(a,b){var c=document.createElement("td");c.setAttribute("data-id",a);a=document.createElement("button");a.className="netgis-button netgis-color-e netgis-hover-d";a.innerHTML="<i class='netgis-icon netgis-text-a far fa-calendar'></i><span>"+b+"</span>";a.setAttribute("type","button");a.addEventListener("click",this.onTimeStepClick.bind(this));c.appendChild(a);this.top.appendChild(c)};
|
||||
netgis.TimeSlider.prototype.addTimeStep_01=function(a,b){a=document.createElement("td");var c=document.createElement("td");this.insertTop?a.innerHTML=b:c.innerHTML=b;this.top.appendChild(a);this.bottom.appendChild(c);this.insertTop=!this.insertTop};
|
||||
netgis.TimeSlider.prototype.setActiveTimeStep=function(a){var b=this.top.getElementsByTagName("td"),c=b[a],d=c.getAttribute("data-id");console.info("Set Active Step:",a,d);for(var e=0;e<b.length;e++){var f=b[e],g=f.getElementsByClassName("netgis-icon")[0];e===a?(f.classList.add("netgis-active"),g.classList.remove("fa-calendar"),g.classList.add("fa-calendar-check")):(f.classList.remove("netgis-active"),g.classList.add("fa-calendar"),g.classList.remove("fa-calendar-check"))}c.scrollIntoView();netgis.util.invoke(c,
|
||||
netgis.Events.TIMESLIDER_SELECT,{layer:this.layerID,time:d})};netgis.TimeSlider.prototype.requestServiceWMST=function(a,b){a=a.trim();1>a.length||(-1===a.indexOf("GetCapabilities")&&(a+="&REQUEST=GetCapabilities"),netgis.util.request(a,this.onServiceResponseWMST.bind(this),{id:b}))};
|
||||
netgis.TimeSlider.prototype.setActiveTimeStep=function(a){for(var b=this.top.getElementsByTagName("td"),c=b[a],d=c.getAttribute("data-id"),e=0;e<b.length;e++){var f=b[e],g=f.getElementsByClassName("netgis-icon")[0];e===a?(f.classList.add("netgis-active"),g.classList.remove("fa-calendar"),g.classList.add("fa-calendar-check")):(f.classList.remove("netgis-active"),g.classList.add("fa-calendar"),g.classList.remove("fa-calendar-check"))}c.scrollIntoView();netgis.util.invoke(c,netgis.Events.TIMESLIDER_SELECT,
|
||||
{layer:this.layerID,time:d})};netgis.TimeSlider.prototype.requestServiceWMST=function(a,b){a=a.trim();1>a.length||(-1===a.indexOf("GetCapabilities")&&(a+="&REQUEST=GetCapabilities"),netgis.util.request(a,this.onServiceResponseWMST.bind(this),{id:b}))};
|
||||
netgis.TimeSlider.prototype.onServiceResponseWMST=function(a,b){for(var c=(new DOMParser).parseFromString(a,"text/xml").documentElement.getElementsByTagName("Layer"),d,e=0;e<c.length;e++){a=c[e];var f=a.getElementsByTagName("Name")[0].textContent;if(f===b.id){d={name:f,title:a.getElementsByTagName("Title")[0].textContent,abstract:a.getElementsByTagName("Abstract")[0].textContent,queryable:"1"===a.getAttribute("queryable"),opaque:"1"===a.getAttribute("opaque")};e=a.getElementsByTagName("SRS");0<e.length&&
|
||||
(d.projection=e[0].textContent);e=a.getElementsByTagName("CRS");0<e.length&&(d.projection=e[0].textContent);e=a.getElementsByTagName("BoundingBox")[0];d.bbox=[Number.parseFloat(e.getAttribute("minx")),Number.parseFloat(e.getAttribute("miny")),Number.parseFloat(e.getAttribute("maxx")),Number.parseFloat(e.getAttribute("maxy"))];b=a.getElementsByTagName("Dimension");for(e=0;e<b.length;e++)if(c=b[e],"time"===c.getAttribute("name")){var g={defaultTime:c.getAttribute("default"),extent:c.textContent.split("/")};
|
||||
break}a=a.getElementsByTagName("Extent");for(e=0;e<a.length;e++)if(b=a[e],"time"===b.getAttribute("name")){g.defaultTime=b.getAttribute("default");g.extent=b.textContent.split("/");break}d.time=g;break}}console.info("WMST Layer:",d);this.setTitle(d.title);if(d.time.extent){g=new Date(d.time.extent[0]);a=new Date(d.time.extent[1]);b=d.time.extent[2];d=[];switch(b){case "P1D":for(;g<=a;)d.push(new Date(g)),g.setDate(g.getDate()+1);break;default:console.error("unsupported WMST date range",b,g,a)}for(e=
|
||||
0;e<d.length;e++)b=d[e],a=g=b.toISOString(),a=a.replace("T",", "),a=a.replace("Z",""),this.addTimeStep(g,a);this.setActiveTimeStep(d.length-1)}};netgis.TimeSlider.prototype.onTimeSliderShow=function(a){a=a.detail;console.info("TimeSlider Show:",a);this.layerID=a.layer;this.setTitle(a.title);this.clearTimeSteps();this.requestServiceWMST(a.url,a.name);this.setVisible(!0)};netgis.TimeSlider.prototype.onTimeSliderHide=function(a){this.setVisible(!1)};netgis.TimeSlider.prototype.onHeaderClick=function(a){this.setVisible(!1)};
|
||||
break}a=a.getElementsByTagName("Extent");for(e=0;e<a.length;e++)if(b=a[e],"time"===b.getAttribute("name")){g.defaultTime=b.getAttribute("default");g.extent=b.textContent.split("/");break}d.time=g;break}}this.setTitle(d.title);if(d.time.extent){g=new Date(d.time.extent[0]);a=new Date(d.time.extent[1]);b=d.time.extent[2];d=[];switch(b){case "P1D":for(;g<=a;)d.push(new Date(g)),g.setDate(g.getDate()+1);break;default:console.error("unsupported WMST date range",b,g,a)}for(e=0;e<d.length;e++)b=d[e],a=g=
|
||||
b.toISOString(),a=a.replace("T",", "),a=a.replace("Z",""),this.addTimeStep(g,a);this.setActiveTimeStep(d.length-1)}};netgis.TimeSlider.prototype.onTimeSliderShow=function(a){a=a.detail;this.layerID=a.layer;this.setTitle(a.title);this.clearTimeSteps();this.requestServiceWMST(a.url,a.name);this.setVisible(!0)};netgis.TimeSlider.prototype.onTimeSliderHide=function(a){this.setVisible(!1)};netgis.TimeSlider.prototype.onHeaderClick=function(a){this.setVisible(!1)};
|
||||
netgis.TimeSlider.prototype.onPointerDown=function(a){a=a.pageX-this.wrapper.offsetLeft;this.down=!0;this.downX=a;this.downScroll=this.wrapper.scrollLeft;this.container.classList.add("netgis-active")};netgis.TimeSlider.prototype.onPointerMove=function(a){this.down&&(a.preventDefault(),this.wrapper.scrollLeft=this.downScroll-(a.pageX-this.wrapper.offsetLeft-this.downX))};netgis.TimeSlider.prototype.onPointerUp=function(a){this.down&&a.preventDefault();this.down=!1;this.container.classList.remove("netgis-active")};
|
||||
netgis.TimeSlider.prototype.onTimeStepClick=function(a){a=a.currentTarget.parentNode;a.getAttribute("data-id");if(!(5<Math.abs(this.wrapper.scrollLeft-this.downScroll))){for(var b=this.top.getElementsByTagName("td"),c=-1,d=0;d<b.length;d++)if(b[d]===a){c=d;break}this.setActiveTimeStep(c)}};netgis=netgis||{};netgis.Toolbox=function(a){this.config=a;this.bottomPanels={};this.initElements(a);this.initOptions(a);this.initEvents();this.setActiveButton(netgis.Commands.VIEW)};netgis.Toolbox.Config={open:!1,items:[],options:{buffer_features:{title:"Buffer",items:[{id:"buffer_radius",type:"integer",title:"Radius (Meter)"},{id:"buffer_segments",type:"integer",title:"Segments"},{id:"buffer_submit",type:"button",title:"<i class='netgis-icon netgis-text-a fas fa-arrow-circle-right'></i><span>Akzeptieren</span>"}]}}};
|
||||
netgis.Toolbox.prototype.initElements=function(a){this.panel=new netgis.Panel("Toolbox");this.panel.content.classList.add("netgis-toolbox");this.top=document.createElement("section");this.panel.content.appendChild(this.top);for(var b=a.toolbox.items,c=0;c<b.length;c++){var d=b[c];if(this.config.tools&&!1===this.config.tools.editable)switch(d.id){case "draw_points":continue;case "draw_lines":continue;case "draw_polygons":continue;case "modify_features":continue;case "delete_features":continue;case "buffer_features":continue;
|
||||
@@ -517,9 +514,9 @@ netgis.Tree.prototype.setFolderOpen=function(a,b){var c=this.container.getElemen
|
||||
netgis.Tree.prototype.setItemChecked=function(a,b,c){var d=this.container.getElementsByClassName("netgis-item");a=a.toString();for(var e=0;e<d.length;e++){var f=d[e],g=f.getElementsByTagName("input")[0];if(g.getAttribute("data-id")===a){if("radio"===g.getAttribute("type")){f=f.parentNode.getElementsByTagName("input");for(var h=0;h<f.length;h++){var k=f[h];k!==g&&"radio"===k.getAttribute("type")&&!1!==k.checked&&(k.checked=!1,netgis.util.invoke(g,netgis.Events.TREE_ITEM_CHANGE,{id:k.getAttribute("data-id"),
|
||||
checked:!1}))}}c?g.checked=b:g.checked!==b&&g.click()}}};netgis.Tree.prototype.setFolderParent=function(a,b){var c=a.parentNode;c&&c.removeChild(a);null!==b?b.getElementsByTagName("ul")[0].appendChild(a):this.container.appendChild(a)};netgis.Tree.prototype.updateFolderChecks=function(){for(var a=this.container.getElementsByClassName("netgis-folder"),b=0;b<a.length;b++)this.updateFolderCheck(a[b])};
|
||||
netgis.Tree.prototype.updateFolderCheck=function(a){a||(a=this.container);for(var b=a.getElementsByClassName("netgis-item"),c=0,d=0;d<b.length;d++){var e=b[d].getElementsByTagName("input")[0];e.checked&&c++}e=a.getElementsByTagName("input")[0];d=0;0<c&&(d=1);0<c&&c===b.length&&(d=2);switch(d){case 0:e.checked=!1;e.classList.remove("netgis-partial");break;case 1:e.checked=!0;e.classList.add("netgis-partial");break;case 2:e.checked=!0,e.classList.remove("netgis-partial")}(a=a.parentElement)&&a!==this.container&&
|
||||
(a=a.parentElement.parentElement)&&-1!==a.className.search("netgis-folder")&&this.updateFolderCheck(a)};netgis.Tree.prototype.onFolderChange=function(a){var b=a.currentTarget;a=b.checked;b=b.parentElement.parentElement.parentElement.parentElement;for(var c=b.getElementsByTagName("input"),d=1;d<c.length;d++){var e=c[d];e.checked!==a&&e.click()}this.updateFolderCheck(b);a=b.parentElement.parentElement.parentElement;-1!==a.className.search("netgis-folder")&&this.updateFolderCheck(a)};
|
||||
netgis.Tree.prototype.onItemChange=function(a){a=a.currentTarget;var b=a.checked,c=a.getAttribute("data-id"),d=a.parentElement.parentElement.parentElement.parentElement.parentElement;if("radio"===a.getAttribute("type"))for(var e=a.parentNode.parentNode.parentNode.parentNode.getElementsByTagName("input"),f=0;f<e.length;f++){var g=e[f].getAttribute("data-id");g&&g!==c&&netgis.util.invoke(a,netgis.Events.TREE_ITEM_CHANGE,{id:g,checked:!1})}netgis.util.invoke(a,netgis.Events.TREE_ITEM_CHANGE,{id:c,checked:b});
|
||||
-1!==d.className.search("netgis-folder")&&this.updateFolderCheck(d)};netgis.Tree.prototype.onRadioChange=function(a){a=a.currentTarget;var b=a.checked,c=a.getAttribute("data-id"),d=Number.parseInt(c);Number.isNaN(d)||(c=d);d=a.parentElement.parentElement.parentElement.parentElement.parentElement;netgis.util.invoke(a,netgis.Events.TREE_ITEM_CHANGE,{id:c,checked:b});-1!==d.className.search("netgis-folder")&&this.updateFolderCheck(d)};
|
||||
(a=a.parentElement.parentElement)&&-1!==a.className.search("netgis-folder")&&this.updateFolderCheck(a)};netgis.Tree.prototype.onFolderChange=function(a){var b=a.currentTarget;a=b.checked;b=b.parentElement.parentElement.parentElement.parentElement.getElementsByTagName("input");for(var c=1;c<b.length;c++){var d=b[c];d.checked!==a&&d.click()}this.updateFolderChecks()};
|
||||
netgis.Tree.prototype.onItemChange=function(a){a=a.currentTarget;var b=a.checked,c=a.getAttribute("data-id");if("radio"===a.getAttribute("type"))for(var d=a.parentNode.parentNode.parentNode.parentNode.getElementsByTagName("input"),e=0;e<d.length;e++){var f=d[e].getAttribute("data-id");f&&f!==c&&netgis.util.invoke(a,netgis.Events.TREE_ITEM_CHANGE,{id:f,checked:!1})}netgis.util.invoke(a,netgis.Events.TREE_ITEM_CHANGE,{id:c,checked:b});this.updateFolderChecks()};
|
||||
netgis.Tree.prototype.onRadioChange=function(a){a=a.currentTarget;var b=a.checked,c=a.getAttribute("data-id"),d=Number.parseInt(c);Number.isNaN(d)||(c=d);d=a.parentElement.parentElement.parentElement.parentElement.parentElement;netgis.util.invoke(a,netgis.Events.TREE_ITEM_CHANGE,{id:c,checked:b});-1!==d.className.search("netgis-folder")&&this.updateFolderCheck(d)};
|
||||
netgis.Tree.prototype.onButtonClick=function(a){a=a.currentTarget;var b=a.getAttribute("data-id");netgis.util.invoke(a,netgis.Events.TREE_BUTTON_CLICK,{id:b})};netgis.Tree.prototype.onItemSliderChange=function(a){a=a.currentTarget;var b=a.getAttribute("data-id");netgis.util.invoke(a,netgis.Events.TREE_ITEM_SLIDER_CHANGE,{id:b,val:Number.parseFloat(a.value)})};
|
||||
netgis.Tree.prototype.onDragStart=function(a){a.stopPropagation();var b=a.currentTarget,c=b.getElementsByTagName("input")[0].getAttribute("data-id");b.classList.add("netgis-dragging");a.dataTransfer.setData("text/plain",c);a.dataTransfer.dropEffect="move";this.dragElement=b};netgis.Tree.prototype.onDragEnter=function(a){a=a.currentTarget;a!==this.dragElement&&a.classList.add("netgis-dragover")};
|
||||
netgis.Tree.prototype.onDragOver=function(a){a.preventDefault();a=a.currentTarget;a!==this.dragElement&&a.classList.add("netgis-dragover")};netgis.Tree.prototype.onDragLeave=function(a){a.currentTarget.classList.remove("netgis-dragover")};
|
||||
@@ -547,13 +544,7 @@ netgis.WMC.prototype.requestLayers=function(a){var b=this.config.wmc;b?(b=b.laye
|
||||
netgis.WMC.prototype.toConfig=function(){var a=this.data.wmc,b=this.data.layerList,c=this.layers.wms.srv,d={},e=a.bbox;e=e.split(",");for(var f=0;f<e.length;f++)e[f]=Number.parseFloat(e[f]);d.map={projection:a.crs,bbox:e};d.attribution||(d.attribution={});d.attribution.prefix=d.attribution.prefix?a.title+", "+d.attribution.prefix:a.title;a=d.folders=[];e=d.layers=[];this.parseServiceLayers(c,b,a,e);b=1E3;for(c=0;c<a.length;c++){f=a[c];for(var g=e.length-1;0<=g;g--){var h=e[g];h.folder===f.id&&(h.order=
|
||||
b,b+=1)}}return d};
|
||||
netgis.WMC.prototype.parseServiceLayers=function(a,b,c,d){c||(c=[]);d||(d=[]);for(var e=0;e<a.length;e++)for(var f=a[e],g=0;g<f.layer.length;g++){var h=f.layer[g];h.isRoot&&c.push({id:h.id,title:h.title,open:"1"===f.isopen});var k=h.layer;if(k){b&&k.sort(function(a,c){a=a.id;var d=c.id,e=null;c=null;for(var f=0;f<b.length;f++){var g=b[f];g.layerId.toString()===a&&(e=g);g.layerId.toString()===d&&(c=g)}a=e.layerPos;c=c.layerPos;return a<c?-1:a>c?1:0});for(var l=k.length-1;0<=l;l--){var m=k[l],n=m.id,
|
||||
p=null;if(b)for(var q=0;q<b.length;q++)if(b[q].layerId.toString()===n){p=b[q];break}m=this.parseServiceLayer(n,f,h.id,m,p);d.push(m)}}}return{folders:c,layers:d}};netgis.WMC.prototype.parseServiceLayer=function(a,b,c,d,e){return{id:a,folder:c,title:d.title,active:e?e.active:!0,query:1===d.queryable,transparency:e?1-.01*e.opacity:0,order:1E3,type:netgis.LayerTypes.WMS,url:b.getMapUrl,name:d.name,format:e?e.currentFormat:"image/png"}};
|
||||
netgis.WMC.prototype.toConfig_02=function(){var a=this.data.wmc,b=this.layers.wms.srv,c=this.data.layerList,d={},e=a.bbox;e=e.split(",");for(var f=0;f<e.length;f++)e[f]=Number.parseFloat(e[f]);d.map={projection:a.crs,bbox:e};d.attribution||(d.attribution={});d.attribution.prefix=d.attribution.prefix?a.title+", "+d.attribution.prefix:a.title;a=d.folders=[];e=d.layers=[];var g=[];for(f=0;f<c.length;f++){var h=c[f],k={id:Number.parseInt(h.layerId),type:"layer",order:h.layerPos,active:h.active,opacity:h.opacity};
|
||||
g.push(k)}for(f=0;f<b.length;f++){c=b[f];k={id:Number.parseInt(c.id),type:"service",title:c.title,url:c.getMapUrl,open:"1"===c.isopen};g.push(k);for(var l=0;l<c.layer.length;l++){h=c.layer[l];var m=this.parseLayer(h,k.id,g);if(h.layer)for(var n=0;n<h.layer.length;n++){var p=h.layer[n],q=this.parseLayer(p,m.id,g);if(p.layer)for(var r=0;r<p.layer.length;r++){var t=p.layer[r],u=this.parseLayer(t,q.id,g);if(t.layer)for(var v=0;v<t.layer.length;v++)this.parseLayer(t.layer[v],u.id,g)}}}}console.info("WMC ITEMS:",
|
||||
g);for(f=0;f<g.length;f++)switch(k=g[f],k.type){case "service":a.push({id:k.id,title:k.title,open:k.open});break;case "layer":h={},e.push(h)}return d};
|
||||
q=null;if(b)for(var p=0;p<b.length;p++)if(b[p].layerId.toString()===n){q=b[p];break}m=this.parseServiceLayer(n,f,h.id,m,q);d.push(m)}}}return{folders:c,layers:d}};netgis.WMC.prototype.parseServiceLayer=function(a,b,c,d,e){return{id:a,folder:c,title:d.title,active:e?e.active:!0,query:1===d.queryable,transparency:e?1-.01*e.opacity:0,order:1E3,type:netgis.LayerTypes.WMS,url:b.getMapUrl,name:d.name,format:e?e.currentFormat:"image/png"}};
|
||||
netgis.WMC.prototype.parseLayer=function(a,b,c){for(var d=null,e=0;e<c.length;e++)if(c[e].id===Number.parseInt(a.id)){d=c[e];break}d||(d={id:Number.parseInt(a.id),type:"layer"},c.push(d));d.title=a.title;d.name=a.name;d.parent=b;a.getLegendGraphicUrl&&a.getLegendGraphicUrlFormat&&(d.legendURL=a.getLegendGraphicUrl,d.legendFormat=a.getLegendGraphicUrlFormat);a.legendUrl&&(d.legendURL=window.decodeURIComponent(a.legendUrl),d.legendFormat=a.getLegendGraphicUrlFormat);d.queryable=1===a.layerQueryable||
|
||||
1===a.queryable?!0:!1;if(a.bbox){a=a.bbox.split(",");for(b=0;b<a.length;b++)a[b]=parseFloat(a[b]);d.bbox=[a[0],a[1],a[2],a[3]]}return d};
|
||||
netgis.WMC.prototype.toConfig_01=function(){var a=this.data.wmc,b=this.layers.wms.srv,c=this.data.layerList,d={},e=a.bbox;e=e.split(",");for(var f=0;f<e.length;f++)e[f]=Number.parseFloat(e[f]);d.map={attribution:a.title+", GeoPortal RLP",projection:a.crs,bbox:e};e=[];var g={};for(f=0;f<b.length;f++){var h=b[f],k={id:h.id,title:h.title,open:"1"===h.isopen};e.push(k);for(k=0;k<h.layer.length;k++){var l=h.layer[k];l.getMapUrl||(l.getMapUrl=h.getMapUrl);g[l.id.toString()]=l;if(l.layer)for(var m=0;m<l.layer.length;m++){var n=
|
||||
l.layer[m];n.getMapUrl||(n.getMapUrl=l.getMapUrl);g[n.id.toString()]=n}}}console.info("WMC FOLDERS:",b,"---\x3e",e);b=[];h=9999;(this.kmloverlay=a.kmloverlay)&&""!==this.kmloverlay&&(k={id:"kmloverlay",title:"Meine Geodaten",parent:null},e.push(k),l={id:"kmloverlay",folder:"kmloverlay",title:"KML Overlay",active:!0,order:h,type:netgis.LayerTypes.KML,url:this.kmloverlay,query:!0},b.push(l),--h);for(f=c.length-1;0<=f;f--)a=c[f],m=a.layerId.toString(),(l=g[m])&&!l.isRoot&&(k=null!==a.layerParent?e[a.layerParent].id:
|
||||
null,l={id:m,folder:k,title:l.title,active:a.active,query:1===a.layerQueryable,transparency:1-.01*a.opacity,order:h,type:netgis.LayerTypes.WMS,url:l.getMapUrl,name:l.name,format:a.currentFormat},"image/tiff"===l.format&&(l.format="image/png"),b.push(l),--h);d.folders=e;d.layers=b;return d};
|
||||
netgis.build="20251010";
|
||||
netgis.build="20251027";
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if geom_form.geom.errors %}
|
||||
{% if geom_form.output.errors %}
|
||||
<div class="alert-danger p-2">
|
||||
{% for error in geom_form.geom.errors %}
|
||||
{% for error in geom_form.output.errors %}
|
||||
<strong class="invalid">{{ error }}</strong>
|
||||
<br>
|
||||
{% endfor %}
|
||||
|
||||
@@ -22,6 +22,7 @@ class NewAPITokenModalForm(BaseModalForm):
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.template = "modal/modal_form.html"
|
||||
super().__init__(*args, **kwargs)
|
||||
self.instance = self.user
|
||||
self.form_title = _("Generate API Token")
|
||||
|
||||
self.form_caption = ""
|
||||
|
||||
@@ -260,7 +260,7 @@ class ApiTokenFormTestCase(BaseTestCase):
|
||||
}
|
||||
|
||||
self.assertIsNone(self.user.api_token)
|
||||
form = NewAPITokenModalForm(request.POST, instance=self.user)
|
||||
form = NewAPITokenModalForm(request.POST, request=request)
|
||||
form.save()
|
||||
self.user.refresh_from_db()
|
||||
token = self.user.api_token
|
||||
|
||||
16
user/urls.py
16
user/urls.py
@@ -9,9 +9,11 @@ from django.urls import path
|
||||
|
||||
from user.autocomplete.share import ShareUserAutocomplete, ShareTeamAutocomplete
|
||||
from user.autocomplete.team import TeamAdminAutocomplete
|
||||
from user.views.api_token import APITokenView, new_api_token_view
|
||||
from user.views.api_token import APITokenView, NewAPITokenView
|
||||
from user.views.propagate import PropagateUserView
|
||||
from user.views.views import *
|
||||
from user.views.teams import TeamIndexView, NewTeamView, TeamDetailModalView, EditTeamView, RemoveTeamView, \
|
||||
LeaveTeamView
|
||||
from user.views.users import UserDetailView, NotificationsView, ContactView
|
||||
|
||||
app_name = "user"
|
||||
urlpatterns = [
|
||||
@@ -19,14 +21,14 @@ urlpatterns = [
|
||||
path("propagate/", PropagateUserView.as_view(), name="propagate"),
|
||||
path("notifications/", NotificationsView.as_view(), name="notifications"),
|
||||
path("token/api", APITokenView.as_view(), name="api-token"),
|
||||
path("token/api/new", new_api_token_view, name="api-token-new"),
|
||||
path("token/api/new", NewAPITokenView.as_view(), name="api-token-new"),
|
||||
path("contact/<id>", ContactView.as_view(), name="contact"),
|
||||
path("team/", TeamIndexView.as_view(), name="team-index"),
|
||||
path("team/new", new_team_view, name="team-new"),
|
||||
path("team/new", NewTeamView.as_view(), name="team-new"),
|
||||
path("team/<id>", TeamDetailModalView.as_view(), name="team-data"),
|
||||
path("team/<id>/edit", edit_team_view, name="team-edit"),
|
||||
path("team/<id>/remove", remove_team_view, name="team-remove"),
|
||||
path("team/<id>/leave", leave_team_view, name="team-leave"),
|
||||
path("team/<id>/edit", EditTeamView.as_view(), name="team-edit"),
|
||||
path("team/<id>/remove", RemoveTeamView.as_view(), name="team-remove"),
|
||||
path("team/<id>/leave", LeaveTeamView.as_view(), name="team-leave"),
|
||||
|
||||
# Autocomplete urls
|
||||
path("atcmplt/share/u", ShareUserAutocomplete.as_view(), name="share-user-autocomplete"),
|
||||
|
||||
@@ -4,9 +4,9 @@ Created on: 08.01.25
|
||||
|
||||
"""
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.http import HttpRequest
|
||||
from django.shortcuts import render
|
||||
from django.urls import reverse
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.views import View
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
@@ -15,7 +15,9 @@ from konova.contexts import BaseContext
|
||||
from konova.decorators import default_group_required
|
||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
||||
from konova.utils.message_templates import NEW_API_TOKEN_GENERATED
|
||||
from konova.views.modal import AbstractModalFormView
|
||||
from user.forms.modals.api_token import NewAPITokenModalForm
|
||||
from user.models import User
|
||||
|
||||
|
||||
class APITokenView(View):
|
||||
@@ -36,22 +38,16 @@ class APITokenView(View):
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, template, context)
|
||||
|
||||
class NewAPITokenView(LoginRequiredMixin, AbstractModalFormView):
|
||||
_MODEL_CLS = User
|
||||
_FORM_CLS = NewAPITokenModalForm
|
||||
_MSG_SUCCESS = NEW_API_TOKEN_GENERATED
|
||||
_REDIRECT_URL = "user:api-token"
|
||||
|
||||
def new_api_token_view(request: HttpRequest):
|
||||
""" Function based view for processing ModalForm
|
||||
(Currently ModalForms only work properly with function based views)
|
||||
def _user_has_shared_access(self, user, **kwargs):
|
||||
# No special checks to be done in here
|
||||
return True
|
||||
|
||||
Args:
|
||||
request ():
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
user = request.user
|
||||
|
||||
form = NewAPITokenModalForm(request.POST or None, instance=user, request=request)
|
||||
return form.process_request(
|
||||
request=request,
|
||||
msg_success=NEW_API_TOKEN_GENERATED,
|
||||
redirect_url=reverse("user:api-token"),
|
||||
)
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
# User should at least be a default user to be able to use the api
|
||||
return user.is_default_user()
|
||||
|
||||
105
user/views/teams.py
Normal file
105
user/views/teams.py
Normal file
@@ -0,0 +1,105 @@
|
||||
"""
|
||||
Author: Michel Peltriaux
|
||||
Created on: 05.11.25
|
||||
|
||||
"""
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.http import Http404, HttpRequest
|
||||
from django.shortcuts import get_object_or_404, render
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from konova.contexts import BaseContext
|
||||
from konova.utils.message_templates import TEAM_LEFT, TEAM_REMOVED, TEAM_EDITED, TEAM_ADDED
|
||||
from konova.views.modal import AbstractModalFormView
|
||||
from user.forms.modals.team import LeaveTeamModalForm, RemoveTeamModalForm, EditTeamModalForm, NewTeamModalForm
|
||||
from user.forms.team import TeamDataForm
|
||||
from user.models import Team
|
||||
from user.views.users import UserBaseView
|
||||
|
||||
|
||||
class TeamDetailModalView(LoginRequiredMixin, AbstractModalFormView):
|
||||
_FORM_CLS = TeamDataForm
|
||||
_MODEL_CLS = Team
|
||||
|
||||
def _user_has_shared_access(self, user, **kwargs):
|
||||
# No specific constraints
|
||||
return True
|
||||
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
# No specific constraints
|
||||
return True
|
||||
|
||||
|
||||
class TeamIndexView(LoginRequiredMixin, UserBaseView):
|
||||
_TEMPLATE = "user/team/index.html"
|
||||
_TAB_TITLE = _("Teams")
|
||||
|
||||
def get(self, request: HttpRequest):
|
||||
user = request.user
|
||||
context = {
|
||||
"teams": user.shared_teams,
|
||||
"tab_title": self._TAB_TITLE,
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, self._TEMPLATE, context)
|
||||
|
||||
|
||||
class BaseTeamView(LoginRequiredMixin, AbstractModalFormView):
|
||||
_REDIRECT_URL = "user:team-index"
|
||||
_MODEL_CLS = Team
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
# Nothing to check here - just pass the test
|
||||
return True
|
||||
|
||||
def _user_has_shared_access(self, user, **kwargs):
|
||||
# Nothing to check here - just pass the test
|
||||
return True
|
||||
|
||||
def _get_redirect_url(self, *args, **kwargs):
|
||||
return reverse(self._REDIRECT_URL)
|
||||
|
||||
class NewTeamView(BaseTeamView):
|
||||
_FORM_CLS = NewTeamModalForm
|
||||
_MSG_SUCCESS = TEAM_ADDED
|
||||
|
||||
class EditTeamView(BaseTeamView):
|
||||
_FORM_CLS = EditTeamModalForm
|
||||
_MSG_SUCCESS = TEAM_EDITED
|
||||
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
team = get_object_or_404(Team, id=kwargs.get("id"))
|
||||
user_is_admin = team.is_user_admin(user)
|
||||
if not user_is_admin:
|
||||
# If user is not an admin, we act as if there is no such team on the database
|
||||
raise Http404()
|
||||
return user_is_admin
|
||||
|
||||
|
||||
class RemoveTeamView(BaseTeamView):
|
||||
_FORM_CLS = RemoveTeamModalForm
|
||||
_MSG_SUCCESS = TEAM_REMOVED
|
||||
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
team_id = kwargs.get("id")
|
||||
team = get_object_or_404(Team, id=team_id)
|
||||
user_is_admin = team.is_user_admin(user)
|
||||
if not user_is_admin:
|
||||
raise Http404()
|
||||
return True
|
||||
|
||||
class LeaveTeamView(BaseTeamView):
|
||||
_FORM_CLS = LeaveTeamModalForm
|
||||
_MSG_SUCCESS = TEAM_LEFT
|
||||
|
||||
def _user_has_shared_access(self, user, **kwargs):
|
||||
team_id = kwargs.get("id")
|
||||
team = get_object_or_404(self._MODEL_CLS, id=team_id)
|
||||
is_user_team_member = team.users.filter(id=user.id).exists()
|
||||
if not is_user_team_member:
|
||||
raise Http404()
|
||||
return True
|
||||
81
user/views/users.py
Normal file
81
user/views/users.py
Normal file
@@ -0,0 +1,81 @@
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
|
||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
||||
from konova.views.modal import AbstractBaseView, AbstractModalFormView
|
||||
from user.forms.modals.user import UserContactForm
|
||||
from user.forms.user import UserNotificationForm
|
||||
from user.models import User
|
||||
from django.http import HttpRequest
|
||||
from django.shortcuts import render, redirect
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from konova.contexts import BaseContext
|
||||
|
||||
|
||||
class UserBaseView(AbstractBaseView):
|
||||
def _user_has_shared_access(self, user, **kwargs):
|
||||
return True
|
||||
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return True
|
||||
|
||||
|
||||
class UserDetailView(LoginRequiredMixin, UserBaseView):
|
||||
_TEMPLATE = "user/index.html"
|
||||
_TAB_TITLE = _("User settings")
|
||||
|
||||
def get(self, request: HttpRequest):
|
||||
context = {
|
||||
"user": request.user,
|
||||
TAB_TITLE_IDENTIFIER: self._TAB_TITLE,
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, self._TEMPLATE, context)
|
||||
|
||||
|
||||
class NotificationsView(LoginRequiredMixin, UserBaseView):
|
||||
_TEMPLATE = "user/notifications.html"
|
||||
_TAB_TITLE = _("User notifications")
|
||||
|
||||
def get(self, request: HttpRequest):
|
||||
user = request.user
|
||||
form = UserNotificationForm(user=user, data=None)
|
||||
context = {
|
||||
"user": user,
|
||||
"form": form,
|
||||
TAB_TITLE_IDENTIFIER: self._TAB_TITLE,
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, self._TEMPLATE, context)
|
||||
|
||||
def post(self, request: HttpRequest):
|
||||
user = request.user
|
||||
form = UserNotificationForm(user=user, data=request.POST)
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
messages.success(
|
||||
request,
|
||||
_("Notifications edited")
|
||||
)
|
||||
return redirect("user:detail")
|
||||
context = {
|
||||
"user": user,
|
||||
"form": form,
|
||||
TAB_TITLE_IDENTIFIER: self._TAB_TITLE,
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, self._TEMPLATE, context)
|
||||
|
||||
|
||||
class ContactView(LoginRequiredMixin, AbstractModalFormView):
|
||||
_FORM_CLS = UserContactForm
|
||||
_MODEL_CLS = User
|
||||
|
||||
def _user_has_shared_access(self, user, **kwargs):
|
||||
# No specific constraints
|
||||
return True
|
||||
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
# No specific constraints
|
||||
return True
|
||||
@@ -1,206 +0,0 @@
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.urls import reverse
|
||||
|
||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
||||
from konova.views.base import BaseView, BaseModalFormView
|
||||
from user.forms.modals.team import NewTeamModalForm, EditTeamModalForm, RemoveTeamModalForm, LeaveTeamModalForm
|
||||
from user.forms.modals.user import UserContactForm
|
||||
from user.forms.team import TeamDataForm
|
||||
from user.forms.user import UserNotificationForm
|
||||
from user.models import User, Team
|
||||
from django.http import HttpRequest, Http404
|
||||
from django.shortcuts import render, redirect, get_object_or_404
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from konova.contexts import BaseContext
|
||||
from konova.decorators import login_required_modal
|
||||
|
||||
|
||||
class UserBaseView(BaseView):
|
||||
def _user_has_shared_access(self, user, **kwargs):
|
||||
return True
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
return True
|
||||
|
||||
|
||||
class UserDetailView(LoginRequiredMixin, UserBaseView):
|
||||
_TEMPLATE = "user/index.html"
|
||||
_TAB_TITLE = _("User settings")
|
||||
|
||||
def get(self, request: HttpRequest):
|
||||
context = {
|
||||
"user": request.user,
|
||||
TAB_TITLE_IDENTIFIER: self._TAB_TITLE,
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, self._TEMPLATE, context)
|
||||
|
||||
|
||||
class NotificationsView(LoginRequiredMixin, UserBaseView):
|
||||
_TEMPLATE = "user/notifications.html"
|
||||
_TAB_TITLE = _("User notifications")
|
||||
|
||||
def get(self, request: HttpRequest):
|
||||
user = request.user
|
||||
form = UserNotificationForm(user=user, data=None)
|
||||
context = {
|
||||
"user": user,
|
||||
"form": form,
|
||||
TAB_TITLE_IDENTIFIER: self._TAB_TITLE,
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, self._TEMPLATE, context)
|
||||
|
||||
def post(self, request: HttpRequest):
|
||||
user = request.user
|
||||
form = UserNotificationForm(user=user, data=request.POST)
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
messages.success(
|
||||
request,
|
||||
_("Notifications edited")
|
||||
)
|
||||
return redirect("user:detail")
|
||||
context = {
|
||||
"user": user,
|
||||
"form": form,
|
||||
TAB_TITLE_IDENTIFIER: self._TAB_TITLE,
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, self._TEMPLATE, context)
|
||||
|
||||
|
||||
class ContactView(LoginRequiredMixin, BaseModalFormView):
|
||||
def get(self, request: HttpRequest, id: str):
|
||||
""" Renders contact modal view of a users contact data
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
id (str): The user's id
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
user = get_object_or_404(User, id=id)
|
||||
form = UserContactForm(request.POST or None, instance=user, request=request)
|
||||
context = {
|
||||
"form": form,
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, self._TEMPLATE, context)
|
||||
|
||||
def _user_has_shared_access(self, user, **kwargs):
|
||||
# No specific constraints
|
||||
return True
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
# No specific constraints
|
||||
return True
|
||||
|
||||
|
||||
class TeamDetailModalView(LoginRequiredMixin, BaseModalFormView):
|
||||
def get(self, request: HttpRequest, id: str):
|
||||
""" Renders team data
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
id (str): The team's id
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
team = get_object_or_404(Team, id=id)
|
||||
form = TeamDataForm(request.POST or None, instance=team, request=request)
|
||||
context = {
|
||||
"form": form,
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, self._TEMPLATE, context)
|
||||
|
||||
def _user_has_shared_access(self, user, **kwargs):
|
||||
# No specific constraints
|
||||
return True
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
# No specific constraints
|
||||
return True
|
||||
|
||||
|
||||
class TeamIndexView(LoginRequiredMixin, UserBaseView):
|
||||
_TEMPLATE = "user/team/index.html"
|
||||
_TAB_TITLE = _("Teams")
|
||||
|
||||
def get(self, request: HttpRequest):
|
||||
user = request.user
|
||||
context = {
|
||||
"teams": user.shared_teams,
|
||||
"tab_title": self._TAB_TITLE,
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, self._TEMPLATE, context)
|
||||
|
||||
|
||||
@login_required_modal
|
||||
@login_required
|
||||
def new_team_view(request: HttpRequest):
|
||||
form = NewTeamModalForm(request.POST or None, request=request)
|
||||
return form.process_request(
|
||||
request,
|
||||
_("New team added"),
|
||||
redirect_url=reverse("user:team-index")
|
||||
)
|
||||
|
||||
|
||||
@login_required_modal
|
||||
@login_required
|
||||
def edit_team_view(request: HttpRequest, id: str):
|
||||
team = get_object_or_404(Team, id=id)
|
||||
user_is_admin = team.is_user_admin(request.user)
|
||||
if not user_is_admin:
|
||||
raise Http404()
|
||||
form = EditTeamModalForm(request.POST or None, instance=team, request=request)
|
||||
return form.process_request(
|
||||
request,
|
||||
_("Team edited"),
|
||||
redirect_url=reverse("user:team-index")
|
||||
)
|
||||
|
||||
|
||||
@login_required_modal
|
||||
@login_required
|
||||
def remove_team_view(request: HttpRequest, id: str):
|
||||
team = get_object_or_404(Team, id=id)
|
||||
user_is_admin = team.is_user_admin(request.user)
|
||||
if not user_is_admin:
|
||||
raise Http404()
|
||||
form = RemoveTeamModalForm(request.POST or None, instance=team, request=request)
|
||||
return form.process_request(
|
||||
request,
|
||||
_("Team removed"),
|
||||
redirect_url=reverse("user:team-index")
|
||||
)
|
||||
|
||||
|
||||
@login_required_modal
|
||||
@login_required
|
||||
def leave_team_view(request: HttpRequest, id: str):
|
||||
team = get_object_or_404(Team, id=id)
|
||||
user = request.user
|
||||
|
||||
is_user_team_member = team.users.filter(id=user.id).exists()
|
||||
if not is_user_team_member:
|
||||
messages.info(
|
||||
request,
|
||||
_("You are not a member of this team")
|
||||
)
|
||||
return redirect("user:team-index")
|
||||
|
||||
form = LeaveTeamModalForm(request.POST or None, instance=team, request=request)
|
||||
return form.process_request(
|
||||
request,
|
||||
_("Left Team"),
|
||||
redirect_url=reverse("user:team-index")
|
||||
)
|
||||
Reference in New Issue
Block a user