Merge pull request 'master' (#130) from master into Docker
Reviewed-on: SGD-Nord/konova#130
This commit is contained in:
@@ -185,7 +185,7 @@ class GeoReferencedTableFilterMixin(django_filters.FilterSet):
|
||||
|
||||
"""
|
||||
matching_districts = District.objects.filter(
|
||||
krs=value
|
||||
krs__icontains=value
|
||||
)
|
||||
matching_parcels = Parcel.objects.filter(
|
||||
district__in=matching_districts
|
||||
@@ -209,7 +209,7 @@ class GeoReferencedTableFilterMixin(django_filters.FilterSet):
|
||||
Returns:
|
||||
|
||||
"""
|
||||
queryset = self._filter_parcel_reference(queryset, name, value, "gmrkng__istartswith")
|
||||
queryset = self._filter_parcel_reference(queryset, name, value, "gmrkng__icontains")
|
||||
return queryset
|
||||
|
||||
def filter_parcel(self, queryset, name, value) -> QuerySet:
|
||||
|
||||
@@ -471,6 +471,7 @@ class EditDocumentModalForm(NewDocumentModalForm):
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.document = kwargs.pop("document", None)
|
||||
super().__init__(*args, **kwargs)
|
||||
self.form_title = _("Edit document")
|
||||
form_data = {
|
||||
"title": self.document.title,
|
||||
"comment": self.document.comment,
|
||||
|
||||
32
konova/templates/konova/includes/parcel_table.html
Normal file
32
konova/templates/konova/includes/parcel_table.html
Normal file
@@ -0,0 +1,32 @@
|
||||
{% load i18n %}
|
||||
<div class="table-container w-100 scroll-300">
|
||||
{% if parcels|length == 0 %}
|
||||
<article class="alert alert-info">
|
||||
{% trans 'Parcels can not be calculated, since no geometry is given.' %}
|
||||
</article>
|
||||
{% else %}
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">{% trans 'Kreis' %}</th>
|
||||
<th scope="col">{% trans 'Gemarkung' %}</th>
|
||||
<th scope="col">{% trans 'Parcel' %}</th>
|
||||
<th scope="col">{% trans 'Parcel counter' %}</th>
|
||||
<th scope="col">{% trans 'Parcel number' %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for parcel in parcels %}
|
||||
<tr>
|
||||
<td>{{parcel.district.krs|default_if_none:"-"}}</td>
|
||||
<td>{{parcel.gmrkng|default_if_none:"-"}}</td>
|
||||
<td>{{parcel.flr|default_if_none:"-"}}</td>
|
||||
<td>{{parcel.flrstck_zhlr|default_if_none:"-"}}</td>
|
||||
<td>{{parcel.flrstck_nnr|default_if_none:"-"}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
{% endif %}
|
||||
</div>
|
||||
@@ -1,37 +1,18 @@
|
||||
{% load i18n %}
|
||||
<div>
|
||||
<h3>{% trans 'Spatial reference' %}</h3>
|
||||
</div>
|
||||
<div class="table-container w-100 scroll-300">
|
||||
{% if parcels|length == 0 %}
|
||||
<article class="alert alert-info">
|
||||
{% blocktrans %}
|
||||
If the geometry is not empty, the parcels are currently recalculated. Please refresh this page in a few moments.
|
||||
{% endblocktrans %}
|
||||
</article>
|
||||
{% else %}
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">{% trans 'Kreis' %}</th>
|
||||
<th scope="col">{% trans 'Gemarkung' %}</th>
|
||||
<th scope="col">{% trans 'Parcel' %}</th>
|
||||
<th scope="col">{% trans 'Parcel counter' %}</th>
|
||||
<th scope="col">{% trans 'Parcel number' %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for parcel in parcels %}
|
||||
<tr>
|
||||
<td>{{parcel.district.krs|default_if_none:"-"}}</td>
|
||||
<td>{{parcel.gmrkng|default_if_none:"-"}}</td>
|
||||
<td>{{parcel.flr|default_if_none:"-"}}</td>
|
||||
<td>{{parcel.flrstck_zhlr|default_if_none:"-"}}</td>
|
||||
<td>{{parcel.flrstck_nnr|default_if_none:"-"}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
{% endif %}
|
||||
{% load i18n fontawesome_5 %}
|
||||
<div class="col-sm-12">
|
||||
<div class="card">
|
||||
<div class="card-header rlp-r">
|
||||
<h5>
|
||||
{% fa5_icon 'search-location' %}
|
||||
{% trans 'Spatial reference' %}
|
||||
</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div hx-trigger="every 2s" hx-get="{% url 'geometry-parcels' geom_form.instance.geometry.id %}" title="{% trans 'Loading...' %}">
|
||||
<div class="row justify-content-center">
|
||||
<span class="spinner-border rlp-r-inv" role="status"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -466,11 +466,15 @@ class KonovaViewTestCase(BaseViewTestCase):
|
||||
""" Holds tests for all regular views, which are not app specific
|
||||
|
||||
"""
|
||||
@classmethod
|
||||
def setUpTestData(cls) -> None:
|
||||
super().setUpTestData()
|
||||
def setUp(self) -> None:
|
||||
super().setUp()
|
||||
|
||||
cls.home_url = reverse("home")
|
||||
geom = self.create_dummy_geometry()
|
||||
self.geom_1 = Geometry.objects.create(
|
||||
geom=geom,
|
||||
)
|
||||
|
||||
self.home_url = reverse("home")
|
||||
|
||||
def test_views_logged_in_no_groups(self):
|
||||
""" Check correct status code for all requests
|
||||
@@ -504,6 +508,24 @@ class KonovaViewTestCase(BaseViewTestCase):
|
||||
]
|
||||
self.assert_url_fail(client, urls)
|
||||
|
||||
def test_htmx_parcel_fetch(self):
|
||||
""" Tests that the htmx geometry-parcel fetch returns a proper status code and content
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
client_user = Client()
|
||||
client_user.login(username=self.superuser.username, password=self.superuser_pw)
|
||||
|
||||
has_parcels = self.geom_1.parcels.all().exists()
|
||||
if not has_parcels:
|
||||
self.geom_1.update_parcels()
|
||||
|
||||
htmx_url = reverse("geometry-parcels", args=(self.geom_1.id,))
|
||||
response = client_user.get(htmx_url)
|
||||
self.assertEqual(response.status_code, 286, "Unexpected status code for HTMX fetch")
|
||||
self.assertGreater(len(response.content), 0)
|
||||
|
||||
|
||||
class AutocompleteTestCase(BaseViewTestCase):
|
||||
@classmethod
|
||||
|
||||
@@ -23,7 +23,7 @@ from konova.autocompletes import EcoAccountAutocomplete, \
|
||||
ShareUserAutocomplete, BiotopeExtraCodeAutocomplete, CompensationActionDetailCodeAutocomplete, ShareTeamAutocomplete
|
||||
from konova.settings import SSO_SERVER, SSO_PUBLIC_KEY, SSO_PRIVATE_KEY, DEBUG
|
||||
from konova.sso.sso import KonovaSSOClient
|
||||
from konova.views import logout_view, home_view
|
||||
from konova.views import logout_view, home_view, get_geom_parcels
|
||||
|
||||
sso_client = KonovaSSOClient(SSO_SERVER, SSO_PUBLIC_KEY, SSO_PRIVATE_KEY)
|
||||
urlpatterns = [
|
||||
@@ -39,6 +39,7 @@ urlpatterns = [
|
||||
path('cl/', include("codelist.urls")),
|
||||
path('analysis/', include("analysis.urls")),
|
||||
path('api/', include("api.urls")),
|
||||
path('geom/<id>/parcels', get_geom_parcels, name="geometry-parcels"),
|
||||
|
||||
# Autocomplete paths for all apps
|
||||
path("atcmplt/eco-accounts", EcoAccountAutocomplete.as_view(), name="accounts-autocomplete"),
|
||||
|
||||
@@ -7,20 +7,17 @@ Created on: 16.11.20
|
||||
"""
|
||||
from django.contrib.auth import logout
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.http import HttpRequest, FileResponse
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from django.shortcuts import redirect, render, get_object_or_404
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from codelist.models import KonovaCode
|
||||
from codelist.settings import CODELIST_COMPENSATION_ACTION_ID
|
||||
from compensation.models import Compensation, EcoAccount
|
||||
from intervention.models import Intervention
|
||||
from konova.contexts import BaseContext
|
||||
from konova.decorators import any_group_check
|
||||
from konova.forms import RemoveModalForm
|
||||
from konova.models import Deadline
|
||||
from konova.models import Deadline, Geometry
|
||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
||||
from news.models import ServerMessage
|
||||
from konova.settings import SSO_SERVER_BASE
|
||||
@@ -102,6 +99,46 @@ def home_view(request: HttpRequest):
|
||||
return render(request, template, context)
|
||||
|
||||
|
||||
@login_required
|
||||
def get_geom_parcels(request: HttpRequest, id: str):
|
||||
""" Getter for HTMX
|
||||
|
||||
Returns all parcels of the requested geometry rendered into a simple HTML table
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
id (str): The geometry's id
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
# HTTP code 286 states that the HTMX should stop polling for updates
|
||||
# https://htmx.org/docs/#polling
|
||||
status_code = 286
|
||||
template = "konova/includes/parcel_table.html"
|
||||
geom = get_object_or_404(Geometry, id=id)
|
||||
parcels = geom.get_underlying_parcels()
|
||||
geos_geom = geom.geom
|
||||
|
||||
parcels_are_currently_calculated = geos_geom is not None and geos_geom.area > 0 and len(parcels) == 0
|
||||
parcels_available = len(parcels) > 0
|
||||
no_geometry_given = geos_geom is None
|
||||
|
||||
if parcels_are_currently_calculated:
|
||||
# Parcels are being calculated right now. Change the status code, so polling stays active for fetching
|
||||
# resutls after the calculation
|
||||
status_code = 200
|
||||
|
||||
if parcels_available or no_geometry_given:
|
||||
context = {
|
||||
"parcels": parcels,
|
||||
}
|
||||
html = render_to_string(template, context, request)
|
||||
return HttpResponse(html, status=status_code)
|
||||
else:
|
||||
return HttpResponse(None, status=404)
|
||||
|
||||
|
||||
def get_404_view(request: HttpRequest, exception=None):
|
||||
""" Returns a 404 handling view
|
||||
|
||||
|
||||
Reference in New Issue
Block a user