Compare commits
97 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 970d0e79fa | |||
| 3f33de3626 | |||
| 9e5bb84ab4 | |||
| 4c372c1a04 | |||
| ee2c859a9e | |||
| 328f672ec0 | |||
| 88058d7caf | |||
| 0e6f8d5b55 | |||
| 047c9489fe | |||
| 38b81996ed | |||
| 3966521cd4 | |||
| e70a8b51d1 | |||
| 02dc0d0a59 | |||
| 0b84d418db | |||
| 6aad76866f | |||
| 1af807deae | |||
| a2bda8d230 | |||
| e4c459f92e | |||
| 2da6f1dc6f | |||
| 72914bab9d | |||
| fdf3adf5ae | |||
| 4c4d64cc3d | |||
| fbde03caec | |||
| 43eb598d3f | |||
| b7fac0ae03 | |||
| 447ba942b5 | |||
| 6df47f1615 | |||
| e25d549a97 | |||
| 5e65b8f4dc | |||
| 22cddb9902 | |||
| c986bd0b92 | |||
| 2c60d86177 | |||
| b7792ececc | |||
| 210f3fcafa | |||
| e7d67560f2 | |||
| b5e991fb95 | |||
| d3a555d406 | |||
| 9a374f50de | |||
| ce63dd30bc | |||
| e5db7f6b13 | |||
| 442f3ceb37 | |||
| cd2949fc03 | |||
| 7bcd32fd7a | |||
| 97f1882698 | |||
| 55cc8eb1f3 | |||
| d6cabd5f6c | |||
| 63a824f9d9 | |||
| a12c2fb57e | |||
| 23bc79ee3b | |||
| 07bac26a58 | |||
| d01816cf71 | |||
| f543dfc1cb | |||
| 62fc019127 | |||
| c01518b675 | |||
| f57306eb72 | |||
| c2b12649b0 | |||
| 6fe67a8fbf | |||
| b38a266bea | |||
| 15f86e866b | |||
| c85b136f0a | |||
| faf8aed777 | |||
| 94c498866f | |||
| 616965c890 | |||
| e39c7eb51f | |||
| 19bd408fbd | |||
| 7bfe6a37f8 | |||
| 9b63307f01 | |||
| 123a470006 | |||
| 5a0c5285e7 | |||
| 3a01eaff92 | |||
| 2af91aa178 | |||
| 53d0af89ac | |||
| 7b5c1f0d97 | |||
| ef076c0b3b | |||
| 72a5075f3b | |||
| d677ac6b5a | |||
| 9149e4cbd3 | |||
| 1c24cbea26 | |||
|
|
bc9cc09372 | ||
| 24518465f3 | |||
| 457548da4d | |||
| fa89bbba99 | |||
| 78eb711057 | |||
| 6ff67d12c9 | |||
| 3c1cbcd0bd | |||
| 416ad8478c | |||
| 6b28c4ec15 | |||
| 46a2a4ff46 | |||
| 90e5cf5b36 | |||
| 50f46e319c | |||
| e2ea087c4e | |||
| a6e43b044b | |||
| be0d261e81 | |||
| 62e1b046c3 | |||
| 669a12410f | |||
| dd77e6c16e | |||
| 33774ce557 |
@@ -24,6 +24,7 @@ DEFAULT_FROM_EMAIL=service@ksp.de
|
|||||||
|
|
||||||
# Proxy
|
# Proxy
|
||||||
PROXY=CHANGE_ME
|
PROXY=CHANGE_ME
|
||||||
|
MAP_PROXY_HOST_WHITELIST=CHANGE_ME_1,CHANGE_ME_2
|
||||||
GEOPORTAL_RLP_USER=CHANGE_ME
|
GEOPORTAL_RLP_USER=CHANGE_ME
|
||||||
GEOPORTAL_RLP_PASSWORD=CHANGE_ME
|
GEOPORTAL_RLP_PASSWORD=CHANGE_ME
|
||||||
|
|
||||||
@@ -37,6 +38,7 @@ SSO_SERVER_BASE_URL=https://login.naturschutz.rlp.de
|
|||||||
OAUTH_CODE_VERIFIER=CHANGE_ME
|
OAUTH_CODE_VERIFIER=CHANGE_ME
|
||||||
OAUTH_CLIENT_ID=CHANGE_ME
|
OAUTH_CLIENT_ID=CHANGE_ME
|
||||||
OAUTH_CLIENT_SECRET=CHANGE_ME
|
OAUTH_CLIENT_SECRET=CHANGE_ME
|
||||||
|
PROPAGATION_SECRET=CHANGE_ME
|
||||||
|
|
||||||
# RabbitMQ
|
# RabbitMQ
|
||||||
## For connections to EGON
|
## For connections to EGON
|
||||||
|
|||||||
@@ -10,6 +10,6 @@ from analysis.views import *
|
|||||||
|
|
||||||
app_name = "analysis"
|
app_name = "analysis"
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("reports/", index_reports_view, name="reports"),
|
path("reports/", ReportIndexView.as_view(), name="reports"),
|
||||||
path("reports/<id>", detail_report_view, name="report-detail"),
|
path("reports/<id>", ReportDetailView.as_view(), name="report-detail"),
|
||||||
]
|
]
|
||||||
@@ -1,8 +1,12 @@
|
|||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
from django.http import HttpRequest, HttpResponse
|
from django.http import HttpRequest, HttpResponse
|
||||||
from django.shortcuts import render, redirect, get_object_or_404
|
from django.shortcuts import render, redirect, get_object_or_404
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
from django.utils.decorators import method_decorator
|
||||||
|
from django.views import View
|
||||||
|
from django.views.generic import DetailView
|
||||||
|
|
||||||
from analysis.forms import TimespanReportForm
|
from analysis.forms import TimespanReportForm
|
||||||
from analysis.utils.excel.excel import TempExcelFile
|
from analysis.utils.excel.excel import TempExcelFile
|
||||||
@@ -42,57 +46,112 @@ def index_reports_view(request: HttpRequest):
|
|||||||
context = BaseContext(request, context).context
|
context = BaseContext(request, context).context
|
||||||
return render(request, template, context)
|
return render(request, template, context)
|
||||||
|
|
||||||
|
class ReportIndexView(LoginRequiredMixin, View):
|
||||||
|
@method_decorator(conservation_office_group_required)
|
||||||
|
def get(self, request: HttpRequest) -> HttpResponse:
|
||||||
|
|
||||||
@login_required
|
"""
|
||||||
@conservation_office_group_required
|
|
||||||
def detail_report_view(request: HttpRequest, id: str):
|
|
||||||
""" Renders the detailed report for a conservation office
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
request (HttpRequest): The incoming request
|
request (HttpRequest): The incoming request
|
||||||
id (str): The conservation_office KonovaCode id
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
# Try to resolve the requested office id
|
template = "analysis/reports/index.html"
|
||||||
cons_office = get_object_or_404(
|
form = TimespanReportForm(None)
|
||||||
KonovaCode,
|
context = {
|
||||||
id=id
|
"form": form
|
||||||
)
|
}
|
||||||
# Try to resolve the date parameters into Date objects -> redirect if this fails
|
context = BaseContext(request, context).context
|
||||||
try:
|
return render(request, template, context)
|
||||||
df = request.GET.get("df", None)
|
|
||||||
dt = request.GET.get("dt", None)
|
@method_decorator(conservation_office_group_required)
|
||||||
date_from = timezone.make_aware(timezone.datetime.fromisoformat(df))
|
def post(self, request: HttpRequest) -> HttpResponse:
|
||||||
date_to = timezone.make_aware(timezone.datetime.fromisoformat(dt))
|
|
||||||
except ValueError:
|
"""
|
||||||
messages.error(
|
|
||||||
request,
|
Args:
|
||||||
PARAMS_INVALID,
|
request (HttpRequest): The incoming request
|
||||||
extra_tags="danger",
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
"""
|
||||||
|
template = "analysis/reports/index.html"
|
||||||
|
form = TimespanReportForm(request.POST or None)
|
||||||
|
if form.is_valid():
|
||||||
|
redirect_url = form.save()
|
||||||
|
return redirect(redirect_url)
|
||||||
|
else:
|
||||||
|
messages.error(
|
||||||
|
request,
|
||||||
|
FORM_INVALID,
|
||||||
|
extra_tags="danger",
|
||||||
|
)
|
||||||
|
context = {
|
||||||
|
"form": form
|
||||||
|
}
|
||||||
|
context = BaseContext(request, context).context
|
||||||
|
return render(request, template, context)
|
||||||
|
|
||||||
|
|
||||||
|
class ReportDetailView(LoginRequiredMixin, DetailView):
|
||||||
|
|
||||||
|
@method_decorator(conservation_office_group_required)
|
||||||
|
def get(self, request: HttpRequest, id: str):
|
||||||
|
""" Renders the detailed report for a conservation office
|
||||||
|
|
||||||
|
Args:
|
||||||
|
request (HttpRequest): The incoming request
|
||||||
|
id (str): The conservation_office KonovaCode id
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
"""
|
||||||
|
# Try to resolve the requested office id
|
||||||
|
cons_office = get_object_or_404(
|
||||||
|
KonovaCode,
|
||||||
|
id=id
|
||||||
)
|
)
|
||||||
return redirect("analysis:reports")
|
# Try to resolve the date parameters into Date objects -> redirect if this fails
|
||||||
|
try:
|
||||||
|
df = request.GET.get("df", None)
|
||||||
|
dt = request.GET.get("dt", None)
|
||||||
|
date_from = timezone.make_aware(timezone.datetime.fromisoformat(df))
|
||||||
|
date_to = timezone.make_aware(timezone.datetime.fromisoformat(dt))
|
||||||
|
except ValueError:
|
||||||
|
messages.error(
|
||||||
|
request,
|
||||||
|
PARAMS_INVALID,
|
||||||
|
extra_tags="danger",
|
||||||
|
)
|
||||||
|
return redirect("analysis:reports")
|
||||||
|
|
||||||
# Check whether the html default rendering is requested or an alternative
|
# Check whether the html default rendering is requested or an alternative
|
||||||
format_param = request.GET.get("format", "html")
|
format_param = request.GET.get("format", "html")
|
||||||
report = TimespanReport(id, date_from, date_to)
|
report = TimespanReport(id, date_from, date_to)
|
||||||
|
|
||||||
if format_param == "html":
|
if format_param == "html":
|
||||||
|
return self.__handle_html_format(request, report, cons_office)
|
||||||
|
elif format_param == "excel":
|
||||||
|
return self.__handle_excel_format(report, cons_office, df, dt)
|
||||||
|
else:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def __handle_html_format(self, request, report: TimespanReport, office: KonovaCode):
|
||||||
template = "analysis/reports/detail.html"
|
template = "analysis/reports/detail.html"
|
||||||
context = {
|
context = {
|
||||||
"office": cons_office,
|
"office": office,
|
||||||
"report": report,
|
"report": report,
|
||||||
}
|
}
|
||||||
context = BaseContext(request, context).context
|
context = BaseContext(request, context).context
|
||||||
return render(request, template, context)
|
return render(request, template, context)
|
||||||
elif format_param == "excel":
|
|
||||||
|
def __handle_excel_format(self, report: TimespanReport, office: KonovaCode, df: str, dt: str):
|
||||||
file = TempExcelFile(report.excel_template_path, report.excel_map)
|
file = TempExcelFile(report.excel_template_path, report.excel_map)
|
||||||
response = HttpResponse(
|
response = HttpResponse(
|
||||||
content=file.stream,
|
content=file.stream,
|
||||||
content_type="application/ms-excel",
|
content_type="application/ms-excel",
|
||||||
)
|
)
|
||||||
response['Content-Disposition'] = f'attachment; filename={cons_office.long_name}_{df}_{dt}.xlsx'
|
response['Content-Disposition'] = f'attachment; filename={office.long_name}_{df}_{dt}.xlsx'
|
||||||
return response
|
return response
|
||||||
else:
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ class APIUserToken(models.Model):
|
|||||||
if token_obj.valid_until is not None and token_obj.valid_until < _today:
|
if token_obj.valid_until is not None and token_obj.valid_until < _today:
|
||||||
raise PermissionError("Token validity expired")
|
raise PermissionError("Token validity expired")
|
||||||
except ObjectDoesNotExist:
|
except ObjectDoesNotExist:
|
||||||
raise PermissionError("Credentials invalid")
|
raise PermissionError("Token unknown")
|
||||||
return token_obj.user
|
return token_obj.user
|
||||||
|
|
||||||
|
|
||||||
@@ -155,3 +155,25 @@ class OAuthToken(UuidModel):
|
|||||||
|
|
||||||
return user
|
return user
|
||||||
|
|
||||||
|
def revoke(self) -> int:
|
||||||
|
""" Revokes the OAuth2 token of the user
|
||||||
|
|
||||||
|
(/o/revoke_token/ indeed removes the corresponding access token on provider side and invalidates the
|
||||||
|
submitted refresh token in one step)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
revocation_status_code (int): HTTP status code for revocation of refresh_token
|
||||||
|
"""
|
||||||
|
revoke_url = f"{SSO_SERVER_BASE}o/revoke_token/"
|
||||||
|
token = self.refresh_token
|
||||||
|
revocation_status_code = requests.post(
|
||||||
|
revoke_url,
|
||||||
|
data={
|
||||||
|
'token': token,
|
||||||
|
'token_type_hint': "refresh_token",
|
||||||
|
},
|
||||||
|
auth=(OAUTH_CLIENT_ID, OAUTH_CLIENT_SECRET),
|
||||||
|
).status_code
|
||||||
|
|
||||||
|
return revocation_status_code
|
||||||
|
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ class APIV1CreateTestCase(BaseAPIV1TestCase):
|
|||||||
# Expect this first request to fail, since user has no shared access on the intervention, we want to create
|
# Expect this first request to fail, since user has no shared access on the intervention, we want to create
|
||||||
# a compensation for
|
# a compensation for
|
||||||
response = self._run_create_request(url, post_body)
|
response = self._run_create_request(url, post_body)
|
||||||
self.assertEqual(response.status_code, 500, msg=response.content)
|
self.assertEqual(response.status_code, 400, msg=response.content)
|
||||||
content = json.loads(response.content)
|
content = json.loads(response.content)
|
||||||
self.assertGreater(len(content.get("errors", [])), 0, msg=response.content)
|
self.assertGreater(len(content.get("errors", [])), 0, msg=response.content)
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ from django.contrib.gis import geos
|
|||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
from api.tests.v1.share.test_api_sharing import BaseAPIV1TestCase
|
from api.tests.v1.share.test_api_sharing import BaseAPIV1TestCase
|
||||||
from konova.sub_settings.lanis_settings import DEFAULT_SRID_RLP
|
from konova.models import Geometry
|
||||||
|
|
||||||
|
|
||||||
class APIV1UpdateTestCase(BaseAPIV1TestCase):
|
class APIV1UpdateTestCase(BaseAPIV1TestCase):
|
||||||
@@ -64,7 +64,7 @@ class APIV1UpdateTestCase(BaseAPIV1TestCase):
|
|||||||
|
|
||||||
put_props = put_body["properties"]
|
put_props = put_body["properties"]
|
||||||
put_geom = geos.fromstr(json.dumps(put_body))
|
put_geom = geos.fromstr(json.dumps(put_body))
|
||||||
put_geom.transform(DEFAULT_SRID_RLP)
|
put_geom = Geometry.cast_to_rlp_srid(put_geom)
|
||||||
self.assertEqual(put_geom, self.intervention.geometry.geom)
|
self.assertEqual(put_geom, self.intervention.geometry.geom)
|
||||||
self.assertEqual(put_props["title"], self.intervention.title)
|
self.assertEqual(put_props["title"], self.intervention.title)
|
||||||
self.assertNotEqual(modified_on, self.intervention.modified)
|
self.assertNotEqual(modified_on, self.intervention.modified)
|
||||||
@@ -94,7 +94,7 @@ class APIV1UpdateTestCase(BaseAPIV1TestCase):
|
|||||||
|
|
||||||
put_props = put_body["properties"]
|
put_props = put_body["properties"]
|
||||||
put_geom = geos.fromstr(json.dumps(put_body))
|
put_geom = geos.fromstr(json.dumps(put_body))
|
||||||
put_geom.transform(DEFAULT_SRID_RLP)
|
put_geom = Geometry.cast_to_rlp_srid(put_geom)
|
||||||
self.assertEqual(put_geom, self.compensation.geometry.geom)
|
self.assertEqual(put_geom, self.compensation.geometry.geom)
|
||||||
self.assertEqual(put_props["title"], self.compensation.title)
|
self.assertEqual(put_props["title"], self.compensation.title)
|
||||||
self.assertNotEqual(modified_on, self.compensation.modified)
|
self.assertNotEqual(modified_on, self.compensation.modified)
|
||||||
@@ -124,7 +124,7 @@ class APIV1UpdateTestCase(BaseAPIV1TestCase):
|
|||||||
|
|
||||||
put_props = put_body["properties"]
|
put_props = put_body["properties"]
|
||||||
put_geom = geos.fromstr(json.dumps(put_body))
|
put_geom = geos.fromstr(json.dumps(put_body))
|
||||||
put_geom.transform(DEFAULT_SRID_RLP)
|
put_geom = Geometry.cast_to_rlp_srid(put_geom)
|
||||||
self.assertEqual(put_geom, self.eco_account.geometry.geom)
|
self.assertEqual(put_geom, self.eco_account.geometry.geom)
|
||||||
self.assertEqual(put_props["title"], self.eco_account.title)
|
self.assertEqual(put_props["title"], self.eco_account.title)
|
||||||
self.assertNotEqual(modified_on, self.eco_account.modified)
|
self.assertNotEqual(modified_on, self.eco_account.modified)
|
||||||
@@ -156,7 +156,7 @@ class APIV1UpdateTestCase(BaseAPIV1TestCase):
|
|||||||
|
|
||||||
put_props = put_body["properties"]
|
put_props = put_body["properties"]
|
||||||
put_geom = geos.fromstr(json.dumps(put_body))
|
put_geom = geos.fromstr(json.dumps(put_body))
|
||||||
put_geom.transform(DEFAULT_SRID_RLP)
|
put_geom = Geometry.cast_to_rlp_srid(put_geom)
|
||||||
self.assertEqual(put_geom, self.ema.geometry.geom)
|
self.assertEqual(put_geom, self.ema.geometry.geom)
|
||||||
self.assertEqual(put_props["title"], self.ema.title)
|
self.assertEqual(put_props["title"], self.ema.title)
|
||||||
self.assertNotEqual(modified_on, self.ema.modified)
|
self.assertNotEqual(modified_on, self.ema.modified)
|
||||||
|
|||||||
@@ -7,11 +7,8 @@ Created on: 21.01.22
|
|||||||
"""
|
"""
|
||||||
from django.urls import path, include
|
from django.urls import path, include
|
||||||
|
|
||||||
from api.views.method_views import generate_new_token_view
|
|
||||||
|
|
||||||
app_name = "api"
|
app_name = "api"
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("v1/", include("api.urls.v1.urls", namespace="v1")),
|
path("v1/", include("api.urls.v1.urls", namespace="v1")),
|
||||||
path("token/generate", generate_new_token_view, name="generate-new-token"),
|
|
||||||
]
|
]
|
||||||
@@ -13,7 +13,7 @@ from django.contrib.gis.geos import GEOSGeometry
|
|||||||
from django.core.paginator import Paginator
|
from django.core.paginator import Paginator
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
|
|
||||||
from konova.sub_settings.lanis_settings import DEFAULT_SRID_RLP
|
from konova.models import Geometry
|
||||||
from konova.utils.message_templates import DATA_UNSHARED
|
from konova.utils.message_templates import DATA_UNSHARED
|
||||||
|
|
||||||
|
|
||||||
@@ -145,8 +145,8 @@ class AbstractModelAPISerializer:
|
|||||||
if isinstance(geojson, dict):
|
if isinstance(geojson, dict):
|
||||||
geojson = json.dumps(geojson)
|
geojson = json.dumps(geojson)
|
||||||
geometry = geos.fromstr(geojson)
|
geometry = geos.fromstr(geojson)
|
||||||
if geometry.srid != DEFAULT_SRID_RLP:
|
geometry = Geometry.cast_to_rlp_srid(geometry)
|
||||||
geometry.transform(DEFAULT_SRID_RLP)
|
geometry = Geometry.cast_to_multipolygon(geometry)
|
||||||
return geometry
|
return geometry
|
||||||
|
|
||||||
def _get_obj_from_db(self, id, user):
|
def _get_obj_from_db(self, id, user):
|
||||||
|
|||||||
@@ -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
|
|
||||||
@@ -6,7 +6,9 @@ Created on: 21.01.22
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
import json
|
import json
|
||||||
|
from json import JSONDecodeError
|
||||||
|
|
||||||
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
from django.http import JsonResponse, HttpRequest
|
from django.http import JsonResponse, HttpRequest
|
||||||
|
|
||||||
from api.utils.serializer.v1.compensation import CompensationAPISerializerV1
|
from api.utils.serializer.v1.compensation import CompensationAPISerializerV1
|
||||||
@@ -66,8 +68,12 @@ class AbstractAPIViewV1(AbstractAPIView):
|
|||||||
body = request.body.decode("utf-8")
|
body = request.body.decode("utf-8")
|
||||||
body = json.loads(body)
|
body = json.loads(body)
|
||||||
created_id = self.serializer.create_model_from_json(body, self.user)
|
created_id = self.serializer.create_model_from_json(body, self.user)
|
||||||
except Exception as e:
|
except (JSONDecodeError,
|
||||||
return self._return_error_response(e, 500)
|
AssertionError,
|
||||||
|
ValueError,
|
||||||
|
PermissionError,
|
||||||
|
ObjectDoesNotExist) as e:
|
||||||
|
return self._return_error_response(e, 400)
|
||||||
return JsonResponse({"id": created_id})
|
return JsonResponse({"id": created_id})
|
||||||
|
|
||||||
def put(self, request: HttpRequest, id=None):
|
def put(self, request: HttpRequest, id=None):
|
||||||
|
|||||||
@@ -50,14 +50,19 @@ class AbstractAPIView(View):
|
|||||||
def dispatch(self, request, *args, **kwargs):
|
def dispatch(self, request, *args, **kwargs):
|
||||||
try:
|
try:
|
||||||
# Fetch the proper user from the given request header token
|
# Fetch the proper user from the given request header token
|
||||||
ksp_token = request.headers.get(KSP_TOKEN_HEADER_IDENTIFIER, None)
|
token = request.headers.get(KSP_TOKEN_HEADER_IDENTIFIER, None)
|
||||||
ksp_user = request.headers.get(KSP_USER_HEADER_IDENTIFIER, None)
|
ksp_user = request.headers.get(KSP_USER_HEADER_IDENTIFIER, None)
|
||||||
token_user = APIUserToken.get_user_from_token(ksp_token)
|
|
||||||
|
|
||||||
if ksp_user != token_user.username:
|
if not token and not ksp_user:
|
||||||
|
bearer_token = request.headers.get("authorization", None)
|
||||||
|
if not bearer_token:
|
||||||
|
raise PermissionError("No token provided")
|
||||||
|
token = bearer_token.split(" ")[1]
|
||||||
|
|
||||||
|
token_user = APIUserToken.get_user_from_token(token)
|
||||||
|
if ksp_user and ksp_user != token_user.username:
|
||||||
raise PermissionError(f"Invalid token for {ksp_user}")
|
raise PermissionError(f"Invalid token for {ksp_user}")
|
||||||
else:
|
self.user = token_user
|
||||||
self.user = token_user
|
|
||||||
|
|
||||||
request.user = self.user
|
request.user = self.user
|
||||||
if not self.user.is_default_user():
|
if not self.user.is_default_user():
|
||||||
@@ -76,9 +81,7 @@ class AbstractAPIView(View):
|
|||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
content = [error.__str__()]
|
content = [f"{error.__class__.__name__}: {str(error)}"]
|
||||||
if hasattr(error, "messages"):
|
|
||||||
content = error.messages
|
|
||||||
return JsonResponse(
|
return JsonResponse(
|
||||||
{
|
{
|
||||||
"errors": content
|
"errors": content
|
||||||
|
|||||||
@@ -82,8 +82,8 @@ class Command(BaseKonovaCommand):
|
|||||||
atom_id = element.find("atomid").text
|
atom_id = element.find("atomid").text
|
||||||
selectable = element.find("selectable").text.lower()
|
selectable = element.find("selectable").text.lower()
|
||||||
selectable = bool_map.get(selectable, False)
|
selectable = bool_map.get(selectable, False)
|
||||||
short_name = element.find("shortname").text
|
short_name = element.find("shortname").text or ""
|
||||||
long_name = element.find("longname").text
|
long_name = element.find("longname").text or ""
|
||||||
is_archived = bool_map.get((element.find("archive").text.lower()), False)
|
is_archived = bool_map.get((element.find("archive").text.lower()), False)
|
||||||
|
|
||||||
code = KonovaCode.objects.get_or_create(
|
code = KonovaCode.objects.get_or_create(
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
# Generated by Django 5.0.8 on 2024-08-26 16:47
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('codelist', '0002_migrate_975_to_288'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='konovacode',
|
||||||
|
name='long_name',
|
||||||
|
field=models.CharField(blank=True, default="", max_length=1000),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='konovacode',
|
||||||
|
name='short_name',
|
||||||
|
field=models.CharField(blank=True, default="", help_text='Short version of long name', max_length=500),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -45,6 +45,14 @@ class AbstractCompensationAdmin(BaseObjectAdmin):
|
|||||||
states = "\n".join(states)
|
states = "\n".join(states)
|
||||||
return states
|
return states
|
||||||
|
|
||||||
|
def get_actions(self, request):
|
||||||
|
DELETE_ACTION_IDENTIFIER = "delete_selected"
|
||||||
|
actions = super().get_actions(request)
|
||||||
|
|
||||||
|
if DELETE_ACTION_IDENTIFIER in actions:
|
||||||
|
del actions[DELETE_ACTION_IDENTIFIER]
|
||||||
|
|
||||||
|
return actions
|
||||||
|
|
||||||
class CompensationAdmin(AbstractCompensationAdmin):
|
class CompensationAdmin(AbstractCompensationAdmin):
|
||||||
autocomplete_fields = [
|
autocomplete_fields = [
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ from compensation.models import EcoAccount
|
|||||||
from intervention.models import Handler, Responsibility, Legal
|
from intervention.models import Handler, Responsibility, Legal
|
||||||
from konova.forms import SimpleGeomForm
|
from konova.forms import SimpleGeomForm
|
||||||
from konova.forms.modals import RemoveModalForm
|
from konova.forms.modals import RemoveModalForm
|
||||||
|
from konova.settings import ETS_GROUP
|
||||||
from konova.utils import validators
|
from konova.utils import validators
|
||||||
from user.models import User, UserActionLogEntry
|
from user.models import User, UserActionLogEntry
|
||||||
|
|
||||||
@@ -246,4 +247,13 @@ class RemoveEcoAccountModalForm(RemoveModalForm):
|
|||||||
"confirm",
|
"confirm",
|
||||||
_("The account can not be removed, since there are still deductions.")
|
_("The account can not be removed, since there are still deductions.")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# If there are deductions but the performing user is not part of an ETS group, we assume this poor
|
||||||
|
# fella does not know what he/she does -> give a hint that they should contact someone in charge...
|
||||||
|
user_is_ets_user = self.user.in_group(ETS_GROUP)
|
||||||
|
if not user_is_ets_user:
|
||||||
|
self.add_error(
|
||||||
|
"confirm",
|
||||||
|
_("Please contact the responsible conservation office to find a solution!")
|
||||||
|
)
|
||||||
return super_valid and not has_deductions
|
return super_valid and not has_deductions
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# Generated by Django 5.0.8 on 2024-08-26 16:47
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('codelist', '0003_alter_konovacode_long_name_and_more'),
|
||||||
|
('compensation', '0015_alter_compensation_after_states_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='compensationstate',
|
||||||
|
name='biotope_type_details',
|
||||||
|
field=models.ManyToManyField(blank=True, limit_choices_to={'code_lists__in': [288], 'is_archived': False, 'is_selectable': True}, related_name='+', to='codelist.konovacode'),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
</td>
|
</td>
|
||||||
<td class="align-middle">
|
<td class="align-middle">
|
||||||
{% if deduction.intervention.recorded %}
|
{% 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 %}
|
{% else %}
|
||||||
<em title="{% trans 'Not recorded yet' %}" class='far fa-bookmark'></em>
|
<em title="{% trans 'Not recorded yet' %}" class='far fa-bookmark'></em>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ class CompensationWorkflowTestCase(BaseWorkflowTestCase):
|
|||||||
post_data = {
|
post_data = {
|
||||||
"identifier": test_id,
|
"identifier": test_id,
|
||||||
"title": test_title,
|
"title": test_title,
|
||||||
"geom": geom_json,
|
"output": geom_json,
|
||||||
"intervention": self.intervention.id,
|
"intervention": self.intervention.id,
|
||||||
}
|
}
|
||||||
pre_creation_intervention_log_count = self.intervention.log.count()
|
pre_creation_intervention_log_count = self.intervention.log.count()
|
||||||
@@ -94,7 +94,7 @@ class CompensationWorkflowTestCase(BaseWorkflowTestCase):
|
|||||||
post_data = {
|
post_data = {
|
||||||
"identifier": test_id,
|
"identifier": test_id,
|
||||||
"title": test_title,
|
"title": test_title,
|
||||||
"geom": geom_json,
|
"output": geom_json,
|
||||||
}
|
}
|
||||||
pre_creation_intervention_log_count = self.intervention.log.count()
|
pre_creation_intervention_log_count = self.intervention.log.count()
|
||||||
|
|
||||||
@@ -150,7 +150,7 @@ class CompensationWorkflowTestCase(BaseWorkflowTestCase):
|
|||||||
"title": new_title,
|
"title": new_title,
|
||||||
"intervention": self.intervention.id, # just keep the intervention as it is
|
"intervention": self.intervention.id, # just keep the intervention as it is
|
||||||
"comment": new_comment,
|
"comment": new_comment,
|
||||||
"geom": geojson,
|
"output": geojson,
|
||||||
}
|
}
|
||||||
self.client_user.post(url, post_data)
|
self.client_user.post(url, post_data)
|
||||||
self.compensation.refresh_from_db()
|
self.compensation.refresh_from_db()
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ class EcoAccountWorkflowTestCase(BaseWorkflowTestCase):
|
|||||||
post_data = {
|
post_data = {
|
||||||
"identifier": test_id,
|
"identifier": test_id,
|
||||||
"title": test_title,
|
"title": test_title,
|
||||||
"geom": geom_json,
|
"output": geom_json,
|
||||||
"surface": test_deductable_surface,
|
"surface": test_deductable_surface,
|
||||||
"conservation_office": test_conservation_office.id
|
"conservation_office": test_conservation_office.id
|
||||||
}
|
}
|
||||||
@@ -86,7 +86,7 @@ class EcoAccountWorkflowTestCase(BaseWorkflowTestCase):
|
|||||||
new_title = self.create_dummy_string()
|
new_title = self.create_dummy_string()
|
||||||
new_identifier = self.create_dummy_string()
|
new_identifier = self.create_dummy_string()
|
||||||
new_comment = self.create_dummy_string()
|
new_comment = self.create_dummy_string()
|
||||||
new_geometry = MultiPolygon(srid=4326) # Create an empty geometry
|
new_geometry = self.create_dummy_geometry()
|
||||||
test_conservation_office = self.get_conservation_office_code()
|
test_conservation_office = self.get_conservation_office_code()
|
||||||
test_deductable_surface = self.eco_account.deductable_surface + 100
|
test_deductable_surface = self.eco_account.deductable_surface + 100
|
||||||
|
|
||||||
@@ -103,7 +103,7 @@ class EcoAccountWorkflowTestCase(BaseWorkflowTestCase):
|
|||||||
"identifier": new_identifier,
|
"identifier": new_identifier,
|
||||||
"title": new_title,
|
"title": new_title,
|
||||||
"comment": new_comment,
|
"comment": new_comment,
|
||||||
"geom": new_geometry.geojson,
|
"output": self.create_geojson(new_geometry),
|
||||||
"surface": test_deductable_surface,
|
"surface": test_deductable_surface,
|
||||||
"conservation_office": test_conservation_office.id
|
"conservation_office": test_conservation_office.id
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,30 +7,32 @@ Created on: 24.08.21
|
|||||||
"""
|
"""
|
||||||
from django.urls import path
|
from django.urls import path
|
||||||
|
|
||||||
|
from compensation.views.compensation.detail import DetailCompensationView
|
||||||
from compensation.views.compensation.document import EditCompensationDocumentView, NewCompensationDocumentView, \
|
from compensation.views.compensation.document import EditCompensationDocumentView, NewCompensationDocumentView, \
|
||||||
GetCompensationDocumentView, RemoveCompensationDocumentView
|
GetCompensationDocumentView, RemoveCompensationDocumentView
|
||||||
|
from compensation.views.compensation.remove import RemoveCompensationView
|
||||||
from compensation.views.compensation.resubmission import CompensationResubmissionView
|
from compensation.views.compensation.resubmission import CompensationResubmissionView
|
||||||
from compensation.views.compensation.report import report_view
|
from compensation.views.compensation.report import CompensationPublicReportView
|
||||||
from compensation.views.compensation.deadline import NewCompensationDeadlineView, EditCompensationDeadlineView, \
|
from compensation.views.compensation.deadline import NewCompensationDeadlineView, EditCompensationDeadlineView, \
|
||||||
RemoveCompensationDeadlineView
|
RemoveCompensationDeadlineView
|
||||||
from compensation.views.compensation.action import NewCompensationActionView, EditCompensationActionView, \
|
from compensation.views.compensation.action import NewCompensationActionView, EditCompensationActionView, \
|
||||||
RemoveCompensationActionView
|
RemoveCompensationActionView
|
||||||
from compensation.views.compensation.state import NewCompensationStateView, EditCompensationStateView, \
|
from compensation.views.compensation.state import NewCompensationStateView, EditCompensationStateView, \
|
||||||
RemoveCompensationStateView
|
RemoveCompensationStateView
|
||||||
from compensation.views.compensation.compensation import index_view, new_view, new_id_view, detail_view, edit_view, \
|
from compensation.views.compensation.compensation import IndexCompensationView, CompensationIdentifierGeneratorView, \
|
||||||
remove_view
|
EditCompensationView, NewCompensationView
|
||||||
from compensation.views.compensation.log import CompensationLogView
|
from compensation.views.compensation.log import CompensationLogView
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
# Main compensation
|
# Main compensation
|
||||||
path("", index_view, name="index"),
|
path("", IndexCompensationView.as_view(), name="index"),
|
||||||
path('new/id', new_id_view, name='new-id'),
|
path('new/id', CompensationIdentifierGeneratorView.as_view(), name='new-id'),
|
||||||
path('new/<intervention_id>', new_view, name='new'),
|
path('new/<intervention_id>', NewCompensationView.as_view(), name='new'),
|
||||||
path('new', new_view, name='new'),
|
path('new', NewCompensationView.as_view(), name='new'),
|
||||||
path('<id>', detail_view, name='detail'),
|
path('<id>', DetailCompensationView.as_view(), name='detail'),
|
||||||
path('<id>/log', CompensationLogView.as_view(), name='log'),
|
path('<id>/log', CompensationLogView.as_view(), name='log'),
|
||||||
path('<id>/edit', edit_view, name='edit'),
|
path('<id>/edit', EditCompensationView.as_view(), name='edit'),
|
||||||
path('<id>/remove', remove_view, name='remove'),
|
path('<id>/remove', RemoveCompensationView.as_view(), name='remove'),
|
||||||
|
|
||||||
path('<id>/state/new', NewCompensationStateView.as_view(), name='new-state'),
|
path('<id>/state/new', NewCompensationStateView.as_view(), name='new-state'),
|
||||||
path('<id>/state/<state_id>/edit', EditCompensationStateView.as_view(), name='state-edit'),
|
path('<id>/state/<state_id>/edit', EditCompensationStateView.as_view(), name='state-edit'),
|
||||||
@@ -43,7 +45,7 @@ urlpatterns = [
|
|||||||
path('<id>/deadline/new', NewCompensationDeadlineView.as_view(), name="new-deadline"),
|
path('<id>/deadline/new', NewCompensationDeadlineView.as_view(), name="new-deadline"),
|
||||||
path('<id>/deadline/<deadline_id>/edit', EditCompensationDeadlineView.as_view(), name='deadline-edit'),
|
path('<id>/deadline/<deadline_id>/edit', EditCompensationDeadlineView.as_view(), name='deadline-edit'),
|
||||||
path('<id>/deadline/<deadline_id>/remove', RemoveCompensationDeadlineView.as_view(), name='deadline-remove'),
|
path('<id>/deadline/<deadline_id>/remove', RemoveCompensationDeadlineView.as_view(), name='deadline-remove'),
|
||||||
path('<id>/report', report_view, name='report'),
|
path('<id>/report', CompensationPublicReportView.as_view(), name='report'),
|
||||||
path('<id>/resub', CompensationResubmissionView.as_view(), name='resubmission-create'),
|
path('<id>/resub', CompensationResubmissionView.as_view(), name='resubmission-create'),
|
||||||
|
|
||||||
# Documents
|
# Documents
|
||||||
|
|||||||
@@ -8,11 +8,13 @@ Created on: 24.08.21
|
|||||||
from django.urls import path
|
from django.urls import path
|
||||||
|
|
||||||
from compensation.autocomplete.eco_account import EcoAccountAutocomplete
|
from compensation.autocomplete.eco_account import EcoAccountAutocomplete
|
||||||
from compensation.views.eco_account.eco_account import index_view, new_view, new_id_view, edit_view, remove_view, \
|
from compensation.views.eco_account.detail import DetailEcoAccountView
|
||||||
detail_view
|
from compensation.views.eco_account.eco_account import IndexEcoAccountView, EcoAccountIdentifierGeneratorView, \
|
||||||
|
NewEcoAccountView, EditEcoAccountView
|
||||||
from compensation.views.eco_account.log import EcoAccountLogView
|
from compensation.views.eco_account.log import EcoAccountLogView
|
||||||
from compensation.views.eco_account.record import EcoAccountRecordView
|
from compensation.views.eco_account.record import EcoAccountRecordView
|
||||||
from compensation.views.eco_account.report import report_view
|
from compensation.views.eco_account.remove import RemoveEcoAccountView
|
||||||
|
from compensation.views.eco_account.report import EcoAccountPublicReportView
|
||||||
from compensation.views.eco_account.resubmission import EcoAccountResubmissionView
|
from compensation.views.eco_account.resubmission import EcoAccountResubmissionView
|
||||||
from compensation.views.eco_account.state import NewEcoAccountStateView, EditEcoAccountStateView, \
|
from compensation.views.eco_account.state import NewEcoAccountStateView, EditEcoAccountStateView, \
|
||||||
RemoveEcoAccountStateView
|
RemoveEcoAccountStateView
|
||||||
@@ -28,15 +30,15 @@ from compensation.views.eco_account.deduction import NewEcoAccountDeductionView,
|
|||||||
|
|
||||||
app_name = "acc"
|
app_name = "acc"
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("", index_view, name="index"),
|
path("", IndexEcoAccountView.as_view(), name="index"),
|
||||||
path('new/', new_view, name='new'),
|
path('new/', NewEcoAccountView.as_view(), name='new'),
|
||||||
path('new/id', new_id_view, name='new-id'),
|
path('new/id', EcoAccountIdentifierGeneratorView.as_view(), name='new-id'),
|
||||||
path('<id>', detail_view, name='detail'),
|
path('<id>', DetailEcoAccountView.as_view(), name='detail'),
|
||||||
path('<id>/log', EcoAccountLogView.as_view(), name='log'),
|
path('<id>/log', EcoAccountLogView.as_view(), name='log'),
|
||||||
path('<id>/record', EcoAccountRecordView.as_view(), name='record'),
|
path('<id>/record', EcoAccountRecordView.as_view(), name='record'),
|
||||||
path('<id>/report', report_view, name='report'),
|
path('<id>/report', EcoAccountPublicReportView.as_view(), name='report'),
|
||||||
path('<id>/edit', edit_view, name='edit'),
|
path('<id>/edit', EditEcoAccountView.as_view(), name='edit'),
|
||||||
path('<id>/remove', remove_view, name='remove'),
|
path('<id>/remove', RemoveEcoAccountView.as_view(), name='remove'),
|
||||||
path('<id>/resub', EcoAccountResubmissionView.as_view(), name='resubmission-create'),
|
path('<id>/resub', EcoAccountResubmissionView.as_view(), name='resubmission-create'),
|
||||||
|
|
||||||
path('<id>/state/new', NewEcoAccountStateView.as_view(), name='new-state'),
|
path('<id>/state/new', NewEcoAccountStateView.as_view(), name='new-state'),
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ from compensation.views.payment import *
|
|||||||
|
|
||||||
app_name = "pay"
|
app_name = "pay"
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('<id>/new', new_payment_view, name='new'),
|
path('<id>/new', NewPaymentView.as_view(), name='new'),
|
||||||
path('<id>/remove/<payment_id>', payment_remove_view, name='remove'),
|
path('<id>/remove/<payment_id>', RemovePaymentView.as_view(), name='remove'),
|
||||||
path('<id>/edit/<payment_id>', payment_edit_view, name='edit'),
|
path('<id>/edit/<payment_id>', EditPaymentView.as_view(), name='edit'),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -6,91 +6,127 @@ Created on: 19.08.22
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
from django.contrib import messages
|
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, HttpResponse
|
||||||
from django.db.models import Sum
|
|
||||||
from django.http import HttpRequest, JsonResponse
|
|
||||||
from django.shortcuts import get_object_or_404, render, redirect
|
from django.shortcuts import get_object_or_404, render, redirect
|
||||||
from django.urls import reverse
|
from django.utils.decorators import method_decorator
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
from django.views import View
|
||||||
|
|
||||||
from compensation.forms.compensation import EditCompensationForm, NewCompensationForm
|
from compensation.forms.compensation import EditCompensationForm, NewCompensationForm
|
||||||
from compensation.models import Compensation
|
from compensation.models import Compensation
|
||||||
from compensation.tables.compensation import CompensationTable
|
from compensation.tables.compensation import CompensationTable
|
||||||
from intervention.models import Intervention
|
from intervention.models import Intervention
|
||||||
from konova.contexts import BaseContext
|
from konova.contexts import BaseContext
|
||||||
from konova.decorators import shared_access_required, default_group_required, any_group_check, login_required_modal, \
|
from konova.decorators import shared_access_required, default_group_required
|
||||||
uuid_required
|
|
||||||
from konova.forms import SimpleGeomForm
|
from konova.forms import SimpleGeomForm
|
||||||
from konova.forms.modals import RemoveModalForm
|
|
||||||
from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP
|
|
||||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
||||||
from konova.utils.message_templates import COMPENSATION_REMOVED_TEMPLATE, DATA_CHECKED_PREVIOUSLY_TEMPLATE, \
|
from konova.utils.message_templates import RECORDED_BLOCKS_EDIT, CHECK_STATE_RESET, FORM_INVALID, PARAMS_INVALID, \
|
||||||
RECORDED_BLOCKS_EDIT, CHECK_STATE_RESET, FORM_INVALID, PARAMS_INVALID, IDENTIFIER_REPLACED, \
|
IDENTIFIER_REPLACED, COMPENSATION_ADDED_TEMPLATE, GEOMETRY_SIMPLIFIED, GEOMETRIES_IGNORED_TEMPLATE
|
||||||
COMPENSATION_ADDED_TEMPLATE, DO_NOT_FORGET_TO_SHARE, GEOMETRY_SIMPLIFIED
|
from konova.views.identifier import AbstractIdentifierGeneratorView
|
||||||
|
from konova.views.index import AbstractIndexView
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
class IndexCompensationView(AbstractIndexView):
|
||||||
@any_group_check
|
def get(self, request, *args, **kwargs) -> HttpResponse:
|
||||||
def index_view(request: HttpRequest):
|
"""
|
||||||
"""
|
Renders the index view for compensation
|
||||||
Renders the index view for compensation
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
request (HttpRequest): The incoming request
|
request (HttpRequest): The incoming request
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
A rendered view
|
A rendered view
|
||||||
"""
|
"""
|
||||||
template = "generic_index.html"
|
compensations = Compensation.objects.filter(
|
||||||
compensations = Compensation.objects.filter(
|
deleted=None, # only show those which are not deleted individually
|
||||||
deleted=None, # only show those which are not deleted individually
|
intervention__deleted=None, # and don't show the ones whose intervention has been deleted
|
||||||
intervention__deleted=None, # and don't show the ones whose intervention has been deleted
|
).order_by(
|
||||||
).order_by(
|
"-modified__timestamp"
|
||||||
"-modified__timestamp"
|
)
|
||||||
)
|
table = CompensationTable(
|
||||||
table = CompensationTable(
|
request=request,
|
||||||
request=request,
|
queryset=compensations
|
||||||
queryset=compensations
|
)
|
||||||
)
|
context = {
|
||||||
context = {
|
"table": table,
|
||||||
"table": table,
|
TAB_TITLE_IDENTIFIER: _("Compensations - Overview"),
|
||||||
TAB_TITLE_IDENTIFIER: _("Compensations - Overview"),
|
}
|
||||||
}
|
context = BaseContext(request, context).context
|
||||||
context = BaseContext(request, context).context
|
return render(request, self._TEMPLATE, context)
|
||||||
return render(request, template, context)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
class NewCompensationView(LoginRequiredMixin, View):
|
||||||
@default_group_required
|
_TEMPLATE = "compensation/form/view.html"
|
||||||
@shared_access_required(Intervention, "intervention_id")
|
|
||||||
def new_view(request: HttpRequest, intervention_id: str = None):
|
|
||||||
"""
|
|
||||||
Renders a view for a new compensation creation
|
|
||||||
|
|
||||||
Args:
|
@method_decorator(default_group_required)
|
||||||
request (HttpRequest): The incoming request
|
@method_decorator(shared_access_required(Intervention, "intervention_id"))
|
||||||
|
def get(self, request: HttpRequest, intervention_id: str = None, *args, **kwargs) -> HttpResponse:
|
||||||
|
"""
|
||||||
|
Renders a view for new compensation
|
||||||
|
|
||||||
Returns:
|
A compensation creation may be called directly from the parent-intervention object. If so - we may take
|
||||||
|
the intervention's id and directly link the compensation to it.
|
||||||
|
|
||||||
"""
|
Args:
|
||||||
template = "compensation/form/view.html"
|
request (HttpRequest): The incoming request
|
||||||
if intervention_id is not None:
|
intervention_id (str): The intervention identifier
|
||||||
try:
|
|
||||||
intervention = Intervention.objects.get(id=intervention_id)
|
Returns:
|
||||||
except ObjectDoesNotExist:
|
|
||||||
messages.error(request, PARAMS_INVALID)
|
"""
|
||||||
return redirect("home")
|
if intervention_id:
|
||||||
if intervention.is_recorded:
|
# If the parent-intervention is recorded, we are not allowed to change anything on it's data.
|
||||||
messages.info(
|
# Not even adding new child elements like compensations!
|
||||||
request,
|
intervention = get_object_or_404(Intervention, id=intervention_id)
|
||||||
RECORDED_BLOCKS_EDIT
|
recording_state_blocks_actions = intervention.is_recorded
|
||||||
)
|
if recording_state_blocks_actions:
|
||||||
return redirect("intervention:detail", id=intervention_id)
|
messages.info(
|
||||||
|
request,
|
||||||
|
RECORDED_BLOCKS_EDIT
|
||||||
|
)
|
||||||
|
return redirect("intervention:detail", id=intervention_id)
|
||||||
|
|
||||||
|
data_form = NewCompensationForm(request.POST or None, intervention_id=intervention_id)
|
||||||
|
geom_form = SimpleGeomForm(request.POST or None, read_only=False)
|
||||||
|
|
||||||
|
context = {
|
||||||
|
"form": data_form,
|
||||||
|
"geom_form": geom_form,
|
||||||
|
TAB_TITLE_IDENTIFIER: _("New compensation"),
|
||||||
|
}
|
||||||
|
context = BaseContext(request, context).context
|
||||||
|
|
||||||
|
return render(request, self._TEMPLATE, context)
|
||||||
|
|
||||||
|
@method_decorator(default_group_required)
|
||||||
|
@method_decorator(shared_access_required(Intervention, "intervention_id"))
|
||||||
|
def post(self, request: HttpRequest, intervention_id: str = None, *args, **kwargs) -> HttpResponse:
|
||||||
|
|
||||||
|
"""
|
||||||
|
Renders a view for a new compensation creation
|
||||||
|
|
||||||
|
Args:
|
||||||
|
request (HttpRequest): The incoming request
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
"""
|
||||||
|
if intervention_id:
|
||||||
|
# If the parent-intervention is recorded, we are not allowed to change anything on it's data.
|
||||||
|
# Not even adding new child elements like compensations!
|
||||||
|
intervention = get_object_or_404(Intervention, id=intervention_id)
|
||||||
|
recording_state_blocks_actions = intervention.is_recorded
|
||||||
|
if recording_state_blocks_actions:
|
||||||
|
messages.info(
|
||||||
|
request,
|
||||||
|
RECORDED_BLOCKS_EDIT
|
||||||
|
)
|
||||||
|
return redirect("intervention:detail", id=intervention_id)
|
||||||
|
|
||||||
|
data_form = NewCompensationForm(request.POST or None, intervention_id=intervention_id)
|
||||||
|
geom_form = SimpleGeomForm(request.POST or None, read_only=False)
|
||||||
|
|
||||||
data_form = NewCompensationForm(request.POST or None, intervention_id=intervention_id)
|
|
||||||
geom_form = SimpleGeomForm(request.POST or None, read_only=False)
|
|
||||||
if request.method == "POST":
|
|
||||||
if data_form.is_valid() and geom_form.is_valid():
|
if data_form.is_valid() and geom_form.is_valid():
|
||||||
generated_identifier = data_form.cleaned_data.get("identifier", None)
|
generated_identifier = data_form.cleaned_data.get("identifier", None)
|
||||||
comp = data_form.save(request.user, geom_form)
|
comp = data_form.save(request.user, geom_form)
|
||||||
@@ -103,199 +139,127 @@ def new_view(request: HttpRequest, intervention_id: str = None):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
messages.success(request, COMPENSATION_ADDED_TEMPLATE.format(comp.identifier))
|
messages.success(request, COMPENSATION_ADDED_TEMPLATE.format(comp.identifier))
|
||||||
if geom_form.geometry_simplified:
|
if geom_form.has_geometry_simplified():
|
||||||
messages.info(
|
messages.info(
|
||||||
request,
|
request,
|
||||||
GEOMETRY_SIMPLIFIED
|
GEOMETRY_SIMPLIFIED
|
||||||
)
|
)
|
||||||
|
num_ignored_geometries = geom_form.get_num_geometries_ignored()
|
||||||
|
if num_ignored_geometries > 0:
|
||||||
|
messages.info(
|
||||||
|
request,
|
||||||
|
GEOMETRIES_IGNORED_TEMPLATE.format(num_ignored_geometries)
|
||||||
|
)
|
||||||
return redirect("compensation:detail", id=comp.id)
|
return redirect("compensation:detail", id=comp.id)
|
||||||
else:
|
else:
|
||||||
messages.error(request, FORM_INVALID, extra_tags="danger",)
|
messages.error(request, FORM_INVALID, extra_tags="danger", )
|
||||||
else:
|
|
||||||
# For clarification: nothing in this case
|
|
||||||
pass
|
|
||||||
context = {
|
|
||||||
"form": data_form,
|
|
||||||
"geom_form": geom_form,
|
|
||||||
TAB_TITLE_IDENTIFIER: _("New compensation"),
|
|
||||||
}
|
|
||||||
context = BaseContext(request, context).context
|
|
||||||
return render(request, template, context)
|
|
||||||
|
|
||||||
|
context = {
|
||||||
@login_required
|
"form": data_form,
|
||||||
@default_group_required
|
"geom_form": geom_form,
|
||||||
def new_id_view(request: HttpRequest):
|
TAB_TITLE_IDENTIFIER: _("New compensation"),
|
||||||
""" JSON endpoint
|
|
||||||
|
|
||||||
Provides fetching of free identifiers for e.g. AJAX calls
|
|
||||||
|
|
||||||
"""
|
|
||||||
tmp = Compensation()
|
|
||||||
identifier = tmp.generate_new_identifier()
|
|
||||||
while Compensation.objects.filter(identifier=identifier).exists():
|
|
||||||
identifier = tmp.generate_new_identifier()
|
|
||||||
return JsonResponse(
|
|
||||||
data={
|
|
||||||
"gen_data": identifier
|
|
||||||
}
|
}
|
||||||
)
|
context = BaseContext(request, context).context
|
||||||
|
|
||||||
|
return render(request, self._TEMPLATE, context)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
class CompensationIdentifierGeneratorView(AbstractIdentifierGeneratorView):
|
||||||
@default_group_required
|
_MODEL = Compensation
|
||||||
@shared_access_required(Compensation, "id")
|
|
||||||
def edit_view(request: HttpRequest, id: str):
|
|
||||||
"""
|
|
||||||
Renders a view for editing compensations
|
|
||||||
|
|
||||||
Args:
|
|
||||||
request (HttpRequest): The incoming request
|
|
||||||
|
|
||||||
Returns:
|
class EditCompensationView(LoginRequiredMixin, View):
|
||||||
|
_TEMPLATE = "compensation/form/view.html"
|
||||||
|
|
||||||
"""
|
@method_decorator(default_group_required)
|
||||||
template = "compensation/form/view.html"
|
@method_decorator(shared_access_required(Compensation, "id"))
|
||||||
# Get object from db
|
def get(self, request: HttpRequest, id: str, *args, **kwargs) -> HttpResponse:
|
||||||
comp = get_object_or_404(Compensation, id=id)
|
|
||||||
if comp.is_recorded:
|
|
||||||
messages.info(
|
|
||||||
request,
|
|
||||||
RECORDED_BLOCKS_EDIT
|
|
||||||
)
|
|
||||||
return redirect("compensation:detail", id=id)
|
|
||||||
|
|
||||||
# Create forms, initialize with values from db/from POST request
|
"""
|
||||||
data_form = EditCompensationForm(request.POST or None, instance=comp)
|
Renders a view for editing compensations
|
||||||
geom_form = SimpleGeomForm(request.POST or None, read_only=False, instance=comp)
|
|
||||||
if request.method == "POST":
|
Args:
|
||||||
|
request (HttpRequest): The incoming request
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
"""
|
||||||
|
# Get object from db
|
||||||
|
comp = get_object_or_404(Compensation, id=id)
|
||||||
|
if comp.is_recorded:
|
||||||
|
messages.info(
|
||||||
|
request,
|
||||||
|
RECORDED_BLOCKS_EDIT
|
||||||
|
)
|
||||||
|
return redirect("compensation:detail", id=id)
|
||||||
|
|
||||||
|
# Create forms, initialize with values from db/from POST request
|
||||||
|
data_form = EditCompensationForm(request.POST or None, instance=comp)
|
||||||
|
geom_form = SimpleGeomForm(request.POST or None, read_only=False, instance=comp)
|
||||||
|
|
||||||
|
context = {
|
||||||
|
"form": data_form,
|
||||||
|
"geom_form": geom_form,
|
||||||
|
TAB_TITLE_IDENTIFIER: _("Edit {}").format(comp.identifier),
|
||||||
|
}
|
||||||
|
context = BaseContext(request, context).context
|
||||||
|
|
||||||
|
return render(request, self._TEMPLATE, context)
|
||||||
|
|
||||||
|
@method_decorator(default_group_required)
|
||||||
|
@method_decorator(shared_access_required(Compensation, "id"))
|
||||||
|
def post(self, request: HttpRequest, id: str, *args, **kwargs) -> HttpResponse:
|
||||||
|
|
||||||
|
"""
|
||||||
|
Renders a view for editing compensations
|
||||||
|
|
||||||
|
Args:
|
||||||
|
request (HttpRequest): The incoming request
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
"""
|
||||||
|
# Get object from db
|
||||||
|
comp = get_object_or_404(Compensation, id=id)
|
||||||
|
if comp.is_recorded:
|
||||||
|
messages.info(
|
||||||
|
request,
|
||||||
|
RECORDED_BLOCKS_EDIT
|
||||||
|
)
|
||||||
|
return redirect("compensation:detail", id=id)
|
||||||
|
|
||||||
|
# Create forms, initialize with values from db/from POST request
|
||||||
|
data_form = EditCompensationForm(request.POST or None, instance=comp)
|
||||||
|
geom_form = SimpleGeomForm(request.POST or None, read_only=False, instance=comp)
|
||||||
if data_form.is_valid() and geom_form.is_valid():
|
if data_form.is_valid() and geom_form.is_valid():
|
||||||
# Preserve state of intervention checked to determine whether the user must be informed or not
|
# Preserve state of intervention checked to determine whether the user must be informed or not
|
||||||
# about a change of the check state
|
# about a change of the check state
|
||||||
intervention_is_checked = comp.intervention.checked is not None
|
intervention_is_checked = comp.intervention.checked is not None
|
||||||
|
|
||||||
# The data form takes the geom form for processing, as well as the performing user
|
# The data form takes the geom form for processing, as well as the performing user
|
||||||
comp = data_form.save(request.user, geom_form)
|
comp = data_form.save(request.user, geom_form)
|
||||||
if intervention_is_checked:
|
if intervention_is_checked:
|
||||||
messages.info(request, CHECK_STATE_RESET)
|
messages.info(request, CHECK_STATE_RESET)
|
||||||
messages.success(request, _("Compensation {} edited").format(comp.identifier))
|
messages.success(request, _("Compensation {} edited").format(comp.identifier))
|
||||||
if geom_form.geometry_simplified:
|
if geom_form.has_geometry_simplified():
|
||||||
messages.info(
|
messages.info(
|
||||||
request,
|
request,
|
||||||
GEOMETRY_SIMPLIFIED
|
GEOMETRY_SIMPLIFIED
|
||||||
)
|
)
|
||||||
|
num_ignored_geometries = geom_form.get_num_geometries_ignored()
|
||||||
|
if num_ignored_geometries > 0:
|
||||||
|
messages.info(
|
||||||
|
request,
|
||||||
|
GEOMETRIES_IGNORED_TEMPLATE.format(num_ignored_geometries)
|
||||||
|
)
|
||||||
return redirect("compensation:detail", id=comp.id)
|
return redirect("compensation:detail", id=comp.id)
|
||||||
else:
|
else:
|
||||||
messages.error(request, FORM_INVALID, extra_tags="danger",)
|
messages.error(request, FORM_INVALID, extra_tags="danger", )
|
||||||
else:
|
|
||||||
# For clarification: nothing in this case
|
|
||||||
pass
|
|
||||||
context = {
|
|
||||||
"form": data_form,
|
|
||||||
"geom_form": geom_form,
|
|
||||||
TAB_TITLE_IDENTIFIER: _("Edit {}").format(comp.identifier),
|
|
||||||
}
|
|
||||||
context = BaseContext(request, context).context
|
|
||||||
return render(request, template, context)
|
|
||||||
|
|
||||||
|
context = {
|
||||||
|
"form": data_form,
|
||||||
|
"geom_form": geom_form,
|
||||||
|
TAB_TITLE_IDENTIFIER: _("Edit {}").format(comp.identifier),
|
||||||
|
}
|
||||||
|
context = BaseContext(request, context).context
|
||||||
|
|
||||||
@login_required
|
return render(request, self._TEMPLATE, context)
|
||||||
@any_group_check
|
|
||||||
@uuid_required
|
|
||||||
def detail_view(request: HttpRequest, id: str):
|
|
||||||
""" Renders a detail view for a compensation
|
|
||||||
|
|
||||||
Args:
|
|
||||||
request (HttpRequest): The incoming request
|
|
||||||
id (str): The compensation's id
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
|
|
||||||
"""
|
|
||||||
template = "compensation/detail/compensation/view.html"
|
|
||||||
comp = get_object_or_404(
|
|
||||||
Compensation.objects.select_related(
|
|
||||||
"modified",
|
|
||||||
"created",
|
|
||||||
"geometry"
|
|
||||||
),
|
|
||||||
id=id,
|
|
||||||
deleted=None,
|
|
||||||
intervention__deleted=None,
|
|
||||||
)
|
|
||||||
geom_form = SimpleGeomForm(instance=comp)
|
|
||||||
parcels = comp.get_underlying_parcels()
|
|
||||||
_user = request.user
|
|
||||||
is_data_shared = comp.intervention.is_shared_with(_user)
|
|
||||||
|
|
||||||
# Order states according to surface
|
|
||||||
before_states = comp.before_states.all().prefetch_related("biotope_type").order_by("-surface")
|
|
||||||
after_states = comp.after_states.all().prefetch_related("biotope_type").order_by("-surface")
|
|
||||||
actions = comp.actions.all().prefetch_related("action_type")
|
|
||||||
|
|
||||||
# Precalculate logical errors between before- and after-states
|
|
||||||
# Sum() returns None in case of no states, so we catch that and replace it with 0 for easier handling
|
|
||||||
sum_before_states = comp.get_surface_before_states()
|
|
||||||
sum_after_states = comp.get_surface_after_states()
|
|
||||||
diff_states = abs(sum_before_states - sum_after_states)
|
|
||||||
|
|
||||||
request = comp.set_status_messages(request)
|
|
||||||
|
|
||||||
last_checked = comp.intervention.get_last_checked_action()
|
|
||||||
last_checked_tooltip = ""
|
|
||||||
if last_checked:
|
|
||||||
last_checked_tooltip = DATA_CHECKED_PREVIOUSLY_TEMPLATE.format(last_checked.get_timestamp_str_formatted(), last_checked.user)
|
|
||||||
|
|
||||||
requesting_user_is_only_shared_user = comp.is_only_shared_with(_user)
|
|
||||||
if requesting_user_is_only_shared_user:
|
|
||||||
messages.info(
|
|
||||||
request,
|
|
||||||
DO_NOT_FORGET_TO_SHARE
|
|
||||||
)
|
|
||||||
|
|
||||||
context = {
|
|
||||||
"obj": comp,
|
|
||||||
"last_checked": last_checked,
|
|
||||||
"last_checked_tooltip": last_checked_tooltip,
|
|
||||||
"geom_form": geom_form,
|
|
||||||
"parcels": parcels,
|
|
||||||
"is_entry_shared": is_data_shared,
|
|
||||||
"actions": actions,
|
|
||||||
"before_states": before_states,
|
|
||||||
"after_states": after_states,
|
|
||||||
"sum_before_states": sum_before_states,
|
|
||||||
"sum_after_states": sum_after_states,
|
|
||||||
"diff_states": diff_states,
|
|
||||||
"is_default_member": _user.in_group(DEFAULT_GROUP),
|
|
||||||
"is_zb_member": _user.in_group(ZB_GROUP),
|
|
||||||
"is_ets_member": _user.in_group(ETS_GROUP),
|
|
||||||
"LANIS_LINK": comp.get_LANIS_link(),
|
|
||||||
TAB_TITLE_IDENTIFIER: f"{comp.identifier} - {comp.title}",
|
|
||||||
"has_finished_deadlines": comp.get_finished_deadlines().exists(),
|
|
||||||
}
|
|
||||||
context = BaseContext(request, context).context
|
|
||||||
return render(request, template, context)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required_modal
|
|
||||||
@login_required
|
|
||||||
@default_group_required
|
|
||||||
@shared_access_required(Compensation, "id")
|
|
||||||
def remove_view(request: HttpRequest, id: str):
|
|
||||||
""" Renders a modal view for removing the compensation
|
|
||||||
|
|
||||||
Args:
|
|
||||||
request (HttpRequest): The incoming request
|
|
||||||
id (str): The compensation's id
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
|
|
||||||
"""
|
|
||||||
comp = get_object_or_404(Compensation, id=id)
|
|
||||||
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("compensation:index"),
|
|
||||||
)
|
|
||||||
|
|
||||||
97
compensation/views/compensation/detail.py
Normal file
97
compensation/views/compensation/detail.py
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
"""
|
||||||
|
Author: Michel Peltriaux
|
||||||
|
Created on: 14.12.25
|
||||||
|
|
||||||
|
"""
|
||||||
|
from django.contrib import messages
|
||||||
|
from django.http import HttpRequest, HttpResponse
|
||||||
|
from django.shortcuts import render, get_object_or_404
|
||||||
|
|
||||||
|
from compensation.models import Compensation
|
||||||
|
from konova.contexts import BaseContext
|
||||||
|
from konova.forms import SimpleGeomForm
|
||||||
|
from konova.settings import ETS_GROUP, ZB_GROUP, DEFAULT_GROUP
|
||||||
|
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
||||||
|
from konova.utils.message_templates import DO_NOT_FORGET_TO_SHARE, DATA_CHECKED_PREVIOUSLY_TEMPLATE
|
||||||
|
from konova.views.detail import AbstractDetailView
|
||||||
|
|
||||||
|
|
||||||
|
class DetailCompensationView(AbstractDetailView):
|
||||||
|
_TEMPLATE = "compensation/detail/compensation/view.html"
|
||||||
|
|
||||||
|
def get(self, request: HttpRequest, id: str, *args, **kwargs) -> HttpResponse:
|
||||||
|
|
||||||
|
""" Renders a detail view for a compensation
|
||||||
|
|
||||||
|
Args:
|
||||||
|
request (HttpRequest): The incoming request
|
||||||
|
id (str): The compensation's id
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
"""
|
||||||
|
comp = get_object_or_404(
|
||||||
|
Compensation.objects.select_related(
|
||||||
|
"modified",
|
||||||
|
"created",
|
||||||
|
"geometry"
|
||||||
|
),
|
||||||
|
id=id,
|
||||||
|
deleted=None,
|
||||||
|
intervention__deleted=None,
|
||||||
|
)
|
||||||
|
geom_form = SimpleGeomForm(instance=comp)
|
||||||
|
parcels = comp.get_underlying_parcels()
|
||||||
|
_user = request.user
|
||||||
|
is_data_shared = comp.intervention.is_shared_with(_user)
|
||||||
|
|
||||||
|
# Order states according to surface
|
||||||
|
before_states = comp.before_states.all().prefetch_related("biotope_type").order_by("-surface")
|
||||||
|
after_states = comp.after_states.all().prefetch_related("biotope_type").order_by("-surface")
|
||||||
|
actions = comp.actions.all().prefetch_related("action_type")
|
||||||
|
|
||||||
|
# Precalculate logical errors between before- and after-states
|
||||||
|
# Sum() returns None in case of no states, so we catch that and replace it with 0 for easier handling
|
||||||
|
sum_before_states = comp.get_surface_before_states()
|
||||||
|
sum_after_states = comp.get_surface_after_states()
|
||||||
|
diff_states = abs(sum_before_states - sum_after_states)
|
||||||
|
|
||||||
|
request = comp.set_status_messages(request)
|
||||||
|
|
||||||
|
last_checked = comp.intervention.get_last_checked_action()
|
||||||
|
last_checked_tooltip = ""
|
||||||
|
if last_checked:
|
||||||
|
last_checked_tooltip = DATA_CHECKED_PREVIOUSLY_TEMPLATE.format(
|
||||||
|
last_checked.get_timestamp_str_formatted(),
|
||||||
|
last_checked.user
|
||||||
|
)
|
||||||
|
|
||||||
|
requesting_user_is_only_shared_user = comp.is_only_shared_with(_user)
|
||||||
|
if requesting_user_is_only_shared_user:
|
||||||
|
messages.info(
|
||||||
|
request,
|
||||||
|
DO_NOT_FORGET_TO_SHARE
|
||||||
|
)
|
||||||
|
|
||||||
|
context = {
|
||||||
|
"obj": comp,
|
||||||
|
"last_checked": last_checked,
|
||||||
|
"last_checked_tooltip": last_checked_tooltip,
|
||||||
|
"geom_form": geom_form,
|
||||||
|
"parcels": parcels,
|
||||||
|
"is_entry_shared": is_data_shared,
|
||||||
|
"actions": actions,
|
||||||
|
"before_states": before_states,
|
||||||
|
"after_states": after_states,
|
||||||
|
"sum_before_states": sum_before_states,
|
||||||
|
"sum_after_states": sum_after_states,
|
||||||
|
"diff_states": diff_states,
|
||||||
|
"is_default_member": _user.in_group(DEFAULT_GROUP),
|
||||||
|
"is_zb_member": _user.in_group(ZB_GROUP),
|
||||||
|
"is_ets_member": _user.in_group(ETS_GROUP),
|
||||||
|
"LANIS_LINK": comp.get_LANIS_link(),
|
||||||
|
TAB_TITLE_IDENTIFIER: f"{comp.identifier} - {comp.title}",
|
||||||
|
"has_finished_deadlines": comp.get_finished_deadlines().exists(),
|
||||||
|
}
|
||||||
|
context = BaseContext(request, context).context
|
||||||
|
return render(request, self._TEMPLATE, context)
|
||||||
20
compensation/views/compensation/remove.py
Normal file
20
compensation/views/compensation/remove.py
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
"""
|
||||||
|
Author: Michel Peltriaux
|
||||||
|
Created on: 14.12.25
|
||||||
|
|
||||||
|
"""
|
||||||
|
from django.http import HttpRequest, HttpResponse
|
||||||
|
from django.utils.decorators import method_decorator
|
||||||
|
|
||||||
|
from compensation.models import Compensation
|
||||||
|
from konova.decorators import shared_access_required
|
||||||
|
from konova.views.remove import AbstractRemoveView
|
||||||
|
|
||||||
|
|
||||||
|
class RemoveCompensationView(AbstractRemoveView):
|
||||||
|
_MODEL = Compensation
|
||||||
|
_REDIRECT_URL = "compensation:index"
|
||||||
|
|
||||||
|
@method_decorator(shared_access_required(Compensation, "id"))
|
||||||
|
def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
|
||||||
|
return super().get(request, *args, **kwargs)
|
||||||
@@ -5,7 +5,7 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
|||||||
Created on: 19.08.22
|
Created on: 19.08.22
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from django.http import HttpRequest
|
from django.http import HttpRequest, HttpResponse
|
||||||
from django.shortcuts import get_object_or_404, render
|
from django.shortcuts import get_object_or_404, render
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
@@ -14,67 +14,72 @@ from compensation.models import Compensation
|
|||||||
from konova.contexts import BaseContext
|
from konova.contexts import BaseContext
|
||||||
from konova.forms import SimpleGeomForm
|
from konova.forms import SimpleGeomForm
|
||||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
||||||
from konova.utils.generators import generate_qr_code
|
from konova.utils.qrcode import QrCode
|
||||||
|
from konova.views.report import AbstractPublicReportView
|
||||||
|
|
||||||
|
|
||||||
def report_view(request: HttpRequest, id: str):
|
class CompensationPublicReportView(AbstractPublicReportView):
|
||||||
""" Renders the public report view
|
_TEMPLATE = "compensation/report/compensation/report.html"
|
||||||
|
|
||||||
Args:
|
def get(self, request: HttpRequest, id: str, *args, **kwargs) -> HttpResponse:
|
||||||
request (HttpRequest): The incoming request
|
""" Renders the public report view
|
||||||
id (str): The id of the intervention
|
|
||||||
|
|
||||||
Returns:
|
Args:
|
||||||
|
request (HttpRequest): The incoming request
|
||||||
|
id (str): The id of the intervention
|
||||||
|
|
||||||
"""
|
Returns:
|
||||||
# Reuse the compensation report template since compensations are structurally identical
|
|
||||||
template = "compensation/report/compensation/report.html"
|
"""
|
||||||
comp = get_object_or_404(Compensation, id=id)
|
comp = get_object_or_404(Compensation, id=id)
|
||||||
|
tab_title = _("Report {}").format(comp.identifier)
|
||||||
|
# If intervention is not recorded (yet or currently) we need to render another template without any data
|
||||||
|
if not comp.is_ready_for_publish():
|
||||||
|
template = "report/unavailable.html"
|
||||||
|
context = {
|
||||||
|
TAB_TITLE_IDENTIFIER: tab_title,
|
||||||
|
}
|
||||||
|
context = BaseContext(request, context).context
|
||||||
|
return render(request, template, context)
|
||||||
|
|
||||||
|
# Prepare data for map viewer
|
||||||
|
geom_form = SimpleGeomForm(
|
||||||
|
instance=comp
|
||||||
|
)
|
||||||
|
parcels = comp.get_underlying_parcels()
|
||||||
|
|
||||||
|
qrcode = QrCode(
|
||||||
|
content=request.build_absolute_uri(reverse("compensation:report", args=(id,))),
|
||||||
|
size=10
|
||||||
|
)
|
||||||
|
qrcode_lanis = QrCode(
|
||||||
|
content=comp.get_LANIS_link(),
|
||||||
|
size=7
|
||||||
|
)
|
||||||
|
|
||||||
|
# Order states by surface
|
||||||
|
before_states = comp.before_states.all().order_by("-surface").prefetch_related("biotope_type")
|
||||||
|
after_states = comp.after_states.all().order_by("-surface").prefetch_related("biotope_type")
|
||||||
|
actions = comp.actions.all().prefetch_related("action_type")
|
||||||
|
|
||||||
tab_title = _("Report {}").format(comp.identifier)
|
|
||||||
# If intervention is not recorded (yet or currently) we need to render another template without any data
|
|
||||||
if not comp.is_ready_for_publish():
|
|
||||||
template = "report/unavailable.html"
|
|
||||||
context = {
|
context = {
|
||||||
|
"obj": comp,
|
||||||
|
"qrcode": {
|
||||||
|
"img": qrcode.get_img(),
|
||||||
|
"url": qrcode.get_content(),
|
||||||
|
},
|
||||||
|
"qrcode_lanis": {
|
||||||
|
"img": qrcode_lanis.get_img(),
|
||||||
|
"url": qrcode_lanis.get_content(),
|
||||||
|
},
|
||||||
|
"is_entry_shared": False, # disables action buttons during rendering
|
||||||
|
"before_states": before_states,
|
||||||
|
"after_states": after_states,
|
||||||
|
"geom_form": geom_form,
|
||||||
|
"parcels": parcels,
|
||||||
|
"actions": actions,
|
||||||
|
"tables_scrollable": False,
|
||||||
TAB_TITLE_IDENTIFIER: tab_title,
|
TAB_TITLE_IDENTIFIER: tab_title,
|
||||||
}
|
}
|
||||||
context = BaseContext(request, context).context
|
context = BaseContext(request, context).context
|
||||||
return render(request, template, context)
|
return render(request, self._TEMPLATE, context)
|
||||||
|
|
||||||
# Prepare data for map viewer
|
|
||||||
geom_form = SimpleGeomForm(
|
|
||||||
instance=comp
|
|
||||||
)
|
|
||||||
parcels = comp.get_underlying_parcels()
|
|
||||||
|
|
||||||
qrcode_url = request.build_absolute_uri(reverse("compensation:report", args=(id,)))
|
|
||||||
qrcode_img = generate_qr_code(qrcode_url, 10)
|
|
||||||
qrcode_lanis_url = comp.get_LANIS_link()
|
|
||||||
qrcode_img_lanis = generate_qr_code(qrcode_lanis_url, 7)
|
|
||||||
|
|
||||||
# Order states by surface
|
|
||||||
before_states = comp.before_states.all().order_by("-surface").prefetch_related("biotope_type")
|
|
||||||
after_states = comp.after_states.all().order_by("-surface").prefetch_related("biotope_type")
|
|
||||||
actions = comp.actions.all().prefetch_related("action_type")
|
|
||||||
|
|
||||||
context = {
|
|
||||||
"obj": comp,
|
|
||||||
"qrcode": {
|
|
||||||
"img": qrcode_img,
|
|
||||||
"url": qrcode_url,
|
|
||||||
},
|
|
||||||
"qrcode_lanis": {
|
|
||||||
"img": qrcode_img_lanis,
|
|
||||||
"url": qrcode_lanis_url,
|
|
||||||
},
|
|
||||||
"is_entry_shared": False, # disables action buttons during rendering
|
|
||||||
"before_states": before_states,
|
|
||||||
"after_states": after_states,
|
|
||||||
"geom_form": geom_form,
|
|
||||||
"parcels": parcels,
|
|
||||||
"actions": actions,
|
|
||||||
"tables_scrollable": False,
|
|
||||||
TAB_TITLE_IDENTIFIER: tab_title,
|
|
||||||
}
|
|
||||||
context = BaseContext(request, context).context
|
|
||||||
return render(request, template, context)
|
|
||||||
|
|||||||
97
compensation/views/eco_account/detail.py
Normal file
97
compensation/views/eco_account/detail.py
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
"""
|
||||||
|
Author: Michel Peltriaux
|
||||||
|
Created on: 14.12.25
|
||||||
|
|
||||||
|
"""
|
||||||
|
from django.contrib import messages
|
||||||
|
from django.http import HttpRequest, HttpResponse
|
||||||
|
from django.shortcuts import render, get_object_or_404
|
||||||
|
|
||||||
|
from compensation.models import EcoAccount
|
||||||
|
from konova.contexts import BaseContext
|
||||||
|
from konova.forms import SimpleGeomForm
|
||||||
|
from konova.settings import ETS_GROUP, ZB_GROUP, DEFAULT_GROUP
|
||||||
|
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
||||||
|
from konova.utils.message_templates import DO_NOT_FORGET_TO_SHARE
|
||||||
|
from konova.views.detail import AbstractDetailView
|
||||||
|
|
||||||
|
|
||||||
|
class DetailEcoAccountView(AbstractDetailView):
|
||||||
|
_TEMPLATE = "compensation/detail/eco_account/view.html"
|
||||||
|
|
||||||
|
def get(self, request: HttpRequest, id: str, *args, **kwargs) -> HttpResponse:
|
||||||
|
""" Renders a detail view for a compensation
|
||||||
|
|
||||||
|
Args:
|
||||||
|
request (HttpRequest): The incoming request
|
||||||
|
id (str): The compensation's id
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
"""
|
||||||
|
acc = get_object_or_404(
|
||||||
|
EcoAccount.objects.prefetch_related(
|
||||||
|
"deadlines",
|
||||||
|
).select_related(
|
||||||
|
'geometry',
|
||||||
|
'responsible',
|
||||||
|
),
|
||||||
|
id=id,
|
||||||
|
deleted=None,
|
||||||
|
)
|
||||||
|
geom_form = SimpleGeomForm(instance=acc)
|
||||||
|
parcels = acc.get_underlying_parcels()
|
||||||
|
_user = request.user
|
||||||
|
is_data_shared = acc.is_shared_with(_user)
|
||||||
|
|
||||||
|
# Order states according to surface
|
||||||
|
before_states = acc.before_states.order_by("-surface")
|
||||||
|
after_states = acc.after_states.order_by("-surface")
|
||||||
|
|
||||||
|
# Precalculate logical errors between before- and after-states
|
||||||
|
# Sum() returns None in case of no states, so we catch that and replace it with 0 for easier handling
|
||||||
|
sum_before_states = acc.get_surface_before_states()
|
||||||
|
sum_after_states = acc.get_surface_after_states()
|
||||||
|
diff_states = abs(sum_before_states - sum_after_states)
|
||||||
|
# Calculate rest of available surface for deductions
|
||||||
|
available_total = acc.deductable_rest
|
||||||
|
available_relative = acc.get_deductable_rest_relative()
|
||||||
|
|
||||||
|
# Prefetch related data to decrease the amount of db connections
|
||||||
|
deductions = acc.deductions.filter(
|
||||||
|
intervention__deleted=None,
|
||||||
|
)
|
||||||
|
actions = acc.actions.all()
|
||||||
|
|
||||||
|
request = acc.set_status_messages(request)
|
||||||
|
|
||||||
|
requesting_user_is_only_shared_user = acc.is_only_shared_with(_user)
|
||||||
|
if requesting_user_is_only_shared_user:
|
||||||
|
messages.info(
|
||||||
|
request,
|
||||||
|
DO_NOT_FORGET_TO_SHARE
|
||||||
|
)
|
||||||
|
|
||||||
|
context = {
|
||||||
|
"obj": acc,
|
||||||
|
"geom_form": geom_form,
|
||||||
|
"parcels": parcels,
|
||||||
|
"is_entry_shared": is_data_shared,
|
||||||
|
"before_states": before_states,
|
||||||
|
"after_states": after_states,
|
||||||
|
"sum_before_states": sum_before_states,
|
||||||
|
"sum_after_states": sum_after_states,
|
||||||
|
"diff_states": diff_states,
|
||||||
|
"available": available_relative,
|
||||||
|
"available_total": available_total,
|
||||||
|
"is_default_member": _user.in_group(DEFAULT_GROUP),
|
||||||
|
"is_zb_member": _user.in_group(ZB_GROUP),
|
||||||
|
"is_ets_member": _user.in_group(ETS_GROUP),
|
||||||
|
"LANIS_LINK": acc.get_LANIS_link(),
|
||||||
|
"deductions": deductions,
|
||||||
|
"actions": actions,
|
||||||
|
TAB_TITLE_IDENTIFIER: f"{acc.identifier} - {acc.title}",
|
||||||
|
"has_finished_deadlines": acc.get_finished_deadlines().exists(),
|
||||||
|
}
|
||||||
|
context = BaseContext(request, context).context
|
||||||
|
return render(request, self._TEMPLATE, context)
|
||||||
@@ -6,72 +6,94 @@ Created on: 19.08.22
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
from django.db.models import Sum
|
from django.http import HttpRequest, HttpResponse
|
||||||
from django.http import HttpRequest, JsonResponse
|
|
||||||
from django.shortcuts import get_object_or_404, redirect, render
|
from django.shortcuts import get_object_or_404, redirect, render
|
||||||
from django.urls import reverse
|
from django.utils.decorators import method_decorator
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
from django.views import View
|
||||||
|
|
||||||
from compensation.forms.eco_account import EditEcoAccountForm, NewEcoAccountForm, RemoveEcoAccountModalForm
|
from compensation.forms.eco_account import EditEcoAccountForm, NewEcoAccountForm
|
||||||
from compensation.models import EcoAccount
|
from compensation.models import EcoAccount
|
||||||
from compensation.tables.eco_account import EcoAccountTable
|
from compensation.tables.eco_account import EcoAccountTable
|
||||||
from konova.contexts import BaseContext
|
from konova.contexts import BaseContext
|
||||||
from konova.decorators import shared_access_required, default_group_required, any_group_check, login_required_modal, \
|
from konova.decorators import shared_access_required, default_group_required
|
||||||
uuid_required
|
|
||||||
from konova.forms import SimpleGeomForm
|
from konova.forms import SimpleGeomForm
|
||||||
from konova.settings import ETS_GROUP, DEFAULT_GROUP, ZB_GROUP
|
|
||||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
||||||
from konova.utils.message_templates import CANCEL_ACC_RECORDED_OR_DEDUCTED, RECORDED_BLOCKS_EDIT, FORM_INVALID, \
|
from konova.utils.message_templates import RECORDED_BLOCKS_EDIT, FORM_INVALID, \
|
||||||
IDENTIFIER_REPLACED, DO_NOT_FORGET_TO_SHARE, GEOMETRY_SIMPLIFIED
|
IDENTIFIER_REPLACED, GEOMETRY_SIMPLIFIED, GEOMETRIES_IGNORED_TEMPLATE
|
||||||
|
from konova.views.identifier import AbstractIdentifierGeneratorView
|
||||||
|
from konova.views.index import AbstractIndexView
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
class IndexEcoAccountView(AbstractIndexView):
|
||||||
@any_group_check
|
def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
|
||||||
def index_view(request: HttpRequest):
|
"""
|
||||||
"""
|
Renders the index view for eco accounts
|
||||||
Renders the index view for eco accounts
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
request (HttpRequest): The incoming request
|
request (HttpRequest): The incoming request
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
A rendered view
|
A rendered view
|
||||||
"""
|
"""
|
||||||
template = "generic_index.html"
|
eco_accounts = EcoAccount.objects.filter(
|
||||||
eco_accounts = EcoAccount.objects.filter(
|
deleted=None,
|
||||||
deleted=None,
|
).order_by(
|
||||||
).order_by(
|
"-modified__timestamp"
|
||||||
"-modified__timestamp"
|
)
|
||||||
)
|
table = EcoAccountTable(
|
||||||
table = EcoAccountTable(
|
request=request,
|
||||||
request=request,
|
queryset=eco_accounts
|
||||||
queryset=eco_accounts
|
)
|
||||||
)
|
context = {
|
||||||
context = {
|
"table": table,
|
||||||
"table": table,
|
TAB_TITLE_IDENTIFIER: _("Eco-account - Overview"),
|
||||||
TAB_TITLE_IDENTIFIER: _("Eco-account - Overview"),
|
}
|
||||||
}
|
context = BaseContext(request, context).context
|
||||||
context = BaseContext(request, context).context
|
return render(request, self._TEMPLATE, context)
|
||||||
return render(request, template, context)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
class NewEcoAccountView(LoginRequiredMixin, View):
|
||||||
@default_group_required
|
_TEMPLATE = "compensation/form/view.html"
|
||||||
def new_view(request: HttpRequest):
|
|
||||||
"""
|
|
||||||
Renders a view for a new eco account creation
|
|
||||||
|
|
||||||
Args:
|
@method_decorator(default_group_required)
|
||||||
request (HttpRequest): The incoming request
|
def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
|
||||||
|
"""
|
||||||
|
Renders a view for a new eco account creation
|
||||||
|
|
||||||
Returns:
|
Args:
|
||||||
|
request (HttpRequest): The incoming request
|
||||||
|
|
||||||
"""
|
Returns:
|
||||||
template = "compensation/form/view.html"
|
|
||||||
data_form = NewEcoAccountForm(request.POST or None)
|
"""
|
||||||
geom_form = SimpleGeomForm(request.POST or None, read_only=False)
|
data_form = NewEcoAccountForm(request.POST or None)
|
||||||
if request.method == "POST":
|
geom_form = SimpleGeomForm(request.POST or None, read_only=False)
|
||||||
|
|
||||||
|
context = {
|
||||||
|
"form": data_form,
|
||||||
|
"geom_form": geom_form,
|
||||||
|
TAB_TITLE_IDENTIFIER: _("New Eco-Account"),
|
||||||
|
}
|
||||||
|
context = BaseContext(request, context).context
|
||||||
|
|
||||||
|
return render(request, self._TEMPLATE, context)
|
||||||
|
|
||||||
|
@method_decorator(default_group_required)
|
||||||
|
def post(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
|
||||||
|
|
||||||
|
"""
|
||||||
|
Renders a view for a new eco account creation
|
||||||
|
|
||||||
|
Args:
|
||||||
|
request (HttpRequest): The incoming request
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
"""
|
||||||
|
data_form = NewEcoAccountForm(request.POST or None)
|
||||||
|
geom_form = SimpleGeomForm(request.POST or None, read_only=False)
|
||||||
if data_form.is_valid() and geom_form.is_valid():
|
if data_form.is_valid() and geom_form.is_valid():
|
||||||
generated_identifier = data_form.cleaned_data.get("identifier", None)
|
generated_identifier = data_form.cleaned_data.get("identifier", None)
|
||||||
acc = data_form.save(request.user, geom_form)
|
acc = data_form.save(request.user, geom_form)
|
||||||
@@ -84,208 +106,123 @@ def new_view(request: HttpRequest):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
messages.success(request, _("Eco-Account {} added").format(acc.identifier))
|
messages.success(request, _("Eco-Account {} added").format(acc.identifier))
|
||||||
if geom_form.geometry_simplified:
|
if geom_form.has_geometry_simplified():
|
||||||
messages.info(
|
messages.info(
|
||||||
request,
|
request,
|
||||||
GEOMETRY_SIMPLIFIED
|
GEOMETRY_SIMPLIFIED
|
||||||
)
|
)
|
||||||
|
num_ignored_geometries = geom_form.get_num_geometries_ignored()
|
||||||
|
if num_ignored_geometries > 0:
|
||||||
|
messages.info(
|
||||||
|
request,
|
||||||
|
GEOMETRIES_IGNORED_TEMPLATE.format(num_ignored_geometries)
|
||||||
|
)
|
||||||
return redirect("compensation:acc:detail", id=acc.id)
|
return redirect("compensation:acc:detail", id=acc.id)
|
||||||
else:
|
else:
|
||||||
messages.error(request, FORM_INVALID, extra_tags="danger",)
|
messages.error(request, FORM_INVALID, extra_tags="danger", )
|
||||||
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)
|
|
||||||
|
|
||||||
|
context = {
|
||||||
@login_required
|
"form": data_form,
|
||||||
@default_group_required
|
"geom_form": geom_form,
|
||||||
def new_id_view(request: HttpRequest):
|
TAB_TITLE_IDENTIFIER: _("New Eco-Account"),
|
||||||
""" JSON endpoint
|
|
||||||
|
|
||||||
Provides fetching of free identifiers for e.g. AJAX calls
|
|
||||||
|
|
||||||
"""
|
|
||||||
tmp = EcoAccount()
|
|
||||||
identifier = tmp.generate_new_identifier()
|
|
||||||
while EcoAccount.objects.filter(identifier=identifier).exists():
|
|
||||||
identifier = tmp.generate_new_identifier()
|
|
||||||
return JsonResponse(
|
|
||||||
data={
|
|
||||||
"gen_data": identifier
|
|
||||||
}
|
}
|
||||||
)
|
context = BaseContext(request, context).context
|
||||||
|
|
||||||
|
return render(request, self._TEMPLATE, context)
|
||||||
|
|
||||||
|
class EcoAccountIdentifierGeneratorView(AbstractIdentifierGeneratorView):
|
||||||
|
_MODEL = EcoAccount
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
class EditEcoAccountView(LoginRequiredMixin, View):
|
||||||
@default_group_required
|
_TEMPLATE = "compensation/form/view.html"
|
||||||
@shared_access_required(EcoAccount, "id")
|
|
||||||
def edit_view(request: HttpRequest, id: str):
|
|
||||||
"""
|
|
||||||
Renders a view for editing compensations
|
|
||||||
|
|
||||||
Args:
|
@method_decorator(default_group_required)
|
||||||
request (HttpRequest): The incoming request
|
@method_decorator(shared_access_required(EcoAccount, "id"))
|
||||||
|
def get(self, request: HttpRequest, id: str, *args, **kwargs) -> HttpResponse:
|
||||||
|
|
||||||
Returns:
|
"""
|
||||||
|
Renders a view for editing compensations
|
||||||
|
|
||||||
"""
|
Args:
|
||||||
template = "compensation/form/view.html"
|
request (HttpRequest): The incoming request
|
||||||
# Get object from db
|
|
||||||
acc = get_object_or_404(EcoAccount, id=id)
|
Returns:
|
||||||
if acc.is_recorded:
|
|
||||||
messages.info(
|
"""
|
||||||
request,
|
# Get object from db
|
||||||
RECORDED_BLOCKS_EDIT
|
acc = get_object_or_404(EcoAccount, id=id)
|
||||||
)
|
if acc.is_recorded:
|
||||||
return redirect("compensation:acc:detail", id=id)
|
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)
|
||||||
|
|
||||||
|
context = {
|
||||||
|
"form": data_form,
|
||||||
|
"geom_form": geom_form,
|
||||||
|
TAB_TITLE_IDENTIFIER: _("Edit {}").format(acc.identifier),
|
||||||
|
}
|
||||||
|
context = BaseContext(request, context).context
|
||||||
|
return render(request, self._TEMPLATE, context)
|
||||||
|
|
||||||
|
@method_decorator(default_group_required)
|
||||||
|
@method_decorator(shared_access_required(EcoAccount, "id"))
|
||||||
|
def post(self, request: HttpRequest, id: str, *args, **kwargs) -> HttpResponse:
|
||||||
|
|
||||||
|
"""
|
||||||
|
Renders a view for editing compensations
|
||||||
|
|
||||||
|
Args:
|
||||||
|
request (HttpRequest): The incoming request
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
"""
|
||||||
|
# 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)
|
||||||
|
|
||||||
# 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()
|
data_form_valid = data_form.is_valid()
|
||||||
geom_form_valid = geom_form.is_valid()
|
geom_form_valid = geom_form.is_valid()
|
||||||
if data_form_valid and geom_form_valid:
|
if data_form_valid and geom_form_valid:
|
||||||
# The data form takes the geom form for processing, as well as the performing user
|
# The data form takes the geom form for processing, as well as the performing user
|
||||||
acc = data_form.save(request.user, geom_form)
|
acc = data_form.save(request.user, geom_form)
|
||||||
messages.success(request, _("Eco-Account {} edited").format(acc.identifier))
|
messages.success(request, _("Eco-Account {} edited").format(acc.identifier))
|
||||||
if geom_form.geometry_simplified:
|
if geom_form.has_geometry_simplified():
|
||||||
messages.info(
|
messages.info(
|
||||||
request,
|
request,
|
||||||
GEOMETRY_SIMPLIFIED
|
GEOMETRY_SIMPLIFIED
|
||||||
)
|
)
|
||||||
|
num_ignored_geometries = geom_form.get_num_geometries_ignored()
|
||||||
|
if num_ignored_geometries > 0:
|
||||||
|
messages.info(
|
||||||
|
request,
|
||||||
|
GEOMETRIES_IGNORED_TEMPLATE.format(num_ignored_geometries)
|
||||||
|
)
|
||||||
return redirect("compensation:acc:detail", id=acc.id)
|
return redirect("compensation:acc:detail", id=acc.id)
|
||||||
else:
|
else:
|
||||||
messages.error(request, FORM_INVALID, extra_tags="danger",)
|
messages.error(request, FORM_INVALID, extra_tags="danger", )
|
||||||
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)
|
|
||||||
|
|
||||||
|
context = {
|
||||||
|
"form": data_form,
|
||||||
|
"geom_form": geom_form,
|
||||||
|
TAB_TITLE_IDENTIFIER: _("Edit {}").format(acc.identifier),
|
||||||
|
}
|
||||||
|
context = BaseContext(request, context).context
|
||||||
|
|
||||||
@login_required
|
return render(request, self._TEMPLATE, context)
|
||||||
@any_group_check
|
|
||||||
@uuid_required
|
|
||||||
def detail_view(request: HttpRequest, id: str):
|
|
||||||
""" Renders a detail view for a compensation
|
|
||||||
|
|
||||||
Args:
|
|
||||||
request (HttpRequest): The incoming request
|
|
||||||
id (str): The compensation's id
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
|
|
||||||
"""
|
|
||||||
template = "compensation/detail/eco_account/view.html"
|
|
||||||
acc = get_object_or_404(
|
|
||||||
EcoAccount.objects.prefetch_related(
|
|
||||||
"deadlines",
|
|
||||||
).select_related(
|
|
||||||
'geometry',
|
|
||||||
'responsible',
|
|
||||||
),
|
|
||||||
id=id,
|
|
||||||
deleted=None,
|
|
||||||
)
|
|
||||||
geom_form = SimpleGeomForm(instance=acc)
|
|
||||||
parcels = acc.get_underlying_parcels()
|
|
||||||
_user = request.user
|
|
||||||
is_data_shared = acc.is_shared_with(_user)
|
|
||||||
|
|
||||||
# Order states according to surface
|
|
||||||
before_states = acc.before_states.order_by("-surface")
|
|
||||||
after_states = acc.after_states.order_by("-surface")
|
|
||||||
|
|
||||||
# Precalculate logical errors between before- and after-states
|
|
||||||
# Sum() returns None in case of no states, so we catch that and replace it with 0 for easier handling
|
|
||||||
sum_before_states = acc.get_surface_before_states()
|
|
||||||
sum_after_states = acc.get_surface_after_states()
|
|
||||||
diff_states = abs(sum_before_states - sum_after_states)
|
|
||||||
# Calculate rest of available surface for deductions
|
|
||||||
available_total = acc.deductable_rest
|
|
||||||
available_relative = acc.get_deductable_rest_relative()
|
|
||||||
|
|
||||||
# Prefetch related data to decrease the amount of db connections
|
|
||||||
deductions = acc.deductions.filter(
|
|
||||||
intervention__deleted=None,
|
|
||||||
)
|
|
||||||
actions = acc.actions.all()
|
|
||||||
|
|
||||||
request = acc.set_status_messages(request)
|
|
||||||
|
|
||||||
requesting_user_is_only_shared_user = acc.is_only_shared_with(_user)
|
|
||||||
if requesting_user_is_only_shared_user:
|
|
||||||
messages.info(
|
|
||||||
request,
|
|
||||||
DO_NOT_FORGET_TO_SHARE
|
|
||||||
)
|
|
||||||
|
|
||||||
context = {
|
|
||||||
"obj": acc,
|
|
||||||
"geom_form": geom_form,
|
|
||||||
"parcels": parcels,
|
|
||||||
"is_entry_shared": is_data_shared,
|
|
||||||
"before_states": before_states,
|
|
||||||
"after_states": after_states,
|
|
||||||
"sum_before_states": sum_before_states,
|
|
||||||
"sum_after_states": sum_after_states,
|
|
||||||
"diff_states": diff_states,
|
|
||||||
"available": available_relative,
|
|
||||||
"available_total": available_total,
|
|
||||||
"is_default_member": _user.in_group(DEFAULT_GROUP),
|
|
||||||
"is_zb_member": _user.in_group(ZB_GROUP),
|
|
||||||
"is_ets_member": _user.in_group(ETS_GROUP),
|
|
||||||
"LANIS_LINK": acc.get_LANIS_link(),
|
|
||||||
"deductions": deductions,
|
|
||||||
"actions": actions,
|
|
||||||
TAB_TITLE_IDENTIFIER: f"{acc.identifier} - {acc.title}",
|
|
||||||
"has_finished_deadlines": acc.get_finished_deadlines().exists(),
|
|
||||||
}
|
|
||||||
context = BaseContext(request, context).context
|
|
||||||
return render(request, template, context)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required_modal
|
|
||||||
@login_required
|
|
||||||
@default_group_required
|
|
||||||
@shared_access_required(EcoAccount, "id")
|
|
||||||
def remove_view(request: HttpRequest, id: str):
|
|
||||||
""" Renders a modal view for removing the eco account
|
|
||||||
|
|
||||||
Args:
|
|
||||||
request (HttpRequest): The incoming request
|
|
||||||
id (str): The account's id
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
|
|
||||||
"""
|
|
||||||
acc = get_object_or_404(EcoAccount, id=id)
|
|
||||||
|
|
||||||
# If the eco account has already been recorded OR there are already deductions, it can not be deleted by a regular
|
|
||||||
# default group user
|
|
||||||
if acc.recorded is not None or acc.deductions.exists():
|
|
||||||
user = request.user
|
|
||||||
if not user.in_group(ETS_GROUP):
|
|
||||||
messages.info(request, CANCEL_ACC_RECORDED_OR_DEDUCTED)
|
|
||||||
return redirect("compensation:acc:detail", id=id)
|
|
||||||
|
|
||||||
form = RemoveEcoAccountModalForm(request.POST or None, instance=acc, request=request)
|
|
||||||
return form.process_request(
|
|
||||||
request=request,
|
|
||||||
msg_success=_("Eco-account removed"),
|
|
||||||
redirect_url=reverse("compensation:acc:index"),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|||||||
22
compensation/views/eco_account/remove.py
Normal file
22
compensation/views/eco_account/remove.py
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
"""
|
||||||
|
Author: Michel Peltriaux
|
||||||
|
Created on: 14.12.25
|
||||||
|
|
||||||
|
"""
|
||||||
|
from django.http import HttpRequest, HttpResponse
|
||||||
|
from django.utils.decorators import method_decorator
|
||||||
|
|
||||||
|
from compensation.forms.eco_account import RemoveEcoAccountModalForm
|
||||||
|
from compensation.models import EcoAccount
|
||||||
|
from konova.decorators import shared_access_required
|
||||||
|
from konova.views.remove import AbstractRemoveView
|
||||||
|
|
||||||
|
|
||||||
|
class RemoveEcoAccountView(AbstractRemoveView):
|
||||||
|
_MODEL = EcoAccount
|
||||||
|
_REDIRECT_URL = "compensation:acc:index"
|
||||||
|
_FORM = RemoveEcoAccountModalForm
|
||||||
|
|
||||||
|
@method_decorator(shared_access_required(EcoAccount, "id"))
|
||||||
|
def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
|
||||||
|
return super().get(request, *args, **kwargs)
|
||||||
@@ -5,7 +5,7 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
|||||||
Created on: 19.08.22
|
Created on: 19.08.22
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from django.http import HttpRequest
|
from django.http import HttpRequest, HttpResponse
|
||||||
from django.shortcuts import get_object_or_404, render
|
from django.shortcuts import get_object_or_404, render
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
@@ -14,74 +14,79 @@ from compensation.models import EcoAccount
|
|||||||
from konova.contexts import BaseContext
|
from konova.contexts import BaseContext
|
||||||
from konova.forms import SimpleGeomForm
|
from konova.forms import SimpleGeomForm
|
||||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
||||||
from konova.utils.generators import generate_qr_code
|
from konova.utils.qrcode import QrCode
|
||||||
|
from konova.views.report import AbstractPublicReportView
|
||||||
|
|
||||||
|
|
||||||
def report_view(request: HttpRequest, id: str):
|
class EcoAccountPublicReportView(AbstractPublicReportView):
|
||||||
""" Renders the public report view
|
_TEMPLATE = "compensation/report/eco_account/report.html"
|
||||||
|
|
||||||
Args:
|
def get(self, request: HttpRequest, id: str, *args, **kwargs) -> HttpResponse:
|
||||||
request (HttpRequest): The incoming request
|
""" Renders the public report view
|
||||||
id (str): The id of the intervention
|
|
||||||
|
|
||||||
Returns:
|
Args:
|
||||||
|
request (HttpRequest): The incoming request
|
||||||
|
id (str): The id of the intervention
|
||||||
|
|
||||||
"""
|
Returns:
|
||||||
# Reuse the compensation report template since EcoAccounts are structurally identical
|
|
||||||
template = "compensation/report/eco_account/report.html"
|
"""
|
||||||
acc = get_object_or_404(EcoAccount, id=id)
|
acc = get_object_or_404(EcoAccount, id=id)
|
||||||
|
tab_title = _("Report {}").format(acc.identifier)
|
||||||
|
# If intervention is not recorded (yet or currently) we need to render another template without any data
|
||||||
|
if not acc.is_ready_for_publish():
|
||||||
|
template = "report/unavailable.html"
|
||||||
|
context = {
|
||||||
|
TAB_TITLE_IDENTIFIER: tab_title,
|
||||||
|
}
|
||||||
|
context = BaseContext(request, context).context
|
||||||
|
return render(request, template, context)
|
||||||
|
|
||||||
|
# Prepare data for map viewer
|
||||||
|
geom_form = SimpleGeomForm(
|
||||||
|
instance=acc
|
||||||
|
)
|
||||||
|
parcels = acc.get_underlying_parcels()
|
||||||
|
|
||||||
|
qrcode = QrCode(
|
||||||
|
content=request.build_absolute_uri(reverse("compensation:acc:report", args=(id,))),
|
||||||
|
size=10
|
||||||
|
)
|
||||||
|
qrcode_lanis = QrCode(
|
||||||
|
content=acc.get_LANIS_link(),
|
||||||
|
size=7
|
||||||
|
)
|
||||||
|
|
||||||
|
# Order states by surface
|
||||||
|
before_states = acc.before_states.all().order_by("-surface").select_related("biotope_type__parent")
|
||||||
|
after_states = acc.after_states.all().order_by("-surface").select_related("biotope_type__parent")
|
||||||
|
actions = acc.actions.all().prefetch_related("action_type__parent")
|
||||||
|
|
||||||
|
# Reduce amount of db fetched data to the bare minimum we need in the template (deduction's intervention id and identifier)
|
||||||
|
deductions = acc.deductions.all() \
|
||||||
|
.distinct("intervention") \
|
||||||
|
.select_related("intervention") \
|
||||||
|
.values_list("intervention__id", "intervention__identifier", "intervention__title", named=True)
|
||||||
|
|
||||||
tab_title = _("Report {}").format(acc.identifier)
|
|
||||||
# If intervention is not recorded (yet or currently) we need to render another template without any data
|
|
||||||
if not acc.is_ready_for_publish():
|
|
||||||
template = "report/unavailable.html"
|
|
||||||
context = {
|
context = {
|
||||||
|
"obj": acc,
|
||||||
|
"qrcode": {
|
||||||
|
"img": qrcode.get_img(),
|
||||||
|
"url": qrcode.get_content(),
|
||||||
|
},
|
||||||
|
"qrcode_lanis": {
|
||||||
|
"img": qrcode_lanis.get_img(),
|
||||||
|
"url": qrcode_lanis.get_content(),
|
||||||
|
},
|
||||||
|
"is_entry_shared": False, # disables action buttons during rendering
|
||||||
|
"before_states": before_states,
|
||||||
|
"after_states": after_states,
|
||||||
|
"geom_form": geom_form,
|
||||||
|
"parcels": parcels,
|
||||||
|
"actions": actions,
|
||||||
|
"deductions": deductions,
|
||||||
|
"tables_scrollable": False,
|
||||||
TAB_TITLE_IDENTIFIER: tab_title,
|
TAB_TITLE_IDENTIFIER: tab_title,
|
||||||
}
|
}
|
||||||
context = BaseContext(request, context).context
|
context = BaseContext(request, context).context
|
||||||
return render(request, template, context)
|
return render(request, self._TEMPLATE, context)
|
||||||
|
|
||||||
# Prepare data for map viewer
|
|
||||||
geom_form = SimpleGeomForm(
|
|
||||||
instance=acc
|
|
||||||
)
|
|
||||||
parcels = acc.get_underlying_parcels()
|
|
||||||
|
|
||||||
qrcode_url = request.build_absolute_uri(reverse("compensation:acc:report", args=(id,)))
|
|
||||||
qrcode_img = generate_qr_code(qrcode_url, 10)
|
|
||||||
qrcode_lanis_url = acc.get_LANIS_link()
|
|
||||||
qrcode_img_lanis = generate_qr_code(qrcode_lanis_url, 7)
|
|
||||||
|
|
||||||
# Order states by surface
|
|
||||||
before_states = acc.before_states.all().order_by("-surface").select_related("biotope_type__parent")
|
|
||||||
after_states = acc.after_states.all().order_by("-surface").select_related("biotope_type__parent")
|
|
||||||
actions = acc.actions.all().prefetch_related("action_type__parent")
|
|
||||||
|
|
||||||
# Reduce amount of db fetched data to the bare minimum we need in the template (deduction's intervention id and identifier)
|
|
||||||
deductions = acc.deductions.all()\
|
|
||||||
.distinct("intervention")\
|
|
||||||
.select_related("intervention")\
|
|
||||||
.values_list("intervention__id", "intervention__identifier", "intervention__title", named=True)
|
|
||||||
|
|
||||||
context = {
|
|
||||||
"obj": acc,
|
|
||||||
"qrcode": {
|
|
||||||
"img": qrcode_img,
|
|
||||||
"url": qrcode_url,
|
|
||||||
},
|
|
||||||
"qrcode_lanis": {
|
|
||||||
"img": qrcode_img_lanis,
|
|
||||||
"url": qrcode_lanis_url,
|
|
||||||
},
|
|
||||||
"is_entry_shared": False, # disables action buttons during rendering
|
|
||||||
"before_states": before_states,
|
|
||||||
"after_states": after_states,
|
|
||||||
"geom_form": geom_form,
|
|
||||||
"parcels": parcels,
|
|
||||||
"actions": actions,
|
|
||||||
"deductions": deductions,
|
|
||||||
"tables_scrollable": False,
|
|
||||||
TAB_TITLE_IDENTIFIER: tab_title,
|
|
||||||
}
|
|
||||||
context = BaseContext(request, context).context
|
|
||||||
return render(request, template, context)
|
|
||||||
|
|||||||
@@ -5,10 +5,12 @@ Contact: michel.peltriaux@sgdnord.rlp.de
|
|||||||
Created on: 09.08.21
|
Created on: 09.08.21
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.contrib.auth.decorators import login_required
|
|
||||||
from django.http import HttpRequest
|
from django.http import HttpRequest
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
|
from django.utils.decorators import method_decorator
|
||||||
|
from django.views import View
|
||||||
|
|
||||||
from compensation.forms.modals.payment import NewPaymentForm, RemovePaymentModalForm, EditPaymentModalForm
|
from compensation.forms.modals.payment import NewPaymentForm, RemovePaymentModalForm, EditPaymentModalForm
|
||||||
from compensation.models import Payment
|
from compensation.models import Payment
|
||||||
@@ -17,72 +19,97 @@ from konova.decorators import default_group_required, shared_access_required
|
|||||||
from konova.utils.message_templates import PAYMENT_ADDED, PAYMENT_REMOVED, PAYMENT_EDITED
|
from konova.utils.message_templates import PAYMENT_ADDED, PAYMENT_REMOVED, PAYMENT_EDITED
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
class NewPaymentView(LoginRequiredMixin, View):
|
||||||
@default_group_required
|
|
||||||
@shared_access_required(Intervention, "id")
|
|
||||||
def new_payment_view(request: HttpRequest, id: str):
|
|
||||||
""" Renders a modal view for adding new payments
|
|
||||||
|
|
||||||
Args:
|
def __process_request(self, request: HttpRequest, id: str):
|
||||||
request (HttpRequest): The incoming request
|
""" Renders a modal view for adding new payments
|
||||||
id (str): The intervention's id for which a new payment shall be added
|
|
||||||
|
|
||||||
Returns:
|
Args:
|
||||||
|
request (HttpRequest): The incoming request
|
||||||
|
id (str): The intervention's id for which a new payment shall be added
|
||||||
|
|
||||||
"""
|
Returns:
|
||||||
intervention = get_object_or_404(Intervention, id=id)
|
|
||||||
form = NewPaymentForm(request.POST or None, instance=intervention, request=request)
|
"""
|
||||||
return form.process_request(
|
intervention = get_object_or_404(Intervention, id=id)
|
||||||
request,
|
form = NewPaymentForm(request.POST or None, instance=intervention, request=request)
|
||||||
msg_success=PAYMENT_ADDED,
|
return form.process_request(
|
||||||
redirect_url=reverse("intervention:detail", args=(id,)) + "#related_data"
|
request,
|
||||||
)
|
msg_success=PAYMENT_ADDED,
|
||||||
|
redirect_url=reverse("intervention:detail", args=(id,)) + "#related_data"
|
||||||
|
)
|
||||||
|
|
||||||
|
@method_decorator(default_group_required)
|
||||||
|
@method_decorator(shared_access_required(Intervention, "id"))
|
||||||
|
def get(self, request: HttpRequest, id: str):
|
||||||
|
return self.__process_request(request, id=id)
|
||||||
|
|
||||||
|
@method_decorator(default_group_required)
|
||||||
|
@method_decorator(shared_access_required(Intervention, "id"))
|
||||||
|
def post(self, request: HttpRequest, id: str):
|
||||||
|
return self.__process_request(request, id=id)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
class RemovePaymentView(LoginRequiredMixin, View):
|
||||||
@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:
|
def __process_request(self, request: HttpRequest, id: str, payment_id: str):
|
||||||
request (HttpRequest): The incoming request
|
""" Renders a modal view for removing payments
|
||||||
id (str): The intervention's id
|
|
||||||
payment_id (str): The payment's id
|
|
||||||
|
|
||||||
Returns:
|
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)
|
intervention = get_object_or_404(Intervention, id=id)
|
||||||
return form.process_request(
|
payment = get_object_or_404(Payment, id=payment_id)
|
||||||
request=request,
|
form = RemovePaymentModalForm(request.POST or None, instance=intervention, payment=payment, request=request)
|
||||||
msg_success=PAYMENT_REMOVED,
|
return form.process_request(
|
||||||
redirect_url=reverse("intervention:detail", args=(payment.intervention_id,)) + "#related_data"
|
request=request,
|
||||||
)
|
msg_success=PAYMENT_REMOVED,
|
||||||
|
redirect_url=reverse("intervention:detail", args=(payment.intervention_id,)) + "#related_data"
|
||||||
|
)
|
||||||
|
|
||||||
|
@method_decorator(default_group_required)
|
||||||
|
@method_decorator(shared_access_required(Intervention, "id"))
|
||||||
|
def get(self, request: HttpRequest, id: str, payment_id: str):
|
||||||
|
return self.__process_request(request, id=id, payment_id=payment_id)
|
||||||
|
|
||||||
|
@method_decorator(default_group_required)
|
||||||
|
@method_decorator(shared_access_required(Intervention, "id"))
|
||||||
|
def post(self, request: HttpRequest, id: str, payment_id: str):
|
||||||
|
return self.__process_request(request, id=id, payment_id=payment_id)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
class EditPaymentView(LoginRequiredMixin, View):
|
||||||
@default_group_required
|
def __process_request(self, request: HttpRequest, id: str, payment_id: str):
|
||||||
@shared_access_required(Intervention, "id")
|
""" Renders a modal view for editing payments
|
||||||
def payment_edit_view(request: HttpRequest, id: str, payment_id: str):
|
|
||||||
""" Renders a modal view for editing payments
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
request (HttpRequest): The incoming request
|
request (HttpRequest): The incoming request
|
||||||
id (str): The intervention's id
|
id (str): The intervention's id
|
||||||
payment_id (str): The payment's id
|
payment_id (str): The payment's id
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
intervention = get_object_or_404(Intervention, id=id)
|
intervention = get_object_or_404(Intervention, id=id)
|
||||||
payment = get_object_or_404(Payment, id=payment_id)
|
payment = get_object_or_404(Payment, id=payment_id)
|
||||||
form = EditPaymentModalForm(request.POST or None, instance=intervention, payment=payment, request=request)
|
form = EditPaymentModalForm(request.POST or None, instance=intervention, payment=payment, request=request)
|
||||||
return form.process_request(
|
return form.process_request(
|
||||||
request=request,
|
request=request,
|
||||||
msg_success=PAYMENT_EDITED,
|
msg_success=PAYMENT_EDITED,
|
||||||
redirect_url=reverse("intervention:detail", args=(payment.intervention_id,)) + "#related_data"
|
redirect_url=reverse("intervention:detail", args=(payment.intervention_id,)) + "#related_data"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@method_decorator(default_group_required)
|
||||||
|
@method_decorator(shared_access_required(Intervention, "id"))
|
||||||
|
def get(self, request: HttpRequest, id: str, payment_id: str):
|
||||||
|
return self.__process_request(request, id=id, payment_id=payment_id)
|
||||||
|
|
||||||
|
@method_decorator(default_group_required)
|
||||||
|
@method_decorator(shared_access_required(Intervention, "id"))
|
||||||
|
def post(self, request: HttpRequest, id: str, payment_id: str):
|
||||||
|
return self.__process_request(request, id=id, payment_id=payment_id)
|
||||||
|
|||||||
@@ -15,10 +15,10 @@
|
|||||||
<button class="btn btn-default btn-modal mr-2" title="{% trans 'Resubmission' %}" data-form-url="{% url 'ema:resubmission-create' obj.id %}">
|
<button class="btn btn-default btn-modal mr-2" title="{% trans 'Resubmission' %}" data-form-url="{% url 'ema:resubmission-create' obj.id %}">
|
||||||
{% fa5_icon 'bell' %}
|
{% fa5_icon 'bell' %}
|
||||||
</button>
|
</button>
|
||||||
<button class="btn btn-default btn-modal mr-2" title="{% trans 'Share' %}" data-form-url="{% url 'ema:share-form' obj.id %}">
|
|
||||||
{% fa5_icon 'share-alt' %}
|
|
||||||
</button>
|
|
||||||
{% if is_ets_member %}
|
{% if is_ets_member %}
|
||||||
|
<button class="btn btn-default btn-modal mr-2" title="{% trans 'Share' %}" data-form-url="{% url 'ema:share-form' obj.id %}">
|
||||||
|
{% fa5_icon 'share-alt' %}
|
||||||
|
</button>
|
||||||
{% if obj.recorded %}
|
{% if obj.recorded %}
|
||||||
<button class="btn btn-default btn-modal mr-2" title="{% trans 'Unrecord' %}" data-form-url="{% url 'ema:record' obj.id %}">
|
<button class="btn btn-default btn-modal mr-2" title="{% trans 'Unrecord' %}" data-form-url="{% url 'ema:record' obj.id %}">
|
||||||
{% fa5_icon 'bookmark' 'far' %}
|
{% fa5_icon 'bookmark' 'far' %}
|
||||||
@@ -28,19 +28,21 @@
|
|||||||
{% fa5_icon 'bookmark' %}
|
{% fa5_icon 'bookmark' %}
|
||||||
</button>
|
</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<a href="{% url 'ema:edit' obj.id %}" class="mr-2">
|
||||||
|
<button class="btn btn-default" title="{% trans 'Edit' %}">
|
||||||
|
{% fa5_icon 'edit' %}
|
||||||
|
</button>
|
||||||
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if is_default_member %}
|
{% if is_default_member %}
|
||||||
<a href="{% url 'ema:edit' obj.id %}" class="mr-2">
|
<button class="btn btn-default btn-modal mr-2" data-form-url="{% url 'ema:log' obj.id %}" title="{% trans 'Show log' %}">
|
||||||
<button class="btn btn-default" title="{% trans 'Edit' %}">
|
{% fa5_icon 'history' %}
|
||||||
{% fa5_icon 'edit' %}
|
</button>
|
||||||
|
{% endif %}
|
||||||
|
{% if is_ets_member %}
|
||||||
|
<button class="btn btn-default btn-modal" data-form-url="{% url 'ema:remove' obj.id %}" title="{% trans 'Delete' %}">
|
||||||
|
{% fa5_icon 'trash' %}
|
||||||
</button>
|
</button>
|
||||||
</a>
|
|
||||||
<button class="btn btn-default btn-modal mr-2" data-form-url="{% url 'ema:log' obj.id %}" title="{% trans 'Show log' %}">
|
|
||||||
{% fa5_icon 'history' %}
|
|
||||||
</button>
|
|
||||||
<button class="btn btn-default btn-modal" data-form-url="{% url 'ema:remove' obj.id %}" title="{% trans 'Delete' %}">
|
|
||||||
{% fa5_icon 'trash' %}
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
@@ -118,6 +118,7 @@ class EmaViewTestCase(CompensationViewTestCase):
|
|||||||
self.index_url,
|
self.index_url,
|
||||||
self.detail_url,
|
self.detail_url,
|
||||||
self.report_url,
|
self.report_url,
|
||||||
|
self.log_url,
|
||||||
]
|
]
|
||||||
fail_urls = [
|
fail_urls = [
|
||||||
self.new_url,
|
self.new_url,
|
||||||
@@ -133,7 +134,6 @@ class EmaViewTestCase(CompensationViewTestCase):
|
|||||||
self.action_remove_url,
|
self.action_remove_url,
|
||||||
self.action_new_url,
|
self.action_new_url,
|
||||||
self.new_doc_url,
|
self.new_doc_url,
|
||||||
self.log_url,
|
|
||||||
self.remove_url,
|
self.remove_url,
|
||||||
]
|
]
|
||||||
self.assert_url_fail(client, fail_urls)
|
self.assert_url_fail(client, fail_urls)
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ class EmaWorkflowTestCase(BaseWorkflowTestCase):
|
|||||||
post_data = {
|
post_data = {
|
||||||
"identifier": test_id,
|
"identifier": test_id,
|
||||||
"title": test_title,
|
"title": test_title,
|
||||||
"geom": geom_json,
|
"output": geom_json,
|
||||||
"conservation_office": test_conservation_office.id
|
"conservation_office": test_conservation_office.id
|
||||||
}
|
}
|
||||||
self.client_user.post(new_url, post_data)
|
self.client_user.post(new_url, post_data)
|
||||||
@@ -84,7 +84,7 @@ class EmaWorkflowTestCase(BaseWorkflowTestCase):
|
|||||||
new_title = self.create_dummy_string()
|
new_title = self.create_dummy_string()
|
||||||
new_identifier = self.create_dummy_string()
|
new_identifier = self.create_dummy_string()
|
||||||
new_comment = self.create_dummy_string()
|
new_comment = self.create_dummy_string()
|
||||||
new_geometry = MultiPolygon(srid=4326) # Create an empty geometry
|
new_geometry = self.create_dummy_geometry() # Create an empty geometry
|
||||||
test_conservation_office = self.get_conservation_office_code()
|
test_conservation_office = self.get_conservation_office_code()
|
||||||
|
|
||||||
check_on_elements = {
|
check_on_elements = {
|
||||||
@@ -99,7 +99,7 @@ class EmaWorkflowTestCase(BaseWorkflowTestCase):
|
|||||||
"identifier": new_identifier,
|
"identifier": new_identifier,
|
||||||
"title": new_title,
|
"title": new_title,
|
||||||
"comment": new_comment,
|
"comment": new_comment,
|
||||||
"geom": new_geometry.geojson,
|
"output": self.create_geojson(new_geometry),
|
||||||
"conservation_office": test_conservation_office.id
|
"conservation_office": test_conservation_office.id
|
||||||
}
|
}
|
||||||
self.client_user.post(url, post_data)
|
self.client_user.post(url, post_data)
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ class NewEmaFormTestCase(BaseTestCase):
|
|||||||
)
|
)
|
||||||
geom_form_data = json.loads(geom_form_data)
|
geom_form_data = json.loads(geom_form_data)
|
||||||
geom_form_data = {
|
geom_form_data = {
|
||||||
"geom": json.dumps(geom_form_data)
|
"output": json.dumps(geom_form_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
geom_form = SimpleGeomForm(geom_form_data)
|
geom_form = SimpleGeomForm(geom_form_data)
|
||||||
@@ -116,7 +116,7 @@ class EditEmaFormTestCase(BaseTestCase):
|
|||||||
)
|
)
|
||||||
geom_form_data = json.loads(geom_form_data)
|
geom_form_data = json.loads(geom_form_data)
|
||||||
geom_form_data = {
|
geom_form_data = {
|
||||||
"geom": json.dumps(geom_form_data)
|
"output": json.dumps(geom_form_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
geom_form = SimpleGeomForm(geom_form_data)
|
geom_form = SimpleGeomForm(geom_form_data)
|
||||||
|
|||||||
20
ema/urls.py
20
ema/urls.py
@@ -9,26 +9,28 @@ from django.urls import path
|
|||||||
|
|
||||||
from ema.views.action import NewEmaActionView, EditEmaActionView, RemoveEmaActionView
|
from ema.views.action import NewEmaActionView, EditEmaActionView, RemoveEmaActionView
|
||||||
from ema.views.deadline import NewEmaDeadlineView, EditEmaDeadlineView, RemoveEmaDeadlineView
|
from ema.views.deadline import NewEmaDeadlineView, EditEmaDeadlineView, RemoveEmaDeadlineView
|
||||||
|
from ema.views.detail import DetailEmaView
|
||||||
from ema.views.document import NewEmaDocumentView, EditEmaDocumentView, RemoveEmaDocumentView, GetEmaDocumentView
|
from ema.views.document import NewEmaDocumentView, EditEmaDocumentView, RemoveEmaDocumentView, GetEmaDocumentView
|
||||||
from ema.views.ema import index_view, new_view, new_id_view, detail_view, edit_view, remove_view
|
from ema.views.ema import IndexEmaView, EmaIdentifierGeneratorView, EditEmaView, NewEmaView
|
||||||
from ema.views.log import EmaLogView
|
from ema.views.log import EmaLogView
|
||||||
from ema.views.record import EmaRecordView
|
from ema.views.record import EmaRecordView
|
||||||
from ema.views.report import report_view
|
from ema.views.remove import RemoveEmaView
|
||||||
|
from ema.views.report import EmaPublicReportView
|
||||||
from ema.views.resubmission import EmaResubmissionView
|
from ema.views.resubmission import EmaResubmissionView
|
||||||
from ema.views.share import EmaShareFormView, EmaShareByTokenView
|
from ema.views.share import EmaShareFormView, EmaShareByTokenView
|
||||||
from ema.views.state import NewEmaStateView, EditEmaStateView, RemoveEmaStateView
|
from ema.views.state import NewEmaStateView, EditEmaStateView, RemoveEmaStateView
|
||||||
|
|
||||||
app_name = "ema"
|
app_name = "ema"
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("", index_view, name="index"),
|
path("", IndexEmaView.as_view(), name="index"),
|
||||||
path("new/", new_view, name="new"),
|
path("new/", NewEmaView.as_view(), name="new"),
|
||||||
path("new/id", new_id_view, name="new-id"),
|
path("new/id", EmaIdentifierGeneratorView.as_view(), name="new-id"),
|
||||||
path("<id>", detail_view, name="detail"),
|
path("<id>", DetailEmaView.as_view(), name="detail"),
|
||||||
path('<id>/log', EmaLogView.as_view(), name='log'),
|
path('<id>/log', EmaLogView.as_view(), name='log'),
|
||||||
path('<id>/edit', edit_view, name='edit'),
|
path('<id>/edit', EditEmaView.as_view(), name='edit'),
|
||||||
path('<id>/remove', remove_view, name='remove'),
|
path('<id>/remove', RemoveEmaView.as_view(), name='remove'),
|
||||||
path('<id>/record', EmaRecordView.as_view(), name='record'),
|
path('<id>/record', EmaRecordView.as_view(), name='record'),
|
||||||
path('<id>/report', report_view, name='report'),
|
path('<id>/report', EmaPublicReportView.as_view(), name='report'),
|
||||||
path('<id>/resub', EmaResubmissionView.as_view(), name='resubmission-create'),
|
path('<id>/resub', EmaResubmissionView.as_view(), name='resubmission-create'),
|
||||||
|
|
||||||
path('<id>/state/new', NewEmaStateView.as_view(), name='new-state'),
|
path('<id>/state/new', NewEmaStateView.as_view(), name='new-state'),
|
||||||
|
|||||||
76
ema/views/detail.py
Normal file
76
ema/views/detail.py
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
"""
|
||||||
|
Author: Michel Peltriaux
|
||||||
|
Created on: 14.12.25
|
||||||
|
|
||||||
|
"""
|
||||||
|
from django.contrib import messages
|
||||||
|
from django.http import HttpResponse, HttpRequest
|
||||||
|
from django.shortcuts import get_object_or_404, render
|
||||||
|
|
||||||
|
from ema.models import Ema
|
||||||
|
from konova.contexts import BaseContext
|
||||||
|
from konova.forms import SimpleGeomForm
|
||||||
|
from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP
|
||||||
|
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
||||||
|
from konova.utils.message_templates import DO_NOT_FORGET_TO_SHARE
|
||||||
|
from konova.views.detail import AbstractDetailView
|
||||||
|
|
||||||
|
|
||||||
|
class DetailEmaView(AbstractDetailView):
|
||||||
|
_TEMPLATE = "ema/detail/view.html"
|
||||||
|
|
||||||
|
def get(self, request: HttpRequest, id: str, *args, **kwargs) -> HttpResponse:
|
||||||
|
""" Renders the detail view of an EMA
|
||||||
|
|
||||||
|
Args:
|
||||||
|
request (HttpRequest): The incoming request
|
||||||
|
id (str): The EMA id
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
"""
|
||||||
|
ema = get_object_or_404(Ema, id=id, deleted=None)
|
||||||
|
|
||||||
|
geom_form = SimpleGeomForm(instance=ema)
|
||||||
|
parcels = ema.get_underlying_parcels()
|
||||||
|
_user = request.user
|
||||||
|
is_entry_shared = ema.is_shared_with(_user)
|
||||||
|
|
||||||
|
# Order states according to surface
|
||||||
|
before_states = ema.before_states.all().order_by("-surface")
|
||||||
|
after_states = ema.after_states.all().order_by("-surface")
|
||||||
|
|
||||||
|
# Precalculate logical errors between before- and after-states
|
||||||
|
# Sum() returns None in case of no states, so we catch that and replace it with 0 for easier handling
|
||||||
|
sum_before_states = ema.get_surface_before_states()
|
||||||
|
sum_after_states = ema.get_surface_after_states()
|
||||||
|
diff_states = abs(sum_before_states - sum_after_states)
|
||||||
|
|
||||||
|
ema.set_status_messages(request)
|
||||||
|
|
||||||
|
requesting_user_is_only_shared_user = ema.is_only_shared_with(_user)
|
||||||
|
if requesting_user_is_only_shared_user:
|
||||||
|
messages.info(
|
||||||
|
request,
|
||||||
|
DO_NOT_FORGET_TO_SHARE
|
||||||
|
)
|
||||||
|
|
||||||
|
context = {
|
||||||
|
"obj": ema,
|
||||||
|
"geom_form": geom_form,
|
||||||
|
"parcels": parcels,
|
||||||
|
"is_entry_shared": is_entry_shared,
|
||||||
|
"before_states": before_states,
|
||||||
|
"after_states": after_states,
|
||||||
|
"sum_before_states": sum_before_states,
|
||||||
|
"sum_after_states": sum_after_states,
|
||||||
|
"diff_states": diff_states,
|
||||||
|
"is_default_member": _user.in_group(DEFAULT_GROUP),
|
||||||
|
"is_zb_member": _user.in_group(ZB_GROUP),
|
||||||
|
"is_ets_member": _user.in_group(ETS_GROUP),
|
||||||
|
"LANIS_LINK": ema.get_LANIS_link(),
|
||||||
|
TAB_TITLE_IDENTIFIER: f"{ema.identifier} - {ema.title}",
|
||||||
|
"has_finished_deadlines": ema.get_finished_deadlines().exists(),
|
||||||
|
}
|
||||||
|
context = BaseContext(request, context).context
|
||||||
|
return render(request, self._TEMPLATE, context)
|
||||||
341
ema/views/ema.py
341
ema/views/ema.py
@@ -7,71 +7,96 @@ Created on: 19.08.22
|
|||||||
"""
|
"""
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.db.models import Sum
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
from django.http import HttpRequest, JsonResponse
|
from django.http import HttpRequest, HttpResponse
|
||||||
from django.shortcuts import get_object_or_404, redirect, render
|
from django.shortcuts import get_object_or_404, redirect, render
|
||||||
from django.urls import reverse
|
from django.utils.decorators import method_decorator
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
from django.views.generic.base import View
|
||||||
|
|
||||||
from ema.forms import NewEmaForm, EditEmaForm
|
from ema.forms import NewEmaForm, EditEmaForm
|
||||||
from ema.models import Ema
|
from ema.models import Ema
|
||||||
from ema.tables import EmaTable
|
from ema.tables import EmaTable
|
||||||
from konova.contexts import BaseContext
|
from konova.contexts import BaseContext
|
||||||
from konova.decorators import shared_access_required, conservation_office_group_required, login_required_modal, \
|
from konova.decorators import shared_access_required, conservation_office_group_required
|
||||||
uuid_required
|
|
||||||
from konova.forms import SimpleGeomForm
|
from konova.forms import SimpleGeomForm
|
||||||
from konova.forms.modals import RemoveModalForm
|
|
||||||
from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP
|
|
||||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
||||||
from konova.utils.message_templates import RECORDED_BLOCKS_EDIT, IDENTIFIER_REPLACED, FORM_INVALID, \
|
from konova.utils.message_templates import RECORDED_BLOCKS_EDIT, IDENTIFIER_REPLACED, FORM_INVALID, \
|
||||||
DO_NOT_FORGET_TO_SHARE, GEOMETRY_SIMPLIFIED
|
GEOMETRY_SIMPLIFIED, GEOMETRIES_IGNORED_TEMPLATE
|
||||||
|
from konova.views.identifier import AbstractIdentifierGeneratorView
|
||||||
|
from konova.views.index import AbstractIndexView
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
class IndexEmaView(AbstractIndexView):
|
||||||
def index_view(request: HttpRequest):
|
def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
|
||||||
""" Renders the index view for EMAs
|
""" Renders the index view for EMAs
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
request (HttpRequest): The incoming request
|
request (HttpRequest): The incoming request
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
template = "generic_index.html"
|
emas = Ema.objects.filter(
|
||||||
emas = Ema.objects.filter(
|
deleted=None,
|
||||||
deleted=None,
|
).order_by(
|
||||||
).order_by(
|
"-modified__timestamp"
|
||||||
"-modified__timestamp"
|
)
|
||||||
)
|
|
||||||
|
|
||||||
table = EmaTable(
|
table = EmaTable(
|
||||||
request,
|
request,
|
||||||
queryset=emas
|
queryset=emas
|
||||||
)
|
)
|
||||||
context = {
|
context = {
|
||||||
"table": table,
|
"table": table,
|
||||||
TAB_TITLE_IDENTIFIER: _("EMAs - Overview"),
|
TAB_TITLE_IDENTIFIER: _("EMAs - Overview"),
|
||||||
}
|
}
|
||||||
context = BaseContext(request, context).context
|
context = BaseContext(request, context).context
|
||||||
return render(request, template, context)
|
return render(request, self._TEMPLATE, context)
|
||||||
|
|
||||||
|
class NewEmaView(LoginRequiredMixin, View):
|
||||||
|
_TEMPLATE = "ema/form/view.html"
|
||||||
|
|
||||||
@login_required
|
@method_decorator(conservation_office_group_required)
|
||||||
@conservation_office_group_required
|
def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
|
||||||
def new_view(request: HttpRequest):
|
""" GET endpoint
|
||||||
"""
|
|
||||||
Renders a view for a new eco account creation
|
|
||||||
|
|
||||||
Args:
|
Renders form for new EMA
|
||||||
request (HttpRequest): The incoming request
|
|
||||||
|
|
||||||
Returns:
|
Args:
|
||||||
|
request (HttpRequest): The incoming request
|
||||||
|
*args ():
|
||||||
|
**kwargs ():
|
||||||
|
|
||||||
"""
|
Returns:
|
||||||
template = "ema/form/view.html"
|
|
||||||
data_form = NewEmaForm(request.POST or None)
|
"""
|
||||||
geom_form = SimpleGeomForm(request.POST or None, read_only=False)
|
data_form = NewEmaForm(request.POST or None)
|
||||||
if request.method == "POST":
|
geom_form = SimpleGeomForm(request.POST or None, read_only=False)
|
||||||
|
context = {
|
||||||
|
"form": data_form,
|
||||||
|
"geom_form": geom_form,
|
||||||
|
TAB_TITLE_IDENTIFIER: _("New EMA"),
|
||||||
|
}
|
||||||
|
context = BaseContext(request, context).context
|
||||||
|
return render(request, self._TEMPLATE, context)
|
||||||
|
|
||||||
|
@method_decorator(conservation_office_group_required)
|
||||||
|
def post(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
|
||||||
|
""" POST endpoint
|
||||||
|
|
||||||
|
Processes submitted form
|
||||||
|
|
||||||
|
Args:
|
||||||
|
request (HttpRequest): The incoming request
|
||||||
|
*args ():
|
||||||
|
**kwargs ():
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
"""
|
||||||
|
data_form = NewEmaForm(request.POST or None)
|
||||||
|
geom_form = SimpleGeomForm(request.POST or None, read_only=False)
|
||||||
if data_form.is_valid() and geom_form.is_valid():
|
if data_form.is_valid() and geom_form.is_valid():
|
||||||
generated_identifier = data_form.cleaned_data.get("identifier", None)
|
generated_identifier = data_form.cleaned_data.get("identifier", None)
|
||||||
ema = data_form.save(request.user, geom_form)
|
ema = data_form.save(request.user, geom_form)
|
||||||
@@ -84,176 +109,124 @@ def new_view(request: HttpRequest):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
messages.success(request, _("EMA {} added").format(ema.identifier))
|
messages.success(request, _("EMA {} added").format(ema.identifier))
|
||||||
if geom_form.geometry_simplified:
|
if geom_form.has_geometry_simplified():
|
||||||
messages.info(
|
messages.info(
|
||||||
request,
|
request,
|
||||||
GEOMETRY_SIMPLIFIED
|
GEOMETRY_SIMPLIFIED
|
||||||
)
|
)
|
||||||
|
num_ignored_geometries = geom_form.get_num_geometries_ignored()
|
||||||
|
if num_ignored_geometries > 0:
|
||||||
|
messages.info(
|
||||||
|
request,
|
||||||
|
GEOMETRIES_IGNORED_TEMPLATE.format(num_ignored_geometries)
|
||||||
|
)
|
||||||
return redirect("ema:detail", id=ema.id)
|
return redirect("ema:detail", id=ema.id)
|
||||||
else:
|
else:
|
||||||
messages.error(request, FORM_INVALID, extra_tags="danger",)
|
messages.error(request, FORM_INVALID, extra_tags="danger",)
|
||||||
else:
|
context = {
|
||||||
# For clarification: nothing in this case
|
"form": data_form,
|
||||||
pass
|
"geom_form": geom_form,
|
||||||
context = {
|
TAB_TITLE_IDENTIFIER: _("New EMA"),
|
||||||
"form": data_form,
|
|
||||||
"geom_form": geom_form,
|
|
||||||
TAB_TITLE_IDENTIFIER: _("New EMA"),
|
|
||||||
}
|
|
||||||
context = BaseContext(request, context).context
|
|
||||||
return render(request, template, context)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
@conservation_office_group_required
|
|
||||||
def new_id_view(request: HttpRequest):
|
|
||||||
""" JSON endpoint
|
|
||||||
|
|
||||||
Provides fetching of free identifiers for e.g. AJAX calls
|
|
||||||
|
|
||||||
"""
|
|
||||||
tmp = Ema()
|
|
||||||
identifier = tmp.generate_new_identifier()
|
|
||||||
while Ema.objects.filter(identifier=identifier).exists():
|
|
||||||
identifier = tmp.generate_new_identifier()
|
|
||||||
return JsonResponse(
|
|
||||||
data={
|
|
||||||
"gen_data": identifier
|
|
||||||
}
|
}
|
||||||
)
|
context = BaseContext(request, context).context
|
||||||
|
return render(request, self._TEMPLATE, context)
|
||||||
|
|
||||||
|
class EmaIdentifierGeneratorView(AbstractIdentifierGeneratorView):
|
||||||
|
_MODEL = Ema
|
||||||
|
|
||||||
@login_required
|
@method_decorator(conservation_office_group_required)
|
||||||
@uuid_required
|
def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
|
||||||
def detail_view(request: HttpRequest, id: str):
|
return super().get(request, *args, **kwargs)
|
||||||
""" Renders the detail view of an EMA
|
|
||||||
|
|
||||||
Args:
|
class EditEmaView(LoginRequiredMixin, View):
|
||||||
request (HttpRequest): The incoming request
|
_TEMPLATE = "compensation/form/view.html"
|
||||||
id (str): The EMA id
|
|
||||||
|
|
||||||
Returns:
|
@method_decorator(conservation_office_group_required)
|
||||||
|
@method_decorator(shared_access_required(Ema, "id"))
|
||||||
|
def get(self, request: HttpRequest, id: str, *args, **kwargs) -> HttpResponse:
|
||||||
|
""" GET endpoint
|
||||||
|
|
||||||
"""
|
Renders form
|
||||||
template = "ema/detail/view.html"
|
|
||||||
ema = get_object_or_404(Ema, id=id, deleted=None)
|
|
||||||
|
|
||||||
geom_form = SimpleGeomForm(instance=ema)
|
Args:
|
||||||
parcels = ema.get_underlying_parcels()
|
request (HttpRequest): The incoming request
|
||||||
_user = request.user
|
id (str): The ema identifier
|
||||||
is_entry_shared = ema.is_shared_with(_user)
|
*args ():
|
||||||
|
**kwargs ():
|
||||||
|
|
||||||
# Order states according to surface
|
Returns:
|
||||||
before_states = ema.before_states.all().order_by("-surface")
|
|
||||||
after_states = ema.after_states.all().order_by("-surface")
|
|
||||||
|
|
||||||
# Precalculate logical errors between before- and after-states
|
"""
|
||||||
# Sum() returns None in case of no states, so we catch that and replace it with 0 for easier handling
|
# Get object from db
|
||||||
sum_before_states = ema.get_surface_before_states()
|
ema = get_object_or_404(Ema, id=id)
|
||||||
sum_after_states = ema.get_surface_after_states()
|
if ema.is_recorded:
|
||||||
diff_states = abs(sum_before_states - sum_after_states)
|
messages.info(
|
||||||
|
request,
|
||||||
|
RECORDED_BLOCKS_EDIT
|
||||||
|
)
|
||||||
|
return redirect("ema:detail", id=id)
|
||||||
|
|
||||||
ema.set_status_messages(request)
|
# Create forms, initialize with values from db/from POST request
|
||||||
|
data_form = EditEmaForm(instance=ema)
|
||||||
|
geom_form = SimpleGeomForm(read_only=False, instance=ema)
|
||||||
|
context = {
|
||||||
|
"form": data_form,
|
||||||
|
"geom_form": geom_form,
|
||||||
|
TAB_TITLE_IDENTIFIER: _("Edit {}").format(ema.identifier),
|
||||||
|
}
|
||||||
|
context = BaseContext(request, context).context
|
||||||
|
return render(request, self._TEMPLATE, context)
|
||||||
|
|
||||||
requesting_user_is_only_shared_user = ema.is_only_shared_with(_user)
|
@method_decorator(conservation_office_group_required)
|
||||||
if requesting_user_is_only_shared_user:
|
@method_decorator(shared_access_required(Ema, "id"))
|
||||||
messages.info(
|
def post(self, request: HttpRequest, id:str, *args, **kwargs) -> HttpResponse:
|
||||||
request,
|
""" POST endpoint
|
||||||
DO_NOT_FORGET_TO_SHARE
|
|
||||||
)
|
|
||||||
|
|
||||||
context = {
|
Process submitted forms
|
||||||
"obj": ema,
|
|
||||||
"geom_form": geom_form,
|
|
||||||
"parcels": parcels,
|
|
||||||
"is_entry_shared": is_entry_shared,
|
|
||||||
"before_states": before_states,
|
|
||||||
"after_states": after_states,
|
|
||||||
"sum_before_states": sum_before_states,
|
|
||||||
"sum_after_states": sum_after_states,
|
|
||||||
"diff_states": diff_states,
|
|
||||||
"is_default_member": _user.in_group(DEFAULT_GROUP),
|
|
||||||
"is_zb_member": _user.in_group(ZB_GROUP),
|
|
||||||
"is_ets_member": _user.in_group(ETS_GROUP),
|
|
||||||
"LANIS_LINK": ema.get_LANIS_link(),
|
|
||||||
TAB_TITLE_IDENTIFIER: f"{ema.identifier} - {ema.title}",
|
|
||||||
"has_finished_deadlines": ema.get_finished_deadlines().exists(),
|
|
||||||
}
|
|
||||||
context = BaseContext(request, context).context
|
|
||||||
return render(request, template, context)
|
|
||||||
|
|
||||||
|
Args:
|
||||||
|
request (HttpRequest): The incoming request
|
||||||
|
id (str): The id of the ema
|
||||||
|
*args ():
|
||||||
|
**kwargs ():
|
||||||
|
|
||||||
@login_required
|
Returns:
|
||||||
@conservation_office_group_required
|
|
||||||
@shared_access_required(Ema, "id")
|
|
||||||
def edit_view(request: HttpRequest, id: str):
|
|
||||||
"""
|
|
||||||
Renders a view for editing compensations
|
|
||||||
|
|
||||||
Args:
|
"""
|
||||||
request (HttpRequest): The incoming request
|
# Get object from db
|
||||||
|
ema = get_object_or_404(Ema, id=id)
|
||||||
|
if ema.is_recorded:
|
||||||
|
messages.info(
|
||||||
|
request,
|
||||||
|
RECORDED_BLOCKS_EDIT
|
||||||
|
)
|
||||||
|
return redirect("ema:detail", id=id)
|
||||||
|
|
||||||
Returns:
|
# Create forms, initialize with values from db/from POST request
|
||||||
|
data_form = EditEmaForm(request.POST or None, instance=ema)
|
||||||
"""
|
geom_form = SimpleGeomForm(request.POST or None, read_only=False, instance=ema)
|
||||||
template = "compensation/form/view.html"
|
|
||||||
# Get object from db
|
|
||||||
ema = get_object_or_404(Ema, id=id)
|
|
||||||
if ema.is_recorded:
|
|
||||||
messages.info(
|
|
||||||
request,
|
|
||||||
RECORDED_BLOCKS_EDIT
|
|
||||||
)
|
|
||||||
return redirect("ema:detail", id=id)
|
|
||||||
|
|
||||||
# Create forms, initialize with values from db/from POST request
|
|
||||||
data_form = EditEmaForm(request.POST or None, instance=ema)
|
|
||||||
geom_form = SimpleGeomForm(request.POST or None, read_only=False, instance=ema)
|
|
||||||
if request.method == "POST":
|
|
||||||
if data_form.is_valid() and geom_form.is_valid():
|
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
|
# The data form takes the geom form for processing, as well as the performing user
|
||||||
ema = data_form.save(request.user, geom_form)
|
ema = data_form.save(request.user, geom_form)
|
||||||
messages.success(request, _("EMA {} edited").format(ema.identifier))
|
messages.success(request, _("EMA {} edited").format(ema.identifier))
|
||||||
if geom_form.geometry_simplified:
|
if geom_form.has_geometry_simplified():
|
||||||
messages.info(
|
messages.info(
|
||||||
request,
|
request,
|
||||||
GEOMETRY_SIMPLIFIED
|
GEOMETRY_SIMPLIFIED
|
||||||
)
|
)
|
||||||
|
num_ignored_geometries = geom_form.get_num_geometries_ignored()
|
||||||
|
if num_ignored_geometries > 0:
|
||||||
|
messages.info(
|
||||||
|
request,
|
||||||
|
GEOMETRIES_IGNORED_TEMPLATE.format(num_ignored_geometries)
|
||||||
|
)
|
||||||
return redirect("ema:detail", id=ema.id)
|
return redirect("ema:detail", id=ema.id)
|
||||||
else:
|
else:
|
||||||
messages.error(request, FORM_INVALID, extra_tags="danger",)
|
messages.error(request, FORM_INVALID, extra_tags="danger", )
|
||||||
else:
|
context = {
|
||||||
# For clarification: nothing in this case
|
"form": data_form,
|
||||||
pass
|
"geom_form": geom_form,
|
||||||
context = {
|
TAB_TITLE_IDENTIFIER: _("Edit {}").format(ema.identifier),
|
||||||
"form": data_form,
|
}
|
||||||
"geom_form": geom_form,
|
context = BaseContext(request, context).context
|
||||||
TAB_TITLE_IDENTIFIER: _("Edit {}").format(ema.identifier),
|
return render(request, self._TEMPLATE, context)
|
||||||
}
|
|
||||||
context = BaseContext(request, context).context
|
|
||||||
return render(request, template, context)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required_modal
|
|
||||||
@login_required
|
|
||||||
@conservation_office_group_required
|
|
||||||
@shared_access_required(Ema, "id")
|
|
||||||
def remove_view(request: HttpRequest, id: str):
|
|
||||||
""" Renders a modal view for removing the EMA
|
|
||||||
|
|
||||||
Args:
|
|
||||||
request (HttpRequest): The incoming request
|
|
||||||
id (str): The EMA's id
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
|
|
||||||
"""
|
|
||||||
ema = get_object_or_404(Ema, id=id)
|
|
||||||
form = RemoveModalForm(request.POST or None, instance=ema, request=request)
|
|
||||||
return form.process_request(
|
|
||||||
request=request,
|
|
||||||
msg_success=_("EMA removed"),
|
|
||||||
redirect_url=reverse("ema:index"),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ class EmaLogView(AbstractLogView):
|
|||||||
|
|
||||||
@method_decorator(login_required_modal)
|
@method_decorator(login_required_modal)
|
||||||
@method_decorator(login_required)
|
@method_decorator(login_required)
|
||||||
@method_decorator(conservation_office_group_required)
|
|
||||||
@method_decorator(shared_access_required(Ema, "id"))
|
@method_decorator(shared_access_required(Ema, "id"))
|
||||||
def dispatch(self, request, *args, **kwargs):
|
def dispatch(self, request, *args, **kwargs):
|
||||||
return super().dispatch(request, *args, **kwargs)
|
return super().dispatch(request, *args, **kwargs)
|
||||||
|
|||||||
21
ema/views/remove.py
Normal file
21
ema/views/remove.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
"""
|
||||||
|
Author: Michel Peltriaux
|
||||||
|
Created on: 14.12.25
|
||||||
|
|
||||||
|
"""
|
||||||
|
from django.http import HttpRequest, HttpResponse
|
||||||
|
from django.utils.decorators import method_decorator
|
||||||
|
|
||||||
|
from ema.models import Ema
|
||||||
|
from konova.decorators import shared_access_required, conservation_office_group_required
|
||||||
|
from konova.views.remove import AbstractRemoveView
|
||||||
|
|
||||||
|
|
||||||
|
class RemoveEmaView(AbstractRemoveView):
|
||||||
|
_MODEL = Ema
|
||||||
|
_REDIRECT_URL = "ema:index"
|
||||||
|
|
||||||
|
@method_decorator(conservation_office_group_required)
|
||||||
|
@method_decorator(shared_access_required(Ema, "id"))
|
||||||
|
def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
|
||||||
|
return super().get(request, *args, **kwargs)
|
||||||
@@ -5,7 +5,7 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
|||||||
Created on: 19.08.22
|
Created on: 19.08.22
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from django.http import HttpRequest
|
from django.http import HttpRequest, HttpResponse
|
||||||
from django.shortcuts import get_object_or_404, render
|
from django.shortcuts import get_object_or_404, render
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
@@ -14,67 +14,72 @@ from ema.models import Ema
|
|||||||
from konova.contexts import BaseContext
|
from konova.contexts import BaseContext
|
||||||
from konova.forms import SimpleGeomForm
|
from konova.forms import SimpleGeomForm
|
||||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
||||||
from konova.utils.generators import generate_qr_code
|
from konova.utils.qrcode import QrCode
|
||||||
|
from konova.views.report import AbstractPublicReportView
|
||||||
|
|
||||||
|
|
||||||
def report_view(request:HttpRequest, id: str):
|
class EmaPublicReportView(AbstractPublicReportView):
|
||||||
""" Renders the public report view
|
_TEMPLATE = "ema/report/report.html"
|
||||||
|
|
||||||
Args:
|
def get(self, request: HttpRequest, id: str, *args, **kwargs) -> HttpResponse:
|
||||||
request (HttpRequest): The incoming request
|
""" Renders the public report view
|
||||||
id (str): The id of the intervention
|
|
||||||
|
|
||||||
Returns:
|
Args:
|
||||||
|
request (HttpRequest): The incoming request
|
||||||
|
id (str): The id of the intervention
|
||||||
|
|
||||||
"""
|
Returns:
|
||||||
# Reuse the compensation report template since EMAs are structurally identical
|
|
||||||
template = "ema/report/report.html"
|
"""
|
||||||
ema = get_object_or_404(Ema, id=id)
|
ema = get_object_or_404(Ema, id=id)
|
||||||
|
tab_title = _("Report {}").format(ema.identifier)
|
||||||
|
# If intervention is not recorded (yet or currently) we need to render another template without any data
|
||||||
|
if not ema.is_ready_for_publish():
|
||||||
|
template = "report/unavailable.html"
|
||||||
|
context = {
|
||||||
|
TAB_TITLE_IDENTIFIER: tab_title,
|
||||||
|
}
|
||||||
|
context = BaseContext(request, context).context
|
||||||
|
return render(request, template, context)
|
||||||
|
|
||||||
|
# Prepare data for map viewer
|
||||||
|
geom_form = SimpleGeomForm(
|
||||||
|
instance=ema,
|
||||||
|
)
|
||||||
|
parcels = ema.get_underlying_parcels()
|
||||||
|
|
||||||
|
qrcode = QrCode(
|
||||||
|
content=request.build_absolute_uri(reverse("ema:report", args=(id,))),
|
||||||
|
size=10
|
||||||
|
)
|
||||||
|
qrcode_lanis = QrCode(
|
||||||
|
content=ema.get_LANIS_link(),
|
||||||
|
size=7
|
||||||
|
)
|
||||||
|
|
||||||
|
# Order states by surface
|
||||||
|
before_states = ema.before_states.all().order_by("-surface").prefetch_related("biotope_type")
|
||||||
|
after_states = ema.after_states.all().order_by("-surface").prefetch_related("biotope_type")
|
||||||
|
actions = ema.actions.all().prefetch_related("action_type")
|
||||||
|
|
||||||
tab_title = _("Report {}").format(ema.identifier)
|
|
||||||
# If intervention is not recorded (yet or currently) we need to render another template without any data
|
|
||||||
if not ema.is_ready_for_publish():
|
|
||||||
template = "report/unavailable.html"
|
|
||||||
context = {
|
context = {
|
||||||
|
"obj": ema,
|
||||||
|
"qrcode": {
|
||||||
|
"img": qrcode.get_img(),
|
||||||
|
"url": qrcode.get_content(),
|
||||||
|
},
|
||||||
|
"qrcode_lanis": {
|
||||||
|
"img": qrcode_lanis.get_img(),
|
||||||
|
"url": qrcode_lanis.get_content(),
|
||||||
|
},
|
||||||
|
"is_entry_shared": False, # disables action buttons during rendering
|
||||||
|
"before_states": before_states,
|
||||||
|
"after_states": after_states,
|
||||||
|
"geom_form": geom_form,
|
||||||
|
"parcels": parcels,
|
||||||
|
"actions": actions,
|
||||||
|
"tables_scrollable": False,
|
||||||
TAB_TITLE_IDENTIFIER: tab_title,
|
TAB_TITLE_IDENTIFIER: tab_title,
|
||||||
}
|
}
|
||||||
context = BaseContext(request, context).context
|
context = BaseContext(request, context).context
|
||||||
return render(request, template, context)
|
return render(request, self._TEMPLATE, context)
|
||||||
|
|
||||||
# Prepare data for map viewer
|
|
||||||
geom_form = SimpleGeomForm(
|
|
||||||
instance=ema,
|
|
||||||
)
|
|
||||||
parcels = ema.get_underlying_parcels()
|
|
||||||
|
|
||||||
qrcode_url = request.build_absolute_uri(reverse("ema:report", args=(id,)))
|
|
||||||
qrcode_img = generate_qr_code(qrcode_url, 10)
|
|
||||||
qrcode_lanis_url = ema.get_LANIS_link()
|
|
||||||
qrcode_img_lanis = generate_qr_code(qrcode_lanis_url, 7)
|
|
||||||
|
|
||||||
# Order states by surface
|
|
||||||
before_states = ema.before_states.all().order_by("-surface").prefetch_related("biotope_type")
|
|
||||||
after_states = ema.after_states.all().order_by("-surface").prefetch_related("biotope_type")
|
|
||||||
actions = ema.actions.all().prefetch_related("action_type")
|
|
||||||
|
|
||||||
context = {
|
|
||||||
"obj": ema,
|
|
||||||
"qrcode": {
|
|
||||||
"img": qrcode_img,
|
|
||||||
"url": qrcode_url
|
|
||||||
},
|
|
||||||
"qrcode_lanis": {
|
|
||||||
"img": qrcode_img_lanis,
|
|
||||||
"url": qrcode_lanis_url
|
|
||||||
},
|
|
||||||
"is_entry_shared": False, # disables action buttons during rendering
|
|
||||||
"before_states": before_states,
|
|
||||||
"after_states": after_states,
|
|
||||||
"geom_form": geom_form,
|
|
||||||
"parcels": parcels,
|
|
||||||
"actions": actions,
|
|
||||||
"tables_scrollable": False,
|
|
||||||
TAB_TITLE_IDENTIFIER: tab_title,
|
|
||||||
}
|
|
||||||
context = BaseContext(request, context).context
|
|
||||||
return render(request, template, context)
|
|
||||||
@@ -37,6 +37,14 @@ class InterventionAdmin(BaseObjectAdmin):
|
|||||||
"geometry",
|
"geometry",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def get_actions(self, request):
|
||||||
|
DELETE_ACTION_IDENTIFIER = "delete_selected"
|
||||||
|
actions = super().get_actions(request)
|
||||||
|
|
||||||
|
if DELETE_ACTION_IDENTIFIER in actions:
|
||||||
|
del actions[DELETE_ACTION_IDENTIFIER]
|
||||||
|
|
||||||
|
return actions
|
||||||
|
|
||||||
class InterventionDocumentAdmin(AbstractDocumentAdmin):
|
class InterventionDocumentAdmin(AbstractDocumentAdmin):
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ class InterventionWorkflowTestCase(BaseWorkflowTestCase):
|
|||||||
post_data = {
|
post_data = {
|
||||||
"identifier": test_id,
|
"identifier": test_id,
|
||||||
"title": test_title,
|
"title": test_title,
|
||||||
"geom": geom_json,
|
"output": geom_json,
|
||||||
}
|
}
|
||||||
response = self.client_user.post(
|
response = self.client_user.post(
|
||||||
new_url,
|
new_url,
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ class NewInterventionFormTestCase(BaseTestCase):
|
|||||||
)
|
)
|
||||||
geom_form_data = json.loads(geom_form_data)
|
geom_form_data = json.loads(geom_form_data)
|
||||||
geom_form_data = {
|
geom_form_data = {
|
||||||
"geom": json.dumps(geom_form_data)
|
"output": json.dumps(geom_form_data)
|
||||||
}
|
}
|
||||||
geom_form = SimpleGeomForm(geom_form_data)
|
geom_form = SimpleGeomForm(geom_form_data)
|
||||||
|
|
||||||
@@ -104,7 +104,7 @@ class EditInterventionFormTestCase(NewInterventionFormTestCase):
|
|||||||
)
|
)
|
||||||
geom_form_data = json.loads(geom_form_data)
|
geom_form_data = json.loads(geom_form_data)
|
||||||
geom_form_data = {
|
geom_form_data = {
|
||||||
"geom": json.dumps(geom_form_data)
|
"output": json.dumps(geom_form_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
geom_form = SimpleGeomForm(geom_form_data)
|
geom_form = SimpleGeomForm(geom_form_data)
|
||||||
@@ -124,7 +124,7 @@ class EditInterventionFormTestCase(NewInterventionFormTestCase):
|
|||||||
self.assertIsNotNone(obj.responsible.handler)
|
self.assertIsNotNone(obj.responsible.handler)
|
||||||
self.assertEqual(obj.title, data["title"])
|
self.assertEqual(obj.title, data["title"])
|
||||||
self.assertEqual(obj.comment, data["comment"])
|
self.assertEqual(obj.comment, data["comment"])
|
||||||
self.assertTrue(test_geom.equals_exact(obj.geometry.geom, 0.000001))
|
self.assert_equal_geometries(test_geom, obj.geometry.geom)
|
||||||
|
|
||||||
self.assertEqual(obj.legal.binding_date, today)
|
self.assertEqual(obj.legal.binding_date, today)
|
||||||
self.assertEqual(obj.legal.registration_date, today)
|
self.assertEqual(obj.legal.registration_date, today)
|
||||||
|
|||||||
@@ -8,39 +8,42 @@ Created on: 30.11.20
|
|||||||
from django.urls import path
|
from django.urls import path
|
||||||
|
|
||||||
from intervention.autocomplete.intervention import InterventionAutocomplete
|
from intervention.autocomplete.intervention import InterventionAutocomplete
|
||||||
from intervention.views.check import check_view
|
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, \
|
from intervention.views.deduction import NewInterventionDeductionView, EditInterventionDeductionView, \
|
||||||
RemoveInterventionDeductionView
|
RemoveInterventionDeductionView
|
||||||
from intervention.views.document import NewInterventionDocumentView, GetInterventionDocumentView, \
|
from intervention.views.document import NewInterventionDocumentView, GetInterventionDocumentView, \
|
||||||
RemoveInterventionDocumentView, EditInterventionDocumentView
|
RemoveInterventionDocumentView, EditInterventionDocumentView
|
||||||
from intervention.views.intervention import index_view, new_view, new_id_view, detail_view, edit_view, remove_view
|
from intervention.views.intervention import IndexInterventionView, InterventionIdentifierGeneratorView, \
|
||||||
|
NewInterventionView, EditInterventionView
|
||||||
|
from intervention.views.remove import RemoveInterventionView
|
||||||
|
from intervention.views.detail import DetailInterventionView
|
||||||
from intervention.views.log import InterventionLogView
|
from intervention.views.log import InterventionLogView
|
||||||
from intervention.views.record import InterventionRecordView
|
from intervention.views.record import InterventionRecordView
|
||||||
from intervention.views.report import report_view
|
from intervention.views.report import InterventionPublicReportView
|
||||||
from intervention.views.resubmission import InterventionResubmissionView
|
from intervention.views.resubmission import InterventionResubmissionView
|
||||||
from intervention.views.revocation import new_revocation_view, edit_revocation_view, remove_revocation_view, \
|
from intervention.views.revocation import NewInterventionRevocationView, GetInterventionRevocationView, \
|
||||||
get_revocation_view
|
EditInterventionRevocationView, RemoveInterventionRevocationView
|
||||||
from intervention.views.share import InterventionShareFormView, InterventionShareByTokenView
|
from intervention.views.share import InterventionShareFormView, InterventionShareByTokenView
|
||||||
|
|
||||||
app_name = "intervention"
|
app_name = "intervention"
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("", index_view, name="index"),
|
path("", IndexInterventionView.as_view(), name="index"),
|
||||||
path('new/', new_view, name='new'),
|
path('new/', NewInterventionView.as_view(), name='new'),
|
||||||
path('new/id', new_id_view, name='new-id'),
|
path('new/id', InterventionIdentifierGeneratorView.as_view(), name='new-id'),
|
||||||
path('<id>', detail_view, name='detail'),
|
path('<id>', DetailInterventionView.as_view(), name='detail'),
|
||||||
path('<id>/log', InterventionLogView.as_view(), name='log'),
|
path('<id>/log', InterventionLogView.as_view(), name='log'),
|
||||||
path('<id>/edit', edit_view, name='edit'),
|
path('<id>/edit', EditInterventionView.as_view(), name='edit'),
|
||||||
path('<id>/remove', remove_view, name='remove'),
|
path('<id>/remove', RemoveInterventionView.as_view(), name='remove'),
|
||||||
path('<id>/share/<token>', InterventionShareByTokenView.as_view(), name='share-token'),
|
path('<id>/share/<token>', InterventionShareByTokenView.as_view(), name='share-token'),
|
||||||
path('<id>/share', InterventionShareFormView.as_view(), name='share-form'),
|
path('<id>/share', InterventionShareFormView.as_view(), name='share-form'),
|
||||||
path('<id>/check', check_view, name='check'),
|
path('<id>/check', InterventionCheckView.as_view(), name='check'),
|
||||||
path('<id>/record', InterventionRecordView.as_view(), name='record'),
|
path('<id>/record', InterventionRecordView.as_view(), name='record'),
|
||||||
path('<id>/report', report_view, name='report'),
|
path('<id>/report', InterventionPublicReportView.as_view(), name='report'),
|
||||||
path('<id>/resub', InterventionResubmissionView.as_view(), name='resubmission-create'),
|
path('<id>/resub', InterventionResubmissionView.as_view(), name='resubmission-create'),
|
||||||
|
|
||||||
# Compensations
|
# 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
|
# Documents
|
||||||
path('<id>/document/new/', NewInterventionDocumentView.as_view(), name='new-doc'),
|
path('<id>/document/new/', NewInterventionDocumentView.as_view(), name='new-doc'),
|
||||||
@@ -54,10 +57,10 @@ urlpatterns = [
|
|||||||
path('<id>/deduction/<deduction_id>/remove', RemoveInterventionDeductionView.as_view(), name='remove-deduction'),
|
path('<id>/deduction/<deduction_id>/remove', RemoveInterventionDeductionView.as_view(), name='remove-deduction'),
|
||||||
|
|
||||||
# Revocation routes
|
# Revocation routes
|
||||||
path('<id>/revocation/new', new_revocation_view, name='new-revocation'),
|
path('<id>/revocation/new', NewInterventionRevocationView.as_view(), name='new-revocation'),
|
||||||
path('<id>/revocation/<revocation_id>/edit', edit_revocation_view, name='edit-revocation'),
|
path('<id>/revocation/<revocation_id>/edit', EditInterventionRevocationView.as_view(), name='edit-revocation'),
|
||||||
path('<id>/revocation/<revocation_id>/remove', remove_revocation_view, name='remove-revocation'),
|
path('<id>/revocation/<revocation_id>/remove', RemoveInterventionRevocationView.as_view(), name='remove-revocation'),
|
||||||
path('revocation/<doc_id>', get_revocation_view, name='get-doc-revocation'),
|
path('revocation/<doc_id>', GetInterventionRevocationView.as_view(), name='get-doc-revocation'),
|
||||||
|
|
||||||
# Autocomplete
|
# Autocomplete
|
||||||
path("atcmplt/interventions", InterventionAutocomplete.as_view(), name="autocomplete"),
|
path("atcmplt/interventions", InterventionAutocomplete.as_view(), name="autocomplete"),
|
||||||
|
|||||||
@@ -5,35 +5,44 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
|||||||
Created on: 19.08.22
|
Created on: 19.08.22
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
from django.http import HttpRequest
|
from django.http import HttpRequest, HttpResponse
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
|
from django.utils.decorators import method_decorator
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
from django.views import View
|
||||||
|
|
||||||
from intervention.forms.modals.check import CheckModalForm
|
from intervention.forms.modals.check import CheckModalForm
|
||||||
from intervention.models import Intervention
|
from intervention.models import Intervention
|
||||||
from konova.decorators import registration_office_group_required, shared_access_required
|
from konova.decorators import registration_office_group_required, shared_access_required
|
||||||
from konova.utils.message_templates import INTERVENTION_INVALID
|
from konova.utils.message_templates import INTERVENTION_INVALID
|
||||||
|
|
||||||
|
class InterventionCheckView(LoginRequiredMixin, View):
|
||||||
|
|
||||||
@login_required
|
def __process_request(self, request: HttpRequest, id: str, *args, **kwargs) -> HttpResponse:
|
||||||
@registration_office_group_required
|
""" Renders check form for an intervention
|
||||||
@shared_access_required(Intervention, "id")
|
|
||||||
def check_view(request: HttpRequest, id: str):
|
|
||||||
""" Renders check form for an intervention
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
request (HttpRequest): The incoming request
|
request (HttpRequest): The incoming request
|
||||||
id (str): Intervention's id
|
id (str): Intervention's id
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
intervention = get_object_or_404(Intervention, id=id)
|
intervention = get_object_or_404(Intervention, id=id)
|
||||||
form = CheckModalForm(request.POST or None, instance=intervention, request=request)
|
form = CheckModalForm(request.POST or None, instance=intervention, request=request)
|
||||||
return form.process_request(
|
return form.process_request(
|
||||||
request,
|
request,
|
||||||
msg_success=_("Check performed"),
|
msg_success=_("Check performed"),
|
||||||
msg_error=INTERVENTION_INVALID
|
msg_error=INTERVENTION_INVALID
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@method_decorator(registration_office_group_required)
|
||||||
|
@method_decorator(shared_access_required(Intervention, "id"))
|
||||||
|
def get(self, request: HttpRequest, id: str, *args, **kwargs) -> HttpResponse:
|
||||||
|
return self.__process_request(request, id, *args, **kwargs)
|
||||||
|
|
||||||
|
@method_decorator(registration_office_group_required)
|
||||||
|
@method_decorator(shared_access_required(Intervention, "id"))
|
||||||
|
def post(self, request: HttpRequest, id: str, *args, **kwargs) -> HttpResponse:
|
||||||
|
return self.__process_request(request, id, *args, **kwargs)
|
||||||
|
|||||||
@@ -5,42 +5,50 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
|||||||
Created on: 19.08.22
|
Created on: 19.08.22
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
from django.http import HttpRequest, Http404
|
from django.http import HttpRequest, Http404, HttpResponse
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
from django.utils.decorators import method_decorator
|
||||||
|
from django.views import View
|
||||||
|
|
||||||
from intervention.models import Intervention
|
from intervention.models import Intervention
|
||||||
from konova.decorators import shared_access_required, login_required_modal
|
from konova.decorators import shared_access_required
|
||||||
from konova.forms.modals import RemoveModalForm
|
from konova.forms.modals import RemoveModalForm
|
||||||
from konova.utils.message_templates import COMPENSATION_REMOVED_TEMPLATE
|
from konova.utils.message_templates import COMPENSATION_REMOVED_TEMPLATE
|
||||||
|
|
||||||
|
|
||||||
@login_required_modal
|
class RemoveCompensationFromInterventionView(LoginRequiredMixin, View):
|
||||||
@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
|
|
||||||
|
|
||||||
Args:
|
def __process_request(self, request: HttpRequest, id: str, comp_id: str, *args, **kwargs) -> HttpResponse:
|
||||||
request (HttpRequest): The incoming request
|
""" Renders a modal view for removing the compensation
|
||||||
id (str): The compensation's id
|
|
||||||
|
|
||||||
Returns:
|
Args:
|
||||||
|
request (HttpRequest): The incoming request
|
||||||
|
id (str): The compensation's id
|
||||||
|
|
||||||
"""
|
Returns:
|
||||||
intervention = get_object_or_404(Intervention, id=id)
|
|
||||||
try:
|
"""
|
||||||
comp = intervention.compensations.get(
|
intervention = get_object_or_404(Intervention, id=id)
|
||||||
id=comp_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",
|
||||||
)
|
)
|
||||||
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",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
@method_decorator(shared_access_required(Intervention, "id"))
|
||||||
|
def get(self, request, id: str, comp_id: str, *args, **kwargs) -> HttpResponse:
|
||||||
|
return self.__process_request(request, id, comp_id, *args, **kwargs)
|
||||||
|
|
||||||
|
@method_decorator(shared_access_required(Intervention, "id"))
|
||||||
|
def post(self, request, id: str, comp_id: str, *args, **kwargs) -> HttpResponse:
|
||||||
|
return self.__process_request(request, id, comp_id, *args, **kwargs)
|
||||||
79
intervention/views/detail.py
Normal file
79
intervention/views/detail.py
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
"""
|
||||||
|
Author: Michel Peltriaux
|
||||||
|
Created on: 14.12.25
|
||||||
|
|
||||||
|
"""
|
||||||
|
from django.contrib import messages
|
||||||
|
from django.http import HttpResponse
|
||||||
|
from django.shortcuts import get_object_or_404, render
|
||||||
|
|
||||||
|
from intervention.models import Intervention
|
||||||
|
from konova.contexts import BaseContext
|
||||||
|
from konova.forms import SimpleGeomForm
|
||||||
|
from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP
|
||||||
|
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
||||||
|
from konova.utils.message_templates import DATA_CHECKED_PREVIOUSLY_TEMPLATE, DO_NOT_FORGET_TO_SHARE
|
||||||
|
from konova.views.detail import AbstractDetailView
|
||||||
|
|
||||||
|
|
||||||
|
class DetailInterventionView(AbstractDetailView):
|
||||||
|
_TEMPLATE = "intervention/detail/view.html"
|
||||||
|
|
||||||
|
def get(self, request, id: str, *args, **kwargs) -> HttpResponse:
|
||||||
|
# Fetch data, filter out deleted related data
|
||||||
|
intervention = get_object_or_404(
|
||||||
|
Intervention.objects.select_related(
|
||||||
|
"geometry",
|
||||||
|
"legal",
|
||||||
|
"responsible",
|
||||||
|
).prefetch_related(
|
||||||
|
"legal__revocations",
|
||||||
|
),
|
||||||
|
id=id,
|
||||||
|
deleted=None
|
||||||
|
)
|
||||||
|
compensations = intervention.compensations.filter(
|
||||||
|
deleted=None,
|
||||||
|
)
|
||||||
|
_user = request.user
|
||||||
|
is_data_shared = intervention.is_shared_with(user=_user)
|
||||||
|
|
||||||
|
geom_form = SimpleGeomForm(
|
||||||
|
instance=intervention,
|
||||||
|
)
|
||||||
|
last_checked = intervention.get_last_checked_action()
|
||||||
|
last_checked_tooltip = ""
|
||||||
|
if last_checked:
|
||||||
|
last_checked_tooltip = DATA_CHECKED_PREVIOUSLY_TEMPLATE.format(
|
||||||
|
last_checked.get_timestamp_str_formatted(),
|
||||||
|
last_checked.user
|
||||||
|
)
|
||||||
|
|
||||||
|
has_payment_without_document = intervention.payments.exists() and not intervention.get_documents()[1].exists()
|
||||||
|
|
||||||
|
requesting_user_is_only_shared_user = intervention.is_only_shared_with(_user)
|
||||||
|
if requesting_user_is_only_shared_user:
|
||||||
|
messages.info(
|
||||||
|
request,
|
||||||
|
DO_NOT_FORGET_TO_SHARE
|
||||||
|
)
|
||||||
|
|
||||||
|
context = {
|
||||||
|
"obj": intervention,
|
||||||
|
"last_checked": last_checked,
|
||||||
|
"last_checked_tooltip": last_checked_tooltip,
|
||||||
|
"compensations": compensations,
|
||||||
|
"is_entry_shared": is_data_shared,
|
||||||
|
"geom_form": geom_form,
|
||||||
|
"is_default_member": _user.in_group(DEFAULT_GROUP),
|
||||||
|
"is_zb_member": _user.in_group(ZB_GROUP),
|
||||||
|
"is_ets_member": _user.in_group(ETS_GROUP),
|
||||||
|
"LANIS_LINK": intervention.get_LANIS_link(),
|
||||||
|
"has_payment_without_document": has_payment_without_document,
|
||||||
|
TAB_TITLE_IDENTIFIER: f"{intervention.identifier} - {intervention.title}",
|
||||||
|
}
|
||||||
|
|
||||||
|
request = intervention.set_status_messages(request)
|
||||||
|
|
||||||
|
context = BaseContext(request, context).context
|
||||||
|
return render(request, self._TEMPLATE, context)
|
||||||
@@ -7,75 +7,98 @@ Created on: 19.08.22
|
|||||||
"""
|
"""
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.http import JsonResponse, HttpRequest
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
|
from django.http import HttpRequest, HttpResponse
|
||||||
from django.shortcuts import get_object_or_404, render, redirect
|
from django.shortcuts import get_object_or_404, render, redirect
|
||||||
from django.urls import reverse
|
from django.utils.decorators import method_decorator
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
from django.views import View
|
||||||
|
|
||||||
from intervention.forms.intervention import EditInterventionForm, NewInterventionForm
|
from intervention.forms.intervention import EditInterventionForm, NewInterventionForm
|
||||||
from intervention.models import Intervention
|
from intervention.models import Intervention
|
||||||
from intervention.tables import InterventionTable
|
from intervention.tables import InterventionTable
|
||||||
from konova.contexts import BaseContext
|
from konova.contexts import BaseContext
|
||||||
from konova.decorators import default_group_required, shared_access_required, any_group_check, login_required_modal, \
|
from konova.decorators import default_group_required, shared_access_required
|
||||||
uuid_required
|
|
||||||
from konova.forms import SimpleGeomForm
|
from konova.forms import SimpleGeomForm
|
||||||
from konova.forms.modals import RemoveModalForm
|
|
||||||
from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP
|
|
||||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
||||||
from konova.utils.message_templates import DATA_CHECKED_PREVIOUSLY_TEMPLATE, RECORDED_BLOCKS_EDIT, \
|
from konova.utils.message_templates import RECORDED_BLOCKS_EDIT, \
|
||||||
CHECK_STATE_RESET, FORM_INVALID, IDENTIFIER_REPLACED, DO_NOT_FORGET_TO_SHARE, GEOMETRY_SIMPLIFIED
|
CHECK_STATE_RESET, FORM_INVALID, IDENTIFIER_REPLACED, GEOMETRY_SIMPLIFIED, \
|
||||||
|
GEOMETRIES_IGNORED_TEMPLATE
|
||||||
|
from konova.views.identifier import AbstractIdentifierGeneratorView
|
||||||
|
from konova.views.index import AbstractIndexView
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
class IndexInterventionView(AbstractIndexView):
|
||||||
@any_group_check
|
def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
|
||||||
def index_view(request: HttpRequest):
|
"""
|
||||||
"""
|
Renders the index view for Interventions
|
||||||
Renders the index view for Interventions
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
request (HttpRequest): The incoming request
|
request (HttpRequest): The incoming request
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
A rendered view
|
A rendered view
|
||||||
"""
|
"""
|
||||||
template = "generic_index.html"
|
# Filtering by user access is performed in table filter inside InterventionTableFilter class
|
||||||
|
interventions = Intervention.objects.filter(
|
||||||
# Filtering by user access is performed in table filter inside InterventionTableFilter class
|
deleted=None, # not deleted
|
||||||
interventions = Intervention.objects.filter(
|
).select_related(
|
||||||
deleted=None, # not deleted
|
"legal"
|
||||||
).select_related(
|
).order_by(
|
||||||
"legal"
|
"-modified__timestamp"
|
||||||
).order_by(
|
)
|
||||||
"-modified__timestamp"
|
table = InterventionTable(
|
||||||
)
|
request=request,
|
||||||
table = InterventionTable(
|
queryset=interventions
|
||||||
request=request,
|
)
|
||||||
queryset=interventions
|
context = {
|
||||||
)
|
"table": table,
|
||||||
context = {
|
TAB_TITLE_IDENTIFIER: _("Interventions - Overview"),
|
||||||
"table": table,
|
}
|
||||||
TAB_TITLE_IDENTIFIER: _("Interventions - Overview"),
|
context = BaseContext(request, context).context
|
||||||
}
|
return render(request, self._TEMPLATE, context)
|
||||||
context = BaseContext(request, context).context
|
|
||||||
return render(request, template, context)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
class NewInterventionView(LoginRequiredMixin, View):
|
||||||
@default_group_required
|
_TEMPLATE = "intervention/form/view.html"
|
||||||
def new_view(request: HttpRequest):
|
|
||||||
"""
|
|
||||||
Renders a view for a new intervention creation
|
|
||||||
|
|
||||||
Args:
|
@method_decorator(default_group_required)
|
||||||
request (HttpRequest): The incoming request
|
def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
|
||||||
|
|
||||||
Returns:
|
"""
|
||||||
|
Renders a view for a new intervention creation
|
||||||
|
|
||||||
|
Args:
|
||||||
|
request (HttpRequest): The incoming request
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
"""
|
||||||
|
data_form = NewInterventionForm()
|
||||||
|
geom_form = SimpleGeomForm(read_only=False)
|
||||||
|
context = {
|
||||||
|
"form": data_form,
|
||||||
|
"geom_form": geom_form,
|
||||||
|
TAB_TITLE_IDENTIFIER: _("New intervention"),
|
||||||
|
}
|
||||||
|
context = BaseContext(request, context).context
|
||||||
|
return render(request, self._TEMPLATE, context)
|
||||||
|
|
||||||
|
@method_decorator(default_group_required)
|
||||||
|
def post(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
|
||||||
|
|
||||||
|
"""
|
||||||
|
Renders a view for a new intervention creation
|
||||||
|
|
||||||
|
Args:
|
||||||
|
request (HttpRequest): The incoming request
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
"""
|
||||||
|
data_form = NewInterventionForm(request.POST or None)
|
||||||
|
geom_form = SimpleGeomForm(request.POST or None, read_only=False)
|
||||||
|
|
||||||
"""
|
|
||||||
template = "intervention/form/view.html"
|
|
||||||
data_form = NewInterventionForm(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():
|
if data_form.is_valid() and geom_form.is_valid():
|
||||||
generated_identifier = data_form.cleaned_data.get("identifier", None)
|
generated_identifier = data_form.cleaned_data.get("identifier", None)
|
||||||
intervention = data_form.save(request.user, geom_form)
|
intervention = data_form.save(request.user, geom_form)
|
||||||
@@ -87,147 +110,100 @@ def new_view(request: HttpRequest):
|
|||||||
intervention.identifier
|
intervention.identifier
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
messages.success(request, _("Intervention {} added").format(intervention.identifier))
|
messages.success(request, _("Intervention {} added").format(intervention.identifier))
|
||||||
if geom_form.geometry_simplified:
|
if geom_form.has_geometry_simplified():
|
||||||
messages.info(
|
messages.info(
|
||||||
request,
|
request,
|
||||||
GEOMETRY_SIMPLIFIED
|
GEOMETRY_SIMPLIFIED
|
||||||
)
|
)
|
||||||
|
|
||||||
|
num_ignored_geometries = geom_form.get_num_geometries_ignored()
|
||||||
|
if num_ignored_geometries > 0:
|
||||||
|
messages.info(
|
||||||
|
request,
|
||||||
|
GEOMETRIES_IGNORED_TEMPLATE.format(num_ignored_geometries)
|
||||||
|
)
|
||||||
return redirect("intervention:detail", id=intervention.id)
|
return redirect("intervention:detail", id=intervention.id)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
messages.error(request, FORM_INVALID, extra_tags="danger",)
|
messages.error(request, FORM_INVALID, extra_tags="danger", )
|
||||||
else:
|
context = {
|
||||||
# For clarification: nothing in this case
|
"form": data_form,
|
||||||
pass
|
"geom_form": geom_form,
|
||||||
context = {
|
TAB_TITLE_IDENTIFIER: _("New intervention"),
|
||||||
"form": data_form,
|
|
||||||
"geom_form": geom_form,
|
|
||||||
TAB_TITLE_IDENTIFIER: _("New intervention"),
|
|
||||||
}
|
|
||||||
context = BaseContext(request, context).context
|
|
||||||
return render(request, template, context)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
@default_group_required
|
|
||||||
def new_id_view(request: HttpRequest):
|
|
||||||
""" JSON endpoint
|
|
||||||
|
|
||||||
Provides fetching of free identifiers for e.g. AJAX calls
|
|
||||||
|
|
||||||
"""
|
|
||||||
tmp_intervention = Intervention()
|
|
||||||
identifier = tmp_intervention.generate_new_identifier()
|
|
||||||
while Intervention.objects.filter(identifier=identifier).exists():
|
|
||||||
identifier = tmp_intervention.generate_new_identifier()
|
|
||||||
return JsonResponse(
|
|
||||||
data={
|
|
||||||
"gen_data": identifier
|
|
||||||
}
|
}
|
||||||
)
|
context = BaseContext(request, context).context
|
||||||
|
return render(request, self._TEMPLATE, context)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
class InterventionIdentifierGeneratorView(AbstractIdentifierGeneratorView):
|
||||||
@any_group_check
|
_MODEL = Intervention
|
||||||
@uuid_required
|
|
||||||
def detail_view(request: HttpRequest, id: str):
|
|
||||||
""" Renders a detail view for viewing an intervention's data
|
|
||||||
|
|
||||||
Args:
|
|
||||||
request (HttpRequest): The incoming request
|
|
||||||
id (str): The intervention's id
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
|
|
||||||
"""
|
|
||||||
template = "intervention/detail/view.html"
|
|
||||||
|
|
||||||
# Fetch data, filter out deleted related data
|
|
||||||
intervention = get_object_or_404(
|
|
||||||
Intervention.objects.select_related(
|
|
||||||
"geometry",
|
|
||||||
"legal",
|
|
||||||
"responsible",
|
|
||||||
).prefetch_related(
|
|
||||||
"legal__revocations",
|
|
||||||
),
|
|
||||||
id=id,
|
|
||||||
deleted=None
|
|
||||||
)
|
|
||||||
compensations = intervention.compensations.filter(
|
|
||||||
deleted=None,
|
|
||||||
)
|
|
||||||
_user = request.user
|
|
||||||
is_data_shared = intervention.is_shared_with(user=_user)
|
|
||||||
|
|
||||||
geom_form = SimpleGeomForm(
|
|
||||||
instance=intervention,
|
|
||||||
)
|
|
||||||
last_checked = intervention.get_last_checked_action()
|
|
||||||
last_checked_tooltip = ""
|
|
||||||
if last_checked:
|
|
||||||
last_checked_tooltip = DATA_CHECKED_PREVIOUSLY_TEMPLATE.format(
|
|
||||||
last_checked.get_timestamp_str_formatted(),
|
|
||||||
last_checked.user
|
|
||||||
)
|
|
||||||
|
|
||||||
has_payment_without_document = intervention.payments.exists() and not intervention.get_documents()[1].exists()
|
|
||||||
|
|
||||||
requesting_user_is_only_shared_user = intervention.is_only_shared_with(_user)
|
|
||||||
if requesting_user_is_only_shared_user:
|
|
||||||
messages.info(
|
|
||||||
request,
|
|
||||||
DO_NOT_FORGET_TO_SHARE
|
|
||||||
)
|
|
||||||
|
|
||||||
context = {
|
|
||||||
"obj": intervention,
|
|
||||||
"last_checked": last_checked,
|
|
||||||
"last_checked_tooltip": last_checked_tooltip,
|
|
||||||
"compensations": compensations,
|
|
||||||
"is_entry_shared": is_data_shared,
|
|
||||||
"geom_form": geom_form,
|
|
||||||
"is_default_member": _user.in_group(DEFAULT_GROUP),
|
|
||||||
"is_zb_member": _user.in_group(ZB_GROUP),
|
|
||||||
"is_ets_member": _user.in_group(ETS_GROUP),
|
|
||||||
"LANIS_LINK": intervention.get_LANIS_link(),
|
|
||||||
"has_payment_without_document": has_payment_without_document,
|
|
||||||
TAB_TITLE_IDENTIFIER: f"{intervention.identifier} - {intervention.title}",
|
|
||||||
}
|
|
||||||
|
|
||||||
request = intervention.set_status_messages(request)
|
|
||||||
|
|
||||||
context = BaseContext(request, context).context
|
|
||||||
return render(request, template, context)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
class EditInterventionView(LoginRequiredMixin, View):
|
||||||
@default_group_required
|
_TEMPLATE = "intervention/form/view.html"
|
||||||
@shared_access_required(Intervention, "id")
|
|
||||||
def edit_view(request: HttpRequest, id: str):
|
|
||||||
"""
|
|
||||||
Renders a view for editing interventions
|
|
||||||
|
|
||||||
Args:
|
@method_decorator(default_group_required)
|
||||||
request (HttpRequest): The incoming request
|
@method_decorator(shared_access_required(Intervention, "id"))
|
||||||
|
def get(self, request: HttpRequest, id: str, *args, **kwargs) -> HttpResponse:
|
||||||
|
"""
|
||||||
|
Renders a view for editing interventions
|
||||||
|
|
||||||
Returns:
|
Args:
|
||||||
|
request (HttpRequest): The incoming request
|
||||||
|
id (str): The intervention identifier
|
||||||
|
|
||||||
"""
|
Returns:
|
||||||
template = "intervention/form/view.html"
|
HttpResponse: The rendered view
|
||||||
# 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
|
# Get object from db
|
||||||
data_form = EditInterventionForm(request.POST or None, instance=intervention)
|
intervention = get_object_or_404(Intervention, id=id)
|
||||||
geom_form = SimpleGeomForm(request.POST or None, read_only=False, instance=intervention)
|
if intervention.is_recorded:
|
||||||
if request.method == "POST":
|
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)
|
||||||
|
context = {
|
||||||
|
"form": data_form,
|
||||||
|
"geom_form": geom_form,
|
||||||
|
TAB_TITLE_IDENTIFIER: _("Edit {}").format(intervention.identifier),
|
||||||
|
}
|
||||||
|
context = BaseContext(request, context).context
|
||||||
|
return render(request, self._TEMPLATE, context)
|
||||||
|
|
||||||
|
|
||||||
|
@method_decorator(default_group_required)
|
||||||
|
@method_decorator(shared_access_required(Intervention, "id"))
|
||||||
|
def post(self, request: HttpRequest, id: str, *args, **kwargs) -> HttpResponse:
|
||||||
|
"""
|
||||||
|
Process saved form content
|
||||||
|
|
||||||
|
Args:
|
||||||
|
request (HttpRequest): The incoming request
|
||||||
|
id (str): The intervention id
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
HttpResponse:
|
||||||
|
"""
|
||||||
|
# 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 data_form.is_valid() and geom_form.is_valid():
|
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
|
# 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
|
# Save the current state of recorded|checked to inform the user in case of a status reset due to editing
|
||||||
@@ -236,45 +212,22 @@ def edit_view(request: HttpRequest, id: str):
|
|||||||
messages.success(request, _("Intervention {} edited").format(intervention.identifier))
|
messages.success(request, _("Intervention {} edited").format(intervention.identifier))
|
||||||
if intervention_is_checked:
|
if intervention_is_checked:
|
||||||
messages.info(request, CHECK_STATE_RESET)
|
messages.info(request, CHECK_STATE_RESET)
|
||||||
if geom_form.geometry_simplified:
|
if geom_form.has_geometry_simplified():
|
||||||
messages.info(
|
messages.info(
|
||||||
request,
|
request,
|
||||||
GEOMETRY_SIMPLIFIED
|
GEOMETRY_SIMPLIFIED
|
||||||
)
|
)
|
||||||
|
num_ignored_geometries = geom_form.get_num_geometries_ignored()
|
||||||
|
if num_ignored_geometries > 0:
|
||||||
|
messages.info(
|
||||||
|
request,
|
||||||
|
GEOMETRIES_IGNORED_TEMPLATE.format(num_ignored_geometries)
|
||||||
|
)
|
||||||
return redirect("intervention:detail", id=intervention.id)
|
return redirect("intervention:detail", id=intervention.id)
|
||||||
else:
|
context = {
|
||||||
messages.error(request, FORM_INVALID, extra_tags="danger",)
|
"form": data_form,
|
||||||
else:
|
"geom_form": geom_form,
|
||||||
# For clarification: nothing in this case
|
TAB_TITLE_IDENTIFIER: _("Edit {}").format(intervention.identifier),
|
||||||
pass
|
}
|
||||||
context = {
|
context = BaseContext(request, context).context
|
||||||
"form": data_form,
|
return render(request, self._TEMPLATE, context)
|
||||||
"geom_form": geom_form,
|
|
||||||
TAB_TITLE_IDENTIFIER: _("Edit {}").format(intervention.identifier),
|
|
||||||
}
|
|
||||||
context = BaseContext(request, context).context
|
|
||||||
return render(request, template, context)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required_modal
|
|
||||||
@login_required
|
|
||||||
@default_group_required
|
|
||||||
@shared_access_required(Intervention, "id")
|
|
||||||
def remove_view(request: HttpRequest, id: str):
|
|
||||||
""" Renders a remove view for this intervention
|
|
||||||
|
|
||||||
Args:
|
|
||||||
request (HttpRequest): The incoming request
|
|
||||||
id (str): The uuid id as string
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
|
|
||||||
"""
|
|
||||||
obj = Intervention.objects.get(id=id)
|
|
||||||
identifier = obj.identifier
|
|
||||||
form = RemoveModalForm(request.POST or None, instance=obj, request=request)
|
|
||||||
return form.process_request(
|
|
||||||
request,
|
|
||||||
_("{} removed").format(identifier),
|
|
||||||
redirect_url=reverse("intervention:index")
|
|
||||||
)
|
|
||||||
|
|||||||
20
intervention/views/remove.py
Normal file
20
intervention/views/remove.py
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
"""
|
||||||
|
Author: Michel Peltriaux
|
||||||
|
Created on: 14.12.25
|
||||||
|
|
||||||
|
"""
|
||||||
|
from django.http import HttpRequest, HttpResponse
|
||||||
|
from django.utils.decorators import method_decorator
|
||||||
|
|
||||||
|
from intervention.models import Intervention
|
||||||
|
from konova.decorators import shared_access_required
|
||||||
|
from konova.views.remove import AbstractRemoveView
|
||||||
|
|
||||||
|
|
||||||
|
class RemoveInterventionView(AbstractRemoveView):
|
||||||
|
_MODEL = Intervention
|
||||||
|
_REDIRECT_URL = "intervention:index"
|
||||||
|
|
||||||
|
@method_decorator(shared_access_required(Intervention, "id"))
|
||||||
|
def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
|
||||||
|
return super().get(request, *args, **kwargs)
|
||||||
@@ -5,72 +5,78 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
|||||||
Created on: 19.08.22
|
Created on: 19.08.22
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from django.http import HttpRequest
|
from django.http import HttpRequest, HttpResponse
|
||||||
from django.shortcuts import get_object_or_404, render
|
from django.shortcuts import get_object_or_404, render
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from intervention.models import Intervention
|
from intervention.models import Intervention
|
||||||
from konova.contexts import BaseContext
|
from konova.contexts import BaseContext
|
||||||
from konova.decorators import uuid_required
|
|
||||||
from konova.forms import SimpleGeomForm
|
from konova.forms import SimpleGeomForm
|
||||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
||||||
from konova.utils.generators import generate_qr_code
|
from konova.utils.qrcode import QrCode
|
||||||
|
from konova.views.report import AbstractPublicReportView
|
||||||
|
|
||||||
|
|
||||||
@uuid_required
|
class InterventionPublicReportView(AbstractPublicReportView):
|
||||||
def report_view(request: HttpRequest, id: str):
|
_TEMPLATE = "intervention/report/report.html"
|
||||||
""" Renders the public report view
|
|
||||||
|
|
||||||
Args:
|
def get(self, request: HttpRequest, id: str, *args, **kwargs) -> HttpResponse:
|
||||||
request (HttpRequest): The incoming request
|
""" Renders the public report view
|
||||||
id (str): The id of the intervention
|
|
||||||
|
|
||||||
Returns:
|
Args:
|
||||||
|
request (HttpRequest): The incoming request
|
||||||
|
id (str): The id of the intervention
|
||||||
|
|
||||||
"""
|
Returns:
|
||||||
template = "intervention/report/report.html"
|
|
||||||
intervention = get_object_or_404(Intervention, id=id)
|
"""
|
||||||
|
intervention = get_object_or_404(Intervention, id=id)
|
||||||
|
|
||||||
|
tab_title = _("Report {}").format(intervention.identifier)
|
||||||
|
# If intervention is not recorded (yet or currently) we need to render another template without any data
|
||||||
|
if not intervention.is_ready_for_publish():
|
||||||
|
template = "report/unavailable.html"
|
||||||
|
context = {
|
||||||
|
TAB_TITLE_IDENTIFIER: tab_title,
|
||||||
|
}
|
||||||
|
context = BaseContext(request, context).context
|
||||||
|
return render(request, template, context)
|
||||||
|
|
||||||
|
# Prepare data for map viewer
|
||||||
|
geom_form = SimpleGeomForm(
|
||||||
|
instance=intervention
|
||||||
|
)
|
||||||
|
parcels = intervention.get_underlying_parcels()
|
||||||
|
|
||||||
|
distinct_deductions = intervention.deductions.all().distinct(
|
||||||
|
"account"
|
||||||
|
)
|
||||||
|
|
||||||
|
qrcode = QrCode(
|
||||||
|
content=request.build_absolute_uri(reverse("intervention:report", args=(id,))),
|
||||||
|
size=10
|
||||||
|
)
|
||||||
|
qrcode_lanis = QrCode(
|
||||||
|
content=intervention.get_LANIS_link(),
|
||||||
|
size=7
|
||||||
|
)
|
||||||
|
|
||||||
tab_title = _("Report {}").format(intervention.identifier)
|
|
||||||
# If intervention is not recorded (yet or currently) we need to render another template without any data
|
|
||||||
if not intervention.is_ready_for_publish():
|
|
||||||
template = "report/unavailable.html"
|
|
||||||
context = {
|
context = {
|
||||||
|
"obj": intervention,
|
||||||
|
"deductions": distinct_deductions,
|
||||||
|
"qrcode": {
|
||||||
|
"img": qrcode.get_img(),
|
||||||
|
"url": qrcode.get_content(),
|
||||||
|
},
|
||||||
|
"qrcode_lanis": {
|
||||||
|
"img": qrcode_lanis.get_img(),
|
||||||
|
"url": qrcode_lanis.get_content(),
|
||||||
|
},
|
||||||
|
"geom_form": geom_form,
|
||||||
|
"parcels": parcels,
|
||||||
|
"tables_scrollable": False,
|
||||||
TAB_TITLE_IDENTIFIER: tab_title,
|
TAB_TITLE_IDENTIFIER: tab_title,
|
||||||
}
|
}
|
||||||
context = BaseContext(request, context).context
|
context = BaseContext(request, context).context
|
||||||
return render(request, template, context)
|
return render(request, self._TEMPLATE, context)
|
||||||
|
|
||||||
# Prepare data for map viewer
|
|
||||||
geom_form = SimpleGeomForm(
|
|
||||||
instance=intervention
|
|
||||||
)
|
|
||||||
parcels = intervention.get_underlying_parcels()
|
|
||||||
|
|
||||||
distinct_deductions = intervention.deductions.all().distinct(
|
|
||||||
"account"
|
|
||||||
)
|
|
||||||
qrcode_url = request.build_absolute_uri(reverse("intervention:report", args=(id,)))
|
|
||||||
qrcode_img = generate_qr_code(qrcode_url, 10)
|
|
||||||
qrcode_lanis_url = intervention.get_LANIS_link()
|
|
||||||
qrcode_img_lanis = generate_qr_code(qrcode_lanis_url, 7)
|
|
||||||
|
|
||||||
context = {
|
|
||||||
"obj": intervention,
|
|
||||||
"deductions": distinct_deductions,
|
|
||||||
"qrcode": {
|
|
||||||
"img": qrcode_img,
|
|
||||||
"url": qrcode_url,
|
|
||||||
},
|
|
||||||
"qrcode_lanis": {
|
|
||||||
"img": qrcode_img_lanis,
|
|
||||||
"url": qrcode_lanis_url,
|
|
||||||
},
|
|
||||||
"geom_form": geom_form,
|
|
||||||
"parcels": parcels,
|
|
||||||
"tables_scrollable": False,
|
|
||||||
TAB_TITLE_IDENTIFIER: tab_title,
|
|
||||||
}
|
|
||||||
context = BaseContext(request, context).context
|
|
||||||
return render(request, template, context)
|
|
||||||
@@ -6,10 +6,12 @@ Created on: 19.08.22
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
from django.contrib import messages
|
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.http import HttpRequest, HttpResponse
|
||||||
from django.shortcuts import get_object_or_404, redirect
|
from django.shortcuts import get_object_or_404, redirect
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
from django.utils.decorators import method_decorator
|
||||||
|
from django.views import View
|
||||||
|
|
||||||
from intervention.forms.modals.revocation import NewRevocationModalForm, EditRevocationModalForm, \
|
from intervention.forms.modals.revocation import NewRevocationModalForm, EditRevocationModalForm, \
|
||||||
RemoveRevocationModalForm
|
RemoveRevocationModalForm
|
||||||
@@ -19,100 +21,125 @@ from konova.utils.documents import get_document
|
|||||||
from konova.utils.message_templates import REVOCATION_ADDED, DATA_UNSHARED, REVOCATION_EDITED, REVOCATION_REMOVED
|
from konova.utils.message_templates import REVOCATION_ADDED, DATA_UNSHARED, REVOCATION_EDITED, REVOCATION_REMOVED
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
class NewInterventionRevocationView(LoginRequiredMixin, View):
|
||||||
@default_group_required
|
def __process_request(self, request: HttpRequest, id: str, *args, **kwargs) -> HttpResponse:
|
||||||
@shared_access_required(Intervention, "id")
|
""" Renders sharing form for an intervention
|
||||||
def new_revocation_view(request: HttpRequest, id: str):
|
|
||||||
""" Renders sharing form for an intervention
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
request (HttpRequest): The incoming request
|
request (HttpRequest): The incoming request
|
||||||
id (str): Intervention's id
|
id (str): Intervention's id
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
intervention = get_object_or_404(Intervention, id=id)
|
intervention = get_object_or_404(Intervention, id=id)
|
||||||
form = NewRevocationModalForm(request.POST or None, request.FILES or None, instance=intervention, request=request)
|
form = NewRevocationModalForm(request.POST or None, request.FILES or None, instance=intervention,
|
||||||
return form.process_request(
|
request=request)
|
||||||
request,
|
return form.process_request(
|
||||||
msg_success=REVOCATION_ADDED,
|
|
||||||
redirect_url=reverse("intervention:detail", args=(id,)) + "#related_data"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
@default_group_required
|
|
||||||
def get_revocation_view(request: HttpRequest, doc_id: str):
|
|
||||||
""" Returns the revocation document as downloadable file
|
|
||||||
|
|
||||||
Wraps the generic document fetcher function from konova.utils.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
request (HttpRequest): The incoming request
|
|
||||||
doc_id (str): The document id
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
|
|
||||||
"""
|
|
||||||
doc = get_object_or_404(RevocationDocument, id=doc_id)
|
|
||||||
# File download only possible if related instance is shared with user
|
|
||||||
if not doc.instance.legal.intervention.users.filter(id=request.user.id):
|
|
||||||
messages.info(
|
|
||||||
request,
|
request,
|
||||||
DATA_UNSHARED
|
msg_success=REVOCATION_ADDED,
|
||||||
|
redirect_url=reverse("intervention:detail", args=(id,)) + "#related_data"
|
||||||
)
|
)
|
||||||
return redirect("intervention:detail", id=doc.instance.id)
|
|
||||||
return get_document(doc)
|
@method_decorator(default_group_required)
|
||||||
|
@method_decorator(shared_access_required(Intervention, "id"))
|
||||||
|
def get(self, request: HttpRequest, id: str, *args, **kwargs) -> HttpResponse:
|
||||||
|
return self.__process_request(request, id, *args, **kwargs)
|
||||||
|
|
||||||
|
@method_decorator(default_group_required)
|
||||||
|
@method_decorator(shared_access_required(Intervention, "id"))
|
||||||
|
def post(self, request: HttpRequest, id: str, *args, **kwargs) -> HttpResponse:
|
||||||
|
return self.__process_request(request, id, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
class GetInterventionRevocationView(LoginRequiredMixin, View):
|
||||||
@default_group_required
|
@method_decorator(default_group_required)
|
||||||
@shared_access_required(Intervention, "id")
|
def get(self, request: HttpRequest, doc_id: str, *args, **kwargs) -> HttpResponse:
|
||||||
def edit_revocation_view(request: HttpRequest, id: str, revocation_id: str):
|
""" Returns the revocation document as downloadable file
|
||||||
""" Renders a edit view for a revocation
|
|
||||||
|
|
||||||
Args:
|
Wraps the generic document fetcher function from konova.utils.
|
||||||
request (HttpRequest): The incoming request
|
|
||||||
id (str): The intervention's id as string
|
|
||||||
revocation_id (str): The revocation's id as string
|
|
||||||
|
|
||||||
Returns:
|
Args:
|
||||||
|
request (HttpRequest): The incoming request
|
||||||
|
doc_id (str): The document id
|
||||||
|
|
||||||
"""
|
Returns:
|
||||||
intervention = get_object_or_404(Intervention, id=id)
|
|
||||||
revocation = get_object_or_404(Revocation, id=revocation_id)
|
|
||||||
|
|
||||||
form = EditRevocationModalForm(request.POST or None, request.FILES or None, instance=intervention, revocation=revocation, request=request)
|
"""
|
||||||
return form.process_request(
|
doc = get_object_or_404(RevocationDocument, id=doc_id)
|
||||||
request,
|
# File download only possible if related instance is shared with user
|
||||||
REVOCATION_EDITED,
|
if not doc.instance.legal.intervention.users.filter(id=request.user.id):
|
||||||
redirect_url=reverse("intervention:detail", args=(intervention.id,)) + "#related_data"
|
messages.info(
|
||||||
)
|
request,
|
||||||
|
DATA_UNSHARED
|
||||||
|
)
|
||||||
|
return redirect("intervention:detail", id=doc.instance.id)
|
||||||
|
return get_document(doc)
|
||||||
|
|
||||||
|
|
||||||
@login_required_modal
|
class EditInterventionRevocationView(LoginRequiredMixin, View):
|
||||||
@login_required
|
def __process_request(self, request: HttpRequest, id: str, revocation_id: str, *args, **kwargs) -> HttpResponse:
|
||||||
@default_group_required
|
""" Renders a edit view for a revocation
|
||||||
@shared_access_required(Intervention, "id")
|
|
||||||
def remove_revocation_view(request: HttpRequest, id: str, revocation_id: str):
|
|
||||||
""" Renders a remove view for a revocation
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
request (HttpRequest): The incoming request
|
request (HttpRequest): The incoming request
|
||||||
id (str): The intervention's id as string
|
id (str): The intervention's id as string
|
||||||
revocation_id (str): The revocation's id as string
|
revocation_id (str): The revocation's id as string
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
intervention = get_object_or_404(Intervention, id=id)
|
intervention = get_object_or_404(Intervention, id=id)
|
||||||
revocation = get_object_or_404(Revocation, id=revocation_id)
|
revocation = get_object_or_404(Revocation, id=revocation_id)
|
||||||
|
|
||||||
form = RemoveRevocationModalForm(request.POST or None, instance=intervention, revocation=revocation, request=request)
|
form = EditRevocationModalForm(request.POST or None, request.FILES or None, instance=intervention,
|
||||||
return form.process_request(
|
revocation=revocation, request=request)
|
||||||
request,
|
return form.process_request(
|
||||||
REVOCATION_REMOVED,
|
request,
|
||||||
redirect_url=reverse("intervention:detail", args=(intervention.id,)) + "#related_data"
|
REVOCATION_EDITED,
|
||||||
)
|
redirect_url=reverse("intervention:detail", args=(intervention.id,)) + "#related_data"
|
||||||
|
)
|
||||||
|
|
||||||
|
@method_decorator(default_group_required)
|
||||||
|
@method_decorator(shared_access_required(Intervention, "id"))
|
||||||
|
def get(self, request: HttpRequest, id: str, revocation_id: str, *args, **kwargs) -> HttpResponse:
|
||||||
|
return self.__process_request(request, id, revocation_id, *args, **kwargs)
|
||||||
|
|
||||||
|
@method_decorator(default_group_required)
|
||||||
|
@method_decorator(shared_access_required(Intervention, "id"))
|
||||||
|
def post(self, request: HttpRequest, id: str, revocation_id: str, *args, **kwargs) -> HttpResponse:
|
||||||
|
return self.__process_request(request, id, revocation_id, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class RemoveInterventionRevocationView(LoginRequiredMixin, View):
|
||||||
|
def __process_request(self, request, id: str, revocation_id: str, *args, **kwargs) -> HttpResponse:
|
||||||
|
""" Renders a remove view for a revocation
|
||||||
|
|
||||||
|
Args:
|
||||||
|
request (HttpRequest): The incoming request
|
||||||
|
id (str): The intervention's id as string
|
||||||
|
revocation_id (str): The revocation's id as string
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
"""
|
||||||
|
intervention = get_object_or_404(Intervention, id=id)
|
||||||
|
revocation = get_object_or_404(Revocation, id=revocation_id)
|
||||||
|
|
||||||
|
form = RemoveRevocationModalForm(request.POST or None, instance=intervention, revocation=revocation,
|
||||||
|
request=request)
|
||||||
|
return form.process_request(
|
||||||
|
request,
|
||||||
|
REVOCATION_REMOVED,
|
||||||
|
redirect_url=reverse("intervention:detail", args=(intervention.id,)) + "#related_data"
|
||||||
|
)
|
||||||
|
|
||||||
|
@method_decorator(default_group_required)
|
||||||
|
@method_decorator(shared_access_required(Intervention, "id"))
|
||||||
|
def get(self, request: HttpRequest, id: str, revocation_id: str, *args, **kwargs) -> HttpResponse:
|
||||||
|
return self.__process_request(request, id, revocation_id, *args, **kwargs)
|
||||||
|
|
||||||
|
@method_decorator(default_group_required)
|
||||||
|
@method_decorator(shared_access_required(Intervention, "id"))
|
||||||
|
def post(self, request, id: str, revocation_id: str, *args, **kwargs) -> HttpResponse:
|
||||||
|
return self.__process_request(request, id, revocation_id, *args, **kwargs)
|
||||||
@@ -11,7 +11,7 @@ from uuid import UUID
|
|||||||
|
|
||||||
from bootstrap_modal_forms.mixins import is_ajax
|
from bootstrap_modal_forms.mixins import is_ajax
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.http import Http404
|
from django.core.exceptions import BadRequest
|
||||||
from django.shortcuts import redirect, get_object_or_404, render
|
from django.shortcuts import redirect, get_object_or_404, render
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
@@ -185,7 +185,7 @@ def uuid_required(function):
|
|||||||
try:
|
try:
|
||||||
uuid = UUID(uuid)
|
uuid = UUID(uuid)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise Http404(
|
raise BadRequest(
|
||||||
"Invalid UUID"
|
"Invalid UUID"
|
||||||
)
|
)
|
||||||
return function(request, *args, **kwargs)
|
return function(request, *args, **kwargs)
|
||||||
|
|||||||
@@ -25,15 +25,17 @@ class SimpleGeomForm(BaseForm):
|
|||||||
""" A geometry form for rendering geometry read-only using a widget
|
""" A geometry form for rendering geometry read-only using a widget
|
||||||
|
|
||||||
"""
|
"""
|
||||||
read_only = True
|
read_only: bool = True
|
||||||
geometry_simplified = False
|
_geometry_simplified: bool = False
|
||||||
geom = JSONField(
|
output = JSONField(
|
||||||
label=_("Geometry"),
|
label=_("Geometry"),
|
||||||
help_text=_(""),
|
help_text=_(""),
|
||||||
label_suffix="",
|
label_suffix="",
|
||||||
required=False,
|
required=False,
|
||||||
disabled=False,
|
disabled=False,
|
||||||
)
|
)
|
||||||
|
_num_geometries_ignored: int = 0
|
||||||
|
empty = False
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
self.read_only = kwargs.pop("read_only", True)
|
self.read_only = kwargs.pop("read_only", True)
|
||||||
@@ -48,33 +50,33 @@ class SimpleGeomForm(BaseForm):
|
|||||||
raise AttributeError
|
raise AttributeError
|
||||||
|
|
||||||
geojson = self.instance.geometry.as_feature_collection(srid=DEFAULT_SRID_RLP)
|
geojson = self.instance.geometry.as_feature_collection(srid=DEFAULT_SRID_RLP)
|
||||||
|
geojson = self._set_geojson_properties(geojson, title=self.instance.identifier or None)
|
||||||
geom = json.dumps(geojson)
|
geom = json.dumps(geojson)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
# If no geometry exists for this form, we simply set the value to None and zoom to the maximum level
|
# If no geometry exists for this form, we simply set the value to None and zoom to the maximum level
|
||||||
geom = ""
|
geom = json.dumps({})
|
||||||
self.empty = True
|
self.empty = True
|
||||||
|
|
||||||
self.initialize_form_field("geom", geom)
|
self.initialize_form_field("output", geom)
|
||||||
|
|
||||||
def is_valid(self):
|
def is_valid(self):
|
||||||
super().is_valid()
|
super().is_valid()
|
||||||
is_valid = True
|
is_valid = True
|
||||||
|
|
||||||
# Get geojson from form
|
# Make sure invalid geometry is properly rendered again to the user
|
||||||
geom = self.data["geom"]
|
# Therefore: write submitted data back into form field
|
||||||
if geom is None or len(geom) == 0:
|
# (does not matter whether we know if it is valid or invalid)
|
||||||
# empty geometry is a valid geometry
|
submitted_data = self.data["output"]
|
||||||
self.cleaned_data["geom"] = MultiPolygon(srid=DEFAULT_SRID_RLP).ewkt
|
submitted_data = json.loads(submitted_data)
|
||||||
return is_valid
|
submitted_data = self._set_geojson_properties(submitted_data)
|
||||||
|
self.initialize_form_field("output", json.dumps(submitted_data))
|
||||||
|
|
||||||
|
# Get geojson from form for validity checking
|
||||||
|
geom = self.data.get("output", json.dumps({}))
|
||||||
geom = json.loads(geom)
|
geom = json.loads(geom)
|
||||||
|
|
||||||
# Write submitted data back into form field to make sure invalid geometry
|
# Initialize features list with empty MultiPolygon, so that an empty input will result in a
|
||||||
# will be rendered again on failed submit
|
# proper empty MultiPolygon object
|
||||||
self.initialize_form_field("geom", self.data["geom"])
|
|
||||||
|
|
||||||
# Read geojson into gdal geometry
|
|
||||||
# HINT: This can be simplified if the geojson format holds data in epsg:4326 (GDAL provides direct creation for
|
|
||||||
# this case)
|
|
||||||
features = []
|
features = []
|
||||||
features_json = geom.get("features", [])
|
features_json = geom.get("features", [])
|
||||||
accepted_ogr_types = [
|
accepted_ogr_types = [
|
||||||
@@ -83,47 +85,64 @@ class SimpleGeomForm(BaseForm):
|
|||||||
"MultiPolygon",
|
"MultiPolygon",
|
||||||
"MultiPolygon25D",
|
"MultiPolygon25D",
|
||||||
]
|
]
|
||||||
|
# Check validity for each feature of the geometry
|
||||||
for feature in features_json:
|
for feature in features_json:
|
||||||
feature_geom = feature.get("geometry", feature)
|
feature_geom = feature.get("geometry", feature)
|
||||||
if feature_geom is None:
|
if feature_geom is None:
|
||||||
# Fallback for rare cases where a feature does not contain any geometry
|
# Fallback for rare cases where a feature does not contain any geometry
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# Try to create a geometry object from the single feature
|
||||||
feature_geom = json.dumps(feature_geom)
|
feature_geom = json.dumps(feature_geom)
|
||||||
g = gdal.OGRGeometry(feature_geom, srs=DEFAULT_SRID_RLP)
|
g = gdal.OGRGeometry(feature_geom, srs=DEFAULT_SRID_RLP)
|
||||||
|
|
||||||
flatten_geometry = g.coord_dim > 2
|
geometry_has_unwanted_dimensions = g.coord_dim > 2
|
||||||
if flatten_geometry:
|
if geometry_has_unwanted_dimensions:
|
||||||
g = self.__flatten_geom_to_2D(g)
|
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
|
||||||
self.add_error("geom", _("Only surfaces allowed. Points or lines must be buffered."))
|
if geometry_type_is_accepted:
|
||||||
|
self.add_error("output", _("Only surfaces allowed. Points or lines must be buffered."))
|
||||||
is_valid &= False
|
is_valid &= False
|
||||||
return is_valid
|
return is_valid
|
||||||
|
|
||||||
is_valid &= self.__is_area_valid(g)
|
is_area_valid = self.__is_area_valid(g)
|
||||||
|
if not is_area_valid:
|
||||||
|
# Geometries with an invalid size will not be saved to the db
|
||||||
|
# We assume these are malicious snippets which are not supposed to be in the geometry in the first place
|
||||||
|
self._num_geometries_ignored += 1
|
||||||
|
continue
|
||||||
|
|
||||||
polygon = Polygon.from_ewkt(g.ewkt)
|
# Whatever this geometry object is -> try to create a Polygon from it
|
||||||
is_valid &= polygon.valid
|
# The resulting polygon object automatically detects whether a valid polygon has been created or not
|
||||||
if not polygon.valid:
|
g = Polygon.from_ewkt(g.ewkt)
|
||||||
self.add_error("geom", polygon.valid_reason)
|
is_valid &= g.valid
|
||||||
|
if not g.valid:
|
||||||
|
self.add_error("output", g.valid_reason)
|
||||||
return is_valid
|
return is_valid
|
||||||
|
|
||||||
features.append(polygon)
|
# 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
|
||||||
form_geom = MultiPolygon(srid=DEFAULT_SRID_RLP)
|
if features:
|
||||||
for feature in features:
|
form_geom = MultiPolygon(*features, srid=DEFAULT_SRID_RLP).unary_union
|
||||||
form_geom = form_geom.union(feature)
|
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.
|
# Make sure to convert into a MultiPolygon. Relevant if a single Polygon is provided.
|
||||||
if form_geom.geom_type != "MultiPolygon":
|
form_geom = Geometry.cast_to_multipolygon(form_geom)
|
||||||
form_geom = MultiPolygon(form_geom, srid=DEFAULT_SRID_RLP)
|
|
||||||
|
|
||||||
# Write unioned Multipolygon into cleaned data
|
# Write unionized Multipolygon back into cleaned data
|
||||||
if self.cleaned_data is None:
|
if self.cleaned_data is None:
|
||||||
self.cleaned_data = {}
|
self.cleaned_data = {}
|
||||||
self.cleaned_data["geom"] = form_geom.ewkt
|
self.cleaned_data["output"] = form_geom.ewkt
|
||||||
|
|
||||||
return is_valid
|
return is_valid
|
||||||
|
|
||||||
@@ -133,7 +152,7 @@ class SimpleGeomForm(BaseForm):
|
|||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
geom = self.cleaned_data.get("geom")
|
geom = self.cleaned_data.get("output")
|
||||||
g = gdal.OGRGeometry(geom, srs=DEFAULT_SRID_RLP)
|
g = gdal.OGRGeometry(geom, srs=DEFAULT_SRID_RLP)
|
||||||
num_vertices = g.num_coords
|
num_vertices = g.num_coords
|
||||||
|
|
||||||
@@ -146,15 +165,6 @@ class SimpleGeomForm(BaseForm):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
is_area_valid = geom.area > 1 # > 1m² (SRID:25832)
|
is_area_valid = geom.area > 1 # > 1m² (SRID:25832)
|
||||||
|
|
||||||
if not is_area_valid:
|
|
||||||
self.add_error(
|
|
||||||
"geom",
|
|
||||||
_("Geometry must be greater than 1m². Currently is {}m²").format(
|
|
||||||
float(geom.area)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
return is_area_valid
|
return is_area_valid
|
||||||
|
|
||||||
def __simplify_geometry(self, geom, max_vert: int):
|
def __simplify_geometry(self, geom, max_vert: int):
|
||||||
@@ -192,14 +202,14 @@ class SimpleGeomForm(BaseForm):
|
|||||||
if self.instance is None or self.instance.geometry is None:
|
if self.instance is None or self.instance.geometry is None:
|
||||||
raise LookupError
|
raise LookupError
|
||||||
geometry = self.instance.geometry
|
geometry = self.instance.geometry
|
||||||
geometry.geom = self.cleaned_data.get("geom", MultiPolygon(srid=DEFAULT_SRID_RLP))
|
geometry.geom = self.cleaned_data.get("output", MultiPolygon(srid=DEFAULT_SRID_RLP))
|
||||||
geometry.modified = action
|
geometry.modified = action
|
||||||
|
|
||||||
geometry.save()
|
geometry.save()
|
||||||
except LookupError:
|
except LookupError:
|
||||||
# No geometry or linked instance holding a geometry exist --> create a new one!
|
# No geometry or linked instance holding a geometry exist --> create a new one!
|
||||||
geometry = Geometry.objects.create(
|
geometry = Geometry.objects.create(
|
||||||
geom=self.cleaned_data.get("geom", MultiPolygon(srid=DEFAULT_SRID_RLP)),
|
geom=self.cleaned_data.get("output", MultiPolygon(srid=DEFAULT_SRID_RLP)),
|
||||||
created=action,
|
created=action,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -207,13 +217,29 @@ class SimpleGeomForm(BaseForm):
|
|||||||
if not is_vertices_num_valid:
|
if not is_vertices_num_valid:
|
||||||
geometry.geom = self.__simplify_geometry(geometry.geom, max_vert=GEOM_MAX_VERTICES)
|
geometry.geom = self.__simplify_geometry(geometry.geom, max_vert=GEOM_MAX_VERTICES)
|
||||||
geometry.save()
|
geometry.save()
|
||||||
self.geometry_simplified = True
|
self._geometry_simplified = True
|
||||||
|
|
||||||
# Start parcel update and geometry conflict checking procedure in a background process
|
# Start parcel update and geometry conflict checking procedure in a background process
|
||||||
celery_update_parcels.delay(geometry.id)
|
celery_update_parcels.delay(geometry.id)
|
||||||
celery_check_for_geometry_conflicts.delay(geometry.id)
|
celery_check_for_geometry_conflicts.delay(geometry.id)
|
||||||
return geometry
|
return geometry
|
||||||
|
|
||||||
|
def get_num_geometries_ignored(self):
|
||||||
|
""" Returns the number of geometries which had to be ignored for various reasons
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
"""
|
||||||
|
return self._num_geometries_ignored
|
||||||
|
|
||||||
|
def has_geometry_simplified(self):
|
||||||
|
""" Returns whether the geometry has been simplified or not.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
"""
|
||||||
|
return self._geometry_simplified
|
||||||
|
|
||||||
def __flatten_geom_to_2D(self, geom):
|
def __flatten_geom_to_2D(self, geom):
|
||||||
"""
|
"""
|
||||||
Enforces a given OGRGeometry from higher dimensions into 2D
|
Enforces a given OGRGeometry from higher dimensions into 2D
|
||||||
@@ -223,3 +249,22 @@ class SimpleGeomForm(BaseForm):
|
|||||||
g_wkt = wkt_w.write(geom.geos).decode("utf-8")
|
g_wkt = wkt_w.write(geom.geos).decode("utf-8")
|
||||||
geom = gdal.OGRGeometry(g_wkt)
|
geom = gdal.OGRGeometry(g_wkt)
|
||||||
return geom
|
return geom
|
||||||
|
|
||||||
|
def _set_geojson_properties(self, geojson: dict, title: str = None):
|
||||||
|
""" Toggles the editable property of the geojson for proper handling in map client
|
||||||
|
|
||||||
|
Args:
|
||||||
|
geojson (dict): The GeoJson
|
||||||
|
title (str): An alternative title for the geometry
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
geojson (dict): The altered GeoJson
|
||||||
|
"""
|
||||||
|
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
|
||||||
|
return geojson
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ Created on: 26.10.22
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
import zipfile
|
import zipfile
|
||||||
|
from datetime import datetime
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
|
||||||
from django.core.mail import EmailMessage
|
from django.core.mail import EmailMessage
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.datetime_safe import datetime
|
|
||||||
|
|
||||||
from analysis.utils.excel.excel import TempExcelFile
|
from analysis.utils.excel.excel import TempExcelFile
|
||||||
from analysis.utils.report import TimespanReport
|
from analysis.utils.report import TimespanReport
|
||||||
|
|||||||
88
konova/management/commands/recalculate_parcels.py
Normal file
88
konova/management/commands/recalculate_parcels.py
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
"""
|
||||||
|
Author: Michel Peltriaux
|
||||||
|
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
|
||||||
|
Contact: michel.peltriaux@sgdnord.rlp.de
|
||||||
|
Created on: 04.01.22
|
||||||
|
|
||||||
|
"""
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
from django.contrib.gis.db.models.functions import Area
|
||||||
|
|
||||||
|
from konova.management.commands.setup import BaseKonovaCommand
|
||||||
|
from konova.models import Geometry, ParcelIntersection
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseKonovaCommand):
|
||||||
|
help = "Recalculates parcels for entries with geometry but missing parcel information"
|
||||||
|
|
||||||
|
def add_arguments(self, parser):
|
||||||
|
parser.add_argument(
|
||||||
|
"--force-all",
|
||||||
|
action="store_true",
|
||||||
|
default=False,
|
||||||
|
help="If Attribute set, all entries parcels will be recalculated"
|
||||||
|
)
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
try:
|
||||||
|
self.recalculate_parcels(options)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
self._break_line()
|
||||||
|
exit(-1)
|
||||||
|
|
||||||
|
def recalculate_parcels(self, options: dict):
|
||||||
|
force_all = options.get("force_all", False)
|
||||||
|
|
||||||
|
geometry_objects = Geometry.objects.filter(
|
||||||
|
geom__isempty=False,
|
||||||
|
).exclude(
|
||||||
|
geom=None
|
||||||
|
)
|
||||||
|
|
||||||
|
if not force_all:
|
||||||
|
# Fetch all intersections
|
||||||
|
intersection_objs = ParcelIntersection.objects.filter(
|
||||||
|
geometry__in=geometry_objects
|
||||||
|
)
|
||||||
|
# Just take the geometry ids, which seem to have intersections
|
||||||
|
geom_with_intersection_ids = intersection_objs.values_list(
|
||||||
|
"geometry__id",
|
||||||
|
flat=True
|
||||||
|
)
|
||||||
|
# ... and resolve into Geometry objects again ...
|
||||||
|
intersected_geom_objs = Geometry.objects.filter(
|
||||||
|
id__in=geom_with_intersection_ids
|
||||||
|
)
|
||||||
|
# ... to be able to use the way more efficient difference() function ...
|
||||||
|
geometry_objects_ids = geometry_objects.difference(intersected_geom_objs).values_list("id", flat=True)
|
||||||
|
# ... so we can resolve these into proper Geometry objects again for further annotation usage
|
||||||
|
geometry_objects = Geometry.objects.filter(id__in=geometry_objects_ids)
|
||||||
|
|
||||||
|
self._write_warning("=== Update parcels and districts ===")
|
||||||
|
# Order geometries by size to process smaller once at first
|
||||||
|
geometries = geometry_objects.annotate(
|
||||||
|
area=Area("geom")
|
||||||
|
).order_by(
|
||||||
|
'area'
|
||||||
|
)
|
||||||
|
self._write_warning(f"Process parcels for {geometries.count()} geometry entries now ...")
|
||||||
|
i = 0
|
||||||
|
num_geoms = geometries.count()
|
||||||
|
geoms_with_errors = {}
|
||||||
|
for geometry in geometries:
|
||||||
|
self._write_warning(f"--- {datetime.datetime.now()} Process {geometry.id} now ...")
|
||||||
|
try:
|
||||||
|
geometry.update_parcels()
|
||||||
|
self._write_warning(f"--- Processed {geometry.get_underlying_parcels().count()} underlying parcels")
|
||||||
|
except Exception as e:
|
||||||
|
geoms_with_errors[geometry.id] = str(e)
|
||||||
|
i += 1
|
||||||
|
self._write_warning(f"--- {i}/{num_geoms} processed")
|
||||||
|
|
||||||
|
self._write_success("Updating parcels done!")
|
||||||
|
|
||||||
|
for key, val in geoms_with_errors.items():
|
||||||
|
self._write_error(f" Error on {key}: {val}")
|
||||||
|
self._write_success(f"{num_geoms - len(geoms_with_errors)} geometries successfuly recalculated!")
|
||||||
|
self._break_line()
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
"""
|
|
||||||
Author: Michel Peltriaux
|
|
||||||
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
|
|
||||||
Contact: michel.peltriaux@sgdnord.rlp.de
|
|
||||||
Created on: 19.08.21
|
|
||||||
|
|
||||||
"""
|
|
||||||
from django.core.management import BaseCommand
|
|
||||||
|
|
||||||
from intervention.models import Intervention
|
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
|
||||||
help = "Performs test on collisions using the identifier generation"
|
|
||||||
|
|
||||||
def handle(self, *args, **options):
|
|
||||||
identifiers = {}
|
|
||||||
max_iterations = 100000
|
|
||||||
try:
|
|
||||||
collisions = 0
|
|
||||||
len_ids = len(identifiers)
|
|
||||||
while len_ids < max_iterations:
|
|
||||||
tmp_intervention = Intervention()
|
|
||||||
_id = tmp_intervention.generate_new_identifier()
|
|
||||||
len_ids = len(identifiers)
|
|
||||||
if _id not in identifiers:
|
|
||||||
if len_ids % (max_iterations/5) == 0:
|
|
||||||
print(len_ids)
|
|
||||||
identifiers[_id] = None
|
|
||||||
else:
|
|
||||||
collisions += 1
|
|
||||||
print("+++ Collision after {} identifiers +++".format(len_ids))
|
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
self._break_line()
|
|
||||||
exit(-1)
|
|
||||||
print(
|
|
||||||
"\n{} collisions in {} identifiers; Collision rate {}%".format(
|
|
||||||
collisions,
|
|
||||||
len_ids,
|
|
||||||
(collisions / len_ids)*100,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
def _break_line(self):
|
|
||||||
""" Simply prints a line break
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
|
|
||||||
"""
|
|
||||||
self.stdout.write("\n")
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
"""
|
|
||||||
Author: Michel Peltriaux
|
|
||||||
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
|
|
||||||
Contact: michel.peltriaux@sgdnord.rlp.de
|
|
||||||
Created on: 04.01.22
|
|
||||||
|
|
||||||
"""
|
|
||||||
import datetime
|
|
||||||
|
|
||||||
from django.contrib.gis.db.models.functions import Area
|
|
||||||
|
|
||||||
from konova.management.commands.setup import BaseKonovaCommand
|
|
||||||
from konova.models import Geometry, Parcel, District
|
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseKonovaCommand):
|
|
||||||
help = "Checks the database' sanity and removes unused entries"
|
|
||||||
|
|
||||||
def handle(self, *args, **options):
|
|
||||||
try:
|
|
||||||
self.update_all_parcels()
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
self._break_line()
|
|
||||||
exit(-1)
|
|
||||||
|
|
||||||
def update_all_parcels(self):
|
|
||||||
num_parcels_before = Parcel.objects.count()
|
|
||||||
num_districts_before = District.objects.count()
|
|
||||||
self._write_warning("=== Update parcels and districts ===")
|
|
||||||
# Order geometries by size to process smaller once at first
|
|
||||||
geometries = Geometry.objects.all().exclude(
|
|
||||||
geom=None
|
|
||||||
).annotate(area=Area("geom")).order_by(
|
|
||||||
'area'
|
|
||||||
)
|
|
||||||
self._write_warning(f"Process parcels for {geometries.count()} geometry entries now ...")
|
|
||||||
i = 0
|
|
||||||
num_geoms = geometries.count()
|
|
||||||
for geometry in geometries:
|
|
||||||
self._write_warning(f"--- {datetime.datetime.now()} Process {geometry.id} now ...")
|
|
||||||
geometry.update_parcels()
|
|
||||||
self._write_warning(f"--- Processed {geometry.get_underlying_parcels().count()} underlying parcels")
|
|
||||||
i += 1
|
|
||||||
self._write_warning(f"--- {i}/{num_geoms} processed")
|
|
||||||
|
|
||||||
num_parcels_after = Parcel.objects.count()
|
|
||||||
num_districts_after = District.objects.count()
|
|
||||||
if num_parcels_after != num_parcels_before:
|
|
||||||
self._write_error(f"Parcels have changed: {num_parcels_before} to {num_parcels_after} entries. You should run the sanitize command.")
|
|
||||||
if num_districts_after != num_districts_before:
|
|
||||||
self._write_error(f"Districts have changed: {num_districts_before} to {num_districts_after} entries. You should run the sanitize command.")
|
|
||||||
|
|
||||||
self._write_success("Updating parcels done!")
|
|
||||||
self._break_line()
|
|
||||||
@@ -8,9 +8,11 @@ Created on: 15.11.21
|
|||||||
import json
|
import json
|
||||||
|
|
||||||
from django.contrib.gis.db.models import MultiPolygonField
|
from django.contrib.gis.db.models import MultiPolygonField
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
|
||||||
from django.db import models, transaction
|
from django.db import models, transaction
|
||||||
|
from django.db.models import Q
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
from django.contrib.gis.geos import MultiPolygon
|
||||||
|
|
||||||
from konova.models import BaseResource, UuidModel
|
from konova.models import BaseResource, UuidModel
|
||||||
from konova.sub_settings.lanis_settings import DEFAULT_SRID_RLP
|
from konova.sub_settings.lanis_settings import DEFAULT_SRID_RLP
|
||||||
@@ -108,17 +110,26 @@ class Geometry(BaseResource):
|
|||||||
objs (list): The list of objects
|
objs (list): The list of objects
|
||||||
"""
|
"""
|
||||||
objs = []
|
objs = []
|
||||||
sets = [
|
|
||||||
|
# Some related data sets can be processed rather easily
|
||||||
|
regular_sets = [
|
||||||
self.intervention_set,
|
self.intervention_set,
|
||||||
self.compensation_set,
|
|
||||||
self.ema_set,
|
self.ema_set,
|
||||||
self.ecoaccount_set,
|
self.ecoaccount_set,
|
||||||
]
|
]
|
||||||
for _set in sets:
|
for _set in regular_sets:
|
||||||
set_objs = _set.filter(
|
set_objs = _set.filter(
|
||||||
deleted=None
|
deleted=None
|
||||||
)
|
)
|
||||||
objs += set_objs
|
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
|
return objs
|
||||||
|
|
||||||
def get_data_object(self):
|
def get_data_object(self):
|
||||||
@@ -223,6 +234,17 @@ class Geometry(BaseResource):
|
|||||||
)
|
)
|
||||||
parcel_obj.updated_on = _now
|
parcel_obj.updated_on = _now
|
||||||
parcels_to_update.append(parcel_obj)
|
parcels_to_update.append(parcel_obj)
|
||||||
|
except MultipleObjectsReturned:
|
||||||
|
parcel_obj = Parcel.make_unique(
|
||||||
|
district=district,
|
||||||
|
municipal=municipal,
|
||||||
|
parcel_group=parcel_group,
|
||||||
|
flr=flr_val,
|
||||||
|
flrstck_nnr=flrstck_nnr,
|
||||||
|
flrstck_zhlr=flrstck_zhlr,
|
||||||
|
)
|
||||||
|
parcel_obj.updated_on = _now
|
||||||
|
parcels_to_update.append(parcel_obj)
|
||||||
except ObjectDoesNotExist:
|
except ObjectDoesNotExist:
|
||||||
# If not existing, create object but do not commit, yet
|
# If not existing, create object but do not commit, yet
|
||||||
parcel_obj = Parcel(
|
parcel_obj = Parcel(
|
||||||
@@ -331,6 +353,7 @@ class Geometry(BaseResource):
|
|||||||
{
|
{
|
||||||
"type": "Feature",
|
"type": "Feature",
|
||||||
"geometry": json.loads(p.json),
|
"geometry": json.loads(p.json),
|
||||||
|
"properties": {},
|
||||||
}
|
}
|
||||||
for p in polygons
|
for p in polygons
|
||||||
]
|
]
|
||||||
@@ -366,13 +389,45 @@ class Geometry(BaseResource):
|
|||||||
diff = geom_envelope - self.geom
|
diff = geom_envelope - self.geom
|
||||||
|
|
||||||
if diff.area == 0:
|
if diff.area == 0:
|
||||||
ratio = 1
|
complexity_factor = 1
|
||||||
else:
|
else:
|
||||||
ratio = self.geom.area / diff.area
|
complexity_factor = self.geom.area / diff.area
|
||||||
|
|
||||||
complexity_factor = 1 - ratio
|
|
||||||
return complexity_factor
|
return complexity_factor
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def cast_to_multipolygon(input_geom):
|
||||||
|
""" If input_geom is not a MultiPolygon, cast to MultiPolygon
|
||||||
|
|
||||||
|
Args:
|
||||||
|
input_geom ():
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
output_geom
|
||||||
|
"""
|
||||||
|
output_geom = input_geom
|
||||||
|
if not isinstance(input_geom, MultiPolygon):
|
||||||
|
try:
|
||||||
|
output_geom = MultiPolygon(input_geom, srid=DEFAULT_SRID_RLP)
|
||||||
|
except TypeError as e:
|
||||||
|
raise AssertionError(f"Only (Multi)Polygon allowed! Could not convert {input_geom.geom_type} to MultiPolygon")
|
||||||
|
return output_geom
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def cast_to_rlp_srid(input_geom):
|
||||||
|
""" If input_geom is not of RLP SRID (25832), cast to RLP SRID
|
||||||
|
|
||||||
|
Args:
|
||||||
|
input_geom ():
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
output_geom
|
||||||
|
"""
|
||||||
|
output_geom = input_geom
|
||||||
|
if output_geom.srid != DEFAULT_SRID_RLP:
|
||||||
|
output_geom.transform(DEFAULT_SRID_RLP)
|
||||||
|
return output_geom
|
||||||
|
|
||||||
|
|
||||||
class GeometryConflict(UuidModel):
|
class GeometryConflict(UuidModel):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -677,12 +677,12 @@ class GeoReferencedMixin(models.Model):
|
|||||||
return request
|
return request
|
||||||
|
|
||||||
instance_objs = []
|
instance_objs = []
|
||||||
conflicts = self.geometry.conflicts_geometries.all()
|
conflicts = self.geometry.conflicts_geometries.iterator()
|
||||||
|
|
||||||
for conflict in conflicts:
|
for conflict in conflicts:
|
||||||
instance_objs += conflict.affected_geometry.get_data_objects()
|
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:
|
for conflict in conflicts:
|
||||||
instance_objs += conflict.conflicting_geometry.get_data_objects()
|
instance_objs += conflict.conflicting_geometry.get_data_objects()
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ Contact: michel.peltriaux@sgdnord.rlp.de
|
|||||||
Created on: 16.12.21
|
Created on: 16.12.21
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from django.db import models
|
from django.db import models, transaction
|
||||||
|
|
||||||
from konova.models import UuidModel
|
from konova.models import UuidModel
|
||||||
|
|
||||||
@@ -158,6 +158,46 @@ class Parcel(UuidModel):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.parcel_group} | {self.flr} | {self.flrstck_zhlr} | {self.flrstck_nnr}"
|
return f"{self.parcel_group} | {self.flr} | {self.flrstck_zhlr} | {self.flrstck_nnr}"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def make_unique(cls, **kwargs):
|
||||||
|
""" Checks for duplicates of a Parcel, choose a (now) unique one,
|
||||||
|
repairs relations for ParcelIntersection and removes duplicates.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
**kwargs ():
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
unique_true (Parcel): The new unique 'true one'
|
||||||
|
"""
|
||||||
|
parcel_objs = Parcel.objects.filter(**kwargs)
|
||||||
|
|
||||||
|
if not parcel_objs.exists():
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Get one of the found parcels and use it as new 'true one'
|
||||||
|
unique_parcel = parcel_objs.first()
|
||||||
|
# separate it from the rest
|
||||||
|
parcel_objs = parcel_objs.exclude(id=unique_parcel.id)
|
||||||
|
|
||||||
|
if not parcel_objs.exists():
|
||||||
|
# There are no duplicates - all good, just return
|
||||||
|
return unique_parcel
|
||||||
|
|
||||||
|
# Fetch existing intersections, which still point on the duplicated parcels
|
||||||
|
intersection_objs = ParcelIntersection.objects.filter(
|
||||||
|
parcel__in=parcel_objs
|
||||||
|
)
|
||||||
|
|
||||||
|
# Change each intersection, so they point on the 'true one' parcel from now on
|
||||||
|
for intersection in intersection_objs:
|
||||||
|
intersection.parcel = unique_parcel
|
||||||
|
intersection.save()
|
||||||
|
|
||||||
|
# Remove the duplicated parcels
|
||||||
|
parcel_objs.delete()
|
||||||
|
|
||||||
|
return unique_parcel
|
||||||
|
|
||||||
|
|
||||||
class ParcelIntersection(UuidModel):
|
class ParcelIntersection(UuidModel):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -278,4 +278,18 @@ Similar to bootstraps 'shadow-lg'
|
|||||||
}
|
}
|
||||||
.alert{
|
.alert{
|
||||||
margin-bottom: 0 !important;
|
margin-bottom: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Overwrites netgis.css attributes
|
||||||
|
*/
|
||||||
|
.netgis-gradient-a{
|
||||||
|
/*
|
||||||
|
Overwrites gradient used on default css of netgis map client
|
||||||
|
*/
|
||||||
|
background: var(--rlp-red) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.netgis-menu{
|
||||||
|
z-index: 1 !important;
|
||||||
}
|
}
|
||||||
BIN
konova/static/images/error_imgs/croc_technician_400.png
Normal file
BIN
konova/static/images/error_imgs/croc_technician_400.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.6 MiB |
BIN
konova/static/images/error_imgs/croc_technician_500.png
Normal file
BIN
konova/static/images/error_imgs/croc_technician_500.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 MiB |
@@ -11,4 +11,4 @@ BASE_TITLE = "KSP - Kompensationsverzeichnis Service Portal"
|
|||||||
BASE_FRONTEND_TITLE = "Kompensationsverzeichnis Service Portal"
|
BASE_FRONTEND_TITLE = "Kompensationsverzeichnis Service Portal"
|
||||||
TAB_TITLE_IDENTIFIER = "tab_title"
|
TAB_TITLE_IDENTIFIER = "tab_title"
|
||||||
HELP_LINK = "https://dienste.naturschutz.rlp.de/doku/doku.php?id=ksp2:start"
|
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"
|
||||||
|
|||||||
@@ -66,7 +66,6 @@ INSTALLED_APPS = [
|
|||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
'django.contrib.gis',
|
'django.contrib.gis',
|
||||||
'django.contrib.humanize',
|
'django.contrib.humanize',
|
||||||
'simple_sso.sso_server',
|
|
||||||
'django_tables2',
|
'django_tables2',
|
||||||
'bootstrap_modal_forms',
|
'bootstrap_modal_forms',
|
||||||
'fontawesome_5',
|
'fontawesome_5',
|
||||||
@@ -189,7 +188,6 @@ STATIC_ROOT = os.path.join(BASE_DIR, "static")
|
|||||||
STATICFILES_DIRS = [
|
STATICFILES_DIRS = [
|
||||||
os.path.join(BASE_DIR, 'konova/static'),
|
os.path.join(BASE_DIR, 'konova/static'),
|
||||||
os.path.join(BASE_DIR, 'templates/map/client'), # NETGIS map client files
|
os.path.join(BASE_DIR, 'templates/map/client'), # NETGIS map client files
|
||||||
os.path.join(BASE_DIR, 'templates/map/client/libs'), # NETGIS map client files
|
|
||||||
]
|
]
|
||||||
|
|
||||||
# EMAIL (see https://docs.djangoproject.com/en/dev/topics/email/)
|
# EMAIL (see https://docs.djangoproject.com/en/dev/topics/email/)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ Contact: michel.peltriaux@sgdnord.rlp.de
|
|||||||
Created on: 31.01.22
|
Created on: 31.01.22
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
from konova.sub_settings.django_settings import env
|
||||||
|
|
||||||
# MAPS
|
# MAPS
|
||||||
DEFAULT_LAT = 50.00
|
DEFAULT_LAT = 50.00
|
||||||
@@ -28,3 +29,6 @@ LANIS_ZOOM_LUT = {
|
|||||||
1000: 30,
|
1000: 30,
|
||||||
500: 31,
|
500: 31,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MAP_PROXY_HOST_WHITELIST = env.list("MAP_PROXY_HOST_WHITELIST")
|
||||||
|
i = 0
|
||||||
@@ -16,3 +16,5 @@ OAUTH_CODE_VERIFIER = env("OAUTH_CODE_VERIFIER")
|
|||||||
|
|
||||||
OAUTH_CLIENT_ID = env("OAUTH_CLIENT_ID")
|
OAUTH_CLIENT_ID = env("OAUTH_CLIENT_ID")
|
||||||
OAUTH_CLIENT_SECRET = env("OAUTH_CLIENT_SECRET")
|
OAUTH_CLIENT_SECRET = env("OAUTH_CLIENT_SECRET")
|
||||||
|
|
||||||
|
PROPAGATION_SECRET = env("PROPAGATION_SECRET")
|
||||||
|
|||||||
@@ -124,6 +124,7 @@ class GeometryTestCase(BaseTestCase):
|
|||||||
{
|
{
|
||||||
"type": "Feature",
|
"type": "Feature",
|
||||||
"geometry": json.loads(p.json),
|
"geometry": json.loads(p.json),
|
||||||
|
"properties": {}
|
||||||
}
|
}
|
||||||
for p in polygons
|
for p in polygons
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -469,7 +469,7 @@ class BaseTestCase(TestCase):
|
|||||||
eco_account.save()
|
eco_account.save()
|
||||||
return eco_account
|
return eco_account
|
||||||
|
|
||||||
def assert_equal_geometries(self, geom1: MultiPolygon, geom2: MultiPolygon, tolerance = 0.001):
|
def assert_equal_geometries(self, geom1: MultiPolygon, geom2: MultiPolygon, tolerance=0.001):
|
||||||
""" Assert for geometries to be equal
|
""" Assert for geometries to be equal
|
||||||
|
|
||||||
Transforms the geometries to matching srids before checking
|
Transforms the geometries to matching srids before checking
|
||||||
@@ -491,7 +491,10 @@ class BaseTestCase(TestCase):
|
|||||||
# transformation from one coordinate system into the other, which is valid
|
# transformation from one coordinate system into the other, which is valid
|
||||||
geom1.transform(geom2.srid)
|
geom1.transform(geom2.srid)
|
||||||
geom2.transform(geom1.srid)
|
geom2.transform(geom1.srid)
|
||||||
self.assertTrue(geom1.equals_exact(geom2, tolerance) or geom2.equals_exact(geom1, tolerance))
|
self.assertTrue(
|
||||||
|
geom1.equals_exact(geom2, tolerance=tolerance),
|
||||||
|
msg=f"Difference is {abs(geom1.area - geom2.area)} with {geom1.area} and {geom2.area} in a tolerance of {tolerance}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class BaseViewTestCase(BaseTestCase):
|
class BaseViewTestCase(BaseTestCase):
|
||||||
|
|||||||
@@ -42,5 +42,6 @@ urlpatterns = [
|
|||||||
path('client/proxy/wfs', ClientProxyParcelWFS.as_view(), name="client-proxy-wfs"),
|
path('client/proxy/wfs', ClientProxyParcelWFS.as_view(), name="client-proxy-wfs"),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
handler400 = "konova.views.error.get_400_view"
|
||||||
handler404 = "konova.views.error.get_404_view"
|
handler404 = "konova.views.error.get_404_view"
|
||||||
handler500 = "konova.views.error.get_500_view"
|
handler500 = "konova.views.error.get_500_view"
|
||||||
|
|||||||
@@ -5,6 +5,9 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
|||||||
Created on: 11.12.23
|
Created on: 11.12.23
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
import json
|
||||||
|
from json import JSONDecodeError
|
||||||
|
|
||||||
from django.views.debug import ExceptionReporter
|
from django.views.debug import ExceptionReporter
|
||||||
|
|
||||||
|
|
||||||
@@ -30,7 +33,7 @@ class KonovaExceptionReporter(ExceptionReporter):
|
|||||||
"""
|
"""
|
||||||
whitelist = [
|
whitelist = [
|
||||||
"is_email",
|
"is_email",
|
||||||
"unicdoe_hint",
|
"unicode_hint",
|
||||||
"frames",
|
"frames",
|
||||||
"request",
|
"request",
|
||||||
"user_str",
|
"user_str",
|
||||||
@@ -39,6 +42,8 @@ class KonovaExceptionReporter(ExceptionReporter):
|
|||||||
"raising_view_name",
|
"raising_view_name",
|
||||||
"exception_type",
|
"exception_type",
|
||||||
"exception_value",
|
"exception_value",
|
||||||
|
"filtered_GET_items",
|
||||||
|
"filtered_POST_items",
|
||||||
]
|
]
|
||||||
clean_data = dict()
|
clean_data = dict()
|
||||||
for entry in whitelist:
|
for entry in whitelist:
|
||||||
@@ -56,7 +61,28 @@ class KonovaExceptionReporter(ExceptionReporter):
|
|||||||
"""
|
"""
|
||||||
tb_data = super().get_traceback_data()
|
tb_data = super().get_traceback_data()
|
||||||
|
|
||||||
|
return_data = tb_data
|
||||||
if self.is_email:
|
if self.is_email:
|
||||||
tb_data = self._filter_traceback_data(tb_data)
|
filtered_data = dict()
|
||||||
|
filtered_data.update(self._filter_traceback_data(tb_data))
|
||||||
|
filtered_data.update(self._filter_POST_body(tb_data))
|
||||||
|
return_data = filtered_data
|
||||||
|
return return_data
|
||||||
|
|
||||||
return tb_data
|
def _filter_POST_body(self, tb_data: dict):
|
||||||
|
""" Filters POST body from traceback data
|
||||||
|
|
||||||
|
"""
|
||||||
|
post_data = tb_data.get("request", None)
|
||||||
|
if post_data:
|
||||||
|
post_data = post_data.body
|
||||||
|
try:
|
||||||
|
post_data = json.loads(post_data)
|
||||||
|
except JSONDecodeError:
|
||||||
|
pass
|
||||||
|
post_data = {
|
||||||
|
"filtered_POST_items": [
|
||||||
|
("body", post_data),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
return post_data
|
||||||
@@ -42,23 +42,24 @@ def generate_random_string(length: int, use_numbers: bool = False, use_letters_l
|
|||||||
ret_val = "".join(random.choice(elements) for i in range(length))
|
ret_val = "".join(random.choice(elements) for i in range(length))
|
||||||
return ret_val
|
return ret_val
|
||||||
|
|
||||||
|
class IdentifierGenerator:
|
||||||
|
_MODEL = None
|
||||||
|
|
||||||
def generate_qr_code(content: str, size: int = 20) -> str:
|
def __init__(self, model):
|
||||||
""" Generates a qr code from given content
|
from konova.models import BaseObject
|
||||||
|
if not issubclass(model, BaseObject):
|
||||||
|
raise AssertionError("Model must be a subclass of BaseObject!")
|
||||||
|
|
||||||
Args:
|
self._MODEL = model
|
||||||
content (str): The content for the qr code
|
|
||||||
size (int): The image size
|
|
||||||
|
|
||||||
Returns:
|
def generate_id(self) -> str:
|
||||||
qrcode_svg (str): The qr code as svg
|
""" Generates a unique identifier
|
||||||
"""
|
|
||||||
qrcode_factory = qrcode.image.svg.SvgImage
|
Returns:
|
||||||
qrcode_img = qrcode.make(
|
|
||||||
content,
|
"""
|
||||||
image_factory=qrcode_factory,
|
unpersisted_object = self._MODEL()
|
||||||
box_size=size
|
identifier = unpersisted_object.generate_new_identifier()
|
||||||
)
|
while self._MODEL.objects.filter(identifier=identifier).exists():
|
||||||
stream = BytesIO()
|
identifier = unpersisted_object.generate_new_identifier()
|
||||||
qrcode_img.save(stream)
|
return identifier
|
||||||
return stream.getvalue().decode()
|
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ EDITED_GENERAL_DATA = _("Edited general data")
|
|||||||
# Geometry
|
# Geometry
|
||||||
GEOMETRY_CONFLICT_WITH_TEMPLATE = _("Geometry conflict detected with {}")
|
GEOMETRY_CONFLICT_WITH_TEMPLATE = _("Geometry conflict detected with {}")
|
||||||
GEOMETRY_SIMPLIFIED = _("The geometry contained more than {} vertices. It had to be simplified to match the allowed limit of {} vertices.").format(GEOM_MAX_VERTICES, GEOM_MAX_VERTICES)
|
GEOMETRY_SIMPLIFIED = _("The geometry contained more than {} vertices. It had to be simplified to match the allowed limit of {} vertices.").format(GEOM_MAX_VERTICES, GEOM_MAX_VERTICES)
|
||||||
|
GEOMETRIES_IGNORED_TEMPLATE = _("The geometry contained {} parts which have been detected as invalid (e.g. too small to be valid). These parts have been removed. Please check the stored geometry.")
|
||||||
|
|
||||||
# INTERVENTION
|
# INTERVENTION
|
||||||
INTERVENTION_HAS_REVOCATIONS_TEMPLATE = _("This intervention has {} revocations")
|
INTERVENTION_HAS_REVOCATIONS_TEMPLATE = _("This intervention has {} revocations")
|
||||||
@@ -91,3 +92,6 @@ INTERVENTION_HAS_REVOCATIONS_TEMPLATE = _("This intervention has {} revocations"
|
|||||||
DATA_CHECKED_ON_TEMPLATE = _("Checked on {} by {}")
|
DATA_CHECKED_ON_TEMPLATE = _("Checked on {} by {}")
|
||||||
DATA_CHECKED_PREVIOUSLY_TEMPLATE = _("Data has changed since last check on {} by {}")
|
DATA_CHECKED_PREVIOUSLY_TEMPLATE = _("Data has changed since last check on {} by {}")
|
||||||
DATA_IS_UNCHECKED = _("Current data not checked yet")
|
DATA_IS_UNCHECKED = _("Current data not checked yet")
|
||||||
|
|
||||||
|
# API TOKEN SETTINGS
|
||||||
|
NEW_API_TOKEN_GENERATED = _("New token generated. Administrators need to validate.")
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
"""
|
|
||||||
Author: Michel Peltriaux
|
|
||||||
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
|
|
||||||
Contact: michel.peltriaux@sgdnord.rlp.de
|
|
||||||
Created on: 17.08.21
|
|
||||||
|
|
||||||
"""
|
|
||||||
from collections import Iterable
|
|
||||||
|
|
||||||
import requests
|
|
||||||
from user.models import User
|
|
||||||
from django.utils.translation import gettext_lazy as _
|
|
||||||
|
|
||||||
from konova.settings import SSO_SERVER_BASE, SSO_PUBLIC_KEY, PROXIES
|
|
||||||
from konova.sub_settings.context_settings import BASE_TITLE_SHORT
|
|
||||||
|
|
||||||
|
|
||||||
class Messenger:
|
|
||||||
""" Used to send messages to the SSO server.
|
|
||||||
|
|
||||||
Messages can be seen by the user the next time they login on their SSO dashboard.
|
|
||||||
Documentation for SSO Server-Client communication can be found here:
|
|
||||||
https://git.naturschutz.rlp.de/SGD-Nord/arnova/wiki/Messages
|
|
||||||
|
|
||||||
"""
|
|
||||||
server_url = "{}communication/message/".format(SSO_SERVER_BASE)
|
|
||||||
|
|
||||||
def __init__(self, users: Iterable, subject: str = None, body: str = None, type: str = None):
|
|
||||||
self.users = users
|
|
||||||
self.msg_subject = subject
|
|
||||||
self.msg_body = body
|
|
||||||
self.msg_type = type
|
|
||||||
|
|
||||||
def send(self):
|
|
||||||
""" Sends a message
|
|
||||||
|
|
||||||
"""
|
|
||||||
if self.msg_body is None or len(self.msg_body) == 0:
|
|
||||||
raise AttributeError("No message body set")
|
|
||||||
|
|
||||||
headers = {
|
|
||||||
"x-services-public-key": SSO_PUBLIC_KEY
|
|
||||||
}
|
|
||||||
for user in self.users:
|
|
||||||
data = {
|
|
||||||
"type": self.msg_type,
|
|
||||||
"sender": BASE_TITLE_SHORT,
|
|
||||||
"receiver": user.username,
|
|
||||||
"subject": self.msg_subject,
|
|
||||||
"body": self.msg_body,
|
|
||||||
}
|
|
||||||
requests.post(
|
|
||||||
self.server_url,
|
|
||||||
data=data,
|
|
||||||
headers=headers,
|
|
||||||
proxies=PROXIES
|
|
||||||
)
|
|
||||||
|
|
||||||
def send_object_checked(self, obj_identifier: str, performing_user: User, detail_view_url: str = ""):
|
|
||||||
""" Wraps sending of a message related to the checking of an object, like an intervention
|
|
||||||
|
|
||||||
Args:
|
|
||||||
obj_identifier (str): The object's identifier (e.g. 'EIV-123'
|
|
||||||
performing_user (User): The user who performed the checking
|
|
||||||
detail_view_url (str): If a direct link to the object shall be added to the message, it can be provided here
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
|
|
||||||
"""
|
|
||||||
self.msg_subject = _("{} checked").format(obj_identifier)
|
|
||||||
if len(detail_view_url) > 0:
|
|
||||||
detail_view_url = _('<a href="{}">Check it out</a>').format(detail_view_url)
|
|
||||||
self.msg_body = _("{} has been checked successfully by user {}! {}").format(
|
|
||||||
obj_identifier,
|
|
||||||
performing_user.username,
|
|
||||||
detail_view_url
|
|
||||||
)
|
|
||||||
self.send()
|
|
||||||
47
konova/utils/qrcode.py
Normal file
47
konova/utils/qrcode.py
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
"""
|
||||||
|
Author: Michel Peltriaux
|
||||||
|
Created on: 14.12.25
|
||||||
|
|
||||||
|
"""
|
||||||
|
from io import BytesIO
|
||||||
|
|
||||||
|
import qrcode
|
||||||
|
import qrcode.image.svg as svg
|
||||||
|
|
||||||
|
|
||||||
|
class QrCode:
|
||||||
|
""" A wrapping class for creating a qr code with content
|
||||||
|
|
||||||
|
"""
|
||||||
|
_content = None
|
||||||
|
_img = None
|
||||||
|
|
||||||
|
def __init__(self, content: str, size: int):
|
||||||
|
self._content = content
|
||||||
|
self._img = self._generate_qr_code(content, size)
|
||||||
|
|
||||||
|
def _generate_qr_code(self, content: str, size: int = 20) -> str:
|
||||||
|
""" Generates a qr code from given content
|
||||||
|
|
||||||
|
Args:
|
||||||
|
content (str): The content for the qr code
|
||||||
|
size (int): The image size
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
qrcode_svg (str): The qr code as svg
|
||||||
|
"""
|
||||||
|
img_factory = svg.SvgImage
|
||||||
|
qrcode_img = qrcode.make(
|
||||||
|
content,
|
||||||
|
image_factory=img_factory,
|
||||||
|
box_size=size
|
||||||
|
)
|
||||||
|
stream = BytesIO()
|
||||||
|
qrcode_img.save(stream)
|
||||||
|
return stream.getvalue().decode()
|
||||||
|
|
||||||
|
def get_img(self):
|
||||||
|
return self._img
|
||||||
|
|
||||||
|
def get_content(self):
|
||||||
|
return self._content
|
||||||
@@ -11,6 +11,7 @@ from json import JSONDecodeError
|
|||||||
import requests
|
import requests
|
||||||
|
|
||||||
from konova.sub_settings import schneider_settings
|
from konova.sub_settings import schneider_settings
|
||||||
|
from konova.sub_settings.lanis_settings import DEFAULT_SRID
|
||||||
from konova.sub_settings.proxy_settings import PROXIES
|
from konova.sub_settings.proxy_settings import PROXIES
|
||||||
|
|
||||||
|
|
||||||
@@ -34,6 +35,7 @@ class ParcelFetcher:
|
|||||||
if geom.area < buffer_threshold:
|
if geom.area < buffer_threshold:
|
||||||
# Fallback for malicious geometries which are way too small and would disappear on negative buffering
|
# Fallback for malicious geometries which are way too small and would disappear on negative buffering
|
||||||
geom = geometry.geom
|
geom = geometry.geom
|
||||||
|
geom.transform(DEFAULT_SRID)
|
||||||
self.geojson = geom.ewkt
|
self.geojson = geom.ewkt
|
||||||
self.results = []
|
self.results = []
|
||||||
|
|
||||||
@@ -55,11 +57,11 @@ class ParcelFetcher:
|
|||||||
content = json.loads(response.content.decode("utf-8"))
|
content = json.loads(response.content.decode("utf-8"))
|
||||||
except JSONDecodeError:
|
except JSONDecodeError:
|
||||||
content = {}
|
content = {}
|
||||||
next = content.get("next", None)
|
_next = content.get("next", None)
|
||||||
fetched_parcels = content.get("results", [])
|
fetched_parcels = content.get("results", [])
|
||||||
self.results += fetched_parcels
|
self.results += fetched_parcels
|
||||||
|
|
||||||
if next:
|
if _next:
|
||||||
self.get_parcels(next)
|
self.get_parcels(_next)
|
||||||
|
|
||||||
return self.results
|
return self.results
|
||||||
25
konova/views/detail.py
Normal file
25
konova/views/detail.py
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
"""
|
||||||
|
Author: Michel Peltriaux
|
||||||
|
Created on: 14.12.25
|
||||||
|
|
||||||
|
"""
|
||||||
|
from abc import ABC
|
||||||
|
|
||||||
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
|
from django.http import HttpRequest, HttpResponse
|
||||||
|
from django.utils.decorators import method_decorator
|
||||||
|
from django.views import View
|
||||||
|
|
||||||
|
from konova.decorators import uuid_required, any_group_check
|
||||||
|
|
||||||
|
|
||||||
|
class AbstractDetailView(LoginRequiredMixin, View, ABC):
|
||||||
|
_TEMPLATE = None
|
||||||
|
|
||||||
|
@method_decorator(uuid_required)
|
||||||
|
def dispatch(self, request, *args, **kwargs):
|
||||||
|
return super().dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
|
@method_decorator(any_group_check)
|
||||||
|
def get(self, request: HttpRequest, id: str, *args, **kwargs) -> HttpResponse:
|
||||||
|
raise NotImplementedError()
|
||||||
@@ -25,6 +25,20 @@ def get_404_view(request: HttpRequest, exception=None):
|
|||||||
return render(request, "404.html", context, status=404)
|
return render(request, "404.html", context, status=404)
|
||||||
|
|
||||||
|
|
||||||
|
def get_400_view(request: HttpRequest, exception=None):
|
||||||
|
""" Returns a 400 handling view
|
||||||
|
|
||||||
|
Args:
|
||||||
|
request ():
|
||||||
|
exception ():
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
"""
|
||||||
|
context = BaseContext.context
|
||||||
|
return render(request, "400.html", context, status=400)
|
||||||
|
|
||||||
|
|
||||||
def get_500_view(request: HttpRequest):
|
def get_500_view(request: HttpRequest):
|
||||||
""" Returns a 404 handling view
|
""" Returns a 404 handling view
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
|||||||
Created on: 19.08.22
|
Created on: 19.08.22
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
|
||||||
from django.contrib.gis.geos import MultiPolygon
|
from django.contrib.gis.geos import MultiPolygon
|
||||||
from django.http import HttpResponse, HttpRequest
|
from django.http import HttpResponse, HttpRequest
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ class HomeView(LoginRequiredMixin, View):
|
|||||||
# Repeat for other objects
|
# Repeat for other objects
|
||||||
comps = Compensation.objects.filter(
|
comps = Compensation.objects.filter(
|
||||||
deleted=None,
|
deleted=None,
|
||||||
|
intervention__deleted=None,
|
||||||
)
|
)
|
||||||
user_comps = comps.filter(
|
user_comps = comps.filter(
|
||||||
Q(intervention__users__in=[user]) | Q(intervention__teams__in=user_teams)
|
Q(intervention__users__in=[user]) | Q(intervention__teams__in=user_teams)
|
||||||
|
|||||||
28
konova/views/identifier.py
Normal file
28
konova/views/identifier.py
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
"""
|
||||||
|
Author: Michel Peltriaux
|
||||||
|
Created on: 14.12.25
|
||||||
|
|
||||||
|
"""
|
||||||
|
from abc import ABC
|
||||||
|
|
||||||
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
|
from django.http import HttpRequest, JsonResponse
|
||||||
|
from django.utils.decorators import method_decorator
|
||||||
|
from django.views import View
|
||||||
|
|
||||||
|
from konova.decorators import default_group_required
|
||||||
|
from konova.utils.generators import IdentifierGenerator
|
||||||
|
|
||||||
|
|
||||||
|
class AbstractIdentifierGeneratorView(LoginRequiredMixin, View, ABC):
|
||||||
|
_MODEL = None
|
||||||
|
|
||||||
|
@method_decorator(default_group_required)
|
||||||
|
def get(self, request: HttpRequest, *args, **kwargs):
|
||||||
|
generator = IdentifierGenerator(model=self._MODEL)
|
||||||
|
identifier = generator.generate_id()
|
||||||
|
return JsonResponse(
|
||||||
|
data={
|
||||||
|
"gen_data": identifier
|
||||||
|
}
|
||||||
|
)
|
||||||
21
konova/views/index.py
Normal file
21
konova/views/index.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
"""
|
||||||
|
Author: Michel Peltriaux
|
||||||
|
Created on: 14.12.25
|
||||||
|
|
||||||
|
"""
|
||||||
|
from abc import ABC
|
||||||
|
|
||||||
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
|
from django.http import HttpRequest, HttpResponse
|
||||||
|
from django.utils.decorators import method_decorator
|
||||||
|
from django.views import View
|
||||||
|
|
||||||
|
from konova.decorators import any_group_check
|
||||||
|
|
||||||
|
|
||||||
|
class AbstractIndexView(LoginRequiredMixin, View, ABC):
|
||||||
|
_TEMPLATE = "generic_index.html"
|
||||||
|
|
||||||
|
@method_decorator(any_group_check)
|
||||||
|
def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
|
||||||
|
raise NotImplementedError()
|
||||||
@@ -24,5 +24,13 @@ class LogoutView(View):
|
|||||||
Returns:
|
Returns:
|
||||||
A redirect
|
A redirect
|
||||||
"""
|
"""
|
||||||
|
user = request.user
|
||||||
|
try:
|
||||||
|
oauth_token = user.oauth_token
|
||||||
|
if oauth_token:
|
||||||
|
oauth_token.revoke()
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
logout(request)
|
logout(request)
|
||||||
return redirect(SSO_SERVER_BASE)
|
return redirect(SSO_SERVER_BASE)
|
||||||
|
|||||||
@@ -9,15 +9,16 @@ import json
|
|||||||
from json import JSONDecodeError
|
from json import JSONDecodeError
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
import urllib3.util
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.http import JsonResponse, HttpRequest
|
from django.http import JsonResponse, HttpRequest, HttpResponse
|
||||||
from django.utils.decorators import method_decorator
|
from django.utils.decorators import method_decorator
|
||||||
from django.utils.http import urlencode
|
from django.utils.http import urlencode
|
||||||
from django.views import View
|
from django.views import View
|
||||||
from django.utils.translation import gettext_lazy as _
|
|
||||||
|
|
||||||
from requests.auth import HTTPDigestAuth
|
from requests.auth import HTTPDigestAuth
|
||||||
|
|
||||||
|
from konova.sub_settings.lanis_settings import MAP_PROXY_HOST_WHITELIST
|
||||||
from konova.sub_settings.proxy_settings import PROXIES, GEOPORTAL_RLP_USER, GEOPORTAL_RLP_PASSWORD
|
from konova.sub_settings.proxy_settings import PROXIES, GEOPORTAL_RLP_USER, GEOPORTAL_RLP_PASSWORD
|
||||||
|
|
||||||
|
|
||||||
@@ -32,6 +33,13 @@ class BaseClientProxyView(View):
|
|||||||
def dispatch(self, request, *args, **kwargs):
|
def dispatch(self, request, *args, **kwargs):
|
||||||
return super().dispatch(request, *args, **kwargs)
|
return super().dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
|
def _check_with_whitelist(self, url):
|
||||||
|
parsed_url = urllib3.util.parse_url(url)
|
||||||
|
parsed_url_host = parsed_url.host
|
||||||
|
whitelist = set(MAP_PROXY_HOST_WHITELIST)
|
||||||
|
is_allowed = parsed_url_host in whitelist
|
||||||
|
return is_allowed
|
||||||
|
|
||||||
def perform_url_call(self, url, headers={}, auth=None):
|
def perform_url_call(self, url, headers={}, auth=None):
|
||||||
""" Generic proxied call
|
""" Generic proxied call
|
||||||
|
|
||||||
@@ -51,7 +59,10 @@ class BaseClientProxyView(View):
|
|||||||
)
|
)
|
||||||
content = response.content
|
content = response.content
|
||||||
if isinstance(content, bytes):
|
if isinstance(content, bytes):
|
||||||
content = content.decode("utf-8")
|
try:
|
||||||
|
content = content.decode("utf-8")
|
||||||
|
except UnicodeDecodeError:
|
||||||
|
content = f"Can not decode content of {url}"
|
||||||
return content, response.status_code
|
return content, response.status_code
|
||||||
|
|
||||||
|
|
||||||
@@ -59,25 +70,13 @@ class ClientProxyParcelSearch(BaseClientProxyView):
|
|||||||
|
|
||||||
def get(self, request: HttpRequest):
|
def get(self, request: HttpRequest):
|
||||||
url = request.META.get("QUERY_STRING")
|
url = request.META.get("QUERY_STRING")
|
||||||
content, response_code = self.perform_url_call(url)
|
|
||||||
try:
|
|
||||||
body = json.loads(content)
|
|
||||||
except JSONDecodeError as e:
|
|
||||||
body = {
|
|
||||||
"totalResultsCount": -1,
|
|
||||||
"geonames": [
|
|
||||||
{
|
|
||||||
"title": _("The external service is currently unavailable.<br>Please try again in a few moments...")
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
if response_code != 200:
|
is_url_allowed = self._check_with_whitelist(url)
|
||||||
return JsonResponse({
|
if not is_url_allowed:
|
||||||
"status_code": response_code,
|
raise PermissionError(f"Proxied url '{url}' is not allowed!")
|
||||||
"content": body,
|
|
||||||
})
|
content, response_code = self.perform_url_call(url)
|
||||||
return JsonResponse(body)
|
return HttpResponse(content)
|
||||||
|
|
||||||
|
|
||||||
class ClientProxyParcelWFS(BaseClientProxyView):
|
class ClientProxyParcelWFS(BaseClientProxyView):
|
||||||
|
|||||||
@@ -115,10 +115,10 @@ class OAuthCallbackView(View):
|
|||||||
if status_code_invalid:
|
if status_code_invalid:
|
||||||
raise RuntimeError(f"OAuth access token could not be fetched: {access_code_response.text}")
|
raise RuntimeError(f"OAuth access token could not be fetched: {access_code_response.text}")
|
||||||
|
|
||||||
oauth_access_token = OAuthToken.from_access_token_response(access_code_response_body, received_on)
|
oauth_token = OAuthToken.from_access_token_response(access_code_response_body, received_on)
|
||||||
oauth_access_token.save()
|
oauth_token.save()
|
||||||
user = oauth_access_token.update_and_get_user()
|
user = oauth_token.update_and_get_user()
|
||||||
user.oauth_replace_token(oauth_access_token)
|
user.oauth_replace_token(oauth_token)
|
||||||
|
|
||||||
login(request, user)
|
login(request, user)
|
||||||
return redirect("home")
|
return redirect("home")
|
||||||
|
|||||||
64
konova/views/remove.py
Normal file
64
konova/views/remove.py
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
"""
|
||||||
|
Author: Michel Peltriaux
|
||||||
|
Created on: 14.12.25
|
||||||
|
|
||||||
|
"""
|
||||||
|
from abc import ABC
|
||||||
|
|
||||||
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
|
from django.http import HttpRequest, HttpResponse
|
||||||
|
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 _
|
||||||
|
|
||||||
|
from konova.decorators import default_group_required
|
||||||
|
from konova.forms.modals import RemoveModalForm
|
||||||
|
|
||||||
|
|
||||||
|
class AbstractRemoveView(LoginRequiredMixin, View, ABC):
|
||||||
|
_MODEL = None
|
||||||
|
_REDIRECT_URL = None
|
||||||
|
_FORM = RemoveModalForm
|
||||||
|
|
||||||
|
def dispatch(self, request, *args, **kwargs):
|
||||||
|
return super().dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
|
@method_decorator(default_group_required)
|
||||||
|
def __process_request(self, request: HttpRequest, id: str, *args, **kwargs) -> HttpResponse:
|
||||||
|
obj = self._MODEL.objects.get(id=id)
|
||||||
|
identifier = obj.identifier
|
||||||
|
form = self._FORM(request.POST or None, instance=obj, request=request)
|
||||||
|
return form.process_request(
|
||||||
|
request,
|
||||||
|
_("{} removed").format(identifier),
|
||||||
|
redirect_url=reverse(self._REDIRECT_URL)
|
||||||
|
)
|
||||||
|
|
||||||
|
def get(self, request: HttpRequest, id: str, *args, **kwargs) -> HttpResponse:
|
||||||
|
""" GET endpoint for removing via modal form
|
||||||
|
|
||||||
|
Due to the legacy logic of the form (which processes get and post requests directly), we simply need to pipe
|
||||||
|
the request from GET and POST endpoints directly into the same method.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
request (HttpRequest): The incoming request
|
||||||
|
id (str): The uuid id as string
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
"""
|
||||||
|
return self.__process_request(request, id, *args, **kwargs)
|
||||||
|
|
||||||
|
def post(self, request: HttpRequest, id: str, *args, **kwargs) -> HttpResponse:
|
||||||
|
""" POST endpoint for removing via modal form
|
||||||
|
|
||||||
|
Due to the legacy logic of the form (which processes get and post requests directly), we simply need to pipe
|
||||||
|
the request from GET and POST endpoints directly into the same method.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
request (HttpRequest): The incoming request
|
||||||
|
id (str): The uuid id as string
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
"""
|
||||||
|
return self.__process_request(request, id, *args, **kwargs)
|
||||||
24
konova/views/report.py
Normal file
24
konova/views/report.py
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
"""
|
||||||
|
Author: Michel Peltriaux
|
||||||
|
Created on: 14.12.25
|
||||||
|
|
||||||
|
"""
|
||||||
|
from abc import abstractmethod, ABC
|
||||||
|
|
||||||
|
from django.http import HttpRequest, HttpResponse
|
||||||
|
from django.utils.decorators import method_decorator
|
||||||
|
from django.views import View
|
||||||
|
|
||||||
|
from konova.decorators import uuid_required
|
||||||
|
|
||||||
|
|
||||||
|
class AbstractPublicReportView(View, ABC):
|
||||||
|
_TEMPLATE = None
|
||||||
|
|
||||||
|
@method_decorator(uuid_required)
|
||||||
|
def dispatch(self, request, *args, **kwargs):
|
||||||
|
return super().dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def get(self, request: HttpRequest, id: str, *args, **kwargs) -> HttpResponse:
|
||||||
|
raise NotImplementedError()
|
||||||
Binary file not shown.
@@ -38,13 +38,14 @@
|
|||||||
#: konova/forms/modals/remove_form.py:23
|
#: konova/forms/modals/remove_form.py:23
|
||||||
#: konova/forms/modals/resubmission_form.py:22
|
#: konova/forms/modals/resubmission_form.py:22
|
||||||
#: konova/forms/modals/resubmission_form.py:38 konova/forms/remove_form.py:25
|
#: konova/forms/modals/resubmission_form.py:38 konova/forms/remove_form.py:25
|
||||||
#: konova/tests/unit/test_forms.py:59 user/forms/user.py:39
|
#: konova/tests/unit/test_forms.py:59 user/forms/modals/api_token.py:17
|
||||||
|
#: user/forms/user.py:39
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2024-08-19 10:32+0200\n"
|
"POT-Creation-Date: 2025-12-14 17:23+0100\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
@@ -373,7 +374,6 @@ msgid "Identifier"
|
|||||||
msgstr "Kennung"
|
msgstr "Kennung"
|
||||||
|
|
||||||
#: compensation/forms/compensation.py:33 intervention/forms/intervention.py:33
|
#: compensation/forms/compensation.py:33 intervention/forms/intervention.py:33
|
||||||
#: user/forms/user.py:77
|
|
||||||
msgid "Generated automatically - not editable"
|
msgid "Generated automatically - not editable"
|
||||||
msgstr "Automatisch generiert - nicht bearbeitbar"
|
msgstr "Automatisch generiert - nicht bearbeitbar"
|
||||||
|
|
||||||
@@ -448,7 +448,7 @@ msgid "Select the intervention for which this compensation compensates"
|
|||||||
msgstr "Wählen Sie den Eingriff, für den diese Kompensation bestimmt ist"
|
msgstr "Wählen Sie den Eingriff, für den diese Kompensation bestimmt ist"
|
||||||
|
|
||||||
#: compensation/forms/compensation.py:114
|
#: compensation/forms/compensation.py:114
|
||||||
#: compensation/views/compensation/compensation.py:120
|
#: compensation/views/compensation/compensation.py:121
|
||||||
msgid "New compensation"
|
msgid "New compensation"
|
||||||
msgstr "Neue Kompensation"
|
msgstr "Neue Kompensation"
|
||||||
|
|
||||||
@@ -456,38 +456,38 @@ msgstr "Neue Kompensation"
|
|||||||
msgid "Edit compensation"
|
msgid "Edit compensation"
|
||||||
msgstr "Bearbeite Kompensation"
|
msgstr "Bearbeite Kompensation"
|
||||||
|
|
||||||
#: compensation/forms/eco_account.py:31 compensation/utils/quality.py:97
|
#: compensation/forms/eco_account.py:32 compensation/utils/quality.py:97
|
||||||
msgid "Available Surface"
|
msgid "Available Surface"
|
||||||
msgstr "Verfügbare Fläche"
|
msgstr "Verfügbare Fläche"
|
||||||
|
|
||||||
#: compensation/forms/eco_account.py:34
|
#: compensation/forms/eco_account.py:35
|
||||||
msgid "The amount that can be used for deductions"
|
msgid "The amount that can be used for deductions"
|
||||||
msgstr "Die für Abbuchungen zur Verfügung stehende Menge"
|
msgstr "Die für Abbuchungen zur Verfügung stehende Menge"
|
||||||
|
|
||||||
#: compensation/forms/eco_account.py:43
|
#: compensation/forms/eco_account.py:44
|
||||||
#: compensation/templates/compensation/detail/eco_account/view.html:67
|
#: compensation/templates/compensation/detail/eco_account/view.html:67
|
||||||
#: compensation/utils/quality.py:84
|
#: compensation/utils/quality.py:84
|
||||||
msgid "Agreement date"
|
msgid "Agreement date"
|
||||||
msgstr "Vereinbarungsdatum"
|
msgstr "Vereinbarungsdatum"
|
||||||
|
|
||||||
#: compensation/forms/eco_account.py:45
|
#: compensation/forms/eco_account.py:46
|
||||||
msgid "When did the parties agree on this?"
|
msgid "When did the parties agree on this?"
|
||||||
msgstr "Wann wurde dieses Ökokonto offiziell vereinbart?"
|
msgstr "Wann wurde dieses Ökokonto offiziell vereinbart?"
|
||||||
|
|
||||||
#: compensation/forms/eco_account.py:72
|
#: compensation/forms/eco_account.py:73
|
||||||
#: compensation/views/eco_account/eco_account.py:101
|
#: compensation/views/eco_account/eco_account.py:105
|
||||||
msgid "New Eco-Account"
|
msgid "New Eco-Account"
|
||||||
msgstr "Neues Ökokonto"
|
msgstr "Neues Ökokonto"
|
||||||
|
|
||||||
#: compensation/forms/eco_account.py:81
|
#: compensation/forms/eco_account.py:82
|
||||||
msgid "Eco-Account XY; Location ABC"
|
msgid "Eco-Account XY; Location ABC"
|
||||||
msgstr "Ökokonto XY; Flur ABC"
|
msgstr "Ökokonto XY; Flur ABC"
|
||||||
|
|
||||||
#: compensation/forms/eco_account.py:147
|
#: compensation/forms/eco_account.py:148
|
||||||
msgid "Edit Eco-Account"
|
msgid "Edit Eco-Account"
|
||||||
msgstr "Ökokonto bearbeiten"
|
msgstr "Ökokonto bearbeiten"
|
||||||
|
|
||||||
#: compensation/forms/eco_account.py:183
|
#: compensation/forms/eco_account.py:184
|
||||||
msgid ""
|
msgid ""
|
||||||
"{}m² have been deducted from this eco account so far. The given value of {} "
|
"{}m² have been deducted from this eco account so far. The given value of {} "
|
||||||
"would be too low."
|
"would be too low."
|
||||||
@@ -495,12 +495,16 @@ msgstr ""
|
|||||||
"{}n² wurden bereits von diesem Ökokonto abgebucht. Der eingegebene Wert von "
|
"{}n² wurden bereits von diesem Ökokonto abgebucht. Der eingegebene Wert von "
|
||||||
"{} wäre daher zu klein."
|
"{} wäre daher zu klein."
|
||||||
|
|
||||||
#: compensation/forms/eco_account.py:247
|
#: compensation/forms/eco_account.py:248
|
||||||
msgid "The account can not be removed, since there are still deductions."
|
msgid "The account can not be removed, since there are still deductions."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Das Ökokonto kann nicht entfernt werden, da hierzu noch Abbuchungen "
|
"Das Ökokonto kann nicht entfernt werden, da hierzu noch Abbuchungen "
|
||||||
"vorliegen."
|
"vorliegen."
|
||||||
|
|
||||||
|
#: compensation/forms/eco_account.py:257
|
||||||
|
msgid "Please contact the responsible conservation office to find a solution!"
|
||||||
|
msgstr "Kontaktieren Sie die zuständige Naturschutzbehörde um eine Lösung zu finden!"
|
||||||
|
|
||||||
#: compensation/forms/mixins.py:37
|
#: compensation/forms/mixins.py:37
|
||||||
#: compensation/templates/compensation/detail/eco_account/view.html:63
|
#: compensation/templates/compensation/detail/eco_account/view.html:63
|
||||||
#: compensation/templates/compensation/report/eco_account/report.html:20
|
#: compensation/templates/compensation/report/eco_account/report.html:20
|
||||||
@@ -1288,44 +1292,40 @@ msgstr ""
|
|||||||
msgid "Responsible data"
|
msgid "Responsible data"
|
||||||
msgstr "Daten zu den verantwortlichen Stellen"
|
msgstr "Daten zu den verantwortlichen Stellen"
|
||||||
|
|
||||||
#: compensation/views/compensation/compensation.py:58
|
#: compensation/views/compensation/compensation.py:52
|
||||||
msgid "Compensations - Overview"
|
msgid "Compensations - Overview"
|
||||||
msgstr "Kompensationen - Übersicht"
|
msgstr "Kompensationen - Übersicht"
|
||||||
|
|
||||||
#: compensation/views/compensation/compensation.py:181
|
#: compensation/views/compensation/compensation.py:167
|
||||||
#: konova/utils/message_templates.py:40
|
#: konova/utils/message_templates.py:40
|
||||||
msgid "Compensation {} edited"
|
msgid "Compensation {} edited"
|
||||||
msgstr "Kompensation {} bearbeitet"
|
msgstr "Kompensation {} bearbeitet"
|
||||||
|
|
||||||
#: compensation/views/compensation/compensation.py:196
|
#: compensation/views/compensation/compensation.py:190
|
||||||
#: compensation/views/eco_account/eco_account.py:173 ema/views/ema.py:232
|
#: compensation/views/eco_account/eco_account.py:168 ema/views/ema.py:173
|
||||||
#: intervention/views/intervention.py:253
|
#: intervention/views/intervention.py:175
|
||||||
msgid "Edit {}"
|
msgid "Edit {}"
|
||||||
msgstr "Bearbeite {}"
|
msgstr "Bearbeite {}"
|
||||||
|
|
||||||
#: compensation/views/compensation/report.py:34
|
#: compensation/views/compensation/report.py:35
|
||||||
#: compensation/views/eco_account/report.py:34 ema/views/report.py:34
|
#: compensation/views/eco_account/report.py:35 ema/views/report.py:35
|
||||||
#: intervention/views/report.py:35
|
#: intervention/views/report.py:36
|
||||||
msgid "Report {}"
|
msgid "Report {}"
|
||||||
msgstr "Bericht {}"
|
msgstr "Bericht {}"
|
||||||
|
|
||||||
#: compensation/views/eco_account/eco_account.py:53
|
#: compensation/views/eco_account/eco_account.py:49
|
||||||
msgid "Eco-account - Overview"
|
msgid "Eco-account - Overview"
|
||||||
msgstr "Ökokonten - Übersicht"
|
msgstr "Ökokonten - Übersicht"
|
||||||
|
|
||||||
#: compensation/views/eco_account/eco_account.py:86
|
#: compensation/views/eco_account/eco_account.py:82
|
||||||
msgid "Eco-Account {} added"
|
msgid "Eco-Account {} added"
|
||||||
msgstr "Ökokonto {} hinzugefügt"
|
msgstr "Ökokonto {} hinzugefügt"
|
||||||
|
|
||||||
#: compensation/views/eco_account/eco_account.py:158
|
#: compensation/views/eco_account/eco_account.py:145
|
||||||
msgid "Eco-Account {} edited"
|
msgid "Eco-Account {} edited"
|
||||||
msgstr "Ökokonto {} bearbeitet"
|
msgstr "Ökokonto {} bearbeitet"
|
||||||
|
|
||||||
#: compensation/views/eco_account/eco_account.py:288
|
#: ema/forms.py:42 ema/tests/unit/test_forms.py:27 ema/views/ema.py:107
|
||||||
msgid "Eco-account removed"
|
|
||||||
msgstr "Ökokonto entfernt"
|
|
||||||
|
|
||||||
#: ema/forms.py:42 ema/tests/unit/test_forms.py:27 ema/views/ema.py:102
|
|
||||||
msgid "New EMA"
|
msgid "New EMA"
|
||||||
msgstr "Neue EMA hinzufügen"
|
msgstr "Neue EMA hinzufügen"
|
||||||
|
|
||||||
@@ -1353,22 +1353,18 @@ msgstr ""
|
|||||||
msgid "Payment funded compensation"
|
msgid "Payment funded compensation"
|
||||||
msgstr "Ersatzzahlungsmaßnahme"
|
msgstr "Ersatzzahlungsmaßnahme"
|
||||||
|
|
||||||
#: ema/views/ema.py:53
|
#: ema/views/ema.py:52
|
||||||
msgid "EMAs - Overview"
|
msgid "EMAs - Overview"
|
||||||
msgstr "EMAs - Übersicht"
|
msgstr "EMAs - Übersicht"
|
||||||
|
|
||||||
#: ema/views/ema.py:86
|
#: ema/views/ema.py:85
|
||||||
msgid "EMA {} added"
|
msgid "EMA {} added"
|
||||||
msgstr "EMA {} hinzugefügt"
|
msgstr "EMA {} hinzugefügt"
|
||||||
|
|
||||||
#: ema/views/ema.py:217
|
#: ema/views/ema.py:150
|
||||||
msgid "EMA {} edited"
|
msgid "EMA {} edited"
|
||||||
msgstr "EMA {} bearbeitet"
|
msgstr "EMA {} bearbeitet"
|
||||||
|
|
||||||
#: ema/views/ema.py:256
|
|
||||||
msgid "EMA removed"
|
|
||||||
msgstr "EMA entfernt"
|
|
||||||
|
|
||||||
#: intervention/forms/intervention.py:49
|
#: intervention/forms/intervention.py:49
|
||||||
msgid "Construction XY; Location ABC"
|
msgid "Construction XY; Location ABC"
|
||||||
msgstr "Bauvorhaben XY; Flur ABC"
|
msgstr "Bauvorhaben XY; Flur ABC"
|
||||||
@@ -1429,7 +1425,7 @@ msgstr "Datum Bestandskraft bzw. Rechtskraft"
|
|||||||
|
|
||||||
#: intervention/forms/intervention.py:216
|
#: intervention/forms/intervention.py:216
|
||||||
#: intervention/tests/unit/test_forms.py:36
|
#: intervention/tests/unit/test_forms.py:36
|
||||||
#: intervention/views/intervention.py:105
|
#: intervention/views/intervention.py:109
|
||||||
msgid "New intervention"
|
msgid "New intervention"
|
||||||
msgstr "Neuer Eingriff"
|
msgstr "Neuer Eingriff"
|
||||||
|
|
||||||
@@ -1665,22 +1661,18 @@ msgstr ""
|
|||||||
msgid "Check performed"
|
msgid "Check performed"
|
||||||
msgstr "Prüfung durchgeführt"
|
msgstr "Prüfung durchgeführt"
|
||||||
|
|
||||||
#: intervention/views/intervention.py:57
|
#: intervention/views/intervention.py:53
|
||||||
msgid "Interventions - Overview"
|
msgid "Interventions - Overview"
|
||||||
msgstr "Eingriffe - Übersicht"
|
msgstr "Eingriffe - Übersicht"
|
||||||
|
|
||||||
#: intervention/views/intervention.py:90
|
#: intervention/views/intervention.py:86
|
||||||
msgid "Intervention {} added"
|
msgid "Intervention {} added"
|
||||||
msgstr "Eingriff {} hinzugefügt"
|
msgstr "Eingriff {} hinzugefügt"
|
||||||
|
|
||||||
#: intervention/views/intervention.py:236
|
#: intervention/views/intervention.py:150
|
||||||
msgid "Intervention {} edited"
|
msgid "Intervention {} edited"
|
||||||
msgstr "Eingriff {} bearbeitet"
|
msgstr "Eingriff {} bearbeitet"
|
||||||
|
|
||||||
#: intervention/views/intervention.py:278
|
|
||||||
msgid "{} removed"
|
|
||||||
msgstr "{} entfernt"
|
|
||||||
|
|
||||||
#: konova/decorators.py:32
|
#: konova/decorators.py:32
|
||||||
msgid "You need to be staff to perform this action!"
|
msgid "You need to be staff to perform this action!"
|
||||||
msgstr "Hierfür müssen Sie Mitarbeiter sein!"
|
msgstr "Hierfür müssen Sie Mitarbeiter sein!"
|
||||||
@@ -1795,8 +1787,7 @@ msgstr "Bearbeitender Nutzer"
|
|||||||
msgid ""
|
msgid ""
|
||||||
"Search for entries where this person has been participated according to log "
|
"Search for entries where this person has been participated according to log "
|
||||||
"history"
|
"history"
|
||||||
msgstr ""
|
msgstr "Sucht nach Einträgen, an denen diese Person gearbeitet hat"
|
||||||
"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:23 templates/form/collapsable/form.html:62
|
||||||
msgid "Save"
|
msgid "Save"
|
||||||
@@ -1811,15 +1802,11 @@ msgstr "Nicht editierbar"
|
|||||||
msgid "Geometry"
|
msgid "Geometry"
|
||||||
msgstr "Geometrie"
|
msgstr "Geometrie"
|
||||||
|
|
||||||
#: konova/forms/geometry_form.py:100
|
#: konova/forms/geometry_form.py:105
|
||||||
msgid "Only surfaces allowed. Points or lines must be buffered."
|
msgid "Only surfaces allowed. Points or lines must be buffered."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Nur Flächen erlaubt. Punkte oder Linien müssen zu Flächen gepuffert werden."
|
"Nur Flächen erlaubt. Punkte oder Linien müssen zu Flächen gepuffert werden."
|
||||||
|
|
||||||
#: konova/forms/geometry_form.py:153
|
|
||||||
msgid "Geometry must be greater than 1m². Currently is {}m²"
|
|
||||||
msgstr "Geometrie muss größer als 1m² sein. Aktueller Flächeninhalt: {}m²"
|
|
||||||
|
|
||||||
#: konova/forms/modals/document_form.py:37
|
#: konova/forms/modals/document_form.py:37
|
||||||
msgid "When has this file been created? Important for photos."
|
msgid "When has this file been created? Important for photos."
|
||||||
msgstr "Wann wurde diese Datei erstellt oder das Foto aufgenommen?"
|
msgstr "Wann wurde diese Datei erstellt oder das Foto aufgenommen?"
|
||||||
@@ -1858,6 +1845,7 @@ msgstr ""
|
|||||||
"Ich, {} {}, bestätige, dass diese Daten wieder entzeichnet werden müssen."
|
"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:22 konova/forms/remove_form.py:24
|
||||||
|
#: user/forms/modals/api_token.py:16
|
||||||
msgid "Confirm"
|
msgid "Confirm"
|
||||||
msgstr "Bestätige"
|
msgstr "Bestätige"
|
||||||
|
|
||||||
@@ -1928,11 +1916,11 @@ msgstr "Kontrolle am"
|
|||||||
msgid "Other"
|
msgid "Other"
|
||||||
msgstr "Sonstige"
|
msgstr "Sonstige"
|
||||||
|
|
||||||
#: konova/sub_settings/django_settings.py:157
|
#: konova/sub_settings/django_settings.py:156
|
||||||
msgid "German"
|
msgid "German"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: konova/sub_settings/django_settings.py:158
|
#: konova/sub_settings/django_settings.py:157
|
||||||
msgid "English"
|
msgid "English"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -2266,34 +2254,36 @@ msgstr ""
|
|||||||
"Die Geometrie enthielt mehr als {} Eckpunkte. Sie musste vereinfacht werden "
|
"Die Geometrie enthielt mehr als {} Eckpunkte. Sie musste vereinfacht werden "
|
||||||
"um die Obergrenze von {} erlaubten Eckpunkten einzuhalten."
|
"um die Obergrenze von {} erlaubten Eckpunkten einzuhalten."
|
||||||
|
|
||||||
#: konova/utils/message_templates.py:88
|
#: konova/utils/message_templates.py:86
|
||||||
|
msgid ""
|
||||||
|
"The geometry contained {} parts which have been detected as invalid (e.g. "
|
||||||
|
"too small to be valid). These parts have been removed. Please check the "
|
||||||
|
"stored geometry."
|
||||||
|
msgstr ""
|
||||||
|
"Die Geometrie enthielt {} invalide Bestandteile (z.B. unaussagekräftige "
|
||||||
|
"Kleinstflächen).Diese Bestandteile wurden automatisch entfernt. Bitte "
|
||||||
|
"überprüfen Sie die angepasste Geometrie."
|
||||||
|
|
||||||
|
#: konova/utils/message_templates.py:89
|
||||||
msgid "This intervention has {} revocations"
|
msgid "This intervention has {} revocations"
|
||||||
msgstr "Dem Eingriff liegen {} Widersprüche vor"
|
msgstr "Dem Eingriff liegen {} Widersprüche vor"
|
||||||
|
|
||||||
#: konova/utils/message_templates.py:91
|
#: konova/utils/message_templates.py:92
|
||||||
msgid "Checked on {} by {}"
|
msgid "Checked on {} by {}"
|
||||||
msgstr "Am {} von {} geprüft worden"
|
msgstr "Am {} von {} geprüft worden"
|
||||||
|
|
||||||
#: konova/utils/message_templates.py:92
|
#: konova/utils/message_templates.py:93
|
||||||
msgid "Data has changed since last check on {} by {}"
|
msgid "Data has changed since last check on {} by {}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Daten wurden nach der letzten Prüfung geändert. Letzte Prüfung am {} durch {}"
|
"Daten wurden nach der letzten Prüfung geändert. Letzte Prüfung am {} durch {}"
|
||||||
|
|
||||||
#: konova/utils/message_templates.py:93
|
#: konova/utils/message_templates.py:94
|
||||||
msgid "Current data not checked yet"
|
msgid "Current data not checked yet"
|
||||||
msgstr "Momentane Daten noch nicht geprüft"
|
msgstr "Momentane Daten noch nicht geprüft"
|
||||||
|
|
||||||
#: konova/utils/messenger.py:70
|
#: konova/utils/message_templates.py:97
|
||||||
msgid "{} checked"
|
msgid "New token generated. Administrators need to validate."
|
||||||
msgstr "{} geprüft"
|
msgstr "Neuer Token generiert. Administratoren sind informiert."
|
||||||
|
|
||||||
#: konova/utils/messenger.py:72
|
|
||||||
msgid "<a href=\"{}\">Check it out</a>"
|
|
||||||
msgstr "<a href=\"{}\">Schauen Sie rein</a>"
|
|
||||||
|
|
||||||
#: konova/utils/messenger.py:73
|
|
||||||
msgid "{} has been checked successfully by user {}! {}"
|
|
||||||
msgstr "{} wurde erfolgreich vom Nutzer {} geprüft! {}"
|
|
||||||
|
|
||||||
#: konova/utils/quality.py:32
|
#: konova/utils/quality.py:32
|
||||||
msgid "missing"
|
msgid "missing"
|
||||||
@@ -2321,14 +2311,6 @@ msgstr "Home"
|
|||||||
msgid "Log"
|
msgid "Log"
|
||||||
msgstr "Log"
|
msgstr "Log"
|
||||||
|
|
||||||
#: konova/views/map_proxy.py:70
|
|
||||||
msgid ""
|
|
||||||
"The external service is currently unavailable.<br>Please try again in a few "
|
|
||||||
"moments..."
|
|
||||||
msgstr ""
|
|
||||||
"Der externe Dienst ist zur Zeit nicht erreichbar.<br>Versuchen Sie es in ein "
|
|
||||||
"paar Sekunden nochmal."
|
|
||||||
|
|
||||||
#: konova/views/record.py:30
|
#: konova/views/record.py:30
|
||||||
msgid "{} unrecorded"
|
msgid "{} unrecorded"
|
||||||
msgstr "{} entzeichnet"
|
msgstr "{} entzeichnet"
|
||||||
@@ -2341,6 +2323,10 @@ msgstr "{} verzeichnet"
|
|||||||
msgid "Errors found:"
|
msgid "Errors found:"
|
||||||
msgstr "Fehler gefunden:"
|
msgstr "Fehler gefunden:"
|
||||||
|
|
||||||
|
#: konova/views/remove.py:35
|
||||||
|
msgid "{} removed"
|
||||||
|
msgstr "{} entfernt"
|
||||||
|
|
||||||
#: konova/views/resubmission.py:39
|
#: konova/views/resubmission.py:39
|
||||||
msgid "Resubmission set"
|
msgid "Resubmission set"
|
||||||
msgstr "Wiedervorlage gesetzt"
|
msgstr "Wiedervorlage gesetzt"
|
||||||
@@ -2385,6 +2371,20 @@ msgstr "Alle"
|
|||||||
msgid "News"
|
msgid "News"
|
||||||
msgstr "Neuigkeiten"
|
msgstr "Neuigkeiten"
|
||||||
|
|
||||||
|
#: templates/400.html:12
|
||||||
|
msgid "Request was invalid"
|
||||||
|
msgstr "Anfrage fehlerhaft"
|
||||||
|
|
||||||
|
#: templates/400.html:17
|
||||||
|
msgid "There seems to be a problem with the link you opened."
|
||||||
|
msgstr "Es scheint ein Problem mit dem Link zu geben, den Sie geöffnet haben."
|
||||||
|
|
||||||
|
#: templates/400.html:18
|
||||||
|
msgid "Make sure the URL is valid (no whitespaces, properly copied, ...)."
|
||||||
|
msgstr ""
|
||||||
|
"Stellen Sie sicher, dass die URL gültig ist (keine Leerzeichen, fehlerfrei "
|
||||||
|
"kopiert, ...)."
|
||||||
|
|
||||||
#: templates/404.html:7
|
#: templates/404.html:7
|
||||||
msgid "Not found"
|
msgid "Not found"
|
||||||
msgstr "Nicht gefunden"
|
msgstr "Nicht gefunden"
|
||||||
@@ -2397,11 +2397,11 @@ msgstr "Die angeforderten Daten existieren nicht."
|
|||||||
msgid "Make sure the URL is valid (no whitespaces, ...)."
|
msgid "Make sure the URL is valid (no whitespaces, ...)."
|
||||||
msgstr "Stellen Sie sicher, dass die URL gültig ist (keine Leerzeichen, ...)."
|
msgstr "Stellen Sie sicher, dass die URL gültig ist (keine Leerzeichen, ...)."
|
||||||
|
|
||||||
#: templates/500.html:7
|
#: templates/500.html:12
|
||||||
msgid "Server Error"
|
msgid "Server Error"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: templates/500.html:10
|
#: templates/500.html:17
|
||||||
msgid "Something happened. Admins have been informed. We are working on it!"
|
msgid "Something happened. Admins have been informed. We are working on it!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Irgendetwas ist passiert. Die Administratoren wurden informiert. Wir "
|
"Irgendetwas ist passiert. Die Administratoren wurden informiert. Wir "
|
||||||
@@ -2831,10 +2831,8 @@ msgid "Reports"
|
|||||||
msgstr "Berichte"
|
msgstr "Berichte"
|
||||||
|
|
||||||
#: templates/navbars/navbar.html:57
|
#: templates/navbars/navbar.html:57
|
||||||
#, fuzzy
|
|
||||||
#| msgid "Admins"
|
|
||||||
msgid "Admin"
|
msgid "Admin"
|
||||||
msgstr "Administratoren"
|
msgstr ""
|
||||||
|
|
||||||
#: templates/navbars/navbar.html:59 user/templates/user/index.html:31
|
#: templates/navbars/navbar.html:59 user/templates/user/index.html:31
|
||||||
msgid "Settings"
|
msgid "Settings"
|
||||||
@@ -2873,6 +2871,22 @@ msgstr ""
|
|||||||
"Falls die Geometrie nicht leer ist, werden die Flurstücke aktuell berechnet. "
|
"Falls die Geometrie nicht leer ist, werden die Flurstücke aktuell berechnet. "
|
||||||
"Bitte laden Sie diese Seite in ein paar Augenblicken erneut..."
|
"Bitte laden Sie diese Seite in ein paar Augenblicken erneut..."
|
||||||
|
|
||||||
|
#: user/forms/modals/api_token.py:25
|
||||||
|
msgid "Generate API Token"
|
||||||
|
msgstr "API Token generieren"
|
||||||
|
|
||||||
|
#: user/forms/modals/api_token.py:29
|
||||||
|
msgid ""
|
||||||
|
"You are about to create a new API token. The existing one will not be usable "
|
||||||
|
"afterwards."
|
||||||
|
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
|
||||||
|
msgid "A new token needs to be validated by an administrator!"
|
||||||
|
msgstr "Neue Tokens müssen durch Administratoren freigeschaltet werden!"
|
||||||
|
|
||||||
#: user/forms/modals/team.py:20 user/forms/modals/team.py:24
|
#: user/forms/modals/team.py:20 user/forms/modals/team.py:24
|
||||||
#: user/forms/team.py:17 user/forms/team.py:22
|
#: user/forms/team.py:17 user/forms/team.py:22
|
||||||
msgid "Team name"
|
msgid "Team name"
|
||||||
@@ -2895,11 +2909,11 @@ msgstr ""
|
|||||||
"Mehrfachauswahl möglich - Sie können nur Nutzer wählen, die noch nicht "
|
"Mehrfachauswahl möglich - Sie können nur Nutzer wählen, die noch nicht "
|
||||||
"Mitglieder dieses Teams sind. Geben Sie den ganzen Nutzernamen an."
|
"Mitglieder dieses Teams sind. Geben Sie den ganzen Nutzernamen an."
|
||||||
|
|
||||||
#: user/forms/modals/team.py:56 user/tests/unit/test_forms.py:31
|
#: user/forms/modals/team.py:56 user/tests/unit/test_forms.py:30
|
||||||
msgid "Create new team"
|
msgid "Create new team"
|
||||||
msgstr "Neues Team anlegen"
|
msgstr "Neues Team anlegen"
|
||||||
|
|
||||||
#: user/forms/modals/team.py:57 user/tests/unit/test_forms.py:32
|
#: user/forms/modals/team.py:57 user/tests/unit/test_forms.py:31
|
||||||
msgid ""
|
msgid ""
|
||||||
"You will become the administrator for this group by default. You do not need "
|
"You will become the administrator for this group by default. You do not need "
|
||||||
"to add yourself to the list of members."
|
"to add yourself to the list of members."
|
||||||
@@ -2928,11 +2942,11 @@ msgid "There must be at least one admin on this team."
|
|||||||
msgstr "Es muss mindestens einen Administrator für das Team geben."
|
msgstr "Es muss mindestens einen Administrator für das Team geben."
|
||||||
|
|
||||||
#: user/forms/modals/team.py:160 user/templates/user/team/index.html:60
|
#: user/forms/modals/team.py:160 user/templates/user/team/index.html:60
|
||||||
#: user/tests/unit/test_forms.py:88
|
#: user/tests/unit/test_forms.py:87
|
||||||
msgid "Edit team"
|
msgid "Edit team"
|
||||||
msgstr "Team bearbeiten"
|
msgstr "Team bearbeiten"
|
||||||
|
|
||||||
#: user/forms/modals/team.py:187 user/tests/unit/test_forms.py:165
|
#: user/forms/modals/team.py:187 user/tests/unit/test_forms.py:164
|
||||||
msgid ""
|
msgid ""
|
||||||
"ATTENTION!\n"
|
"ATTENTION!\n"
|
||||||
"\n"
|
"\n"
|
||||||
@@ -2949,7 +2963,7 @@ msgstr ""
|
|||||||
"Sind Sie sicher, dass Sie dieses Team löschen möchten?"
|
"Sind Sie sicher, dass Sie dieses Team löschen möchten?"
|
||||||
|
|
||||||
#: user/forms/modals/team.py:197 user/templates/user/team/index.html:56
|
#: user/forms/modals/team.py:197 user/templates/user/team/index.html:56
|
||||||
#: user/tests/unit/test_forms.py:198
|
#: user/tests/unit/test_forms.py:197
|
||||||
msgid "Leave team"
|
msgid "Leave team"
|
||||||
msgstr "Team verlassen"
|
msgstr "Team verlassen"
|
||||||
|
|
||||||
@@ -2981,22 +2995,10 @@ msgstr "Benachrichtigungen"
|
|||||||
msgid "Select the situations when you want to receive a notification"
|
msgid "Select the situations when you want to receive a notification"
|
||||||
msgstr "Wann wollen Sie per E-Mail benachrichtigt werden?"
|
msgstr "Wann wollen Sie per E-Mail benachrichtigt werden?"
|
||||||
|
|
||||||
#: user/forms/user.py:38 user/tests/unit/test_forms.py:234
|
#: user/forms/user.py:38 user/tests/unit/test_forms.py:233
|
||||||
msgid "Edit notifications"
|
msgid "Edit notifications"
|
||||||
msgstr "Benachrichtigungen bearbeiten"
|
msgstr "Benachrichtigungen bearbeiten"
|
||||||
|
|
||||||
#: user/forms/user.py:73
|
|
||||||
msgid "Token"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: user/forms/user.py:88 user/tests/unit/test_forms.py:260
|
|
||||||
msgid "Create new token"
|
|
||||||
msgstr "Neuen Token generieren"
|
|
||||||
|
|
||||||
#: user/forms/user.py:89 user/tests/unit/test_forms.py:261
|
|
||||||
msgid "A new token needs to be validated by an administrator!"
|
|
||||||
msgstr "Neue Tokens müssen durch Administratoren freigeschaltet werden!"
|
|
||||||
|
|
||||||
#: user/models/user_action.py:23
|
#: user/models/user_action.py:23
|
||||||
msgid "Unrecorded"
|
msgid "Unrecorded"
|
||||||
msgstr "Entzeichnet"
|
msgstr "Entzeichnet"
|
||||||
@@ -3051,7 +3053,7 @@ msgid "Manage teams"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: user/templates/user/index.html:53 user/templates/user/team/index.html:19
|
#: user/templates/user/index.html:53 user/templates/user/team/index.html:19
|
||||||
#: user/views/views.py:171
|
#: user/views/views.py:135
|
||||||
msgid "Teams"
|
msgid "Teams"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -3087,270 +3089,58 @@ msgstr "API Einstellungen"
|
|||||||
msgid "Current token"
|
msgid "Current token"
|
||||||
msgstr "Aktueller Token"
|
msgstr "Aktueller Token"
|
||||||
|
|
||||||
#: user/templates/user/token.html:14
|
#: user/templates/user/token.html:15
|
||||||
|
msgid "Create new token"
|
||||||
|
msgstr "Neuen Token generieren"
|
||||||
|
|
||||||
|
#: user/templates/user/token.html:23
|
||||||
msgid "Authenticated by admins"
|
msgid "Authenticated by admins"
|
||||||
msgstr "Von Admin freigeschaltet"
|
msgstr "Von Admin freigeschaltet"
|
||||||
|
|
||||||
#: user/templates/user/token.html:18
|
#: user/templates/user/token.html:27
|
||||||
msgid "Token has been verified and can be used"
|
msgid "Token has been verified and can be used"
|
||||||
msgstr "Token wurde freigeschaltet und kann verwendet werden"
|
msgstr "Token wurde freigeschaltet und kann verwendet werden"
|
||||||
|
|
||||||
#: user/templates/user/token.html:20
|
#: user/templates/user/token.html:29
|
||||||
msgid "Token waiting for verification"
|
msgid "Token waiting for verification"
|
||||||
msgstr "Token noch nicht freigeschaltet"
|
msgstr "Token noch nicht freigeschaltet"
|
||||||
|
|
||||||
#: user/templates/user/token.html:24
|
#: user/templates/user/token.html:33
|
||||||
msgid "Valid until"
|
msgid "Valid until"
|
||||||
msgstr "Läuft ab am"
|
msgstr "Läuft ab am"
|
||||||
|
|
||||||
#: user/views/views.py:35
|
#: user/views/api_token.py:34
|
||||||
msgid "User settings"
|
|
||||||
msgstr "Einstellungen"
|
|
||||||
|
|
||||||
#: user/views/views.py:61
|
|
||||||
msgid "Notifications edited"
|
|
||||||
msgstr "Benachrichtigungen bearbeitet"
|
|
||||||
|
|
||||||
#: user/views/views.py:73
|
|
||||||
msgid "User notifications"
|
|
||||||
msgstr "Benachrichtigungen"
|
|
||||||
|
|
||||||
#: user/views/views.py:96
|
|
||||||
msgid "New token generated. Administrators need to validate."
|
|
||||||
msgstr "Neuer Token generiert. Administratoren sind informiert."
|
|
||||||
|
|
||||||
#: user/views/views.py:107
|
|
||||||
msgid "User API token"
|
msgid "User API token"
|
||||||
msgstr "API Nutzer Token"
|
msgstr "API Nutzer Token"
|
||||||
|
|
||||||
#: user/views/views.py:183
|
#: user/views/views.py:33
|
||||||
|
msgid "User settings"
|
||||||
|
msgstr "Einstellungen"
|
||||||
|
|
||||||
|
#: user/views/views.py:59
|
||||||
|
msgid "Notifications edited"
|
||||||
|
msgstr "Benachrichtigungen bearbeitet"
|
||||||
|
|
||||||
|
#: user/views/views.py:71
|
||||||
|
msgid "User notifications"
|
||||||
|
msgstr "Benachrichtigungen"
|
||||||
|
|
||||||
|
#: user/views/views.py:147
|
||||||
msgid "New team added"
|
msgid "New team added"
|
||||||
msgstr "Neues Team hinzugefügt"
|
msgstr "Neues Team hinzugefügt"
|
||||||
|
|
||||||
#: user/views/views.py:198
|
#: user/views/views.py:162
|
||||||
msgid "Team edited"
|
msgid "Team edited"
|
||||||
msgstr "Team bearbeitet"
|
msgstr "Team bearbeitet"
|
||||||
|
|
||||||
#: user/views/views.py:213
|
#: user/views/views.py:177
|
||||||
msgid "Team removed"
|
msgid "Team removed"
|
||||||
msgstr "Team gelöscht"
|
msgstr "Team gelöscht"
|
||||||
|
|
||||||
#: user/views/views.py:228
|
#: user/views/views.py:192
|
||||||
msgid "You are not a member of this team"
|
msgid "You are not a member of this team"
|
||||||
msgstr "Sie sind kein Mitglied dieses Teams"
|
msgstr "Sie sind kein Mitglied dieses Teams"
|
||||||
|
|
||||||
#: user/views/views.py:235
|
#: user/views/views.py:199
|
||||||
msgid "Left Team"
|
msgid "Left Team"
|
||||||
msgstr "Team verlassen"
|
msgstr "Team verlassen"
|
||||||
|
|
||||||
#~ msgid "close"
|
|
||||||
#~ msgstr "Schließen"
|
|
||||||
|
|
||||||
#~ msgid "Options"
|
|
||||||
#~ msgstr "Optionen"
|
|
||||||
|
|
||||||
#~ msgid "Commands"
|
|
||||||
#~ msgstr "Befehle"
|
|
||||||
|
|
||||||
#~ msgid "Missing command."
|
|
||||||
#~ msgstr "Befehl fehlt"
|
|
||||||
|
|
||||||
#~ msgid "Missing argument"
|
|
||||||
#~ msgstr "Argument fehlt"
|
|
||||||
|
|
||||||
#~ msgid "Missing option"
|
|
||||||
#~ msgstr "Option fehlt"
|
|
||||||
|
|
||||||
#~ msgid "Missing parameter"
|
|
||||||
#~ msgstr "Parameter fehlt"
|
|
||||||
|
|
||||||
#~ msgid "Messages"
|
|
||||||
#~ msgstr "Nachrichten"
|
|
||||||
|
|
||||||
#~ msgid "This field is required."
|
|
||||||
#~ msgstr "Pflichtfeld"
|
|
||||||
|
|
||||||
#~ msgid "Monday"
|
|
||||||
#~ msgstr "Montag"
|
|
||||||
|
|
||||||
#~ msgid "Tuesday"
|
|
||||||
#~ msgstr "Dienstag"
|
|
||||||
|
|
||||||
#~ msgid "Wednesday"
|
|
||||||
#~ msgstr "Mittwoch"
|
|
||||||
|
|
||||||
#~ msgid "Thursday"
|
|
||||||
#~ msgstr "Donnerstag"
|
|
||||||
|
|
||||||
#~ msgid "Friday"
|
|
||||||
#~ msgstr "Freitag"
|
|
||||||
|
|
||||||
#~ msgid "Saturday"
|
|
||||||
#~ msgstr "Samstag"
|
|
||||||
|
|
||||||
#~ msgid "Sunday"
|
|
||||||
#~ msgstr "Sonntag"
|
|
||||||
|
|
||||||
#~ msgid "Mon"
|
|
||||||
#~ msgstr "Mo"
|
|
||||||
|
|
||||||
#~ msgid "Tue"
|
|
||||||
#~ msgstr "Di"
|
|
||||||
|
|
||||||
#~ msgid "Wed"
|
|
||||||
#~ msgstr "Mi"
|
|
||||||
|
|
||||||
#~ msgid "Thu"
|
|
||||||
#~ msgstr "Do"
|
|
||||||
|
|
||||||
#~ msgid "Fri"
|
|
||||||
#~ msgstr "Fr"
|
|
||||||
|
|
||||||
#~ msgid "Sat"
|
|
||||||
#~ msgstr "Sa"
|
|
||||||
|
|
||||||
#~ msgid "Sun"
|
|
||||||
#~ msgstr "So"
|
|
||||||
|
|
||||||
#~ msgid "January"
|
|
||||||
#~ msgstr "Januar"
|
|
||||||
|
|
||||||
#~ msgid "February"
|
|
||||||
#~ msgstr "Februar"
|
|
||||||
|
|
||||||
#~ msgid "March"
|
|
||||||
#~ msgstr "März"
|
|
||||||
|
|
||||||
#~ msgid "May"
|
|
||||||
#~ msgstr "Mai"
|
|
||||||
|
|
||||||
#~ msgid "June"
|
|
||||||
#~ msgstr "Juni"
|
|
||||||
|
|
||||||
#~ msgid "July"
|
|
||||||
#~ msgstr "Juli"
|
|
||||||
|
|
||||||
#~ msgid "October"
|
|
||||||
#~ msgstr "Oktober"
|
|
||||||
|
|
||||||
#~ msgid "December"
|
|
||||||
#~ msgstr "Dezember"
|
|
||||||
|
|
||||||
#~ msgid "mar"
|
|
||||||
#~ msgstr "mär"
|
|
||||||
|
|
||||||
#~ msgid "may"
|
|
||||||
#~ msgstr "mai"
|
|
||||||
|
|
||||||
#~ msgid "oct"
|
|
||||||
#~ msgstr "okt"
|
|
||||||
|
|
||||||
#~ msgid "dec"
|
|
||||||
#~ msgstr "dez"
|
|
||||||
|
|
||||||
#~ msgctxt "abbrev. month"
|
|
||||||
#~ msgid "March"
|
|
||||||
#~ msgstr "Mär"
|
|
||||||
|
|
||||||
#~ msgctxt "abbrev. month"
|
|
||||||
#~ msgid "May"
|
|
||||||
#~ msgstr "Mai"
|
|
||||||
|
|
||||||
#~ msgctxt "abbrev. month"
|
|
||||||
#~ msgid "June"
|
|
||||||
#~ msgstr "Juni"
|
|
||||||
|
|
||||||
#~ msgctxt "abbrev. month"
|
|
||||||
#~ msgid "July"
|
|
||||||
#~ msgstr "Juli"
|
|
||||||
|
|
||||||
#~ msgctxt "abbrev. month"
|
|
||||||
#~ msgid "Oct."
|
|
||||||
#~ msgstr "Okt."
|
|
||||||
|
|
||||||
#~ msgctxt "abbrev. month"
|
|
||||||
#~ msgid "Dec."
|
|
||||||
#~ msgstr "Dez."
|
|
||||||
|
|
||||||
#~ msgctxt "alt. month"
|
|
||||||
#~ msgid "January"
|
|
||||||
#~ msgstr "Januar"
|
|
||||||
|
|
||||||
#~ msgctxt "alt. month"
|
|
||||||
#~ msgid "February"
|
|
||||||
#~ msgstr "Februar"
|
|
||||||
|
|
||||||
#~ msgctxt "alt. month"
|
|
||||||
#~ msgid "March"
|
|
||||||
#~ msgstr "März"
|
|
||||||
|
|
||||||
#~ msgctxt "alt. month"
|
|
||||||
#~ msgid "May"
|
|
||||||
#~ msgstr "Mai"
|
|
||||||
|
|
||||||
#~ msgctxt "alt. month"
|
|
||||||
#~ msgid "June"
|
|
||||||
#~ msgstr "Juni"
|
|
||||||
|
|
||||||
#~ msgctxt "alt. month"
|
|
||||||
#~ msgid "July"
|
|
||||||
#~ msgstr "Juli"
|
|
||||||
|
|
||||||
#~ msgctxt "alt. month"
|
|
||||||
#~ msgid "October"
|
|
||||||
#~ msgstr "Oktober"
|
|
||||||
|
|
||||||
#~ msgctxt "alt. month"
|
|
||||||
#~ msgid "December"
|
|
||||||
#~ msgstr "Dezember"
|
|
||||||
|
|
||||||
#~ msgid "or"
|
|
||||||
#~ msgstr "oder"
|
|
||||||
|
|
||||||
#~ msgid ""
|
|
||||||
#~ "Deductable surface can not be larger than existing surfaces in after "
|
|
||||||
#~ "states"
|
|
||||||
#~ msgstr ""
|
|
||||||
#~ "Die abbuchbare Fläche darf die Gesamtfläche der Zielzustände nicht "
|
|
||||||
#~ "überschreiten"
|
|
||||||
|
|
||||||
#~ msgid ""
|
|
||||||
#~ "Deductable surface can not be smaller than the sum of already existing "
|
|
||||||
#~ "deductions. Please contact the responsible users for the deductions!"
|
|
||||||
#~ msgstr ""
|
|
||||||
#~ "Es wurde bereits mehr Fläche abgebucht, als Sie nun als abbuchbar "
|
|
||||||
#~ "einstellen wollen. Kontaktieren Sie die für die Abbuchungen "
|
|
||||||
#~ "verantwortlichen Nutzer!"
|
|
||||||
|
|
||||||
#~ msgid "Added deadline"
|
|
||||||
#~ msgstr "Frist/Termin hinzugefügt"
|
|
||||||
|
|
||||||
#~ msgid "Change default configuration for your KSP map"
|
|
||||||
#~ msgstr "Karteneinstellungen ändern"
|
|
||||||
|
|
||||||
#~ msgid "Map settings"
|
|
||||||
#~ msgstr "Karte"
|
|
||||||
|
|
||||||
#~ msgid "There are errors on this intervention:"
|
|
||||||
#~ msgstr "Es liegen Fehler in diesem Eingriff vor:"
|
|
||||||
|
|
||||||
#~ msgid "Before"
|
|
||||||
#~ msgstr "Vor"
|
|
||||||
|
|
||||||
#~ msgid "Groups"
|
|
||||||
#~ msgstr "Gruppen"
|
|
||||||
|
|
||||||
#~ msgid "Show more..."
|
|
||||||
#~ msgstr "Mehr anzeigen..."
|
|
||||||
|
|
||||||
#~ msgid "Kreis"
|
|
||||||
#~ msgstr "Kreis"
|
|
||||||
|
|
||||||
#~ msgid "Gemarkung"
|
|
||||||
#~ msgstr "Gemarkung"
|
|
||||||
|
|
||||||
#~ msgid "Loading..."
|
|
||||||
#~ msgstr "Lade..."
|
|
||||||
|
|
||||||
#~ msgid "Who handles the eco-account"
|
|
||||||
#~ msgstr "Wer für die Herrichtung des Ökokontos verantwortlich ist"
|
|
||||||
|
|||||||
@@ -1,65 +1,63 @@
|
|||||||
amqp==5.2.0
|
amqp==5.3.1
|
||||||
asgiref==3.8.1
|
asgiref==3.8.1
|
||||||
async-timeout==4.0.3
|
async-timeout==5.0.1
|
||||||
beautifulsoup4==4.13.0b2
|
beautifulsoup4==4.13.0b2
|
||||||
billiard==4.2.0
|
billiard==4.2.1
|
||||||
cached-property==1.5.2
|
cached-property==2.0.1
|
||||||
celery==5.4.0
|
celery==5.4.0
|
||||||
certifi==2024.7.4
|
certifi==2024.12.14
|
||||||
cffi==1.17.0
|
cffi==1.17.1
|
||||||
chardet==5.2.0
|
chardet==5.2.0
|
||||||
charset-normalizer==3.3.2
|
charset-normalizer==3.4.0
|
||||||
click==8.1.7
|
click==8.1.8
|
||||||
click-didyoumean==0.3.1
|
click-didyoumean==0.3.1
|
||||||
click-plugins==1.1.1
|
click-plugins==1.1.1
|
||||||
click-repl==0.3.0
|
click-repl==0.3.0
|
||||||
coverage==7.5.4
|
coverage==7.6.9
|
||||||
cryptography==43.0.0
|
cryptography==44.0.0
|
||||||
Deprecated==1.2.14
|
Deprecated==1.2.15
|
||||||
Django==5.0.8
|
Django==5.1.4
|
||||||
django-autocomplete-light==3.11.0
|
django-autocomplete-light==3.11.0
|
||||||
django-bootstrap-modal-forms==3.0.4
|
django-bootstrap-modal-forms==3.0.5
|
||||||
django-bootstrap4==24.3
|
django-bootstrap4==24.4
|
||||||
django-environ==0.11.2
|
django-environ==0.11.2
|
||||||
django-filter==24.3
|
django-filter==24.3
|
||||||
django-fontawesome-5==1.0.18
|
django-fontawesome-5==1.0.18
|
||||||
django-oauth-toolkit==2.4.0
|
django-oauth-toolkit==3.0.1
|
||||||
django-simple-sso==1.2.0
|
django-tables2==2.7.1
|
||||||
django-tables2==2.7.0
|
et_xmlfile==2.0.0
|
||||||
et-xmlfile==1.1.0
|
gunicorn==23.0.0
|
||||||
gunicorn==22.0.0
|
idna==3.10
|
||||||
idna==3.7
|
importlib_metadata==8.5.0
|
||||||
importlib_metadata==8.2.0
|
|
||||||
itsdangerous==0.24
|
|
||||||
jwcrypto==1.5.6
|
jwcrypto==1.5.6
|
||||||
kombu==5.4.0rc1
|
kombu==5.4.0rc1
|
||||||
oauthlib==3.2.2
|
oauthlib==3.2.2
|
||||||
openpyxl==3.2.0b1
|
openpyxl==3.2.0b1
|
||||||
packaging==24.1
|
packaging==24.2
|
||||||
pika==1.3.2
|
pika==1.3.2
|
||||||
pillow==10.4.0
|
pillow==11.0.0
|
||||||
prompt_toolkit==3.0.47
|
prompt_toolkit==3.0.48
|
||||||
psycopg==3.2.1
|
psycopg==3.2.3
|
||||||
psycopg-binary==3.2.1
|
psycopg-binary==3.2.3
|
||||||
pycparser==2.22
|
pycparser==2.22
|
||||||
pyparsing==3.1.2
|
pyparsing==3.2.0
|
||||||
pypng==0.20220715.0
|
pypng==0.20220715.0
|
||||||
pyproj==3.6.1
|
pyproj==3.7.0
|
||||||
python-dateutil==2.9.0.post0
|
python-dateutil==2.9.0.post0
|
||||||
pytz==2024.1
|
pytz==2024.2
|
||||||
PyYAML==6.0.2
|
PyYAML==6.0.2
|
||||||
qrcode==7.3.1
|
qrcode==7.3.1
|
||||||
redis==5.1.0b6
|
redis==5.1.0b6
|
||||||
requests<2.32.0 # kombu 5.4.0rc1 depends on requests<2.32.0
|
requests==2.32.3
|
||||||
six==1.16.0
|
six==1.16.0
|
||||||
soupsieve==2.5
|
soupsieve==2.5
|
||||||
sqlparse==0.5.1
|
sqlparse==0.5.1
|
||||||
typing_extensions==4.12.2
|
typing_extensions==4.12.2
|
||||||
tzdata==2024.1
|
tzdata==2024.2
|
||||||
urllib3==2.2.2
|
urllib3==2.3.0
|
||||||
vine==5.1.0
|
vine==5.1.0
|
||||||
wcwidth==0.2.13
|
wcwidth==0.2.13
|
||||||
webservices==0.7
|
webservices==0.7
|
||||||
wrapt==1.16.0
|
wrapt==1.16.0
|
||||||
xmltodict==0.13.0
|
xmltodict==0.14.2
|
||||||
zipp==3.19.2
|
zipp==3.21.0
|
||||||
|
|||||||
21
templates/400.html
Normal file
21
templates/400.html
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{% extends 'public_base.html' %}
|
||||||
|
{% load i18n fontawesome_5 static %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
<div class="jumbotron">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-auto">
|
||||||
|
<img src="{% static 'images/error_imgs/croc_technician_400.png' %}" style="max-width: 150px">
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-12 col-md-9 col-lg-9 col-xl-10">
|
||||||
|
<h1 class="display-4">{% fa5_icon 'question-circle' %}400</h1>
|
||||||
|
<h1 class="display-4">{% trans 'Request was invalid' %}</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
<p class="lead">
|
||||||
|
{% trans 'There seems to be a problem with the link you opened.' %}
|
||||||
|
{% trans 'Make sure the URL is valid (no whitespaces, properly copied, ...).' %}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
@@ -1,10 +1,17 @@
|
|||||||
{% extends 'public_base.html' %}
|
{% extends 'public_base.html' %}
|
||||||
{% load i18n fontawesome_5 %}
|
{% load i18n fontawesome_5 static %}
|
||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<div class="jumbotron">
|
<div class="jumbotron">
|
||||||
<h1 class="display-4">{% fa5_icon 'fire-extinguisher' %} {% fa5_icon 'fire-alt' %} 500</h1>
|
<div class="row">
|
||||||
<h1 class="display-4">{% trans 'Server Error' %}</h1>
|
<div class="col-auto">
|
||||||
|
<img src="{% static 'images/error_imgs/croc_technician_500.png' %}" style="max-width: 150px">
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-12 col-md-9 col-lg-9 col-xl-10">
|
||||||
|
<h1 class="display-4">{% fa5_icon 'fire-alt' %} 500</h1>
|
||||||
|
<h1 class="display-4">{% trans 'Server Error' %}</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<hr>
|
<hr>
|
||||||
<p class="lead">
|
<p class="lead">
|
||||||
{% trans 'Something happened. Admins have been informed. We are working on it!' %}
|
{% trans 'Something happened. Admins have been informed. We are working on it!' %}
|
||||||
|
|||||||
@@ -1,170 +1,305 @@
|
|||||||
{
|
{
|
||||||
"layers":
|
"modules":
|
||||||
[
|
{
|
||||||
{ "folder": 5, "type": "WMS", "title": "KOM Flächen", "url": "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_ogc/wms_getmap.php?mapfile=kom_f&", "name": "kom_f" },
|
"menu": true,
|
||||||
{ "folder": 5, "type": "WMS", "title": "KOM Linien", "url": "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_ogc/wms_getmap.php?mapfile=kom_l&", "name": "kom_l" },
|
"layertree": true,
|
||||||
{ "folder": 5, "type": "WMS", "title": "KOM Punkte", "url": "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_ogc/wms_getmap.php?mapfile=komon&", "name": "kom_p" },
|
"map": true,
|
||||||
|
"controls": true,
|
||||||
{ "folder": 6, "type": "WMS", "title": "EIV Flächen", "url": "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_ogc/wms_getmap.php?mapfile=eiv_f&", "name": "eiv_f" },
|
"attribution": true,
|
||||||
{ "folder": 6, "type": "WMS", "title": "EIV Linien", "url": "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_ogc/wms_getmap.php?mapfile=eiv_l&", "name": "eiv_l" },
|
"info": true,
|
||||||
{ "folder": 6, "type": "WMS", "title": "EIV Punkte", "url": "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_ogc/wms_getmap.php?mapfile=eiv_p&", "name": "eiv_p" },
|
"searchplace": true,
|
||||||
|
"searchparcel": true,
|
||||||
{ "folder": 7, "type": "WMS", "title": "OEK Flächen", "url": "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_ogc/wms_getmap.php?mapfile=oek_f&", "name": "oek_f" },
|
"toolbox": true,
|
||||||
|
"import": true,
|
||||||
{ "folder": 8, "type": "WMS", "title": "EMA Flächen", "url": "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_ogc/wms_getmap.php?mapfile=ema_f&", "name": "ema_f" },
|
"export": true
|
||||||
|
},
|
||||||
{ "folder": 9, "type": "WMS", "title": "MAE Flächen", "url": "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_ogc/wms_getmap.php?mapfile=mae&", "name": "mae" },
|
"menu":
|
||||||
|
{
|
||||||
{ "folder": 10, "type": "WMS", "title": "Naturschutzgebiete", "url": "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_ogc/wms_getmap.php?mapfile=naturschutzgebiet&", "name": "naturschutzgebiet" },
|
"header": "",
|
||||||
{ "folder": 10, "type": "WMS", "title": "Naturparkzonen", "url": "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_ogc/wms_getmap.php?mapfile=naturparkzonen&", "name": "naturparkzonen" },
|
"items":
|
||||||
{ "folder": 10, "type": "WMS", "title": "Landschaftsschutzgebiete", "url": "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_ogc/wms_getmap.php?mapfile=landschaftsschutzgebiet&", "name": "landschaftsschutzgebiet" },
|
[
|
||||||
{ "folder": 10, "type": "WMS", "title": "Vogelschutzgebiete", "url": "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_ogc/wms_getmap.php?mapfile=vogelschutzgebiet&", "name": "vogelschutzgebiet" },
|
{ "id": "searchplace", "title": "<i class='fas fa-search'></i><span>Suche</span>" },
|
||||||
{ "folder": 10, "type": "WMS", "title": "FFH Gebiete", "url": "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_ogc/wms_getmap.php?mapfile=ffh&", "name": "ffh" },
|
{ "id": "searchparcel", "title": "<i class='fas fa-vector-square'></i><span>Flurstücke</span>" },
|
||||||
|
{ "id": "toolbox", "title": "<i class='fas fa-tools'></i><span>Werkzeuge</span>" },
|
||||||
{ "folder": 11, "type": "WMS", "title": "Nationalpark Zonen", "url": "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_ogc/wms_getmap.php?mapfile=nationalpark_zonen&", "name": "nationalpark_zonen" },
|
{ "id": "layertree", "title": "<i class='fas fa-layer-group'></i><span>Inhalte</span>" }
|
||||||
{ "folder": 11, "type": "WMS", "title": "Nationalpark Grenzen", "url": "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_ogc/wms_getmap.php?mapfile=nationalpark_grenze&", "name": "nationalpark_grenze" },
|
]
|
||||||
|
},
|
||||||
{ "folder": 12, "type": "WMS", "title": "Naturräume Grenzen", "url": "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_ogc/wms_getmap.php?mapfile=natraum_lkompvo_grenzen&", "name": "natraum_lkompvo_grenzen" },
|
|
||||||
{ "folder": 12, "type": "WMS", "title": "Naturräume Flächen", "url": "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_ogc/wms_getmap.php?mapfile=natraum_lkompvo&", "name": "natraum_lkompvo" },
|
|
||||||
|
|
||||||
{ "folder": 1, "type": "WMS", "title": "Lagebezeichnungen", "url": "https://geo5.service24.rlp.de/wms/liegenschaften_rp.fcgi?", "name": "Lagebezeichnungen" },
|
|
||||||
{ "folder": 1, "type": "WMS", "title": "Flurstücke (WMS)", "url": "https://geo5.service24.rlp.de/wms/liegenschaften_rp.fcgi?", "name": "Flurstueck", "active": true},
|
|
||||||
{ "folder": 1, "type": "WFS", "title": "Flurstücke (WFS; ab hoher Zoomstufe)", "url": "/client/proxy/wfs?", "name": "ave:Flurstueck", "minZoom": 17},
|
|
||||||
{ "folder": 1, "type": "WMS", "title": "Gebäude / Bauwerke", "url": "https://geo5.service24.rlp.de/wms/liegenschaften_rp.fcgi?", "name": "GebaeudeBauwerke" },
|
|
||||||
{ "folder": 1, "type": "WMS", "title": "Nutzung", "url": "https://geo5.service24.rlp.de/wms/liegenschaften_rp.fcgi?", "name": "Nutzung" },
|
|
||||||
|
|
||||||
{ "folder": 2, "type": "WMS", "title": "Landkreise", "url": "http://geo5.service24.rlp.de/wms/verwaltungsgrenzen_rp.fcgi?", "name": "Landkreise" },
|
|
||||||
{ "folder": 2, "type": "WMS", "title": "Verbandsgemeinden", "url": "http://geo5.service24.rlp.de/wms/verwaltungsgrenzen_rp.fcgi?", "name": "Verbandsgemeinden" },
|
|
||||||
{ "folder": 2, "type": "WMS", "title": "Gemeinden", "url": "http://geo5.service24.rlp.de/wms/verwaltungsgrenzen_rp.fcgi?", "name": "Gemeinden" },
|
|
||||||
|
|
||||||
{ "folder": 15, "type": "WMS", "order": -1, "title": "farbig", "attribution": "LVermGeo", "url": "https://maps.service24.rlp.de/gisserver/services/RP/RP_WebAtlasRP/MapServer/WmsServer?", "name": "RP_WebAtlasRP", "active": true},
|
|
||||||
{ "folder": 15, "type": "WMS", "title": "grau", "attribution": "LVermGeo", "url": "https://maps.service24.rlp.de/gisserver/services/RP/RP_ETRS_Gt/MapServer/WmsServer?", "name": "0", "active": false },
|
|
||||||
{ "folder": 0, "type": "WMS", "title": "Luftbilder", "attribution": "LVermGeo", "url": "http://geo4.service24.rlp.de/wms/dop_basis.fcgi?", "name": "rp_dop", "active": false },
|
|
||||||
{ "folder": 14, "type": "WMS", "title": "farbig", "attribution": "BKG", "url": "https://sgx.geodatenzentrum.de/wms_basemapde?", "name": "de_basemapde_web_raster_farbe", "active": false },
|
|
||||||
{ "folder": 14, "type": "WMS", "title": "grau", "attribution": "BKG", "url": "https://sgx.geodatenzentrum.de/wms_basemapde?", "name": "de_basemapde_web_raster_grau", "active": false },
|
|
||||||
{ "folder": 13, "type": "WMS", "title": "farbig", "attribution": "LVermGeo", "url": "https://geo4.service24.rlp.de/wms/dtk5_rp.fcgi?", "name": "rp_dtk5", "active": false },
|
|
||||||
{ "folder": 13, "type": "WMS", "title": "grau", "attribution": "LVermGeo", "url": "https://geo4.service24.rlp.de/wms/dtk5_rp.fcgi?", "name": "rp_dtk5_grau", "active": false }
|
|
||||||
],
|
|
||||||
"folders":
|
|
||||||
[
|
|
||||||
{ "title": "Hintergrund", "parent": -1 },
|
|
||||||
{ "title": "ALKIS Liegenschaften", "parent": -1 },
|
|
||||||
{ "title": "Verwaltungsgrenzen", "parent": -1 },
|
|
||||||
{ "title": "Geofachdaten", "parent": -1 },
|
|
||||||
{ "title": "Kompensationsverzeichnis", "parent": 3 },
|
|
||||||
{ "title": "Kompensationen", "parent": 4 },
|
|
||||||
{ "title": "Eingriffe", "parent": 4 },
|
|
||||||
{ "title": "Ökokonten", "parent": 4 },
|
|
||||||
{ "title": "EMA", "parent": 4 },
|
|
||||||
{ "title": "MAE", "parent": 4 },
|
|
||||||
{ "title": "Schutzgebiete", "parent": 3 },
|
|
||||||
{ "title": "Nationalparke", "parent": 10 },
|
|
||||||
{ "title": "Naturräume", "parent": 10 },
|
|
||||||
{ "title": "Topographisch (DTK5)", "parent": 0 },
|
|
||||||
{ "title": "BaseMap", "parent": 0 },
|
|
||||||
{ "title": "Webatlas", "parent": 0 }
|
|
||||||
],
|
|
||||||
"projections":
|
"projections":
|
||||||
[
|
[
|
||||||
[ "EPSG:25832", "+proj=utm +zone=32 +ellps=GRS80 +units=m +no_defs" ]
|
[ "EPSG:25832", "+proj=utm +zone=32 +ellps=GRS80 +units=m +no_defs" ]
|
||||||
],
|
],
|
||||||
|
|
||||||
"map":
|
"map":
|
||||||
{
|
{
|
||||||
"projection": "EPSG:25832",
|
"projection": "EPSG:25832",
|
||||||
"center": [ 385000, 5543000 ],
|
"center_lonlat": [ 7.0, 50.0 ],
|
||||||
"minZoom": 5,
|
|
||||||
"maxZoom": 22,
|
|
||||||
"zoom": 9,
|
"zoom": 9,
|
||||||
"attribution": "LANIS RLP",
|
"min_zoom": 5,
|
||||||
"scalebar": true
|
"max_zoom": 24,
|
||||||
},
|
"scalebar": true,
|
||||||
|
"move_tolerance": 5
|
||||||
"output":
|
|
||||||
{
|
|
||||||
"id": "netgis-storage"
|
|
||||||
},
|
|
||||||
|
|
||||||
"search":
|
|
||||||
{
|
|
||||||
"url": "/client/proxy?https://www.geoportal.rlp.de/mapbender/geoportal/gaz_geom_mobile.php?outputFormat=json&resultTarget=web&searchEPSG={epsg}&maxResults=5&maxRows=5&featureClass=P&style=full&searchText={q}&name_startsWith={q}"
|
|
||||||
},
|
},
|
||||||
|
"folders":
|
||||||
|
[
|
||||||
|
{ "id": "bg", "title": "Hintergrund", "parent": null , "radio": true},
|
||||||
|
{ "id": "alkis", "parent": null, "title": "ALKIS Liegenschaften" },
|
||||||
|
{ "id": "verwaltung", "parent": null, "title": "Verwaltungsgrenzen" },
|
||||||
|
{ "id": "fachdaten", "parent": null, "title": "Geofachdaten" },
|
||||||
|
{ "id": "ksp", "parent": "fachdaten", "title": "Kompensationsverzeichnis"},
|
||||||
|
{ "id": "schutzgebiet", "parent": "fachdaten", "title": "Schutzgebiete"},
|
||||||
|
{ "id": "nationalpark", "parent": "schutzgebiet", "title": "Nationalparke"},
|
||||||
|
{ "id": "naturraum", "parent": "schutzgebiet", "title": "Naturräume" },
|
||||||
|
{ "id": "kom", "parent": "ksp", "title": "Kompensationen" },
|
||||||
|
{ "id": "eiv", "parent": "ksp", "title": "Eingriffe" },
|
||||||
|
{ "id": "oek", "parent": "ksp", "title": "Ökokonten" },
|
||||||
|
{ "id": "ema", "parent": "ksp", "title": "EMA" },
|
||||||
|
{ "id": "mae", "parent": "ksp", "title": "MAE" }
|
||||||
|
],
|
||||||
|
"layers":
|
||||||
|
[
|
||||||
|
{ "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/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 },
|
||||||
|
{ "id": "dtk_grau", "folder": "bg", "type": "WMS", "order": -1, "title": "DTK5 grau", "attribution": "LVermGeo", "url": "https://geo4.service24.rlp.de/wms/dtk5_rp.fcgi?", "name": "rp_dtk5_grau", "active": false },
|
||||||
|
|
||||||
"searchParcel":
|
{ "id": "kom", "folder": "kom", "type": "WMS", "title": "KOM", "url": "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_ogc/wms_getmap.php?mapfile=kom_recorded&", "name": "kom_recorded" },
|
||||||
|
{ "id": "kom_rec", "folder": "kom", "type": "WMS", "title": "KOM - In Bearbeitung", "url": "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_ogc/wms_getmap.php?mapfile=kom_unrecorded&", "name": "kom_unrecorded" },
|
||||||
|
{ "id": "kom_rec_unfinished", "folder": "kom", "type": "WMS", "title": "KOM - Unvollständige Altfälle", "url": "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_ogc/wms_getmap.php?mapfile=kom_unrecorded_old_entries&", "name": "kom_unrecorded_old_entries" },
|
||||||
|
|
||||||
|
{ "id": "eiv", "folder": "eiv", "type": "WMS", "title": "EIV", "url": "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_ogc/wms_getmap.php?mapfile=eiv_recorded&", "name": "eiv_recorded" },
|
||||||
|
{ "id": "eiv_rec", "folder": "eiv", "type": "WMS", "title": "EIV - In Bearbeitung", "url": "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_ogc/wms_getmap.php?mapfile=eiv_unrecorded&", "name": "eiv_unrecorded" },
|
||||||
|
{ "id": "eiv_rec_unfinished", "folder": "eiv", "type": "WMS", "title": "EIV - Unvollständige Altfälle", "url": "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_ogc/wms_getmap.php?mapfile=eiv_unrecorded_old_entries&", "name": "eiv_unrecorded_old_entries" },
|
||||||
|
|
||||||
|
{ "id": "oek", "folder": "oek", "type": "WMS", "title": "OEK", "url": "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_ogc/wms_getmap.php?mapfile=oek_recorded&", "name": "oek_recorded" },
|
||||||
|
{ "id": "oek_rec", "folder": "oek", "type": "WMS", "title": "OEK - In Bearbeitung", "url": "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_ogc/wms_getmap.php?mapfile=oek_unrecorded&", "name": "oek_unrecorded" },
|
||||||
|
|
||||||
|
{ "id": "ema", "folder": "ema", "type": "WMS", "title": "EMA", "url": "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_ogc/wms_getmap.php?mapfile=ema_recorded&", "name": "ema_recorded" },
|
||||||
|
{ "id": "ema_rec", "folder": "ema", "type": "WMS", "title": "EMA - In Bearbeitung", "url": "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_ogc/wms_getmap.php?mapfile=ema_unrecorded&", "name": "ema_unrecorded" },
|
||||||
|
|
||||||
|
{ "id": "mae", "folder": "mae", "type": "WMS", "title": "MAE", "url": "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_ogc/wms_getmap.php?mapfile=mae&", "name": "mae" },
|
||||||
|
|
||||||
|
{ "id": "nsg", "folder": "schutzgebiet", "type": "WMS", "title": "Naturschutzgebiete", "url": "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_ogc/wms_getmap.php?mapfile=naturschutzgebiet&", "name": "naturschutzgebiet" },
|
||||||
|
{ "id": "npz", "folder": "schutzgebiet", "type": "WMS", "title": "Naturparkzonen", "url": "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_ogc/wms_getmap.php?mapfile=naturparkzonen&", "name": "naturparkzonen" },
|
||||||
|
{ "id": "lsg", "folder": "schutzgebiet", "type": "WMS", "title": "Landschaftsschutzgebiete", "url": "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_ogc/wms_getmap.php?mapfile=landschaftsschutzgebiet&", "name": "landschaftsschutzgebiet" },
|
||||||
|
{ "id": "vsg", "folder": "schutzgebiet", "type": "WMS", "title": "Vogelschutzgebiete", "url": "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_ogc/wms_getmap.php?mapfile=vogelschutzgebiet&", "name": "vogelschutzgebiet" },
|
||||||
|
{ "id": "ffh", "folder": "schutzgebiet", "type": "WMS", "title": "FFH Gebiete", "url": "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_ogc/wms_getmap.php?mapfile=ffh&", "name": "ffh" },
|
||||||
|
|
||||||
|
{"id": "ntpz", "folder": "nationalpark", "type": "WMS", "title": "Nationalpark Zonen", "url": "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_ogc/wms_getmap.php?mapfile=nationalpark_zonen&", "name": "nationalpark_zonen" },
|
||||||
|
{"id": "ntpg", "folder": "nationalpark", "type": "WMS", "title": "Nationalpark Grenzen", "url": "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_ogc/wms_getmap.php?mapfile=nationalpark_grenze&", "name": "nationalpark_grenze" },
|
||||||
|
|
||||||
|
{ "id": "natraum_g", "folder": "naturraum", "type": "WMS", "title": "Naturräume Grenzen", "url": "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_ogc/wms_getmap.php?mapfile=natraum_lkompvo_grenzen&", "name": "natraum_lkompvo_grenzen" },
|
||||||
|
{ "id": "natraum_f", "folder": "naturraum", "type": "WMS", "title": "Naturräume Flächen", "url": "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_ogc/wms_getmap.php?mapfile=natraum_lkompvo&", "name": "natraum_lkompvo" },
|
||||||
|
|
||||||
|
{ "id": "lagebezeichnung", "folder": "alkis", "type": "WMS", "title": "Lagebezeichnungen", "url": "https://geo5.service24.rlp.de/wms/liegenschaften_rp.fcgi?", "name": "Lagebezeichnungen" },
|
||||||
|
{ "id": "flurstueck_wms", "folder": "alkis", "type": "WMS", "title": "Flurstücke (WMS)", "url": "https://geo5.service24.rlp.de/wms/liegenschaften_rp.fcgi?", "name": "Flurstueck", "active": true},
|
||||||
|
{ "id": "flurstueck_wfs", "folder": "alkis", "type": "WFS", "title": "Flurstücke (WFS; ab hoher Zoomstufe)", "url": "/client/proxy/wfs?", "name": "ave:Flurstueck", "minZoom": 17},
|
||||||
|
{ "id": "gebaeude", "folder": "alkis", "type": "WMS", "title": "Gebäude / Bauwerke", "url": "https://geo5.service24.rlp.de/wms/liegenschaften_rp.fcgi?", "name": "GebaeudeBauwerke" },
|
||||||
|
{ "id": "nutzung", "folder": "alkis", "type": "WMS", "title": "Nutzung", "url": "https://geo5.service24.rlp.de/wms/liegenschaften_rp.fcgi?", "name": "Nutzung" },
|
||||||
|
|
||||||
|
{ "id": "lk", "folder": "verwaltung", "type": "WMS", "title": "Landkreise", "url": "https://geo5.service24.rlp.de/wms/verwaltungsgrenzen_rp.fcgi?", "name": "Landkreise" },
|
||||||
|
{ "id": "vg", "folder": "verwaltung", "type": "WMS", "title": "Verbandsgemeinden", "url": "https://geo5.service24.rlp.de/wms/verwaltungsgrenzen_rp.fcgi?", "name": "Verbandsgemeinden" },
|
||||||
|
{ "id": "gmd", "folder": "verwaltung", "type": "WMS", "title": "Gemeinden", "url": "https://geo5.service24.rlp.de/wms/verwaltungsgrenzen_rp.fcgi?", "name": "Gemeinden" }
|
||||||
|
],
|
||||||
|
"layertree":
|
||||||
{
|
{
|
||||||
"nameURL": "/client/proxy?https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_alkis/gem_search.php?placename={q}",
|
"open": false,
|
||||||
"parcelURL": "/client/proxy?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",
|
"title": "Inhalte",
|
||||||
|
"buttons":
|
||||||
|
[
|
||||||
|
{ "id": "import_layer", "title": "<i class='netgis-icon fas fa-plus' style='font-size: 1em;'></i><span>Hinzufügen...</span>" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"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": "zoom_home", "icon": "<i class='fas fa-home'></i>", "title": "Anfangsausdehung" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"searchplace":
|
||||||
|
{
|
||||||
|
"title": "Adresse...",
|
||||||
|
"url": "/client/proxy?https://www.geoportal.rlp.de/mapbender/geoportal/gaz_geom_mobile.php?outputFormat=json&resultTarget=web&searchEPSG={epsg}&maxResults=5&maxRows=5&featureClass=P&style=full&searchText={query}&name_startsWith={query}",
|
||||||
|
"zoom": 17,
|
||||||
|
"marker_color": "darkgray",
|
||||||
|
"marker_title": "Such-Ergebnis"
|
||||||
|
},
|
||||||
|
"searchparcel":
|
||||||
|
{
|
||||||
|
"open": false,
|
||||||
|
"name_url": "/client/proxy?https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_alkis/gem_search.php?placename={q}",
|
||||||
|
"parcel_url": "/client/proxy?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":
|
"districts_service":
|
||||||
{
|
{
|
||||||
"type": "WFS",
|
"type": "WFS",
|
||||||
"url": "http://geo5.service24.rlp.de/wfs/verwaltungsgrenzen_rp.fcgi?",
|
"url": "https://geo5.service24.rlp.de/wfs/verwaltungsgrenzen_rp.fcgi?",
|
||||||
"name": "vermkv:gemarkungen_rlp",
|
"name": "vermkv:gemarkungen_rlp",
|
||||||
"order": 10,
|
"format": "application/json; subtype=geojson",
|
||||||
"minZoom": 11,
|
"min_zoom": 12
|
||||||
"maxZoom": 17
|
|
||||||
},
|
},
|
||||||
"fields_service":
|
"fields_service":
|
||||||
{
|
{
|
||||||
"url": "http://geo5.service24.rlp.de/wfs/verwaltungsgrenzen_rp.fcgi?",
|
"url": "https://geo5.service24.rlp.de/wfs/verwaltungsgrenzen_rp.fcgi?",
|
||||||
"name": "vermkv:fluren_rlp",
|
"name": "vermkv:fluren_rlp",
|
||||||
"filter_property": "gmkgnr"
|
"filter_property": "gmkgnr"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"toolbox":
|
||||||
|
{
|
||||||
|
"open": false,
|
||||||
|
"items":
|
||||||
|
[
|
||||||
|
{ "id": "view", "title": "<i class='netgis-icon netgis-text-a fas fa-hand-paper'></i><span>Betrachten</span>" },
|
||||||
|
{ "id": "zoom_box", "title": "<i class='netgis-icon netgis-text-a fas fa-expand'></i><span>Zoom-Rechteck</span>" },
|
||||||
|
{ "id": "view_prev", "title": "<i class='netgis-icon netgis-text-a fas fa-step-backward'></i><span>Vorherige Ansicht</span>" },
|
||||||
|
{ "id": "view_next", "title": "<i class='netgis-icon netgis-text-a fas fa-step-forward'></i><span>Nächste Ansicht</span>" },
|
||||||
|
{ "id": "measure_line", "title": "<i class='netgis-icon netgis-text-a fas fa-ruler'></i><span>Strecke messen</span>" },
|
||||||
|
{ "id": "measure_area", "title": "<i class='netgis-icon netgis-text-a fas fa-ruler-combined'></i><span>Fläche messen</span>" },
|
||||||
|
{ "id": "measure_clear", "title": "<i class='netgis-icon netgis-text-a fas fa-trash-alt'></i><span>Messung löschen</span>" },
|
||||||
|
{ "id": "draw_points", "title": "<i class='netgis-icon netgis-text-a fas fa-map-marker-alt'></i><span>Punkte zeichnen</span>" },
|
||||||
|
{ "id": "draw_lines", "title": "<i class='netgis-icon netgis-text-a fas fa-minus'></i><span>Linien zeichnen</span>" },
|
||||||
|
{ "id": "draw_polygons", "title": "<i class='netgis-icon netgis-text-a fas fa-vector-square'></i><span>Polygone zeichnen</span>" },
|
||||||
|
{ "id": "modify_features", "title": "<i class='netgis-icon netgis-text-a fas fa-arrows-alt'></i><span>Verschieben</span>" },
|
||||||
|
{ "id": "delete_features", "title": "<i class='netgis-icon netgis-text-a fas fa-eraser'></i><span>Löschen</span>" },
|
||||||
|
{ "id": "buffer_features", "title": "<i class='netgis-icon netgis-text-a far fa-dot-circle'></i><span>Puffern</span>" },
|
||||||
|
{ "id": "cut_features", "title": "<i class='netgis-icon netgis-text-a fas fa-cut'></i><span>Ausschneiden</span>" },
|
||||||
|
{ "id": "import_layer", "title": "<i class='netgis-icon netgis-text-a fas fa-upload'></i><span>Importieren</span>" },
|
||||||
|
{ "id": "export", "title": "<i class='netgis-icon netgis-text-a fas fa-save'></i><span>Exportieren</span>" }
|
||||||
|
],
|
||||||
|
"options":
|
||||||
|
{
|
||||||
|
"buffer_features":
|
||||||
|
{
|
||||||
|
"title": "Puffern",
|
||||||
|
"items":
|
||||||
|
[
|
||||||
|
{ "id": "buffer_radius", "type": "integer", "title": "Radius (Meter)" },
|
||||||
|
{ "id": "buffer_segments", "type": "integer", "title": "Segmente" },
|
||||||
|
{ "id": "buffer_submit", "type": "button", "title": "<i class='netgis-icon netgis-text-a fas fa-arrow-circle-right'></i><span>Akzeptieren</span>" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"import":
|
"import":
|
||||||
{
|
{
|
||||||
"geopackageLibURL": "/static/libs/geopackage/4.2.3/"
|
"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?",
|
||||||
|
"geopackage_lib": "/static/libs/geopackage/4.2.3/"
|
||||||
},
|
},
|
||||||
"export":
|
"export":
|
||||||
{
|
{
|
||||||
|
"title": "Exportieren",
|
||||||
"logo": "/static/assets/logo.png",
|
"logo": "/static/assets/logo.png",
|
||||||
"gifWebWorker": "/static/libs/gifjs/0.2.0/gif.worker.js",
|
"gif_worker": "/static/libs/gifjs/0.2.0/gif.worker.js",
|
||||||
"defaultFilename": "Export",
|
"default_filename": "Export",
|
||||||
"defaultMargin": 10
|
"default_margin": 10
|
||||||
|
},
|
||||||
|
"measure":
|
||||||
|
{
|
||||||
|
"line_color": "rgba( 255, 0, 0, 1.0 )",
|
||||||
|
"line_width": 3.0,
|
||||||
|
"line_dash": [ 5, 10 ],
|
||||||
|
"area_fill": "rgba( 255, 0, 0, 0.3 )",
|
||||||
|
"point_radius": 4.0,
|
||||||
|
"point_fill": "rgba( 255, 255, 255, 1.0 )",
|
||||||
|
"point_stroke": "rgba( 0, 0, 0, 1.0 )",
|
||||||
|
"text_color": "#871d33",
|
||||||
|
"text_back": "rgba( 255, 255, 255, 0.7 )"
|
||||||
},
|
},
|
||||||
"tools":
|
"tools":
|
||||||
{
|
{
|
||||||
|
"editable": true,
|
||||||
|
"interactive_render": true,
|
||||||
"buffer":
|
"buffer":
|
||||||
{
|
{
|
||||||
"defaultRadius": 5,
|
"default_radius": 5,
|
||||||
"defaultSegments": 2
|
"default_segments": 3
|
||||||
}
|
},
|
||||||
|
"snapping":
|
||||||
|
{
|
||||||
|
"show": true,
|
||||||
|
"active": true,
|
||||||
|
"tolerance": 35
|
||||||
|
},
|
||||||
|
"bounds_message": "Ausserhalb des erlaubten Bereichs!",
|
||||||
|
"show_bounds": true
|
||||||
|
},
|
||||||
|
"output":
|
||||||
|
{
|
||||||
|
"id": "netgis-storage"
|
||||||
|
},
|
||||||
|
"attribution":
|
||||||
|
{
|
||||||
|
"prefix": "LANIS"
|
||||||
},
|
},
|
||||||
"styles":
|
"styles":
|
||||||
{
|
{
|
||||||
"editLayer":
|
"draw":
|
||||||
{
|
{
|
||||||
"fill": "rgba( 255, 0, 0, 0.2 )",
|
"fill": "rgba( 135, 29, 51, 0.5 )",
|
||||||
"stroke": "#ff0000",
|
"stroke": "#871d33",
|
||||||
"strokeWidth": 3,
|
"width": 3,
|
||||||
"pointRadius": 6
|
"radius": 6,
|
||||||
|
"viewport_labels": true
|
||||||
|
},
|
||||||
|
"non_edit":
|
||||||
|
{
|
||||||
|
"fill": "rgba( 135, 29, 51, 0.5 )",
|
||||||
|
"stroke": "#871d33",
|
||||||
|
"width": 3,
|
||||||
|
"radius": 6,
|
||||||
|
"viewport_labels": true
|
||||||
},
|
},
|
||||||
"select":
|
"select":
|
||||||
{
|
{
|
||||||
"fill": "rgba( 0, 127, 255, 0.5 )",
|
"fill": "rgba( 0, 127, 255, 0.5 )",
|
||||||
"stroke": "#007fff",
|
"stroke": "#007fff",
|
||||||
"strokeWidth": 3,
|
"width": 3,
|
||||||
"pointRadius": 6
|
"radius": 6
|
||||||
},
|
},
|
||||||
"sketch":
|
"sketch":
|
||||||
{
|
{
|
||||||
"fill": "rgba( 0, 127, 255, 0.2 )",
|
"fill": "rgba( 29, 135, 113, 0.5 )",
|
||||||
"stroke": "#0080ff",
|
"stroke": "#1D8771",
|
||||||
"strokeWidth": 3,
|
"width": 3,
|
||||||
"pointRadius": 6
|
"radius": 6
|
||||||
|
},
|
||||||
|
"error":
|
||||||
|
{
|
||||||
|
"fill": "rgba( 255, 0, 0, 0.5 )",
|
||||||
|
"stroke": "#ff0000",
|
||||||
|
"width": 3,
|
||||||
|
"radius": 6
|
||||||
|
},
|
||||||
|
"bounds":
|
||||||
|
{
|
||||||
|
"fill": "rgba( 0, 0, 0, 0.0 )",
|
||||||
|
"stroke": "#000000",
|
||||||
|
"width": 3,
|
||||||
|
"radius": 6
|
||||||
},
|
},
|
||||||
"modify":
|
"modify":
|
||||||
{
|
{
|
||||||
"fill": "rgba( 0, 127, 255, 0.5 )",
|
"fill": "rgba( 29, 135, 113, 0.5 )",
|
||||||
"stroke": "#0080ff",
|
"stroke": "#1D8771",
|
||||||
"strokeWidth": 3,
|
"width": 3,
|
||||||
"pointRadius": 6
|
"radius": 6
|
||||||
},
|
},
|
||||||
"parcel":
|
"parcel":
|
||||||
{
|
{
|
||||||
"fill": "rgba( 127, 255, 255, 0.5 )",
|
"fill": "rgba( 127, 0, 0, 0.2 )",
|
||||||
"stroke": "#7fffff",
|
"stroke": "rgba( 127, 0, 0, 1.0 )",
|
||||||
"strokeWidth": 3
|
"width": 2.5
|
||||||
},
|
},
|
||||||
|
|
||||||
"import":
|
"import":
|
||||||
{
|
{
|
||||||
"fill": "rgba( 0, 127, 255, 0.2 )",
|
"fill": "rgba( 0, 127, 255, 0.2 )",
|
||||||
@@ -172,4 +307,4 @@
|
|||||||
"width": 1.5
|
"width": 1.5
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
1
templates/map/client/dist/netgis.min.css
vendored
Normal file
1
templates/map/client/dist/netgis.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
550
templates/map/client/dist/netgis.min.js
vendored
Normal file
550
templates/map/client/dist/netgis.min.js
vendored
Normal file
@@ -0,0 +1,550 @@
|
|||||||
|
var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.ASSUME_ES5=!1;$jscomp.ASSUME_NO_NATIVE_MAP=!1;$jscomp.ASSUME_NO_NATIVE_SET=!1;$jscomp.SIMPLE_FROUND_POLYFILL=!1;$jscomp.defineProperty=$jscomp.ASSUME_ES5||"function"==typeof Object.defineProperties?Object.defineProperty:function(a,b,c){a!=Array.prototype&&a!=Object.prototype&&(a[b]=c.value)};$jscomp.getGlobal=function(a){return"undefined"!=typeof window&&window===a?a:"undefined"!=typeof global&&null!=global?global:a};$jscomp.global=$jscomp.getGlobal(this);
|
||||||
|
$jscomp.polyfill=function(a,b,c,d){if(b){c=$jscomp.global;a=a.split(".");for(d=0;d<a.length-1;d++){var e=a[d];e in c||(c[e]={});c=c[e]}a=a[a.length-1];d=c[a];b=b(d);b!=d&&null!=b&&$jscomp.defineProperty(c,a,{configurable:!0,writable:!0,value:b})}};$jscomp.polyfill("Number.parseFloat",function(a){return a||parseFloat},"es6","es3");$jscomp.polyfill("Number.parseInt",function(a){return a||parseInt},"es6","es3");
|
||||||
|
$jscomp.arrayIteratorImpl=function(a){var b=0;return function(){return b<a.length?{done:!1,value:a[b++]}:{done:!0}}};$jscomp.arrayIterator=function(a){return{next:$jscomp.arrayIteratorImpl(a)}};$jscomp.SYMBOL_PREFIX="jscomp_symbol_";$jscomp.initSymbol=function(){$jscomp.initSymbol=function(){};$jscomp.global.Symbol||($jscomp.global.Symbol=$jscomp.Symbol)};$jscomp.SymbolClass=function(a,b){this.$jscomp$symbol$id_=a;$jscomp.defineProperty(this,"description",{configurable:!0,writable:!0,value:b})};
|
||||||
|
$jscomp.SymbolClass.prototype.toString=function(){return this.$jscomp$symbol$id_};$jscomp.Symbol=function(){function a(c){if(this instanceof a)throw new TypeError("Symbol is not a constructor");return new $jscomp.SymbolClass($jscomp.SYMBOL_PREFIX+(c||"")+"_"+b++,c)}var b=0;return a}();
|
||||||
|
$jscomp.initSymbolIterator=function(){$jscomp.initSymbol();var a=$jscomp.global.Symbol.iterator;a||(a=$jscomp.global.Symbol.iterator=$jscomp.global.Symbol("Symbol.iterator"));"function"!=typeof Array.prototype[a]&&$jscomp.defineProperty(Array.prototype,a,{configurable:!0,writable:!0,value:function(){return $jscomp.iteratorPrototype($jscomp.arrayIteratorImpl(this))}});$jscomp.initSymbolIterator=function(){}};
|
||||||
|
$jscomp.initSymbolAsyncIterator=function(){$jscomp.initSymbol();var a=$jscomp.global.Symbol.asyncIterator;a||(a=$jscomp.global.Symbol.asyncIterator=$jscomp.global.Symbol("Symbol.asyncIterator"));$jscomp.initSymbolAsyncIterator=function(){}};$jscomp.iteratorPrototype=function(a){$jscomp.initSymbolIterator();a={next:a};a[$jscomp.global.Symbol.iterator]=function(){return this};return a};
|
||||||
|
$jscomp.iteratorFromArray=function(a,b){$jscomp.initSymbolIterator();a instanceof String&&(a+="");var c=0,d={next:function(){if(c<a.length){var e=c++;return{value:b(e,a[e]),done:!1}}d.next=function(){return{done:!0,value:void 0}};return d.next()}};d[Symbol.iterator]=function(){return d};return d};$jscomp.polyfill("Array.prototype.values",function(a){return a?a:function(){return $jscomp.iteratorFromArray(this,function(a,c){return c})}},"es8","es3");
|
||||||
|
$jscomp.polyfill("Number.isNaN",function(a){return a?a:function(a){return"number"===typeof a&&isNaN(a)}},"es6","es3");$jscomp.owns=function(a,b){return Object.prototype.hasOwnProperty.call(a,b)};$jscomp.assign="function"==typeof Object.assign?Object.assign:function(a,b){for(var c=1;c<arguments.length;c++){var d=arguments[c];if(d)for(var e in d)$jscomp.owns(d,e)&&(a[e]=d[e])}return a};$jscomp.polyfill("Object.assign",function(a){return a||$jscomp.assign},"es6","es3");var netgis=netgis||{};
|
||||||
|
netgis.Attribution=function(a){this.config=a;this.layers=this.client=null;this.items=[];this.initElements(a);this.initConfig(a)};netgis.Attribution.Config={prefix:"NetGIS"};netgis.Attribution.prototype.initElements=function(a){this.container=document.createElement("section");this.container.className="netgis-attribution netgis-text-a";var b=this;window.setTimeout(function(){b.update()},100)};
|
||||||
|
netgis.Attribution.prototype.initConfig=function(a){if(a&&(a.attribution&&a.attribution.prefix&&this.items.push(a.attribution.prefix),a=a.layers))for(var b=0;b<a.length;b++){var c=a[b],d=c.attribution;d&&0!==d.length&&c.active&&this.items.push(d)}};
|
||||||
|
netgis.Attribution.prototype.attachTo=function(a){a.appendChild(this.container);a.addEventListener(netgis.Events.CLIENT_CONTEXT_RESPONSE,this.onContextUpdate.bind(this));a.addEventListener(netgis.Events.MAP_LAYER_TOGGLE,this.onMapLayerToggle.bind(this));a.addEventListener(netgis.Events.MAP_EDIT_LAYER_CHANGE,this.onEditLayerChange.bind(this))};netgis.Attribution.prototype.update=function(){var a="© "+this.items.join(", ");this.appendix&&(a+=", "+this.appendix);this.container.innerHTML=a};
|
||||||
|
netgis.Attribution.prototype.add=function(a){for(var b=0;b<this.items.length;b++)if(this.items[b]===a)return;this.items.push(a);this.update()};netgis.Attribution.prototype.remove=function(a){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.onMapLayerToggle=function(a){a=a.detail;for(var b=this.config.layers,c=null,d=0;d<b.length;d++){var e=b[d];e.id===a.id&&(c=e.attribution)}c&&(a.on?this.add(c):this.remove(c))};
|
||||||
|
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)};
|
||||||
|
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,
|
||||||
|
projection:"EPSG:25832",extent:"map",scales:"map",transparency:0};a.layers.push(d)}c.URL_BACKGROUND_AERIAL&&(d=c.URL_BACKGROUND_AERIAL,d={id:"bg_aerial",folder:"bg",order:1,title:"Luftbild",type:"WMS",url:d,query:!1,transparency:0},a.layers.push(d));c.URL_HEIGHT_REQUEST&&(d=c.URL_HEIGHT_REQUEST,-1===d.indexOf("{x}")&&-1===d.indexOf("{y}")&&(d+="&coord={x},{y}"),d={id:"dem_hidden",title:"Digitales H\u00f6henmodell",hidden:!0,active:!0,query:!0,type:"HIDDEN",query_url:d},a.layers.push(d));a.layertree||
|
||||||
|
(a.layertree={});a.layertree.title="Ebenen";a.info||(a.info={});a.info.default_format="text/html";c.URL_FEATURE_INFO_PROXY&&0<c.URL_FEATURE_INFO_PROXY.length&&(a.info.proxy=c.URL_FEATURE_INFO_PROXY);a.menu||(a.menu={header:"GeoPortal",compact:!0,items:[{title:"<i class='fas fa-tools'></i><span>Tools</span>",items:[{id:"view",title:"<i class='netgis-icon fas fa-hand-paper'></i><span>Betrachten</span>"},{id:"zoom_box",title:"<i class='netgis-icon fas fa-expand'></i><span>Zoom-Rechteck</span>"},{id:"measure_line",
|
||||||
|
title:"<i class='netgis-icon fas fa-ruler'></i><span>Strecke messen</span>"},{id:"measure_area",title:"<i class='netgis-icon fas fa-ruler-combined'></i><span>Fl\u00e4che messen</span>"},{id:"measure_clear",title:"<i class='netgis-icon fas fa-trash-alt'></i><span>Messung l\u00f6schen</span>"}]},{id:"layertree",title:"<i class='fas fa-layer-group'></i><span>Ebenen</span>"}]},c.MAP_SCALES&&0<c.MAP_SCALES.length&&a.menu.items.unshift({title:"<i class='far fa-eye'></i><span>Ansicht</span>",items:[{id:"view_prev",
|
||||||
|
title:"<i class='fas fa-step-backward'></i><span>Vorherige</span>"},{id:"view_next",title:"<i class='fas fa-step-forward'></i><span>N\u00e4chste</span>"},{id:"scales",title:"<i class='fas fa-ruler-horizontal'></i><span>Ma\u00dfstab</span><i class='fas fa-caret-right'></i>",items:[]}]}),c.URL_USAGE_TERMS&&0<c.URL_USAGE_TERMS.length&&a.menu.items.unshift({title:"<i class='fas fa-info-circle'></i><span>Info</span>",items:[{url:c.URL_USAGE_TERMS,title:"<i class='fas fa-external-link-alt'></i><span>Nutzungsbedingungen</span>"}]}));
|
||||||
|
c.URL_SEARCH_REQUEST&&(d=c.URL_SEARCH_REQUEST,-1===d.indexOf("{query}")&&(d+="?outputFormat=json&resultTarget=web&searchEPSG=4326&maxResults=5&maxRows=5&featureClass=P&style=full&searchText={query}&name_startsWith={query}"),c.URL_SEARCH_PROXY&&0<c.URL_SEARCH_PROXY.length&&(d=c.URL_SEARCH_PROXY+"?"+d),a.menu.items.unshift({id:"searchplace",title:"<i class='fas fa-search'></i><span>Suche</span>"}),a.searchplace={title:"Suche...",url:d});a.wmc||(a.wmc={});if(c.URL_WMC_REQUEST){d=c.URL_WMC_REQUEST;if(-1===
|
||||||
|
d.indexOf("{id}")){var e="mobilemap2";c.CONF_FILE_NAME&&0<c.CONF_FILE_NAME.length&&(e=c.CONF_FILE_NAME);d+="?confFileName="+e+"&epsg=25832&withHierarchy=1&wmc_id={id}"}c.URL_WMC_PROXY&&0<c.URL_WMC_PROXY.length&&(d=c.URL_WMC_PROXY+"?"+d);a.wmc.url=d}c.URL_LAYERS_REQUEST&&(d=c.URL_LAYERS_REQUEST,-1===d.indexOf("{ids}")&&(d+="?languageCode=de&resultTarget=web&maxResults=40&resourceIds={ids}"),c.URL_LAYERS_PROXY&&0<c.URL_LAYERS_PROXY.length&&(d=c.URL_LAYERS_PROXY+"?"+d),a.wmc.layers_url=d);return b};
|
||||||
|
netgis.Client.prototype.initContainer=function(a){netgis.util.isString(a)&&(a=document.getElementById(a));a.classList.add("netgis-client","netgis-font");return a};
|
||||||
|
netgis.Client.prototype.initParams=function(a){var b=window.location.search.substr(1);b=b.split("&");this.params={};for(var c=0;c<b.length;c++){var d=b[c].split("="),e=d[0].toLowerCase();d=d[1];e&&""!==e&&(this.params[e]=d)}for(e in this.params)switch(d=this.params[e],e){case "wmc_id":a.wmc&&(a.wmc.id=d);break;case "layerid":a&&a.wmc&&a.wmc.layers_url&&(b=a.wmc.layers_url,b=netgis.util.replace(b,"{ids}",d),netgis.util.request(b,this.onContextResponseLayer.bind(this)))}};
|
||||||
|
netgis.Client.prototype.initConfig=function(a){a&&a.wmc&&a.wmc.url&&this.requestContextWMC(a.wmc.url,a.wmc.id);a&&a.ows&&a.ows.url&&this.requestContextOWS(a.ows.url)};
|
||||||
|
netgis.Client.prototype.initElements=function(a){if(a.hasAttribute("data-lon")){var b=Number.parseFloat(a.getAttribute("data-lon"));this.config.map.center_lonlat||(this.config.map.center_lonlat=[]);this.config.map.center_lonlat[0]=b}a.hasAttribute("data-lat")&&(b=Number.parseFloat(a.getAttribute("data-lat")),this.config.map.center_lonlat||(this.config.map.center_lonlat=[]),this.config.map.center_lonlat[1]=b);a.hasAttribute("data-zoom")&&(b=Number.parseFloat(a.getAttribute("data-zoom")),this.config.map.zoom=
|
||||||
|
b);a.hasAttribute("data-bounds")&&(b=a.getAttribute("data-bounds"),this.config.tools.bounds=b);a.hasAttribute("data-editable")&&(a="true"===a.getAttribute("data-editable"),this.config.tools||(this.config.tools={}),this.config.tools.editable=a)};
|
||||||
|
netgis.Client.prototype.initOutput=function(a){var b;if(a.output&&a.output.id){var c=a.output.id;console.warn('config[ "output" ][ "id" ] is deprecated, use config[ "tools" ][ "output_id" ] instead')}a.tools&&(a.tools.output_id&&(c=a.tools.output_id),a.tools.output_name&&(b=a.tools.output_name));if(c){if((a=document.getElementById(c))&&a.value&&0<a.value.length){var d=JSON.parse(a.value);netgis.util.invoke(this.container,netgis.Events.MAP_EDIT_LAYER_LOADED,{geojson:d})}this.output=a}this.output||
|
||||||
|
(this.output=document.createElement("input"),this.output.className="netgis-storage",this.output.setAttribute("type","hidden"),c&&this.output.setAttribute("id",c),b&&this.output.setAttribute("name",b),this.container.appendChild(this.output))};
|
||||||
|
netgis.Client.prototype.initModules=function(a){this.modules={};if(a=a.modules)a.map&&this.addModule("map",netgis.Map),a.controls&&this.addModule("controls",netgis.Controls),a.attribution&&this.addModule("attribution",netgis.Attribution),a.legend&&this.addModule("legend",netgis.Legend),a.geolocation&&this.addModule("geolocation",netgis.Geolocation),a.info&&this.addModule("info",netgis.Info),a.menu&&this.addModule("menu",netgis.Menu),a.layertree&&this.addModule("layertree",netgis.LayerTree),a.searchplace&&
|
||||||
|
this.addModule("searchplace",netgis.SearchPlace),a.searchparcel&&this.addModule("searchparcel",netgis.SearchParcel),a.toolbox&&this.addModule("toolbox",netgis.Toolbox),a["import"]&&this.addModule("import",netgis.Import),a["export"]&&this.addModule("export",netgis.Export),a.timeslider&&this.addModule("timeslider",netgis.TimeSlider),a.plugins&&this.addModule("plugins",netgis.Plugins)};
|
||||||
|
netgis.Client.prototype.initEvents=function(){this.container.addEventListener(void 0,function(a){console.error("undefined event invoked",a)});for(var a in netgis.Events)this.container.addEventListener(netgis.Events[a],this.handleEvent.bind(this));this.container.addEventListener(netgis.Events.MAP_EDIT_LAYER_CHANGE,this.onMapEditLayerChange.bind(this))};
|
||||||
|
netgis.Client.prototype.showLoader=function(a){this.loader||(this.loader=document.createElement("div"),this.loader.className="netgis-loader netgis-color-e netgis-text-a",this.loader.innerHTML="<i class='fas fa-cog'></i>",this.config&&this.config.client&&this.config.client.loading_text&&(this.loader.innerHTML+="<h2>"+this.config.client.loading_text+"</h2>"),this.container.appendChild(this.loader));!1===a?(this.loader.classList.add("netgis-fade"),this.loaderTimeout=window.setTimeout(function(){this.loader.classList.add("netgis-hide");
|
||||||
|
this.loaderTimeout=null}.bind(this),600)):(this.loader.classList.remove("netgis-hide"),this.loader.classList.remove("netgis-fade"),this.loaderTimeout&&(window.clearTimeout(this.loaderTimeout),this.loaderTimeout=null))};netgis.Client.prototype.handleEvent=function(a){var b=a.type;a=a.detail;!0===this.debug&&console.info("EVENT:",b,a)};netgis.Client.prototype.addModule=function(a,b){b=new b(this.config);b.attachTo&&b.attachTo(this.container);return this.modules[a]=b};
|
||||||
|
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.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});
|
||||||
|
break;case netgis.Commands.ZOOM_SCALE:c=Number.parseInt(a.innerText.split(":")[1]);netgis.util.invoke(a,netgis.Events.MAP_ZOOM_SCALE,{scale:c,anim:!0});break;case netgis.Commands.MEASURE_LINE:netgis.util.invoke(a,netgis.Events.CLIENT_SET_MODE,{mode:netgis.Modes.MEASURE_LINE});break;case netgis.Commands.MEASURE_AREA:netgis.util.invoke(a,netgis.Events.CLIENT_SET_MODE,{mode:netgis.Modes.MEASURE_AREA});break;case netgis.Commands.MEASURE_CLEAR:netgis.util.invoke(a,netgis.Events.MEASURE_CLEAR,null);break;
|
||||||
|
case netgis.Commands.DRAW_POINTS:netgis.util.invoke(a,netgis.Events.CLIENT_SET_MODE,{mode:netgis.Modes.DRAW_POINTS});break;case netgis.Commands.DRAW_LINES:netgis.util.invoke(a,netgis.Events.CLIENT_SET_MODE,{mode:netgis.Modes.DRAW_LINES});break;case netgis.Commands.DRAW_POLYGONS:netgis.util.invoke(a,netgis.Events.CLIENT_SET_MODE,{mode:netgis.Modes.DRAW_POLYGONS});break;case netgis.Commands.MODIFY_FEATURES:netgis.util.invoke(a,netgis.Events.CLIENT_SET_MODE,{mode:netgis.Modes.MODIFY_FEATURES});break;
|
||||||
|
case netgis.Commands.DELETE_FEATURES:netgis.util.invoke(a,netgis.Events.CLIENT_SET_MODE,{mode:netgis.Modes.DELETE_FEATURES});break;case netgis.Commands.BUFFER_FEATURES:netgis.util.invoke(a,netgis.Events.CLIENT_SET_MODE,{mode:netgis.Modes.BUFFER_FEATURES_DYNAMIC});break;case netgis.Commands.CUT_FEATURES:netgis.util.invoke(a,netgis.Events.CLIENT_SET_MODE,{mode:netgis.Modes.CUT_FEATURES});break;case netgis.Commands.IMPORT_LAYER:netgis.util.invoke(a,netgis.Events.IMPORT_LAYER_SHOW,null);break;case netgis.Commands.EXPORT:netgis.util.invoke(a,
|
||||||
|
netgis.Events.EXPORT_SHOW,null);break;case netgis.Commands.GEOLOCATION:netgis.util.invoke(a,netgis.Events.GEOLOCATION_SHOW_OPTIONS,null);break;default:console.error("unhandled command id",b)}};netgis=netgis||{};
|
||||||
|
netgis.Commands={PLUGIN:"PLUGIN",LAYERTREE:"LAYERTREE",SEARCHPLACE:"SEARCHPLACE",SEARCHPARCEL:"SEARCHPARCEL",TOOLBOX:"TOOLBOX",LEGEND:"LEGEND",VIEW_PREV:"VIEW_PREV",VIEW_NEXT:"VIEW_NEXT",VIEW:"VIEW",ZOOM_BOX:"ZOOM_BOX",ZOOM_SCALE:"ZOOM_SCALE",MEASURE_LINE:"MEASURE_LINE",MEASURE_AREA:"MEASURE_AREA",MEASURE_CLEAR:"MEASURE_CLEAR",DRAW_POINTS:"DRAW_POINTS",DRAW_LINES:"DRAW_LINES",DRAW_POLYGONS:"DRAW_POLYGONS",MODIFY_FEATURES:"MODIFY_FEATURES",DELETE_FEATURES:"DELETE_FEATURES",BUFFER_FEATURES:"BUFFER_FEATURES",CUT_FEATURES:"CUT_FEATURES",
|
||||||
|
SNAP_TOGGLE:"SNAP_TOGGLE",IMPORT_LAYER:"IMPORT_LAYER",EXPORT:"EXPORT",GEOLOCATION:"GEOLOCATION"};netgis=netgis||{};netgis.ContextMenu=function(){this.initElements()};netgis.ContextMenu.prototype.initElements=function(){this.container=document.createElement("div");this.container.className="netgis-contextmenu netgis-shadow-large netgis-color-e netgis-hide"};
|
||||||
|
netgis.ContextMenu.prototype.attachTo=function(a){a.appendChild(this.container);a.addEventListener(netgis.Events.CONTEXTMENU_SHOW,this.onContextMenuShow.bind(this));a.addEventListener("click",this.onParentClick.bind(this));a.addEventListener("pointerup",this.onParentClick.bind(this));a.addEventListener("scroll",this.onParentScroll.bind(this),!0);a.addEventListener("keydown",this.onParentKeyDown.bind(this))};netgis.ContextMenu.prototype.clear=function(){this.container.innerHTML=""};
|
||||||
|
netgis.ContextMenu.prototype.addButton=function(a,b){var c=document.createElement("button");c.className="netgis-button netgis-clip-text netgis-hover-d";c.innerHTML=b;c.setAttribute("type","button");c.setAttribute("data-id",a);c.addEventListener("click",this.onButtonClick.bind(this));this.container.appendChild(c);return c};
|
||||||
|
netgis.ContextMenu.prototype.addCheckbox=function(a,b,c){var d=document.createElement("label");d.className="netgis-noselect netgis-hover-d";var e=document.createElement("input");e.setAttribute("type","checkbox");e.setAttribute("title",b);e.setAttribute("data-id",a);e.checked=c;e.addEventListener("change",this.onCheckboxChange.bind(this));d.appendChild(e);a=document.createElement("span");a.className="netgis-clip-text";a.innerHTML=b;d.appendChild(a);this.container.appendChild(d);return e};
|
||||||
|
netgis.ContextMenu.prototype.addSlider=function(a,b,c,d,e,f){var g=document.createElement("label");g.className="netgis-noselect netgis-hover-d";var h=document.createElement("span");h.className="netgis-clip-text";h.innerHTML=b;g.appendChild(h);h=document.createElement("span");g.appendChild(h);c||0===c||(c=50);d||0===d||(d=0);e||0===e||(e=100);f||(f=1);var k=document.createElement("input");k.setAttribute("type","range");k.setAttribute("min",d);k.setAttribute("max",e);k.setAttribute("step",f);k.setAttribute("value",
|
||||||
|
c);k.setAttribute("data-id",a);k.setAttribute("data-title",b);k.setAttribute("title",b+" "+c);k.addEventListener("change",this.onSliderChange.bind(this));k.addEventListener("input",this.onSliderChange.bind(this));h.appendChild(k);this.container.appendChild(g);return k};netgis.ContextMenu.prototype.setVisible=function(a){a?this.container.classList.remove("netgis-hide"):this.container.classList.add("netgis-hide")};
|
||||||
|
netgis.ContextMenu.prototype.setPosition=function(a,b){var c=this.container.parentNode.getBoundingClientRect(),d=this.container.getBoundingClientRect();a+d.width>c.width&&(a-=d.width);b+d.height>c.height&&(b-=d.height);this.container.style.left=a+"px";this.container.style.top=b+"px"};
|
||||||
|
netgis.ContextMenu.prototype.onContextMenuShow=function(a){a=a.detail;this.clear();for(var b=0;b<a.items.length;b++){var c=a.items[b];switch(c.type){case "slider":this.addSlider(c.id,c.title,c.val,c.min,c.max)}}this.setVisible(!0);this.setPosition(a.x,a.y)};netgis.ContextMenu.prototype.onContextMenu=function(a){a.preventDefault();var b=a.clientX;a=a.clientY;this.setVisible(!0);this.setPosition(b,a);return!1};
|
||||||
|
netgis.ContextMenu.prototype.onParentClick=function(a){this.container.contains(a.target)||this.setVisible(!1)};netgis.ContextMenu.prototype.onParentScroll=function(a){this.setVisible(!1)};netgis.ContextMenu.prototype.onParentKeyDown=function(a){27===(a.keyCode||a.which)&&this.setVisible(!1)};
|
||||||
|
netgis.ContextMenu.prototype.onButtonClick=function(a){a=a.currentTarget;var b=a.getAttribute("data-id");this.setVisible(!1);netgis.util.invoke(a,netgis.Events.CONTEXTMENU_BUTTON_CLICK,{id:b});netgis.Client.handleCommand(a,b)};netgis.ContextMenu.prototype.onCheckboxChange=function(a){a=a.currentTarget;var b=a.getAttribute("data-id");netgis.util.invoke(a,netgis.Events.CONTEXTMENU_CHECKBOX_CHANGE,{id:b,checked:a.checked})};
|
||||||
|
netgis.ContextMenu.prototype.onSliderChange=function(a){a=a.currentTarget;var b=a.getAttribute("data-id"),c=Number.parseFloat(a.value),d=a.getAttribute("data-title");a.setAttribute("title",d+" "+c);netgis.util.invoke(a,netgis.Events.CONTEXTMENU_SLIDER_CHANGE,{id:b,val:c})};netgis=netgis||{};netgis.Controls=function(a){this.config=a;this.initElements(a);this.initConfig(a)};netgis.Controls.Config={buttons:[]};
|
||||||
|
netgis.Controls.prototype.initElements=function(a){this.container=document.createElement("section");this.container.className="netgis-controls netgis-color-e netgis-text-a netgis-shadow netgis-round";if(a&&a.modules&&!0===a.modules.geolocation){this.popupGeoloc=new netgis.Popup({direction:"right"});this.popupGeoloc.container.style.width="60mm";this.popupGeoloc.setHeader("Ger\u00e4te-Standort");a=document.createElement("label");a.className="netgis-hover-d netgis-clip-text netgis-clickable netgis-noselect";
|
||||||
|
var b=document.createElement("input");b.setAttribute("type","checkbox");b.addEventListener("change",this.onInputGeolocActiveChange.bind(this));a.appendChild(b);this.inputGeolocActive=b;b=document.createElement("span");b.innerHTML="Aktiviert";a.appendChild(b);this.popupGeoloc.wrapper.appendChild(a);a=document.createElement("label");a.className="netgis-hover-d netgis-clip-text netgis-clickable netgis-noselect";b=document.createElement("input");b.setAttribute("type","checkbox");b.addEventListener("change",
|
||||||
|
this.onInputGeolocCenterChange.bind(this));a.appendChild(b);this.inputGeolocCenter=b;b=document.createElement("span");b.innerHTML="Zentriert";a.appendChild(b);this.popupGeoloc.wrapper.appendChild(a)}};netgis.Controls.prototype.initConfig=function(a){if(a=a.controls)if(a=a.buttons)for(var b=0;b<a.length;b++){var c=a[b];this.addButton(c.id,c.icon,c.title)}};
|
||||||
|
netgis.Controls.prototype.attachTo=function(a){a.appendChild(this.container);this.popupGeoloc&&this.popupGeoloc.attachTo(a);a.addEventListener(netgis.Events.GEOLOCATION_SHOW_OPTIONS,this.onGeolocShowOptions.bind(this));a.addEventListener(netgis.Events.GEOLOCATION_TOGGLE_ACTIVE,this.onGeolocToggleActive.bind(this));a.addEventListener(netgis.Events.GEOLOCATION_TOGGLE_CENTER,this.onGeolocToggleCenter.bind(this));a.addEventListener("pointerdown",this.onParentPointerDown.bind(this))};
|
||||||
|
netgis.Controls.prototype.addButton=function(a,b,c){var d=document.createElement("button");d.setAttribute("type","button");d.setAttribute("data-id",a);d.className="netgis-hover-a";d.innerHTML=b;d.title=c;d.addEventListener("pointerdown",this.onButtonClick.bind(this));this.container.appendChild(d);return d};
|
||||||
|
netgis.Controls.prototype.onButtonClick=function(a){a=a.currentTarget;var b=a.getAttribute("data-id");switch(b){case "zoom_in":netgis.util.invoke(a,netgis.Events.MAP_ZOOM,{delta:1});break;case "zoom_out":netgis.util.invoke(a,netgis.Events.MAP_ZOOM,{delta:-1});break;case "zoom_home":netgis.util.invoke(a,netgis.Events.MAP_ZOOM_HOME,null);break;default:netgis.Client.handleCommand(a,b)}};
|
||||||
|
netgis.Controls.prototype.onGeolocShowOptions=function(a){a=this.container.getElementsByTagName("button");for(var b=null,c=0;c<a.length;c++){var d=a[c].getAttribute("data-id");if(d&&d.toUpperCase()===netgis.Commands.GEOLOCATION){b=a[c];break}}b&&(this.popupGeoloc.isVisible()?this.popupGeoloc.hide():(this.popupGeoloc.show(),a=b.getBoundingClientRect(),this.popupGeoloc.setPosition(a.x+4,a.y+.3*a.height)))};
|
||||||
|
netgis.Controls.prototype.onParentPointerDown=function(a){netgis.util.insideElement(this.container,a.clientX,a.clientY)||this.popupGeoloc&&this.popupGeoloc.hide()};netgis.Controls.prototype.onInputGeolocActiveChange=function(a){a=a.currentTarget;netgis.util.invoke(a,netgis.Events.GEOLOCATION_TOGGLE_ACTIVE,{on:a.checked})};netgis.Controls.prototype.onInputGeolocCenterChange=function(a){a=a.currentTarget;netgis.util.invoke(a,netgis.Events.GEOLOCATION_TOGGLE_CENTER,{on:a.checked})};
|
||||||
|
netgis.Controls.prototype.onGeolocToggleActive=function(a){a.target!==this.inputGeolocActive&&(this.inputGeolocActive.checked=a.detail.on)};netgis.Controls.prototype.onGeolocToggleCenter=function(a){a.target!==this.inputGeolocCenter&&(this.inputGeolocCenter.checked=a.detail.on)};netgis=netgis||{};
|
||||||
|
netgis.Events={CLIENT_CONTEXT_RESPONSE:"client-context-response",CLIENT_SET_MODE:"client-set-mode",PLUGIN_TOGGLE:"plugin-toggle",CONTROLS_BUTTON_CLICK:"controls-button-click",MAP_ZOOM:"map-zoom",MAP_ZOOM_HOME:"map-zoom-home",MAP_ZOOM_LONLAT:"map-zoom-lonlat",MAP_ZOOM_SCALE:"map-zoom-scale",MAP_ZOOM_LAYER:"map-zoom-layer",MAP_ZOOM_LEVEL:"map-zoom-level",MAP_LAYER_CREATE:"map-layer-create",MAP_LAYER_TOGGLE:"map-layer-toggle",MAP_LAYER_TRANSPARENCY:"map-layer-transparency",MAP_LAYER_ORDER:"map-layer-order",MAP_LAYER_DELETE:"map-layer-delete",
|
||||||
|
MAP_VIEW_CHANGE:"map-view-change",MAP_VIEW_NEXT:"map-view-next",MAP_VIEW_PREV:"map-view-prev",MAP_CLICK:"map-click",MAP_FEATURE_ENTER:"map-feature-enter",MAP_FEATURE_CLICK:"map-feature-click",MAP_FEATURE_LEAVE:"map-feature-leave",MAP_SNAP_TOGGLE:"map-snap-toggle",MAP_EDIT_LAYER_CHANGE:"map-edit-layer-change",MAP_EDIT_LAYER_LOADED:"map-edit-layer-loaded",MAP_COPY_FEATURE_TO_EDIT:"map-copy-feature-to-edit",PANEL_TOGGLE:"panel-toggle",PANEL_RESIZE:"panel-resize",WINDOW_TOGGLE:"window-toggle",WINDOW_RESIZE:"window-resize",
|
||||||
|
TREE_ITEM_CHANGE:"tree-item-change",TREE_ITEM_SLIDER_CHANGE:"tree-item-slider-change",TREE_ITEM_ORDER_CHANGE:"tree-item-order-change",TREE_BUTTON_CLICK:"tree-button-click",LAYERTREE_TOGGLE:"layertree-toggle",LEGEND_TOGGLE:"legend-toggle",GEOLOCATION_SHOW_OPTIONS:"geolocation-show-options",GEOLOCATION_TOGGLE_ACTIVE:"geolocation-toggle-active",GEOLOCATION_TOGGLE_CENTER:"geolocation-toggle-center",GEOLOCATION_CHANGE:"geolocation-change",TOOLBOX_TOGGLE:"toolbox-toggle",TOOLBOX_BUTTON_CLICK:"toolbox-button-click",
|
||||||
|
MENU_BUTTON_CLICK:"menu-button-click",MENU_CHECKBOX_CHANGE:"menu-checkbox-change",MENU_SELECT_CHANGE:"menu-select-change",CONTEXTMENU_SHOW:"contextmenu-show",CONTEXTMENU_BUTTON_CLICK:"contextmenu-button-click",CONTEXTMENU_CHECKBOX_CHANGE:"contextmenu-checkbox-change",CONTEXTMENU_SLIDER_CHANGE:"contextmenu-slider-change",SEARCH_CHANGE:"search-change",SEARCH_SELECT:"search-select",SEARCH_CLEAR:"search-clear",SEARCHPLACE_TOGGLE:"searchplace-toggle",SEARCHPARCEL_TOGGLE:"searchparcel-toggle",SEARCHPARCEL_RESET:"searchparcel-reset",
|
||||||
|
SEARCHPARCEL_PARCELS_RESPONSE:"searchparcel-parcels-response",SEARCHPARCEL_ITEM_ENTER:"searchparcel-item-enter",SEARCHPARCEL_ITEM_LEAVE:"searchparcel-item-leave",SEARCHPARCEL_ITEM_CLICK:"searchparcel-item-click",SEARCHPARCEL_ITEM_IMPORT:"searchparcel-item-import",MEASURE_CLEAR:"measure-clear",SELECT_MULTI_TOGGLE:"select-multi-toggle",DRAW_BUFFER_TOGGLE:"draw-buffer-toggle",DRAW_BUFFER_CHANGE:"draw-buffer-change",BUFFER_CHANGE:"buffer-change",BUFFER_ACCEPT:"buffer-accept",IMPORT_LAYER_SHOW:"import-layer-show",
|
||||||
|
IMPORT_LAYER_ACCEPT:"import-layer-accept",IMPORT_LAYER_PREVIEW:"import-layer-preview",IMPORT_LAYER_PREVIEW_FEATURES:"import-layer-preview-features",IMPORT_GEOPORTAL_SUBMIT:"import-geoportal-submit",EXPORT_SHOW:"export-show",EXPORT_BEGIN:"export-begin",EXPORT_END:"export-end",TIMESLIDER_SHOW:"timeslider-show",TIMESLIDER_HIDE:"timeslider-hide",TIMESLIDER_SELECT:"timeslider-select"};netgis=netgis||{};netgis.Export=function(a){this.config=a;this.initElements(a);this.initSections()};netgis.Export.Config={title:"Export",logo:"",gif_worker:"/libs/gifjs/0.2.0/gif.worker.js",default_filename:"Export",default_margin:10};
|
||||||
|
netgis.Export.prototype.initElements=function(a){a=a["export"];this.modal=new netgis.Modal(a.title?a.title:"Export");this.modal.container.classList.add("netgis-export");this.tabs=new netgis.Tabs(["PDF","JPEG","PNG","GIF","GeoJSON"]);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.Export.prototype.initSections=function(){this.sections={};var a=0;this.sections.pdf=this.tabs.getContentSection(a);a+=1;this.addInputNumber(this.sections.pdf,"Breite (Pixel):",1600,0);this.addInputNumber(this.sections.pdf,"H\u00f6he (Pixel):",900,0);this.addInputNumber(this.sections.pdf,"Seitenr\u00e4nder (Millimeter):",10,0);this.addCheckbox(this.sections.pdf,"Querformat",!0);this.addButton(this.sections.pdf,"<i class='netgis-icon fas fa-save'></i><span>Exportieren</span>",this.onExportClickPDF.bind(this));
|
||||||
|
this.sections.jpeg=this.tabs.getContentSection(a);a+=1;this.addInputNumber(this.sections.jpeg,"Breite (Pixel):",1600,0);this.addInputNumber(this.sections.jpeg,"H\u00f6he (Pixel):",900,0);this.addCheckbox(this.sections.jpeg,"Querformat",!0);this.addButton(this.sections.jpeg,"<i class='netgis-icon fas fa-save'></i><span>Exportieren</span>",this.onExportClickJPEG.bind(this));this.sections.png=this.tabs.getContentSection(a);a+=1;this.addInputNumber(this.sections.png,"Breite (Pixel):",1600,0);this.addInputNumber(this.sections.png,
|
||||||
|
"H\u00f6he (Pixel):",900,0);this.addCheckbox(this.sections.png,"Querformat",!0);this.addButton(this.sections.png,"<i class='netgis-icon fas fa-save'></i><span>Exportieren</span>",this.onExportClickPNG.bind(this));this.sections.gif=this.tabs.getContentSection(a);a+=1;this.addInputNumber(this.sections.gif,"Breite (Pixel):",1600,0);this.addInputNumber(this.sections.gif,"H\u00f6he (Pixel):",900,0);this.addCheckbox(this.sections.gif,"Querformat",!0);this.addButton(this.sections.gif,"<i class='netgis-icon fas fa-save'></i><span>Exportieren</span>",
|
||||||
|
this.onExportClickGIF.bind(this));this.sections.geojson=this.tabs.getContentSection(a);this.addCheckbox(this.sections.geojson,"Nicht-Editierbare Geometrien einbeziehen",!1);this.addButton(this.sections.geojson,"<i class='netgis-icon fas fa-save'></i><span>Exportieren</span>",this.onExportClickGeoJSON.bind(this))};
|
||||||
|
netgis.Export.prototype.attachTo=function(a){a.appendChild(this.modal.container);a.addEventListener(netgis.Events.EXPORT_SHOW,this.onExportShow.bind(this));a.addEventListener(netgis.Events.EXPORT_END,this.onExportEnd.bind(this))};netgis.Export.prototype.addText=function(a,b){var c=document.createElement("div");c.innerHTML=b;a.appendChild(c);return c};
|
||||||
|
netgis.Export.prototype.addButton=function(a,b,c){var d=document.createElement("button");d.className="netgis-button netgis-center netgis-color-a netgis-hover-c netgis-shadow";d.setAttribute("type","button");d.innerHTML=b;c&&(d.onclick=c);a.appendChild(d);return d};
|
||||||
|
netgis.Export.prototype.addInputText=function(a,b,c){var d=document.createElement("label");d.innerHTML=b;var e=document.createElement("input");e.setAttribute("type","text");d.appendChild(e);if(c){b="list-"+netgis.util.stringToID(b);var f=document.createElement("datalist");f.setAttribute("id",b);for(var g=0;g<c.length;g++){var h=document.createElement("option");h.setAttribute("value",c[g]);f.appendChild(h)}a.appendChild(f);e.setAttribute("list",b)}a.appendChild(d);return e};
|
||||||
|
netgis.Export.prototype.addInputNumber=function(a,b,c,d,e){var f=document.createElement("label");f.innerHTML=b;b=document.createElement("input");b.setAttribute("type","number");(d||0===d)&&b.setAttribute("min",d);e&&b.setAttribute("max",e);b.setAttribute("value",c);f.appendChild(b);a.appendChild(f);return b};
|
||||||
|
netgis.Export.prototype.addCheckbox=function(a,b,c){var d=document.createElement("label"),e=document.createElement("input");e.setAttribute("type","checkbox");e.checked=c;d.appendChild(e);c=document.createElement("span");c.innerHTML=b;d.appendChild(c);a.appendChild(d);return e};netgis.Export.prototype.onExportShow=function(a){this.modal.show()};
|
||||||
|
netgis.Export.prototype.onExportClickPDF=function(a){var b=this.sections.pdf.getElementsByTagName("input");b={format:"pdf",width:Number.parseInt(b[0].value),height:Number.parseInt(b[1].value),padding:Number.parseInt(b[2].value),landscape:b[3].checked};netgis.util.invoke(a.target,netgis.Events.EXPORT_BEGIN,b)};
|
||||||
|
netgis.Export.prototype.onExportClickJPEG=function(a){var b=this.sections.pdf.getElementsByTagName("input");b={format:"jpeg",width:Number.parseInt(b[0].value),height:Number.parseInt(b[1].value),landscape:b[3].checked};netgis.util.invoke(a.target,netgis.Events.EXPORT_BEGIN,b)};
|
||||||
|
netgis.Export.prototype.onExportClickPNG=function(a){var b=this.sections.pdf.getElementsByTagName("input");b={format:"png",width:Number.parseInt(b[0].value),height:Number.parseInt(b[1].value),landscape:b[3].checked};netgis.util.invoke(a.target,netgis.Events.EXPORT_BEGIN,b)};
|
||||||
|
netgis.Export.prototype.onExportClickGIF=function(a){var b=this.sections.pdf.getElementsByTagName("input");b={format:"gif",width:Number.parseInt(b[0].value),height:Number.parseInt(b[1].value),landscape:b[3].checked};netgis.util.invoke(a.target,netgis.Events.EXPORT_BEGIN,b)};netgis.Export.prototype.onExportClickGeoJSON=function(a){var b={format:"geojson",nonEdits:this.sections.geojson.getElementsByTagName("input")[0].checked};netgis.util.invoke(a.target,netgis.Events.EXPORT_BEGIN,b)};
|
||||||
|
netgis.Export.prototype.onExportEnd=function(a){this.modal.hide()};netgis=netgis||{};netgis.Geolocation=function(a){this.config=a;this.center=this.active=!1};netgis.Geolocation.Config={marker_color:"#3480eb",marker_title:"Geolocation",timeout:1E4};netgis.Geolocation.prototype.initConfig=function(a){};netgis.Geolocation.prototype.attachTo=function(a){this.container=a;a.addEventListener(netgis.Events.GEOLOCATION_TOGGLE_ACTIVE,this.onGeolocToggleActive.bind(this));a.addEventListener(netgis.Events.GEOLOCATION_TOGGLE_CENTER,this.onGeolocToggleCenter.bind(this))};
|
||||||
|
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,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.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)};
|
||||||
|
netgis.Import.prototype.attachTo=function(a){a.appendChild(this.modal.container);a.addEventListener(netgis.Events.IMPORT_LAYER_SHOW,this.onImportShow.bind(this));a.addEventListener(netgis.Events.IMPORT_LAYER_PREVIEW_FEATURES,this.onImportPreviewFeatures.bind(this))};netgis.Import.prototype.addText=function(a,b){var c=document.createElement("div");c.innerHTML=b;a.appendChild(c);return c};
|
||||||
|
netgis.Import.prototype.addButton=function(a,b,c){var d=document.createElement("button");d.className="netgis-button netgis-center netgis-color-a netgis-hover-c netgis-shadow";d.setAttribute("type","button");d.innerHTML=b;c&&(d.onclick=c);a.appendChild(d);return d};
|
||||||
|
netgis.Import.prototype.addInputText=function(a,b,c){var d=document.createElement("label");d.innerHTML=b;var e=document.createElement("input");e.setAttribute("type","text");d.appendChild(e);if(c){b="list-"+netgis.util.stringToID(b);var f=document.createElement("datalist");f.setAttribute("id",b);for(var g=0;g<c.length;g++){var h=document.createElement("option");h.setAttribute("value",c[g]);f.appendChild(h)}a.appendChild(f);e.setAttribute("list",b)}a.appendChild(d);return e};
|
||||||
|
netgis.Import.prototype.addInputSelect=function(a,b,c){c=document.createElement("label");c.innerHTML=b;b=document.createElement("select");c.appendChild(b);a.appendChild(c);return b};netgis.Import.prototype.addInputFile=function(a,b,c){var d=document.createElement("label");d.innerHTML=b;b=document.createElement("input");b.setAttribute("type","file");b.setAttribute("accept",c);d.appendChild(b);a.appendChild(d);return b};netgis.Import.prototype.getLayerOrder=function(){return 1E4};
|
||||||
|
netgis.Import.prototype.showDetailsWMS=function(a){var b=this.sections.wms,c=b.getElementsByTagName("label");b=b.getElementsByTagName("button");a?(c[1].classList.remove("netgis-hide"),c[2].classList.remove("netgis-hide"),c[3].classList.remove("netgis-hide"),b[1].classList.remove("netgis-hide")):(c[1].classList.add("netgis-hide"),c[2].classList.add("netgis-hide"),c[3].classList.add("netgis-hide"),b[1].classList.add("netgis-hide"))};
|
||||||
|
netgis.Import.prototype.showDetailsWFS=function(a){var b=this.sections.wfs,c=b.getElementsByTagName("label");b=b.getElementsByTagName("button");a?(c[1].classList.remove("netgis-hide"),c[2].classList.remove("netgis-hide"),c[3].classList.remove("netgis-hide"),b[1].classList.remove("netgis-hide")):(c[1].classList.add("netgis-hide"),c[2].classList.add("netgis-hide"),c[3].classList.add("netgis-hide"),b[1].classList.add("netgis-hide"))};
|
||||||
|
netgis.Import.prototype.submitImportLayer=function(a){!0===this.config["import"].preview?netgis.util.invoke(this.modal.container,netgis.Events.IMPORT_LAYER_PREVIEW,a):(this.config.layers.push(a),netgis.util.invoke(this.modal.container,netgis.Events.IMPORT_LAYER_ACCEPT,a),this.modal.hide())};netgis.Import.prototype.onImportShow=function(a){this.modal.show();this.tabs.updateHeaderScroll()};
|
||||||
|
netgis.Import.prototype.onWMSLoadClick=function(a){this.showDetailsWMS(!1);a=this.sections.wms.getElementsByTagName("input")[0].value;a=a.trim();if(!(1>a.length)){var b=netgis.util.parseURL(a);a=b.base;b=b.parameters;b.push("request=GetCapabilities");b=b.join("&");-1===b.search("service=")&&(b+="&service=WMS");netgis.util.request(a+"?"+b,this.onWMSCapsResponse.bind(this))}};
|
||||||
|
netgis.Import.prototype.onWMSCapsResponse=function(a){var b=(new DOMParser).parseFromString(a,"text/xml"),c=b.documentElement;b=b.getElementsByTagName("parsererror");for(var d=0;d<b.length;d++)console.error("WMS caps parser error:",b[d].textContent);0<b.length&&alert(0<a.length?a:b[0].textContent);a=this.sections.wms;var e=a.getElementsByTagName("input");a=a.getElementsByTagName("select");b=a[0];a=a[1];for(d=b.options.length-1;0<=d;d--)b.options.remove(d);for(d=a.options.length-1;0<=d;d--)a.options.remove(d);
|
||||||
|
switch(c.nodeName){default:case "HTML":console.warn("could not detect WMS service",c);break;case "WMS_Capabilities":case "WMT_MS_Capabilities":c.getAttribute("version");d=c.getElementsByTagName("Service")[0].getElementsByTagName("Title")[0].textContent;e[1].value=d;d=c.getElementsByTagName("Layer");for(var f=[],g=0;g<d.length;g++){e=d[g];var h=e.getElementsByTagName("Name")[0].textContent,k=e.getElementsByTagName("Title")[0].textContent;f.push({name:h,title:k});e=document.createElement("option");
|
||||||
|
e.text=k;e.value=h;b.options.add(e)}c=c.getElementsByTagName("GetMap")[0].getElementsByTagName("Format");b=[];for(d=0;d<c.length;d++)e=c[d],f=e.textContent,-1!==f.search("image")&&(b.push(f),e=document.createElement("option"),e.text=f,e.value=f,a.options.add(e))}this.showDetailsWMS(!0)};
|
||||||
|
netgis.Import.prototype.onWMSAcceptClick=function(a){a=this.sections.wms;var b=a.getElementsByTagName("input"),c=a.getElementsByTagName("select"),d="import_"+netgis.util.getTimeStamp(!0),e=b[0].value;b=c[0].selectedOptions[0].innerText;var f=c[0].value;c=c[1].value;e=netgis.util.replace(e,"request=","oldrequest=");e=netgis.util.replace(e,"Request=","oldrequest=");var g=netgis.util.parseURL(e);e=g.base;g=g.parameters;g=g.join("&");-1===g.search("service=")&&(g+="&service=WMS");e=e+"?"+g;g={id:d,folder:null,
|
||||||
|
active:!0,query:!0,order:this.getLayerOrder(),type:netgis.LayerTypes.WMS,url:e,title:b,name:f,format:c,tiled:!0};this.config.layers.push(g);netgis.util.invoke(a,netgis.Events.IMPORT_LAYER_ACCEPT,g);this.modal.hide()};
|
||||||
|
netgis.Import.prototype.onWFSLoadClick=function(a){this.showDetailsWFS(!1);var b=this.sections.wfs.getElementsByTagName("input")[0].value;b=b.trim();if(!(1>b.length)){var c=b.indexOf("?");a=-1<c?b.substr(0,c):b;var d=["request=GetCapabilities"];if(-1<c)for(b=b.substr(c+1),b=b.split("&"),c=0;c<b.length;c++){var e=b[c];e=e.toLowerCase();-1<e.search("service")?d.push(e):-1<e.search("version")?d.push(e):-1<e.search("request")||d.push(e)}d=d.join("&");-1===d.search("service=")&&(d+="&service=WFS");a=a+
|
||||||
|
"?"+d;this.config["import"].wfs_proxy&&(a=this.config["import"].wfs_proxy+a);netgis.util.request(a,this.onWFSCapsResponse.bind(this))}};
|
||||||
|
netgis.Import.prototype.onWFSCapsResponse=function(a){var b=(new DOMParser).parseFromString(a,"text/xml"),c=b.documentElement;b=b.getElementsByTagName("parsererror");for(var d=0;d<b.length;d++)console.error("WFS caps parser error:",b[d].textContent);0<b.length&&alert(0<a.length?a:b[0].textContent);a=this.sections.wfs;var e=a.getElementsByTagName("input");a=a.getElementsByTagName("select");b=a[0];a=a[1];for(d=b.options.length-1;0<=d;d--)b.options.remove(d);for(d=a.options.length-1;0<=d;d--)a.options.remove(d);
|
||||||
|
switch(c.nodeName){default:case "HTML":console.error("could not detect WFS service",c);break;case "WFS_Capabilities":case "wfs:WFS_Capabilities":c.getAttribute("version");d=c.getElementsByTagName("ows:ServiceIdentification")[0].getElementsByTagName("ows:Title")[0].textContent;e[1].value=d;d=c.getElementsByTagName("FeatureType");for(var f=[],g=0;g<d.length;g++){e=d[g];var h=e.getElementsByTagName("Name")[0].textContent,k=e.getElementsByTagName("Title")[0].textContent;f.push({name:h,title:k});e=document.createElement("option");
|
||||||
|
e.text=k;e.value=h;b.options.add(e)}c=c.getElementsByTagName("ows:Operation");b=null;for(e=0;e<c.length;e++)if("GetFeature"===c[e].getAttribute("name")){b=c[e];break}c=null;if(b)for(b=b.getElementsByTagName("ows:Parameter"),e=0;e<b.length;e++)if(d=b[e],"outputFormat"===d.getAttribute("name")){b=d.getElementsByTagName("ows:Value");for(d=0;d<b.length;d++)e=b[d],f=e.textContent,e=document.createElement("option"),e.text=f,e.value=f,a.options.add(e),-1<f.search("json")&&(c=f);break}c&&(a.value=c)}this.showDetailsWFS(!0)};
|
||||||
|
netgis.Import.prototype.onWFSAcceptClick=function(a){a=this.sections.wfs;var b=a.getElementsByTagName("input"),c=a.getElementsByTagName("select"),d="import_"+netgis.util.getTimeStamp(!0);b=b[0].value;var e=c[0].selectedOptions[0].innerText,f=c[0].value;c=c[1].value;b=netgis.util.replace(b,"request=","oldrequest=");b=netgis.util.replace(b,"Request=","oldrequest=");this.config["import"].wfs_proxy&&(b=this.config["import"].wfs_proxy+b);d={id:d,folder:null,active:!0,order:this.getLayerOrder(),style:this.config.styles["import"],
|
||||||
|
title:e,type:netgis.LayerTypes.WFS,url:b,name:f,format:c};this.config.layers.push(d);netgis.util.invoke(a,netgis.Events.IMPORT_LAYER_ACCEPT,d);this.modal.hide()};netgis.Import.prototype.onGeoJSONAcceptClick=function(a){if(a=this.sections.geojson.getElementsByTagName("input")[0].files[0]){var b=new FileReader;b.title=a.name;b.onload=this.onGeoJSONLoad.bind(this);b.readAsText(a)}else alert("No file selected!")};
|
||||||
|
netgis.Import.prototype.onGeoJSONLoad=function(a){var b=a.target;a=b.title;b=b.result;a={id:"import_"+netgis.util.getTimeStamp(!0),folder:null,active:!0,order:this.getLayerOrder(),style:this.config.styles["import"],title:a,type:netgis.LayerTypes.GEOJSON,data:b};this.submitImportLayer(a)};netgis.Import.prototype.onGMLAcceptClick=function(a){if(a=this.sections.gml.getElementsByTagName("input")[0].files[0]){var b=new FileReader;b.title=a.name;b.onload=this.onGMLLoad.bind(this);b.readAsText(a)}else alert("No file selected!")};
|
||||||
|
netgis.Import.prototype.onGMLLoad=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.GML,data:a};this.submitImportLayer(a)};netgis.Import.prototype.onGeoPackageAcceptClick=function(a){if(a=this.sections.geopackage.getElementsByTagName("input")[0].files[0]){var b=new FileReader;b.title=a.name;b.onload=this.onGeoPackageLoad.bind(this);b.readAsArrayBuffer(a)}else alert("No file selected!")};
|
||||||
|
netgis.Import.prototype.onGeoPackageLoad=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.GEOPACKAGE,data:a};this.submitImportLayer(a)};
|
||||||
|
netgis.Import.prototype.onSpatialiteAcceptClick=function(a){if(a=this.sections.spatialite.getElementsByTagName("input")[0].files[0]){var b=new FileReader;b.title=a.name;b.onload=this.onSpatialiteLoad.bind(this);b.readAsArrayBuffer(a)}else alert("No file selected!")};
|
||||||
|
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=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,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.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,
|
||||||
|
this.onImportLayerAccept.bind(this));a.addEventListener(netgis.Events.IMPORT_GEOPORTAL_SUBMIT,this.onImportGeoportalSubmit.bind(this));a.addEventListener(netgis.Events.MAP_CLICK,this.onMapClick.bind(this));a.addEventListener(netgis.Events.MAP_FEATURE_CLICK,this.onMapFeatureClick.bind(this))};netgis.Info.prototype.isLayerQueryable=function(a){var b=!1;if(!0===a.query)b=!0;else if(!1!==a.query)switch(a.type){case netgis.LayerTypes.WMS:case netgis.LayerTypes.WMST:b=!0}return b};
|
||||||
|
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&&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&&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",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>");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;!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})};
|
||||||
|
netgis.LayerTree.prototype.onTreeItemSliderChange=function(a){var b=a.detail;a=b.id;b=.01*b.val;for(var c=this.config.layers,d=0;d<c.length;d++){var e=c[d];if(e.id===a){e.transparency=b;break}}netgis.util.invoke(this.tree.container,netgis.Events.MAP_LAYER_TRANSPARENCY,{id:a,transparency:b})};
|
||||||
|
netgis.LayerTree.prototype.onTreeItemOrderChange=function(a){a=a.detail.items;for(var b=this.config.layers,c=a.length,d=0;d<a.length;d++){for(var e=a[d].getElementsByTagName("input")[0].getAttribute("data-id"),f=0;f<b.length;f++){var g=b[f];g.id===e&&(g.order=c,netgis.util.invoke(this.tree.container,netgis.Events.MAP_LAYER_ORDER,{id:e,order:c}))}c--}};
|
||||||
|
netgis.LayerTree.prototype.onTreeItemDeleteClick=function(a){a=a.currentTarget.parentNode.parentNode.parentNode.parentNode.getElementsByTagName("input")[0].getAttribute("data-id");netgis.util.invoke(this.tree.container,netgis.Events.MAP_LAYER_DELETE,{id:a});this.tree.removeItem(a)};netgis.LayerTree.prototype.onMapEditLayerChange=function(a){this.editFolder.classList.remove("netgis-hide")};netgis.LayerTree.prototype.onDragOver=function(a){a.preventDefault()};
|
||||||
|
netgis.LayerTree.prototype.onDragDrop=function(a){a=this.tree.dragElement;"summary"===a.nodeName.toLowerCase()&&(a=a.parentNode.parentNode);a.parentNode.removeChild(a);0<this.tree.container.childNodes.length?this.tree.container.insertBefore(a,this.tree.container.childNodes[0]):this.tree.container.appendChild(a);netgis.util.invoke(this.tree.container,netgis.Events.TREE_ITEM_ORDER_CHANGE,{items:this.tree.container.getElementsByClassName("netgis-item")})};netgis=netgis||{};netgis.LayerTypes={TMS:"TMS",XYZ:"XYZ",OSM:"OSM",WMTS:"WMTS",WMS:"WMS",WMST:"WMST",GEOJSON:"GEOJSON",VTILES:"VTILES",WFS:"WFS",GML:"GML",KML:"KML",GEOPACKAGE:"GEOPACKAGE",SPATIALITE:"SPATIALITE",SHAPEFILE:"SHAPEFILE",WKT:"WKT",HIDDEN:"HIDDEN"};netgis=netgis||{};netgis.Legend=function(a){this.config=a;this.initElements();this.initConfig(a)};netgis.Legend.Config={open:!1};netgis.Legend.prototype.initElements=function(){this.panel=new netgis.Panel("<i class='netgis-icon fas fa-bars'></i><span>Legende</span>");this.panel.content.classList.add("netgis-legend")};netgis.Legend.prototype.initConfig=function(a){var b=a.legend;b&&!0===b.open&&this.show();a=a.layers;for(b=0;b<a.length;b++){var c=a[b];!0===c.active?this.addLayerLegend(c.id):this.removeLayerLegend(c.id)}};
|
||||||
|
netgis.Legend.prototype.attachTo=function(a){this.panel.attachTo(a);a.addEventListener(netgis.Events.CLIENT_CONTEXT_RESPONSE,this.onClientContextResponse.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.LEGEND_TOGGLE,this.onLegendToggle.bind(this))};
|
||||||
|
netgis.Legend.prototype.show=function(){this.panel.show()};netgis.Legend.prototype.hide=function(){this.panel.hide()};netgis.Legend.prototype.addSection=function(a,b,c,d){this.panel.content.innerHTML=[!0===d?"<details data-id='"+a+"' open='open'>":"<details data-id='"+a+"'>","<summary class='netgis-button netgis-noselect netgis-clip-text netgis-color-d netgis-hover-text-a netgis-hover-d'>",b,"</summary><div class='netgis-border-d'>",c,"</div></details>"].join("")+this.panel.content.innerHTML};
|
||||||
|
netgis.Legend.prototype.addLayerLegend=function(a){for(var b=null,c=this.config.layers,d=0;d<c.length;d++){var e=c[d];if(e.id===a){b=e;break}}if(b){c=b.legend;if(!c||""===c)switch(b.type){case netgis.LayerTypes.WMS:case netgis.LayerTypes.WMST:(c=b.url)&&-1===c.indexOf("?")&&(c+="?"),c+=["service=WMS&version=1.1.0&request=GetLegendGraphic&format=image/png","layer="+b.name].join("&")}c&&""!==c&&this.addSection(a,b.title,"<img src='"+c+"'/>",!0)}};
|
||||||
|
netgis.Legend.prototype.removeLayerLegend=function(a){for(var b=this.panel.content.getElementsByTagName("details"),c=0;c<b.length;c++){var d=b[c];d.getAttribute("data-id")===a&&d.parentNode.removeChild(d)}};netgis.Legend.prototype.onClientContextResponse=function(a){this.initConfig(a.detail.context.config)};netgis.Legend.prototype.onMapLayerToggle=function(a){a=a.detail;a.on?this.addLayerLegend(a.id):this.removeLayerLegend(a.id)};netgis.Legend.prototype.onMapLayerCreate=function(a){this.addLayerLegend(a.detail.id)};
|
||||||
|
netgis.Legend.prototype.onMapLayerDelete=function(a){this.removeLayerLegend(a.detail.id)};netgis.Legend.prototype.onLegendToggle=function(a){this.panel.toggle()};netgis=netgis||{};
|
||||||
|
netgis.Map=function(a){this.config=a;this.mode=null;this.interactions={};this.layers={};this.viewHistory=[];this.viewIndex=-1;this.viewFromHistory=!1;this.viewHistoryMax=20;this.paddingBuffer=40;this.hoverBounds=this.hoverFeature=null;this.selectedFeatures=[];this.sketchFeatures=[];this.snap=null;this.snapFeatures=new ol.Collection;this.drawError=this.selectReset=this.selectMultiple=this.editEventsSilent=!1;this.initElements();a.map&&(this.initMap(a),this.initLayers(),this.initOverlays(),this.initInteractions(),
|
||||||
|
this.initConfig(a),this.setPadding(0,0,0,0),this.setMode(netgis.Modes.VIEW))};netgis.Map.Config={projection:"EPSG:25832",center:[329766.1782104631,5513621.076679279],center_lonlat:[7,50],zoom:14,min_zoom:5,max_zoom:19,extent:[293315.97,5423948.96,464350.97,5644103.06],bbox:[293315.97,5423948.96,464350.97,5644103.06],scales:[500,1E3,3E3,5E3,8E3,1E4,15E3,25E3,5E4,1E5,15E4,25E4,5E5,1E6,15E5,2E6],scale:1E5,scalebar:!0,max_view_history:20};netgis.Map.Projections=[["EPSG:25832","+proj=utm +zone=32 +ellps=GRS80 +units=m +no_defs"]];
|
||||||
|
netgis.Map.Layers=[];netgis.Map.Measure={line_color:"rgba( 255, 0, 0, 1.0 )",line_width:3,line_dash:[5,10],area_fill:"rgba( 255, 0, 0, 0.3 )",point_radius:4,point_fill:"rgba( 255, 255, 255, 1.0 )",point_stroke:"rgba( 0, 0, 0, 1.0 )",text_color:"#871d33",text_back:"rgba( 255, 255, 255, 0.7 )"};
|
||||||
|
netgis.Map.Tools={editable:!0,output_id:"",interactive_render:!0,select_multi_reset:!0,buffer:{default_radius:300,default_segments:3},snapping:{show:!0,active:!0,tolerance:10},bounds:void 0,bounds_message:"Out of bounds!",show_bounds:!0};
|
||||||
|
netgis.Map.Styles={draw:{fill:"rgba( 255, 0, 0, 0.5 )",stroke:"#ff0000",width:3,radius:6,viewport_labels:!0},non_edit:{fill:"rgba( 80, 80, 80, 0.5 )",stroke:"#666666",width:3,radius:6,viewport_labels:!0},select:{fill:"rgba( 0, 127, 255, 0.5 )",stroke:"#007fff",width:3,radius:6},sketch:{fill:"rgba( 0, 127, 0, 0.5 )",stroke:"#007f00",width:3,radius:6},error:{fill:"rgba( 255, 0, 0, 0.5 )",stroke:"#ff0000",width:3,radius:6},bounds:{fill:"rgba( 0, 0, 0, 0.0 )",stroke:"#000000",width:3,radius:6},modify:{fill:"rgba( 255, 127, 0, 0.5 )",
|
||||||
|
stroke:"#ff7f00",width:3,radius:6},parcel:{fill:"rgba( 127, 0, 0, 0.0 )",stroke:"rgba( 127, 0, 0, 1.0 )",width:1.5},"import":{fill:"rgba( 0, 127, 255, 0.2 )",stroke:"rgba( 0, 127, 255, 1.0 )",width:1.5}};
|
||||||
|
netgis.Map.prototype.initElements=function(){this.container=document.createElement("div");this.container.setAttribute("tabindex",-1);this.container.className="netgis-map";this.container.addEventListener("pointerleave",this.onPointerLeave.bind(this));this.container.addEventListener("click",this.onContainerClick.bind(this));this.container.addEventListener("contextmenu",this.onRightClick.bind(this));this.container.addEventListener("keydown",this.onKeyDown.bind(this));this.container.addEventListener("keyup",
|
||||||
|
this.onKeyUp.bind(this))};
|
||||||
|
netgis.Map.prototype.initMap=function(a){var b=a.map;"undefined"!==typeof proj4?(a.projections&&0<a.projections.length&&proj4.defs(a.projections),proj4.defs("urn:ogc:def:crs:OGC:1.3:CRS84",proj4.defs("EPSG:4326")),ol.proj.proj4.register(proj4)):(a.projections&&0<a.projections.length||b.projection)&&console.error("map projections configured but no proj4 js library found",a.projections,b.projection);a=void 0;b.center_lonlat&&(a=ol.proj.fromLonLat(b.center_lonlat,b.projection));!a&&b.center&&(a=b.center);
|
||||||
|
var c=void 0;if(b.zoom||0===b.zoom)c=b.zoom;void 0===c&&void 0!==b.min_zoom&&(c=b.min_zoom);void 0===c&&(c=0);this.view=new ol.View({projection:b.projection,center:a,minZoom:b.min_zoom,maxZoom:b.max_zoom,zoom:c});b.default_scale&&console.error("config[ 'map' ][ 'default_scale' ] is deprecated, use config[ 'map' ][ 'scale' ] instead");b.scale&&this.view.setResolution(this.getResolutionFromScale(b.scale));this.map=new ol.Map({target:this.container,view:this.view,pixelRatio:1,moveTolerance:b.move_tolerance||
|
||||||
|
0===b.move_tolerance?b.move_tolerance:7,controls:[]});if(b.scalebar&&(this.scalebar=new ol.control.ScaleLine({bar:!0}),this.map.addControl(this.scalebar),(a=b.scales)&&0<a.length))for(this.scalebarSelect=document.createElement("select"),this.scalebarSelect.addEventListener("change",this.onScalebarSelectChange.bind(this)),this.scalebar.element.appendChild(this.scalebarSelect),c=0;c<a.length;c++){var d=a[c],e=document.createElement("option");e.innerHTML="1:"+d;e.setAttribute("value",d);this.scalebarSelect.appendChild(e)}this.map.on("moveend",
|
||||||
|
this.onMapMoveEnd.bind(this));this.map.on("pointermove",this.onPointerMove.bind(this));this.map.on("click",this.onPointerClick.bind(this));if(b){var f=b.extent;b.bbox&&(f=b.bbox);if(f){var g=this;window.setTimeout(function(){g.map.updateSize();g.view.fit(f)},10)}}};
|
||||||
|
netgis.Map.prototype.initLayers=function(){this.measureLayer=new ol.layer.Vector({source:new ol.source.Vector({features:[]}),zIndex:6E4,style:this.styleMeasure.bind(this)});this.map.addLayer(this.measureLayer);var a=this.config.tools;if(a&&(this.nonEditLayer=new ol.layer.Vector({source:new ol.source.Vector({features:[]}),zIndex:5E4,style:this.styleNonEdit.bind(this),updateWhileAnimating:a&&a.interactive_render?a.interactive_render:!1,updateWhileInteracting:a&&a.interactive_render?a.interactive_render:
|
||||||
|
!1}),this.map.addLayer(this.nonEditLayer),this.editLayer=new ol.layer.Vector({source:new ol.source.Vector({features:[]}),zIndex:5E4,style:this.styleEdit.bind(this),updateWhileAnimating:a&&a.interactive_render?a.interactive_render:!1,updateWhileInteracting:a&&a.interactive_render?a.interactive_render:!1}),this.map.addLayer(this.editLayer),this.editLayer.getSource().on("addfeature",this.onEditLayerAdd.bind(this)),this.editLayer.getSource().on("changefeature",this.onEditLayerChange.bind(this)),this.editLayer.getSource().on("removefeature",
|
||||||
|
this.onEditLayerRemove.bind(this)),this.previewLayer=new ol.layer.Vector({source:new ol.source.Vector({features:[]}),zIndex:55E3,style:this.styleSketch.bind(this)}),this.map.addLayer(this.previewLayer),this.boundsLayer=null,a=a.bounds)){a=netgis.util.replace(a,"'",'"');var b=(new ol.format.GeoJSON).readFeatures(a);a=null;this.config.tools.show_bounds&&this.config.styles.bounds&&(a=this.createStyle(this.config.styles.bounds));this.boundsLayer=new ol.layer.Vector({source:new ol.source.Vector({features:b}),
|
||||||
|
style:a,zIndex:6E4});this.map.addLayer(this.boundsLayer)}this.geolocLayer=null;this.config.modules&&!0===this.config.modules.geolocation&&(a=this.config.geolocation,a||(a=netgis.Geolocation.Config),a=[new ol.style.Style({image:new ol.style.Circle({fill:new ol.style.Fill({color:"#ffffff"}),radius:8})}),new ol.style.Style({image:new ol.style.Circle({fill:new ol.style.Fill({color:a.marker_color?a.marker_color:"#ff0000"}),radius:5})})],b=new ol.Feature({geometry:new ol.geom.Point(ol.proj.fromLonLat([7,
|
||||||
|
50],this.view.getProjection()))}),b.setId("geolocation"),this.geolocLayer=new ol.layer.Vector({source:new ol.source.Vector({features:[b]}),style:a,zIndex:66E3}),this.map.addLayer(this.geolocLayer),this.geolocLayer.setVisible(!1))};netgis.Map.prototype.initOverlays=function(){var a=document.createElement("div");a.className="netgis-map-overlay";this.popupOverlay=new ol.Overlay({id:"popup",element:a,positioning:"center-center"});this.map.addOverlay(this.popupOverlay)};
|
||||||
|
netgis.Map.prototype.initInteractions=function(){this.interactions[netgis.Modes.VIEW]=[new ol.interaction.DragPan,new ol.interaction.DragPan({condition:function(a){return 1===a.originalEvent.button}}),new ol.interaction.MouseWheelZoom];this.interactions[netgis.Modes.ZOOM_BOX]=[new ol.interaction.DragZoom({condition:function(a){return 0===a.originalEvent.button},out:!1,className:"netgis-zoom-box"}),new ol.interaction.DragPan({condition:function(a){return 1===a.originalEvent.button}}),new ol.interaction.MouseWheelZoom];
|
||||||
|
this.interactions[netgis.Modes.MEASURE_LINE]=[new ol.interaction.DragPan,new ol.interaction.Modify({source:this.measureLayer.getSource(),deleteCondition:ol.events.condition.doubleClick,style:this.styleMeasure.bind(this)}),new ol.interaction.Draw({type:"LineString",source:this.measureLayer.getSource(),style:this.styleMeasure.bind(this)}),new ol.interaction.DragPan({condition:function(a){return 1===a.originalEvent.button}}),new ol.interaction.PinchZoom,new ol.interaction.MouseWheelZoom];this.interactions[netgis.Modes.MEASURE_AREA]=
|
||||||
|
[new ol.interaction.DragPan,new ol.interaction.Modify({source:this.measureLayer.getSource(),deleteCondition:ol.events.condition.doubleClick,style:this.styleMeasure.bind(this)}),new ol.interaction.Draw({type:"Polygon",source:this.measureLayer.getSource(),style:this.styleMeasure.bind(this)}),new ol.interaction.DragPan({condition:function(a){return 1===a.originalEvent.button}}),new ol.interaction.PinchZoom,new ol.interaction.MouseWheelZoom];this.interactions[netgis.Modes.MEASURE_LINE][2].on("drawstart",
|
||||||
|
this.onMeasureLineBegin.bind(this));this.interactions[netgis.Modes.MEASURE_AREA][2].on("drawstart",this.onMeasureAreaBegin.bind(this));if(this.config.tools&&!0===this.config.tools.editable){var a=this.config.tools.bounds?!0:!1;this.interactions[netgis.Modes.DRAW_POINTS]=[new ol.interaction.Draw({type:"Point",source:this.editLayer.getSource(),style:this.styleSketch.bind(this),geometryFunction:a?this.onDrawPointsUpdateGeom.bind(this):void 0}),new ol.interaction.DragPan,new ol.interaction.DragPan({condition:function(a){return 1===
|
||||||
|
a.originalEvent.button}}),new ol.interaction.MouseWheelZoom];this.interactions[netgis.Modes.DRAW_POINTS][0].on("drawend",this.onDrawBufferEnd.bind(this));if(a)this.interactions[netgis.Modes.DRAW_POINTS][0].on("drawend",this.onDrawPointsEnd.bind(this));this.interactions[netgis.Modes.DRAW_LINES]=[new ol.interaction.Draw({type:"LineString",source:this.editLayer.getSource(),style:this.styleSketch.bind(this),geometryFunction:a?this.onDrawLinesUpdateGeom.bind(this):void 0}),new ol.interaction.DragPan,new ol.interaction.DragPan({condition:function(a){return 1===
|
||||||
|
a.originalEvent.button}}),new ol.interaction.MouseWheelZoom];this.interactions[netgis.Modes.DRAW_LINES][0].on("drawend",this.onDrawBufferEnd.bind(this));if(a)this.interactions[netgis.Modes.DRAW_LINES][0].on("drawend",this.onDrawLinesEnd.bind(this));this.interactions[netgis.Modes.DRAW_POLYGONS]=[new ol.interaction.Draw({type:"Polygon",source:this.editLayer.getSource(),style:this.styleSketch.bind(this),geometryFunction:a?this.onDrawPolygonsUpdateGeom.bind(this):void 0}),new ol.interaction.DragPan,new ol.interaction.DragPan({condition:function(a){return 1===
|
||||||
|
a.originalEvent.button}}),new ol.interaction.MouseWheelZoom];if(a)this.interactions[netgis.Modes.DRAW_POLYGONS][0].on("drawend",this.onDrawPolygonsEnd.bind(this));this.interactions[netgis.Modes.MODIFY_FEATURES]=[new ol.interaction.DragPan,new ol.interaction.Modify({source:this.editLayer.getSource(),deleteCondition:ol.events.condition.doubleClick,style:this.styleModify.bind(this)}),new ol.interaction.DragPan({condition:function(a){return 1===a.originalEvent.button}}),new ol.interaction.MouseWheelZoom];
|
||||||
|
this.interactions[netgis.Modes.DELETE_FEATURES]=[new ol.interaction.DragPan,new ol.interaction.DragPan({condition:function(a){return 1===a.originalEvent.button}}),new ol.interaction.MouseWheelZoom];this.interactions[netgis.Modes.CUT_FEATURES_DRAW]=[new ol.interaction.Draw({type:"Polygon",style:this.styleSketch.bind(this)}),new ol.interaction.DragPan,new ol.interaction.DragPan({condition:function(a){return 1===a.originalEvent.button}}),new ol.interaction.MouseWheelZoom];this.interactions[netgis.Modes.CUT_FEATURES_DRAW][0].on("drawend",
|
||||||
|
this.onCutFeaturesDrawEnd.bind(this))}};netgis.Map.prototype.initConfig=function(a){var b=a.map;b&&(b.bbox&&this.zoomBBox(a.map.bbox),!b.zoom||b.extent||b.scale||this.view.setZoom(a.map.zoom),b.max_view_history&&(this.viewHistoryMax=b.max_view_history));if(a=a.layers)for(b=a.length-1;0<=b;b--){var c=a[b];!0===c.active&&this.addLayer(c.id,c)}};
|
||||||
|
netgis.Map.prototype.attachTo=function(a){a.appendChild(this.container);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.PANEL_TOGGLE,this.onPanelToggle.bind(this));a.addEventListener(netgis.Events.PANEL_RESIZE,this.onPanelResize.bind(this));a.addEventListener(netgis.Events.MAP_EDIT_LAYER_LOADED,this.onEditLayerLoaded.bind(this));a.addEventListener(netgis.Events.MAP_ZOOM,
|
||||||
|
this.onMapZoom.bind(this));a.addEventListener(netgis.Events.MAP_ZOOM_HOME,this.onMapZoomHome.bind(this));a.addEventListener(netgis.Events.MAP_ZOOM_LONLAT,this.onMapZoomLonLat.bind(this));a.addEventListener(netgis.Events.MAP_ZOOM_SCALE,this.onMapZoomScale.bind(this));a.addEventListener(netgis.Events.MAP_ZOOM_LAYER,this.onMapZoomLayer.bind(this));a.addEventListener(netgis.Events.MAP_ZOOM_LEVEL,this.onMapZoomLevel.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.MAP_LAYER_TRANSPARENCY,this.onMapLayerTransparency.bind(this));a.addEventListener(netgis.Events.MAP_LAYER_ORDER,this.onMapLayerOrder.bind(this));a.addEventListener(netgis.Events.MAP_LAYER_DELETE,this.onMapLayerDelete.bind(this));a.addEventListener(netgis.Events.MAP_SNAP_TOGGLE,this.onMapSnapToggle.bind(this));a.addEventListener(netgis.Events.MAP_VIEW_PREV,this.onMapViewPrev.bind(this));
|
||||||
|
a.addEventListener(netgis.Events.MAP_VIEW_NEXT,this.onMapViewNext.bind(this));a.addEventListener(netgis.Events.GEOLOCATION_TOGGLE_ACTIVE,this.onGeolocToggleActive.bind(this));a.addEventListener(netgis.Events.GEOLOCATION_CHANGE,this.onGeolocChange.bind(this));a.addEventListener(netgis.Events.MEASURE_CLEAR,this.onMeasureClear.bind(this));a.addEventListener(netgis.Events.SELECT_MULTI_TOGGLE,this.onSelectMultiToggle.bind(this));a.addEventListener(netgis.Events.DRAW_BUFFER_TOGGLE,this.onDrawBufferToggle.bind(this));
|
||||||
|
a.addEventListener(netgis.Events.DRAW_BUFFER_CHANGE,this.onDrawBufferChange.bind(this));a.addEventListener(netgis.Events.BUFFER_CHANGE,this.onBufferChange.bind(this));a.addEventListener(netgis.Events.BUFFER_ACCEPT,this.onBufferAccept.bind(this));a.addEventListener(netgis.Events.IMPORT_LAYER_ACCEPT,this.onImportLayerAccept.bind(this));a.addEventListener(netgis.Events.IMPORT_LAYER_PREVIEW,this.onImportLayerPreview.bind(this));a.addEventListener(netgis.Events.IMPORT_GEOPORTAL_SUBMIT,this.onImportGeoportalSubmit.bind(this));
|
||||||
|
a.addEventListener(netgis.Events.MAP_COPY_FEATURE_TO_EDIT,this.onCopyFeatureToEdit.bind(this));a.addEventListener(netgis.Events.SEARCHPARCEL_ITEM_ENTER,this.onSearchParcelItemEnter.bind(this));a.addEventListener(netgis.Events.SEARCHPARCEL_ITEM_LEAVE,this.onSearchParcelItemLeave.bind(this));a.addEventListener(netgis.Events.SEARCHPARCEL_ITEM_CLICK,this.onSearchParcelItemClick.bind(this));a.addEventListener(netgis.Events.SEARCHPARCEL_ITEM_IMPORT,this.onSearchParcelItemImport.bind(this));a.addEventListener(netgis.Events.EXPORT_BEGIN,
|
||||||
|
this.onExportBegin.bind(this));a.addEventListener(netgis.Events.TIMESLIDER_SHOW,this.onTimeSliderShow.bind(this));a.addEventListener(netgis.Events.TIMESLIDER_HIDE,this.onTimeSliderHide.bind(this));a.addEventListener(netgis.Events.TIMESLIDER_SELECT,this.onTimeSliderSelect.bind(this))};
|
||||||
|
netgis.Map.prototype.setMode=function(a){switch(this.mode){case netgis.Modes.VIEW:this.container.classList.remove("netgis-clickable");break;case netgis.Modes.MODIFY_FEATURES:this.editLayer.setStyle(this.styleEdit.bind(this));break;case netgis.Modes.DRAW_POINTS:case netgis.Modes.DRAW_LINES:this.previewLayer.getSource().clear();this.container.classList.remove("netgis-not-allowed");this.container.removeAttribute("title");break;case netgis.Modes.DRAW_POLYGONS:this.container.classList.remove("netgis-not-allowed");
|
||||||
|
this.container.removeAttribute("title");break;case netgis.Modes.BUFFER_FEATURES:this.clearSketchFeatures();break;case netgis.Modes.BUFFER_FEATURES_EDIT:this.clearSketchFeatures();this.selectedFeatures=[];this.redrawVectorLayers();break;case netgis.Modes.BUFFER_FEATURES_DYNAMIC:this.clearSketchFeatures();this.selectedFeatures=[];this.redrawVectorLayers();break;case netgis.Modes.CUT_FEATURES:a!==netgis.Modes.CUT_FEATURES_DRAW&&(this.selectedFeatures=[],this.redrawVectorLayers());break;case netgis.Modes.CUT_FEATURES_DRAW:this.selectedFeatures=
|
||||||
|
[],this.redrawVectorLayers()}this.map.getInteractions().clear();this.mode&&this.container.classList.remove("netgis-mode-"+this.mode);var b=this.interactions[a];b||(console.warn("no interactions found for mode",a),b=this.interactions[netgis.Modes.VIEW]);for(var c=0;c<b.length;c++)this.map.addInteraction(b[c]);b=this.config.tools&&this.config.tools.editable;switch(a){case netgis.Modes.DRAW_POINTS:case netgis.Modes.DRAW_LINES:b&&(this.setSnapping(this.drawSnapOn),this.onDrawBufferToggle({detail:{on:this.drawBufferOn,
|
||||||
|
radius:this.drawBufferRadius,segments:this.drawBufferSegments}}));break;case netgis.Modes.DRAW_POLYGONS:b&&this.setSnapping(this.drawSnapOn);break;case netgis.Modes.MODIFY_FEATURES:b&&(this.setSnapping(this.drawSnapOn),this.editLayer.setStyle(this.styleModify.bind(this)))}this.container.classList.add("netgis-mode-"+a);this.mode=a};
|
||||||
|
netgis.Map.prototype.addLayer=function(a,b){var c=this.createLayer(b);c&&(c.set("id",a),this.map.addLayer(c),this.layers[a]=c,b.order&&c.setZIndex(b.order),b.transparency&&c.setOpacity(1-b.transparency),b.style&&c.setStyle(this.createStyle(b.style)),b.min_zoom&&c.setMinZoom(b.min_zoom-1E-4),b.max_zoom&&c.setMaxZoom(b.max_zoom),c instanceof ol.layer.Vector&&this.addSnapLayer(c),b.type===netgis.LayerTypes.WMST&&netgis.util.invoke(this.container,netgis.Events.TIMESLIDER_SHOW,{layer:a,title:b.title,url:b.url,
|
||||||
|
name:b.name}));return c};netgis.Map.prototype.isLayerQueryable=function(a){var b=!1;if(!0===a.query)b=!0;else if(!1!==a.query)switch(a.type){case netgis.LayerTypes.WMS:case netgis.LayerTypes.WMST:b=!0}return b};netgis.Map.prototype.getQueryableLayers=function(a){var b=[],c=this.config.layers;if(c)for(var d=0;d<c.length;d++){var e=c[d],f=this.layers[e.id];f&&(a&&f instanceof ol.layer.Vector||this.isLayerQueryable(e)&&b.push(e))}return b};
|
||||||
|
netgis.Map.prototype.createLayer=function(a){switch(a.type){case netgis.LayerTypes.HIDDEN:break;case netgis.LayerTypes.TMS:case netgis.LayerTypes.XYZ:var b=this.createLayerTMS(a.url,a.projection,a.extent,a.scales,a.resolutions);break;case netgis.LayerTypes.OSM:b=this.createLayerTMS("https://{a-c}.tile.openstreetmap.de/{z}/{x}/{y}.png");break;case netgis.LayerTypes.WMTS:b=this.createLayerWMTS(a.url,a.name);break;case netgis.LayerTypes.WMS:b=this.createLayerWMS(a.url,a.name,a.format,a.tiled,a.username,
|
||||||
|
a.password);break;case netgis.LayerTypes.WMST:b=this.createLayerWMST(a.url,a.name,a.format,a.tiled,a.username,a.password);break;case netgis.LayerTypes.GEOJSON:(b=a.data)&&netgis.util.isString(b)&&(b=JSON.parse(b));b=this.createLayerGeoJSON(b?b:a.url);break;case netgis.LayerTypes.WFS:b=this.createLayerWFS(a.url,a.name,this.view.getProjection().getCode(),a.format,a.username,a.password);break;case netgis.LayerTypes.VTILES:b=this.createLayerVectorTiles(a.url,a.extent,a.min_zoom,a.max_zoom);break;case netgis.LayerTypes.GML:b=
|
||||||
|
this.createLayerGML(a.data);break;case netgis.LayerTypes.KML:b=this.createLayerKML(a.url);break;case netgis.LayerTypes.GEOPACKAGE:b=this.createLayerGeoPackage(a.data);break;case netgis.LayerTypes.SPATIALITE:b=this.createLayerSpatialite(a.data);break;case netgis.LayerTypes.SHAPEFILE:b=this.createLayerShapefile(a.data);break;case netgis.LayerTypes.WKT:b=this.createLayerWKT(a.data);break;default:console.error("unknown layer type",a.type)}return b};
|
||||||
|
netgis.Map.prototype.removeLayer=function(a){var b=this.layers[a];b instanceof ol.layer.Vector&&this.removeSnapLayer(b);for(var c=0;c<this.config.layers.length;c++){var d=this.config.layers[c];d.id===a&&d.type===netgis.LayerTypes.WMST&&netgis.util.invoke(this.container,netgis.Events.TIMESLIDER_HIDE,null)}this.map.removeLayer(b);delete this.layers[a]};netgis.Map.prototype.setLayerOrder=function(a,b){this.layers[a].setZIndex(b)};
|
||||||
|
netgis.Map.prototype.createStyle=function(a){var b=a.radius?a.radius:3,c=a.width?a.width:1,d=a.fill?a.fill:"gray",e=a.stroke?a.stroke:"black";return function(a){return new ol.style.Style({image:new ol.style.Circle({radius:b-c,fill:new ol.style.Fill({color:d})}),fill:new ol.style.Fill({color:d}),stroke:new ol.style.Stroke({color:e,width:c})})}};
|
||||||
|
netgis.Map.prototype.styleMeasure=function(a){var b=a.getGeometry(),c=this.config.measure;c||(c=netgis.Map.Measure);var d=new ol.style.Style({fill:new ol.style.Fill({color:c.area_fill}),stroke:new ol.style.Stroke({color:c.line_color,width:c.line_width,lineDash:c.line_dash})});b instanceof ol.geom.Polygon?(b=b.getArea(),d.setText(new ol.style.Text({text:[netgis.util.formatArea(b,!0),"4mm sans-serif"],font:"Arial",fill:new ol.style.Fill({color:c.text_color}),backgroundFill:new ol.style.Fill({color:c.text_back}),
|
||||||
|
padding:[2,4,2,4],overflow:!0}))):b instanceof ol.geom.LineString&&(this.mode===netgis.Modes.MEASURE_LINE||this.mode===netgis.Modes.VIEW)&&(b=b.getLength(),d.setText(new ol.style.Text({text:[netgis.util.formatDistance(b),"4mm sans-serif"],font:"Arial",fill:new ol.style.Fill({color:c.text_color}),backgroundFill:new ol.style.Fill({color:c.text_back}),padding:[2,4,2,4],overflow:!0})));return c.point_radius&&0<c.point_radius?(b=this.getGeometryPoints(a),a=new ol.style.Style({image:new ol.style.Circle({radius:1.25*
|
||||||
|
c.point_radius,fill:new ol.style.Fill({color:c.point_stroke})}),geometry:b}),c=new ol.style.Style({image:new ol.style.Circle({radius:c.point_radius,fill:new ol.style.Fill({color:c.point_fill})}),geometry:b}),[d,a,c]):d};
|
||||||
|
netgis.Map.prototype.styleEdit=function(a){var b,c;this.config&&this.config.styles&&(this.config.styles.draw&&(b=this.config.styles.draw),this.config.styles.select&&(c=this.config.styles.select));b||(b=netgis.Map.Styles.draw);c||(c=netgis.Map.Styles.select);var d=a.getGeometry(),e=this.hoverFeature===a;-1<this.selectedFeatures.indexOf(a)&&(e=!0);var f=e?c.fill:b.fill,g=e?c.stroke:b.stroke;c=new ol.style.Style({image:new ol.style.Circle({radius:e?c.radius:b.radius,fill:new ol.style.Fill({color:g})}),
|
||||||
|
fill:new ol.style.Fill({color:f}),stroke:new ol.style.Stroke({color:g,width:b.width})});e&&c.setZIndex(1);if(d instanceof ol.geom.Polygon||d instanceof ol.geom.MultiPolygon){e=d.getArea();if(!e||0>=e)return c;!0===b.viewport_labels&&(b=this.view.calculateExtent(this.map.getSize()),f=ol.geom.Polygon.fromExtent(b),b=new jsts.io.OL3Parser,d=b.read(d),f=b.read(f),d=d.intersection(f),d=b.write(d),c.setGeometry(d));e=netgis.util.formatArea(e,!0);(a=a.getProperties().title)&&(e=a+"\n"+e);c.setText(new ol.style.Text({text:e,
|
||||||
|
font:"4mm Arial, sans-serif",fill:new ol.style.Fill({color:g}),backgroundFill:new ol.style.Fill({color:"rgba( 255, 255, 255, 0.5 )"}),padding:[2,4,2,4]}))}return c};
|
||||||
|
netgis.Map.prototype.styleNonEdit=function(a){var b,c;this.config&&this.config.styles&&(this.config.styles.non_edit&&(b=this.config.styles.non_edit),this.config.styles.select&&(c=this.config.styles.select));b||(b=netgis.Map.Styles.non_edit);c||(c=netgis.Map.Styles.select);var d=a.getGeometry(),e=this.hoverFeature===a;-1<this.selectedFeatures.indexOf(a)&&(e=!0);var f=e?c.fill:b.fill,g=e?c.stroke:b.stroke;c=new ol.style.Style({image:new ol.style.Circle({radius:e?c.radius:b.radius,fill:new ol.style.Fill({color:g})}),
|
||||||
|
fill:new ol.style.Fill({color:f}),stroke:new ol.style.Stroke({color:g,width:b.width})});e&&c.setZIndex(1);if(d instanceof ol.geom.Polygon){e=d.getArea();if(!e||0>=e)return c;!0===b.viewport_labels&&(b=this.map.getView().calculateExtent(this.map.getSize()),f=ol.geom.Polygon.fromExtent(b),b=new jsts.io.OL3Parser,d=b.read(d),f=b.read(f),d=d.intersection(f),d=b.write(d),c.setGeometry(d));e=netgis.util.formatArea(e,!0);(a=a.getProperties().title)&&(e=a+"\n"+e);c.setText(new ol.style.Text({text:e,font:"4mm Arial, sans-serif",
|
||||||
|
fill:new ol.style.Fill({color:g}),backgroundFill:new ol.style.Fill({color:"rgba( 255, 255, 255, 0.5 )"}),padding:[2,4,2,4]}))}return c};
|
||||||
|
netgis.Map.prototype.styleSketch=function(a){var b,c;this.config&&this.config.styles&&(this.config.styles.sketch&&(b=this.config.styles.sketch),this.config.styles.error&&(c=this.config.styles.error));b||(b=netgis.Map.Styles.sketch);c||(c=netgis.Map.Styles.error);this.drawError&&c&&(b=c);var d=a.getGeometry();c=new ol.style.Style({image:new ol.style.Circle({radius:b.radius,fill:new ol.style.Fill({color:b.fill})}),fill:new ol.style.Fill({color:b.fill}),stroke:new ol.style.Stroke({color:b.stroke,width:b.width})});
|
||||||
|
d instanceof ol.geom.Polygon&&(d=d.getArea(),c.setText(new ol.style.Text({text:[netgis.util.formatArea(d,!0),"4mm sans-serif"],font:"Arial",fill:new ol.style.Fill({color:b.stroke}),backgroundFill:new ol.style.Fill({color:"rgba( 255, 255, 255, 0.5 )"}),padding:[2,4,2,4]})));a=new ol.style.Style({image:new ol.style.Circle({radius:b.radius,fill:new ol.style.Fill({color:b.stroke})}),geometry:this.getGeometryPoints(a)});return[c,a]};
|
||||||
|
netgis.Map.prototype.styleModify=function(a){var b;this.config&&this.config.styles&&this.config.styles.modify&&(b=this.config.styles.modify);b||(b=netgis.Map.Styles.modify);var c=new ol.style.Style({image:new ol.style.Circle({radius:b.radius,fill:new ol.style.Fill({color:b.stroke})}),fill:new ol.style.Fill({color:b.fill}),stroke:new ol.style.Stroke({color:b.stroke,width:b.width})}),d=new ol.style.Style({image:new ol.style.Circle({radius:b.radius,fill:new ol.style.Fill({color:b.stroke})}),geometry:this.getGeometryPoints(a)});
|
||||||
|
a=a.getGeometry();a instanceof ol.geom.Polygon&&(a=a.getArea(),c.setText(new ol.style.Text({text:[netgis.util.formatArea(a,!0),"4mm sans-serif"],font:"Arial",fill:new ol.style.Fill({color:b.stroke}),backgroundFill:new ol.style.Fill({color:"rgba( 255, 255, 255, 0.5 )"}),padding:[2,4,2,4]})));return[c,d]};
|
||||||
|
netgis.Map.prototype.styleHover=function(a){var b;this.config&&this.config.styles&&this.config.styles.select&&(b=this.config.styles.select);b||(b=netgis.Map.Styles.select);return new ol.style.Style({image:new ol.style.Circle({radius:b.radius,fill:new ol.style.Fill({color:b.stroke})}),fill:new ol.style.Fill({color:b.fill}),stroke:new ol.style.Stroke({color:b.stroke,width:b.width}),zIndex:1})};
|
||||||
|
netgis.Map.prototype.getGeometryPoints=function(a){var b=a.getGeometry();if(b instanceof ol.geom.LineString)return new ol.geom.MultiPoint(b.getCoordinates());if(b instanceof ol.geom.Polygon){a=[];b=b.getCoordinates();for(var c=0;c<b.length;c++)for(var d=b[c],e=0;e<d.length;e++)a.push(d[e]);return new ol.geom.MultiPoint(a)}if(b instanceof ol.geom.MultiPolygon){a=[];for(var f=b.getPolygons(),g=0;g<f.length;g++)for(b=f[g].getCoordinates(),c=0;c<b.length;c++)for(d=b[c],e=0;e<d.length;e++)a.push(d[e]);
|
||||||
|
return new ol.geom.MultiPoint(a)}if(b instanceof ol.geom.MultiLineString){a=[];f=b.getPolygons();for(g=0;g<f.length;g++)for(b=f[g].getCoordinates(),c=0;c<b.length;c++)for(d=b[c],e=0;e<d.length;e++)a.push(d[e]);return new ol.geom.MultiPoint(a)}return b};netgis.Map.prototype.redrawVectorLayers=function(){this.map.getLayers().forEach(function(a,b,c){(a instanceof ol.layer.Vector||a instanceof ol.layer.VectorTile)&&a.setStyle(a.getStyle())})};
|
||||||
|
netgis.Map.prototype.setSnapping=function(a){var b=this.config.tools.snapping;a?(this.snap=new ol.interaction.Snap({features:this.snapFeatures,pixelTolerance:b.tolerance?b.tolerance:10}),this.map.addInteraction(this.snap),this.snapFeatures.changed()):this.snap&&(this.map.removeInteraction(this.snap),this.snap=null);this.drawSnapOn=a};netgis.Map.prototype.setDrawTrace=function(a){};netgis.Map.prototype.addSnapLayer=function(a){a=a.getSource().getFeatures();for(var b=0;b<a.length;b++)this.snapFeatures.push(a[b])};
|
||||||
|
netgis.Map.prototype.removeSnapLayer=function(a){a=a.getSource().getFeatures();for(var b=0;b<a.length;b++)this.snapFeatures.remove(a[b])};netgis.Map.prototype.setDrawBuffer=function(a,b,c){if(a){var d=this.createBufferFeature(new ol.geom.Point(this.view.getCenter()),b,c);this.previewLayer.getSource().addFeature(d);this.drawBufferRadius=b;this.drawBufferSegments=c}else this.previewLayer.getSource().clear();this.drawBufferOn=a};
|
||||||
|
netgis.Map.prototype.createLayerTMS=function(a,b,c,d,e){"map"===d&&(this.config.map&&this.config.map.scales?d=this.config.map.scales:(console.error("TMS layer references map scales, but none given in config,",a),d=void 0));"map"===c&&(this.config.map&&this.config.map.extent?c=this.config.map.extent:(console.error("TMS layer references map 'extent', but none given in config 'map',",a),c=void 0));if(b&&c&&(d||e)){if(d)for(e=[],b=0;b<d.length;b++)e.unshift(this.getResolutionFromScale(d[b]));c=new ol.source.TileImage({crossOrigin:null,
|
||||||
|
projection:this.view.getProjection(),tileGrid:new ol.tilegrid.TileGrid({extent:c,origin:c?[c[0],c[1]]:[0,0],resolutions:e}),tileUrlFunction:function(b){if(null!==b){var c=a;c=netgis.util.replace(c,"{z}",b[0]);c=netgis.util.replace(c,"{x}",b[1]);c=netgis.util.replace(c,"{y}",b[2]);return c=netgis.util.replace(c,"{-y}",-b[2]-1)}}});c=new ol.layer.Tile({source:c})}else c=new ol.layer.Tile({source:new ol.source.XYZ({url:a,crossOrigin:"anonymous"})});return c};
|
||||||
|
netgis.Map.prototype.createLayerWMS=function(a,b,c,d,e,f){"image/tiff"===c&&(console.error("WMS layer format 'image/tiff' detected but not supported in OL, reverting to 'image/png' for '"+a+"'"),c="image/png");a={url:a,params:{LAYERS:b,FORMAT:c?c:"image/png",TRANSPARENT:"true"},hidpi:!1};e&&f&&(a.imageLoadFunction=function(a,b){var c=new XMLHttpRequest;c.open("GET",b);c.setRequestHeader("Authorization","Basic "+window.btoa(e+":"+f));c.onload=function(){a.getImage().src=b};c.send()});d?(d=new ol.source.TileWMS(a),
|
||||||
|
d=new ol.layer.Tile({source:d})):(d=new ol.source.ImageWMS(a),d=new ol.layer.Image({source:d}));return d};
|
||||||
|
netgis.Map.prototype.createLayerWMST=function(a,b,c,d,e,f){"image/tiff"===c&&(console.error("WMST layer format 'image/tiff' detected but not supported in OL, reverting to 'image/png' for '"+a+"'"),c="image/png");a={url:a,params:{LAYERS:b,FORMAT:c?c:"image/png",TRANSPARENT:"true",VERSION:"1.1.1"},hidpi:!1};e&&f&&(a.imageLoadFunction=function(a,b){var c=new XMLHttpRequest;c.open("GET",b);c.setRequestHeader("Authorization","Basic "+window.btoa(e+":"+f));c.onload=function(){a.getImage().src=b};c.send()});
|
||||||
|
d?(d=new ol.source.TileWMS(a),d=new ol.layer.Tile({source:d})):(d=new ol.source.ImageWMS(a),d=new ol.layer.Image({source:d}));return d};
|
||||||
|
netgis.Map.prototype.createLayerWMTS=function(a){for(var b=[],c=this.client.config.map.scales,d=this.client.config.map.extent,e=0;e<c.length;e++)b.unshift(this.getResolutionFromScale(c[e]));b=new ol.source.TileImage({crossOrigin:null,projection:this.view.getProjection(),tileGrid:new ol.tilegrid.TileGrid({extent:d,origin:[d[0],d[1]],resolutions:b}),tileUrlFunction:function(b){if(null!==b){var c=a;c=netgis.util.replace(c,"{z}",b[0]);c=netgis.util.replace(c,"{x}",b[1]);c=netgis.util.replace(c,"{y}",
|
||||||
|
b[2]);return c=netgis.util.replace(c,"{-y}",-b[2])}}});return new ol.layer.Tile({source:b})};
|
||||||
|
netgis.Map.prototype.createLayerWMTS_01=function(a,b){for(var c=this.view.getProjection().getExtent(),d=ol.extent.getWidth(c)/256,e=Array(14),f=Array(14),g=0;14>g;++g)e[g]=d/Math.pow(2,g),f[g]=g;source=new ol.source.WMTS({url:a,params:{LAYER:b,FORMAT:"image/png",TRANSPARENT:"true",VERSION:"1.1.1"},layer:b,format:"image/jpeg",matrixSet:"UTM32",tileGrid:new ol.tilegrid.WMTS({origin:ol.extent.getTopLeft(c),resolutions:e,matrixIds:f})})};
|
||||||
|
netgis.Map.prototype.createLayerGeoJSON=function(a){if(netgis.util.isObject(a)){var b=new ol.format.GeoJSON,c=b.readProjection(a);a=b.readFeatures(a,{featureProjection:this.view.getProjection()});c=c.getCode();switch(c){case "EPSG:3857":case "EPSG:4326":case this.view.getProjection().getCode():break;default:console.warn("unsupported import projection '"+c+"'")}var d=new ol.layer.Vector({source:new ol.source.Vector({features:a})});return d}if(netgis.util.isString(a)){d=new ol.layer.Vector({source:new ol.source.Vector({features:[]})});
|
||||||
|
var e=this;netgis.util.request(a,function(a){a=JSON.parse(a);a=e.createLayerGeoJSON(a);d.getSource().addFeatures(a.getSource().getFeatures())});return d}};
|
||||||
|
netgis.Map.prototype.createLayerGML=function(a){console.warn("GML support is experimental!");var b=[];a=(new DOMParser).parseFromString(a,"text/xml").getElementsByTagName("gml:featureMember");for(var c=0;c<a.length;c++){for(var d={},e=a[c].children[0],f=0;f<e.attributes.length;f++){var g=e.attributes[f];d[g.nodeName]=g.nodeValue}for(f=0;f<e.children.length;f++)if(g=e.children[f],"ogr:geometryProperty"!==g.nodeName){var h=g.nodeName.split(":");d[h[h.length-1]]=g.innerHTML}e=e.getElementsByTagName("ogr:geometryProperty")[0].children[0];
|
||||||
|
(f=e.getAttribute("srsName"))&&"EPSG:4326"!==f&&f!==this.projection&&console.warn("unsupported import projection:",f);switch(e.nodeName){case "gml:Polygon":d.geometry=this.gmlParsePolygon(e,f);break;case "gml:MultiPolygon":d.geometry=this.gmlParseMultiPolygon(e,f)}d=new ol.Feature(d);b.push(d)}return new ol.layer.Vector({source:new ol.source.Vector({features:b})})};
|
||||||
|
netgis.Map.prototype.gmlParsePolygon=function(a,b){var c=[];a=a.getElementsByTagName("gml:LinearRing");for(var d=0;d<a.length;d++){var e=a[d].getElementsByTagName("gml:coordinates")[0].innerHTML;c.push(this.gmlParseCoordinates(e,b))}return new ol.geom.Polygon(c)};netgis.Map.prototype.gmlParseMultiPolygon=function(a,b){var c=[];a=a.getElementsByTagName("gml:polygonMember");for(var d=0;d<a.length;d++){var e=a[d].getElementsByTagName("gml:Polygon")[0];c.push(this.gmlParsePolygon(e,b))}return new ol.geom.MultiPolygon(c)};
|
||||||
|
netgis.Map.prototype.gmlParseCoordinates=function(a,b){a=a.split(" ");for(var c=0;c<a.length;c++){a[c]=a[c].split(",");for(var d=0;d<a[c].length;d++)a[c][d]=Number.parseFloat(a[c][d]);b&&(a[c]=ol.proj.transform(a[c],b,this.view.getProjection()))}return a};
|
||||||
|
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 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,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,
|
||||||
|
width:h.width})});f.setStyle(h)}b.getSource().addFeatures(a)});return b};netgis.Map.prototype.createBufferFeature=function(a,b,c){a=this.createBufferGeometry(a,b,c);return new ol.Feature({geometry:a})};netgis.Map.prototype.createBufferGeometry=function(a,b,c){var d=new jsts.io.OL3Parser;a=d.read(a).buffer(b,c);if(this.boundsLayer)for(b=this.boundsLayer.getSource().getFeatures(),c=0;c<b.length;c++){var e=d.read(b[c].getGeometry());a.intersects(e)&&(a=a.intersection(e))}return d.write(a)};
|
||||||
|
netgis.Map.prototype.splitMultiPolygons=function(a){a=a.getSource();for(var b=a.getFeatures(),c=[],d=[],e=0;e<b.length;e++){var f=b[e],g=f.getGeometry();if(g instanceof ol.geom.MultiPolygon){g=g.getPolygons();for(var h=0;h<g.length;h++){var k=new ol.Feature({geometry:g[h]});d.push(k)}c.push(f)}}for(e=0;e<c.length;e++)a.removeFeature(c[e]);a.addFeatures(d)};
|
||||||
|
netgis.Map.prototype.clearSketchFeatures=function(){for(var a=this.editLayer.getSource(),b=0;b<this.sketchFeatures.length;b++)a.removeFeature(this.sketchFeatures[b]);this.sketchFeatures=[]};
|
||||||
|
netgis.Map.prototype.updateDrawBufferPreview=function(){if(!1!==this.config.tools.editable){var a=this.interactions[this.mode][0].getOverlay().getSource().getFeatures();if(!(1>a.length)){var b=this.previewLayer.getSource().getFeatures()[0];b&&(a=a[0].getGeometry(),a=this.createBufferGeometry(a,this.drawBufferRadius,this.drawBufferSegments),b.setGeometry(a))}}};
|
||||||
|
netgis.Map.prototype.isPointInsideLayer=function(a,b){a=a.getSource().getFeatures();for(var c=0;c<a.length;c++)if(a[c].getGeometry().intersectsCoordinate(b))return!0;return!1};
|
||||||
|
netgis.Map.prototype.isGeomInsideLayer=function(a,b){var c=b.getCoordinates();if(b instanceof ol.geom.LineString){if(2>c.length)return!1}else if(b instanceof ol.geom.Polygon&&(c=c[0],4>c.length||0>=b.getArea()))return!1;c=new jsts.io.OL3Parser;b=c.read(b);a=a.getSource().getFeatures();for(var d=0;d<a.length;d++){var e=a[d].getGeometry();if(c.read(e).contains(b))return!0}return!1};netgis.Map.prototype.getScaleFromResolution=function(a){return Math.round(2834.6472*a)};
|
||||||
|
netgis.Map.prototype.getResolutionFromScale=function(a){var b=39.3701*ol.proj.Units.METERS_PER_UNIT[this.view.getProjection().getUnits()];return 1/(this.normalizeScale(a)*b*72)};netgis.Map.prototype.normalizeScale=function(a){return 1<a?1/a:a};
|
||||||
|
netgis.Map.prototype.updateEditOutput=function(){var a=this.editLayer.getSource().getFeatures(),b=this.view.getProjection().getCode(),c=(new ol.format.GeoJSON).writeFeaturesObject(a,{dataProjection:b,featureProjection:b});c.crs={type:"name",properties:{name:"urn:ogc:def:crs:"+b.replace(":","::")}};for(var d=b=0;d<a.length;d++){var e=a[d].getGeometry();e instanceof ol.geom.Polygon&&(b+=e.getArea())}c.area=b;netgis.util.invoke(this.container,netgis.Events.MAP_EDIT_LAYER_CHANGE,{geojson:c})};
|
||||||
|
netgis.Map.prototype.updateSnapFeatures=function(){this.snapFeatures.clear();var a=this;this.map.getLayers().forEach(function(b,c,d){c=b.get("id");c!==netgis.Client.Layers.PARCEL_DISTRICTS&&c!==netgis.Client.Layers.PARCEL_FIELDS&&c!==netgis.Client.Layers.PARCEL_FEATURES&&b instanceof ol.layer.Vector&&a.addSnapLayer(b)})};netgis.Map.prototype.zoom=function(a){this.view.animate({zoom:this.view.getZoom()+a,duration:200})};
|
||||||
|
netgis.Map.prototype.zoomLevel=function(a){this.view.animate({zoom:a,center:this.view.getCenter(),duration:300})};netgis.Map.prototype.zoomCoords=function(a,b,c){this.view.animate({zoom:c,center:[a,b],duration:500})};netgis.Map.prototype.zoomLonLat=function(a,b,c){this.view.animate({zoom:c,center:ol.proj.fromLonLat([a,b],this.view.getProjection()),duration:500})};
|
||||||
|
netgis.Map.prototype.zoomExtentLonLat=function(a,b,c,d){a=ol.proj.fromLonLat([a,b],this.view.getProjection());c=ol.proj.fromLonLat([c,d],this.view.getProjection());this.view.fit([a[0],a[1],c[0],c[1]])};netgis.Map.prototype.zoomExtent=function(a,b,c,d){this.view.fit([a,b,c,d])};netgis.Map.prototype.zoomBBox=function(a,b){this.view.fit(a,{duration:b})};netgis.Map.prototype.zoomScale=function(a,b){b?this.view.animate({resolution:this.getResolutionFromScale(a),duration:500}):this.view.setResolution(this.getResolutionFromScale(a))};
|
||||||
|
netgis.Map.prototype.zoomFeature=function(a,b){a=this.layers[a].getSource().getFeatureById(b);this.view.fit(a.getGeometry().getExtent(),{duration:500})};netgis.Map.prototype.zoomFeatures=function(a){if(a&&!(1>a.length)){for(var b=a[0].getGeometry().getExtent(),c=1;c<a.length;c++)b=ol.extent.extend(b,a[c].getGeometry().getExtent());this.view.fit(b,{duration:0,padding:this.view.padding})}};
|
||||||
|
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 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()};
|
||||||
|
netgis.Map.prototype.onPanelToggle=function(a){a=!1;for(var b=0,c=this.container.parentNode.getElementsByClassName("netgis-panel"),d=0;d<c.length;d++)if(c[d].classList.contains("netgis-show")){a=!0;b=c[d].getBoundingClientRect().width;break}a?this.setPadding(0,0,0,b):this.setPadding(0,0,0,0);this.redrawVectorLayers()};netgis.Map.prototype.onMapZoom=function(a){this.zoom(a.detail.delta)};
|
||||||
|
netgis.Map.prototype.onMapZoomHome=function(a){a=this.config;if(a.map.bbox)this.zoomBBox(a.map.bbox,500);else if(a.map.center){var b=a.map.center;this.zoomCoords(b[0],b[1],a.map.zoom)}else a.map.center_lonlat&&(b=a.map.center_lonlat,this.zoomLonLat(b[0],b[1],a.map.zoom))};netgis.Map.prototype.onMapZoomLonLat=function(a){a=a.detail;this.zoomLonLat(a.lon,a.lat,a.zoom)};netgis.Map.prototype.onMapZoomScale=function(a){a=a.detail;this.zoomScale(a.scale,a.anim)};
|
||||||
|
netgis.Map.prototype.onMapZoomLayer=function(a){a=a.detail;var b=this.layers[a.id];b?this.view.fit(b.getSource().getExtent(),{duration:600}):console.warning("trying to zoom non existing layer",a.id)};netgis.Map.prototype.onMapZoomLevel=function(a){this.view.setZoom(a.detail.z)};netgis.Map.prototype.onMapViewPrev=function(a){this.gotoViewHistory(this.viewIndex-1)};netgis.Map.prototype.onMapViewNext=function(a){this.gotoViewHistory(this.viewIndex+1)};
|
||||||
|
netgis.Map.prototype.onMapLayerToggle=function(a){a=a.detail;switch(a.id){case netgis.LayerID.EDITABLE:a.on?this.map.addLayer(this.editLayer):this.map.removeLayer(this.editLayer);break;case netgis.LayerID.NON_EDITABLE:a.on?this.map.addLayer(this.nonEditLayer):this.map.removeLayer(this.nonEditLayer);break;default:if(a.on)for(var b=this.config.layers,c=0;c<b.length;c++){var d=b[c];d.id===a.id&&this.addLayer(a.id,d)}else this.removeLayer(a.id)}};
|
||||||
|
netgis.Map.prototype.onMapLayerTransparency=function(a){a=a.detail;var b=this.layers[a.id];b||(netgis.util.invoke(this.container,netgis.Events.MAP_LAYER_TOGGLE,{id:a.id,on:!0}),b=this.layers[a.id]);b.setOpacity(1-a.transparency)};netgis.Map.prototype.onMapLayerOrder=function(a){a=a.detail;var b=this.layers[a.id];b&&b.setZIndex(a.order)};netgis.Map.prototype.onMapLayerCreate=function(a){a=a.detail;this.addLayer(a.id,a)};netgis.Map.prototype.onMapLayerDelete=function(a){this.removeLayer(a.detail.id)};
|
||||||
|
netgis.Map.prototype.onMapSnapToggle=function(a){this.setSnapping(a.detail.on)};netgis.Map.prototype.onMapMoveEnd=function(a){a=this.view.getCenter();var b=this.view.getZoom(),c=this.getScaleFromResolution(this.view.getResolution());!1===this.viewFromHistory&&this.addViewHistory(a,b);netgis.util.invoke(this.container,netgis.Events.MAP_VIEW_CHANGE,{center:a,zoom:b,scale:c});this.viewFromHistory=!1};
|
||||||
|
netgis.Map.prototype.onPointerMove=function(a){var b=a.pixel;a=a.coordinate;var c=null,d=null,e=void 0,f=this;this.map.forEachFeatureAtPixel(b,function(a,b){if(b&&b!==f.measureLayer&&b!==f.nonEditLayer)if(b===f.boundsLayer)e=a;else if(b!==f.previewLayer)return c=a,d=b,!0});switch(this.mode){case netgis.Modes.VIEW:0===this.getQueryableLayers(!0).length?c?this.container.classList.add("netgis-clickable"):this.container.classList.remove("netgis-clickable"):this.container.classList.add("netgis-clickable");
|
||||||
|
break;case netgis.Modes.DRAW_POINTS:case netgis.Modes.DRAW_LINES:this.updateDrawBufferPreview()}if(this.boundsLayer&&(this.mode===netgis.Modes.DRAW_POINTS||this.mode===netgis.Modes.DRAW_LINES||this.mode===netgis.Modes.DRAW_POLYGONS)){if(e)this.container.classList.remove("netgis-not-allowed"),this.container.removeAttribute("title");else{this.container.classList.add("netgis-not-allowed");var g=this.config.tools.bounds_message;g&&0<g.length&&this.container.setAttribute("title",g)}this.hoverBounds=e}g=
|
||||||
|
!0;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);if(c!==this.hoverFeature&&g){if(this.hoverFeature)this.onFeatureLeave(this.hoverFeature,this.hoverLayer,b,a);if(c)this.onFeatureEnter(c,d,b,a);this.redrawVectorLayers();this.hoverFeature=c;this.hoverLayer=d}if(c)this.onFeatureHover(c,
|
||||||
|
d,b,a)};netgis.Map.prototype.onPointerLeave=function(a){this.hoverFeature&&(this.onFeatureLeave(this.hoverFeature,this.hoverLayer,[a.offsetX,a.offsetY],null),this.hoverLayer=this.hoverFeature=null)};
|
||||||
|
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++)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]&&
|
||||||
|
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()}a.preventDefault();return!1};
|
||||||
|
netgis.Map.prototype.onKeyDown=function(a){a=a.keyCode||a.which;switch(this.mode){case netgis.Modes.MEASURE_LINE:13===a&&this.interactions[netgis.Modes.MEASURE_LINE][2].finishDrawing();27===a&&this.interactions[netgis.Modes.MEASURE_LINE][2].abortDrawing();break;case netgis.Modes.MEASURE_AREA:13===a&&this.interactions[netgis.Modes.MEASURE_AREA][2].finishDrawing();27===a&&this.interactions[netgis.Modes.MEASURE_AREA][2].abortDrawing();break;case netgis.Modes.DRAW_LINES:var b=this.interactions[netgis.Modes.DRAW_LINES][0];
|
||||||
|
13===a&&b.finishDrawing();27===a&&b.abortDrawing();8===a&&b.removeLastPoint();46===a&&b.abortDrawing();break;case netgis.Modes.DRAW_POLYGONS:b=this.interactions[netgis.Modes.DRAW_POLYGONS][0];13===a&&b.finishDrawing();27===a&&b.abortDrawing();8===a&&b.removeLastPoint();46===a&&b.abortDrawing();break;case netgis.Modes.CUT_FEATURES_DRAW:b=this.interactions[netgis.Modes.CUT_FEATURES_DRAW][0],13===a&&b.finishDrawing(),27===a&&b.abortDrawing(),8===a&&b.removeLastPoint(),46===a&&b.abortDrawing(),16===a&&
|
||||||
|
netgis.util.invoke(this.container,netgis.Events.CLIENT_SET_MODE,{mode:netgis.Modes.CUT_FEATURES})}16===a&&!1===this.selectMultiple&&netgis.util.invoke(this.container,netgis.Events.SELECT_MULTI_TOGGLE,{on:!0})};
|
||||||
|
netgis.Map.prototype.onKeyUp=function(a){a=a.keyCode||a.which;switch(this.mode){case netgis.Modes.BUFFER_FEATURES:this.selectMultiple&&netgis.util.invoke(this.container,netgis.Events.CLIENT_SET_MODE,{mode:netgis.Modes.BUFFER_FEATURES_EDIT});break;case netgis.Modes.CUT_FEATURES:this.selectMultiple&&netgis.util.invoke(this.container,netgis.Events.CLIENT_SET_MODE,{mode:netgis.Modes.CUT_FEATURES_DRAW})}16===a&&(netgis.util.invoke(this.container,netgis.Events.SELECT_MULTI_TOGGLE,{on:!1}),this.selectReset=
|
||||||
|
!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){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)};
|
||||||
|
netgis.Map.prototype.onGeolocChange=function(a){a=a.detail;this.geolocLayer.getSource().getFeatures()[0].getGeometry().setCoordinates(ol.proj.fromLonLat([a.lon,a.lat],this.view.getProjection()));!0===a.center&&this.zoomLonLat(a.lon,a.lat,this.view.getZoom())};netgis.Map.prototype.onMeasureLineBegin=function(a){this.measureLayer.getSource().clear()};netgis.Map.prototype.onMeasureAreaBegin=function(a){this.measureLayer.getSource().clear()};netgis.Map.prototype.onMeasureClear=function(a){this.measureLayer.getSource().clear()};
|
||||||
|
netgis.Map.prototype.onDrawBufferEnd=function(a){var b=a.feature;a=this.previewLayer.getSource().getFeatures();if(0!==a.length){a=a[0];if(this.boundsLayer){var c=!0;c=b.getGeometry()instanceof ol.geom.Point?this.isPointInsideLayer(this.boundsLayer,b.getGeometry().getCoordinates()):this.isGeomInsideLayer(this.boundsLayer,b.getGeometry());if(!c)return;c=new jsts.io.OL3Parser;for(var d=c.read(a.getGeometry()),e=this.boundsLayer.getSource().getFeatures(),f=0;f<e.length;f++){var g=c.read(e[f].getGeometry());
|
||||||
|
d.intersects(g)&&(d=d.intersection(g))}c=c.write(d);a.setGeometry(c)}var h=this.editLayer.getSource();h.addFeature(a.clone());window.setTimeout(function(){h.removeFeature(b)},10)}};netgis.Map.prototype.onSelectMultiToggle=function(a){this.selectMultiple=a.detail.on};netgis.Map.prototype.onDrawBufferToggle=function(a){a=a.detail;this.setDrawBuffer(a.on,a.radius,a.segments)};
|
||||||
|
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.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;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))};
|
||||||
|
netgis.Menu.prototype.addHeader=function(a){var b=document.createElement("h1");b.className="netgis-hover-c";b.innerHTML=a;this.container.appendChild(b);return b};netgis.Menu.prototype.addButton=function(a,b){a=this.createButton(a,b);this.container.appendChild(a);return a};netgis.Menu.prototype.addLink=function(a,b){a=this.createLink(a,b);this.container.appendChild(a);return a};
|
||||||
|
netgis.Menu.prototype.addSelect=function(a,b,c,d){var e=document.createElement("span");e.className="netgis-wrapper netgis-hover-c";var f=document.createElement("select");f.setAttribute("data-id",a);for(var g in c){a=c[g];var h=document.createElement("option");h.setAttribute("value",g);h.innerHTML=a;f.appendChild(h)}f.value=d;f.addEventListener("change",this.onSelectChange.bind(this));e.appendChild(f);b&&(c=document.createElement("span"),c.className="netgis-icon",c.innerHTML=b,e.appendChild(c));this.container.appendChild(e);
|
||||||
|
return f};netgis.Menu.prototype.addDropdown=function(a,b){var c=document.createElement("div");c.className="netgis-dropdown netgis-hover-c";var d=document.createElement("button");d.setAttribute("type","button");d.addEventListener("click",this.onDropdownClick.bind(this));d.innerHTML=a;c.appendChild(d);a=document.createElement("ul");a.className="netgis-color-e netgis-shadow";c.appendChild(a);for(d=0;d<b.length;d++)a.appendChild(this.createMenuItem(b[d]));this.container.appendChild(c);return c};
|
||||||
|
netgis.Menu.prototype.getScaleItems=function(){var a=[];if(!this.config||!this.config.map||!this.config.map.scales)return a;for(var b=this.config.map.scales,c=0;c<b.length;c++)a.push({id:netgis.Commands.ZOOM_SCALE,title:"1:"+b[c]});return a};
|
||||||
|
netgis.Menu.prototype.createMenuItem=function(a){var b=document.createElement("li");b.className="netgis-hover-c";var c=a.items;if("scales"===a.id)for(var d=this.getScaleItems(),e=0;e<d.length;e++)c.push(d[e]);if(c&&0<c.length)a=this.createMenu(a.title,c),b.appendChild(a.button),b.appendChild(a.list);else if(a.type)switch(a.type){case "checkbox":a=this.createCheckbox(a.id,a.title,a.value);b.appendChild(a);break;default:console.error("unhandled menu item type",a.type,"for",a.id)}else a.url?(a=this.createLink(a.url,
|
||||||
|
a.title),b.appendChild(a)):(a=this.createButton(a.id,a.title),b.appendChild(a));return b};netgis.Menu.prototype.createMenu=function(a,b){var c=document.createElement("button");c.setAttribute("type","button");c.addEventListener("pointerdown",this.onButtonClick.bind(this));c.innerHTML=a;a=document.createElement("ul");a.className="netgis-color-e netgis-shadow";for(var d=0;d<b.length;d++)a.appendChild(this.createMenuItem(b[d]));return{button:c,list:a}};
|
||||||
|
netgis.Menu.prototype.createLink=function(a,b){var c=document.createElement("a");c.setAttribute("href",a);c.setAttribute("target","_blank");c.className="netgis-button netgis-text-e netgis-hover-c";c.innerHTML=b;return c};netgis.Menu.prototype.createButton=function(a,b){var c=document.createElement("button");c.className="netgis-text-e netgis-hover-c";c.setAttribute("type","button");c.setAttribute("data-id",a);c.addEventListener("pointerdown",this.onButtonClick.bind(this));c.innerHTML=b;return c};
|
||||||
|
netgis.Menu.prototype.createCheckbox=function(a,b,c){var d=document.createElement("label");d.className="netgis-button";var e=document.createElement("input");e.setAttribute("type","checkbox");e.setAttribute("data-id",a);e.addEventListener("change",this.onCheckboxChange.bind(this));e.checked=c;d.appendChild(e);a=document.createElement("span");a.innerHTML=b;d.appendChild(a);return d};netgis.Menu.prototype.onToggleClick=function(a){this.container.classList.toggle("netgis-menu-large")};
|
||||||
|
netgis.Menu.prototype.onButtonClick=function(a){a=a.currentTarget;var b=a.getAttribute("data-id");this.container.classList.remove("netgis-menu-large");this.container.scrollTop=0;netgis.util.invoke(a,netgis.Events.MENU_BUTTON_CLICK,{id:b});netgis.Client.handleCommand(a,b)};
|
||||||
|
netgis.Menu.prototype.onCheckboxChange=function(a){a=a.currentTarget;var b=a.getAttribute("data-id"),c=a.checked;netgis.util.invoke(a,netgis.Events.MENU_CHECKBOX_CHANGE,{id:b,checked:c});switch(b){case netgis.Menu.ItemID.SNAP_TOGGLE:netgis.util.invoke(a,netgis.Events.MAP_SNAP_TOGGLE,{on:c});break;default:console.error("unhandled menu item id",b)}};
|
||||||
|
netgis.Menu.prototype.onSelectChange=function(a){a=a.currentTarget;var b=a.getAttribute("data-id"),c=a.value;netgis.util.invoke(a,netgis.Events.MENU_SELECT_CHANGE,{id:b,value:c});switch(b){case "scales":netgis.util.invoke(a,netgis.Events.MAP_ZOOM_SCALE,{scale:Number.parseInt(c)})}};
|
||||||
|
netgis.Menu.prototype.onMapViewChange=function(a){a=a.detail;for(var b=a.scale,c=this.container.getElementsByTagName("button"),d=0;d<c.length;d++){var e=c[d];"zoom_scale"===e.getAttribute("data-id")&&(Number.parseInt(e.innerText.split(":")[1])===b?e.classList.add("netgis-bold"):e.classList.remove("netgis-bold"))}c=this.container.getElementsByTagName("select");for(d=0;d<c.length;d++){e=c[d];if("scales"===!e.getAttribute("data-id"))break;for(var f=!1,g=this.config.map.scales,h=0;h<g.length;h++)if(g[h]===
|
||||||
|
b){f=!0;break}f?e.options[0].classList.add("netgis-hide"):(e.options[0].setAttribute("value",a.scale),e.options[0].innerHTML="1:"+a.scale,e.options[0].classList.remove("netgis-hide"));e.value=b}};netgis.Menu.prototype.onDropdownClick=function(a){a.currentTarget.parentNode.classList.toggle("netgis-active")};netgis=netgis||{};netgis.Modal=function(a){this.initElements(a);this.initEvents()};netgis.Modal.prototype.initElements=function(a){this.container=document.createElement("div");this.container.className="netgis-modal";this.container.addEventListener("click",this.onContainerClick.bind(this));this.content=document.createElement("div");this.content.className="netgis-color-e netgis-shadow";this.container.appendChild(this.content);this.header=this.addHeader(this.content,a,this.onHeaderClick.bind(this))};
|
||||||
|
netgis.Modal.prototype.initEvents=function(){};netgis.Modal.prototype.attachTo=function(a){a.appendChild(this.container)};netgis.Modal.prototype.show=function(){this.container.classList.add("netgis-show")};netgis.Modal.prototype.hide=function(){this.container.classList.remove("netgis-show")};
|
||||||
|
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.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}))};
|
||||||
|
netgis.Panel.prototype.toggle=function(){this.container.classList.toggle("netgis-show");var a=this.container.classList.contains("netgis-show");netgis.util.invoke(this.container,netgis.Events.PANEL_TOGGLE,{container:this.container,visible:a,width:a?this.container.getBoundingClientRect().width:void 0})};netgis.Panel.prototype.visible=function(){return this.container.classList.contains("netgis-show")};netgis.Panel.prototype.width=function(){return this.container.getBoundingClientRect().width};
|
||||||
|
netgis.Panel.prototype.setTitle=function(a){this.header.getElementsByTagName("span")[0].innerHTML=a};netgis.Panel.prototype.onHeaderClick=function(a){this.hide()};netgis.Panel.prototype.onResize=function(a){this.container.classList.contains("netgis-show")&&(a=this.container.getBoundingClientRect(),netgis.util.invoke(this.container,netgis.Events.PANEL_RESIZE,{width:a.width}))};netgis.Panel.prototype.onPanelToggle=function(a){a=a.detail;a.visible&&a.container!==this.container&&this.hide()};netgis=netgis||{};netgis.Plugins=function(a){this.config=a;this.plugins={};this.initConfig(a)};netgis.Plugins.Config={};
|
||||||
|
netgis.Plugins.prototype.initConfig=function(a){if(a=a.plugins)for(var b=0;b<a.length;b++){var c=a[b],d={};switch(c.type){case "panel":var e=new netgis.Panel(c.title);e.container.classList.add("netgis-plugin");c.active&&e.show();d.panel=e;break;case "window":e=new netgis.Window(c.title),e.container.classList.add("netgis-plugin"),c.active&&e.show(),d.window=e}if(e&&(e.container.setAttribute("data-id",c.id),c.url&&0<c.url.length)){var f=document.createElement("iframe");f.setAttribute("name",c.id);f.setAttribute("title",
|
||||||
|
c.title);f.setAttribute("src",c.url);f.setAttribute("data-id",c.id);f.onload=this.onIFrameLoad.bind(this);d.iframe=f;e.content.appendChild(f)}this.plugins[c.id]=d}};
|
||||||
|
netgis.Plugins.prototype.attachTo=function(a){for(var b in this.plugins){var c=this.plugins[b];c.panel&&c.panel.attachTo(a);c.window&&c.window.attachTo(a)}a.addEventListener(netgis.Events.PLUGIN_TOGGLE,this.onPluginToggle.bind(this));a.addEventListener(netgis.Events.PANEL_TOGGLE,this.onPanelToggle.bind(this));for(var d in netgis.Events)a.addEventListener(netgis.Events[d],this.onClientEvent.bind(this))};
|
||||||
|
netgis.Plugins.prototype.onPluginToggle=function(a){a=this.plugins[a.detail.id];a.panel&&a.panel.toggle();a.window&&a.window.toggle()};netgis.Plugins.prototype.onIFrameLoad=function(a){var b=a.target,c;for(c in netgis.Events)b.contentDocument.addEventListener(netgis.Events[c],function(a){this.onIFrameEvent(a,b.getAttribute("data-id"))}.bind(this))};netgis.Plugins.prototype.onIFrameMessage=function(a){console.info("IFrame Message:",a)};
|
||||||
|
netgis.Plugins.prototype.onIFrameEvent=function(a,b){var c=a.explicitOriginalTarget,d=a.detail;b=this.plugins[b];b.panel&&!b.panel.container.parentNode.contains(c)&&netgis.util.invoke(b.panel.container,a.type,d);b.window&&!b.window.container.parentNode.contains(c)&&netgis.util.invoke(b.window.container,a.type,d)};
|
||||||
|
netgis.Plugins.prototype.onClientEvent=function(a){var b=a.srcElement,c=a.type;a=a.detail;if(!b.classList.contains("netgis-plugin"))for(var d in this.plugins){var e=this.plugins[d];e.panel&&e.panel.container===b||e.window&&e.window.container===b||netgis.util.invoke(e.iframe.contentDocument,c,a)}};netgis.Plugins.prototype.onPanelToggle=function(a){a=a.detail;if(a.visible)for(var b in this.plugins){var c=this.plugins[b];c.panel&&a.container!==c.panel.container&&c.panel.hide()}};netgis=netgis||{};netgis.Popup=function(a){a||(a={direction:"down"});this.options=a;this.initElements()};
|
||||||
|
netgis.Popup.prototype.initElements=function(){document.body.addEventListener("pointerdown",this.onDocumentPointerDown.bind(this));this.container=document.createElement("div");this.container.className="netgis-popup";this.container.addEventListener("pointerdown",this.onPointerDown.bind(this));this.content=document.createElement("div");this.content.className="netgis-content netgis-color-e netgis-round";this.container.appendChild(this.content);this.content.addEventListener("pointermove",function(a){a.stopPropagation()});
|
||||||
|
switch(this.options.direction){default:case "down":this.container.classList.add("netgis-dir-down");break;case "right":this.container.classList.add("netgis-dir-right")}this.arrow=document.createElement("div");this.arrow.className="netgis-arrow";this.container.appendChild(this.arrow);this.closer=document.createElement("button");this.closer.setAttribute("type","button");this.closer.className="netgis-closer netgis-color-e netgis-text-a";this.closer.innerHTML="<span></span><i class='fas fa-times'></i>";
|
||||||
|
this.closer.onclick=this.onCloserClick.bind(this);this.content.appendChild(this.closer);this.loader=document.createElement("div");this.loader.className="netgis-loader netgis-color-e netgis-text-a";this.loader.innerHTML="<i class='netgis-icon netgis-anim-spin fas fa-sync-alt'></i>";this.wrapper=document.createElement("div");this.wrapper.className="netgis-wrapper";this.content.appendChild(this.wrapper)};netgis.Popup.prototype.attachTo=function(a){a.appendChild(this.container)};
|
||||||
|
netgis.Popup.prototype.show=function(){this.container.classList.add("netgis-show");netgis.util.isMobile()&&(this.container.style.width=document.body.getBoundingClientRect().width-10+"px")};netgis.Popup.prototype.hide=function(){this.container.classList.remove("netgis-show")};netgis.Popup.prototype.isVisible=function(){return this.container.classList.contains("netgis-show")};netgis.Popup.prototype.showLoader=function(){this.content.appendChild(this.loader)};
|
||||||
|
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.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: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"}};
|
||||||
|
netgis.SearchParcel.prototype.initElements=function(){this.panel=new netgis.Panel("Flurst\u00fccks-Suche");this.panel.container.style.minWidth="92mm";this.panel.container.addEventListener(netgis.Events.PANEL_TOGGLE,this.onPanelToggle.bind(this));this.container=document.createElement("section");this.container.className="netgis-search-parcel";this.panel.content.appendChild(this.container);this.popup=new netgis.Popup;this.popup.setHeader("Flurst\u00fcck");var a=document.createElement("section");this.top=
|
||||||
|
a;this.container.appendChild(a);var b=this.createInput("Gemarkungsname:");b.style.position="relative";a.appendChild(b);this.nameInput=b.children[0];this.nameInput.setAttribute("title","ENTER: Ausw\u00e4hlen, ESCAPE: Zur\u00fccksetzen");this.nameInput.addEventListener("keyup",this.onInputNameKey.bind(this));this.nameLoader=document.createElement("div");this.nameLoader.className="netgis-loader netgis-text-primary netgis-hide";this.nameLoader.innerHTML="<i class='fas fa-spinner'></i>";b.appendChild(this.nameLoader);
|
||||||
|
this.nameList=document.createElement("ul");a.appendChild(this.nameList);b=this.createInput("Gemarkungsnummer:");this.districtInput=b.children[0];a.appendChild(b);b=this.createInput("Flurnummer:");this.fieldInput=b.children[0];this.fieldInput.addEventListener("keyup",this.onInputFieldKey.bind(this));a.appendChild(b);b=this.createInput("<span>Flurst\u00fccksnummer (Z\u00e4hler/Nenner):</span>");this.parcelInputA=b.children[1];this.parcelInputA.style.width="48%";this.parcelInputB=this.parcelInputA.cloneNode(!0);
|
||||||
|
this.parcelInputB.style.marginLeft="4%";b.appendChild(this.parcelInputB);a.appendChild(b);b=document.createElement("button");b.setAttribute("type","button");b.addEventListener("click",this.onParcelSearchClick.bind(this));b.className="netgis-color-a netgis-hover-c";b.innerHTML="Flurst\u00fccke suchen";b.style.marginTop="4mm";a.appendChild(b);b=document.createElement("section");b.className="netgis-hide";this.bottom=b;this.container.appendChild(b);var c=document.createElement("button");c.className="netgis-button netgis-clip-text netgis-color-c netgis-gradient-a";
|
||||||
|
c.innerHTML="<span>Flurst\u00fccke</span> <span></span><i class='netgis-icon fas fa-times'></i>";c.setAttribute("type","button");c.addEventListener("click",this.onBottomHeaderClick.bind(this));b.appendChild(c);this.parcelCount=c.getElementsByTagName("span")[1];this.parcelInfo=document.createElement("p");this.parcelTable=this.createTable(["Flur","Z\u00e4hler","Nenner","FKZ","Fl\u00e4che (qm)"]);this.parcelTable.classList.add("netgis-hide");this.parcelTable.style.position="absolute";this.parcelTable.style.width=
|
||||||
|
"100%";this.parcelTable.style.top="12mm";this.parcelTable.style.bottom="0mm";this.parcelTable.style.margin="0mm";this.parcelTable.style.overflow="auto";b.appendChild(this.parcelTable);this.parcelList=this.parcelTable.getElementsByTagName("tbody")[0];this.parcelReset=document.createElement("button");this.parcelReset.setAttribute("type","button");this.parcelReset.addEventListener("click",this.onResetClick.bind(this));this.parcelReset.className="netgis-color-a netgis-hover-c";this.parcelReset.innerHTML=
|
||||||
|
"Zur\u00fccksetzen";this.parcelReset.style.marginTop="4mm";a.appendChild(this.parcelReset)};netgis.SearchParcel.prototype.initEvents=function(){this.resizeObserver=(new ResizeObserver(this.onTopResize.bind(this))).observe(this.top)};
|
||||||
|
netgis.SearchParcel.prototype.initConfig=function(a){this.districtsLayer=a.searchparcel.districts_service;this.districtsLayer.id=this.districtsLayerID;this.districtsLayer.style=a.styles.parcel;this.districtsLayer.order=99999;a.layers.push(this.districtsLayer);this.fieldsLayer={id:this.fieldsLayerID,type:netgis.LayerTypes.GEOJSON,style:a.styles.parcel,order:99999,data:null};a.layers.push(this.fieldsLayer);this.parcelsLayer={id:this.parcelsLayerID,type:netgis.LayerTypes.WKT,style:a.styles.parcel,order:99999,
|
||||||
|
data:null};a.layers.push(this.parcelsLayer);if(!0===a.searchparcel.open){var b=this;window.setTimeout(function(){b.panel.show()},100)}};
|
||||||
|
netgis.SearchParcel.prototype.attachTo=function(a){this.panel.attachTo(a);this.popup.attachTo(a);a.addEventListener(netgis.Events.CLIENT_SET_MODE,this.onClientSetMode.bind(this));a.addEventListener(netgis.Events.SEARCHPARCEL_TOGGLE,this.onSearchParcelToggle.bind(this));a.addEventListener(netgis.Events.MAP_FEATURE_ENTER,this.onMapFeatureEnter.bind(this));a.addEventListener(netgis.Events.MAP_FEATURE_CLICK,this.onMapFeatureClick.bind(this));a.addEventListener(netgis.Events.MAP_FEATURE_LEAVE,this.onMapFeatureLeave.bind(this));
|
||||||
|
a.addEventListener(netgis.Events.MAP_COPY_FEATURE_TO_EDIT,this.onMapCopyFeatureToEdit.bind(this))};netgis.SearchParcel.prototype.createInput=function(a){var b=document.createElement("label");b.className="netgis-hover-text-primary";b.innerHTML=a;a=document.createElement("input");a.setAttribute("type","text");b.appendChild(a);return b};
|
||||||
|
netgis.SearchParcel.prototype.createNameItem=function(a){var b=document.createElement("li"),c=document.createElement("button");c.setAttribute("type","button");c.addEventListener("click",this.onNameItemClick.bind(this));c.className="netgis-color-e netgis-hover-a netgis-text-a netgis-hover-text-e";c.innerHTML=a;b.appendChild(c);return b};
|
||||||
|
netgis.SearchParcel.prototype.createTable=function(a){var b=document.createElement("div");b.className="netgis-table-wrapper";var c=document.createElement("table");b.appendChild(c);var d=document.createElement("thead");c.appendChild(d);var e=document.createElement("tr");e.className="netgis-color-d netgis-shadow";d.appendChild(e);d=document.createElement("th");e.appendChild(d);var f=document.createElement("input");f.setAttribute("type","checkbox");f.addEventListener("change",this.onTableFilterChange.bind(this));
|
||||||
|
f.setAttribute("title","Nur markierte Parzellen anzeigen");d.appendChild(f);this.tableFilter=f;for(f=0;f<a.length;f++)d=document.createElement("th"),d.innerHTML=a[f],e.appendChild(d);a=document.createElement("tbody");c.appendChild(a);return b};
|
||||||
|
netgis.SearchParcel.prototype.createParcelItem=function(a,b,c,d,e,f,g){var h=document.createElement("tr");h.className="netgis-hover-d";h.setAttribute("title","Klicken zum zoomen");h.setAttribute("data-id",d);h.setAttribute("data-field",a);h.setAttribute("data-parcel-a",b);h.setAttribute("data-parcel-b",c);h.setAttribute("data-bbox",f);h.setAttribute("data-geom",g);h.addEventListener("pointerenter",this.onParcelEnter.bind(this));h.addEventListener("pointerleave",this.onParcelLeave.bind(this));h.addEventListener("click",
|
||||||
|
this.onParcelClick.bind(this));f=document.createElement("td");h.appendChild(f);g=document.createElement("button");g.setAttribute("type","button");g.setAttribute("title","Geometrie \u00fcbernehmen");g.addEventListener("click",this.onParcelImportClick.bind(this));g.className="netgis-hover-a";g.innerHTML="<i class='fas fa-paste'></i>";f.appendChild(g);f=document.createElement("td");f.innerHTML=a;h.appendChild(f);a=document.createElement("td");a.innerHTML=b;h.appendChild(a);b=document.createElement("td");
|
||||||
|
b.innerHTML=c;h.appendChild(b);c=document.createElement("td");c.innerHTML=netgis.util.trim(d,"_");h.appendChild(c);d=document.createElement("td");d.innerHTML=e;h.appendChild(d);return h};
|
||||||
|
netgis.SearchParcel.prototype.reset=function(){this.hideBottom();this.nameLoader.classList.add("netgis-hide");this.nameInput.value="";this.districtInput.value="";this.fieldInput.value="";this.parcelInputA.value="";this.parcelInputB.value="";this.nameList.innerHTML="";this.parcelInfo.innerHTML="";this.parcelList.innerHTML="";this.parcelTable.classList.add("netgis-hide");this.tableFilter.checked=!1;this.parcelList.classList.remove("netgis-filter-active");this.selected={};this.parcelReset.classList.add("netgis-hide");
|
||||||
|
this.parcelCount.innerHTML="";var a=this;window.setTimeout(function(){a.top.scrollTop=0;a.parcelTable.scrollTop=0},10);netgis.util.invoke(this.container,netgis.Events.SEARCHPARCEL_RESET,null);this.panel.visible()&&this.showDistricts(!0);this.showFields(!1);this.showParcels(!1)};
|
||||||
|
netgis.SearchParcel.prototype.showDistricts=function(a){a?(netgis.util.invoke(this.container,netgis.Events.MAP_LAYER_TOGGLE,{id:this.districtsLayerID,on:!0}),netgis.util.invoke(this.container,netgis.Events.MAP_ZOOM_LEVEL,{z:this.config.searchparcel.districts_service.min_zoom})):netgis.util.invoke(this.container,netgis.Events.MAP_LAYER_TOGGLE,{id:this.districtsLayerID,on:!1})};
|
||||||
|
netgis.SearchParcel.prototype.showFields=function(a,b){a?(b.crs={type:"name",properties:{name:"urn:ogc:def:crs:EPSG::25832"}},this.fieldsLayer.data=b,netgis.util.invoke(this.container,netgis.Events.MAP_LAYER_TOGGLE,{id:this.fieldsLayerID,on:!0}),netgis.util.invoke(this.container,netgis.Events.MAP_ZOOM_LAYER,{id:this.fieldsLayerID})):(netgis.util.invoke(this.container,netgis.Events.MAP_LAYER_TOGGLE,{id:this.fieldsLayerID,on:!1}),this.fieldsLayer.data=null)};
|
||||||
|
netgis.SearchParcel.prototype.showParcels=function(a,b){if(a){a=[];for(var c=0;c<b.length;c++){var d=b[c];a.push({id:d.fsk,geometry:d.geometry,properties:{flaeche:d.flaeche,fln:d.fln,fsk:d.fsk,fsn_nen:d.fsn_nen,fsn_zae:d.fsn_zae}})}this.parcelsLayer.data=a;netgis.util.invoke(this.container,netgis.Events.MAP_LAYER_TOGGLE,{id:this.parcelsLayerID,on:!0});netgis.util.invoke(this.container,netgis.Events.MAP_ZOOM_LAYER,{id:this.parcelsLayerID})}else netgis.util.invoke(this.container,netgis.Events.MAP_LAYER_TOGGLE,
|
||||||
|
{id:this.parcelsLayerID,on:!1})};netgis.SearchParcel.prototype.onSearchParcelToggle=function(a){this.panel.toggle()};netgis.SearchParcel.prototype.onClientSetMode=function(a){a=a.detail;this.popup.clearContent();this.popup.hide();a.mode===netgis.Modes.SEARCH_PARCEL?this.reset():(this.showDistricts(!1),this.showFields(!1),this.showParcels(!1))};
|
||||||
|
netgis.SearchParcel.prototype.onPanelToggle=function(a){!1===a.detail.visible?netgis.util.invoke(this.panel.container,netgis.Events.CLIENT_SET_MODE,{mode:netgis.Modes.VIEW}):netgis.util.invoke(this.panel.container,netgis.Events.CLIENT_SET_MODE,{mode:netgis.Modes.SEARCH_PARCEL})};netgis.SearchParcel.prototype.onInputNameKey=function(a){switch(a.keyCode){case 13:this.selectFirstName();break;case 27:this.reset();break;default:this.requestName(this.nameInput.value.trim())}};
|
||||||
|
netgis.SearchParcel.prototype.requestName=function(a){this.nameDebounce&&window.clearTimeout(this.nameDebounce);if(0!==a.length){var b=this.config.searchparcel.name_url;b=netgis.util.replace(b,"{q}",window.encodeURIComponent(a));this.nameDebounce=window.setTimeout(this.onInputNameDebounce.bind(this,b),200);this.nameLoader.classList.remove("netgis-hide")}};netgis.SearchParcel.prototype.onInputNameDebounce=function(a){netgis.util.request(a,this.onInputNameResponse.bind(this))};
|
||||||
|
netgis.SearchParcel.prototype.onInputNameResponse=function(a){this.nameLoader.classList.add("netgis-hide");this.parcelReset.classList.remove("netgis-hide");this.nameList.innerHTML="";if("{"===a.charAt(0)||"["===a.charAt(0)){a=JSON.parse(a);for(var b=0;b<a.data.length;b++){var c=a.data[b],d=this.createNameItem(c.gmk_name);d.getElementsByTagName("button")[0].setAttribute("data-id",c.gmk_gmn);this.nameList.appendChild(d)}}};
|
||||||
|
netgis.SearchParcel.prototype.onNameItemClick=function(a){a=a.target;var b=a.getAttribute("data-id");this.nameInput.value=a.innerHTML;this.nameList.innerHTML="";this.districtInput.value=b;this.requestFields(b)};
|
||||||
|
netgis.SearchParcel.prototype.requestFields=function(a){var b=this.config.searchparcel.fields_service,c=b.url;c=c+"service=WFS&version=1.0.0&request=GetFeature&outputFormat=application/json; subtype=geojson&typename="+b.name;c=c+"&filter=<Filter><PropertyIsEqualTo><PropertyName>"+(b.filter_property+"</PropertyName>");netgis.util.request(c+("<Literal>"+a+"</Literal></PropertyIsEqualTo></Filter>"),this.onFieldsResponse.bind(this))};
|
||||||
|
netgis.SearchParcel.prototype.onFieldsResponse=function(a){a=JSON.parse(a);this.showDistricts(!1);this.showFields(!0,a);this.showParcels(!1)};netgis.SearchParcel.prototype.selectFirstName=function(){var a=this.nameList.getElementsByTagName("button");0<a.length&&a[0].click()};netgis.SearchParcel.prototype.setDistrict=function(a,b){this.nameInput.value=a;this.districtInput.value=b;this.requestFields(b)};netgis.SearchParcel.prototype.setFieldNumber=function(a){this.fieldInput.value=a;this.onParcelSearchClick()};
|
||||||
|
netgis.SearchParcel.prototype.setParcelNumber=function(a,b){this.parcelInputA.value=a;this.parcelInputB.value=b;this.onParcelSearchClick()};netgis.SearchParcel.prototype.showBottom=function(){this.top.classList.add("netgis-resize-bottom");this.top.style.height="50%";this.top.style.bottom="auto";this.bottom.classList.remove("netgis-hide")};netgis.SearchParcel.prototype.hideBottom=function(){this.top.classList.remove("netgis-resize-bottom");this.top.style.height="auto";this.top.style.bottom="0mm";this.bottom.classList.add("netgis-hide")};
|
||||||
|
netgis.SearchParcel.prototype.onInputFieldKey=function(a){switch(a.keyCode){case 13:this.onParcelSearchClick()}};netgis.SearchParcel.prototype.onParcelSearchClick=function(a){this.requestParcels(this.districtInput.value.trim(),this.fieldInput.value.trim(),this.parcelInputA.value.trim(),this.parcelInputB.value.trim())};
|
||||||
|
netgis.SearchParcel.prototype.requestParcels=function(a,b,c,d){var e=this.config.searchparcel.parcel_url;e=netgis.util.replace(e,"{district}",a?a:"");e=netgis.util.replace(e,"{field}",b?b:"");e=netgis.util.replace(e,"{parcelA}",c?c:"");e=netgis.util.replace(e,"{parcelB}",d?d:"");this.parcelTable.classList.add("netgis-hide");this.parcelList.innerHTML="";this.parcelList.classList.remove("netgis-filter-active");this.tableFilter.checked=!1;this.selected={};this.parcelInfo.innerHTML="Suche Flurst\u00fccke...";
|
||||||
|
netgis.util.request(e,this.onParcelsResponse.bind(this))};
|
||||||
|
netgis.SearchParcel.prototype.updateTableRows=function(){for(var a=this.parcelList.getElementsByTagName("tr"),b=0;b<a.length;b++){var c=a[b],d=c.getAttribute("data-id"),e=c.getElementsByTagName("button")[0];!0===this.selected[d]?(c.classList.add("netgis-active","netgis-text-a","netgis-hover-text-a"),e.setAttribute("disabled","disabled"),e.setAttribute("title","Geometrie bereits \u00fcbernommen"),e.classList.remove("netgis-hover-a")):(c.classList.remove("netgis-active","netgis-text-a","netgis-hover-text-a"),
|
||||||
|
e.removeAttribute("disabled"),e.setAttribute("title","Geometrie \u00fcbernehmen"),e.classList.add("netgis-hover-a"))}};
|
||||||
|
netgis.SearchParcel.prototype.onParcelsResponse=function(a){a=JSON.parse(a);this.parcelCount.innerHTML="("+a.count+")";if(0===a.count)this.parcelInfo.innerHTML=a.Info;else{for(var b=0;b<a.data.length;b++){var c=a.data[b];c=this.createParcelItem(c.fln,c.fsn_zae,c.fsn_nen,c.fsk,c.flaeche,c.bbox,c.geometry);this.parcelList.appendChild(c)}this.parcelTable.classList.remove("netgis-hide");this.showBottom();this.showDistricts(!1);this.showFields(!1);this.showParcels(!0,a.data)}this.container.classList.contains("netgis-hide")||
|
||||||
|
this.parcelTable.scrollIntoView()};netgis.SearchParcel.prototype.onParcelEnter=function(a){a=a.target;var b=a.getAttribute("data-geom");a={id:a.getAttribute("data-id"),field:a.getAttribute("data-field"),parcelA:a.getAttribute("data-parcel-a"),parcelB:a.getAttribute("data-parcel-b"),geom:b};netgis.util.invoke(this.container,netgis.Events.SEARCHPARCEL_ITEM_ENTER,a)};netgis.SearchParcel.prototype.onParcelLeave=function(a){netgis.util.invoke(this.container,netgis.Events.SEARCHPARCEL_ITEM_LEAVE,{id:a.target.getAttribute("data-id")})};
|
||||||
|
netgis.SearchParcel.prototype.onParcelClick=function(a){netgis.util.invoke(this.container,netgis.Events.SEARCHPARCEL_ITEM_CLICK,{id:a.currentTarget.getAttribute("data-id")})};netgis.SearchParcel.prototype.onParcelImportClick=function(a){a.stopPropagation();a=a.currentTarget.parentElement.parentElement;var b=a.getAttribute("data-id");a.getAttribute("data-geom");netgis.util.invoke(this.container,netgis.Events.MAP_COPY_FEATURE_TO_EDIT,{source:this.parcelsLayerID,id:b})};
|
||||||
|
netgis.SearchParcel.prototype.onResetClick=function(a){this.reset()};netgis.SearchParcel.prototype.onTopResize=function(a){if(!this.bottom.classList.contains("netgis-hide")){a=this.top.getBoundingClientRect();var b=this.top.parentNode.getBoundingClientRect();this.bottom.style.top=a.bottom-b.top+"px"}};netgis.SearchParcel.prototype.onBottomHeaderClick=function(a){this.reset()};
|
||||||
|
netgis.SearchParcel.prototype.onMapFeatureEnter=function(a){var b=a.target;a=a.detail;switch(a.layer){case this.districtsLayerID:a=a.properties.gemarkung;b.setAttribute("title",a);break;case this.fieldsLayerID:a=a.properties.flurname;b.setAttribute("title",a);break;case this.parcelsLayerID:a="Flur: "+a.properties.fln+" / Z\u00e4hler: "+a.properties.fsn_zae+" / Nenner: "+a.properties.fsn_nen,b.setAttribute("title",a)}};
|
||||||
|
netgis.SearchParcel.prototype.onMapFeatureClick=function(a){var b=a.detail;this.popup.hide();switch(b.layer){case this.districtsLayerID:this.setDistrict(b.properties.gemarkung+" ("+b.properties.ldkreis+")",b.properties.gmkgnr);break;case this.fieldsLayerID:this.setFieldNumber(b.properties.flur);break;case this.parcelsLayerID:if(a=b.properties.fsk,!this.selected[a]){this.popup.container!==b.overlay&&this.popup.attachTo(b.overlay);var c="<table style='margin: 1mm;'><tr><th>Flur:</th><td>"+(b.properties.fln+
|
||||||
|
"</td>");c+="<tr><th>Z\u00e4hler:</th><td>"+b.properties.fsn_zae+"</td>";c+="<tr><th>Nenner:</th><td>"+b.properties.fsn_nen+"</td>";c+="<tr><th>Fl\u00e4che:</th><td>"+b.properties.flaeche+" qm</td>";this.popup.setContent(c+"</table><button type='button' class='netgis-hover-a'><i class='netgis-icon fas fa-paste' style='margin-right: 3mm;'></i><span>Geometrie \u00fcbernehmen</span></button>");b=this.popup.content.getElementsByTagName("button")[1];b.setAttribute("data-id",a);b.addEventListener("click",
|
||||||
|
this.onParcelPopupButtonClick.bind(this));this.popup.show()}}};netgis.SearchParcel.prototype.onParcelPopupButtonClick=function(a){a=a.currentTarget.getAttribute("data-id");netgis.util.invoke(this.container,netgis.Events.MAP_COPY_FEATURE_TO_EDIT,{source:this.parcelsLayerID,id:a});this.popup.hide()};
|
||||||
|
netgis.SearchParcel.prototype.onMapFeatureLeave=function(a){var b=a.target;switch(a.detail.layer){case this.districtsLayerID:case this.fieldsLayerID:b.setAttribute("title","");break;case this.parcelsLayerID:b.setAttribute("title","")}};netgis.SearchParcel.prototype.onMapCopyFeatureToEdit=function(a){a=a.detail;var b=a.id;a.source===this.parcelsLayerID&&(this.selected[b]||(this.selected[b]=!0),this.updateTableRows())};
|
||||||
|
netgis.SearchParcel.prototype.onTableFilterChange=function(a){this.parcelList.classList.toggle("netgis-filter-active",a.currentTarget.checked)};netgis=netgis||{};netgis.SearchPlace=function(a){this.config=a;this.initElements();this.initEvents();this.initConfig(a)};netgis.SearchPlace.Config={title:"Search...",url:"",zoom:17,marker_color:"darkgray",marker_title:"Search-Result"};
|
||||||
|
netgis.SearchPlace.prototype.initElements=function(){this.search=new netgis.Search("");this.container=this.search.container;this.container.classList.add("netgis-search-place","netgis-responsive");this.search.container.addEventListener(netgis.Events.SEARCH_CHANGE,this.onSearchChange.bind(this));this.search.container.addEventListener(netgis.Events.SEARCH_SELECT,this.onSearchSelect.bind(this));this.search.container.addEventListener(netgis.Events.SEARCH_CLEAR,this.onSearchClear.bind(this))};
|
||||||
|
netgis.SearchPlace.prototype.initEvents=function(){};netgis.SearchPlace.prototype.initConfig=function(a){(a=a.searchplace)&&a.title&&this.search.setTitle(a.title)};netgis.SearchPlace.prototype.attachTo=function(a){this.search.attachTo(a);a.addEventListener(netgis.Events.SEARCHPLACE_TOGGLE,this.onSearchPlaceToggle.bind(this))};
|
||||||
|
netgis.SearchPlace.prototype.onSearchPlaceToggle=function(a){(a=a.detail)&&a.on?this.search.show():this.search.toggle();if(this.search.isVisible()){var b=this.search;window.setTimeout(function(){b.focus()},200)}};netgis.SearchPlace.prototype.onSearchChange=function(a){var b=this.config.searchplace;b&&b.url&&(b=b.url,b=netgis.util.replace(b,"{query}",window.encodeURIComponent(a.detail.query)),b=netgis.util.replace(b,"{epsg}",4326),netgis.util.request(b,this.onSearchResponse.bind(this)))};
|
||||||
|
netgis.SearchPlace.prototype.onSearchResponse=function(a){a=JSON.parse(a);this.search.clearResults();if(a.geonames){a=a.geonames;for(var b=0;b<a.length;b++){var c=a[b],d=c.title,e=.5*(Number.parseFloat(c.minx)+Number.parseFloat(c.maxx)),f=.5*(Number.parseFloat(c.miny)+Number.parseFloat(c.maxy));c={type:c.category,id:b,lon:e,lat:f};this.search.addResult(d,JSON.stringify(c))}}else if(a.data)for(a=a.data,b=0;b<a.length;b++)c=a[b],d=c.name,c={type:"street",id:c.strid,lon:Number.parseFloat(c.wgs_x),lat:Number.parseFloat(c.wgs_y)},
|
||||||
|
this.search.addResult(d,JSON.stringify(c))};netgis.SearchPlace.prototype.onSearchSelect=function(a){a=JSON.parse(a.detail.data);netgis.util.invoke(this.container,netgis.Events.MAP_ZOOM_LONLAT,{lon:a.lon,lat:a.lat,zoom:this.config.searchplace.zoom});if("street"===a.type){var b=this.config.searchplace.url_detail;b&&(b=netgis.util.replace(b,"{id}",a.id),netgis.util.request(b,this.onSearchDetailResponse.bind(this)))}};
|
||||||
|
netgis.SearchPlace.prototype.onSearchDetailResponse=function(a){a=JSON.parse(a);var b=a.hsnrarr;if(0!==b.length){this.search.clearResults();for(var c=0;c<b.length;c++){var d=b[c],e=a.strname+" "+d.hsnr;d={type:"address",lon:Number.parseFloat(d.wgs_x),lat:Number.parseFloat(d.wgs_y)};this.search.addResult(e,JSON.stringify(d))}}};netgis.SearchPlace.prototype.onSearchClear=function(a){};netgis=netgis||{};
|
||||||
|
netgis.SLD=function(){return{read:function(a,b){var c={};a=(new DOMParser).parseFromString(a,"text/xml").getElementsByTagName("NamedLayer");for(var d=0;d<a.length;d++){var e=a[d],f=e.getElementsByTagName("se:Name")[0].innerHTML;console.info("Layer:",f);e=e.getElementsByTagName("se:FeatureTypeStyle");for(f=0;f<e.length;f++)for(var g=e[f].getElementsByTagName("se:Rule"),h=0;h<g.length;h++){var k=g[h],l=k.getElementsByTagName("se:Name")[0].innerHTML;console.info("Rule:",l);l=k.getElementsByTagName("se:PolygonSymbolizer")[0];k=
|
||||||
|
l.getElementsByTagName("se:Fill")[0];l=l.getElementsByTagName("se:Stroke")[0];c.polygon={fill:k.querySelector("[name='fill']").innerHTML,stroke:l.querySelector("[name='stroke']").innerHTML,strokeWidth:Number.parseFloat(l.querySelector("[name='stroke-width']").innerHTML)}}}console.info("SLD:",c);b.invoke(netgis.Events.MAP_UPDATE_STYLE,c);return c}}}();netgis=netgis||{};netgis.Tabs=function(a){this.initElements(a);this.setActiveTab(0)};
|
||||||
|
netgis.Tabs.prototype.initElements=function(a){this.container=document.createElement("div");this.container.className="netgis-tabs";this.header=document.createElement("div");this.header.className="netgis-header netgis-color-d";this.container.appendChild(this.header);this.content=document.createElement("div");this.content.className="netgis-content netgis-color-e";this.container.appendChild(this.content);for(var b=0;b<a.length;b++){var c=document.createElement("button");c.setAttribute("type","button");
|
||||||
|
c.addEventListener("click",this.onHeaderButtonClick.bind(this));c.className="netgis-button netgis-color-d";c.innerHTML=a[b];this.header.appendChild(c);c=document.createElement("section");c.className="netgis-color-e netgis-form";this.content.appendChild(c)}};netgis.Tabs.prototype.attachTo=function(a){a.appendChild(this.container)};
|
||||||
|
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();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){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}}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;
|
||||||
|
case "cut_features":continue}this.addButton(this.top,d.id,d.title)}this.bottom=document.createElement("section");this.bottom.className="netgis-color-e netgis-hide";this.panel.content.appendChild(this.bottom);b=document.createElement("button");b.className="netgis-button netgis-clip-text netgis-color-c netgis-gradient-a";b.innerHTML="<span>Einstellungen</span><i class='netgis-icon fas fa-times'></i>";b.setAttribute("type","button");b.addEventListener("click",this.onBottomHeaderClick.bind(this));this.bottom.appendChild(b);
|
||||||
|
this.bottomTitle=b.getElementsByTagName("span")[0];a.toolbox&&!0===a.toolbox.open&&this.panel.show()};
|
||||||
|
netgis.Toolbox.prototype.initOptions=function(a){var b=a.toolbox.options;if(b)for(var c in b);a=a.tools;b=[];a&&(a.buffer||(a.buffer={}),this.bottomPanels.drawPoints=document.createElement("div"),b.push(this.addCheckbox(this.bottomPanels.drawPoints,"Einrasten",this.onDrawSnapToggle.bind(this))),this.addCheckbox(this.bottomPanels.drawPoints,"Puffern",this.onDrawBufferToggle.bind(this)),this.addInputNumber(this.bottomPanels.drawPoints,"Radius (Meter):",a.buffer.default_radius,this.onDrawBufferChange.bind(this)),
|
||||||
|
this.addInputNumber(this.bottomPanels.drawPoints,"Segmente:",a.buffer.default_segments,this.onDrawBufferChange.bind(this)),this.bottom.appendChild(this.bottomPanels.drawPoints),this.bottomPanels.drawLines=document.createElement("div"),b.push(this.addCheckbox(this.bottomPanels.drawLines,"Einrasten",this.onDrawSnapToggle.bind(this))),this.addCheckbox(this.bottomPanels.drawLines,"Puffern",this.onDrawBufferToggle.bind(this)),this.addInputNumber(this.bottomPanels.drawLines,"Radius (Meter):",a.buffer.default_radius,
|
||||||
|
this.onDrawBufferChange.bind(this)),this.addInputNumber(this.bottomPanels.drawLines,"Segmente:",a.buffer.default_segments,this.onDrawBufferChange.bind(this)),this.bottom.appendChild(this.bottomPanels.drawLines),this.showDrawBufferOptions(!1),this.bottomPanels.drawPolygons=document.createElement("div"),b.push(this.addCheckbox(this.bottomPanels.drawPolygons,"Einrasten",this.onDrawSnapToggle.bind(this))),this.bottom.appendChild(this.bottomPanels.drawPolygons),this.bottomPanels.bufferFeatures=document.createElement("div"),
|
||||||
|
this.addInputNumber(this.bottomPanels.bufferFeatures,"Radius (Meter):",a.buffer.default_radius,this.onBufferFeaturesChange.bind(this)),this.addInputNumber(this.bottomPanels.bufferFeatures,"Segmente:",a.buffer.default_segments,this.onBufferFeaturesChange.bind(this)),this.addCheckbox(this.bottomPanels.bufferFeatures,"Mehrfach-Auswahl",this.onSelectMultipleChange.bind(this)),this.addButton(this.bottomPanels.bufferFeatures,null,"<i class='netgis-icon netgis-text-a fas fa-arrow-circle-right'></i><span>Akzeptieren</span>",
|
||||||
|
this.onBufferFeaturesAccept.bind(this)),this.bottom.appendChild(this.bottomPanels.bufferFeatures),this.bottomPanels.cutFeatures=document.createElement("div"),this.addCheckbox(this.bottomPanels.cutFeatures,"Mehrfach-Auswahl",this.onSelectMultipleChange.bind(this)),this.bottom.appendChild(this.bottomPanels.cutFeatures),this.bottomPanels.modifyFeatures=document.createElement("div"),b.push(this.addCheckbox(this.bottomPanels.modifyFeatures,"Einrasten",this.onDrawSnapToggle.bind(this))),this.bottom.appendChild(this.bottomPanels.modifyFeatures));
|
||||||
|
if(a&&a.snapping){if(!1===a.snapping.show)for(c=0;c<b.length;c++)b[c].parentNode.classList.add("netgis-hide");if(!0===a.snapping.active){for(c=0;c<b.length;c++)b[c].checked=!0;var d=this;window.setTimeout(function(){netgis.util.invoke(d.panel.container,netgis.Events.MAP_SNAP_TOGGLE,{on:!0})},100)}}};netgis.Toolbox.prototype.initEvents=function(){this.resizeObserver=(new ResizeObserver(this.onTopResize.bind(this))).observe(this.top)};
|
||||||
|
netgis.Toolbox.prototype.attachTo=function(a){this.panel.attachTo(a);a.addEventListener(netgis.Events.CLIENT_SET_MODE,this.onClientSetMode.bind(this));a.addEventListener(netgis.Events.TOOLBOX_TOGGLE,this.onToolboxToggle.bind(this));a.addEventListener(netgis.Events.SELECT_MULTI_TOGGLE,this.onSelectMultiToggle.bind(this))};
|
||||||
|
netgis.Toolbox.prototype.addButton=function(a,b,c,d){var e=document.createElement("button");e.className="netgis-button netgis-clip-text netgis-color-e netgis-hover-d";e.innerHTML=c;e.setAttribute("type","button");e.setAttribute("data-id",b);d?e.onclick=d:e.addEventListener("click",this.onButtonClick.bind(this));a&&a.appendChild(e);return e};
|
||||||
|
netgis.Toolbox.prototype.addCheckbox=function(a,b,c){var d=document.createElement("label");d.className="netgis-noselect netgis-color-e netgis-hover-d";var e=document.createElement("input");e.setAttribute("type","checkbox");d.appendChild(e);var f=document.createElement("span");f.innerHTML=b;d.appendChild(f);c&&(e.onchange=c);a&&a.appendChild(d);return e};
|
||||||
|
netgis.Toolbox.prototype.addInputNumber=function(a,b,c,d){var e=document.createElement("label");e.className="netgis-noselect netgis-color-e netgis-hover-d";var f=document.createElement("span");f.innerHTML=b;e.appendChild(f);b=document.createElement("input");b.setAttribute("type","number");b.setAttribute("min",0);b.value=c;e.appendChild(b);d&&(b.onchange=d,b.onkeyup=d);a&&a.appendChild(e);return b};
|
||||||
|
netgis.Toolbox.prototype.showBottom=function(a,b){this.top.classList.add("netgis-resize-bottom");this.top.style.height="50%";this.top.style.bottom="auto";this.bottom.classList.remove("netgis-hide");this.bottomTitle.innerHTML=b;if(a)for(var c in this.bottomPanels)b=this.bottomPanels[c],b===a?b.classList.remove("netgis-hide"):b.classList.add("netgis-hide")};
|
||||||
|
netgis.Toolbox.prototype.hideBottom=function(){this.top.classList.remove("netgis-resize-bottom");this.top.style.height="auto";this.top.style.bottom="0mm";this.bottom.classList.add("netgis-hide")};
|
||||||
|
netgis.Toolbox.prototype.showDrawBufferOptions=function(a){var b=this.bottomPanels.drawPoints.getElementsByTagName("label"),c=this.bottomPanels.drawLines.getElementsByTagName("label");b[1].getElementsByTagName("input")[0].checked=a;(c[1].getElementsByTagName("input")[0].checked=a)?(b[2].classList.remove("netgis-hide"),b[3].classList.remove("netgis-hide"),c[2].classList.remove("netgis-hide"),c[3].classList.remove("netgis-hide")):(b[2].classList.add("netgis-hide"),b[3].classList.add("netgis-hide"),
|
||||||
|
c[2].classList.add("netgis-hide"),c[3].classList.add("netgis-hide"))};
|
||||||
|
netgis.Toolbox.prototype.setActiveButton=function(a){for(var b=this.top.getElementsByTagName("button"),c=null,d=0;d<b.length;d++){var e=b[d];a&&e.getAttribute("data-id")===a.toLowerCase()?(c=e,e.classList.remove("netgis-color-e"),e.classList.add("netgis-active","netgis-color-d")):(e.classList.remove("netgis-active","netgis-color-d"),e.classList.add("netgis-color-e"))}if(c){var f=this;window.setTimeout(function(){f.top.scrollTo({top:c.offsetTop,behavior:"smooth"})},10)}};
|
||||||
|
netgis.Toolbox.prototype.onToolboxToggle=function(a){this.panel.toggle()};
|
||||||
|
netgis.Toolbox.prototype.onClientSetMode=function(a){a=a.detail;this.hideBottom();switch(a.mode){default:this.setActiveButton(null);break;case netgis.Modes.VIEW:this.setActiveButton(netgis.Commands.VIEW);break;case netgis.Modes.ZOOM_BOX:this.setActiveButton(netgis.Commands.ZOOM_BOX);break;case netgis.Modes.MEASURE_LINE:this.setActiveButton(netgis.Commands.MEASURE_LINE);break;case netgis.Modes.MEASURE_AREA:this.setActiveButton(netgis.Commands.MEASURE_AREA);break;case netgis.Modes.DRAW_POINTS:this.setActiveButton(netgis.Commands.DRAW_POINTS);
|
||||||
|
this.showBottom(this.bottomPanels.drawPoints,"Punkte zeichnen");break;case netgis.Modes.DRAW_LINES:this.setActiveButton(netgis.Commands.DRAW_LINES);this.showBottom(this.bottomPanels.drawLines,"Linien zeichnen");break;case netgis.Modes.DRAW_POLYGONS:this.setActiveButton(netgis.Commands.DRAW_POLYGONS);this.showBottom(this.bottomPanels.drawPolygons,"Polygone zeichnen");break;case netgis.Modes.MODIFY_FEATURES:this.setActiveButton(netgis.Commands.MODIFY_FEATURES);this.showBottom(this.bottomPanels.modifyFeatures,
|
||||||
|
"Verschieben");break;case netgis.Modes.DELETE_FEATURES:this.setActiveButton(netgis.Commands.DELETE_FEATURES);break;case netgis.Modes.BUFFER_FEATURES:this.setActiveButton(netgis.Commands.BUFFER_FEATURES);this.showBottom(this.bottomPanels.bufferFeatures,"Puffern");this.onBufferFeaturesChange();break;case netgis.Modes.BUFFER_FEATURES_EDIT:this.setActiveButton(netgis.Commands.BUFFER_FEATURES);this.showBottom(this.bottomPanels.bufferFeatures,"Puffern");this.onBufferFeaturesChange();break;case netgis.Modes.BUFFER_FEATURES_DYNAMIC:this.setActiveButton(netgis.Commands.BUFFER_FEATURES);
|
||||||
|
this.showBottom(this.bottomPanels.bufferFeatures,"Puffern");this.onBufferFeaturesChange();break;case netgis.Modes.CUT_FEATURES:netgis.util.invoke(this.panel.container,netgis.Events.SELECT_MULTI_TOGGLE,{on:!1});this.setActiveButton(netgis.Commands.CUT_FEATURES);break;case netgis.Modes.CUT_FEATURES_DRAW:this.setActiveButton(netgis.Commands.CUT_FEATURES)}};
|
||||||
|
netgis.Toolbox.prototype.onTopResize=function(a){if(!this.bottom.classList.contains("netgis-hide")){a=this.top.getBoundingClientRect();var b=this.top.parentNode.getBoundingClientRect();this.bottom.style.top=a.bottom-b.top+"px"}};netgis.Toolbox.prototype.onBottomHeaderClick=function(a){netgis.util.invoke(this.panel.container,netgis.Events.CLIENT_SET_MODE,{mode:netgis.Modes.VIEW})};
|
||||||
|
netgis.Toolbox.prototype.onButtonClick=function(a){a=a.currentTarget;var b=a.getAttribute("data-id");netgis.util.invoke(a,netgis.Events.TOOLBOX_BUTTON_CLICK,{id:b});netgis.Client.handleCommand(a,b)};
|
||||||
|
netgis.Toolbox.prototype.onDrawSnapToggle=function(a){var b=a.currentTarget,c=b.parentNode.parentNode;a=b.checked;netgis.util.invoke(b,netgis.Events.MAP_SNAP_TOGGLE,{on:a});b=[];c===this.bottomPanels.drawPoints&&(b.push(this.bottomPanels.drawLines),b.push(this.bottomPanels.drawPolygons),b.push(this.bottomPanels.modifyFeatures));c===this.bottomPanels.drawLines&&(b.push(this.bottomPanels.drawPoints),b.push(this.bottomPanels.drawPolygons),b.push(this.bottomPanels.modifyFeatures));c===this.bottomPanels.drawPolygons&&
|
||||||
|
(b.push(this.bottomPanels.drawPoints),b.push(this.bottomPanels.drawLines),b.push(this.bottomPanels.modifyFeatures));c===this.bottomPanels.modifyFeatures&&(b.push(this.bottomPanels.drawPoints),b.push(this.bottomPanels.drawLines),b.push(this.bottomPanels.drawPolygons));for(c=0;c<b.length;c++)b[c].getElementsByTagName("input")[0].checked=a};
|
||||||
|
netgis.Toolbox.prototype.onDrawBufferToggle=function(a){a=a.currentTarget;var b=a.checked;this.showDrawBufferOptions(b);var c=this.bottomPanels.drawPoints.getElementsByTagName("input"),d=Number.parseFloat(c[2].value);c=Number.parseInt(c[3].value);netgis.util.invoke(a,netgis.Events.DRAW_BUFFER_TOGGLE,{on:b,radius:d,segments:c})};
|
||||||
|
netgis.Toolbox.prototype.onDrawBufferChange=function(a){a=a.currentTarget.parentNode.parentNode;var b=a.getElementsByTagName("input"),c=b[1].checked,d=Number.parseFloat(b[2].value),e=Number.parseInt(b[3].value);netgis.util.invoke(this.bottomPanels.drawPoints,netgis.Events.DRAW_BUFFER_CHANGE,{on:c,radius:d,segments:e});if(a===this.bottomPanels.drawPoints)var f=this.bottomPanels.drawLines;a===this.bottomPanels.drawLines&&(f=this.bottomPanels.drawPoints);f&&(b=f.getElementsByTagName("input"),b[1].checked=
|
||||||
|
c,b[2].value=d,b[3].value=e)};netgis.Toolbox.prototype.onBufferFeaturesChange=function(a){var b=this.bottomPanels.bufferFeatures.getElementsByTagName("input");a=Number.parseFloat(b[0].value);b=Number.parseInt(b[1].value);netgis.util.invoke(this.bottomPanels.bufferFeatures,netgis.Events.BUFFER_CHANGE,{radius:a,segments:b})};netgis.Toolbox.prototype.onSelectMultipleChange=function(a){netgis.util.invoke(this.bottomPanels.bufferFeatures,netgis.Events.SELECT_MULTI_TOGGLE,{on:a.currentTarget.checked})};
|
||||||
|
netgis.Toolbox.prototype.onSelectMultiToggle=function(a){a=a.detail;this.bottomPanels.bufferFeatures.getElementsByTagName("input")[2].checked=a.on};
|
||||||
|
netgis.Toolbox.prototype.onBufferFeaturesAccept=function(a){var b=this.bottomPanels.bufferFeatures.getElementsByTagName("input");a=Number.parseFloat(b[0].value);b=Number.parseInt(b[1].value);netgis.util.invoke(this.bottomPanels.bufferFeatures,netgis.Events.BUFFER_ACCEPT,{radius:a,segments:b});netgis.util.invoke(this.bottomPanels.bufferFeatures,netgis.Events.CLIENT_SET_MODE,{mode:netgis.Modes.VIEW})};netgis=netgis||{};netgis.Tree=function(a){this.draggable=a?a:!1;this.dragElement=null;this.initElements()};netgis.Tree.prototype.initElements=function(){var a=document.createElement("ul");a.className="netgis-tree";this.container=a};netgis.Tree.prototype.attachTo=function(a){a.appendChild(this.container)};netgis.Tree.prototype.clear=function(){this.container.innerHTML=""};
|
||||||
|
netgis.Tree.prototype.addFolder=function(a,b,c,d,e,f){var g=document.createElement("li");g.className="netgis-folder";g.setAttribute("data-id",b);b=document.createElement("details");g.appendChild(b);var h=document.createElement("summary");h.className="netgis-button netgis-noselect netgis-clip-text netgis-color-e netgis-hover-d";h.innerHTML="<i class='netgis-icon netgis-hide-open fas fa-folder'></i><i class='netgis-icon netgis-show-open fas fa-folder-open'></i><span>"+c+"</span>";b.appendChild(h);!0===
|
||||||
|
this.draggable&&(netgis.util.isDefined(f)&&!0!==f||this.setItemDraggable(h));c=document.createElement("label");h.appendChild(c);f=document.createElement("input");f.setAttribute("type","checkbox");f.onchange=this.onFolderChange.bind(this);c.appendChild(f);!0===e&&g.classList.add("netgis-nocheck");e=document.createElement("ul");b.appendChild(e);a=a?a.getElementsByTagName("ul")[0]:this.container;d?a.insertBefore(g,a.firstChild):a.appendChild(g);return g};
|
||||||
|
netgis.Tree.prototype.addCheckbox=function(a,b,c,d,e,f){var g=document.createElement("li");g.className="netgis-item";!0===this.draggable&&this.setItemDraggable(g);var h=document.createElement("label");h.className="netgis-button netgis-noselect netgis-clip-text netgis-color-e netgis-hover-d";h.innerHTML="<span>"+c+"</span>";g.appendChild(h);c=document.createElement("span");c.className="netgis-wrapper";h.insertBefore(c,h.firstChild);h=document.createElement("input");h.setAttribute("type","checkbox");
|
||||||
|
h.setAttribute("data-id",b);d&&(h.checked=d);h.onchange=this.onItemChange.bind(this);c.appendChild(h);f&&this.addItemDetails(g,b,f);a=a?a.getElementsByTagName("ul")[0]:this.container;e?a.insertBefore(g,a.firstChild):a.appendChild(g);return g};
|
||||||
|
netgis.Tree.prototype.addRadioButton=function(a,b,c,d,e){var f=document.createElement("li");f.className="netgis-item";var g=document.createElement("label");g.className="netgis-button netgis-noselect netgis-clip-text netgis-color-e netgis-hover-d";g.innerHTML="<span>"+c+"</span>";f.appendChild(g);c=document.createElement("span");c.className="netgis-wrapper";g.insertBefore(c,g.firstChild);g=a?"radio-"+a.getAttribute("data-id"):"radio-noname";var h=document.createElement("input");h.setAttribute("type",
|
||||||
|
"radio");h.setAttribute("name",g);h.setAttribute("value","radio-"+b);h.setAttribute("data-id",b);d&&(h.checked=d);h.onchange=this.onItemChange.bind(this);c.appendChild(h);e&&this.addItemDetails(f,b,e);a?a.getElementsByTagName("ul")[0].appendChild(f):this.container.appendChild(f);return f};
|
||||||
|
netgis.Tree.prototype.addButton=function(a,b,c,d){var e=document.createElement("li"),f=document.createElement("button");f.innerHTML=c;f.className="netgis-button netgis-color-e netgis-hover-d netgis-clip-text";f.setAttribute("type","button");e.appendChild(f);b&&f.setAttribute("data-id",b);d&&(f.onclick=d);f.addEventListener("click",this.onButtonClick.bind(this));a?a.getElementsByTagName("ul")[0].appendChild(e):this.container.appendChild(e);return e};
|
||||||
|
netgis.Tree.prototype.addSpace=function(a){var b=document.createElement("li");b.className="netgis-space";a?a.getElementsByTagName("ul")[0].appendChild(b):this.container.appendChild(b);return b};
|
||||||
|
netgis.Tree.prototype.addItemDetails=function(a,b,c){var d=document.createElement("details");d.className="netgis-noselect";var e=document.createElement("summary");e.className="netgis-clickable netgis-hover-d";e.innerHTML="<i class='fas fa-angle-down'></i>";d.appendChild(e);e=document.createElement("div");d.appendChild(e);for(var f=0;f<c.length;f++){var g=c[f],h=document.createElement("label");h.className="netgis-hover-d";switch(g.type){case "button":var k=document.createElement("button");k.setAttribute("type",
|
||||||
|
"button");k.addEventListener("click",g.callback);k.className="netgis-button netgis-color-e netgis-hover-d";k.innerHTML=g.title;h.appendChild(k);break;case "slider":k=document.createElement("span");k.className="netgis-clip-text";k.innerHTML=g.title;h.appendChild(k);k=document.createElement("span");h.appendChild(k);var l=document.createElement("input");l.setAttribute("type","range");l.setAttribute("min",0);l.setAttribute("max",100);l.setAttribute("step",1);l.setAttribute("value",g.val);l.setAttribute("data-id",
|
||||||
|
b);l.addEventListener("change",this.onItemSliderChange.bind(this));l.addEventListener("input",this.onItemSliderChange.bind(this));this.draggable&&(l.setAttribute("draggable","true"),l.addEventListener("dragstart",function(a){a.preventDefault();a.stopImmediatePropagation()}));k.appendChild(l)}e.appendChild(h)}a.appendChild(d)};
|
||||||
|
netgis.Tree.prototype.setItemDraggable=function(a){a.setAttribute("draggable","true");a.addEventListener("dragstart",this.onDragStart.bind(this));a.addEventListener("dragenter",this.onDragEnter.bind(this));a.addEventListener("dragover",this.onDragOver.bind(this));a.addEventListener("dragleave",this.onDragLeave.bind(this));a.addEventListener("drop",this.onDragDrop.bind(this));a.addEventListener("dragend",this.onDragEnd.bind(this))};
|
||||||
|
netgis.Tree.prototype.getFolder=function(a){for(var b=this.container.getElementsByClassName("netgis-folder"),c=0;c<b.length;c++){var d=b[c];if(d.getAttribute("data-id")===a)return d}return null};netgis.Tree.prototype.getItem=function(a){for(var b=this.container.getElementsByTagName("input"),c=0;c<b.length;c++){var d=b[c];if(d.getAttribute("data-id")===a)return d}return null};
|
||||||
|
netgis.Tree.prototype.removeItem=function(a){if(a=this.getItem(a))a=a.parentNode.parentNode.parentNode,a.parentNode.removeChild(a),this.removeEmptyFolders(),this.updateFolderChecks()};netgis.Tree.prototype.removeEmptyFolders=function(){for(var a=this.container.getElementsByClassName("netgis-folder"),b=0;b<a.length;b++)a[b].getElementsByTagName("ul")[0].getElementsByTagName("li")};
|
||||||
|
netgis.Tree.prototype.setFolderOpen=function(a,b){var c=this.container.getElementsByClassName("netgis-folder");a=a.toString();for(var d=0;d<c.length;d++){var e=c[d],f=e.getElementsByTagName("details")[0];e.getAttribute("data-id")===a&&(!0===b?f.setAttribute("open",""):f.removeAttribute("open"))}};
|
||||||
|
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.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")};
|
||||||
|
netgis.Tree.prototype.onDragDrop=function(a){a.preventDefault();a.stopPropagation();var b=a.currentTarget;a.dataTransfer.getData("text/plain");if(b!==this.dragElement){b.classList.remove("netgis-dragover");"summary"===b.nodeName.toLowerCase()?(a=b.parentNode.getElementsByTagName("ul")[0],b=0<a.childNodes.length?a.childNodes[0]:null):a=b.parentNode;var c="summary"===this.dragElement.nodeName.toLowerCase()?this.dragElement.parentNode.parentNode:this.dragElement;c.parentNode!==a||1<a.childNodes.length||
|
||||||
|
(b=null);c.contains(a)||(c.parentNode.removeChild(c),b?a.insertBefore(c,b):a.appendChild(c),netgis.util.invoke(this.container,netgis.Events.TREE_ITEM_ORDER_CHANGE,{items:this.container.getElementsByClassName("netgis-item")}))}};netgis.Tree.prototype.onDragEnd=function(a){a.currentTarget.classList.remove("netgis-dragging");this.dragElement=null};netgis=netgis||{};
|
||||||
|
netgis.util=function(){var a=function(a,b){for(var c in a)a.hasOwnProperty(c)&&b(c,a[c])},b=function(){return navigator.language||"de-DE"};return{isDefined:function(a){return"undefined"!==typeof a},isObject:function(a){return"object"!==typeof a||Array.isArray(a)||null===a?!1:!0},isString:function(a){return"string"===typeof a||a instanceof String},isJSON:function(a,b){if(!0===b){a="string"!==typeof a?JSON.stringify(a):a;try{a=JSON.parse(a)}catch(e){return!1}return"object"===typeof a&&null!==a}b=a.trim();
|
||||||
|
a=b.charAt(0);b=b.charAt(b.length-1);return"{"===a&&"}"===b||"["===a&&"]"===b?!0:!1},isMobile:function(a){return a?600>a.getBoundingClientRect().width:600>document.body.getBoundingClientRect().width},clone:function(a){return JSON.parse(JSON.stringify(a))},stringToID:function(a,b){b||(b="-");a=a.trim();a=a.toLowerCase();a=this.replace(a," ",b);a=this.replace(a,"\n",b);a=this.replace(a,"\t",b);a=this.replace(a,"\\.",b);a=this.replace(a,"\\,",b);a=this.replace(a,"\\!",b);a=this.replace(a,"\\?",b);a=
|
||||||
|
this.replace(a,":",b);a=this.replace(a,";",b);a=this.replace(a,'"',b);a=this.replace(a,"'",b);a=this.replace(a,"\\\u00a7",b);a=this.replace(a,"\\$",b);a=this.replace(a,"\\%",b);a=this.replace(a,"\\&",b);a=this.replace(a,"\\/",b);a=this.replace(a,"\\\\",b);a=this.replace(a,"\\(",b);a=this.replace(a,"\\)",b);a=this.replace(a,"\\{",b);a=this.replace(a,"\\}",b);a=this.replace(a,"\\[",b);a=this.replace(a,"\\]",b);a=this.replace(a,"=",b);a=this.replace(a,"\\+",b);a=this.replace(a,"\\*",b);a=this.replace(a,
|
||||||
|
"\\~",b);a=this.replace(a,"\\^",b);a=this.replace(a,"\\\u00b0",b);a=this.replace(a,"\u00b2",b);a=this.replace(a,"\u00b3",b);a=this.replace(a,"\\#",b);a=this.replace(a,"\\<",b);a=this.replace(a,"\\>",b);a=this.replace(a,"\\|",b);a=this.replace(a,"\\@",b);a=this.replace(a,"\u20ac",b);a=this.replace(a,"\u00b5",b);a=this.trim(a,b);a=this.replace(a,"\u00e4","ae");a=this.replace(a,"\u00f6","oe");a=this.replace(a,"\u00fc","ue");a=this.replace(a,"\u00df","ss");a=this.replace(a,"\u00e1","a");a=this.replace(a,
|
||||||
|
"\u00e0","a");a=this.replace(a,"\u00e2","a");a=this.replace(a,"\u00e9","e");a=this.replace(a,"\u00e8","e");a=this.replace(a,"\u00ea","e");a=this.replace(a,"\u00ed","i");a=this.replace(a,"\u00ec","i");a=this.replace(a,"\u00ee","i");a=this.replace(a,"\u00f3","o");a=this.replace(a,"\u00f2","o");a=this.replace(a,"\u00f4","o");a=this.replace(a,"\u00fa","u");a=this.replace(a,"\u00f9","u");return a=this.replace(a,"\u00fb","u")},replace:function(a,b,e){return a.replace(new RegExp(b,"g"),e)},trim:function(a,
|
||||||
|
b){a=a.replace(new RegExp("^"+b+"+"),"");return a=a.replace(new RegExp(b+"+$"),"")},foreach:a,template:function(b,d){a(d,function(a,c){b=b.replace(new RegExp("{"+a+"}","g"),c)});return b},newlines:function(a){return a.replace(/\n/g,"<br />")},create:function(a){var b=document.createElement("tbody");b.innerHTML=a;return b.children[0]},insideElement:function(a,b,e){a=a.getBoundingClientRect();return b<a.left||e<a.top||b>a.right||e>a.bottom?!1:!0},size:function(a){a=(new TextEncoder).encode(JSON.stringify(a)).length;
|
||||||
|
var b=a/1024;return{bytes:a,kilobytes:b,megabytes:b/1024}},request:function(a,b,e,f){f=new XMLHttpRequest;e&&(f._requestData=e);f.onload=function(){b(this.responseText,this._requestData,this)};f.withCredentials=!1;f.open("GET",a,!0);f.send();return f},downloadJSON:function(a,b){a="data:text/json;charset=utf-8,"+encodeURIComponent(JSON.stringify(a));var c=document.createElement("a");c.setAttribute("href",a);c.setAttribute("download",b);document.body.appendChild(c);c.click();c.remove()},padstr:function(a,
|
||||||
|
b){for(a=a.toString();a.length<b;)a="0"+a;return a},merge:function(a,b){return Object.assign(a,b)},getTimeStamp:function(a){var b=new Date;if(!0===a){a=b.getFullYear();var c=b.getMonth()+1,f=b.getDate(),g=b.getHours(),h=b.getMinutes();b=b.getSeconds();10>c&&(c="0"+c);10>f&&(f="0"+f);10>g&&(g="0"+g);10>h&&(h="0"+h);10>b&&(b="0"+b);a=[a,c,f,"_",g,h,b].join("")}else a=b.getDate()+"."+(b.getMonth()+1)+"."+b.getFullYear(),a+=" "+b.getHours()+":"+b.getMinutes();return a},getUserLanguage:b,getFileExtension:function(a){a=
|
||||||
|
a.split(".");return 1>=a.length?"":a[a.length-1]},parseURL:function(a){var b=a.indexOf("?"),c=-1<b?a.substr(0,b):a,f=[];if(-1<b)for(a=a.substr(b+1),a=a.split("&"),b=0;b<a.length;b++){var g=a[b];g=g.toLowerCase();-1<g.search("request")||f.push(g)}return{base:c,parameters:f}},formatDistance:function(a){return 100<a?Math.round(a/1E3*100)/100+" km":Math.round(100*a)/100+" m"},formatLength:function(a,b){var c=1E3<a;a=c?b?Math.round(a/1E3*1E3)/1E3:Math.round(a/1E3):b?Math.round(100*a)/100:Math.round(a);
|
||||||
|
0===a&&(c=!1);return a+(c?" km":" m")},formatArea:function(a,d,e,f){a=(e=a>(e||1E5))?d?Math.round(a/1E6*1E3)/1E3:Math.round(a/1E6):d?Math.round(100*a)/100:Math.round(a);0===a&&(e=!1);a=a.toLocaleString(b());return a+(e?" km\u00b2":" m\u00b2")},hexToRGB:function(a){"#"===a.charAt(0)&&(a=a.substr(1));a=Number.parseInt(a,16);return[a>>16&255,a>>8&255,a&255]},invoke:function(a,b,e){a.dispatchEvent(new CustomEvent(b,{bubbles:!0,detail:e}))},handler:function(a,b){return function(c){b||(b=c);netgis.util.invoke(this,
|
||||||
|
a,b)}}}}();netgis=netgis||{};netgis.Window=function(a){this.resizing=this.dragging=!1;this.py=this.px=0;this.initElements(a);this.initEvents();var b=this;window.setTimeout(function(){var a=b.container.getBoundingClientRect();b.container.style.right="auto";b.container.style.bottom="auto";b.container.style.left=a.left+"px";b.container.style.top=a.top+"px"},100)};
|
||||||
|
netgis.Window.prototype.initElements=function(a){this.container=document.createElement("section");this.container.className="netgis-window netgis-shadow";this.header=document.createElement("button");this.header.setAttribute("type","button");this.header.className="netgis-mover netgis-button netgis-clip-text netgis-color-c netgis-gradient-a netgis-shadow";this.header.innerHTML=a;this.container.appendChild(this.header);this.closer=document.createElement("button");this.closer.className="netgis-closer netgis-button netgis-text-e";
|
||||||
|
this.closer.innerHTML='<i class="netgis-icon fas fa-times"></i>';this.closer.setAttribute("type","button");this.container.appendChild(this.closer);this.content=document.createElement("div");this.content.className="netgis-content";this.container.appendChild(this.content)};
|
||||||
|
netgis.Window.prototype.initEvents=function(){this.closer.addEventListener("click",this.onCloserClick.bind(this));this.header.addEventListener("pointerdown",this.onPointerDown.bind(this));document.addEventListener("pointermove",this.onDocPointerMove.bind(this));document.addEventListener("pointerup",this.onDocPointerUp.bind(this));this.observer=new ResizeObserver(this.onResizeObserve.bind(this));this.observer.observe(this.container,{attributes:!0})};netgis.Window.prototype.attachTo=function(a){a.appendChild(this.container)};
|
||||||
|
netgis.Window.prototype.show=function(){this.container.classList.remove("netgis-hide")};netgis.Window.prototype.hide=function(){this.container.classList.add("netgis-hide")};netgis.Window.prototype.toggle=function(){this.container.classList.toggle("netgis-hide")};netgis.Window.prototype.isVisible=function(){return!this.container.classList.contains("netgis-hide")};netgis.Window.prototype.onCloserClick=function(a){this.hide()};
|
||||||
|
netgis.Window.prototype.onPointerDown=function(a){var b=this.container.getBoundingClientRect();this.dragging=!0;this.px=a.clientX-b.left;this.py=a.clientY-b.top;this.container.classList.add("netgis-dragging")};
|
||||||
|
netgis.Window.prototype.onDocPointerMove=function(a){var b=a.clientX,c=a.clientY,d=this.container.getBoundingClientRect();if(!this.resizing&&this.dragging){b-=this.px;c-=this.py;var e=this.container.parentNode.getBoundingClientRect();0>b&&(b=0,this.px=a.clientX-d.left);40>c&&(c=40,this.py=a.clientY-d.top);b+d.width>e.right&&(b=e.width-d.width,this.px=a.clientX-d.left);c+d.height>e.bottom&&(c=e.height-d.height,this.py=a.clientY-d.top);this.container.style.left=b+"px";this.container.style.top=c+"px";
|
||||||
|
this.container.style.right="auto";this.container.style.bottom="auto"}};netgis.Window.prototype.onDocPointerUp=function(a){this.resizing=this.dragging=!1;this.container.classList.remove("netgis-dragging")};netgis.Window.prototype.onResizeObserve=function(a){this.dragging&&(this.dragging=!1,this.resizing=!0);a=this.container.getBoundingClientRect();netgis.util.invoke(this.container,netgis.Events.WINDOW_RESIZE,{x:a.x,y:a.y,w:a.width,h:a.height})};netgis=netgis||{};netgis.WMC=function(a){this.config=a};netgis.WMC.Config={url:"",layers_url:""};netgis.WMC.prototype.requestContext=function(a,b){this.callback=b;netgis.util.request(a,this.onContextResponse.bind(this))};netgis.WMC.prototype.onContextResponse=function(a){var b=JSON.parse(a);this.data=b;a=[];b=b.layerList;for(var c=0;c<b.length;c++)a.push(b[c].layerId);this.requestLayers(a)};
|
||||||
|
netgis.WMC.prototype.requestLayers=function(a){var b=this.config.wmc;b?(b=b.layers_url,b=netgis.util.replace(b,"{ids}",a.join(",")),netgis.util.request(b,this.onLayersResponse.bind(this))):console.error("no config[ 'wmc' ] found, skipping WMC layer loading")};netgis.WMC.prototype.onLayersResponse=function(a){this.layers=a=JSON.parse(a);console.info("WMC Layers Response:",a);this.callback&&this.callback({config:this.toConfig()})};
|
||||||
|
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,
|
||||||
|
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.build="20251027";
|
||||||
@@ -1,15 +1,13 @@
|
|||||||
{% load static %}
|
{% load static %}
|
||||||
|
|
||||||
<!-- Library Styles -->
|
<!-- Library Styles -->
|
||||||
<link rel="stylesheet" type="text/css" href="{% static 'libs/fontawesome/5.12.0/css/all.min.css' %}" />
|
<link rel="stylesheet" type="text/css" href="{% static 'libs/fontawesome/5.12.0/css/all.min.css' %}" />
|
||||||
<link rel="stylesheet" type="text/css" href="{% static 'libs/openlayers/7.2.2/ol.css' %}" />
|
<link rel="stylesheet" type="text/css" href="{% static 'libs/openlayers/10.0.0/ol.css' %}" />
|
||||||
|
|
||||||
<!-- Client Styles -->
|
<!-- Client Styles -->
|
||||||
<link rel="stylesheet" type="text/css" href="{% static 'netgis.min.css' %}" />
|
<link rel="stylesheet" type="text/css" href="{% static 'dist/netgis.min.css' %}" />
|
||||||
|
|
||||||
|
|
||||||
<!-- Library Scripts-->
|
<!-- Library Scripts-->
|
||||||
<script type="text/javascript" src="{% static 'libs/openlayers/7.2.2/ol.js' %}"></script>
|
<script type="text/javascript" src="{% static 'libs/openlayers/10.0.0/ol.js' %}"></script>
|
||||||
<script type="text/javascript" src="{% static 'libs/proj4js/2.6.0/proj4.js' %}"></script>
|
<script type="text/javascript" src="{% static 'libs/proj4js/2.6.0/proj4.js' %}"></script>
|
||||||
<script type="text/javascript" src="{% static 'libs/jsts/1.6.1/jsts.min.js' %}"></script>
|
<script type="text/javascript" src="{% static 'libs/jsts/1.6.1/jsts.min.js' %}"></script>
|
||||||
<script type="text/javascript" src="{% static 'libs/shapefilejs/4.0.2/shp.js' %}"></script>
|
<script type="text/javascript" src="{% static 'libs/shapefilejs/4.0.2/shp.js' %}"></script>
|
||||||
@@ -19,13 +17,14 @@
|
|||||||
<script type="text/javascript" src="{% static 'libs/geopackage/4.2.3/geopackage.min.js' %}"></script>
|
<script type="text/javascript" src="{% static 'libs/geopackage/4.2.3/geopackage.min.js' %}"></script>
|
||||||
|
|
||||||
<!-- Client Scripts -->
|
<!-- Client Scripts -->
|
||||||
<script type="text/javascript" src="{% static 'netgis.min.js' %}"></script>
|
<script type="text/javascript" src="{% static 'dist/netgis.min.js' %}"></script>
|
||||||
|
|
||||||
|
<main id="container"
|
||||||
<main id="container" {% if geom_form.read_only %}data-editable="false"{% else %}data-editable="true"{% endif %} style="position: relative; width: 100%; height: 100%;">
|
{% if geom_form.read_only %}data-editable="false"{% else %}data-editable="true"{% endif %}
|
||||||
|
style="position: relative; width: 100%; height: 100%;">
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<input type="hidden" id="netgis-storage" name="geom" value="{{geom_form.fields.geom.initial}}"/>
|
<input type="hidden" id="netgis-storage" name="output" value="{{geom_form.fields.output.initial}}"/>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
|||||||
@@ -109,6 +109,11 @@
|
|||||||
|
|
||||||
.ol-viewport canvas {
|
.ol-viewport canvas {
|
||||||
all: unset;
|
all: unset;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ol-viewport {
|
||||||
|
touch-action: pan-x pan-y;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ol-selectable {
|
.ol-selectable {
|
||||||
@@ -343,3 +348,7 @@
|
|||||||
.ol-overviewmap .ol-overviewmap-box:hover {
|
.ol-overviewmap .ol-overviewmap-box:hover {
|
||||||
cursor: move;
|
cursor: move;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ol-overviewmap .ol-viewport:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
1767
templates/map/client/libs/openlayers/10.0.0/ol.d.ts
vendored
Normal file
1767
templates/map/client/libs/openlayers/10.0.0/ol.d.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
templates/map/client/libs/openlayers/10.0.0/ol.d.ts.map
Normal file
1
templates/map/client/libs/openlayers/10.0.0/ol.d.ts.map
Normal file
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user