Checkpoint. Lots of tests will still fail. Reordered some migrations. Brought about half of the ietf.doc.views_review views into line with the new models. Next step is the other half.
- Legacy-Id: 16012
This commit is contained in:
parent
82025f9dca
commit
b85052fe63
118
ietf/dbtemplate/migrations/0003_adjust_review_templates.py
Normal file
118
ietf/dbtemplate/migrations/0003_adjust_review_templates.py
Normal file
|
@ -0,0 +1,118 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.20 on 2019-03-05 11:39
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
def forward(apps, schema_editor):
|
||||
DBTemplate = apps.get_model('dbtemplate', 'DBTemplate')
|
||||
DBTemplate.objects.filter(id=186).update(content="""I am the assigned Gen-ART reviewer for this draft. The General Area
|
||||
Review Team (Gen-ART) reviews all IETF documents being processed
|
||||
by the IESG for the IETF Chair. Please treat these comments just
|
||||
like any other last call comments.
|
||||
|
||||
For more information, please see the FAQ at
|
||||
|
||||
<https://trac.ietf.org/trac/gen/wiki/GenArtfaq>.
|
||||
|
||||
Document: {{ assignment.review_request.doc.name }}-??
|
||||
Reviewer: {{ assignment.reviewer.person.plain_name }}
|
||||
Review Date: {{ today }}
|
||||
IETF LC End Date: {% if assignment.review_request.doc.most_recent_ietflc %}{{ assignment.review_request.doc.most_recent_ietflc.expires|date:"Y-m-d" }}{% else %}None{% endif %}
|
||||
IESG Telechat date: {{ assignment.review_request.doc.telechat_date|default:'Not scheduled for a telechat' }}
|
||||
|
||||
Summary:
|
||||
|
||||
Major issues:
|
||||
|
||||
Minor issues:
|
||||
|
||||
Nits/editorial comments:
|
||||
""")
|
||||
|
||||
DBTemplate.objects.filter(id=187).update(content="""I am the assigned Gen-ART reviewer for this draft. The General Area
|
||||
Review Team (Gen-ART) reviews all IETF documents being processed
|
||||
by the IESG for the IETF Chair. Please wait for direction from your
|
||||
document shepherd or AD before posting a new version of the draft.
|
||||
|
||||
For more information, please see the FAQ at
|
||||
|
||||
<https://trac.ietf.org/trac/gen/wiki/GenArtfaq>.
|
||||
|
||||
Document: {{ assignment.review_request.doc.name }}-??
|
||||
Reviewer: {{ assignment.reviewer.person.plain_name }}
|
||||
Review Date: {{ today }}
|
||||
IETF LC End Date: {% if assignment.review_req.doc.most_recent_ietflc %}{{ assignment.review_request.doc.most_recent_ietflc.expires|date:"Y-m-d" }}{% else %}None{% endif %}
|
||||
IESG Telechat date: {{ assignment.review_request.doc.telechat_date|default:'Not scheduled for a telechat' }}
|
||||
|
||||
Summary:
|
||||
|
||||
Major issues:
|
||||
|
||||
Minor issues:
|
||||
|
||||
Nits/editorial comments:
|
||||
|
||||
""")
|
||||
|
||||
def reverse(apps, schema_editor):
|
||||
DBTemplate = apps.get_model('dbtemplate','DBTemplate')
|
||||
DBTemplate.objects.filter(id=186).update(content="""I am the assigned Gen-ART reviewer for this draft. The General Area
|
||||
Review Team (Gen-ART) reviews all IETF documents being processed
|
||||
by the IESG for the IETF Chair. Please treat these comments just
|
||||
like any other last call comments.
|
||||
|
||||
For more information, please see the FAQ at
|
||||
|
||||
<https://trac.ietf.org/trac/gen/wiki/GenArtfaq>.
|
||||
|
||||
Document: {{ review_req.doc.name }}-??
|
||||
Reviewer: {{ review_req.reviewer.person.plain_name }}
|
||||
Review Date: {{ today }}
|
||||
IETF LC End Date: {% if review_req.doc.most_recent_ietflc %}{{ review_req.doc.most_recent_ietflc.expires|date:"Y-m-d" }}{% else %}None{% endif %}
|
||||
IESG Telechat date: {{ review_req.doc.telechat_date|default:'Not scheduled for a telechat' }}
|
||||
|
||||
Summary:
|
||||
|
||||
Major issues:
|
||||
|
||||
Minor issues:
|
||||
|
||||
Nits/editorial comments:
|
||||
|
||||
""")
|
||||
DBTemplate.objects.filter(id=187).update(content="""I am the assigned Gen-ART reviewer for this draft. The General Area
|
||||
Review Team (Gen-ART) reviews all IETF documents being processed
|
||||
by the IESG for the IETF Chair. Please wait for direction from your
|
||||
document shepherd or AD before posting a new version of the draft.
|
||||
|
||||
For more information, please see the FAQ at
|
||||
|
||||
<https://trac.ietf.org/trac/gen/wiki/GenArtfaq>.
|
||||
|
||||
Document: {{ review_req.doc.name }}-??
|
||||
Reviewer: {{ review_req.reviewer.person.plain_name }}
|
||||
Review Date: {{ today }}
|
||||
IETF LC End Date: {% if review_req.doc.most_recent_ietflc %}{{ review_req.doc.most_recent_ietflc.expires|date:"Y-m-d" }}{% else %}None{% endif %}
|
||||
IESG Telechat date: {{ review_req.doc.telechat_date|default:'Not scheduled for a telechat' }}
|
||||
|
||||
Summary:
|
||||
|
||||
Major issues:
|
||||
|
||||
Minor issues:
|
||||
|
||||
Nits/editorial comments:
|
||||
|
||||
""")
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('dbtemplate', '0002_auto_20180220_1052'),
|
||||
('doc','0011_reviewassignmentdocevent'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(forward, reverse)
|
||||
]
|
|
@ -11,7 +11,7 @@ class Migration(migrations.Migration):
|
|||
|
||||
dependencies = [
|
||||
('review', '0009_refactor_review_request'),
|
||||
('name', '0006_adjust_statenames'),
|
||||
('name', '0005_reviewassignmentstatename'),
|
||||
('doc', '0010_auto_20190225_1302'),
|
||||
]
|
||||
|
||||
|
|
|
@ -18,13 +18,13 @@ import debug # pyflakes:ignore
|
|||
|
||||
import ietf.review.mailarch
|
||||
from ietf.doc.factories import NewRevisionDocEventFactory, WgDraftFactory, WgRfcFactory
|
||||
from ietf.doc.models import DocumentAuthor, RelatedDocument, DocEvent, ReviewRequestDocEvent
|
||||
from ietf.doc.models import DocumentAuthor, RelatedDocument, DocEvent, ReviewRequestDocEvent, ReviewAssignmentDocEvent
|
||||
from ietf.group.factories import RoleFactory, ReviewTeamFactory
|
||||
from ietf.group.models import Group
|
||||
from ietf.message.models import Message
|
||||
from ietf.name.models import ReviewResultName, ReviewRequestStateName, ReviewTypeName
|
||||
from ietf.name.models import ReviewResultName, ReviewRequestStateName, ReviewAssignmentStateName, ReviewTypeName
|
||||
from ietf.person.models import Email, Person
|
||||
from ietf.review.factories import ReviewRequestFactory
|
||||
from ietf.review.factories import ReviewRequestFactory, ReviewAssignmentFactory
|
||||
from ietf.review.models import (ReviewRequest, ReviewerSettings,
|
||||
ReviewWish, UnavailablePeriod, NextReviewerInTeam)
|
||||
from ietf.review.utils import reviewer_rotation_list, possibly_advance_next_reviewer_for_team
|
||||
|
@ -60,7 +60,8 @@ class ReviewTests(TestCase):
|
|||
RoleFactory(group=review_team,person__user__username='reviewsecretary',person__user__email='reviewsecretary@example.com',name_id='secr')
|
||||
RoleFactory(group=review_team3,person__user__username='reviewsecretary3',person__user__email='reviewsecretary3@example.com',name_id='secr')
|
||||
|
||||
ReviewRequestFactory(doc=doc,team=review_team,type_id='early',state_id='accepted',requested_by=rev_role.person,reviewer=rev_role.person.email_set.first(),deadline=datetime.datetime.now()+datetime.timedelta(days=20))
|
||||
req = ReviewRequestFactory(doc=doc,team=review_team,type_id='early',state_id='assigned',requested_by=rev_role.person,deadline=datetime.datetime.now()+datetime.timedelta(days=20))
|
||||
ReviewAssignmentFactory(review_request = req, reviewer = rev_role.person.email_set.first(), state_id='accepted')
|
||||
|
||||
url = urlreverse('ietf.doc.views_review.request_review', kwargs={ "name": doc.name })
|
||||
login_testing_unauthorized(self, "ad", url)
|
||||
|
@ -135,7 +136,8 @@ class ReviewTests(TestCase):
|
|||
doc = WgDraftFactory(group__acronym='mars',rev='01')
|
||||
review_team = ReviewTeamFactory(acronym="reviewteam", name="Review Team", type_id="review", list_email="reviewteam@ietf.org", parent=Group.objects.get(acronym="farfut"))
|
||||
rev_role = RoleFactory(group=review_team,person__user__username='reviewer',person__user__email='reviewer@example.com',name_id='reviewer')
|
||||
review_req = ReviewRequestFactory(doc=doc,team=review_team,type_id='early',state_id='accepted',requested_by=rev_role.person,reviewer=rev_role.person.email_set.first(),deadline=datetime.datetime.now()+datetime.timedelta(days=20))
|
||||
review_req = ReviewRequestFactory(doc=doc,team=review_team,type_id='early',state_id='assigned',requested_by=rev_role.person,deadline=datetime.datetime.now()+datetime.timedelta(days=20))
|
||||
assignment = ReviewAssignmentFactory(review_request=review_req, reviewer=rev_role.person.email_set.first(), state_id='accepted')
|
||||
|
||||
# move the review request to a doubly-replaced document to
|
||||
# check we can fish it out
|
||||
|
@ -156,7 +158,8 @@ class ReviewTests(TestCase):
|
|||
doc = WgDraftFactory(group__acronym='mars',rev='01')
|
||||
review_team = ReviewTeamFactory(acronym="reviewteam", name="Review Team", type_id="review", list_email="reviewteam@ietf.org", parent=Group.objects.get(acronym="farfut"))
|
||||
rev_role = RoleFactory(group=review_team,person__user__username='reviewer',person__user__email='reviewer@example.com',name_id='reviewer')
|
||||
review_req = ReviewRequestFactory(doc=doc,team=review_team,type_id='early',state_id='accepted',requested_by=rev_role.person,reviewer=rev_role.person.email_set.first(),deadline=datetime.datetime.now()+datetime.timedelta(days=20))
|
||||
review_req = ReviewRequestFactory(doc=doc,team=review_team,type_id='early',state_id='assigned',requested_by=rev_role.person,deadline=datetime.datetime.now()+datetime.timedelta(days=20))
|
||||
assignment = ReviewAssignmentFactory(review_request = review_req, reviewer = rev_role.person.email_set.first(), state_id='accepted')
|
||||
|
||||
url = urlreverse('ietf.doc.views_review.review_request', kwargs={ "name": doc.name, "request_id": review_req.pk })
|
||||
|
||||
|
@ -436,13 +439,14 @@ class ReviewTests(TestCase):
|
|||
review_team = ReviewTeamFactory(acronym="reviewteam", name="Review Team", type_id="review", list_email="reviewteam@ietf.org", parent=Group.objects.get(acronym="farfut"))
|
||||
rev_role = RoleFactory(group=review_team,person__user__username='reviewer',person__user__email='reviewer@example.com',name_id='reviewer')
|
||||
RoleFactory(group=review_team,person__user__username='reviewsecretary',person__user__email='reviewsecretary@example.com',name_id='secr')
|
||||
review_req = ReviewRequestFactory(doc=doc,team=review_team,type_id='early',state_id='accepted',requested_by=rev_role.person,reviewer=rev_role.person.email_set.first(),deadline=datetime.datetime.now()+datetime.timedelta(days=20))
|
||||
review_req = ReviewRequestFactory(doc=doc,team=review_team,type_id='early',state_id='assigned',requested_by=rev_role.person,deadline=datetime.datetime.now()+datetime.timedelta(days=20))
|
||||
assignment = ReviewAssignmentFactory(review_request = review_req, reviewer=rev_role.person.email_set.first(), state_id='accepted')
|
||||
|
||||
reject_url = urlreverse('ietf.doc.views_review.reject_reviewer_assignment', kwargs={ "name": doc.name, "request_id": review_req.pk })
|
||||
reject_url = urlreverse('ietf.doc.views_review.reject_reviewer_assignment', kwargs={ "name": doc.name, "assignment_id": assignment.pk })
|
||||
|
||||
|
||||
# follow link
|
||||
req_url = urlreverse('ietf.doc.views_review.review_request', kwargs={ "name": doc.name, "request_id": review_req.pk })
|
||||
req_url = urlreverse('ietf.doc.views_review.review_request', kwargs={ "name": doc.name, "request_id": assignment.review_request.pk })
|
||||
self.client.login(username="reviewsecretary", password="reviewsecretary+password")
|
||||
r = self.client.get(req_url)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
|
@ -453,19 +457,18 @@ class ReviewTests(TestCase):
|
|||
login_testing_unauthorized(self, "reviewsecretary", reject_url)
|
||||
r = self.client.get(reject_url)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
self.assertTrue(unicode(review_req.reviewer.person) in unicontent(r))
|
||||
self.assertTrue(unicode(assignment.reviewer.person) in unicontent(r))
|
||||
|
||||
# reject
|
||||
empty_outbox()
|
||||
r = self.client.post(reject_url, { "action": "reject", "message_to_secretary": "Test message" })
|
||||
self.assertEqual(r.status_code, 302)
|
||||
|
||||
review_req = reload_db_objects(review_req)
|
||||
self.assertEqual(review_req.state_id, "rejected")
|
||||
assignment = reload_db_objects(assignment)
|
||||
self.assertEqual(assignment.state_id, "rejected")
|
||||
e = doc.latest_event()
|
||||
self.assertEqual(e.type, "closed_review_request")
|
||||
self.assertTrue("rejected" in e.desc)
|
||||
self.assertEqual(ReviewRequest.objects.filter(doc=review_req.doc, team=review_req.team, state="requested").count(), 1)
|
||||
self.assertEqual(len(outbox), 1)
|
||||
self.assertTrue("Test message" in outbox[0].get_payload(decode=True).decode("utf-8"))
|
||||
|
||||
|
@ -509,7 +512,8 @@ class ReviewTests(TestCase):
|
|||
review_team = ReviewTeamFactory(acronym="reviewteam", name="Review Team", type_id="review", list_email="reviewteam@ietf.org", parent=Group.objects.get(acronym="farfut"))
|
||||
rev_role = RoleFactory(group=review_team,person__user__username='reviewer',person__user__email='reviewer@example.com',name_id='reviewer')
|
||||
RoleFactory(group=review_team,person__user__username='reviewsecretary',person__user__email='reviewsecretary@example.com',name_id='secr')
|
||||
review_req = ReviewRequestFactory(doc=doc,team=review_team,type_id='early',state_id='accepted',requested_by=rev_role.person,reviewer=rev_role.person.email_set.first(),deadline=datetime.datetime.now()+datetime.timedelta(days=20))
|
||||
review_req = ReviewRequestFactory(doc=doc,team=review_team,type_id='early',state_id='assigned',requested_by=rev_role.person,deadline=datetime.datetime.now()+datetime.timedelta(days=20))
|
||||
assignment = ReviewAssignmentFactory(review_request=review_req, reviewer=rev_role.person.email_set.first(), state_id='accepted')
|
||||
|
||||
# test URL construction
|
||||
query_urls = ietf.review.mailarch.construct_query_urls(review_req)
|
||||
|
@ -525,7 +529,7 @@ class ReviewTests(TestCase):
|
|||
real_fn = ietf.review.mailarch.construct_query_urls
|
||||
ietf.review.mailarch.construct_query_urls = lambda review_req, query=None: { "query_data_url": "file://" + os.path.abspath(mbox_path) }
|
||||
|
||||
url = urlreverse('ietf.doc.views_review.search_mail_archive', kwargs={ "name": doc.name, "request_id": review_req.pk })
|
||||
url = urlreverse('ietf.doc.views_review.search_mail_archive', kwargs={ "name": doc.name, "assignment_id": assignment.pk })
|
||||
login_testing_unauthorized(self, "reviewsecretary", url)
|
||||
|
||||
r = self.client.get(url)
|
||||
|
@ -555,7 +559,7 @@ class ReviewTests(TestCase):
|
|||
f.write('Content-Type: text/html\n\n<html><body><div class="xtr"><div class="xtd no-results">No results found</div></div>')
|
||||
ietf.review.mailarch.construct_query_urls = lambda review_req, query=None: { "query_data_url": "file://" + os.path.abspath(no_result_path) }
|
||||
|
||||
url = urlreverse('ietf.doc.views_review.search_mail_archive', kwargs={ "name": doc.name, "request_id": review_req.pk })
|
||||
url = urlreverse('ietf.doc.views_review.search_mail_archive', kwargs={ "name": doc.name, "assignment_id": assignment.pk })
|
||||
|
||||
r = self.client.get(url)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
|
@ -572,18 +576,19 @@ class ReviewTests(TestCase):
|
|||
review_team = ReviewTeamFactory(acronym="reviewteam", name="Review Team", type_id="review", list_email="reviewteam@ietf.org", parent=Group.objects.get(acronym="farfut"))
|
||||
rev_role = RoleFactory(group=review_team,person__user__username='reviewer',person__user__email='reviewer@example.com',name_id='reviewer')
|
||||
RoleFactory(group=review_team,person__user__username='reviewsecretary',person__user__email='reviewsecretary@example.com',name_id='secr')
|
||||
review_req = ReviewRequestFactory(doc=doc,team=review_team,type_id='early',state_id='accepted',requested_by=rev_role.person,reviewer=rev_role.person.email_set.first(),deadline=datetime.datetime.now()+datetime.timedelta(days=20))
|
||||
review_req = ReviewRequestFactory(doc=doc,team=review_team,type_id='early',state_id='assigned',requested_by=rev_role.person,deadline=datetime.datetime.now()+datetime.timedelta(days=20))
|
||||
assignment = ReviewAssignmentFactory(review_request=review_req, state_id='accepted', reviewer=rev_role.person.email_set.first())
|
||||
for r in ReviewResultName.objects.filter(slug__in=("issues", "ready")):
|
||||
review_req.team.reviewteamsettings.review_results.add(r)
|
||||
|
||||
url = urlreverse('ietf.doc.views_review.complete_review', kwargs={ "name": doc.name, "request_id": review_req.pk })
|
||||
url = urlreverse('ietf.doc.views_review.complete_review', kwargs={ "name": doc.name, "assignment_id": review_req.pk })
|
||||
|
||||
return review_req, url
|
||||
return assignment, url
|
||||
|
||||
def test_complete_review_upload_content(self):
|
||||
review_req, url = self.setup_complete_review_test()
|
||||
assignment, url = self.setup_complete_review_test()
|
||||
|
||||
login_testing_unauthorized(self, review_req.reviewer.person.user.username, url)
|
||||
login_testing_unauthorized(self, assignment.reviewer.person.user.username, url)
|
||||
|
||||
# get
|
||||
r = self.client.get(url)
|
||||
|
@ -611,9 +616,9 @@ class ReviewTests(TestCase):
|
|||
test_file.name = "unnamed"
|
||||
|
||||
r = self.client.post(url, data={
|
||||
"result": ReviewResultName.objects.get(reviewteamsettings_review_results_set__group=review_req.team, slug="ready").pk,
|
||||
"state": ReviewRequestStateName.objects.get(slug="completed").pk,
|
||||
"reviewed_rev": review_req.doc.rev,
|
||||
"result": ReviewResultName.objects.get(reviewteamsettings_review_results_set__group=assignment.review_request.team, slug="ready").pk,
|
||||
"state": ReviewAssignmentStateName.objects.get(slug="completed").pk,
|
||||
"reviewed_rev": assignment.review_request.doc.rev,
|
||||
"review_submission": "upload",
|
||||
"review_content": "",
|
||||
"review_url": "",
|
||||
|
@ -621,25 +626,25 @@ class ReviewTests(TestCase):
|
|||
})
|
||||
self.assertEqual(r.status_code, 302)
|
||||
|
||||
review_req = reload_db_objects(review_req)
|
||||
self.assertEqual(review_req.state_id, "completed")
|
||||
self.assertEqual(review_req.result_id, "ready")
|
||||
self.assertEqual(review_req.reviewed_rev, review_req.doc.rev)
|
||||
self.assertTrue(review_req.team.acronym.lower() in review_req.review.name)
|
||||
self.assertTrue(review_req.doc.rev in review_req.review.name)
|
||||
assignment = reload_db_objects(assignment)
|
||||
self.assertEqual(assignment.state_id, "completed")
|
||||
self.assertEqual(assignment.result_id, "ready")
|
||||
self.assertEqual(assignment.reviewed_rev, assignment.review_request.doc.rev)
|
||||
self.assertTrue(assignment.review_request.team.acronym.lower() in assignment.review.name)
|
||||
self.assertTrue(assignment.review_request.doc.rev in assignment.review.name)
|
||||
|
||||
with open(os.path.join(self.review_subdir, review_req.review.name + ".txt")) as f:
|
||||
with open(os.path.join(self.review_subdir, assignment.review.name + ".txt")) as f:
|
||||
self.assertEqual(f.read(), "This is a review\nwith two lines")
|
||||
|
||||
self.assertEqual(len(outbox), 1)
|
||||
self.assertTrue(review_req.team.list_email in outbox[0]["To"])
|
||||
self.assertTrue(review_req.reviewer.role_set.filter(group=review_req.team,name='reviewer').first().email.address in outbox[0]["From"])
|
||||
self.assertTrue(assignment.review_request.team.list_email in outbox[0]["To"])
|
||||
self.assertTrue(assignment.reviewer.role_set.filter(group=assignment.review_request.team,name='reviewer').first().email.address in outbox[0]["From"])
|
||||
self.assertTrue("This is a review" in outbox[0].get_payload(decode=True).decode("utf-8"))
|
||||
|
||||
self.assertTrue(settings.MAILING_LIST_ARCHIVE_URL in review_req.review.external_url)
|
||||
self.assertTrue(settings.MAILING_LIST_ARCHIVE_URL in assignment.review.external_url)
|
||||
|
||||
# Check that the review has the reviewer as author
|
||||
self.assertEqual(review_req.reviewer, review_req.review.documentauthor_set.first().email)
|
||||
self.assertEqual(assignment.reviewer, assignment.review.documentauthor_set.first().email)
|
||||
|
||||
# Check that we have a copy of the outgoing message
|
||||
msgid = outbox[0]["Message-ID"]
|
||||
|
@ -649,25 +654,25 @@ class ReviewTests(TestCase):
|
|||
self.assertEqual(outbox[0].get_payload(decode=True).decode(str(outbox[0].get_charset())), message.body)
|
||||
|
||||
# check the review document page
|
||||
url = urlreverse('ietf.doc.views_doc.document_main', kwargs={ "name": review_req.review.name })
|
||||
url = urlreverse('ietf.doc.views_doc.document_main', kwargs={ "name": assignment.review.name })
|
||||
r = self.client.get(url)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
content = unicontent(r)
|
||||
self.assertTrue("{} Review".format(review_req.type.name) in content)
|
||||
self.assertTrue("{} Review".format(assignment.review_request.type.name) in content)
|
||||
self.assertTrue("This is a review" in content)
|
||||
|
||||
|
||||
def test_complete_review_enter_content(self):
|
||||
review_req, url = self.setup_complete_review_test()
|
||||
assignment, url = self.setup_complete_review_test()
|
||||
|
||||
login_testing_unauthorized(self, review_req.reviewer.person.user.username, url)
|
||||
login_testing_unauthorized(self, assignment.reviewer.person.user.username, url)
|
||||
|
||||
empty_outbox()
|
||||
|
||||
r = self.client.post(url, data={
|
||||
"result": ReviewResultName.objects.get(reviewteamsettings_review_results_set__group=review_req.team, slug="ready").pk,
|
||||
"state": ReviewRequestStateName.objects.get(slug="completed").pk,
|
||||
"reviewed_rev": review_req.doc.rev,
|
||||
"result": ReviewResultName.objects.get(reviewteamsettings_review_results_set__group=assignment.review_request.team, slug="ready").pk,
|
||||
"state": ReviewAssignmentStateName.objects.get(slug="completed").pk,
|
||||
"reviewed_rev": assignment.review_request.doc.rev,
|
||||
"review_submission": "enter",
|
||||
"review_content": "This is a review\nwith two lines",
|
||||
"review_url": "",
|
||||
|
@ -675,32 +680,32 @@ class ReviewTests(TestCase):
|
|||
})
|
||||
self.assertEqual(r.status_code, 302)
|
||||
|
||||
review_req = reload_db_objects(review_req)
|
||||
self.assertEqual(review_req.state_id, "completed")
|
||||
assignment = reload_db_objects(assignment)
|
||||
self.assertEqual(assignment.state_id, "completed")
|
||||
|
||||
with open(os.path.join(self.review_subdir, review_req.review.name + ".txt")) as f:
|
||||
with open(os.path.join(self.review_subdir, assignment.review.name + ".txt")) as f:
|
||||
self.assertEqual(f.read(), "This is a review\nwith two lines")
|
||||
|
||||
self.assertEqual(len(outbox), 1)
|
||||
self.assertTrue(review_req.team.list_email in outbox[0]["To"])
|
||||
self.assertTrue(assignment.review_request.team.list_email in outbox[0]["To"])
|
||||
self.assertTrue("This is a review" in outbox[0].get_payload(decode=True).decode("utf-8"))
|
||||
|
||||
self.assertTrue(settings.MAILING_LIST_ARCHIVE_URL in review_req.review.external_url)
|
||||
self.assertTrue(settings.MAILING_LIST_ARCHIVE_URL in assignment.review.external_url)
|
||||
|
||||
def test_complete_notify_ad_because_team_settings(self):
|
||||
review_req, url = self.setup_complete_review_test()
|
||||
review_req.team.reviewteamsettings.notify_ad_when.add(ReviewResultName.objects.get(slug='issues'))
|
||||
assignment, url = self.setup_complete_review_test()
|
||||
assignment.review_request.team.reviewteamsettings.notify_ad_when.add(ReviewResultName.objects.get(slug='issues'))
|
||||
# TODO - it's a little surprising that the factories so far didn't give this doc an ad
|
||||
review_req.doc.ad = PersonFactory()
|
||||
review_req.doc.save_with_history([DocEvent.objects.create(doc=review_req.doc, rev=review_req.doc.rev, by=review_req.reviewer.person, type='changed_document',desc='added an AD')])
|
||||
login_testing_unauthorized(self, review_req.reviewer.person.user.username, url)
|
||||
assignment.review_request.doc.ad = PersonFactory()
|
||||
assignment.review_request.doc.save_with_history([DocEvent.objects.create(doc=assignment.review_request.doc, rev=assignment.review_request.doc.rev, by=assignment.reviewer.person, type='changed_document',desc='added an AD')])
|
||||
login_testing_unauthorized(self, assignment.reviewer.person.user.username, url)
|
||||
|
||||
empty_outbox()
|
||||
|
||||
r = self.client.post(url, data={
|
||||
"result": ReviewResultName.objects.get(reviewteamsettings_review_results_set__group=review_req.team, slug="issues").pk,
|
||||
"result": ReviewResultName.objects.get(reviewteamsettings_review_results_set__group=assignment.review_request.team, slug="issues").pk,
|
||||
"state": ReviewRequestStateName.objects.get(slug="completed").pk,
|
||||
"reviewed_rev": review_req.doc.rev,
|
||||
"reviewed_rev": assignment.review_request.doc.rev,
|
||||
"review_submission": "enter",
|
||||
"review_content": "This is a review\nwith two lines",
|
||||
"review_url": "",
|
||||
|
@ -713,17 +718,17 @@ class ReviewTests(TestCase):
|
|||
self.assertIn('settings indicated', outbox[-1].get_payload(decode=True).decode("utf-8"))
|
||||
|
||||
def test_complete_notify_ad_because_checkbox(self):
|
||||
review_req, url = self.setup_complete_review_test()
|
||||
review_req.doc.ad = PersonFactory()
|
||||
review_req.doc.save_with_history([DocEvent.objects.create(doc=review_req.doc, rev=review_req.doc.rev, by=review_req.reviewer.person, type='changed_document',desc='added an AD')])
|
||||
login_testing_unauthorized(self, review_req.reviewer.person.user.username, url)
|
||||
assignment, url = self.setup_complete_review_test()
|
||||
assignment.review_request.doc.ad = PersonFactory()
|
||||
assignment.review_request.doc.save_with_history([DocEvent.objects.create(doc=assignment.review_request.doc, rev=assignment.review_request.doc.rev, by=assignment.reviewer.person, type='changed_document',desc='added an AD')])
|
||||
login_testing_unauthorized(self, assignment.reviewer.person.user.username, url)
|
||||
|
||||
empty_outbox()
|
||||
|
||||
r = self.client.post(url, data={
|
||||
"result": ReviewResultName.objects.get(reviewteamsettings_review_results_set__group=review_req.team, slug="issues").pk,
|
||||
"state": ReviewRequestStateName.objects.get(slug="completed").pk,
|
||||
"reviewed_rev": review_req.doc.rev,
|
||||
"result": ReviewResultName.objects.get(reviewteamsettings_review_results_set__group=assignment.review_request.team, slug="issues").pk,
|
||||
"state": ReviewAssignmentStateName.objects.get(slug="completed").pk,
|
||||
"reviewed_rev": assignment.review_request.doc.rev,
|
||||
"review_submission": "enter",
|
||||
"review_content": "This is a review\nwith two lines",
|
||||
"review_url": "",
|
||||
|
@ -745,16 +750,16 @@ class ReviewTests(TestCase):
|
|||
mock.return_value = response
|
||||
|
||||
# Run the test
|
||||
review_req, url = self.setup_complete_review_test()
|
||||
assignment, url = self.setup_complete_review_test()
|
||||
|
||||
login_testing_unauthorized(self, review_req.reviewer.person.user.username, url)
|
||||
login_testing_unauthorized(self, assignment.reviewer.person.user.username, url)
|
||||
|
||||
empty_outbox()
|
||||
|
||||
r = self.client.post(url, data={
|
||||
"result": ReviewResultName.objects.get(reviewteamsettings_review_results_set__group=review_req.team, slug="ready").pk,
|
||||
"state": ReviewRequestStateName.objects.get(slug="completed").pk,
|
||||
"reviewed_rev": review_req.doc.rev,
|
||||
"result": ReviewResultName.objects.get(reviewteamsettings_review_results_set__group=assignment.review_request.team, slug="ready").pk,
|
||||
"state": ReviewAssignmentStateName.objects.get(slug="completed").pk,
|
||||
"reviewed_rev": assignment.review_request.doc.rev,
|
||||
"review_submission": "link",
|
||||
"review_content": response.content,
|
||||
"review_url": "http://example.com/testreview/",
|
||||
|
@ -762,27 +767,27 @@ class ReviewTests(TestCase):
|
|||
})
|
||||
self.assertEqual(r.status_code, 302)
|
||||
|
||||
review_req = reload_db_objects(review_req)
|
||||
self.assertEqual(review_req.state_id, "completed")
|
||||
assignment = reload_db_objects(assignment)
|
||||
self.assertEqual(assignment.state_id, "completed")
|
||||
|
||||
with open(os.path.join(self.review_subdir, review_req.review.name + ".txt")) as f:
|
||||
with open(os.path.join(self.review_subdir, assignment.review.name + ".txt")) as f:
|
||||
self.assertEqual(f.read(), "This is a review\nwith two lines")
|
||||
|
||||
self.assertEqual(len(outbox), 0)
|
||||
self.assertTrue("http://example.com" in review_req.review.external_url)
|
||||
self.assertTrue("http://example.com" in assignment.review.external_url)
|
||||
|
||||
def test_partially_complete_review(self):
|
||||
review_req, url = self.setup_complete_review_test()
|
||||
assignment, url = self.setup_complete_review_test()
|
||||
|
||||
login_testing_unauthorized(self, review_req.reviewer.person.user.username, url)
|
||||
login_testing_unauthorized(self, assignment.reviewer.person.user.username, url)
|
||||
|
||||
# partially complete
|
||||
empty_outbox()
|
||||
|
||||
r = self.client.post(url, data={
|
||||
"result": ReviewResultName.objects.get(reviewteamsettings_review_results_set__group=review_req.team, slug="ready").pk,
|
||||
"state": ReviewRequestStateName.objects.get(slug="part-completed").pk,
|
||||
"reviewed_rev": review_req.doc.rev,
|
||||
"result": ReviewResultName.objects.get(reviewteamsettings_review_results_set__group=assignment.review_request.team, slug="ready").pk,
|
||||
"state": ReviewAssignmentStateName.objects.get(slug="part-completed").pk,
|
||||
"reviewed_rev": assignment.review_request.doc.rev,
|
||||
"review_submission": "enter",
|
||||
"review_content": "This is a review with a somewhat long line spanning over 80 characters to test word wrapping\nand another line",
|
||||
})
|
||||
|
@ -790,16 +795,15 @@ class ReviewTests(TestCase):
|
|||
|
||||
|
||||
|
||||
review_req = reload_db_objects(review_req)
|
||||
self.assertEqual(review_req.state_id, "part-completed")
|
||||
self.assertTrue(review_req.doc.rev in review_req.review.name)
|
||||
assignment = reload_db_objects(assignment)
|
||||
self.assertEqual(assignment.state_id, "part-completed")
|
||||
self.assertTrue(assignment.review_request.doc.rev in assignment.review.name)
|
||||
|
||||
self.assertEqual(len(outbox), 2)
|
||||
self.assertTrue("reviewsecretary@example.com" in outbox[0]["To"])
|
||||
self.assertTrue("partially" in outbox[0]["Subject"].lower())
|
||||
self.assertTrue("new review request" in outbox[0].get_payload(decode=True).decode("utf-8"))
|
||||
|
||||
self.assertTrue(review_req.team.list_email in outbox[1]["To"])
|
||||
self.assertTrue(assignment.review_request.team.list_email in outbox[1]["To"])
|
||||
self.assertTrue("partial review" in outbox[1]["Subject"].lower())
|
||||
body = outbox[1].get_payload(decode=True).decode("utf-8")
|
||||
self.assertTrue("This is a review" in body)
|
||||
|
@ -809,30 +813,27 @@ class ReviewTests(TestCase):
|
|||
self.assertTrue(not any( len(line) > 100 for line in body.splitlines() ))
|
||||
self.assertTrue(any( len(line) > 80 for line in body.splitlines() ))
|
||||
|
||||
first_review = review_req.review
|
||||
first_reviewer = review_req.reviewer
|
||||
first_review = assignment.review
|
||||
first_reviewer = assignment.reviewer
|
||||
|
||||
# complete
|
||||
review_req = ReviewRequest.objects.get(state="requested", doc=review_req.doc, team=review_req.team)
|
||||
self.assertEqual(review_req.reviewer, None)
|
||||
review_req.reviewer = first_reviewer # same reviewer, so we can test uniquification
|
||||
review_req.save()
|
||||
assignment = assignment.review_request.reviewassignment_set.create(state_id="requested", reviewer=assignment.reviewer)
|
||||
|
||||
url = urlreverse('ietf.doc.views_review.complete_review', kwargs={ "name": review_req.doc.name, "request_id": review_req.pk })
|
||||
url = urlreverse('ietf.doc.views_review.complete_review', kwargs={ "name": assignment.review_request.doc.name, "assignment_id": assignment.pk })
|
||||
|
||||
r = self.client.post(url, data={
|
||||
"result": ReviewResultName.objects.get(reviewteamsettings_review_results_set__group=review_req.team, slug="ready").pk,
|
||||
"state": ReviewRequestStateName.objects.get(slug="completed").pk,
|
||||
"reviewed_rev": review_req.doc.rev,
|
||||
"result": ReviewResultName.objects.get(reviewteamsettings_review_results_set__group=assignment.review_request.team, slug="ready").pk,
|
||||
"state": ReviewAssignmentStateName.objects.get(slug="completed").pk,
|
||||
"reviewed_rev": assignment.review_request.doc.rev,
|
||||
"review_submission": "enter",
|
||||
"review_content": "This is another review with a really, really, really, really, really, really, really, really, really, really long line.",
|
||||
})
|
||||
self.assertEqual(r.status_code, 302)
|
||||
|
||||
review_req = reload_db_objects(review_req)
|
||||
self.assertEqual(review_req.state_id, "completed")
|
||||
self.assertTrue(review_req.doc.rev in review_req.review.name)
|
||||
second_review = review_req.review
|
||||
assignment = reload_db_objects(assignment)
|
||||
self.assertEqual(assignment.state_id, "completed")
|
||||
self.assertTrue(assignment.review_request.doc.rev in assignment.review.name)
|
||||
second_review = assignment.review
|
||||
self.assertTrue(first_review.name != second_review.name)
|
||||
self.assertTrue(second_review.name.endswith("-2")) # uniquified
|
||||
|
||||
|
@ -844,18 +845,18 @@ class ReviewTests(TestCase):
|
|||
|
||||
|
||||
def test_revise_review_enter_content(self):
|
||||
review_req, url = self.setup_complete_review_test()
|
||||
review_req.state = ReviewRequestStateName.objects.get(slug="no-response")
|
||||
review_req.save()
|
||||
assignment, url = self.setup_complete_review_test()
|
||||
assignment.state = ReviewAssignmentStateName.objects.get(slug="no-response")
|
||||
assignment.save()
|
||||
|
||||
login_testing_unauthorized(self, review_req.reviewer.person.user.username, url)
|
||||
login_testing_unauthorized(self, assignment.reviewer.person.user.username, url)
|
||||
|
||||
empty_outbox()
|
||||
|
||||
r = self.client.post(url, data={
|
||||
"result": ReviewResultName.objects.get(reviewteamsettings_review_results_set__group=review_req.team, slug="ready").pk,
|
||||
"state": ReviewRequestStateName.objects.get(slug="completed").pk,
|
||||
"reviewed_rev": review_req.doc.rev,
|
||||
"result": ReviewResultName.objects.get(reviewteamsettings_review_results_set__group=assignment.review_request.team, slug="ready").pk,
|
||||
"state": ReviewAssignmentStateName.objects.get(slug="completed").pk,
|
||||
"reviewed_rev": assignment.review_request.doc.rev,
|
||||
"review_submission": "enter",
|
||||
"review_content": "This is a review\nwith two lines",
|
||||
"review_url": "",
|
||||
|
@ -865,12 +866,12 @@ class ReviewTests(TestCase):
|
|||
})
|
||||
self.assertEqual(r.status_code, 302)
|
||||
|
||||
review_req = reload_db_objects(review_req)
|
||||
self.assertEqual(review_req.state_id, "completed")
|
||||
event = ReviewRequestDocEvent.objects.get(type="closed_review_request", review_request=review_req)
|
||||
assignment = reload_db_objects(assignment)
|
||||
self.assertEqual(assignment.state_id, "completed")
|
||||
event = ReviewAssignmentDocEvent.objects.get(type="closed_review_request", review_assignment=assignment)
|
||||
self.assertEqual(event.time, datetime.datetime(2012, 12, 24, 12, 13, 14))
|
||||
|
||||
with open(os.path.join(self.review_subdir, review_req.review.name + ".txt")) as f:
|
||||
with open(os.path.join(self.review_subdir, assignment.review.name + ".txt")) as f:
|
||||
self.assertEqual(f.read(), "This is a review\nwith two lines")
|
||||
|
||||
self.assertEqual(len(outbox), 0)
|
||||
|
@ -878,9 +879,9 @@ class ReviewTests(TestCase):
|
|||
# revise again
|
||||
empty_outbox()
|
||||
r = self.client.post(url, data={
|
||||
"result": ReviewResultName.objects.get(reviewteamsettings_review_results_set__group=review_req.team, slug="ready").pk,
|
||||
"state": ReviewRequestStateName.objects.get(slug="part-completed").pk,
|
||||
"reviewed_rev": review_req.doc.rev,
|
||||
"result": ReviewResultName.objects.get(reviewteamsettings_review_results_set__group=assignment.review_request.team, slug="ready").pk,
|
||||
"state": ReviewAssignmentStateName.objects.get(slug="part-completed").pk,
|
||||
"reviewed_rev": assignment.review_request.doc.rev,
|
||||
"review_submission": "enter",
|
||||
"review_content": "This is a revised review",
|
||||
"review_url": "",
|
||||
|
@ -890,9 +891,9 @@ class ReviewTests(TestCase):
|
|||
})
|
||||
self.assertEqual(r.status_code, 302)
|
||||
|
||||
review_req = reload_db_objects(review_req)
|
||||
self.assertEqual(review_req.review.rev, "01")
|
||||
event = ReviewRequestDocEvent.objects.get(type="closed_review_request", review_request=review_req)
|
||||
assignment = reload_db_objects(assignment)
|
||||
self.assertEqual(assignment.review.rev, "01")
|
||||
event = ReviewAssignmentDocEvent.objects.get(type="closed_review_request", review_assignment=assignment)
|
||||
self.assertEqual(event.time, datetime.datetime(2013, 12, 24, 11, 11, 11))
|
||||
|
||||
self.assertEqual(len(outbox), 0)
|
||||
|
@ -902,7 +903,8 @@ class ReviewTests(TestCase):
|
|||
review_team = ReviewTeamFactory(acronym="reviewteam", name="Review Team", type_id="review", list_email="reviewteam@ietf.org", parent=Group.objects.get(acronym="farfut"))
|
||||
rev_role = RoleFactory(group=review_team,person__user__username='reviewer',person__user__email='reviewer@example.com',name_id='reviewer')
|
||||
RoleFactory(group=review_team,person__user__username='reviewsecretary',person__user__email='reviewsecretary@example.com',name_id='secr')
|
||||
review_req = ReviewRequestFactory(doc=doc,team=review_team,type_id='early',state_id='accepted',requested_by=rev_role.person,reviewer=rev_role.person.email_set.first(),deadline=datetime.datetime.now()+datetime.timedelta(days=20))
|
||||
review_req = ReviewRequestFactory(doc=doc,team=review_team,type_id='early',state_id='assigned',requested_by=rev_role.person,deadline=datetime.datetime.now()+datetime.timedelta(days=20))
|
||||
assignment = ReviewAssignmentFactory(review_request = review_req, reviewer = rev_role.person.email_set.first(), state_id='accepted')
|
||||
|
||||
url = urlreverse('ietf.doc.views_review.edit_comment', kwargs={ "name": doc.name, "request_id": review_req.pk })
|
||||
|
||||
|
@ -923,7 +925,8 @@ class ReviewTests(TestCase):
|
|||
review_team = ReviewTeamFactory(acronym="reviewteam", name="Review Team", type_id="review", list_email="reviewteam@ietf.org", parent=Group.objects.get(acronym="farfut"))
|
||||
rev_role = RoleFactory(group=review_team,person__user__username='reviewer',person__user__email='reviewer@example.com',name_id='reviewer')
|
||||
RoleFactory(group=review_team,person__user__username='reviewsecretary',person__user__email='reviewsecretary@example.com',name_id='secr')
|
||||
review_req = ReviewRequestFactory(doc=doc,team=review_team,type_id='early',state_id='accepted',requested_by=rev_role.person,reviewer=rev_role.person.email_set.first(),deadline=datetime.datetime.now()+datetime.timedelta(days=20))
|
||||
review_req = ReviewRequestFactory(doc=doc,team=review_team,type_id='early',state_id='accepted',requested_by=rev_role.person,deadline=datetime.datetime.now()+datetime.timedelta(days=20))
|
||||
assignment = ReviewAssignmentFactory(review_request = review_req, reviewer = rev_role.person.email_set.first(), state_id='accepted')
|
||||
|
||||
url = urlreverse('ietf.doc.views_review.edit_deadline', kwargs={ "name": doc.name, "request_id": review_req.pk })
|
||||
|
||||
|
|
|
@ -7,9 +7,9 @@ urlpatterns = [
|
|||
url(r'^(?P<request_id>[0-9]+)/login/$', views_review.review_request_forced_login),
|
||||
url(r'^(?P<request_id>[0-9]+)/close/$', views_review.close_request),
|
||||
url(r'^(?P<request_id>[0-9]+)/assignreviewer/$', views_review.assign_reviewer),
|
||||
url(r'^(?P<request_id>[0-9]+)/rejectreviewerassignment/$', views_review.reject_reviewer_assignment),
|
||||
url(r'^(?P<request_id>[0-9]+)/complete/$', views_review.complete_review),
|
||||
url(r'^(?P<request_id>[0-9]+)/searchmailarchive/$', views_review.search_mail_archive),
|
||||
url(r'^(?P<assignment_id>[0-9]+)/rejectreviewerassignment/$', views_review.reject_reviewer_assignment),
|
||||
url(r'^(?P<assignment_id>[0-9]+)/complete/$', views_review.complete_review),
|
||||
url(r'^(?P<assignment_id>[0-9]+)/searchmailarchive/$', views_review.search_mail_archive),
|
||||
url(r'^(?P<request_id>[0-9]+)/editcomment/$', views_review.edit_comment),
|
||||
url(r'^(?P<request_id>[0-9]+)/editdeadline/$', views_review.edit_deadline),
|
||||
]
|
||||
|
|
|
@ -598,7 +598,8 @@ def document_main(request, name, rev=None):
|
|||
# If we want to go back to using markup_txt.markup_unicode, call it explicitly here like this:
|
||||
# content = markup_txt.markup_unicode(content, split=False, width=80)
|
||||
|
||||
review_req = ReviewRequest.objects.filter(review=doc.name).first()
|
||||
# TODO - verify if this shows other reviews from the same team - I bet it doesn't
|
||||
review_req = ReviewRequest.objects.filter(reviewassignment__review=doc.name).first()
|
||||
|
||||
other_reviews = []
|
||||
if review_req:
|
||||
|
|
|
@ -20,7 +20,7 @@ from django.template.loader import render_to_string, TemplateDoesNotExist
|
|||
from django.urls import reverse as urlreverse
|
||||
|
||||
from ietf.doc.models import (Document, NewRevisionDocEvent, State, DocAlias,
|
||||
LastCallDocEvent, ReviewRequestDocEvent, DocumentAuthor)
|
||||
LastCallDocEvent, ReviewRequestDocEvent, ReviewAssignmentDocEvent, DocumentAuthor)
|
||||
from ietf.name.models import ReviewRequestStateName, ReviewAssignmentStateName, ReviewResultName, DocTypeName
|
||||
from ietf.review.models import ReviewRequest, ReviewAssignment
|
||||
from ietf.group.models import Group
|
||||
|
@ -184,7 +184,6 @@ def review_request(request, name, request_id):
|
|||
doc = get_object_or_404(Document, name=name)
|
||||
review_req = get_object_or_404(ReviewRequest, pk=request_id)
|
||||
|
||||
is_reviewer = review_req.reviewer and user_is_person(request.user, review_req.reviewer.person)
|
||||
can_manage_request = can_manage_review_requests_for_team(request.user, review_req.team)
|
||||
|
||||
can_close_request = (review_req.state_id in ["requested", "accepted"]
|
||||
|
@ -194,37 +193,38 @@ def review_request(request, name, request_id):
|
|||
can_assign_reviewer = (review_req.state_id in ["requested", "accepted"]
|
||||
and can_manage_request)
|
||||
|
||||
can_accept_reviewer_assignment = (review_req.state_id == "requested"
|
||||
and review_req.reviewer
|
||||
and (is_reviewer or can_manage_request))
|
||||
|
||||
can_reject_reviewer_assignment = (review_req.state_id in ["requested", "accepted"]
|
||||
and review_req.reviewer
|
||||
and (is_reviewer or can_manage_request))
|
||||
|
||||
can_complete_review = (review_req.state_id in ["requested", "accepted", "overtaken", "no-response", "part-completed", "completed"]
|
||||
and review_req.reviewer
|
||||
and (is_reviewer or can_manage_request))
|
||||
|
||||
can_edit_comment = can_request_review_of_doc(request.user, doc)
|
||||
|
||||
can_edit_deadline = can_edit_comment
|
||||
|
||||
if request.method == "POST" and request.POST.get("action") == "accept" and can_accept_reviewer_assignment:
|
||||
review_req.state = ReviewRequestStateName.objects.get(slug="accepted")
|
||||
review_req.save()
|
||||
assignments = review_req.reviewassignment_set.all()
|
||||
for assignment in assignments:
|
||||
assignment.is_reviewer = user_is_person(request.user, assignment.reviewer.person)
|
||||
|
||||
assignment.can_accept_reviewer_assignment = (assignment.state_id == "requested"
|
||||
and (assignment.is_reviewer or can_manage_request))
|
||||
|
||||
assignment.can_reject_reviewer_assignment = (assignment.state_id in ["requested", "accepted"]
|
||||
and (assignment.is_reviewer or can_manage_request))
|
||||
|
||||
assignment.can_complete_review = (assignment.state_id in ["requested", "accepted", "overtaken", "no-response", "part-completed", "completed"]
|
||||
and (assignment.is_reviewer or can_manage_request))
|
||||
|
||||
if request.method == "POST" and request.POST.get("action") == "accept":
|
||||
for assignment in assignments:
|
||||
if assignment.can_accept_reviewer_assignment:
|
||||
assignment.state = ReviewAssignmentStateName.objects.get(slug="accepted")
|
||||
assignment.save()
|
||||
return redirect(review_request, name=review_req.doc.name, request_id=review_req.pk)
|
||||
|
||||
return render(request, 'doc/review/review_request.html', {
|
||||
'doc': doc,
|
||||
'review_req': review_req,
|
||||
'can_close_request': can_close_request,
|
||||
'can_reject_reviewer_assignment': can_reject_reviewer_assignment,
|
||||
'can_assign_reviewer': can_assign_reviewer,
|
||||
'can_accept_reviewer_assignment': can_accept_reviewer_assignment,
|
||||
'can_complete_review': can_complete_review,
|
||||
'can_edit_comment': can_edit_comment,
|
||||
'can_edit_deadline': can_edit_deadline,
|
||||
'assignments': assignments,
|
||||
})
|
||||
|
||||
|
||||
|
@ -327,20 +327,19 @@ def reject_reviewer_assignment(request, name, assignment_id):
|
|||
review_assignment.state = ReviewAssignmentStateName.objects.get(slug="rejected")
|
||||
review_assignment.save()
|
||||
|
||||
# TODO: this needs to be reworked as a ReviewAssignmentDocEvent
|
||||
#ReviewRequestDocEvent.objects.create(
|
||||
# type="closed_review_request",
|
||||
# doc=review_req.doc,
|
||||
# rev=review_req.doc.rev,
|
||||
# by=request.user.person,
|
||||
# desc="Assignment of request for {} review by {} to {} was rejected".format(
|
||||
# review_req.type.name,
|
||||
# review_req.team.acronym.upper(),
|
||||
# review_req.reviewer.person,
|
||||
# ),
|
||||
# review_request=review_req,
|
||||
# state=review_req.state,
|
||||
#)
|
||||
ReviewAssignmentDocEvent.objects.create(
|
||||
type="closed_review_request",
|
||||
doc=review_assignment.review_request.doc,
|
||||
rev=review_assignment.review_request.doc.rev,
|
||||
by=request.user.person,
|
||||
desc="Assignment of request for {} review by {} to {} was rejected".format(
|
||||
review_assignment.review_request.type.name,
|
||||
review_assignment.review_request.team.acronym.upper(),
|
||||
review_assignment.reviewer.person,
|
||||
),
|
||||
review_assignment=review_assignment,
|
||||
state=review_assignment.state,
|
||||
)
|
||||
|
||||
msg = render_to_string("review/reviewer_assignment_rejected.txt", {
|
||||
"by": request.user.person,
|
||||
|
@ -360,7 +359,7 @@ def reject_reviewer_assignment(request, name, assignment_id):
|
|||
})
|
||||
|
||||
class CompleteReviewForm(forms.Form):
|
||||
state = forms.ModelChoiceField(queryset=ReviewRequestStateName.objects.filter(slug__in=("completed", "part-completed")).order_by("-order"), widget=forms.RadioSelect, initial="completed")
|
||||
state = forms.ModelChoiceField(queryset=ReviewAssignmentStateName.objects.filter(slug__in=("completed", "part-completed")).order_by("-order"), widget=forms.RadioSelect, initial="completed")
|
||||
reviewed_rev = forms.CharField(label="Reviewed revision", max_length=4)
|
||||
result = forms.ModelChoiceField(queryset=ReviewResultName.objects.filter(used=True), widget=forms.RadioSelect, empty_label=None)
|
||||
ACTIONS = [
|
||||
|
@ -378,16 +377,16 @@ class CompleteReviewForm(forms.Form):
|
|||
cc = MultiEmailField(required=False, help_text="Email addresses to send to in addition to the review team list")
|
||||
email_ad = forms.BooleanField(label="Send extra email to the responsible AD suggesting early attention", required=False)
|
||||
|
||||
def __init__(self, review_req, is_reviewer, *args, **kwargs):
|
||||
self.review_req = review_req
|
||||
def __init__(self, assignment, is_reviewer, *args, **kwargs):
|
||||
self.assignment = assignment
|
||||
|
||||
super(CompleteReviewForm, self).__init__(*args, **kwargs)
|
||||
|
||||
doc = self.review_req.doc
|
||||
doc = self.assignment.review_request.doc
|
||||
|
||||
known_revisions = NewRevisionDocEvent.objects.filter(doc=doc).order_by("time", "id").values_list("rev", "time", flat=False)
|
||||
|
||||
revising_review = review_req.state_id not in ["requested", "accepted"]
|
||||
revising_review = assignment.state_id not in ["requested", "accepted"]
|
||||
|
||||
if not revising_review:
|
||||
self.fields["state"].choices = [
|
||||
|
@ -399,7 +398,7 @@ class CompleteReviewForm(forms.Form):
|
|||
reviewed_rev_class = []
|
||||
for r in known_revisions:
|
||||
last_version = r[0]
|
||||
if r[1] < review_req.time:
|
||||
if r[1] < assignment.review_request.time:
|
||||
kwargs["initial"]["reviewed_rev"] = r[0]
|
||||
reviewed_rev_class.append('reviewer-doc-past')
|
||||
else:
|
||||
|
@ -423,13 +422,13 @@ class CompleteReviewForm(forms.Form):
|
|||
" ".join("<a class=\"rev label label-default {0}\" title=\"{2:%Y-%m-%d}\">{1}</a>".format('', *r)
|
||||
for i, r in enumerate(known_revisions)))
|
||||
|
||||
self.fields["result"].queryset = self.fields["result"].queryset.filter(reviewteamsettings_review_results_set__group=review_req.team)
|
||||
self.fields["result"].queryset = self.fields["result"].queryset.filter(reviewteamsettings_review_results_set__group=assignment.review_request.team)
|
||||
|
||||
def format_submission_choice(label):
|
||||
if revising_review:
|
||||
label = label.replace(" (automatically posts to {mailing_list})", "")
|
||||
|
||||
return label.format(mailing_list=review_req.team.list_email or "[error: team has no mailing list set]")
|
||||
return label.format(mailing_list=assignment.review_request.team.list_email or "[error: team has no mailing list set]")
|
||||
|
||||
self.fields["review_submission"].choices = [ (k, format_submission_choice(label)) for k, label in self.fields["review_submission"].choices]
|
||||
|
||||
|
@ -440,7 +439,7 @@ class CompleteReviewForm(forms.Form):
|
|||
del self.fields["completion_time"]
|
||||
|
||||
def clean_reviewed_rev(self):
|
||||
return clean_doc_revision(self.review_req.doc, self.cleaned_data.get("reviewed_rev"))
|
||||
return clean_doc_revision(self.assignment.review_request.doc, self.cleaned_data.get("reviewed_rev"))
|
||||
|
||||
def clean_review_content(self):
|
||||
return self.cleaned_data["review_content"].replace("\r", "")
|
||||
|
@ -458,7 +457,7 @@ class CompleteReviewForm(forms.Form):
|
|||
return url
|
||||
|
||||
def clean(self):
|
||||
if "@" in self.review_req.reviewer.person.ascii:
|
||||
if "@" in self.assignment.reviewer.person.ascii:
|
||||
raise forms.ValidationError("Reviewer name must be filled in (the ASCII version is currently \"{}\" - since it contains an @ sign the name is probably still the original email address).".format(self.review_req.reviewer.person.ascii))
|
||||
|
||||
def require_field(f):
|
||||
|
@ -474,40 +473,37 @@ class CompleteReviewForm(forms.Form):
|
|||
require_field("review_url")
|
||||
|
||||
@login_required
|
||||
def complete_review(request, name, request_id):
|
||||
def complete_review(request, name, assignment_id):
|
||||
doc = get_object_or_404(Document, name=name)
|
||||
review_req = get_object_or_404(ReviewRequest, pk=request_id)
|
||||
assignment = get_object_or_404(ReviewAssignment, pk=assignment_id)
|
||||
|
||||
revising_review = review_req.state_id not in ["requested", "accepted"]
|
||||
revising_review = assignment.state_id not in ["requested", "accepted"]
|
||||
|
||||
if not review_req.reviewer:
|
||||
return redirect(review_request, name=review_req.doc.name, request_id=review_req.pk)
|
||||
|
||||
is_reviewer = user_is_person(request.user, review_req.reviewer.person)
|
||||
can_manage_request = can_manage_review_requests_for_team(request.user, review_req.team)
|
||||
is_reviewer = user_is_person(request.user, assignment.reviewer.person)
|
||||
can_manage_request = can_manage_review_requests_for_team(request.user, assignment.review_request.team)
|
||||
|
||||
if not (is_reviewer or can_manage_request):
|
||||
return HttpResponseForbidden("You do not have permission to perform this action")
|
||||
|
||||
(to, cc) = gather_address_lists('review_completed',review_req = review_req)
|
||||
(to, cc) = gather_address_lists('review_completed', review_req = assignment.review_request)
|
||||
|
||||
if request.method == "POST":
|
||||
form = CompleteReviewForm(review_req, is_reviewer,
|
||||
form = CompleteReviewForm(assignment, is_reviewer,
|
||||
request.POST, request.FILES)
|
||||
if form.is_valid():
|
||||
review_submission = form.cleaned_data['review_submission']
|
||||
|
||||
review = review_req.review
|
||||
review = assignment.review
|
||||
if not review:
|
||||
# create review doc
|
||||
for i in range(1, 100):
|
||||
name_components = [
|
||||
"review",
|
||||
strip_prefix(review_req.doc.name, "draft-"),
|
||||
strip_prefix(assignment.review_request.doc.name, "draft-"),
|
||||
form.cleaned_data["reviewed_rev"],
|
||||
review_req.team.acronym,
|
||||
review_req.type.slug,
|
||||
xslugify(review_req.reviewer.person.ascii_parts()[3]),
|
||||
assignment.review_request.team.acronym,
|
||||
assignment.review_request.type.slug,
|
||||
xslugify(assignment.reviewer.person.ascii_parts()[3]),
|
||||
datetime.date.today().isoformat(),
|
||||
]
|
||||
if i > 1:
|
||||
|
@ -520,10 +516,10 @@ def complete_review(request, name, request_id):
|
|||
break
|
||||
|
||||
review.type = DocTypeName.objects.get(slug="review")
|
||||
review.group = review_req.team
|
||||
review.group = assignment.review_request.team
|
||||
|
||||
review.rev = "00" if not review.rev else "{:02}".format(int(review.rev) + 1)
|
||||
review.title = "{} Review of {}-{}".format(review_req.type.name, review_req.doc.name, form.cleaned_data["reviewed_rev"])
|
||||
review.title = "{} Review of {}-{}".format(assignment.review_request.type.name, assignment.review_request.doc.name, form.cleaned_data["reviewed_rev"])
|
||||
review.time = datetime.datetime.now()
|
||||
if review_submission == "link":
|
||||
review.external_url = form.cleaned_data['review_url']
|
||||
|
@ -551,63 +547,56 @@ def complete_review(request, name, request_id):
|
|||
with open(filename, 'wb') as destination:
|
||||
destination.write(encoded_content)
|
||||
|
||||
# close review request
|
||||
review_req.state = form.cleaned_data["state"]
|
||||
review_req.reviewed_rev = form.cleaned_data["reviewed_rev"]
|
||||
review_req.result = form.cleaned_data["result"]
|
||||
review_req.review = review
|
||||
review_req.save()
|
||||
|
||||
need_to_email_review = review_submission != "link" and review_req.team.list_email and not revising_review
|
||||
|
||||
desc = "Request for {} review by {} {}: {}. Reviewer: {}.".format(
|
||||
review_req.type.name,
|
||||
review_req.team.acronym.upper(),
|
||||
review_req.state.name,
|
||||
review_req.result.name,
|
||||
review_req.reviewer.person,
|
||||
)
|
||||
if need_to_email_review:
|
||||
desc += " " + "Sent review to list."
|
||||
|
||||
completion_datetime = datetime.datetime.now()
|
||||
if "completion_date" in form.cleaned_data:
|
||||
completion_datetime = datetime.datetime.combine(form.cleaned_data["completion_date"], form.cleaned_data.get("completion_time") or datetime.time.min)
|
||||
|
||||
close_event = ReviewRequestDocEvent.objects.filter(type="closed_review_request", review_request=review_req).first()
|
||||
if not close_event:
|
||||
close_event = ReviewRequestDocEvent(type="closed_review_request", review_request=review_req)
|
||||
# complete assignment
|
||||
assignment.state = form.cleaned_data["state"]
|
||||
assignment.reviewed_rev = form.cleaned_data["reviewed_rev"]
|
||||
assignment.result = form.cleaned_data["result"]
|
||||
assignment.review = review
|
||||
assignment.completed_on = completion_datetime
|
||||
assignment.save()
|
||||
|
||||
close_event.doc = review_req.doc
|
||||
close_event.rev = review_req.doc.rev
|
||||
need_to_email_review = review_submission != "link" and assignment.review_request.team.list_email and not revising_review
|
||||
|
||||
desc = "Request for {} review by {} {}: {}. Reviewer: {}.".format(
|
||||
assignment.review_request.type.name,
|
||||
assignment.review_request.team.acronym.upper(),
|
||||
assignment.state.name,
|
||||
assignment.result.name,
|
||||
assignment.reviewer.person,
|
||||
)
|
||||
if need_to_email_review:
|
||||
desc += " " + "Sent review to list."
|
||||
|
||||
close_event = ReviewAssignmentDocEvent.objects.filter(type="closed_review_request", review_assignment=assignment).first()
|
||||
if not close_event:
|
||||
close_event = ReviewAssignmentDocEvent(type="closed_review_request", review_assignment=assignment)
|
||||
|
||||
close_event.doc = assignment.review_request.doc
|
||||
close_event.rev = assignment.review_request.doc.rev
|
||||
close_event.by = request.user.person
|
||||
close_event.desc = desc
|
||||
close_event.state = review_req.state
|
||||
close_event.state = assignment.state
|
||||
close_event.time = completion_datetime
|
||||
close_event.save()
|
||||
|
||||
if review_req.state_id == "part-completed" and not revising_review:
|
||||
existing_open_reqs = ReviewRequest.objects.filter(doc=review_req.doc, team=review_req.team, state__in=("requested", "accepted"))
|
||||
if assignment.state_id == "part-completed" and not revising_review:
|
||||
existing_assignments = ReviewAssignment.objects.filter(review_request__doc=assignment.review_request.doc, review_request__team=assignment.review_request.team, state__in=("requested", "accepted", "completed"))
|
||||
|
||||
new_review_req_url = new_review_req = None
|
||||
if not existing_open_reqs:
|
||||
new_review_req = make_new_review_request_from_existing(review_req)
|
||||
new_review_req.save()
|
||||
|
||||
new_review_req_url = urlreverse("ietf.doc.views_review.review_request", kwargs={ "name": new_review_req.doc.name, "request_id": new_review_req.pk })
|
||||
new_review_req_url = request.build_absolute_uri(new_review_req_url)
|
||||
|
||||
subject = "Review of {}-{} completed partially".format(review_req.doc.name, review_req.reviewed_rev)
|
||||
subject = "Review of {}-{} completed partially".format(assignment.review_request.doc.name, assignment.reviewed_rev)
|
||||
|
||||
msg = render_to_string("review/partially_completed_review.txt", {
|
||||
"new_review_req_url": new_review_req_url,
|
||||
"existing_open_reqs": existing_open_reqs,
|
||||
"existing_assignments": existing_assignments,
|
||||
"by": request.user.person,
|
||||
})
|
||||
|
||||
email_review_request_change(request, review_req, subject, msg, request.user.person, notify_secretary=True, notify_reviewer=False, notify_requested_by=False)
|
||||
# TODO: replumb this function to work with assignments
|
||||
email_review_request_change(request, assignment.review_request, subject, msg, request.user.person, notify_secretary=True, notify_reviewer=False, notify_requested_by=False)
|
||||
|
||||
role = request.user.person.role_set.filter(group=review_req.team,name='reviewer').first()
|
||||
role = request.user.person.role_set.filter(group=assignment.review_request.team,name='reviewer').first()
|
||||
if role and role.email.active:
|
||||
author_email = role.email
|
||||
frm = role.formatted_email()
|
||||
|
@ -618,10 +607,10 @@ def complete_review(request, name, request_id):
|
|||
|
||||
if need_to_email_review:
|
||||
# email the review
|
||||
subject = "{} {} {} of {}-{}".format(review_req.team.acronym.capitalize(),review_req.type.name.lower(),"partial review" if review_req.state_id == "part-completed" else "review", review_req.doc.name, review_req.reviewed_rev)
|
||||
related_groups = [ review_req.team, ]
|
||||
if review_req.doc.group:
|
||||
related_groups.append(review_req.doc.group)
|
||||
subject = "{} {} {} of {}-{}".format(assignment.review_request.team.acronym.capitalize(),assignment.review_request.type.name.lower(),"partial review" if assignment.state_id == "part-completed" else "review", assignment.review_request.doc.name, assignment.reviewed_rev)
|
||||
related_groups = [ assignment.review_request.team, ]
|
||||
if assignment.review_request.doc.group:
|
||||
related_groups.append(assignment.review_request.doc.group)
|
||||
msg = Message.objects.create(
|
||||
by=request.user.person,
|
||||
subject=subject,
|
||||
|
@ -629,26 +618,26 @@ def complete_review(request, name, request_id):
|
|||
to=", ".join(to),
|
||||
cc=form.cleaned_data["cc"],
|
||||
body = render_to_string("review/completed_review.txt", {
|
||||
"review_req": review_req,
|
||||
"assignment": assignment,
|
||||
"content": encoded_content.decode("utf-8"),
|
||||
}),
|
||||
)
|
||||
msg.related_groups.add(*related_groups)
|
||||
msg.related_docs.add(review_req.doc)
|
||||
msg.related_docs.add(assignment.review_request.doc)
|
||||
|
||||
msg = send_mail_message(request, msg)
|
||||
|
||||
list_name = mailarch.list_name_from_email(review_req.team.list_email)
|
||||
list_name = mailarch.list_name_from_email(assignment.review_request.team.list_email)
|
||||
if list_name:
|
||||
review.external_url = mailarch.construct_message_url(list_name, email.utils.unquote(msg["Message-ID"]))
|
||||
review.save_with_history([close_event])
|
||||
|
||||
if form.cleaned_data['email_ad'] or review_req.result in review_req.team.reviewteamsettings.notify_ad_when.all():
|
||||
(to, cc) = gather_address_lists('review_notify_ad',review_req = review_req).as_strings()
|
||||
if form.cleaned_data['email_ad'] or assignment.result in assignment.review_request.team.reviewteamsettings.notify_ad_when.all():
|
||||
(to, cc) = gather_address_lists('review_notify_ad',review_req = assignment.review_request).as_strings()
|
||||
msg_txt = render_to_string("review/notify_ad.txt", {
|
||||
"to": to,
|
||||
"cc": cc,
|
||||
"review_req": review_req,
|
||||
"assignment": assignment,
|
||||
"settings": settings,
|
||||
"explicit_request": form.cleaned_data['email_ad'],
|
||||
})
|
||||
|
@ -657,42 +646,41 @@ def complete_review(request, name, request_id):
|
|||
msg.save()
|
||||
send_mail_message(request, msg)
|
||||
|
||||
return redirect("ietf.doc.views_doc.document_main", name=review_req.review.name)
|
||||
return redirect("ietf.doc.views_doc.document_main", name=assignment.review.name)
|
||||
else:
|
||||
initial={
|
||||
"reviewed_rev": review_req.reviewed_rev,
|
||||
"result": review_req.result_id,
|
||||
"reviewed_rev": assignment.reviewed_rev,
|
||||
"result": assignment.result_id,
|
||||
"cc": ", ".join(cc),
|
||||
}
|
||||
|
||||
try:
|
||||
initial['review_content'] = render_to_string('/group/%s/review/content_templates/%s.txt' % (review_req.team.acronym, review_req.type.slug), {'review_req':review_req,'today':datetime.date.today()})
|
||||
initial['review_content'] = render_to_string('/group/%s/review/content_templates/%s.txt' % (assignment.review_request.team.acronym, assignment.review_request.type.slug), {'assignment':assignment,'today':datetime.date.today()})
|
||||
except TemplateDoesNotExist:
|
||||
pass
|
||||
|
||||
form = CompleteReviewForm(review_req, is_reviewer, initial=initial)
|
||||
form = CompleteReviewForm(assignment, is_reviewer, initial=initial)
|
||||
|
||||
mail_archive_query_urls = mailarch.construct_query_urls(review_req)
|
||||
mail_archive_query_urls = mailarch.construct_query_urls(assignment.review_request)
|
||||
|
||||
return render(request, 'doc/review/complete_review.html', {
|
||||
'doc': doc,
|
||||
'review_req': review_req,
|
||||
'assignment': assignment,
|
||||
'form': form,
|
||||
'mail_archive_query_urls': mail_archive_query_urls,
|
||||
'revising_review': revising_review,
|
||||
})
|
||||
|
||||
def search_mail_archive(request, name, request_id):
|
||||
#doc = get_object_or_404(Document, name=name)
|
||||
review_req = get_object_or_404(ReviewRequest, pk=request_id)
|
||||
def search_mail_archive(request, name, assignment_id):
|
||||
assignment = get_object_or_404(ReviewAssignment, pk=assignment_id)
|
||||
|
||||
is_reviewer = user_is_person(request.user, review_req.reviewer.person)
|
||||
can_manage_request = can_manage_review_requests_for_team(request.user, review_req.team)
|
||||
is_reviewer = user_is_person(request.user, assignment.reviewer.person)
|
||||
can_manage_request = can_manage_review_requests_for_team(request.user, assignment.review_request.team)
|
||||
|
||||
if not (is_reviewer or can_manage_request):
|
||||
return HttpResponseForbidden("You do not have permission to perform this action")
|
||||
|
||||
res = mailarch.construct_query_urls(review_req, query=request.GET.get("query"))
|
||||
res = mailarch.construct_query_urls(assignment.review_request, query=request.GET.get("query"))
|
||||
if not res:
|
||||
return JsonResponse({ "error": "Couldn't do lookup in mail archive - don't know where to look"})
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -85,6 +85,7 @@ class Migration(migrations.Migration):
|
|||
|
||||
dependencies = [
|
||||
('name', '0005_reviewassignmentstatename'),
|
||||
('doc','0011_reviewassignmentdocevent'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import factory
|
||||
import datetime
|
||||
|
||||
from ietf.review.models import ReviewTeamSettings, ReviewRequest, ReviewerSettings
|
||||
from ietf.review.models import ReviewTeamSettings, ReviewRequest, ReviewAssignment, ReviewerSettings
|
||||
from ietf.name.models import ReviewTypeName, ReviewResultName
|
||||
|
||||
class ReviewTeamSettingsFactory(factory.DjangoModelFactory):
|
||||
|
@ -39,6 +39,14 @@ class ReviewRequestFactory(factory.DjangoModelFactory):
|
|||
deadline = datetime.datetime.today()+datetime.timedelta(days=14)
|
||||
requested_by = factory.SubFactory('ietf.person.factories.PersonFactory')
|
||||
|
||||
class ReviewAssignmentFactory(factory.DjangoModelFactory):
|
||||
class Meta:
|
||||
model = ReviewAssignment
|
||||
|
||||
review_request = factory.SubFactory('ietf.review.factories.ReviewRequestFactory')
|
||||
state_id = 'requested'
|
||||
reviewer = factory.SubFactory('ietf.person.factories.EmailFactory')
|
||||
|
||||
class ReviewerSettingsFactory(factory.DjangoModelFactory):
|
||||
class Meta:
|
||||
model = ReviewerSettings
|
||||
|
|
|
@ -11,7 +11,7 @@ class Migration(migrations.Migration):
|
|||
|
||||
dependencies = [
|
||||
('doc', '0009_move_non_url_externalurls_to_uploaded_filename'),
|
||||
('name', '0006_adjust_statenames'),
|
||||
('name', '0005_reviewassignmentstatename'),
|
||||
('person', '0008_auto_20181014_1448'),
|
||||
('review', '0008_remove_reviewrequest_old_id'),
|
||||
]
|
||||
|
|
|
@ -701,7 +701,8 @@ def extract_revision_ordered_review_requests_for_documents_and_replaced(review_r
|
|||
replaces = extract_complete_replaces_ancestor_mapping_for_docs(names)
|
||||
|
||||
requests_for_each_doc = defaultdict(list)
|
||||
for r in review_request_queryset.filter(doc__in=set(e for l in replaces.itervalues() for e in l) | names).order_by("-reviewed_rev", "-time", "-id").iterator():
|
||||
# TODO : See if this function is still meeting the need. I removed "-reviewed_rev" from the order_by below. The whole thing may need to be operating on ReviewAssignments?
|
||||
for r in review_request_queryset.filter(doc__in=set(e for l in replaces.itervalues() for e in l) | names).order_by("-time", "-id").iterator():
|
||||
requests_for_each_doc[r.doc_id].append(r)
|
||||
|
||||
# now collect in breadth-first order to keep the revision order intact
|
||||
|
|
|
@ -446,7 +446,11 @@ table tbody.meta th:nth-child(2), table tbody.meta td:nth-child(2) {
|
|||
width: 9em;
|
||||
}
|
||||
|
||||
|
||||
table tbody.panel-meta th, table tbody.panel-meta td { border-top: 0; }
|
||||
table tbody.panel-meta th:first-child, table tbody.panel-meta td:first-child {
|
||||
text-align: right;
|
||||
width: 9em;
|
||||
}
|
||||
|
||||
td.area-director div { border-bottom: solid #ccc 1px; }
|
||||
|
||||
|
|
|
@ -11,14 +11,14 @@
|
|||
{% block content %}
|
||||
{% origin %}
|
||||
<h1>{% if revising_review %}Revise{% else %}Complete{% endif %} review<br>
|
||||
<small>{{ review_req.doc.name }}</small>
|
||||
<small>{{ assignment.review_request.doc.name }}</small>
|
||||
</h1>
|
||||
|
||||
<p>
|
||||
<div><strong>Review type:</strong> {{ review_req.team.acronym }} - {{ review_req.type }} review </div>
|
||||
<div><strong>Requested version for review:</strong> {{ review_req.requested_rev|default:"Current" }} </div>
|
||||
<div><strong>Requsted:</strong> {{ review_req.time|date:"Y-m-d" }} </div>
|
||||
<div><strong>Reviewer:</strong> {{ review_req.reviewer.person.name }}</div>
|
||||
<div><strong>Review type:</strong> {{ assignment.review_request.team.acronym }} - {{ assignment.review_request.type }} review </div>
|
||||
<div><strong>Requested version for review:</strong> {{ assignment.review_request.requested_rev|default:"Current" }} </div>
|
||||
<div><strong>Requested:</strong> {{ assignment.review_request.time|date:"Y-m-d" }} </div>
|
||||
<div><strong>Reviewer:</strong> {{ assignment.reviewer.person.name }}</div>
|
||||
</p>
|
||||
|
||||
{% if not revising_review %}
|
||||
|
@ -37,7 +37,7 @@
|
|||
{% bootstrap_form form layout="horizontal" %}
|
||||
|
||||
{% buttons %}
|
||||
<a class="btn btn-default" href="{% url "ietf.doc.views_review.review_request" name=doc.canonical_name request_id=review_req.pk %}">Cancel</a>
|
||||
<a class="btn btn-default" href="{% url "ietf.doc.views_review.review_request" name=doc.canonical_name request_id=assignment.review_request.pk %}">Cancel</a>
|
||||
<button type="submit" class="btn btn-primary">{% if revising_review %}Revise{% else %}Complete{% endif %} review</button>
|
||||
{% endbuttons %}
|
||||
|
||||
|
@ -95,7 +95,7 @@
|
|||
{% block js %}
|
||||
<script src="{% static 'bootstrap-datepicker/js/bootstrap-datepicker.min.js' %}"></script>
|
||||
<script>
|
||||
var searchMailArchiveUrl = "{% url "ietf.doc.views_review.search_mail_archive" name=review_req.doc.name request_id=review_req.pk %}";
|
||||
var searchMailArchiveUrl = "{% url "ietf.doc.views_review.search_mail_archive" name=assignment.review_request.doc.name assignment_id=assignment.pk %}";
|
||||
</script>
|
||||
<script src="{% static 'ietf/js/complete-review.js' %}"></script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{# Copyright The IETF Trust 2017, All Rights Reserved #}{% load origin %}{% origin %}
|
||||
{# Copyright The IETF Trust 2017, All Rights Reserved #}{% load origin bootstrap3 %}{% origin %}
|
||||
<p>I got included</p>
|
||||
<table class="table table-condensed">
|
||||
<tbody class="meta">
|
||||
<tr>
|
||||
|
@ -68,11 +69,19 @@
|
|||
</tr>
|
||||
{% endif %}
|
||||
|
||||
{% if doc.time %}
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Other Reviews</th>
|
||||
<th>Draft last updated</th>
|
||||
<td>{{ doc.time|date:"Y-m-d" }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Reviews from other teams</th>
|
||||
<td>
|
||||
{% for req in review_req.other_completed_requests %}
|
||||
{% for req in review_req.other_completed_requests %} {# TODO: align this with new models #}
|
||||
{% if req.reviewer == review_req.reviewer %}<strong>{% endif %}
|
||||
<a href="{% url "ietf.doc.views_review.review_request" name=req.doc request_id=req.id %}">{{req.team.acronym|capfirst}} {{req.type.name}} review of -{{req.reviewed_rev}} by {{req.reviewer.person.plain_name}}</a> {% if req.reviewed_rev != req.doc.rev %} (<a href="{{ rfcdiff_base_url }}?url1={{ req.doc.name }}-{{ req.reviewed_rev }}&url2={{ req.doc.name }}-{{ req.doc.rev }}">diff</a>){% endif %}<br>
|
||||
{% if req.reviewer == review_req.reviewer %}</strong>{% endif %}
|
||||
|
@ -92,115 +101,99 @@
|
|||
</tr>
|
||||
{% endif %}
|
||||
</tbody>
|
||||
|
||||
<tbody class="meta">
|
||||
<tr>
|
||||
<th>Review</th>
|
||||
<th>State</th>
|
||||
<td>{{ review_req.state.name }}
|
||||
{% if snapshot %}
|
||||
<span class="label label-warning">Snapshot</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Reviewer</th>
|
||||
<td>
|
||||
{% if review_req.reviewer %}
|
||||
{{ review_req.reviewer.person }}
|
||||
{% else %}
|
||||
None assigned yet
|
||||
{% endif %}
|
||||
|
||||
{% if can_assign_reviewer %}
|
||||
<a class="btn btn-default btn-xs" href="{% url "ietf.doc.views_review.assign_reviewer" name=doc.name request_id=review_req.pk %}"><span class="fa fa-user"></span> {% if review_req.reviewer %}Reassign{% else %}Assign{% endif %} reviewer</a>
|
||||
{% endif %}
|
||||
|
||||
{% if review_req.reviewer %}
|
||||
{% if can_reject_reviewer_assignment or can_accept_reviewer_assignment %}
|
||||
<div class="reviewer-assignment-not-accepted">
|
||||
{% if review_req.state_id == "requested"%}
|
||||
<em>Assignment not accepted yet:</em>
|
||||
{% else %}
|
||||
<em>Assignment accepted:</em>
|
||||
{% endif %}
|
||||
|
||||
{% if can_reject_reviewer_assignment %}
|
||||
<a class="btn btn-danger btn-xs" href="{% url "ietf.doc.views_review.reject_reviewer_assignment" name=doc.name request_id=review_req.pk %}"><span class="fa fa-ban"></span> Reject</a>
|
||||
{% endif %}
|
||||
|
||||
{% if can_accept_reviewer_assignment %}
|
||||
<form style="display:inline" method="post" action="{% url "ietf.doc.views_review.review_request" name=doc.name request_id=review_req.pk %}">{% csrf_token %}<button class="btn btn-success btn-xs" type="submit" name="action" value="accept"><span class="fa fa-check"></span> Accept</button></form>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Review</th>
|
||||
<td>
|
||||
{% if review_req.review %}
|
||||
<a href="{{ review_req.review.get_absolute_url }}">{{ review_req.review.name }}</a>
|
||||
{% elif review_req.state_id == "requested" or review_req.state_id == "accepted" %}
|
||||
Not completed yet
|
||||
{% else %}
|
||||
Not available
|
||||
{% endif %}
|
||||
|
||||
{% if can_complete_review %}
|
||||
<a class="btn btn-primary btn-xs" href="{% url "ietf.doc.views_review.complete_review" name=doc.name request_id=review_req.pk %}"><span class="fa fa-pencil-square-o"></span> {% if review_req.state_id == "requested" or review_req.state_id == "accepted" %}Complete review{% else %}Correct review{% endif %}</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{% if review_req.review and review_req.review.external_url %}
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Posted at</th>
|
||||
<td>
|
||||
<a href="{{ review_req.review.external_url }}">{{ review_req.review.external_url }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
|
||||
{% if review_req.reviewed_rev %}
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Reviewed rev.</th>
|
||||
<td><a href="{% url "ietf.doc.views_doc.document_main" name=review_req.doc.name rev=review_req.reviewed_rev %}">{{ review_req.reviewed_rev }}</a> {% if review_req.reviewed_rev != review_req.doc.rev %}(document currently at {{ review_req.doc.rev }}){% endif %}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
|
||||
{% if review_req.result %}
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Review result</th>
|
||||
<td>{{ review_req.result.name }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
|
||||
{% if doc.time %}
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Draft last updated</th>
|
||||
<td>{{ doc.time|date:"Y-m-d" }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
|
||||
{% if review_req.state_id == "completed" or review_req.state_id == "part-completed" %}
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Review completed:</th>
|
||||
<td>
|
||||
{{ review_req.review_done_time|date:"Y-m-d" }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<p><strong>Assignments</strong></p>
|
||||
{% if can_assign_reviewer %}
|
||||
<p>
|
||||
<a class="btn btn-default btn-xs" href="{% url "ietf.doc.views_review.assign_reviewer" name=doc.name request_id=review_req.pk %}"><span class="fa fa-user"></span> Assign reviewer</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% for assignment in assignments %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
{{ assignment.reviewer.person }}
|
||||
{% if assignment.can_reject_reviewer_assignment or assignment.can_accept_reviewer_assignment %}
|
||||
<div class="reviewer-assignment-not-accepted">
|
||||
{% if assignment.state_id == "requested"%}
|
||||
<em>Assignment not accepted yet:</em>
|
||||
{% else %}
|
||||
<em>Assignment accepted:</em>
|
||||
{% endif %}
|
||||
{% if assignment.can_reject_reviewer_assignment %}
|
||||
<a class="btn btn-danger btn-xs" href="{% url "ietf.doc.views_review.reject_reviewer_assignment" name=doc.name assignment_id=assignment.pk %}"><span class="fa fa-ban"></span> Reject</a>
|
||||
{% endif %}
|
||||
{% if assignment.can_accept_reviewer_assignment %}
|
||||
<form style="display:inline" method="post" action="{% url "ietf.doc.views_review.review_request" name=doc.name request_id=review_req.pk %}">{% csrf_token %}<button class="btn btn-success btn-xs" type="submit" name="action" value="accept"><span class="fa fa-check"></span> Accept</button></form>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<table class="table table-condensed">
|
||||
<tbody class="panel-meta">
|
||||
<tr>
|
||||
<th>State</th>
|
||||
<td>{{ review_req.state.name }}
|
||||
{% if snapshot %}
|
||||
<span class="label label-warning">Snapshot</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>Review</th>
|
||||
<td>
|
||||
{% if assignment.review %}
|
||||
<a href="{{ assignment.review.get_absolute_url }}">{{ assignment.review.name }}</a>
|
||||
{% elif assignment.state_id == "requested" or assignment.state_id == "accepted" %}
|
||||
Not completed yet
|
||||
{% else %}
|
||||
Not available
|
||||
{% endif %}
|
||||
|
||||
{% if assignment.can_complete_review %}
|
||||
{# TODO: The url below needs to be to a new complete_assignment passed the assignment.pk #}
|
||||
<a class="btn btn-primary btn-xs" href="{% url "ietf.doc.views_review.complete_review" name=doc.name assignment_id=assignment.pk %}"><span class="fa fa-pencil-square-o"></span> {% if assignment.state_id == "requested" or assignment.state_id == "accepted" %}Complete review{% else %}Correct review{% endif %}</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{% if assignment.review and assignment.review.external_url %}
|
||||
<tr>
|
||||
<th>Posted at</th>
|
||||
<td>
|
||||
<a href="{{ assignment.review.external_url }}">{{ assignment.review.external_url }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
|
||||
{% if assignment.reviewed_rev %}
|
||||
<tr>
|
||||
<th>Reviewed rev.</th>
|
||||
<td><a href="{% url "ietf.doc.views_doc.document_main" name=review_req.doc.name rev=assignment.reviewed_rev %}">{{ assignment.reviewed_rev }}</a> {% if assignment.reviewed_rev != review_req.doc.rev %}(document currently at {{ review_req.doc.rev }}){% endif %}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
|
||||
{% if assignment.result %}
|
||||
<tr>
|
||||
<th>Review result</th>
|
||||
<td>{{ assignment.result.name }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if assignment.state_id == "completed" or assignment.state_id == "part-completed" %}
|
||||
<tr>
|
||||
<th>Review completed:</th>
|
||||
<td>
|
||||
{{ assignment.completed_on|date:"Y-m-d" }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
{% load ietf_filters %}{% autoescape off %}{% filter maybewordwrap:80 %}{% if review_req.state_id == "part-completed" %}
|
||||
Review is partially done. Another review request has been registered for
|
||||
completing it.
|
||||
{% load ietf_filters %}{% autoescape off %}{% filter maybewordwrap:80 %}{% if assignment.state_id == "part-completed" %}
|
||||
Review is partially done. Another assignment may be needed to complete it.
|
||||
|
||||
{% endif %}Reviewer: {{ review_req.reviewer.person }}
|
||||
Review result: {{ review_req.result.name }}
|
||||
{% endif %}Reviewer: {{ assignment.reviewer.person }}
|
||||
Review result: {{ assignment.result.name }}
|
||||
|
||||
{{ content }}
|
||||
{% endfilter %}{% endautoescape %}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
{% load ietf_filters %}{% autoescape off %}From: {{settings.DEFAULT_FROM_EMAIL}}
|
||||
To: {{to}}{% if cc %}
|
||||
Cc: {{cc}}{% endif %}
|
||||
Subject: "{{review_req.result}}" review submitted for {{review_req.doc}}{% if review_req.reviewed_rev %}-{{review_req.reviewed_rev}}{% endif %}
|
||||
Subject: "{{assignment.result}}" review submitted for {{assignment.review_request.doc}}{% if assignment.reviewed_rev %}-{{assignment.reviewed_rev}}{% endif %}
|
||||
|
||||
{{review_req.reviewer.person.name}} has submitted a "{{review_req.result}}" review result for {{review_req.doc}}{% if review_req.reviewed_rev %}-{{review_req.reviewed_rev}}{% endif %}.
|
||||
{{assignment.reviewer.person}} has submitted a "{{assignment.result}}" review result for {{assignment.review_request.doc}}{% if assignment.reviewed_rev %}-{{assignment.reviewed_rev}}{% endif %}.
|
||||
|
||||
The review is available at {{settings.IDTRACKER_BASE_URL}}{% url 'ietf.doc.views_doc.document_main' name=review_req.review.name %}
|
||||
The review is available at {{settings.IDTRACKER_BASE_URL}}{% url 'ietf.doc.views_doc.document_main' name=assignment.review.name %}
|
||||
|
||||
The document is available at {{settings.IDTRACKER_BASE_URL}}{% url 'ietf.doc.views_doc.document_main' name=review_req.doc.name %}
|
||||
The document is available at {{settings.IDTRACKER_BASE_URL}}{% url 'ietf.doc.views_doc.document_main' name=assignment.review_request.doc.name %}
|
||||
|
||||
This message was sent because {% if explicit_request %}the reviewer indicated it should be on the review completion form{% else %}the review team settings indicated it should be{% endif %}.
|
||||
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
{% autoescape off %}Review was partially completed by {{ by }}.
|
||||
|
||||
{% if new_review_req_url %}
|
||||
A new review request has been added for completing the review:
|
||||
|
||||
{{ new_review_req_url }}
|
||||
{% else %}
|
||||
Found {{ existing_open_reqs|length }} open review request{{ existing_open_reqs|pluralize }} on the document so a new
|
||||
review request has not been added.
|
||||
A new reviewer may need to be assigned to get a complete review.
|
||||
{% if existing_assignments %}
|
||||
The following are already assigned to review this document:{% for assignment in existing_assignments %}
|
||||
{{ assignment.reviewer.name }} : {{ assignment.state }}{% endfor %}
|
||||
{% endif %}{% endautoescape %}
|
||||
|
|
Loading…
Reference in a new issue