From 6a91631f9bc9f9d72da167e156f655f3db93a348 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laura=20Kl=C3=BCnder?=
Date: Wed, 25 Dec 2019 10:16:40 +0100
Subject: [PATCH] quick comment feature for reports and stuff
---
.../migrations/0081_auto_20191225_1015.py | 39 +++++++++++++++++++
src/c3nav/mapdata/models/report.py | 15 +++++--
src/c3nav/site/forms.py | 30 +++++++++++++-
src/c3nav/site/templates/site/account.html | 2 +-
.../site/templates/site/report_detail.html | 31 +++++++++++++++
src/c3nav/site/views.py | 21 +++++++++-
6 files changed, 131 insertions(+), 7 deletions(-)
create mode 100644 src/c3nav/mapdata/migrations/0081_auto_20191225_1015.py
diff --git a/src/c3nav/mapdata/migrations/0081_auto_20191225_1015.py b/src/c3nav/mapdata/migrations/0081_auto_20191225_1015.py
new file mode 100644
index 00000000..ace2d53b
--- /dev/null
+++ b/src/c3nav/mapdata/migrations/0081_auto_20191225_1015.py
@@ -0,0 +1,39 @@
+# Generated by Django 2.2.8 on 2019-12-25 09:15
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('mapdata', '0080_auto_20191224_2203'),
+ ]
+
+ operations = [
+ migrations.AlterModelOptions(
+ name='reportupdate',
+ options={'default_related_name': 'reportupdates', 'ordering': ('datetime',), 'verbose_name': 'Report update', 'verbose_name_plural': 'Report updates'},
+ ),
+ migrations.AlterField(
+ model_name='reportupdate',
+ name='author',
+ field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='reportupdates', to=settings.AUTH_USER_MODEL, verbose_name='author'),
+ ),
+ migrations.AlterField(
+ model_name='reportupdate',
+ name='comment',
+ field=models.TextField(blank=True, verbose_name='comment'),
+ ),
+ migrations.AlterField(
+ model_name='reportupdate',
+ name='public',
+ field=models.BooleanField(verbose_name='comment is public'),
+ ),
+ migrations.AlterField(
+ model_name='reportupdate',
+ name='report',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='updates', to='mapdata.Report'),
+ ),
+ ]
diff --git a/src/c3nav/mapdata/models/report.py b/src/c3nav/mapdata/models/report.py
index 8370ab92..f3b94dea 100644
--- a/src/c3nav/mapdata/models/report.py
+++ b/src/c3nav/mapdata/models/report.py
@@ -130,6 +130,12 @@ class Report(models.Model):
Q(permissions__review_group_reports__in=self.get_affected_group_ids())
)
+ def request_can_review(self, request):
+ return (
+ request.user_permissions.review_all_reports or
+ set(request.user_permissions.review_group_ids) & set(self.get_affected_group_ids())
+ )
+
def notify_reviewers(self):
reviewers = tuple(self.get_reviewers_qs().values_list('pk', flat=True))
send_report_notification.delay(pk=self.pk,
@@ -158,16 +164,17 @@ class Report(models.Model):
class ReportUpdate(models.Model):
- report = models.ForeignKey(Report, on_delete=models.CASCADE)
+ report = models.ForeignKey(Report, on_delete=models.CASCADE, related_name='updates')
datetime = models.DateTimeField(auto_now_add=True, verbose_name=_('datetime'))
author = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.PROTECT, verbose_name=_('author'))
open = models.NullBooleanField(verbose_name=_('open'))
- comment = models.TextField(verbose_name=_('comment'))
+ comment = models.TextField(verbose_name=_('comment'), blank=True)
assigned_to = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.PROTECT,
related_name='report_update_assigns', verbose_name=_('assigned to'))
- public = models.BooleanField(verbose_name=_('public'))
+ public = models.BooleanField(verbose_name=_('comment is public'))
class Meta:
verbose_name = _('Report update')
verbose_name_plural = _('Report updates')
- default_related_name = 'reportupdate'
+ default_related_name = 'reportupdates'
+ ordering = ('datetime', )
diff --git a/src/c3nav/site/forms.py b/src/c3nav/site/forms.py
index c63cd9e8..9481c9fc 100644
--- a/src/c3nav/site/forms.py
+++ b/src/c3nav/site/forms.py
@@ -1,7 +1,9 @@
+from django.db import transaction
from django.forms import ModelForm
+from django.utils.translation import ugettext_lazy as _
from c3nav.mapdata.forms import I18nModelFormMixin
-from c3nav.mapdata.models.report import Report
+from c3nav.mapdata.models.report import Report, ReportUpdate
class ReportIssueForm(I18nModelFormMixin, ModelForm):
@@ -18,3 +20,29 @@ class ReportMissingLocationForm(I18nModelFormMixin, ModelForm):
class Meta:
model = Report
fields = ['title', 'description', 'created_title', 'created_groups']
+
+
+class ReportUpdateForm(ModelForm):
+ def __init__(self, request, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.request = request
+ self.fields['open'].label = _('change status')
+ self.fields['open'].widget.choices = (
+ ('unknown', _('don\'t change')),
+ ('true', _('open')),
+ ('false', _('closed')),
+ )
+
+ def save(self):
+ with transaction.atomic():
+ super().save()
+ report = self.instance.report
+ if self.instance.open is not None:
+ report.open = self.instance.open
+ if self.instance.assigned_to:
+ report.assigned_to = self.instance.assigned_to
+ report.save()
+
+ class Meta:
+ model = ReportUpdate
+ fields = ['open', 'comment', 'public']
diff --git a/src/c3nav/site/templates/site/account.html b/src/c3nav/site/templates/site/account.html
index 0b28b00b..574ced43 100644
--- a/src/c3nav/site/templates/site/account.html
+++ b/src/c3nav/site/templates/site/account.html
@@ -29,7 +29,7 @@
{% trans 'You can review reports' %}
- {% trans 'Show reports' %}
+ {% trans 'Show reports' %}
{% elif user_has_reports %}
diff --git a/src/c3nav/site/templates/site/report_detail.html b/src/c3nav/site/templates/site/report_detail.html
index 073d0114..2d0c9dea 100644
--- a/src/c3nav/site/templates/site/report_detail.html
+++ b/src/c3nav/site/templates/site/report_detail.html
@@ -44,5 +44,36 @@
{% endif %}
{% endfor %}
+
+ {% for update in report.updates.all %}
+ {% if update_form or update.public or update.open != None %}
+
+ {{ update.datetime }} – {{ update.author.username }}
+ {% if update.open == True %}
+ {% trans 'Issue was opened.' %}
+ {% elif update.open == False %}
+ {% trans 'Issue was closed.' %}
+ {% endif %}
+ {% if update.comment %}
+ {% if update.public or update_form %}
+ {{ update.comment|linebreaksbr }}
+ {% endif %}
+ {% if update.public and update_form %}
+ {% trans '(public)' %}
+ {% endif %}
+ {% endif %}
+ {% endif %}
+
+ {% endfor %}
+
+ {% if update_form %}
+
+
+ {% endif %}
{% endblock %}
diff --git a/src/c3nav/site/views.py b/src/c3nav/site/views.py
index 7c7edcfa..8f20e94a 100644
--- a/src/c3nav/site/views.py
+++ b/src/c3nav/site/views.py
@@ -29,12 +29,13 @@ from c3nav.mapdata.grid import grid
from c3nav.mapdata.models import Location, Source
from c3nav.mapdata.models.access import AccessPermissionToken
from c3nav.mapdata.models.locations import LocationRedirect, SpecificLocation
-from c3nav.mapdata.models.report import Report
+from c3nav.mapdata.models.report import Report, ReportUpdate
from c3nav.mapdata.utils.locations import (get_location_by_id_for_request, get_location_by_slug_for_request,
levels_by_short_label_for_request)
from c3nav.mapdata.utils.user import can_access_editor, get_user_data
from c3nav.mapdata.views import set_tile_access_cookie
from c3nav.routing.models import RouteOptions
+from c3nav.site.forms import ReportUpdateForm
from c3nav.site.models import Announcement, SiteUpdate
@@ -455,7 +456,25 @@ def report_detail(request, pk, secret=None):
form = report.form_cls(instance=report)
+ can_review = report.request_can_review(request)
+ if can_review:
+ new_update = ReportUpdate(
+ report=report,
+ author=request.user,
+ )
+ if request.method == 'POST':
+ update_form = ReportUpdateForm(request, instance=new_update, data=request.POST)
+ if update_form.is_valid():
+ update_form.save()
+ messages.success(request, _('Report updated.'))
+ return redirect(request.path_info)
+ else:
+ update_form = ReportUpdateForm(request, instance=new_update)
+ else:
+ update_form = None
+
return render(request, 'site/report_detail.html', {
'report': report,
'form': form,
+ 'update_form': update_form,
})