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
This commit is contained in:
Ole Laursen 2016-11-07 22:32:53 +00:00
parent c3e8cabafb
commit cde7cfacd5
3 changed files with 44 additions and 13 deletions

View file

@ -299,6 +299,7 @@ class ReviewTests(TestCase):
self.assertIn("unavailable indefinitely", reviewer_label)
self.assertIn("skip next 1", reviewer_label)
self.assertIn("#1", reviewer_label)
self.assertIn("no response 0/1", reviewer_label)
# assign
empty_outbox()

View file

@ -1,4 +1,4 @@
import datetime, math, itertools
import datetime, math
from collections import defaultdict
from django.shortcuts import render, redirect, get_object_or_404
@ -21,7 +21,7 @@ from ietf.review.utils import (can_manage_review_requests_for_team,
current_unavailable_periods_for_reviewers,
email_reviewer_availability_change,
reviewer_rotation_list,
extract_review_request_data)
latest_review_requests_for_reviewers)
from ietf.group.models import Role
from ietf.group.utils import get_group_or_404, construct_group_menu_context
from ietf.person.fields import PersonEmailChoiceField
@ -130,12 +130,7 @@ def reviewer_overview(request, acronym, group_type=None):
today = datetime.date.today()
extracted_data = extract_review_request_data(teams=[group], time_from=today - datetime.timedelta(days=365), ordering=["reviewer"])
req_data_for_reviewer = {}
for reviewer, req_data_items in itertools.groupby(extracted_data, key=lambda data: data.reviewer):
l = list(req_data_items)
l.reverse()
req_data_for_reviewer[reviewer] = l
req_data_for_reviewers = latest_review_requests_for_reviewers(group)
review_state_by_slug = { n.slug: n for n in ReviewRequestStateName.objects.all() }
for person in reviewers:
@ -152,13 +147,12 @@ def reviewer_overview(request, acronym, group_type=None):
and (p.start_date is None or p.start_date <= today) and (p.end_date is None or today <= p.end_date)
for p in person.unavailable_periods)
MAX_REQS = 5
req_data = req_data_for_reviewer.get(person.pk, [])
open_reqs = sum(1 for d in req_data if d.state in ("requested", "accepted"))
MAX_CLOSED_REQS = 10
req_data = req_data_for_reviewers.get(person.pk, [])
open_reqs = sum(1 for d in req_data if d.state in ["requested", "accepted"])
latest_reqs = []
for d in req_data:
# any open requests pushes the others out
if ((d.state in ("requested", "accepted") and len(latest_reqs) < MAX_REQS) or (len(latest_reqs) + open_reqs < MAX_REQS)):
if d.state in ["requested", "accepted"] or len(latest_reqs) < MAX_CLOSED_REQS + open_reqs:
latest_reqs.append((d.req_pk, d.doc, d.reviewed_rev, d.deadline,
review_state_by_slug.get(d.state),
int(math.ceil(d.assignment_to_closure_days)) if d.assignment_to_closure_days is not None else None))

View file

@ -294,6 +294,23 @@ def sum_raw_review_request_aggregations(raw_aggregations):
return state_dict, late_state_dict, result_dict, assignment_to_closure_days_list, assignment_to_closure_days_count
def latest_review_requests_for_reviewers(team, days_back=365):
"""Collect and return stats for reviewers on latest requests, in
extract_review_request_data format."""
extracted_data = extract_review_request_data(
teams=[team],
time_from=datetime.date.today() - datetime.timedelta(days=days_back),
ordering=["reviewer"],
)
req_data_for_reviewers = {
reviewer: list(reversed(list(req_data_items)))
for reviewer, req_data_items in itertools.groupby(extracted_data, key=lambda data: data.reviewer)
}
return req_data_for_reviewers
def make_new_review_request_from_existing(review_req):
obj = ReviewRequest()
obj.time = review_req.time
@ -717,6 +734,9 @@ def make_assignment_choices(email_queryset, review_req):
# unavailable periods
unavailable_periods = current_unavailable_periods_for_reviewers(team)
# reviewers statistics
req_data_for_reviewers = latest_review_requests_for_reviewers(team)
ranking = []
for e in possible_emails:
settings = reviewer_settings.get(e.person_id)
@ -763,10 +783,26 @@ def make_assignment_choices(email_queryset, review_req):
if settings.skip_next > 0:
explanations.append("skip next {}".format(settings.skip_next))
# index
index = rotation_index.get(e.person_id, 0)
scores.append(-index)
explanations.append("#{}".format(index + 1))
# stats
stats = []
req_data = req_data_for_reviewers.get(e.person_id, [])
currently_open = sum(1 for d in req_data if d.state in ["requested", "accepted"])
if currently_open > 0:
stats.append("currently {} open".format(currently_open))
could_have_completed = [d for d in req_data if d.state in ["part-completed", "completed", "no-response"]]
if could_have_completed:
no_response = sum(1 for d in could_have_completed if d.state == "no-response")
stats.append("no response {}/{}".format(no_response, len(could_have_completed)))
if stats:
explanations.append(", ".join(stats))
label = unicode(e.person)
if explanations:
label = u"{}: {}".format(label, u"; ".join(explanations))