diff --git a/ietf/doc/urls_review.py b/ietf/doc/urls_review.py index 1cc37f744..013344427 100644 --- a/ietf/doc/urls_review.py +++ b/ietf/doc/urls_review.py @@ -9,6 +9,7 @@ urlpatterns = [ url(r'^(?P[0-9]+)/$', views_review.review_request), url(r'^(?P[0-9]+)/login/$', views_review.review_request_forced_login), url(r'^(?P[0-9]+)/close/$', views_review.close_request), + url(r'^(?P[0-9]+)/addrequestcomment/$', views_review.add_request_comment), url(r'^(?P[0-9]+)/assignreviewer/$', views_review.assign_reviewer), url(r'^(?P[0-9]+)/rejectreviewerassignment/$', views_review.reject_reviewer_assignment), url(r'^(?P[0-9]+)/complete/$', views_review.complete_review), diff --git a/ietf/doc/views_review.py b/ietf/doc/views_review.py index e267d9a46..e0e6cb05b 100644 --- a/ietf/doc/views_review.py +++ b/ietf/doc/views_review.py @@ -219,6 +219,8 @@ def review_request(request, name, request_id): can_edit_deadline = can_edit_comment + can_add_comment = can_manage_request + assignments = review_req.reviewassignment_set.all() for assignment in assignments: assignment.is_reviewer = user_is_person(request.user, assignment.reviewer.person) @@ -260,6 +262,7 @@ def review_request(request, name, request_id): 'can_assign_reviewer': can_assign_reviewer, 'can_edit_comment': can_edit_comment, 'can_edit_deadline': can_edit_deadline, + 'can_add_comment': can_add_comment, 'assignments': assignments, 'wg_chairs': wg_chairs, 'iesg_state_summary': iesg_state_summary, @@ -310,6 +313,31 @@ def close_request(request, name, request_id): 'form': form, }) +class AddCommentForm(forms.Form): + comment = forms.CharField(required=True, widget=forms.Textarea, strip=False) + +@login_required +def add_request_comment(request, name, request_id): + doc = get_object_or_404(Document, name=name) + review_req = get_object_or_404(ReviewRequest, pk=request_id) + + can_request = is_authorized_in_doc_stream(request.user, doc) + can_manage_request = can_manage_review_requests_for_team(request.user, review_req.team) + if not (can_request or can_manage_request): + permission_denied(request, "You do not have permission to perform this action") + + if request.method == "POST": + form = AddCommentForm(request.POST) + if form.is_valid(): + c = form.cleaned_data['comment'] + + review_req.add_history(c) + return redirect(review_request, name=review_req.doc.name, request_id=review_req.pk) + else: + form = AddCommentForm() + + return render(request, 'doc/add_comment.html', + dict(doc=doc, form=form, review_req=review_req)) class AssignReviewerForm(forms.Form): reviewer = PersonEmailChoiceField(label="Assign Additional Reviewer", empty_label="(None)") diff --git a/ietf/review/models.py b/ietf/review/models.py index f78e9b83c..d1b50c711 100644 --- a/ietf/review/models.py +++ b/ietf/review/models.py @@ -143,6 +143,10 @@ class ReviewRequest(models.Model): def request_closed_time(self): return self.doc.request_closed_time(self) or self.time + def add_history(self, description): + self._change_reason = description + self.save() + class ReviewAssignment(models.Model): """ One of possibly many reviews assigned in response to a ReviewRequest """ history = HistoricalRecords(history_change_reason_field=models.TextField(null=True)) diff --git a/ietf/review/tests.py b/ietf/review/tests.py index f76d03f56..f9d55d9d1 100644 --- a/ietf/review/tests.py +++ b/ietf/review/tests.py @@ -1,10 +1,14 @@ # Copyright The IETF Trust 2019-2020, All Rights Reserved # -*- coding: utf-8 -*- import datetime +import debug # pyflakes:ignore +from pyquery import PyQuery from ietf.group.factories import RoleFactory +from ietf.doc.factories import WgDraftFactory from ietf.utils.mail import empty_outbox, get_payload_text, outbox from ietf.utils.test_utils import TestCase, reload_db_objects +from ietf.utils.test_utils import login_testing_unauthorized, unicontent from ietf.utils.timezone import date_today, datetime_from_date from .factories import ReviewAssignmentFactory, ReviewRequestFactory, ReviewerSettingsFactory from .mailarch import hash_list_message_id @@ -14,6 +18,7 @@ from .utils import (email_secretary_reminder, review_assignments_needing_secreta send_reminder_unconfirmed_assignments, send_review_reminder_overdue_assignment, send_reminder_all_open_reviews, send_unavailability_period_ending_reminder, ORIGIN_DATE_PERIODIC_REMINDERS) +from django.urls import reverse as urlreverse class HashTest(TestCase): @@ -508,3 +513,40 @@ class ReviewAssignmentReminderTests(TestCase): self.assertTrue(self.reviewer.email_address() in log[0]) self.assertTrue('1 open review' in log[0]) +class AddReviewCommentTestCase(TestCase): + def test_review_add_comment(self): + draft = WgDraftFactory(name='draft-ietf-mars-test',group__acronym='mars') + review_req = ReviewRequestFactory(doc=draft, state_id='assigned') + ReviewAssignmentFactory(review_request=review_req, state_id='assigned') + + url_post = urlreverse('ietf.doc.views_review.add_request_comment', kwargs=dict(name=draft.name, request_id=review_req.pk)) + url_page = urlreverse('ietf.doc.views_review.review_request', kwargs=dict(name=draft.name, request_id=review_req.pk)) + + login_testing_unauthorized(self, "secretary", url_post) + + # Check that we do not have entry on the page + r = self.client.get(url_page) + self.assertEqual(r.status_code, 200) + # Needs to have history + self.assertContains(r, 'History') + # But can't have the comment we are goint to add. + self.assertNotContains(r, 'This is a test.') + + # Get the form + r = self.client.get(url_post) + self.assertEqual(r.status_code, 200) + q = PyQuery(unicontent(r)) + self.assertEqual(len(q('form textarea[name=comment]')), 1) + + # Post the comment + r = self.client.post(url_post, dict(comment="This is a test.")) + self.assertEqual(r.status_code, 302) + + # Get the main page again + r = self.client.get(url_page) + self.assertEqual(r.status_code, 200) + # Needs to have history + self.assertContains(r, 'History') + # But can't have the comment we are goint to add. + self.assertContains(r, 'This is a test.') + diff --git a/ietf/templates/doc/add_comment.html b/ietf/templates/doc/add_comment.html index 01e12418d..211cb380d 100644 --- a/ietf/templates/doc/add_comment.html +++ b/ietf/templates/doc/add_comment.html @@ -2,13 +2,14 @@ {# Copyright The IETF Trust 2015, All Rights Reserved #} {% load origin %} {% load django_bootstrap5 %} -{% block title %}Add comment for {{ doc }}{% endblock %} +{% block title %}Add comment for +{% if review_req %} {{ review_req }} {% else %} {{ doc }} {% endif %} {% endblock %} {% block content %} {% origin %}

Add comment
- {{ doc }} + {% if review_req %} {{ review_req }} {% else %} {{ doc }} {% endif %}

{% csrf_token %} @@ -17,7 +18,12 @@ The comment will be added to the history trail.

{% bootstrap_button button_type="submit" content="Submit" %} + {% if review_req %} + Back + {% else %} Back + {% endif %}
{% endblock %} \ No newline at end of file diff --git a/ietf/templates/doc/review/review_request.html b/ietf/templates/doc/review/review_request.html index ccf3c1836..85335aab6 100644 --- a/ietf/templates/doc/review/review_request.html +++ b/ietf/templates/doc/review/review_request.html @@ -21,6 +21,15 @@ {% endif %}

History

+ {% if can_add_comment %} + + {% endif %}
@@ -30,6 +39,7 @@ + {% for h in history %} {% if h.history_change_reason %} @@ -39,6 +49,7 @@ {% endif %} {% endfor %} +
Description
{% endblock %}