Intervention Detail View

* adds (WIP) detail view for interventions
* renames typo in conservations_file_number to conservation_file_number
* adds simple has_access check for intervention objects for given users
* renames occurences of "Registered" to "Recorded" (verzeichnen)
* adds an informing message for detail view of intervention objects which are not editable for a user
* adds GeometryAdmin
* adds fallback DEFAULT_SRID for Geometry model
* adds translations
This commit is contained in:
mipel 2021-07-22 13:19:14 +02:00
parent 591bc739ec
commit 5e48bac013
13 changed files with 292 additions and 95 deletions

View File

@ -25,7 +25,7 @@ class Intervention(BaseObject):
registration_office = models.ForeignKey(Organisation, on_delete=models.SET_NULL, null=True, related_name="+")
registration_file_number = models.CharField(max_length=1000, blank=True, null=True)
conservation_office = models.ForeignKey(Organisation, on_delete=models.SET_NULL, null=True, related_name="+")
conservations_file_number = models.CharField(max_length=1000, blank=True, null=True)
conservation_file_number = models.CharField(max_length=1000, blank=True, null=True)
process_type = models.CharField(max_length=500, null=True, blank=True)
law = models.CharField(max_length=500, null=True, blank=True)
@ -107,4 +107,17 @@ class Intervention(BaseObject):
while Intervention.objects.filter(identifier=new_id).exists():
new_id = self._generate_new_identifier()
self.identifier = new_id
super().save(*args, **kwargs)
super().save(*args, **kwargs)
def has_access(self, user: User):
""" Access check
Checks whether a given user has access to this intervention
Args:
user ():
Returns:
"""
return self.users.filter(username=user.username).exists()

View File

@ -36,7 +36,7 @@ class InterventionTable(BaseTable):
accessor="checked_on",
)
r = tables.Column(
verbose_name=_("Registered"),
verbose_name=_("Recorded"),
orderable=True,
empty_values=[],
accessor="recorded_on",

View File

@ -0,0 +1,121 @@
{% extends 'base.html' %}
{% load i18n static fontawesome_5 %}
{% block body %}
<div id="detail-header" class="row">
<div class="col-sm-12 col-md-12 col-lg-6">
<h3>{% trans 'Intervention' %} {{intervention.identifier}}</h3>
</div>
<div class="col-sm-12 col-md-12 col-lg-6">
<div class="d-flex justify-content-end">
<a href="{% url 'home' %}" class="mr-2">
<button class="btn btn-default" title="{% trans 'Open in LANIS' %}">
LANIS
</button>
</a>
{% if has_access %}
<a href="{% url 'home' %}" class="mr-2">
<button class="btn btn-default" title="{% trans 'Run check' %}">
{% fa5_icon 'star' %}
</button>
</a>
<a href="{% url 'home' %}" class="mr-2">
<button class="btn btn-default" title="{% trans 'Record' %}">
{% fa5_icon 'bookmark' %}
</button>
</a>
<a href="{% url 'home' %}" class="mr-2">
<button class="btn btn-default" title="{% trans 'Edit' %}">
{% fa5_icon 'edit' %}
</button>
</a>
<a href="{% url 'home' %}" class="mr-2">
<button class="btn btn-default" title="{% trans 'Delete' %}">
{% fa5_icon 'trash' %}
</button>
</a>
{% endif %}
</div>
</div>
</div>
<hr>
<div id="data" class="row">
<div class="col-sm-12 col-md-12 col-lg-6">
<div class="table-container">
<table class="table table-hover">
<tr>
<th class="w-25" scope="row">{% trans 'Title' %}</th>
<td class="align-middle">{{intervention.title}}</td>
</tr>
<tr>
<th scope="row">{% trans 'Registration office' %}</th>
<td class="align-middle">{{intervention.registration_office|default_if_none:""}}</td>
</tr>
<tr>
<th scope="row">{% trans 'Registration office file number' %}</th>
<td class="align-middle">{{intervention.registration_file_number|default_if_none:""}}</td>
</tr>
<tr>
<th scope="row">{% trans 'Conservation office' %}</th>
<td class="align-middle">{{intervention.conservation_office|default_if_none:""}}</td>
</tr>
<tr>
<th scope="row">{% trans 'Conversation office file number' %}</th>
<td class="align-middle">{{intervention.conservation_file_number|default_if_none:""}}</td>
</tr>
<tr>
<th scope="row">{% trans 'Checked' %}</th>
<td class="align-middle">
{% if intervention.checked_on is None %}
<span>
{% fa5_icon 'star' 'far' %}
</span>
{% else %}
<span class="check-star">
{% fa5_icon 'star' %}
</span>
{% endif %}
</td>
</tr>
<tr>
<th scope="row">{% trans 'Recorded' %}</th>
<td class="align-middle">
{% if intervention.recorded_on is None %}
<span>
{% fa5_icon 'bookmark' 'far' %}
</span>
{% else %}
<span class="registered-bookmark">
{% fa5_icon 'bookmark' %}
</span>
{% endif %}
</td>
</tr>
<tr>
<th scope="row">{% trans 'Registration date' %}</th>
<td class="align-middle">{{intervention.registration_date|default_if_none:""}}</td>
</tr>
<tr>
<th scope="row">{% trans 'Binding on' %}</th>
<td class="align-middle">{{intervention.binding_on|default_if_none:""}}</td>
</tr>
<tr>
<th scope="row">{% trans 'Last modified' %}</th>
<td class="align-middle">
{{intervention.created_on|default_if_none:""}}
<br>
{% trans 'by' %}
{{intervention.created_by|default_if_none:""}}
</td>
</tr>
</table>
</div>
</div>
<div class="col-sm-12 col-md-12 col-lg-6">
{{geom_form.media}}
{{geom_form.geom}}
</div>
</div>
<div id="related-objects" class="row"></div>
{% endblock %}

View File

@ -1,47 +0,0 @@
{% extends 'base.html' %}
{% load i18n static %}
{% block body %}
<div class="rows">
<div class="columns">
<div class="large-10 column">
<h3>{% trans 'Intervention' %}: {{ intervention.title }}</h3>
</div>
<div class="large-2 column">
<a href="{% url 'intervention:edit' intervention.id %}">
<button class="button small" role="button" value="{% trans 'Edit' %}"><i class='fas fa-edit'></i> {% trans 'Edit' %}</button>
</a>
</div>
</div>
<hr>
{% comment %}
form.media needs to be loaded to ensure the openlayers client will be loaded properly
{% endcomment %}
{{ form.media }}
<div class="columns">
<div class="small-6 columns">
<table>
<tbody>
{% for field in form %}
{% if field != form.geometry %}
<tr title="{{ field.help_text }}" class="{% if field.errors %}error{% endif %}">
<th scope="row" class="small-3">
<div>{{ field.label }}</div>
<small>{{ field.help_text }}</small>
</th>
<td class="small-12">
{{ field }}
</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
</div>
<div class="small-6 columns">
{{ form.geometry }}
</div>
</div>
</div>
{% endblock %}

View File

@ -9,7 +9,7 @@ from intervention.models import Intervention
from intervention.tables import InterventionTable
from konova.contexts import BaseContext
from konova.decorators import *
from konova.forms import RemoveForm
from konova.forms import RemoveForm, SimpleGeomForm
@login_required
@ -75,7 +75,7 @@ def new_view(request: HttpRequest):
@login_required
def open_view(request: HttpRequest, id: str):
""" Renders a view for viewing an intervention's data
""" Renders a detail view for viewing an intervention's data
Args:
request (HttpRequest): The incoming request
@ -84,12 +84,21 @@ def open_view(request: HttpRequest, id: str):
Returns:
"""
template = "intervention/open.html"
template = "intervention/detail-view.html"
intervention = get_object_or_404(Intervention, id=id)
form = OpenInterventionForm(instance=intervention)
has_access = intervention.has_access(user=request.user)
if not has_access:
messages.info(request, _("Remember: This data has not been shared with you, yet. This means you can only read but can not edit or perform any actions like running a check or recording."))
geom_form = SimpleGeomForm(
instance=intervention
)
context = {
"intervention": intervention,
"form": form,
"has_access": has_access,
"geom_form": geom_form,
}
context = BaseContext(request, context).context
return render(request, template, context)

21
konova/admin.py Normal file
View File

@ -0,0 +1,21 @@
"""
Author: Michel Peltriaux
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
Contact: michel.peltriaux@sgdnord.rlp.de
Created on: 22.07.21
"""
from django.contrib import admin
from konova.models import Geometry
class GeometryAdmin(admin.ModelAdmin):
list_display = [
"id",
"created_on",
"created_by",
]
admin.site.register(Geometry, GeometryAdmin)

View File

@ -10,6 +10,7 @@ from abc import abstractmethod
from django import forms
from django.contrib.auth.models import User
from django.contrib.gis.forms import GeometryField, OSMWidget, MultiPolygonField
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
@ -94,3 +95,30 @@ class RemoveForm(BaseForm):
self.object_to_remove.save()
return self.object_to_remove
class SimpleGeomForm(BaseForm):
""" A geometry form for rendering geometry read-only using a widget
"""
geom = GeometryField(
widget=OSMWidget(
attrs={
"map_width": 600,
"map_height": 400,
}
)
)
def __init__(self, *args, **kwargs):
"""
Constructor does not need to perform further initial setup, like other forms.
We simply use this here for easy rendering of a geometry view component
Args:
*args ():
**kwargs ():
"""
super().__init__(*args, **kwargs)
geom = self.instance.geometry.geom
self.initialize_form_field("geom", geom)
self.disable_form_field("geom")

View File

@ -42,7 +42,7 @@ USER_NOTIFICATIONS_NAMES = {
"NOTIFY_ON_NEW_RELATED_DATA": _("On new related data"),
"NOTIFY_ON_SHARE_LINK_DISABLED": _("On disabled share link"),
"NOTIFY_ON_SHARED_ACCESS_REMOVED": _("On shared access removed"),
"NOTIFY_ON_SHARED_DATA_REGISTERED": _("On shared data registered"),
"NOTIFY_ON_SHARED_DATA_RECORDED": _("On shared data recorded"),
"NOTIFY_ON_SHARED_DATA_DELETED": _("On shared data deleted"),
"NOTIFY_ON_REGISTERED_DATA_EDITED": _("On registered data edited"),
}

View File

@ -11,6 +11,8 @@ from django.contrib.auth.models import User
from django.contrib.gis.db.models import MultiPolygonField
from django.db import models
from konova.settings import DEFAULT_SRID
class BaseResource(models.Model):
"""
@ -67,4 +69,4 @@ class Geometry(BaseResource):
"""
Outsourced geometry model so multiple versions of the same object can refer to the same geometry if it is not changed
"""
geom = MultiPolygonField(null=True, blank=True)
geom = MultiPolygonField(null=True, blank=True, srid=DEFAULT_SRID)

View File

@ -48,6 +48,7 @@ SSO_PUBLIC_KEY = "CHANGE_ME"
DEFAULT_LAT = 50.00
DEFAULT_LON = 7.00
DEFAULT_ZOOM = 8.0
DEFAULT_SRID = 4326
# GROUPS
DEFAULT_GROUP = "Default"

Binary file not shown.

View File

@ -3,15 +3,15 @@
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#: intervention/filters.py:21 intervention/filters.py:27
#: intervention/filters.py:34 intervention/filters.py:35 konova/forms.py:69
#: intervention/filters.py:25 intervention/filters.py:31
#: intervention/filters.py:38 intervention/filters.py:39 konova/forms.py:70
#: user/forms.py:38
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-07-22 09:31+0200\n"
"POT-Creation-Date: 2021-07-22 13:15+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -28,6 +28,7 @@ msgstr "Kennung"
#: compensation/tables.py:23 compensation/tables.py:76 intervention/forms.py:33
#: intervention/tables.py:28
#: intervention/templates/intervention/detail-view.html:47
msgid "Title"
msgstr "Titel"
@ -49,17 +50,17 @@ msgid "Compensation"
msgstr "Kompensation"
#: compensation/tables.py:54 compensation/tables.py:107
#: intervention/tables.py:92 intervention/tables.py:179
#: intervention/tables.py:92 intervention/tables.py:173
msgid "Open {}"
msgstr "Öffne {}"
#: compensation/tables.py:59 compensation/tables.py:112
#: intervention/tables.py:183
#: intervention/tables.py:177
msgid "Edit {}"
msgstr "Bearbeite {}"
#: compensation/tables.py:63 compensation/tables.py:116
#: intervention/tables.py:187
#: intervention/tables.py:181
msgid "Delete {}"
msgstr "Lösche {}"
@ -67,19 +68,19 @@ msgstr "Lösche {}"
msgid "Eco Accounts"
msgstr "Ökokonten"
#: intervention/filters.py:20
#: intervention/filters.py:24
msgid "Show all"
msgstr "Alle anzeigen"
#: intervention/filters.py:26
#: intervention/filters.py:30
msgid "Show recorded"
msgstr "Verzeichnete anzeigen"
#: intervention/filters.py:38
#: intervention/filters.py:42
msgid "District"
msgstr "Gemarkung"
#: intervention/filters.py:39
#: intervention/filters.py:43
msgid "Search for district"
msgstr "Nach Gemarkung suchen"
@ -152,11 +153,13 @@ msgid "Edit intervention"
msgstr "Eingriff bearbeiten"
#: intervention/tables.py:33
#: intervention/templates/intervention/detail-view.html:67
msgid "Checked"
msgstr "Geprüft"
#: intervention/tables.py:39
msgid "Registered"
#: intervention/templates/intervention/detail-view.html:81
msgid "Recorded"
msgstr "Verzeichnet"
#: intervention/tables.py:45
@ -171,8 +174,8 @@ msgstr "Zuletzt bearbeitet"
msgid "Interventions"
msgstr "Eingriffe"
#: intervention/tables.py:92 intervention/tables.py:176
#: intervention/templates/intervention/open.html:8
#: intervention/tables.py:92 intervention/tables.py:170
#: intervention/templates/intervention/detail-view.html:7
#: konova/templates/konova/home.html:11 templates/navbar.html:22
msgid "Intervention"
msgstr "Eingriff"
@ -193,27 +196,86 @@ msgstr "Noch nicht verzeichnet"
msgid "Registered on {} by {}"
msgstr "Am {} von {} verzeichnet worden"
#: intervention/tables.py:167
#: intervention/tables.py:161
msgid "Full access granted"
msgstr "Für Sie freigegeben - Datensatz kann bearbeitet werden"
#: intervention/tables.py:167
#: intervention/tables.py:161
msgid "Access not granted"
msgstr "Nicht freigegeben - Datensatz nur lesbar"
#: intervention/templates/intervention/open.html:12
#: intervention/templates/intervention/detail-view.html:12
msgid "Open in LANIS"
msgstr ""
#: intervention/templates/intervention/detail-view.html:18
msgid "Run check"
msgstr ""
#: intervention/templates/intervention/detail-view.html:23
msgid "Record"
msgstr "Verzeichnen"
#: intervention/templates/intervention/detail-view.html:28
msgid "Edit"
msgstr "Bearbeiten"
#: intervention/views.py:63
#: intervention/templates/intervention/detail-view.html:33
#: venv/lib/python3.7/site-packages/django/forms/formsets.py:391
msgid "Delete"
msgstr "Löschen"
#: intervention/templates/intervention/detail-view.html:51
msgid "Registration office"
msgstr "Zulassungsbehörde"
#: intervention/templates/intervention/detail-view.html:55
msgid "Registration office file number"
msgstr "Aktenzeichen Zulassungsbehörde"
#: intervention/templates/intervention/detail-view.html:59
msgid "Conservation office"
msgstr "Naturschutzbehörde"
#: intervention/templates/intervention/detail-view.html:63
msgid "Conversation office file number"
msgstr "Aktenzeichen Naturschutzbehörde"
#: intervention/templates/intervention/detail-view.html:95
msgid "Registration date"
msgstr "Datum Zulassung bzw. Satzungsbeschluss"
#: intervention/templates/intervention/detail-view.html:99
msgid "Binding on"
msgstr "Datum Bestandskraft"
#: intervention/templates/intervention/detail-view.html:103
msgid "Last modified"
msgstr "Zuletzt bearbeitet"
#: intervention/templates/intervention/detail-view.html:107
msgid "by"
msgstr "von"
#: intervention/views.py:62
msgid "Intervention {} added"
msgstr "Eingriff {} hinzugefügt"
#: intervention/views.py:66 intervention/views.py:119
#: intervention/views.py:65 intervention/views.py:127
msgid "Invalid input"
msgstr "Eingabe fehlerhaft"
#: intervention/views.py:116
#: intervention/views.py:92
msgid ""
"Remember: This data has not been shared with you, yet. This means you can "
"only read but can not edit or perform any actions like running a check or "
"recording."
msgstr ""
"Beachten Sie: Diese Daten sind für Sie noch nicht freigegeben worden. Das "
"bedeutet, dass Sie nur lesenden Zugriff hierauf haben und weder bearbeiten, "
"noch Prüfungen durchführen oder verzeichnen können."
#: intervention/views.py:124
msgid "{} edited"
msgstr "{} bearbeitet"
@ -229,19 +291,19 @@ msgstr "Hierfür müssen Sie Administrator sein!"
msgid "You need to be part of another user group."
msgstr "Hierfür müssen Sie einer anderen Nutzergruppe angehören!"
#: konova/forms.py:42
#: konova/forms.py:43
msgid "Not editable"
msgstr "Nicht editierbar"
#: konova/forms.py:68
#: konova/forms.py:69
msgid "Confirm"
msgstr "Bestätigen"
#: konova/forms.py:80
#: konova/forms.py:81
msgid "Remove"
msgstr "Entferne"
#: konova/forms.py:82
#: konova/forms.py:83
msgid "You are about to remove {} {}"
msgstr "Sie sind dabei {} {} zu löschen"
@ -258,7 +320,7 @@ msgid "On shared access removed"
msgstr "Wenn mir eine Freigabe zu Daten entzogen wird"
#: konova/management/commands/setup_data.py:45
msgid "On shared data registered"
msgid "On shared data recorded"
msgstr "Wenn meine freigegebenen Daten verzeichnet wurden"
#: konova/management/commands/setup_data.py:46
@ -1026,10 +1088,6 @@ msgstr[1] ""
msgid "Order"
msgstr ""
#: venv/lib/python3.7/site-packages/django/forms/formsets.py:391
msgid "Delete"
msgstr ""
#: venv/lib/python3.7/site-packages/django/forms/models.py:755
#, python-format
msgid "Please correct the duplicate data for %(field)s."
@ -1668,12 +1726,6 @@ msgstr ""
#~ msgid "Default"
#~ msgstr "Standard"
#~ msgid "Registration office"
#~ msgstr "Zulassungsbehörde"
#~ msgid "Conservation office"
#~ msgstr "Naturschutzbehörde"
#~ msgid "Quickstart"
#~ msgstr "Schnellstart"
@ -1710,9 +1762,6 @@ msgstr ""
#~ msgid "Confirm check on data"
#~ msgstr "Datenprüfung bestätigen"
#~ msgid "Record data"
#~ msgstr "Daten verzeichnen"
#~ msgid "Add new EMA"
#~ msgstr "Neue EMA hinzufügen"

View File

@ -12,6 +12,6 @@ class UserNotificationEnum(BaseEnum):
NOTIFY_ON_NEW_RELATED_DATA = "NOTIFY_ON_NEW_RELATED_DATA" # notifies in case new data has been added which is related to the user's organisation
NOTIFY_ON_SHARE_LINK_DISABLED = "NOTIFY_ON_SHARE_LINK_DISABLED" # notifies in case share link for data has been disabled
NOTIFY_ON_SHARED_ACCESS_REMOVED = "NOTIFY_ON_SHARED_ACCESS_REMOVED" # notifies in case shared access to data has been removed
NOTIFY_ON_SHARED_DATA_REGISTERED = "NOTIFY_ON_SHARED_DATA_REGISTERED" # notifies in case data has been "verzeichnet"
NOTIFY_ON_SHARED_DATA_RECORDED = "NOTIFY_ON_SHARED_DATA_RECORDED" # notifies in case data has been "verzeichnet"
NOTIFY_ON_SHARED_DATA_DELETED = "NOTIFY_ON_SHARED_DATA_DELETED" # notifies in case data has been deleted
NOTIFY_ON_REGISTERED_DATA_EDITED = "NOTIFY_ON_REGISTERED_DATA_EDITED" # notifies in case registered ("verzeichnet") data has been edited