Skip to content

Commit b1f1ceb

Browse files
committed
Add public and private complete views to do comments
Add new manager for position model Add templatetag to see the total number of nominations by user on a position Add feedback receipt template See ietf-tools#970 - Legacy-Id: 5554
1 parent 04ab58d commit b1f1ceb

11 files changed

Lines changed: 397 additions & 113 deletions

File tree

ietf/dbtemplate/fixtures/nomcom_templates.xml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,27 @@ The following comments have also been registered:
125125
$comments
126126
--------------------------------------------------------------------------
127127

128+
Thank you,</field>
129+
<field to="group.group" name="group" rel="ManyToOneRel"><None></None></field>
130+
</object>
131+
<object p="10" model="dbtemplate.dbtemplate">
132+
<field type="CharField" name="path">/nomcom/defaults/email/feedback_receipt.txt</field>
133+
<field type="CharField" name="title">Email sent to feedback author to get a confirmation mail containing feedback in cleartext</field>
134+
<field type="TextField" name="variables">$nominee: Full name of the nominee
135+
$position: Nomination position
136+
$comments: Comments on this candidate</field>
137+
<field to="name.dbtemplatetypename" name="type" rel="ManyToOneRel">plain</field>
138+
<field type="TextField" name="content">Hi,
139+
140+
Your input regarding $nominee for the position of
141+
$position has been received and registered.
142+
143+
The following comments have been registered:
144+
145+
--------------------------------------------------------------------------
146+
$comments
147+
--------------------------------------------------------------------------
148+
128149
Thank you,</field>
129150
<field to="group.group" name="group" rel="ManyToOneRel"><None></None></field>
130151
</object>

ietf/nomcom/forms.py

Lines changed: 122 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
Position, Feedback
2222
from ietf.nomcom.utils import QUESTIONNAIRE_TEMPLATE, NOMINATION_EMAIL_TEMPLATE, \
2323
INEXISTENT_PERSON_TEMPLATE, NOMINEE_EMAIL_TEMPLATE, \
24-
NOMINATION_RECEIPT_TEMPLATE, get_user_email
24+
NOMINATION_RECEIPT_TEMPLATE, FEEDBACK_RECEIPT_TEMPLATE, \
25+
get_user_email
2526
from ietf.nomcom.decorators import member_required
2627

2728
ROLODEX_URL = getattr(settings, 'ROLODEX_URL', None)
@@ -288,7 +289,7 @@ class NominateForm(BaseNomcomForm, forms.ModelForm):
288289
widget=forms.Textarea())
289290
confirmation = forms.BooleanField(label='Email comments back to me as confirmation',
290291
help_text="If you want to get a confirmation mail containing your feedback in cleartext, \
291-
please check the 'email comments back to me as confirmation' box below.",
292+
please check the 'email comments back to me as confirmation'",
292293
required=False)
293294

294295
fieldsets = [('Candidate Nomination', ('position', 'candidate_name',
@@ -300,8 +301,16 @@ def __init__(self, *args, **kwargs):
300301
self.public = kwargs.pop('public', None)
301302

302303
super(NominateForm, self).__init__(*args, **kwargs)
304+
305+
fieldset = ['nominator_email',
306+
'position',
307+
'candidate_name',
308+
'candidate_email', 'candidate_phone',
309+
'comments']
310+
303311
if self.nomcom:
304-
self.fields['position'].queryset = Position.objects.filter(nomcom=self.nomcom)
312+
self.fields['position'].queryset = Position.objects.get_by_nomcom(self.nomcom).opened()
313+
305314
if not self.public:
306315
author = get_user_email(self.user)
307316
if author:
@@ -310,11 +319,10 @@ def __init__(self, *args, **kwargs):
310319
nomination wishes to be anonymous. The confirmation email will be sent to the address given here,
311320
and the address will also be captured as part of the registered nomination.)"""
312321
self.fields['nominator_email'].help_text = help_text
313-
self.fieldsets = [('Candidate Nomination', ('nominator_email',
314-
'position',
315-
'candidate_name',
316-
'candidate_email', 'candidate_phone',
317-
'comments'))]
322+
else:
323+
fieldset.append('confirmation')
324+
325+
self.fieldsets = [('Candidate Nomination', fieldset)]
318326

319327
def save(self, commit=True):
320328
# Create nomination
@@ -413,6 +421,7 @@ def save(self, commit=True):
413421
path = nomcom_template_path + NOMINATION_EMAIL_TEMPLATE
414422
send_mail(None, to_email, from_email, subject, path, context)
415423

424+
# send receipt email to nominator
416425
if confirmation or not self.public:
417426
if author:
418427
subject = 'Nomination Receipt'
@@ -437,39 +446,130 @@ class Media:
437446

438447

439448
class FeedbackForm(BaseNomcomForm, forms.ModelForm):
440-
position = forms.CharField(label='position')
441-
nominee_name = forms.CharField(label='nominee name')
442-
nominee_email = forms.CharField(label='nominee email')
449+
position_name = forms.CharField(label='position',
450+
widget=forms.TextInput(attrs={'size': '40'}))
451+
nominee_name = forms.CharField(label='your name',
452+
widget=forms.TextInput(attrs={'size': '40'}))
453+
nominee_email = forms.CharField(label='your email',
454+
widget=forms.TextInput(attrs={'size': '40'}))
443455
nominator_name = forms.CharField(label='nominator name')
444456
nominator_email = forms.CharField(label='nominator email')
445457

446-
comments = forms.CharField(label='Comments on this candidate', widget=forms.Textarea())
447-
448-
fieldsets = [('Provide comments', ('position',
449-
'nominee_name',
450-
'nominee_email',
451-
'nominator_name',
452-
'nominator_email',
453-
'comments'))]
458+
comments = forms.CharField(label='Comments on this candidate',
459+
widget=forms.Textarea())
460+
confirmation = forms.BooleanField(label='Email comments back to me as confirmation',
461+
help_text="If you want to get a confirmation mail containing your feedback in cleartext, \
462+
please check the 'email comments back to me as confirmation'",
463+
required=False)
454464

455465
def __init__(self, *args, **kwargs):
456466
self.nomcom = kwargs.pop('nomcom', None)
457467
self.user = kwargs.pop('user', None)
458468
self.public = kwargs.pop('public', None)
469+
self.position = kwargs.pop('position', None)
470+
self.nominee = kwargs.pop('nominee', None)
459471

460472
super(FeedbackForm, self).__init__(*args, **kwargs)
461473

474+
readonly_fields = ['position_name',
475+
'nominee_name',
476+
'nominee_email']
477+
478+
fieldset = ['position_name',
479+
'nominee_name',
480+
'nominee_email',
481+
'nominator_name',
482+
'nominator_email',
483+
'comments',
484+
'position',
485+
'type',
486+
'nominee']
487+
488+
if self.public:
489+
readonly_fields += ['nominator_name', 'nominator_email']
490+
fieldset.append('confirmation')
491+
else:
492+
help_text = """(Nomcom Chair/Member: please fill this in. Use your own email address if the person making the
493+
comments wishes to be anonymous. The confirmation email will be sent to the address given here,
494+
and the address will also be captured as part of the registered nomination.)"""
495+
self.fields['nominator_email'].help_text = help_text
496+
497+
hidden_fields = ['position', 'type', 'nominee']
498+
499+
author = get_user_email(self.user)
500+
if author:
501+
self.fields['nominator_email'].initial = author.address
502+
self.fields['nominator_name'].initial = author.person.name
503+
504+
if self.position and self.nominee:
505+
self.fields['type'].initial = "comment"
506+
self.fields['position'].initial = self.position
507+
self.fields['position_name'].initial = self.position.name
508+
self.fields['nominee'].initial = self.nominee
509+
self.fields['nominee_name'].initial = self.nominee.email.person.name
510+
self.fields['nominee_email'].initial = self.nominee.email.address
511+
else:
512+
help_text = "Please pick a name on the nominees list"
513+
self.fields['position_name'].initial = help_text
514+
self.fields['nominee_name'].initial = help_text
515+
self.fields['nominee_email'].initial = help_text
516+
self.fields['comments'].initial = help_text
517+
readonly_fields += ['comments']
518+
self.fields['confirmation'].widget.attrs['disabled'] = "disabled"
519+
520+
for field in readonly_fields:
521+
self.fields[field].widget.attrs['readonly'] = True
522+
523+
for field in hidden_fields:
524+
self.fields[field].widget = forms.HiddenInput()
525+
526+
self.fieldsets = [('Provide comments', fieldset)]
527+
462528
def save(self, commit=True):
463-
pass
529+
feedback = super(FeedbackForm, self).save(commit=False)
530+
confirmation = self.cleaned_data['confirmation']
531+
nominee = self.cleaned_data['nominee']
532+
position = self.cleaned_data['position']
533+
comments = self.cleaned_data['comments']
534+
nominator_email = self.cleaned_data['nominator_email']
535+
nomcom_template_path = '/nomcom/%s/' % self.nomcom.group.acronym
536+
537+
author = None
538+
if self.public:
539+
author = get_user_email(self.user)
540+
else:
541+
if nominator_email:
542+
emails = Email.objects.filter(address=nominator_email)
543+
author = emails and emails[0] or None
544+
545+
if author:
546+
feedback.author = author
547+
feedback.save()
548+
549+
# send receipt email to feedback author
550+
if confirmation or not self.public:
551+
if author:
552+
subject = "NomCom comment confirmation"
553+
from_email = settings.NOMCOM_FROM_EMAIL
554+
to_email = author.address
555+
context = {'nominee': nominee.email.person.name,
556+
'comments': comments,
557+
'position': position.name}
558+
path = nomcom_template_path + FEEDBACK_RECEIPT_TEMPLATE
559+
send_mail(None, to_email, from_email, subject, path, context)
464560

465561
class Meta:
466562
model = Feedback
467-
fields = ('position',
563+
fields = ('author',
564+
'position',
565+
'nominee',
468566
'nominee_name',
469567
'nominee_email',
470568
'nominator_name',
471569
'nominator_email',
472-
'comments')
570+
'confirmation',
571+
'comments',
572+
'type')
473573

474574
class Media:
475575
js = ("/js/jquery-1.5.1.min.js",

ietf/nomcom/managers.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,28 @@ def __getattr__(self, attr, *args):
3737
class NomineeManager(models.Manager):
3838
def get_by_nomcom(self, nomcom):
3939
return self.filter(nominee_position__nomcom=nomcom)
40+
41+
42+
class PositionQuerySet(QuerySet):
43+
44+
def get_by_nomcom(self, nomcom):
45+
return self.filter(nomcom=nomcom)
46+
47+
def opened(self):
48+
""" only opened positions """
49+
return self.filter(is_open=True)
50+
51+
def closed(self):
52+
""" only closed positions """
53+
return self.filter(is_open=False)
54+
55+
56+
class PositionManager(models.Manager):
57+
def get_query_set(self):
58+
return PositionQuerySet(self.model)
59+
60+
def __getattr__(self, attr, *args):
61+
try:
62+
return getattr(self.__class__, attr, *args)
63+
except AttributeError:
64+
return getattr(self.get_query_set(), attr, *args)

ietf/nomcom/models.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from ietf.name.models import NomineePositionState, FeedbackType
1313
from ietf.dbtemplate.models import DBTemplate
1414

15-
from ietf.nomcom.managers import NomineePositionManager, NomineeManager
15+
from ietf.nomcom.managers import NomineePositionManager, NomineeManager, PositionManager
1616
from ietf.nomcom.utils import (initialize_templates_for_group,
1717
initialize_questionnaire_for_position,
1818
initialize_requirements_for_position)
@@ -114,6 +114,8 @@ class Position(models.Model):
114114
is_open = models.BooleanField(verbose_name='Is open')
115115
incumbent = models.ForeignKey(Email)
116116

117+
objects = PositionManager()
118+
117119
class Meta:
118120
verbose_name_plural = 'Positions'
119121

ietf/nomcom/templatetags/nomcom_tags.py

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@
44
from django import template
55
from django.conf import settings
66

7-
from ietf.ietfauth.decorators import has_role
8-
from ietf.nomcom.utils import get_nomcom_by_year
97
from ietf.utils.pipe import pipe
8+
from ietf.ietfauth.decorators import has_role
9+
10+
from ietf.nomcom.models import Feedback
11+
from ietf.nomcom.utils import get_nomcom_by_year, get_user_email
12+
1013

1114
register = template.Library()
1215

@@ -21,6 +24,21 @@ def is_chair(user, year):
2124
return nomcom.group.is_chair(user)
2225

2326

27+
@register.simple_tag
28+
def add_num_nominations(user, position, nominee):
29+
author = get_user_email(user)
30+
count = Feedback.objects.filter(position=position,
31+
nominee=nominee,
32+
author=author,
33+
type='comment').count()
34+
if count:
35+
mark = """<span style="white-space: pre; color: red;">*</span>"""
36+
else:
37+
mark = """<span style="white-space: pre;"> </span> """
38+
39+
return '<span title="%d earlier comments from you on %s as %s">%s</span>&nbsp;' % (count, nominee, position, mark)
40+
41+
2442
@register.filter
2543
def decrypt(string, key=None):
2644
if not key:
@@ -34,7 +52,6 @@ def decrypt(string, key=None):
3452
code, out, error = pipe(command % (settings.OPENSSL_COMMAND,
3553
encrypted_file.name), key)
3654

37-
3855
os.unlink(encrypted_file.name)
3956

4057
if error:

ietf/nomcom/utils.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,15 @@
1616
NOMINATION_EMAIL_TEMPLATE = 'email/new_nomination.txt'
1717
NOMINEE_REMINDER_TEMPLATE = 'email/nomination_reminder.txt'
1818
NOMINATION_RECEIPT_TEMPLATE = 'email/nomination_receipt.txt'
19+
FEEDBACK_RECEIPT_TEMPLATE = 'email/feedback_receipt.txt'
20+
1921
DEFAULT_NOMCOM_TEMPLATES = [HOME_TEMPLATE,
2022
INEXISTENT_PERSON_TEMPLATE,
2123
NOMINEE_EMAIL_TEMPLATE,
2224
NOMINATION_EMAIL_TEMPLATE,
2325
NOMINEE_REMINDER_TEMPLATE,
24-
NOMINATION_RECEIPT_TEMPLATE]
26+
NOMINATION_RECEIPT_TEMPLATE,
27+
FEEDBACK_RECEIPT_TEMPLATE]
2528

2629

2730
def get_nomcom_by_year(year):

ietf/nomcom/views.py

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from ietf.dbtemplate.models import DBTemplate
1515
from ietf.dbtemplate.views import template_edit
1616
from ietf.name.models import NomineePositionState
17+
1718
from ietf.nomcom.decorators import member_required, private_key_required
1819
from ietf.nomcom.forms import (EditPublicKeyForm, NominateForm, FeedbackForm, MergeForm,
1920
NomComTemplateForm, PositionForm, PrivateKeyForm)
@@ -252,6 +253,18 @@ def private_feedback(request, year):
252253
def feedback(request, year, public):
253254
nomcom = get_nomcom_by_year(year)
254255
has_publickey = nomcom.public_key and True or False
256+
submit_disabled = True
257+
nominee = None
258+
position = None
259+
selected_nominee = request.GET.get('nominee')
260+
selected_position = request.GET.get('position')
261+
if selected_nominee and selected_position:
262+
nominee = Nominee.objects.get(id=selected_nominee)
263+
position = Position.objects.get(id=selected_position)
264+
submit_disabled = False
265+
266+
positions = Position.objects.get_by_nomcom(nomcom=nomcom).opened()
267+
255268
if public:
256269
template = 'nomcom/public_feedback.html'
257270
else:
@@ -268,19 +281,23 @@ def feedback(request, year, public):
268281

269282
message = None
270283
if request.method == 'POST':
271-
form = FeedbackForm(data=request.POST, nomcom=nomcom, user=request.user, public=public)
284+
form = FeedbackForm(data=request.POST, nomcom=nomcom, user=request.user,
285+
public=public, position=position, nominee=nominee)
272286
if form.is_valid():
273287
form.save()
274-
message = ('success', 'Your nomination has been registered. Thank you for the nomination.')
288+
message = ('success', 'Your feedback has been registered.')
275289
else:
276-
form = FeedbackForm(nomcom=nomcom, user=request.user, public=public)
290+
form = FeedbackForm(nomcom=nomcom, user=request.user, public=public,
291+
position=position, nominee=nominee)
277292

278293
return render_to_response(template,
279294
{'has_publickey': has_publickey,
280295
'form': form,
281296
'message': message,
282297
'nomcom': nomcom,
283298
'year': year,
299+
'positions': positions,
300+
'submit_disabled': submit_disabled,
284301
'selected': 'feedback'}, RequestContext(request))
285302

286303

0 commit comments

Comments
 (0)