feat: Download questionnaire responses (#6111)
* feat: Download questionnaire responses (#4981) * style: Expand "questio" to "questionnaire"
This commit is contained in:
parent
e1c1daa13b
commit
73c2a6aa8b
|
@ -2870,7 +2870,6 @@ class ReclassifyFeedbackTests(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
setup_test_public_keys_dir(self)
|
setup_test_public_keys_dir(self)
|
||||||
nomcom_test_data()
|
|
||||||
self.nc = NomComFactory.create(**nomcom_kwargs_for_year())
|
self.nc = NomComFactory.create(**nomcom_kwargs_for_year())
|
||||||
self.chair = self.nc.group.role_set.filter(name='chair').first().person
|
self.chair = self.nc.group.role_set.filter(name='chair').first().person
|
||||||
self.member = self.nc.group.role_set.filter(name='member').first().person
|
self.member = self.nc.group.role_set.filter(name='member').first().person
|
||||||
|
@ -2882,6 +2881,28 @@ class ReclassifyFeedbackTests(TestCase):
|
||||||
teardown_test_public_keys_dir(self)
|
teardown_test_public_keys_dir(self)
|
||||||
super().tearDown()
|
super().tearDown()
|
||||||
|
|
||||||
|
def test_download_feedback_nominee(self):
|
||||||
|
# not really a reclassification test, but in closely adjacent code
|
||||||
|
fb = FeedbackFactory.create(nomcom=self.nc,type_id='questio')
|
||||||
|
fb.positions.add(self.position)
|
||||||
|
fb.nominees.add(self.nominee)
|
||||||
|
fb.save()
|
||||||
|
self.assertEqual(Feedback.objects.questionnaires().count(), 1)
|
||||||
|
|
||||||
|
url = reverse('ietf.nomcom.views.view_feedback_nominee', kwargs={'year':self.nc.year(), 'nominee_id':self.nominee.id})
|
||||||
|
login_testing_unauthorized(self,self.member.user.username,url)
|
||||||
|
provide_private_key_to_test_client(self)
|
||||||
|
response = self.client.post(url, {'feedback_id': fb.id, 'submit': 'download'})
|
||||||
|
self.assertEqual(response.status_code, 403)
|
||||||
|
|
||||||
|
self.client.logout()
|
||||||
|
self.client.login(username=self.chair.user.username, password=self.chair.user.username + "+password")
|
||||||
|
provide_private_key_to_test_client(self)
|
||||||
|
|
||||||
|
response = self.client.post(url, {'feedback_id': fb.id, 'submit': 'download'})
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertIn('questionnaire-', response['Content-Disposition'])
|
||||||
|
|
||||||
def test_reclassify_feedback_nominee(self):
|
def test_reclassify_feedback_nominee(self):
|
||||||
fb = FeedbackFactory.create(nomcom=self.nc,type_id='comment')
|
fb = FeedbackFactory.create(nomcom=self.nc,type_id='comment')
|
||||||
fb.positions.add(self.position)
|
fb.positions.add(self.position)
|
||||||
|
@ -2892,14 +2913,14 @@ class ReclassifyFeedbackTests(TestCase):
|
||||||
url = reverse('ietf.nomcom.views.view_feedback_nominee', kwargs={'year':self.nc.year(), 'nominee_id':self.nominee.id})
|
url = reverse('ietf.nomcom.views.view_feedback_nominee', kwargs={'year':self.nc.year(), 'nominee_id':self.nominee.id})
|
||||||
login_testing_unauthorized(self,self.member.user.username,url)
|
login_testing_unauthorized(self,self.member.user.username,url)
|
||||||
provide_private_key_to_test_client(self)
|
provide_private_key_to_test_client(self)
|
||||||
response = self.client.post(url, {'feedback_id': fb.id, 'type': 'obe'})
|
response = self.client.post(url, {'feedback_id': fb.id, 'type': 'obe', 'submit': 'reclassify'})
|
||||||
self.assertEqual(response.status_code, 403)
|
self.assertEqual(response.status_code, 403)
|
||||||
|
|
||||||
self.client.logout()
|
self.client.logout()
|
||||||
self.client.login(username=self.chair.user.username, password=self.chair.user.username + "+password")
|
self.client.login(username=self.chair.user.username, password=self.chair.user.username + "+password")
|
||||||
provide_private_key_to_test_client(self)
|
provide_private_key_to_test_client(self)
|
||||||
|
|
||||||
response = self.client.post(url, {'feedback_id': fb.id, 'type': 'obe'})
|
response = self.client.post(url, {'feedback_id': fb.id, 'type': 'obe', 'submit': 'reclassify'})
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
fb = Feedback.objects.get(id=fb.id)
|
fb = Feedback.objects.get(id=fb.id)
|
||||||
|
|
|
@ -19,6 +19,7 @@ from django.shortcuts import render, get_object_or_404, redirect
|
||||||
from django.template.loader import render_to_string
|
from django.template.loader import render_to_string
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.encoding import force_bytes, force_str
|
from django.utils.encoding import force_bytes, force_str
|
||||||
|
from django.utils.text import slugify
|
||||||
|
|
||||||
from email.errors import HeaderParseError
|
from email.errors import HeaderParseError
|
||||||
|
|
||||||
|
@ -1023,24 +1024,38 @@ def view_feedback_nominee(request, year, nominee_id):
|
||||||
return HttpResponseForbidden('Restricted to roles: Nomcom Chair, Nomcom Advisor')
|
return HttpResponseForbidden('Restricted to roles: Nomcom Chair, Nomcom Advisor')
|
||||||
feedback_id = request.POST.get('feedback_id', None)
|
feedback_id = request.POST.get('feedback_id', None)
|
||||||
feedback = get_object_or_404(Feedback, id=feedback_id)
|
feedback = get_object_or_404(Feedback, id=feedback_id)
|
||||||
type = request.POST.get('type', None)
|
submit = request.POST.get('submit', None)
|
||||||
if type:
|
if submit == 'download':
|
||||||
if type == 'unclassified':
|
fn = f'questionnaire-{slugify(nominee.name())}-{feedback.time.date()}.txt'
|
||||||
feedback.type = None
|
response = render_to_string('nomcom/download_questionnaire.txt',
|
||||||
feedback.nominees.clear()
|
{'year': year,
|
||||||
messages.success(request, 'The selected feedback has been de-classified. Please reclassify it in the Pending emails tab.')
|
'nominee': nominee,
|
||||||
|
'feedback': feedback,
|
||||||
|
'positions': ','.join([str(p) for p in feedback.positions.all()]),
|
||||||
|
},
|
||||||
|
request=request)
|
||||||
|
response = HttpResponse(response, content_type='text/plain')
|
||||||
|
response['Content-Disposition'] = f'attachment; filename="{fn}"'
|
||||||
|
return response
|
||||||
|
elif submit == 'reclassify':
|
||||||
|
type = request.POST.get('type', None)
|
||||||
|
if type:
|
||||||
|
if type == 'unclassified':
|
||||||
|
feedback.type = None
|
||||||
|
feedback.nominees.clear()
|
||||||
|
messages.success(request, 'The selected feedback has been de-classified. Please reclassify it in the Pending emails tab.')
|
||||||
|
else:
|
||||||
|
feedback.type = FeedbackTypeName.objects.get(slug=type)
|
||||||
|
messages.success(request, f'The selected feedback has been reclassified as {feedback.type.name}.')
|
||||||
|
feedback.save()
|
||||||
else:
|
else:
|
||||||
feedback.type = FeedbackTypeName.objects.get(slug=type)
|
return render(request, 'nomcom/view_feedback_nominee.html',
|
||||||
messages.success(request, f'The selected feedback has been reclassified as {feedback.type.name}.')
|
{'year': year,
|
||||||
feedback.save()
|
'nomcom': nomcom,
|
||||||
else:
|
'feedback_types': feedback_types,
|
||||||
return render(request, 'nomcom/view_feedback_nominee.html',
|
'reclassify_feedback': feedback,
|
||||||
{'year': year,
|
'is_chair_task': True,
|
||||||
'nomcom': nomcom,
|
})
|
||||||
'feedback_types': feedback_types,
|
|
||||||
'reclassify_feedback': feedback,
|
|
||||||
'is_chair_task': True,
|
|
||||||
})
|
|
||||||
|
|
||||||
last_seen = FeedbackLastSeen.objects.filter(reviewer=request.user.person,nominee=nominee).first()
|
last_seen = FeedbackLastSeen.objects.filter(reviewer=request.user.person,nominee=nominee).first()
|
||||||
last_seen_time = (last_seen and last_seen.time) or datetime.datetime(year=1, month=1, day=1, tzinfo=datetime.timezone.utc)
|
last_seen_time = (last_seen and last_seen.time) or datetime.datetime(year=1, month=1, day=1, tzinfo=datetime.timezone.utc)
|
||||||
|
|
9
ietf/templates/nomcom/download_questionnaire.txt
Normal file
9
ietf/templates/nomcom/download_questionnaire.txt
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
{# Copyright The IETF Trust 2023, All Rights Reserved #}{% autoescape off %}{% load nomcom_tags %}Questionnaire response from {{ nominee.person.name }}
|
||||||
|
|
||||||
|
From: {{ feedback.author|formatted_email|default:"Anonymous" }}
|
||||||
|
Date: {{ feedback.time|date:"Y-m-d" }}
|
||||||
|
Positions: {{ positions }}{% if feedback.subject %}
|
||||||
|
Subject: {{ feedback.subject }}{% endif %}
|
||||||
|
|
||||||
|
{% decrypt feedback.comments request year 1 %}
|
||||||
|
{% endautoescape %}
|
|
@ -99,5 +99,5 @@
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<input type="hidden" name="feedback_id" value="{{ reclassify_feedback.id }}">
|
<input type="hidden" name="feedback_id" value="{{ reclassify_feedback.id }}">
|
||||||
<button class="btn btn-primary" type="submit">Classify</button>
|
<button class="btn btn-primary" type="submit" name="submit" value="reclassify">Classify</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -89,7 +89,12 @@
|
||||||
<form id="reclassify-{{ feedback.id }}" method="post">
|
<form id="reclassify-{{ feedback.id }}" method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<input type="hidden" name="feedback_id" value="{{ feedback.id }}">
|
<input type="hidden" name="feedback_id" value="{{ feedback.id }}">
|
||||||
<button class="btn btn-warning btn-sm" type="submit">
|
{% if ft.slug == "questio" %}
|
||||||
|
<p><button class="btn btn-warning btn-sm" type="submit" name="submit" value="download">
|
||||||
|
Download
|
||||||
|
</button></p>
|
||||||
|
{% endif %}
|
||||||
|
<button class="btn btn-warning btn-sm" type="submit" name="submit" value="reclassify">
|
||||||
Reclassify
|
Reclassify
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
Loading…
Reference in a new issue