Skip to content

Commit 507baad

Browse files
committed
Add refresh button to manage reviews page, make save detect changes in
the requests and pop the page back up for confirmation if so - Legacy-Id: 11827
1 parent 8b65c3a commit 507baad

4 files changed

Lines changed: 122 additions & 17 deletions

File tree

ietf/group/tests_review.py

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,21 +107,52 @@ def test_manage_review_requests(self):
107107
self.assertEqual(r.status_code, 200)
108108
self.assertTrue(review_req1.doc.name in unicontent(r))
109109

110+
# can't save: conflict
111+
new_reviewer = Email.objects.get(role__name="reviewer", role__group=group, person__user__username="marschairman")
112+
# provoke conflict by posting bogus data
113+
r = self.client.post(url, {
114+
"reviewrequest": [str(review_req1.pk), str(review_req2.pk), str(123456)],
115+
116+
# close
117+
"r{}-existing_reviewer".format(review_req1.pk): "123456",
118+
"r{}-action".format(review_req1.pk): "close",
119+
"r{}-close".format(review_req1.pk): "no-response",
120+
121+
# assign
122+
"r{}-existing_reviewer".format(review_req2.pk): "123456",
123+
"r{}-action".format(review_req2.pk): "assign",
124+
"r{}-reviewer".format(review_req2.pk): new_reviewer.pk,
125+
126+
"action": "save",
127+
})
128+
self.assertEqual(r.status_code, 200)
129+
content = unicontent(r).lower()
130+
self.assertTrue("1 request closed" in content)
131+
self.assertTrue("1 request opened" in content)
132+
self.assertTrue("2 requests changed assignment" in content)
133+
110134
# close and assign
111135
new_reviewer = Email.objects.get(role__name="reviewer", role__group=group, person__user__username="marschairman")
112136
r = self.client.post(url, {
137+
"reviewrequest": [str(review_req1.pk), str(review_req2.pk), str(review_req3.pk)],
138+
113139
# close
140+
"r{}-existing_reviewer".format(review_req1.pk): review_req1.reviewer_id or "",
114141
"r{}-action".format(review_req1.pk): "close",
115142
"r{}-close".format(review_req1.pk): "no-response",
116143

117144
# assign
145+
"r{}-existing_reviewer".format(review_req2.pk): review_req2.reviewer_id or "",
118146
"r{}-action".format(review_req2.pk): "assign",
119147
"r{}-reviewer".format(review_req2.pk): new_reviewer.pk,
120148

121149
# no change
150+
"r{}-existing_reviewer".format(review_req3.pk): review_req3.reviewer_id or "",
122151
"r{}-action".format(review_req3.pk): "",
123152
"r{}-close".format(review_req3.pk): "no-response",
124153
"r{}-reviewer".format(review_req3.pk): "",
154+
155+
"action": "save",
125156
})
126157
self.assertEqual(r.status_code, 302)
127158

@@ -130,7 +161,3 @@ def test_manage_review_requests(self):
130161
self.assertEqual(review_req2.state_id, "requested")
131162
self.assertEqual(review_req2.reviewer, new_reviewer)
132163
self.assertEqual(review_req3.state_id, "requested")
133-
134-
# FIXME: test suggested
135-
136-

ietf/group/views_review.py

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,7 @@ class ManageReviewRequestForm(forms.Form):
2222
]
2323

2424
action = forms.ChoiceField(choices=ACTIONS, widget=forms.HiddenInput, required=False)
25-
2625
close = forms.ModelChoiceField(queryset=close_review_request_states(), required=False)
27-
2826
reviewer = PersonEmailChoiceField(empty_label="(None)", required=False, label_with="person")
2927

3028
def __init__(self, review_req, *args, **kwargs):
@@ -83,6 +81,8 @@ def manage_review_requests(request, acronym, group_type=None):
8381
set(r.doc_id for r in review_requests),
8482
)
8583

84+
# we need a mutable query dict
85+
query_dict = request.POST.copy() if request.method == "POST" else None
8686
for req in review_requests:
8787
l = []
8888
# take all on the latest reviewed rev
@@ -98,31 +98,68 @@ def manage_review_requests(request, acronym, group_type=None):
9898

9999
req.latest_reqs = l
100100

101-
req.form = ManageReviewRequestForm(req, request.POST if request.method == "POST" else None)
101+
req.form = ManageReviewRequestForm(req, query_dict)
102+
103+
saving = False
104+
newly_closed = newly_opened = newly_assigned = 0
102105

103106
if request.method == "POST":
107+
saving = request.POST.get("action") == "save"
108+
109+
# check for conflicts
110+
review_requests_dict = { unicode(r.pk): r for r in review_requests }
111+
posted_reqs = set(request.POST.getlist("reviewrequest", []))
112+
current_reqs = set(review_requests_dict.iterkeys())
113+
114+
closed_reqs = posted_reqs - current_reqs
115+
newly_closed += len(closed_reqs)
116+
117+
opened_reqs = current_reqs - posted_reqs
118+
newly_opened += len(opened_reqs)
119+
for r in opened_reqs:
120+
review_requests_dict[r].form.add_error(None, "New request.")
121+
122+
for req in review_requests:
123+
existing_reviewer = request.POST.get(req.form.prefix + "-existing_reviewer")
124+
if existing_reviewer is None:
125+
continue
126+
127+
if existing_reviewer != unicode(req.reviewer_id or ""):
128+
msg = "Assignment was changed."
129+
a = req.form["action"].value()
130+
if a == "assign":
131+
msg += " Didn't assign reviewer."
132+
elif a == "close":
133+
msg += " Didn't close request."
134+
req.form.add_error(None, msg)
135+
req.form.data[req.form.prefix + "-action"] = "" # cancel the action
136+
137+
newly_assigned += 1
138+
104139
form_results = []
105140
for req in review_requests:
106141
form_results.append(req.form.is_valid())
107142

108-
if all(form_results):
143+
if saving and all(form_results) and not (newly_closed > 0 or newly_opened > 0 or newly_assigned > 0):
109144
for review_req in review_requests:
110145
action = review_req.form.cleaned_data.get("action")
111146
if action == "assign":
112147
assign_review_request_to_reviewer(request, review_req, review_req.form.cleaned_data["reviewer"])
113148
elif action == "close":
114149
close_review_request(request, review_req, review_req.form.cleaned_data["close"])
115150

116-
117151
kwargs = { "acronym": group.acronym }
118152
if group_type:
119153
kwargs["group_type"] = group_type
120154
import ietf.group.views
121155
return redirect(ietf.group.views.review_requests, **kwargs)
122156

123-
124157
return render(request, 'group/manage_review_requests.html', {
125158
'group': group,
126159
'review_requests': review_requests,
160+
'newly_closed': newly_closed,
161+
'newly_opened': newly_opened,
162+
'newly_assigned': newly_assigned,
163+
'saving': saving,
127164
})
128165

ietf/static/ietf/js/manage-review-requests.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,15 @@ $(document).ready(function () {
3232
});
3333

3434
form.find("[name$=\"-action\"]").each(function () {
35-
console.log(this);
35+
var v = $(this).val();
36+
if (!v)
37+
return;
38+
39+
var row = $(this).closest("tr");
40+
41+
if (v == "assign")
42+
row.find(".reviewer-action").click();
43+
else if (v == "close")
44+
row.find(".close-action").click();
3645
});
3746
});

ietf/templates/group/manage_review_requests.html

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
{% load ietf_filters staticfiles bootstrap3 %}
66

7-
{% block title %}Manage pending review requests for {{ group.acronym }}{% endblock %}
7+
{% block title %}Manage open review requests for {{ group.acronym }}{% endblock %}
88

99
{% block pagehead %}
1010
<link rel="stylesheet" href="{% static "jquery.tablesorter/css/theme.bootstrap.min.css" %}">
@@ -15,7 +15,23 @@
1515

1616
<h1>Manage open review requests for {{ group.acronym }}</h1>
1717

18-
<p>For reference: <a href="{% url "ietf.group.views.review_requests" group_type=group.type_id acronym=group.acronym %}#closed-review-requests">closed review requests</a>
18+
<p>Other options:
19+
<a href="{% url "ietf.group.views.review_requests" group_type=group.type_id acronym=group.acronym %}#closed-review-requests">Closed review requests</a>
20+
- <a href="FIXME">Email open assignments summary</a>
21+
</p>
22+
23+
{% if newly_closed > 0 or newly_opened > 0 or newly_assigned > 0 %}
24+
<p class="alert alert-danger">
25+
Changes since last refresh:
26+
{% if newly_closed %}{{ newly_closed }} request{{ newly_closed|pluralize }} closed.{% endif %}
27+
{% if newly_opened %}{{ newly_opened }} request{{ newly_opened|pluralize }} opened.{% endif %}
28+
{% if newly_assigned %}{{ newly_assigned }} request{{ newly_assigned|pluralize }} changed assignment.{% endif %}
29+
30+
{% if saving %}
31+
Check that you are happy with the results, then re-save.
32+
{% endif %}
33+
</p>
34+
{% endif %}
1935

2036
{% if review_requests %}
2137
<form class="review-requests" method="post">{% csrf_token %}
@@ -33,7 +49,8 @@ <h1>Manage open review requests for {{ group.acronym }}</h1>
3349
<tbody>
3450
{% for r in review_requests %}
3551
<tr>
36-
<td><a href="{% if r.requested_rev %}{% url "doc_view" name=r.doc.name rev=r.requested_rev %}{% else %}{% url "doc_view" name=r.doc.name %}{% endif %}">{{ r.doc.name }}{% if r.requested_rev %}-{{ r.requested_rev }}{% endif %}</a>
52+
<td>
53+
<a href="{% if r.requested_rev %}{% url "doc_view" name=r.doc.name rev=r.requested_rev %}{% else %}{% url "doc_view" name=r.doc.name %}{% endif %}">{{ r.doc.name }}{% if r.requested_rev %}-{{ r.requested_rev }}{% endif %}</a>
3754
{% if r.latest_reqs %}
3855
<br>
3956
<small>- prev. review:
@@ -43,6 +60,14 @@ <h1>Manage open review requests for {{ group.acronym }}</h1>
4360
{% endfor %}
4461
</small>
4562
{% endif %}
63+
64+
{% if r.form.non_field_errors %}
65+
<div class="alert alert-danger">
66+
{% for e in r.form.non_field_errors %}
67+
{{ e }}
68+
{% endfor %}
69+
</div>
70+
{% endif %}
4671
</td>
4772
<td>{{ r.type.name }}</td>
4873
<td>{% if r.time %}{{ r.time|date:"Y-m-d" }}{% else %}<em>auto-suggested</em>{% endif %}</td>
@@ -51,6 +76,9 @@ <h1>Manage open review requests for {{ group.acronym }}</h1>
5176
{% if r.due %}<span class="label label-warning">{{ r.due }} day{{ r.due|pluralize }}</span>{% endif %}
5277
</td>
5378
<td>
79+
<input type="hidden" name="reviewrequest" value="{{ r.pk }}">
80+
<input type="hidden" name="{{ r.form.prefix }}-existing_reviewer" value="{{ r.reviewer_id }}">
81+
5482
{% if r.reviewer %}
5583
<button type="button" class="btn btn-default btn-sm reviewer-action" title="Click to reassign request">{{ r.reviewer.person }} {% if r.state_id == "accepted" %}<span class="label label-default">accp</span>{% endif %}</button>
5684
{% else %}
@@ -64,8 +92,11 @@ <h1>Manage open review requests for {{ group.acronym }}</h1>
6492
{{ r.form.reviewer }}
6593
<button type="button" class="btn btn-default btn-sm undo" title="Undo assignment"><span class="fa fa-times"></span></button>
6694
{% if r.form.reviewer.errors %}
67-
<br>
68-
{{ r.form.reviewer.errors }}
95+
<div class="alert alert-danger">
96+
{% for e in r.form.reviewer.errors %}
97+
{{ e }}
98+
{% endfor %}
99+
</div>
69100
{% endif %}
70101
{% endspaceless %}
71102
</span>
@@ -91,7 +122,8 @@ <h1>Manage open review requests for {{ group.acronym }}</h1>
91122

92123
{% buttons %}
93124
<a href="{% url "ietf.group.views.review_requests" group_type=group.type_id acronym=group.acronym %}" class="btn btn-default pull-right">Cancel</a>
94-
<button class="btn btn-primary" type="submit">Save changes</button>
125+
<button class="btn btn-primary" type="submit" name="action" value="save">Save changes</button>
126+
<button class="btn btn-default" type="submit" name="action" value="refresh">Refresh (keeping changes)</button>
95127
{% endbuttons %}
96128
</form>
97129
{% else %}

0 commit comments

Comments
 (0)