diff --git a/ietf/nomcom/fields.py b/ietf/nomcom/fields.py index e0d491bf6..7989a97ca 100644 --- a/ietf/nomcom/fields.py +++ b/ietf/nomcom/fields.py @@ -1,6 +1,3 @@ -import os - -import tempfile from django.conf import settings from django.db import models @@ -17,14 +14,9 @@ class EncryptedTextField(models.TextField): comments = getattr(instance, 'comments') nomcom = getattr(instance, 'nomcom') cert_file = nomcom.public_key.path - comments_file = tempfile.NamedTemporaryFile(delete=False) - comments_file.write(comments) - comments_file.close() - code, out, error = pipe("%s smime -encrypt -in %s %s" % (settings.OPENSSL_COMMAND, - comments_file.name, - cert_file)) - os.unlink(comments_file.name) + code, out, error = pipe("%s smime -encrypt -in /dev/stdin %s" % (settings.OPENSSL_COMMAND, + cert_file), comments) if not error: instance.comments = out return out diff --git a/ietf/nomcom/managers.py b/ietf/nomcom/managers.py index 69bb4b543..b9d3be07c 100644 --- a/ietf/nomcom/managers.py +++ b/ietf/nomcom/managers.py @@ -2,6 +2,14 @@ from django.db import models from django.db.models.query import QuerySet +class MixinManager(object): + def __getattr__(self, attr, *args): + try: + return getattr(self.__class__, attr, *args) + except AttributeError: + return getattr(self.get_query_set(), attr, *args) + + class NomineePositionQuerySet(QuerySet): def get_by_nomcom(self, nomcom): @@ -23,16 +31,10 @@ class NomineePositionQuerySet(QuerySet): return self.by_state('declined') -class NomineePositionManager(models.Manager): +class NomineePositionManager(models.Manager, MixinManager): def get_query_set(self): return NomineePositionQuerySet(self.model) - def __getattr__(self, attr, *args): - try: - return getattr(self.__class__, attr, *args) - except AttributeError: - return getattr(self.get_query_set(), attr, *args) - class NomineeManager(models.Manager): def get_by_nomcom(self, nomcom): @@ -53,12 +55,29 @@ class PositionQuerySet(QuerySet): return self.filter(is_open=False) -class PositionManager(models.Manager): +class PositionManager(models.Manager, MixinManager): def get_query_set(self): return PositionQuerySet(self.model) - def __getattr__(self, attr, *args): - try: - return getattr(self.__class__, attr, *args) - except AttributeError: - return getattr(self.get_query_set(), attr, *args) + +class FeedbackQuerySet(QuerySet): + + def get_by_nomcom(self, nomcom): + return self.filter(nomcom=nomcom) + + def by_type(self, type): + return self.filter(type=type) + + def comments(self): + return self.by_type('comment') + + def questionnaires(self): + return self.by_type('questio') + + def nominations(self): + return self.by_type('nomina') + + +class FeedbackManager(models.Manager, MixinManager): + def get_query_set(self): + return FeedbackQuerySet(self.model) diff --git a/ietf/nomcom/models.py b/ietf/nomcom/models.py index a8b029219..721a5857e 100644 --- a/ietf/nomcom/models.py +++ b/ietf/nomcom/models.py @@ -13,7 +13,8 @@ from ietf.group.models import Group from ietf.name.models import NomineePositionState, FeedbackType from ietf.dbtemplate.models import DBTemplate -from ietf.nomcom.managers import NomineePositionManager, NomineeManager, PositionManager +from ietf.nomcom.managers import NomineePositionManager, NomineeManager, \ + PositionManager, FeedbackManager from ietf.nomcom.utils import (initialize_templates_for_group, initialize_questionnaire_for_position, initialize_requirements_for_position) @@ -125,7 +126,7 @@ class Position(models.Model): verbose_name_plural = 'Positions' def __unicode__(self): - return u"%s: %s" % (self.nomcom, self.name) + return self.name def save(self, *args, **kwargs): created = not self.id @@ -158,9 +159,14 @@ class Feedback(models.Model): user = models.ForeignKey(User, blank=True, null=True) time = models.DateTimeField(auto_now_add=True) + objects = FeedbackManager() + def __unicode__(self): return u"%s - %s" % (self.author, self.nominee) + class Meta: + ordering = ['time'] + # ----- adding south rules to help introspection ----- add_introspection_rules([], ["^ietf\.nomcom\.fields\.EncryptedTextField"]) diff --git a/ietf/nomcom/templatetags/nomcom_tags.py b/ietf/nomcom/templatetags/nomcom_tags.py index 7f4ad71e7..2081e9abc 100644 --- a/ietf/nomcom/templatetags/nomcom_tags.py +++ b/ietf/nomcom/templatetags/nomcom_tags.py @@ -3,10 +3,12 @@ import tempfile from django import template from django.conf import settings +from django.template.defaultfilters import linebreaksbr from ietf.utils.pipe import pipe from ietf.ietfauth.decorators import has_role +from ietf.person.models import Person from ietf.nomcom.models import Feedback from ietf.nomcom.utils import get_nomcom_by_year, get_user_email, retrieve_nomcom_private_key @@ -40,6 +42,15 @@ def add_num_nominations(user, position, nominee): return '%s ' % (count, nominee, position, mark) +@register.filter +def get_person(email): + person = email + if email: + persons = Person.objects.filter(email__address__in=[email]) + person = persons and persons[0].name or person + return person + + @register.simple_tag def decrypt(string, request, year): key = retrieve_nomcom_private_key(request, year) @@ -60,4 +71,4 @@ def decrypt(string, request, year): if error: return '<-Encripted text [Your private key is invalid]->' - return out + return linebreaksbr(out) diff --git a/ietf/nomcom/urls.py b/ietf/nomcom/urls.py index 616c6ff1b..2e39de3d9 100644 --- a/ietf/nomcom/urls.py +++ b/ietf/nomcom/urls.py @@ -8,6 +8,7 @@ urlpatterns = patterns('ietf.nomcom.views', url(r'^(?P\d{4})/private/nominate/$', 'private_nominate', name='nomcom_private_nominate'), url(r'^(?P\d{4})/private/feedback/$', 'private_feedback', name='nomcom_private_feedback'), url(r'^(?P\d{4})/private/view-feedback/$', 'view_feedback', name='nomcom_view_feedback'), + url(r'^(?P\d{4})/private/view-feedback/nominee/(?P\d+)$', 'view_feedback_nominee', name='nomcom_view_feedback_nominee'), url(r'^(?P\d{4})/private/merge/$', 'private_merge', name='nomcom_private_merge'), url(r'^(?P\d{4})/private/send-reminder-mail/$', 'send_reminder_mail', name='nomcom_send_reminder_mail'), url(r'^(?P\d{4})/private/edit-members/$', EditMembersFormPreview(EditMembersForm), name='nomcom_edit_members'), diff --git a/ietf/nomcom/views.py b/ietf/nomcom/views.py index 771b7ad3f..5efd904f9 100644 --- a/ietf/nomcom/views.py +++ b/ietf/nomcom/views.py @@ -3,7 +3,7 @@ from django.conf import settings from django.contrib.auth.decorators import login_required from django.core.urlresolvers import reverse from django.http import HttpResponse, Http404, HttpResponseRedirect -from django.shortcuts import render_to_response +from django.shortcuts import render_to_response, get_object_or_404 from django.template import RequestContext from django.template.loader import render_to_string from django.utils import simplejson @@ -13,7 +13,7 @@ from ietf.utils.mail import send_mail from ietf.dbtemplate.models import DBTemplate from ietf.dbtemplate.views import template_edit -from ietf.name.models import NomineePositionState +from ietf.name.models import NomineePositionState, FeedbackType from ietf.nomcom.decorators import member_required, private_key_required from ietf.nomcom.forms import (EditPublicKeyForm, NominateForm, FeedbackForm, MergeForm, @@ -306,10 +306,27 @@ def feedback(request, year, public): @private_key_required def view_feedback(request, year): nomcom = get_nomcom_by_year(year) + nominees = Nominee.objects.get_by_nomcom(nomcom).distinct() return render_to_response('nomcom/view_feedback.html', {'year': year, 'selected': 'view_feedback', + 'nominees': nominees, + 'nomcom': nomcom}, RequestContext(request)) + + +@member_required(role='member') +@private_key_required +def view_feedback_nominee(request, year, nominee_id): + nomcom = get_nomcom_by_year(year) + nominee = get_object_or_404(Nominee, id=nominee_id) + feedback_types = FeedbackType.objects.all() + + return render_to_response('nomcom/view_feedback_nominee.html', + {'year': year, + 'selected': 'view_feedback', + 'nominee': nominee, + 'feedback_types': feedback_types, 'nomcom': nomcom}, RequestContext(request)) diff --git a/ietf/templates/nomcom/view_feedback.html b/ietf/templates/nomcom/view_feedback.html index 8ed0ebe8f..93e1952c9 100644 --- a/ietf/templates/nomcom/view_feedback.html +++ b/ietf/templates/nomcom/view_feedback.html @@ -8,4 +8,21 @@

List of Nominees

+ + + + + + + +{% for nominee in nominees %} + + + + + + +{% endfor %} +
NomineeNominationsCommentsQuestionnaires
{{ nominee.email.person.name }}{{ nominee.feedback_set.nominations.count }}{{ nominee.feedback_set.comments.count }}{{ nominee.feedback_set.questionnaires.count }}
+ {% endblock %} \ No newline at end of file diff --git a/ietf/templates/nomcom/view_feedback_nominee.html b/ietf/templates/nomcom/view_feedback_nominee.html new file mode 100644 index 000000000..357c81daf --- /dev/null +++ b/ietf/templates/nomcom/view_feedback_nominee.html @@ -0,0 +1,64 @@ +{% extends "nomcom/nomcom_private_base.html" %} + +{% load nomcom_tags %} + +{% block pagehead %} + {{ block.super }} + + + +{% endblock pagehead %} + +{% block subtitle %} - View comments of {{ nominee.email.person.name }}{% endblock %} + +{% block nomcom_content %} + +

Back to list of nominees

+ +

Feedback of {{ nominee.email.person.name }}

+ +
+
    + {% for ft in feedback_types %} +
  • {{ ft.name }}
  • + {% endfor %} +
+ Pick the feedback type to view from the list immediately above +
+ {% for ft in feedback_types %} +
+ {% for feedback in nominee.feedback_set.all %} + {% ifequal feedback.type.slug ft.slug %} +
+

From {{ feedback.author|get_person|default:"Anonymous" }} ({{ feedback.time|date:"Y-m-d" }})

+ Positions: {{ feedback.positions.all|join:"," }} +

+ {% decrypt feedback.comments request year %} +

+
+ {% endifequal %} + {% endfor %} +
+ {% endfor %} +
+ + + + + +{% endblock %} \ No newline at end of file