Skip to content

Commit cde7cfa

Browse files
committed
Modify the reviewer overview page to display up to 10 historic reviews
per person from the past year instead of only 5. Add basic reviewer stats to the assignment select box. - Legacy-Id: 12279
1 parent c3e8cab commit cde7cfa

3 files changed

Lines changed: 44 additions & 13 deletions

File tree

ietf/doc/tests_review.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,7 @@ def test_assign_reviewer(self):
299299
self.assertIn("unavailable indefinitely", reviewer_label)
300300
self.assertIn("skip next 1", reviewer_label)
301301
self.assertIn("#1", reviewer_label)
302+
self.assertIn("no response 0/1", reviewer_label)
302303

303304
# assign
304305
empty_outbox()

ietf/group/views_review.py

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import datetime, math, itertools
1+
import datetime, math
22
from collections import defaultdict
33

44
from django.shortcuts import render, redirect, get_object_or_404
@@ -21,7 +21,7 @@
2121
current_unavailable_periods_for_reviewers,
2222
email_reviewer_availability_change,
2323
reviewer_rotation_list,
24-
extract_review_request_data)
24+
latest_review_requests_for_reviewers)
2525
from ietf.group.models import Role
2626
from ietf.group.utils import get_group_or_404, construct_group_menu_context
2727
from ietf.person.fields import PersonEmailChoiceField
@@ -130,12 +130,7 @@ def reviewer_overview(request, acronym, group_type=None):
130130

131131
today = datetime.date.today()
132132

133-
extracted_data = extract_review_request_data(teams=[group], time_from=today - datetime.timedelta(days=365), ordering=["reviewer"])
134-
req_data_for_reviewer = {}
135-
for reviewer, req_data_items in itertools.groupby(extracted_data, key=lambda data: data.reviewer):
136-
l = list(req_data_items)
137-
l.reverse()
138-
req_data_for_reviewer[reviewer] = l
133+
req_data_for_reviewers = latest_review_requests_for_reviewers(group)
139134
review_state_by_slug = { n.slug: n for n in ReviewRequestStateName.objects.all() }
140135

141136
for person in reviewers:
@@ -152,13 +147,12 @@ def reviewer_overview(request, acronym, group_type=None):
152147
and (p.start_date is None or p.start_date <= today) and (p.end_date is None or today <= p.end_date)
153148
for p in person.unavailable_periods)
154149

155-
MAX_REQS = 5
156-
req_data = req_data_for_reviewer.get(person.pk, [])
157-
open_reqs = sum(1 for d in req_data if d.state in ("requested", "accepted"))
150+
MAX_CLOSED_REQS = 10
151+
req_data = req_data_for_reviewers.get(person.pk, [])
152+
open_reqs = sum(1 for d in req_data if d.state in ["requested", "accepted"])
158153
latest_reqs = []
159154
for d in req_data:
160-
# any open requests pushes the others out
161-
if ((d.state in ("requested", "accepted") and len(latest_reqs) < MAX_REQS) or (len(latest_reqs) + open_reqs < MAX_REQS)):
155+
if d.state in ["requested", "accepted"] or len(latest_reqs) < MAX_CLOSED_REQS + open_reqs:
162156
latest_reqs.append((d.req_pk, d.doc, d.reviewed_rev, d.deadline,
163157
review_state_by_slug.get(d.state),
164158
int(math.ceil(d.assignment_to_closure_days)) if d.assignment_to_closure_days is not None else None))

ietf/review/utils.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,23 @@ def sum_raw_review_request_aggregations(raw_aggregations):
294294

295295
return state_dict, late_state_dict, result_dict, assignment_to_closure_days_list, assignment_to_closure_days_count
296296

297+
def latest_review_requests_for_reviewers(team, days_back=365):
298+
"""Collect and return stats for reviewers on latest requests, in
299+
extract_review_request_data format."""
300+
301+
extracted_data = extract_review_request_data(
302+
teams=[team],
303+
time_from=datetime.date.today() - datetime.timedelta(days=days_back),
304+
ordering=["reviewer"],
305+
)
306+
307+
req_data_for_reviewers = {
308+
reviewer: list(reversed(list(req_data_items)))
309+
for reviewer, req_data_items in itertools.groupby(extracted_data, key=lambda data: data.reviewer)
310+
}
311+
312+
return req_data_for_reviewers
313+
297314
def make_new_review_request_from_existing(review_req):
298315
obj = ReviewRequest()
299316
obj.time = review_req.time
@@ -717,6 +734,9 @@ def make_assignment_choices(email_queryset, review_req):
717734
# unavailable periods
718735
unavailable_periods = current_unavailable_periods_for_reviewers(team)
719736

737+
# reviewers statistics
738+
req_data_for_reviewers = latest_review_requests_for_reviewers(team)
739+
720740
ranking = []
721741
for e in possible_emails:
722742
settings = reviewer_settings.get(e.person_id)
@@ -763,10 +783,26 @@ def format_period(p):
763783
if settings.skip_next > 0:
764784
explanations.append("skip next {}".format(settings.skip_next))
765785

786+
# index
766787
index = rotation_index.get(e.person_id, 0)
767788
scores.append(-index)
768789
explanations.append("#{}".format(index + 1))
769790

791+
# stats
792+
stats = []
793+
req_data = req_data_for_reviewers.get(e.person_id, [])
794+
795+
currently_open = sum(1 for d in req_data if d.state in ["requested", "accepted"])
796+
if currently_open > 0:
797+
stats.append("currently {} open".format(currently_open))
798+
could_have_completed = [d for d in req_data if d.state in ["part-completed", "completed", "no-response"]]
799+
if could_have_completed:
800+
no_response = sum(1 for d in could_have_completed if d.state == "no-response")
801+
stats.append("no response {}/{}".format(no_response, len(could_have_completed)))
802+
803+
if stats:
804+
explanations.append(", ".join(stats))
805+
770806
label = unicode(e.person)
771807
if explanations:
772808
label = u"{}: {}".format(label, u"; ".join(explanations))

0 commit comments

Comments
 (0)