Skip to content

Commit b84efe2

Browse files
committed
display previous year's response on RoR page, if exists
Pulls the code for much of this out into the base view so it can be shared between the first mark and right of reply views.
1 parent e074608 commit b84efe2

File tree

4 files changed

+218
-29
lines changed

4 files changed

+218
-29
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
{% extends 'crowdsourcer/base.html' %}
2+
3+
{% load django_bootstrap5 %}
4+
{% load neighbourhood_filters %}
5+
6+
{% block content %}
7+
<h1 class="mb-3 mb-md-4">
8+
{% if authority.website %}
9+
<a href="{{ authority.website }}">{{ authority_name }}</a>:
10+
{% else %}
11+
{{ authority_name }}:
12+
{% endif %}
13+
{{section_title}}
14+
</h1>
15+
16+
<div class="sticky-top py-3 bg-white border-bottom" style="margin-bottom: -1px;">
17+
<div class="dropdown">
18+
<button class="btn btn-outline-secondary dropdown-toggle" id="navbarDropdown" data-bs-toggle="dropdown" aria-expanded="false">
19+
Skip to question
20+
</button>
21+
<ul class="dropdown-menu" aria-labelledby="navbarDropdown">
22+
{% for q_form in form %}
23+
<li><a class="dropdown-item d-flex" style="max-width: 30em; white-space: normal;" href="#q{{q_form.question_obj.number_and_part}}">
24+
<span style="width: 2em; flex: 0 0 auto;">Q{{q_form.question_obj.number_and_part}}</span>
25+
<span class="text-muted fs-7 ms-3">{{ q_form.question_obj.description }}</span>
26+
</a></li>
27+
{% endfor %}
28+
</ul>
29+
</div>
30+
</div>
31+
32+
{% if message %}
33+
<h3 class="mb-4 mb-md-5 text-success">
34+
{{ message }}
35+
</h3>
36+
{% endif %}
37+
38+
<form method="POST">
39+
{% csrf_token %}
40+
{% if form.total_error_count > 0 %}
41+
<div class="mb-4">
42+
<div class="col-md-7 text-danger">
43+
<strong>Changes not saved</strong>. There were some errors which are highlighted in red below. Your progress <b>will not be saved</b> until you correct these.
44+
</div>
45+
</div>
46+
{% endif %}
47+
{{ form.management_form }}
48+
{% for q_form in form %}
49+
<fieldset class="py-4 py-md-5 border-top">
50+
<div class="row">
51+
<div class="col-md-7">
52+
<legend id="q{{q_form.question_obj.number_and_part}}" class="h4 mb-3 mb-sm-4">
53+
{{q_form.question_obj.number_and_part}}. {{ q_form.question_obj.description }}
54+
{% if q_form.question_obj.how_marked == "foi" %}(FOI){% endif %}
55+
</legend>
56+
</div>
57+
</div>
58+
<div class="row">
59+
<div class="col-md-4 offset-md-1 order-md-2 mb-3 mb-sm-4">
60+
<details class="text-muted">
61+
<summary class="fw-bold mb-2">Criteria</summary>
62+
{% autoescape off %}
63+
{{q_form.question_obj.criteria|linebreaks }}
64+
{% endautoescape %}
65+
</details>
66+
<details class="text-muted">
67+
<summary class="fw-bold mb-2">Clarifications</summary>
68+
{% autoescape off %}
69+
{{q_form.question_obj.clarifications|linebreaks }}
70+
{% endautoescape %}
71+
</details>
72+
</div>
73+
</div>
74+
<div class="row">
75+
<div class="col-lg-6 mt-6">
76+
</div>
77+
<div class="col-lg-6 mt-6">
78+
<h2 class="form-label fs-6">Marker’s answer</h2>
79+
<div class="read-only-answer mb-3 mb-md-4">
80+
{% if q_form.orig.multi_option.values %}
81+
<p>
82+
{% for option in q_form.orig.multi_option.values %}
83+
{{ option.description }},
84+
{% empty %}
85+
(none)
86+
{% endfor %}
87+
</p>
88+
{% else %}
89+
{{ q_form.orig.option|default:"(none)"|linebreaks }}
90+
{% endif %}
91+
</div>
92+
93+
{% if q_form.question_obj.how_marked == 'foi' %}
94+
<h2 class="form-label fs-6">FOI request</h2>
95+
<div class="read-only-answer mb-3 mb-md-4">
96+
{{ q_form.orig.evidence|urlize }}
97+
</div>
98+
{% else %}
99+
<h2 class="form-label fs-6">Marker’s evidence of criteria met</h2>
100+
<div class="read-only-answer mb-3 mb-md-4">
101+
{{ q_form.orig.evidence|default:"(none)"|linebreaks }}
102+
</div>
103+
{% endif %}
104+
105+
{% if q_form.question_obj.how_marked != 'foi' %}
106+
<h2 class="form-label fs-6">Links to evidence</h2>
107+
<div class="read-only-answer mb-3 mb-md-4">
108+
{{ q_form.orig.public_notes|default:"(none)"|urlize|linebreaks }}
109+
</div>
110+
111+
<h2 class="form-label fs-6">Page number</h2>
112+
<div class="read-only-answer mb-3 mb-md-4">
113+
{{ q_form.orig.page_number|default:"(none)" }}<br>
114+
</div>
115+
{% endif %}
116+
117+
<h2 class="form-label fs-6">Marker’s additional notes</h2>
118+
<div class="read-only-answer mb-3 mb-md-4">
119+
{{ q_form.orig.private_notes|default:"(none)"|linebreaks }}
120+
</div>
121+
</div>
122+
</div>
123+
<div class="row">
124+
<div class="col-lg-6 mt-6">
125+
<h4 class="form-label fs-6">Your Scorecards 2023 response</h4>
126+
<div class="read-only-answer mb-3 mb-md-4">
127+
{% if q_form.previous_response.multi_option.values %}
128+
<p>
129+
{% for option in q_form.previous_response.multi_option.values %}
130+
{{ option.description }},
131+
{% empty %}
132+
(none)
133+
{% endfor %}
134+
</p>
135+
{% else %}
136+
{{ q_form.previous_response.option|default:"(none)"|linebreaks }}
137+
{% endif %}
138+
</div>
139+
140+
<h4 class="form-label fs-6">Links to evidence</h4>
141+
<div class="read-only-answer mb-0 mb-md-0">
142+
{% for link in q_form.previous_response.evidence_links %}
143+
<p>
144+
{{ link|check_if_broken }}
145+
</p>
146+
{% endfor %}
147+
</div>
148+
149+
<h4 class="form-label fs-6">Additional notes</h4>
150+
<div class="read-only-answer mb-3 mb-md-4">
151+
{{ q_form.previous_response.private_notes|default:"(none)"|linebreaks }}
152+
</div>
153+
</div>
154+
<div class="col-lg-6 mt-6">
155+
{% bootstrap_field q_form.agree_with_response %}
156+
157+
{% bootstrap_field q_form.evidence %}
158+
159+
{% bootstrap_field q_form.private_notes %}
160+
161+
{{ q_form.authority }}
162+
{{ q_form.question }}
163+
{{ q_form.id }}
164+
</div>
165+
</div>
166+
</fieldset>
167+
{% endfor %}
168+
169+
<div class="sticky-bottom py-3 bg-white border-top" style="margin-top: -1px;">
170+
<input type="submit" class="btn btn-primary" value="Save answers">
171+
</div>
172+
</form>
173+
174+
{% endblock %}

crowdsourcer/views/base.py

+32
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,38 @@ def check_permissions(self):
5757
):
5858
raise PermissionDenied
5959

60+
def has_previous(self):
61+
has_previous = Question.objects.filter(
62+
section__marking_session=self.request.current_session,
63+
section__title=self.kwargs["section_title"],
64+
questiongroup=self.authority.questiongroup,
65+
how_marked__in=self.how_marked_in,
66+
previous_question__isnull=False,
67+
).exists()
68+
69+
self.has_previous_questions = has_previous
70+
return has_previous
71+
72+
def add_previous(self, initial, rt):
73+
question_list = self.questions.values_list("previous_question_id", flat=True)
74+
prev_responses = Response.objects.filter(
75+
authority=self.authority,
76+
question__in=question_list,
77+
response_type=rt,
78+
).select_related("question")
79+
80+
response_map = {}
81+
for r in prev_responses:
82+
response_map[r.question.id] = r
83+
84+
for q in self.questions:
85+
data = initial[q.id]
86+
data["previous_response"] = response_map.get(q.previous_question_id)
87+
88+
initial[q.id] = data
89+
90+
return initial
91+
6092
def get_initial_obj(self):
6193
self.authority = PublicAuthority.objects.get(name=self.kwargs["name"])
6294
self.questions = Question.objects.filter(

crowdsourcer/views/marking.py

+2-29
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
MarkingSession,
1010
PublicAuthority,
1111
Question,
12-
Response,
1312
ResponseType,
1413
)
1514
from crowdsourcer.views.base import (
@@ -244,35 +243,9 @@ def get_initial_obj(self):
244243

245244
initial = super().get_initial_obj()
246245

247-
is_previous = Question.objects.filter(
248-
section__marking_session=self.request.current_session,
249-
section__title=self.kwargs["section_title"],
250-
questiongroup=self.authority.questiongroup,
251-
how_marked__in=self.how_marked_in,
252-
previous_question__isnull=False,
253-
).exists()
254-
255-
if is_previous:
256-
self.has_previous_questions = True
246+
if self.has_previous():
257247
audit_rt = ResponseType.objects.get(type="Audit")
258-
question_list = self.questions.values_list(
259-
"previous_question_id", flat=True
260-
)
261-
prev_responses = Response.objects.filter(
262-
authority=self.authority,
263-
question__in=question_list,
264-
response_type=audit_rt,
265-
).select_related("question")
266-
267-
response_map = {}
268-
for r in prev_responses:
269-
response_map[r.question.id] = r
270-
271-
for q in self.questions:
272-
data = initial[q.id]
273-
data["previous_response"] = response_map.get(q.previous_question_id)
274-
275-
initial[q.id] = data
248+
initial = self.add_previous(initial, audit_rt)
276249

277250
return initial
278251

crowdsourcer/views/rightofreply.py

+10
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,12 @@ class AuthorityRORSectionQuestions(BaseQuestionView):
139139
title_start = "Right of Reply - "
140140
how_marked_in = ["volunteer", "national_volunteer", "foi"]
141141

142+
def get_template_names(self):
143+
if self.has_previous_questions:
144+
return ["crowdsourcer/authority_ror_questions_with_previous.html"]
145+
else:
146+
return [self.template_name]
147+
142148
def get_initial_obj(self):
143149
initial = super().get_initial_obj()
144150

@@ -153,6 +159,10 @@ def get_initial_obj(self):
153159

154160
initial[r.question.id] = data
155161

162+
if self.has_previous():
163+
ror_rt = ResponseType.objects.get(type="Right of Reply")
164+
initial = self.add_previous(initial, ror_rt)
165+
156166
return initial
157167

158168
def check_permissions(self):

0 commit comments

Comments
 (0)