* Add skek view to manage feedback generated from email.
* Now, nominee, type and user fields in feedback model can be null See #975 - Legacy-Id: 5576
This commit is contained in:
parent
3f64b5303b
commit
40fd14da25
|
@ -1,5 +1,6 @@
|
|||
from django.conf import settings
|
||||
from django import forms
|
||||
from django.forms.models import BaseModelFormSet
|
||||
from django.contrib.formtools.preview import FormPreview, AUTO_ID
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.shortcuts import get_object_or_404
|
||||
|
@ -8,6 +9,7 @@ from django.template.loader import render_to_string
|
|||
from django.utils.decorators import method_decorator
|
||||
from django.shortcuts import render_to_response
|
||||
from django.template.context import RequestContext
|
||||
from django.db.models import Q
|
||||
|
||||
from ietf.dbtemplate.forms import DBTemplateForm
|
||||
from ietf.utils import unaccent
|
||||
|
@ -568,6 +570,14 @@ class FeedbackForm(BaseNomcomForm, forms.ModelForm):
|
|||
"/js/nomcom.js", )
|
||||
|
||||
|
||||
class BaseFeedbackFormSet(BaseModelFormSet):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(BaseFeedbackFormSet, self).__init__(*args, **kwargs)
|
||||
self.queryset = Feedback.objects.filter(Q(type__isnull=True) |
|
||||
Q(nominee__isnull=True) |
|
||||
Q(positions=True))
|
||||
|
||||
|
||||
class NomComTemplateForm(BaseNomcomForm, DBTemplateForm):
|
||||
|
||||
fieldsets = [('Template content', ('content', )),
|
||||
|
|
|
@ -72,9 +72,9 @@ class Migration(SchemaMigration):
|
|||
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
||||
('nomcom', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['nomcom.NomCom'])),
|
||||
('author', self.gf('django.db.models.fields.EmailField')(max_length=75, blank=True)),
|
||||
('nominee', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['nomcom.Nominee'])),
|
||||
('nominee', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['nomcom.Nominee'], null=True, blank=True)),
|
||||
('comments', self.gf('ietf.nomcom.fields.EncryptedTextField')()),
|
||||
('type', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['name.FeedbackType'])),
|
||||
('type', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['name.FeedbackType'], null=True, blank=True)),
|
||||
('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True, blank=True)),
|
||||
('time', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
|
||||
))
|
||||
|
@ -332,15 +332,15 @@ class Migration(SchemaMigration):
|
|||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'nomcom.feedback': {
|
||||
'Meta': {'object_name': 'Feedback'},
|
||||
'Meta': {'ordering': "['time']", 'object_name': 'Feedback'},
|
||||
'author': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
||||
'comments': ('ietf.nomcom.fields.EncryptedTextField', [], {}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'nomcom': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['nomcom.NomCom']"}),
|
||||
'nominee': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['nomcom.Nominee']"}),
|
||||
'nominee': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['nomcom.Nominee']", 'null': 'True', 'blank': 'True'}),
|
||||
'positions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['nomcom.Position']", 'null': 'True', 'blank': 'True'}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.FeedbackType']"}),
|
||||
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.FeedbackType']", 'null': 'True', 'blank': 'True'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
'nomcom.nomcom': {
|
||||
|
|
|
@ -54,7 +54,7 @@ class Nomination(models.Model):
|
|||
nominee = models.ForeignKey('Nominee')
|
||||
comments = models.ForeignKey('Feedback')
|
||||
nominator_email = models.EmailField(verbose_name='Nominator Email', blank=True)
|
||||
user = models.ForeignKey(User)
|
||||
user = models.ForeignKey(User, editable=False)
|
||||
time = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
class Meta:
|
||||
|
@ -153,16 +153,16 @@ class Feedback(models.Model):
|
|||
nomcom = models.ForeignKey('NomCom')
|
||||
author = models.EmailField(verbose_name='Author', blank=True)
|
||||
positions = models.ManyToManyField('Position', blank=True, null=True)
|
||||
nominee = models.ForeignKey('Nominee')
|
||||
nominee = models.ForeignKey('Nominee', blank=True, null=True)
|
||||
comments = EncryptedTextField(verbose_name='Comments')
|
||||
type = models.ForeignKey(FeedbackType)
|
||||
user = models.ForeignKey(User, blank=True, null=True)
|
||||
type = models.ForeignKey(FeedbackType, blank=True, null=True)
|
||||
user = models.ForeignKey(User, editable=False, blank=True, null=True)
|
||||
time = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
objects = FeedbackManager()
|
||||
|
||||
def __unicode__(self):
|
||||
return u"%s - %s" % (self.author, self.nominee)
|
||||
return u"from %s to %s" % (self.author, self.nominee)
|
||||
|
||||
class Meta:
|
||||
ordering = ['time']
|
||||
|
|
|
@ -258,7 +258,29 @@ class NomcomViewsTest(TestCase):
|
|||
self.client.logout()
|
||||
|
||||
def feedback_view(self, *args, **kwargs):
|
||||
pass
|
||||
public = kwargs.pop('public', True)
|
||||
nominee_email = kwargs.pop('nominee_email', u'nominee@example.com')
|
||||
position_name = kwargs.pop('position', 'IAOC')
|
||||
|
||||
if public:
|
||||
nominate_url = self.public_feedback_url
|
||||
else:
|
||||
nominate_url = self.private_feedback_url
|
||||
|
||||
response = self.client.get(nominate_url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
nomcom = get_nomcom_by_year(self.year)
|
||||
if not nomcom.public_key:
|
||||
self.assertNotContains(response, "feedbackform")
|
||||
|
||||
# save the cert file in tmp
|
||||
nomcom.public_key.storage.location = tempfile.gettempdir()
|
||||
nomcom.public_key.save('cert', File(open(self.cert_file.name, 'r')))
|
||||
|
||||
response = self.client.get(nominate_url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, "feedbackform")
|
||||
|
||||
def test_public_nominate(self):
|
||||
login_testing_unauthorized(self, COMMUNITY_USER, self.public_nominate_url)
|
||||
|
|
|
@ -8,6 +8,7 @@ urlpatterns = patterns('ietf.nomcom.views',
|
|||
url(r'^(?P<year>\d{4})/private/nominate/$', 'private_nominate', name='nomcom_private_nominate'),
|
||||
url(r'^(?P<year>\d{4})/private/feedback/$', 'private_feedback', name='nomcom_private_feedback'),
|
||||
url(r'^(?P<year>\d{4})/private/view-feedback/$', 'view_feedback', name='nomcom_view_feedback'),
|
||||
url(r'^(?P<year>\d{4})/private/view-feedback/pending/$', 'view_feedback_pending', name='nomcom_view_feedback_pending'),
|
||||
url(r'^(?P<year>\d{4})/private/view-feedback/nominee/(?P<nominee_id>\d+)$', 'view_feedback_nominee', name='nomcom_view_feedback_nominee'),
|
||||
url(r'^(?P<year>\d{4})/private/merge/$', 'private_merge', name='nomcom_private_merge'),
|
||||
url(r'^(?P<year>\d{4})/private/send-reminder-mail/$', 'send_reminder_mail', name='nomcom_send_reminder_mail'),
|
||||
|
|
|
@ -8,6 +8,7 @@ from django.template import RequestContext
|
|||
from django.template.loader import render_to_string
|
||||
from django.utils import simplejson
|
||||
from django.db.models import Count
|
||||
from django.forms.models import modelformset_factory
|
||||
|
||||
from ietf.utils.mail import send_mail
|
||||
|
||||
|
@ -17,7 +18,8 @@ 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,
|
||||
NomComTemplateForm, PositionForm, PrivateKeyForm)
|
||||
NomComTemplateForm, PositionForm, PrivateKeyForm,
|
||||
BaseFeedbackFormSet)
|
||||
from ietf.nomcom.models import Position, NomineePosition, Nominee, Feedback
|
||||
from ietf.nomcom.utils import (get_nomcom_by_year, HOME_TEMPLATE,
|
||||
retrieve_nomcom_private_key,
|
||||
|
@ -315,6 +317,30 @@ def view_feedback(request, year):
|
|||
'nomcom': nomcom}, RequestContext(request))
|
||||
|
||||
|
||||
@member_required(role='chair')
|
||||
@private_key_required
|
||||
def view_feedback_pending(request, year):
|
||||
nomcom = get_nomcom_by_year(year)
|
||||
message = None
|
||||
FeedbackFormSet = modelformset_factory(Feedback,
|
||||
formset=BaseFeedbackFormSet,
|
||||
exclude=('nomcom', 'comments'),
|
||||
extra=0)
|
||||
if request.method == 'POST':
|
||||
formset = FeedbackFormSet(request.POST)
|
||||
if formset.is_valid():
|
||||
formset.save()
|
||||
message = ('success', 'The feedbacks has been saved.')
|
||||
else:
|
||||
formset = FeedbackFormSet()
|
||||
return render_to_response('nomcom/view_feedback_pending.html',
|
||||
{'year': year,
|
||||
'selected': 'view_feedback',
|
||||
'formset': formset,
|
||||
'message': message,
|
||||
'nomcom': nomcom}, RequestContext(request))
|
||||
|
||||
|
||||
@member_required(role='member')
|
||||
@private_key_required
|
||||
def view_feedback_nominee(request, year, nominee_id):
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
{% block nomcom_content %}
|
||||
|
||||
<p><a href="{% url nomcom_view_feedback_pending year %}">Feedbak pending</a></p>
|
||||
|
||||
<h2>List of Nominees</h2>
|
||||
|
||||
<table class="ietf-table ietf-doctable">
|
||||
|
@ -17,7 +19,7 @@
|
|||
</tr>
|
||||
{% for nominee in nominees %}
|
||||
<tr class="{{ forloop.counter|divisibleby:2|yesno:"oddrow,evenrow" }}">
|
||||
<td><a href="{% url nomcom_view_feedback_nominee year nominee.id %}">{{ nominee.email.person.name }}</td>
|
||||
<td><a href="{% url nomcom_view_feedback_nominee year nominee.id %}#comment">{{ nominee.email.person.name }}</td>
|
||||
<td>{{ nominee.feedback_set.nominations.count }}</td>
|
||||
<td>{{ nominee.feedback_set.comments.count }}</td>
|
||||
<td>{{ nominee.feedback_set.questionnaires.count }}</td>
|
||||
|
|
|
@ -20,24 +20,33 @@
|
|||
<div id="mytabs" class="yui-navset">
|
||||
<ul class="yui-nav">
|
||||
{% for ft in feedback_types %}
|
||||
<li><a href="#{{ ft.name }}"><em>{{ ft.name }}</em></a></li>
|
||||
<li><a href="#{{ ft.slug }}"><em>{{ ft.name }}</em></a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
Pick the feedback type to view from the list immediately above
|
||||
<div class="yui-content">
|
||||
{% for ft in feedback_types %}
|
||||
<div id="{{ ft.name }}">
|
||||
{% for feedback in nominee.feedback_set.all %}
|
||||
{% ifequal feedback.type.slug ft.slug %}
|
||||
<div>
|
||||
<h3 class="ietf-divider">From {{ feedback.author|get_person|default:"Anonymous" }} ({{ feedback.time|date:"Y-m-d" }})</h3>
|
||||
<b>Positions:</b> {{ feedback.positions.all|join:"," }}
|
||||
<p>
|
||||
{% decrypt feedback.comments request year %}
|
||||
</p>
|
||||
</div>
|
||||
{% endifequal %}
|
||||
{% endfor %}
|
||||
<div id="#{{ ft.slug }}">
|
||||
{% ifequal ft.slug "comment" %}
|
||||
<b>Number of comments: {{ nominee.feedback_set.comments.count|default:"0" }}</b>
|
||||
{% endifequal %}
|
||||
{% ifequal ft.slug "questio" %}
|
||||
<b>Number of questionnaires: {{ nominee.feedback_set.questionaires.count|default:"0" }}</b>
|
||||
{% endifequal %}
|
||||
{% ifequal ft.slug "nomina" %}
|
||||
<b>Number of nominations: {{ nominee.feedback_set.nominations.count|default:"0" }}</b>
|
||||
{% endifequal %}
|
||||
{% for feedback in nominee.feedback_set.all %}
|
||||
{% ifequal feedback.type.slug ft.slug %}
|
||||
<div>
|
||||
<h3 class="ietf-divider">From {{ feedback.author|get_person|default:"Anonymous" }} ({{ feedback.time|date:"Y-m-d" }})</h3>
|
||||
<b>Positions:</b> {{ feedback.positions.all|join:"," }}
|
||||
<p>
|
||||
{% decrypt feedback.comments request year %}
|
||||
</p>
|
||||
</div>
|
||||
{% endifequal %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
|
37
ietf/templates/nomcom/view_feedback_pending.html
Normal file
37
ietf/templates/nomcom/view_feedback_pending.html
Normal file
|
@ -0,0 +1,37 @@
|
|||
{% extends "nomcom/nomcom_private_base.html" %}
|
||||
|
||||
{% load nomcom_tags %}
|
||||
|
||||
|
||||
{% block subtitle %} - Feeback pending{% endblock %}
|
||||
|
||||
{% block nomcom_content %}
|
||||
|
||||
<p>Back to <a href="{% url nomcom_view_feedback year %}">feedback index</a></p>
|
||||
|
||||
<h2>Feedback pending from email list</h2>
|
||||
|
||||
{% if message %}
|
||||
<div class="info-message-{{ message.0 }}">{{ message.1 }}</div>
|
||||
{% endif %}
|
||||
|
||||
<div>
|
||||
<form id="feedbackformset" action="" method="post">{% csrf_token %}
|
||||
{{ formset.management_form }}
|
||||
{% for form in formset.forms %}
|
||||
<div class="ietf-divider"></div>
|
||||
<div>
|
||||
{% for field in form %}
|
||||
<div>
|
||||
{{ field.label_tag }}: {{ field }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% decrypt form.instance.comments request year %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
<div class="ietf-divider"></div>
|
||||
<input type="submit" value="Submit" />
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
Loading…
Reference in a new issue