From 5efa7551884a22b0ce2681c1a20fc803f40b0e31 Mon Sep 17 00:00:00 2001 From: mipel Date: Thu, 5 Aug 2021 12:54:28 +0200 Subject: [PATCH] Log * adds modal_generic.html template for generic usage * adds M2M field log to BaseObject * adds show log button to controls.html * adds logging on adding related objects * adds render log table using generic modal * adds tooltip to missing values in detail views * adds/updates translations --- compensation/forms.py | 43 +++- compensation/models.py | 6 +- .../detail/includes/controls.html | 21 +- compensation/urls.py | 1 + compensation/views.py | 24 +++ intervention/forms.py | 31 +-- intervention/models.py | 4 +- .../detail/includes/controls.html | 21 +- .../templates/intervention/detail/view.html | 16 +- intervention/urls.py | 3 +- intervention/views.py | 22 ++ konova/forms.py | 30 ++- konova/models.py | 19 ++ locale/de/LC_MESSAGES/django.mo | Bin 15434 -> 15843 bytes locale/de/LC_MESSAGES/django.po | 204 +++++++++++------- templates/log.html | 33 +++ templates/modal/modal_generic.html | 17 ++ user/models.py | 19 +- 18 files changed, 368 insertions(+), 146 deletions(-) create mode 100644 templates/log.html create mode 100644 templates/modal/modal_generic.html diff --git a/compensation/forms.py b/compensation/forms.py index ccba35c..c2a225b 100644 --- a/compensation/forms.py +++ b/compensation/forms.py @@ -25,6 +25,14 @@ class NewCompensationForm(BaseForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) + def save(self): + with transaction.atomic(): + user_action = UserActionLogEntry.objects.create( + user=self.user, + action=UserAction.CREATED + ) + # Save action to log + class NewPaymentForm(BaseModalForm): amount = forms.DecimalField( @@ -62,17 +70,23 @@ class NewPaymentForm(BaseModalForm): def save(self): with transaction.atomic(): - action = UserActionLogEntry.objects.create( + created_action = UserActionLogEntry.objects.create( user=self.user, action=UserAction.CREATED, ) + edited_action = UserActionLogEntry.objects.create( + user=self.user, + action=UserAction.EDITED, + comment=_("Added payment"), + ) pay = Payment.objects.create( - created=action, + created=created_action, amount=self.cleaned_data.get("amount", -1), due_on=self.cleaned_data.get("due", None), comment=self.cleaned_data.get("transfer_note", None), intervention=self.intervention, ) + self.intervention.log.add(edited_action) return pay @@ -99,6 +113,13 @@ class NewStateModalForm(BaseModalForm): def save(self, is_before_state: bool = False): with transaction.atomic(): + user_action = UserActionLogEntry.objects.create( + user=self.user, + action=UserAction.EDITED, + comment=_("Added state") + ) + self.instance.log.add(user_action) + state = CompensationState.objects.create( biotope_type=self.cleaned_data["biotope_type"], surface=self.cleaned_data["surface"], @@ -196,7 +217,7 @@ class NewDeadlineModalForm(BaseModalForm): def save(self): with transaction.atomic(): - action = UserActionLogEntry.objects.create( + created_action = UserActionLogEntry.objects.create( user=self.user, action=UserAction.CREATED ) @@ -204,8 +225,14 @@ class NewDeadlineModalForm(BaseModalForm): type=self.cleaned_data["type"], date=self.cleaned_data["date"], comment=self.cleaned_data["comment"], - created=action, + created=created_action, + ) + edited_action = UserActionLogEntry.objects.create( + user=self.user, + action=UserAction.EDITED, + comment=_("Added deadline") ) + self.instance.log.add(edited_action) self.instance.deadlines.add(deadline) return deadline @@ -260,7 +287,7 @@ class NewActionModalForm(BaseModalForm): with transaction.atomic(): user_action = UserActionLogEntry.objects.create( user=self.user, - action=UserAction.CREATED + action=UserAction.CREATED, ) comp_action = CompensationAction.objects.create( action_type=self.cleaned_data["action_type"], @@ -269,6 +296,12 @@ class NewActionModalForm(BaseModalForm): comment=self.cleaned_data["comment"], created=user_action, ) + edited_action = UserActionLogEntry.objects.create( + user=self.user, + action=UserAction.EDITED, + comment=_("Added action"), + ) + self.instance.log.add(edited_action) self.instance.actions.add(comp_action) return comp_action diff --git a/compensation/models.py b/compensation/models.py index 16b814f..35f2c71 100644 --- a/compensation/models.py +++ b/compensation/models.py @@ -110,12 +110,12 @@ class AbstractCompensation(BaseObject): after_states = models.ManyToManyField(CompensationState, blank=True, related_name='+', help_text="Refers to 'Zielzustand Biotop'") actions = models.ManyToManyField(CompensationAction, blank=True, help_text="Refers to 'Maßnahmen'") - deadlines = models.ManyToManyField("konova.Deadline", null=True, blank=True, related_name="+") + deadlines = models.ManyToManyField("konova.Deadline", blank=True, related_name="+") geometry = models.ForeignKey(Geometry, null=True, blank=True, on_delete=models.SET_NULL) documents = models.ManyToManyField("konova.Document", blank=True) - # Holds which intervention is simply a newer version of this dataset + # Holds a successor for this data next_version = models.ForeignKey("Compensation", null=True, blank=True, on_delete=models.DO_NOTHING) class Meta: @@ -172,7 +172,7 @@ class EcoAccount(AbstractCompensation): # Not needed in regular Compensation since their access is defined by the linked intervention's access users = models.ManyToManyField( User, - help_text="Users having access" + help_text="Users having access (shared with)" ) def __str__(self): diff --git a/compensation/templates/compensation/detail/includes/controls.html b/compensation/templates/compensation/detail/includes/controls.html index 18ce432..528833a 100644 --- a/compensation/templates/compensation/detail/includes/controls.html +++ b/compensation/templates/compensation/detail/includes/controls.html @@ -12,15 +12,18 @@ {% if has_access %} - {% if is_default_member %} - - + + - - - {% endif %} + + {% endif %} {% endif %} \ No newline at end of file diff --git a/compensation/urls.py b/compensation/urls.py index be40c0a..0f3dbe3 100644 --- a/compensation/urls.py +++ b/compensation/urls.py @@ -15,6 +15,7 @@ urlpatterns = [ path("", index_view, name="index"), path('new', new_view, name='new'), path('', open_view, name='open'), + path('/log', log_view, name='log'), path('/edit', edit_view, name='edit'), path('/remove', remove_view, name='remove'), path('/state/new', state_new_view, name='new-state'), diff --git a/compensation/views.py b/compensation/views.py index 0927cf3..2cd1a16 100644 --- a/compensation/views.py +++ b/compensation/views.py @@ -103,6 +103,30 @@ def open_view(request: HttpRequest, id: str): return render(request, template, context) +@login_required +def log_view(request: HttpRequest, id: str): + """ Renders a log view using modal + + Args: + request (HttpRequest): The incoming request + id (str): The compensation's id + + Returns: + + """ + comp = get_object_or_404(Compensation, id=id) + template = "modal/modal_generic.html" + body_template = "log.html" + + context = { + "modal_body_template": body_template, + "log": comp.log.all().order_by("-timestamp"), + "modal_title": _("Log"), + } + context = BaseContext(request, context).context + return render(request, template, context) + + @login_required def remove_view(request: HttpRequest, id: str): """ Renders a modal view for removing the compensation diff --git a/intervention/forms.py b/intervention/forms.py index 2b7fe93..e61528a 100644 --- a/intervention/forms.py +++ b/intervention/forms.py @@ -133,12 +133,7 @@ class NewInterventionForm(BaseForm): created=action, ) intervention.save() - for doc in documents: - doc_obj = Document() - doc_obj.file = doc - # ToDo Add functionality for other attributes - doc_obj.save() - intervention.documents.add(doc_obj) + intervention.log.add(action) return intervention @@ -201,12 +196,12 @@ class EditInterventionForm(NewInterventionForm): self.instance.geometry = geometry self.instance.save() - for doc in documents: - doc_obj = Document() - doc_obj.document = doc - # ToDo Add functionality for other attributes - doc_obj.save() - self.instance.documents.add(doc_obj) + user_action = UserActionLogEntry.objects.create( + user=self.user, + action=UserAction.EDITED + ) + self.instance.log.add(user_action) + return self.instance @@ -364,10 +359,14 @@ class NewRevocationForm(BaseModalForm): def save(self): with transaction.atomic(): - user_action = UserActionLogEntry.objects.create( + created_action = UserActionLogEntry.objects.create( user=self.user, action=UserAction.CREATED ) + edited_action = UserActionLogEntry.objects.create( + user=self.user, + action=UserAction.EDITED + ) document = Document.objects.create( title="revocation_of_{}".format(self.instance.identifier), date_of_creation=self.cleaned_data["date"], @@ -378,8 +377,9 @@ class NewRevocationForm(BaseModalForm): date=self.cleaned_data["date"], comment=self.cleaned_data["comment"], document=document, - created=user_action, + created=created_action, ) + self.instance.log.add(edited_action) self.instance.legal.revocation = revocation self.instance.legal.save() return revocation @@ -421,4 +421,5 @@ class RunCheckForm(BaseModalForm): if self.instance.checked: self.instance.checked.delete() self.instance.checked = user_action - self.instance.save() \ No newline at end of file + self.instance.log.add(user_action) + self.instance.save() diff --git a/intervention/models.py b/intervention/models.py index fc6bd91..7a25ca8 100644 --- a/intervention/models.py +++ b/intervention/models.py @@ -17,7 +17,7 @@ from konova.models import BaseObject, Geometry, UuidModel, BaseResource from konova.utils import generators from konova.utils.generators import generate_random_string from organisation.models import Organisation -from user.models import UserActionLogEntry, UserAction +from user.models import UserActionLogEntry class ResponsibilityData(UuidModel): @@ -123,7 +123,7 @@ class Intervention(BaseObject): next_version = models.ForeignKey("Intervention", null=True, blank=True, on_delete=models.DO_NOTHING) # Users having access on this object - users = models.ManyToManyField(User) + users = models.ManyToManyField(User, help_text="Users having access (data shared with)") access_token = models.CharField( max_length=255, null=True, diff --git a/intervention/templates/intervention/detail/includes/controls.html b/intervention/templates/intervention/detail/includes/controls.html index ca3f4e9..b851444 100644 --- a/intervention/templates/intervention/detail/includes/controls.html +++ b/intervention/templates/intervention/detail/includes/controls.html @@ -27,15 +27,18 @@ {% endif %} - {% if is_default_member %} - - + + - - - {% endif %} + + {% endif %} {% endif %} \ No newline at end of file diff --git a/intervention/templates/intervention/detail/view.html b/intervention/templates/intervention/detail/view.html index 1e4cb3b..387f958 100644 --- a/intervention/templates/intervention/detail/view.html +++ b/intervention/templates/intervention/detail/view.html @@ -20,15 +20,15 @@
- + - + - + @@ -36,7 +36,7 @@ - + @@ -48,7 +48,7 @@ - + @@ -80,15 +80,15 @@ {% endif %} - + - + - + diff --git a/intervention/urls.py b/intervention/urls.py index 16ff259..e580d4b 100644 --- a/intervention/urls.py +++ b/intervention/urls.py @@ -8,7 +8,7 @@ Created on: 30.11.20 from django.urls import path from intervention.views import index_view, new_view, open_view, edit_view, remove_view, new_document_view, share_view, \ - create_share_view, remove_revocation_view, new_revocation_view, run_check_view + create_share_view, remove_revocation_view, new_revocation_view, run_check_view, log_view app_name = "intervention" urlpatterns = [ @@ -16,6 +16,7 @@ urlpatterns = [ path('new/', new_view, name='new'), path('/document/new/', new_document_view, name='new-doc'), path('', open_view, name='open'), + path('/log', log_view, name='log'), path('/edit', edit_view, name='edit'), path('/remove', remove_view, name='remove'), path('/share/', share_view, name='share'), diff --git a/intervention/views.py b/intervention/views.py index 03715cb..5a7e920 100644 --- a/intervention/views.py +++ b/intervention/views.py @@ -370,3 +370,25 @@ def new_revocation_view(request: HttpRequest, id: str): raise NotImplementedError +@login_required +def log_view(request: HttpRequest, id: str): + """ Renders a log view using modal + + Args: + request (HttpRequest): The incoming request + id (str): The compensation's id + + Returns: + + """ + intervention = get_object_or_404(Intervention, id=id) + template = "modal/modal_generic.html" + body_template = "log.html" + + context = { + "modal_body_template": body_template, + "log": intervention.log.all().order_by("-timestamp"), + "modal_title": _("Log"), + } + context = BaseContext(request, context).context + return render(request, template, context) diff --git a/konova/forms.py b/konova/forms.py index 31a474d..36717d9 100644 --- a/konova/forms.py +++ b/konova/forms.py @@ -21,7 +21,7 @@ from django.utils import timezone from django.utils.translation import gettext_lazy as _ from konova.contexts import BaseContext -from konova.models import Document +from konova.models import Document, BaseObject from konova.utils.message_templates import FORM_INVALID from user.models import UserActionLogEntry, UserAction @@ -236,14 +236,16 @@ class RemoveModalForm(BaseModalForm): self.form_caption = _("Are you sure?") def save(self): - if hasattr(self.instance, "deleted"): - action = UserActionLogEntry.objects.create( - user=self.user, - timestamp=timezone.now(), - action=UserAction.DELETED, - ) - self.instance.deleted = action - self.instance.save() + if isinstance(self.instance, BaseObject): + with transaction.atomic(): + action = UserActionLogEntry.objects.create( + user=self.user, + timestamp=timezone.now(), + action=UserAction.DELETED, + ) + self.instance.deleted = action + self.instance.log.add(action) + self.instance.save() else: # If the class does not provide restorable delete functionality, we must delete the entry finally self.instance.delete() @@ -317,4 +319,12 @@ class NewDocumentForm(BaseModalForm): date_of_creation=self.cleaned_data["creation_date"], ) self.instance.documents.add(doc) - return doc \ No newline at end of file + + edited_action = UserActionLogEntry.objects.create( + user=self.user, + action=UserAction.EDITED, + comment=_("Added document"), + ) + self.instance.log.add(edited_action) + + return doc diff --git a/konova/models.py b/konova/models.py index 8743b48..043a958 100644 --- a/konova/models.py +++ b/konova/models.py @@ -8,6 +8,7 @@ Created on: 17.11.20 import os import uuid +from django.contrib.auth.models import User from django.utils.translation import gettext_lazy as _ from django.contrib.gis.db.models import MultiPolygonField from django.db import models, transaction @@ -54,6 +55,7 @@ class BaseObject(BaseResource): title = models.CharField(max_length=1000, null=True, blank=True) deleted = models.ForeignKey(UserActionLogEntry, on_delete=models.SET_NULL, null=True, blank=True, related_name='+') comment = models.TextField(null=True, blank=True) + log = models.ManyToManyField(UserActionLogEntry, blank=True, help_text="Keeps all user actions of an object", editable=False) class Meta: abstract = True @@ -83,6 +85,23 @@ class BaseObject(BaseResource): self.deleted = action self.save() + def add_log_entry(self, action: UserAction, user: User, comment: str): + """ Wraps adding of UserActionLogEntry to self.log + + Args: + action (UserAction): The performed UserAction + user (User): Performing user + + Returns: + + """ + user_action = UserActionLogEntry.objects.create( + user=user, + action=action, + comment=comment + ) + self.log.add(user_action) + class DeadlineType(models.TextChoices): """ diff --git a/locale/de/LC_MESSAGES/django.mo b/locale/de/LC_MESSAGES/django.mo index 602d85e86880718e358606346cca53c845faec9a..fcc2b162b1010c159d5effa0a30cb2482ee34c9f 100644 GIT binary patch delta 5626 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 JVO^4Ze*)CnRzv^* delta 5275 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 diff --git a/locale/de/LC_MESSAGES/django.po b/locale/de/LC_MESSAGES/django.po index eafe7ee..d495318 100644 --- a/locale/de/LC_MESSAGES/django.po +++ b/locale/de/LC_MESSAGES/django.po @@ -3,20 +3,20 @@ # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # -#: compensation/forms.py:34 compensation/forms.py:39 compensation/forms.py:52 -#: compensation/forms.py:182 compensation/forms.py:244 +#: compensation/forms.py:42 compensation/forms.py:47 compensation/forms.py:60 +#: compensation/forms.py:203 compensation/forms.py:271 #: intervention/filters.py:26 intervention/filters.py:40 #: intervention/filters.py:47 intervention/filters.py:48 -#: intervention/forms.py:323 intervention/forms.py:335 -#: intervention/forms.py:347 konova/forms.py:91 konova/forms.py:227 -#: konova/forms.py:258 konova/forms.py:263 konova/forms.py:275 -#: konova/forms.py:287 konova/forms.py:300 user/forms.py:38 +#: intervention/forms.py:318 intervention/forms.py:330 +#: intervention/forms.py:342 konova/forms.py:92 konova/forms.py:228 +#: konova/forms.py:261 konova/forms.py:266 konova/forms.py:278 +#: konova/forms.py:290 konova/forms.py:303 user/forms.py:38 #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-08-04 15:12+0200\n" +"POT-Creation-Date: 2021-08-05 12:43+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -26,140 +26,156 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: compensation/forms.py:33 compensation/forms.py:233 +#: compensation/forms.py:41 compensation/forms.py:260 #: intervention/templates/intervention/detail/includes/eco-account-withdraws.html:33 msgid "Amount" msgstr "Menge" -#: compensation/forms.py:35 +#: compensation/forms.py:43 msgid "Amount in Euro" msgstr "Betrag in Euro" -#: compensation/forms.py:38 +#: compensation/forms.py:46 #: intervention/templates/intervention/detail/includes/payments.html:31 msgid "Due on" msgstr "Fällig am" -#: compensation/forms.py:40 +#: compensation/forms.py:48 msgid "Due on which date" msgstr "Zahlung wird an diesem Datum erwartet" -#: compensation/forms.py:53 +#: compensation/forms.py:61 msgid "Transfer note" msgstr "Verwendungszweck" -#: compensation/forms.py:54 +#: compensation/forms.py:62 msgid "Note for money transfer" msgstr "Verwendungszweck für Überweisung" -#: compensation/forms.py:60 +#: compensation/forms.py:68 msgid "Payment" msgstr "Zahlung" -#: compensation/forms.py:61 +#: compensation/forms.py:69 msgid "Add a payment for intervention '{}'" msgstr "Neue Ersatzzahlung zu Eingriff '{}' hinzufügen" -#: compensation/forms.py:81 +#: compensation/forms.py:80 +msgid "Added payment" +msgstr "Zahlung hinzufügen" + +#: compensation/forms.py:95 msgid "Biotope Type" msgstr "Biotoptyp" -#: compensation/forms.py:84 +#: compensation/forms.py:98 msgid "Select the biotope type" msgstr "Biotoptyp wählen" -#: compensation/forms.py:89 +#: compensation/forms.py:103 #: compensation/templates/compensation/detail/includes/states-after.html:36 #: compensation/templates/compensation/detail/includes/states-before.html:36 msgid "Surface" msgstr "Fläche" -#: compensation/forms.py:92 +#: compensation/forms.py:106 msgid "in m²" msgstr "" -#: compensation/forms.py:97 +#: compensation/forms.py:111 msgid "New state" msgstr "Neuer Zustand" -#: compensation/forms.py:98 +#: compensation/forms.py:112 msgid "Insert data for the new state" msgstr "Geben Sie die Daten des neuen Zustandes ein" -#: compensation/forms.py:112 konova/forms.py:141 +#: compensation/forms.py:119 +msgid "Added state" +msgstr "Zustand hinzugefügt" + +#: compensation/forms.py:133 konova/forms.py:142 msgid "Object removed" msgstr "Objekt entfernt" -#: compensation/forms.py:154 +#: compensation/forms.py:175 msgid "Deadline Type" msgstr "Fristart" -#: compensation/forms.py:157 +#: compensation/forms.py:178 msgid "Select the deadline type" msgstr "Fristart wählen" -#: compensation/forms.py:166 +#: compensation/forms.py:187 #: compensation/templates/compensation/detail/includes/deadlines.html:31 -#: intervention/forms.py:322 +#: intervention/forms.py:317 msgid "Date" msgstr "Datum" -#: compensation/forms.py:169 +#: compensation/forms.py:190 msgid "Select date" msgstr "Datum wählen" -#: compensation/forms.py:181 compensation/forms.py:243 +#: compensation/forms.py:202 compensation/forms.py:270 #: compensation/templates/compensation/detail/includes/actions.html:34 #: compensation/templates/compensation/detail/includes/deadlines.html:34 #: compensation/templates/compensation/detail/includes/documents.html:31 -#: intervention/forms.py:346 +#: intervention/forms.py:341 #: intervention/templates/intervention/detail/includes/documents.html:31 #: intervention/templates/intervention/detail/includes/revocation.html:35 -#: konova/forms.py:286 +#: konova/forms.py:289 msgid "Comment" msgstr "Kommentar" -#: compensation/forms.py:183 compensation/forms.py:245 -#: intervention/forms.py:348 konova/forms.py:288 +#: compensation/forms.py:204 compensation/forms.py:272 +#: intervention/forms.py:343 konova/forms.py:291 msgid "Additional comment, maximum {} letters" msgstr "Zusätzlicher Kommentar, maximal {} Zeichen" -#: compensation/forms.py:194 +#: compensation/forms.py:215 msgid "New deadline" msgstr "Neue Frist" -#: compensation/forms.py:195 +#: compensation/forms.py:216 msgid "Insert data for the new deadline" msgstr "Geben Sie die Daten der neuen Frist ein" -#: compensation/forms.py:215 +#: compensation/forms.py:233 +msgid "Added deadline" +msgstr "Frist/Termin hinzugefügt" + +#: compensation/forms.py:242 msgid "Action Type" msgstr "Maßnahmentyp" -#: compensation/forms.py:218 +#: compensation/forms.py:245 msgid "Select the action type" msgstr "Maßnahmentyp wählen" -#: compensation/forms.py:221 +#: compensation/forms.py:248 msgid "Unit" msgstr "Einheit" -#: compensation/forms.py:224 +#: compensation/forms.py:251 msgid "Select the unit" msgstr "Einheit wählen" -#: compensation/forms.py:236 +#: compensation/forms.py:263 msgid "Insert the amount" msgstr "Menge eingeben" -#: compensation/forms.py:256 +#: compensation/forms.py:283 msgid "New action" msgstr "Neue Maßnahme" -#: compensation/forms.py:257 +#: compensation/forms.py:284 msgid "Insert data for the new action" msgstr "Geben Sie die Daten der neuen Maßnahme ein" +#: compensation/forms.py:302 +msgid "Added action" +msgstr "Maßnahme hinzugefügt" + #: compensation/models.py:59 msgid "cm" msgstr "" @@ -196,7 +212,7 @@ msgstr "Kennung" #: intervention/forms.py:35 intervention/tables.py:28 #: intervention/templates/intervention/detail/includes/compensations.html:33 #: intervention/templates/intervention/detail/includes/documents.html:28 -#: intervention/templates/intervention/detail/view.html:24 konova/forms.py:257 +#: intervention/templates/intervention/detail/view.html:24 konova/forms.py:260 msgid "Title" msgstr "Bezeichnung" @@ -265,7 +281,7 @@ msgstr "Für Sie freigegeben - Datensatz kann bearbeitet werden" msgid "Access not granted" msgstr "Nicht freigegeben - Datensatz nur lesbar" -#: compensation/tables.py:174 konova/forms.py:262 +#: compensation/tables.py:174 konova/forms.py:265 msgid "Created on" msgstr "Erstellt" @@ -313,6 +329,7 @@ msgstr "Menge" #: intervention/templates/intervention/detail/includes/eco-account-withdraws.html:36 #: intervention/templates/intervention/detail/includes/payments.html:37 #: intervention/templates/intervention/detail/includes/revocation.html:41 +#: templates/log.html:10 msgid "Action" msgstr "Aktionen" @@ -336,6 +353,10 @@ msgid "Edit" msgstr "Bearbeiten" #: compensation/templates/compensation/detail/includes/controls.html:21 +msgid "Show log" +msgstr "Log anzeigen" + +#: compensation/templates/compensation/detail/includes/controls.html:24 #: intervention/templates/intervention/detail/includes/controls.html:36 #: venv/lib/python3.7/site-packages/django/forms/formsets.py:391 msgid "Delete" @@ -365,7 +386,7 @@ msgstr "Dokumente" #: compensation/templates/compensation/detail/includes/documents.html:14 #: intervention/templates/intervention/detail/includes/documents.html:14 -#: konova/forms.py:299 +#: konova/forms.py:302 msgid "Add new document" msgstr "Neues Dokument hinzufügen" @@ -434,54 +455,58 @@ msgstr "Verzeichnet am" msgid "Last modified" msgstr "Zuletzt bearbeitet" -#: compensation/templates/compensation/detail/view.html:74 -#: intervention/forms.py:256 -#: intervention/templates/intervention/detail/view.html:106 +#: compensation/templates/compensation/detail/view.html:72 +#: intervention/forms.py:251 +#: intervention/templates/intervention/detail/view.html:104 msgid "Shared with" msgstr "Freigegeben für" -#: compensation/templates/compensation/detail/view.html:86 -#: intervention/templates/intervention/detail/view.html:118 +#: compensation/templates/compensation/detail/view.html:84 +#: intervention/templates/intervention/detail/view.html:116 msgid "No geometry added, yet." msgstr "Keine Geometrie vorhanden" -#: compensation/views.py:121 +#: compensation/views.py:127 +msgid "Log" +msgstr "Log" + +#: compensation/views.py:148 msgid "Compensation removed" msgstr "Kompensation entfernt" -#: compensation/views.py:201 +#: compensation/views.py:228 msgid "Payment added" msgstr "Zahlung hinzugefügt" -#: compensation/views.py:236 +#: compensation/views.py:263 msgid "Payment removed" msgstr "Zahlung gelöscht" -#: compensation/views.py:262 +#: compensation/views.py:289 msgid "Withdraw removed" msgstr "Abbuchung entfernt" -#: compensation/views.py:280 intervention/views.py:96 +#: compensation/views.py:307 intervention/views.py:96 msgid "Document added" msgstr "Dokument hinzugefügt" -#: compensation/views.py:299 +#: compensation/views.py:326 msgid "State added" msgstr "Zustand hinzugefügt" -#: compensation/views.py:318 +#: compensation/views.py:345 msgid "Action added" msgstr "Maßnahme hinzugefügt" -#: compensation/views.py:337 +#: compensation/views.py:364 msgid "Deadline added" msgstr "Frist hinzugefügt" -#: compensation/views.py:356 +#: compensation/views.py:383 msgid "State removed" msgstr "Zustand gelöscht" -#: compensation/views.py:375 +#: compensation/views.py:402 msgid "Action removed" msgstr "Maßnahme entfernt" @@ -563,45 +588,45 @@ msgstr "Dateien" msgid "New intervention" msgstr "Neuer Eingriff" -#: intervention/forms.py:151 +#: intervention/forms.py:146 msgid "Edit intervention" msgstr "Eingriff bearbeiten" -#: intervention/forms.py:245 +#: intervention/forms.py:240 msgid "Share link" msgstr "Freigabelink" -#: intervention/forms.py:247 +#: intervention/forms.py:242 msgid "Send this link to users who you want to have writing access on the data" msgstr "Andere Nutzer erhalten über diesen Link Zugriff auf die Daten" -#: intervention/forms.py:259 +#: intervention/forms.py:254 msgid "Remove check to remove access for this user" msgstr "Wählen Sie die Nutzer ab, die keinen Zugriff mehr haben sollen" -#: intervention/forms.py:270 +#: intervention/forms.py:265 #: intervention/templates/intervention/detail/includes/controls.html:15 msgid "Share" msgstr "Freigabe" -#: intervention/forms.py:271 +#: intervention/forms.py:266 msgid "Share settings for {}" msgstr "Freigabe Einstellungen für {}" -#: intervention/forms.py:324 +#: intervention/forms.py:319 msgid "Date of revocation" msgstr "Datum des Widerspruchs" -#: intervention/forms.py:334 +#: intervention/forms.py:329 #: intervention/templates/intervention/detail/includes/revocation.html:38 msgid "Document" msgstr "Dokument" -#: intervention/forms.py:336 konova/forms.py:276 +#: intervention/forms.py:331 konova/forms.py:279 msgid "Must be smaller than 15 Mb" msgstr "Muss kleiner als 15 Mb sein" -#: intervention/forms.py:359 +#: intervention/forms.py:354 #: intervention/templates/intervention/detail/includes/revocation.html:18 msgid "Add revocation" msgstr "Widerspruch hinzufügen" @@ -823,35 +848,39 @@ msgstr "" msgid "You need to be part of another user group." msgstr "Hierfür müssen Sie einer anderen Nutzergruppe angehören!" -#: konova/forms.py:64 +#: konova/forms.py:65 msgid "Not editable" msgstr "Nicht editierbar" -#: konova/forms.py:90 konova/forms.py:226 +#: konova/forms.py:91 konova/forms.py:227 msgid "Confirm" msgstr "Bestätige" -#: konova/forms.py:102 konova/forms.py:235 +#: konova/forms.py:103 konova/forms.py:236 msgid "Remove" msgstr "Löschen" -#: konova/forms.py:104 +#: konova/forms.py:105 msgid "You are about to remove {} {}" msgstr "Sie sind dabei {} {} zu löschen" -#: konova/forms.py:236 +#: konova/forms.py:237 msgid "Are you sure?" msgstr "Sind Sie sicher?" -#: konova/forms.py:264 +#: konova/forms.py:267 msgid "When has this file been created? Important for photos." msgstr "Wann wurde diese Datei erstellt oder das Foto aufgenommen?" -#: konova/forms.py:274 +#: konova/forms.py:277 #: venv/lib/python3.7/site-packages/django/db/models/fields/files.py:231 msgid "File" msgstr "Datei" +#: konova/forms.py:327 +msgid "Added document" +msgstr "Dokument hinzugefügt" + #: konova/management/commands/setup_data.py:42 msgid "On new related data" msgstr "Wenn neue Daten für mich angelegt werden" @@ -876,19 +905,19 @@ msgstr "Wenn meine freigegebenen Daten gelöscht wurden" msgid "On registered data edited" msgstr "Wenn meine freigegebenen Daten bearbeitet wurden" -#: konova/models.py:92 +#: konova/models.py:110 msgid "Finished" msgstr "Umgesetzt bis" -#: konova/models.py:93 +#: konova/models.py:111 msgid "Maintain" msgstr "Unterhaltung bis" -#: konova/models.py:94 +#: konova/models.py:112 msgid "Control" msgstr "Kontrolle am" -#: konova/models.py:95 +#: konova/models.py:113 msgid "Other" msgstr "Sonstige" @@ -1012,6 +1041,14 @@ msgstr "" msgid "Apply filter" msgstr "Filter anwenden" +#: templates/log.html:7 +msgid "Timestamp" +msgstr "" + +#: templates/log.html:13 +msgid "User" +msgstr "Nutzer" + #: templates/modal/modal_form.html:25 msgid "Continue" msgstr "Weiter" @@ -1101,6 +1138,10 @@ msgid "Created" msgstr "Erstellt" #: user/models.py:51 +msgid "Edited" +msgstr "Bearbeitet" + +#: user/models.py:52 msgid "Deleted" msgstr "Gelöscht" @@ -2342,9 +2383,6 @@ msgstr "" #~ msgid "Missing surfaces: " #~ msgstr "Fehlende Flächen: " -#~ msgid "Show all" -#~ msgstr "Alle anzeigen" - #~ msgid "This will remove '{}'. Are you sure?" #~ msgstr "Hiermit wird '{}' gelöscht. Sind Sie sicher?" diff --git a/templates/log.html b/templates/log.html new file mode 100644 index 0000000..acc2ee6 --- /dev/null +++ b/templates/log.html @@ -0,0 +1,33 @@ +{% load i18n %} +
+
{% trans 'Title' %} {{intervention.title|default_if_none:""}}
{% trans 'Process type' %} {{intervention.legal.process_type|default_if_none:""}}
{% trans 'Law' %} {{intervention.legal.law|default_if_none:""}}
{% trans 'Registration office' %} {{intervention.responsible.registration_office|default_if_none:""}}
{% trans 'Registration office file number' %} {{intervention.responsible.registration_file_number|default_if_none:""}}
{% trans 'Conversation office file number' %} {{intervention.responsible.conservation_file_number|default_if_none:""}}
{% trans 'Intervention handler' %} {{intervention.responsible.handler|default_if_none:""}}
{% trans 'Registration date' %} {{intervention.legal.registration_date|default_if_none:""}}
{% trans 'Binding on' %} {{intervention.legal.binding_date|default_if_none:""}}
{% trans 'Revocation' %} {{intervention.legal.revocation.date|naturalday|default_if_none:""}}
+ + + + + + + + + {% for entry in log %} + + + + + + {% endfor %} + +
+ {% trans 'Timestamp' %} + + {% trans 'Action' %} + + {% trans 'User' %} +
+ {{entry.timestamp}} + + {{ entry.action_humanize}} + + {{entry.user}} +
+
\ No newline at end of file diff --git a/templates/modal/modal_generic.html b/templates/modal/modal_generic.html new file mode 100644 index 0000000..5e0f6b8 --- /dev/null +++ b/templates/modal/modal_generic.html @@ -0,0 +1,17 @@ +{% load i18n l10n %} +{% comment %} + A generic modal template which is derived from modal_form.html on django-bootstrap-modal-forms package + https://pypi.org/project/django-bootstrap-modal-forms/ +{% endcomment %} + + + + + \ No newline at end of file diff --git a/user/models.py b/user/models.py index 53a5ca7..ebeb5cf 100644 --- a/user/models.py +++ b/user/models.py @@ -48,6 +48,7 @@ class UserAction(models.TextChoices): CHECKED = "checked", _("Checked") RECORDED = "recorded", _("Recorded") CREATED = "created", _("Created") + EDITED = "edited", _("Edited") DELETED = "deleted", _("Deleted") @@ -70,6 +71,22 @@ class UserActionLogEntry(models.Model): help_text="Short name for performed action - optional", choices=UserAction.choices, ) + comment = models.CharField(max_length=255, null=True, blank=True, help_text="Additional comment on this entry") def __str__(self): - return "{} | {} | {}".format(self.user.username, self.timestamp, self.action) \ No newline at end of file + return "{} | {} | {}".format(self.user.username, self.timestamp, self.action) + + @property + def action_humanize(self): + """ Returns humanized version of enum + + Used for template rendering + + Returns: + + """ + choices = UserAction.choices + for choice in choices: + if choice[0] == self.action: + return choice[1] + return None