diff --git a/ietf/dbtemplate/fixtures/nomcom_templates.xml b/ietf/dbtemplate/fixtures/nomcom_templates.xml index efb65c8af..ee0f9564d 100644 --- a/ietf/dbtemplate/fixtures/nomcom_templates.xml +++ b/ietf/dbtemplate/fixtures/nomcom_templates.xml @@ -55,8 +55,8 @@ $position: Nomination position plain A new nomination have been received. -Nominator: $nominator <$nominator_email> -Nominee: $nominee <$nominee_email> +Nominator: $nominator ($nominator_email) +Nominee: $nominee ($nominee_email) Position: $position diff --git a/ietf/nomcom/forms.py b/ietf/nomcom/forms.py index 209daeccf..5df333457 100644 --- a/ietf/nomcom/forms.py +++ b/ietf/nomcom/forms.py @@ -14,13 +14,10 @@ from ietf.name.models import RoleName, FeedbackType from ietf.person.models import Email, Person from ietf.nomcom.models import NomCom, Nomination, Nominee, NomineePosition, \ Position, Feedback - +from ietf.nomcom.utils import QUESTIONNAIRE_TEMPLATE, NOMINATION_EMAIL_TEMPLATE, \ + INEXISTENT_PERSON_TEMPLATE, NOMINEE_EMAIL_TEMPLATE ROLODEX_URL = getattr(settings, 'ROLODEX_URL', None) -INEXISTENT_PERSON_TEMPLATE = "email/inexistent_person.txt" -NOMINEE_TEMPLATE = "email/new_nominee.txt" -NOMINATION_TEMPLATE = "email/new_nomination.txt" -QUESTIONNAIRE_TEMPLATE = "position/questionnaire.txt" def get_group_or_404(year): @@ -227,7 +224,7 @@ class NominateForm(forms.ModelForm): to_email = email.address context = {'nominee': email.person.name, 'position': position} - path = nomcom_template_path + NOMINEE_TEMPLATE + path = nomcom_template_path + NOMINEE_EMAIL_TEMPLATE send_mail(None, to_email, from_email, subject, path, context) # send email to nominee with questionnaire @@ -251,7 +248,7 @@ class NominateForm(forms.ModelForm): if author: context.update({'nominator': author.person.name, 'nominator_email': author.address}) - path = nomcom_template_path + NOMINATION_TEMPLATE + path = nomcom_template_path + NOMINATION_EMAIL_TEMPLATE send_mail(None, to_email, from_email, subject, path, context) return nomination diff --git a/ietf/nomcom/test_data.py b/ietf/nomcom/test_data.py index 49d09daff..eb93d1d22 100644 --- a/ietf/nomcom/test_data.py +++ b/ietf/nomcom/test_data.py @@ -22,11 +22,11 @@ POSITIONS = { def nomcom_test_data(): group, created = Group.objects.get_or_create(name='IAB/IESG Nominating Committee 2013/2014', - state=GroupStateName.objects.get(='active'), + state=GroupStateName.objects.get(slug='active'), type=GroupTypeName.objects.get(slug='nomcom'), acronym='nomcom2013') nomcom, created = NomCom.objects.get_or_create(group=group) - u, created = User.objects.get_or_create(username="plain") + u, created = User.objects.get_or_create(username="plain", password="plain") plainman, created = Person.objects.get_or_create( name="Plain Man", ascii="Plain Man", diff --git a/ietf/nomcom/tests.py b/ietf/nomcom/tests.py index feb8d6411..e60e6b379 100644 --- a/ietf/nomcom/tests.py +++ b/ietf/nomcom/tests.py @@ -1,10 +1,52 @@ from django.test import TestCase from django.db import IntegrityError +from django.core.urlresolvers import reverse +from ietf.utils.test_utils import login_testing_unauthorized from ietf.nomcom.test_data import nomcom_test_data from ietf.nomcom.models import NomineePosition, Position, Nominee, NomineePositionState +class NomcomTest(TestCase): + """Tests to create a new nomcom""" + fixtures = ['names', 'nomcom_templates'] + + def check_url_status(self, url, status): + response = self.client.get(url) + self.assertEqual(response.status_code, status) + + def setUp(self): + nomcom_test_data() + self.year = 2013 + + def test_home_view(self): + """Verify home view""" + url = reverse('nomcom_index', kwargs={'year': self.year}) + self.check_url_status(url, 200) + + def test_nominate_view(self): + """Verify nominate view""" + url = reverse('nomcom_nominate', kwargs={'year': self.year}) + login_testing_unauthorized(self, 'kaligula', url) + self.check_url_status(url, 200) + + def test_requirements_view(self): + """Verify requirements view""" + url = reverse('nomcom_requirements', kwargs={'year': self.year}) + self.check_url_status(url, 200) + + def test_questionnaires_view(self): + """Verify questionnaires view""" + url = reverse('nomcom_questionnaires', kwargs={'year': self.year}) + self.check_url_status(url, 200) + + def test_comments_view(self): + """Verify comments view""" + url = reverse('nomcom_comments', kwargs={'year': self.year}) + login_testing_unauthorized(self, 'plain', url) + self.check_url_status(url, 200) + + class NomineePositionStateSaveTest(TestCase): """Tests for the NomineePosition save override method""" fixtures = ['names', 'nomcom_templates'] diff --git a/ietf/nomcom/urls.py b/ietf/nomcom/urls.py index 972cf25fd..c65103c6e 100644 --- a/ietf/nomcom/urls.py +++ b/ietf/nomcom/urls.py @@ -3,8 +3,14 @@ from ietf.nomcom.forms import EditChairForm, EditChairFormPreview, \ EditMembersForm, EditMembersFormPreview urlpatterns = patterns('ietf.nomcom.views', + url(r'^(?P\d{4})/$', 'index', name='nomcom_index'), + url(r'^(?P\d{4})/requirements/$', 'requirements', name='nomcom_requirements'), + url(r'^(?P\d{4})/questionnaires/$', 'questionnaires', name='nomcom_questionnaires'), + url(r'^(?P\d{4})/requirement/(?P[^/]+)/$', 'requirement_detail', name='nomcom_requirement_detail'), + url(r'^(?P\d{4})/questionnaire/(?P[^/]+)/$', 'questionnaire_detail', name='nomcom_questionnaire_detail'), + url(r'^(?P\d{4})/comments/$', 'comments', name='nomcom_comments'), + url(r'^(?P\d{4})/nominate/$', 'nominate', name='nomcom_nominate'), url(r'^(?P\d{4})/edit-chair/$', EditChairFormPreview(EditChairForm), name='edit_chair'), url(r'^(?P\d{4})/edit-members/$', EditMembersFormPreview(EditMembersForm), name='edit_members'), url(r'^(?P\d{4})/edit-publickey/$', 'edit_publickey', name='edit_publickey'), - url(r'^(?P\d{4})/nominate/$', 'nominate', name='nominate'), ) diff --git a/ietf/nomcom/utils.py b/ietf/nomcom/utils.py index 2e6640923..3da455d9f 100644 --- a/ietf/nomcom/utils.py +++ b/ietf/nomcom/utils.py @@ -1,9 +1,15 @@ +from django.shortcuts import get_object_or_404 + from ietf.dbtemplate.models import DBTemplate MAIN_NOMCOM_TEMPLATE_PATH = '/nomcom/defaults/' -DEFAULT_NOMCOM_TEMPLATES = 'home.rst', 'email/inexistent_person.txt', 'email/new_nomination.txt', 'email/new_nominee.txt' -DEFAULT_QUESTIONNAIRE_TEMPLATE = 'position/questionnaire.txt' -DEFAULT_REQUIREMENTS_TEMPLATE = 'position/requirements.txt' +QUESTIONNAIRE_TEMPLATE = 'position/questionnaire.txt' +REQUIREMENTS_TEMPLATE = 'position/requirements.txt' +HOME_TEMPLATE = 'home.rst' +INEXISTENT_PERSON_TEMPLATE = 'email/inexistent_person.txt' +NOMINEE_EMAIL_TEMPLATE = 'email/new_nominee.txt' +NOMINATION_EMAIL_TEMPLATE = 'email/new_nomination.txt' +DEFAULT_NOMCOM_TEMPLATES = [HOME_TEMPLATE, INEXISTENT_PERSON_TEMPLATE, NOMINATION_EMAIL_TEMPLATE, NOMINEE_EMAIL_TEMPLATE] def initialize_templates_for_group(group): @@ -20,24 +26,31 @@ def initialize_templates_for_group(group): def initialize_questionnaire_for_position(position): - questionnaire_path = MAIN_NOMCOM_TEMPLATE_PATH + DEFAULT_QUESTIONNAIRE_TEMPLATE + questionnaire_path = MAIN_NOMCOM_TEMPLATE_PATH + QUESTIONNAIRE_TEMPLATE template = DBTemplate.objects.get(path=questionnaire_path) return DBTemplate.objects.create( group=position.nomcom.group, title=template.title + '[%s]' % position.name, - path='/nomcom/' + position.nomcom.group.acronym + '/' + str(position.id) + '/' + DEFAULT_QUESTIONNAIRE_TEMPLATE, + path='/nomcom/' + position.nomcom.group.acronym + '/' + str(position.id) + '/' + QUESTIONNAIRE_TEMPLATE, variables=template.variables, type_id=template.type_id, content=template.content) def initialize_requirements_for_position(position): - requirements_path = MAIN_NOMCOM_TEMPLATE_PATH + DEFAULT_REQUIREMENTS_TEMPLATE + requirements_path = MAIN_NOMCOM_TEMPLATE_PATH + REQUIREMENTS_TEMPLATE template = DBTemplate.objects.get(path=requirements_path) return DBTemplate.objects.create( group=position.nomcom.group, title=template.title + '[%s]' % position.name, - path='/nomcom/' + position.nomcom.group.acronym + '/' + str(position.id) + '/' + DEFAULT_REQUIREMENTS_TEMPLATE, + path='/nomcom/' + position.nomcom.group.acronym + '/' + str(position.id) + '/' + REQUIREMENTS_TEMPLATE, variables=template.variables, type_id=template.type_id, content=template.content) + + +def get_nomcom_by_year(year): + from ietf.nomcom.models import NomCom + return get_object_or_404(NomCom, + group__acronym__icontains=year, + group__state__slug='active') diff --git a/ietf/nomcom/views.py b/ietf/nomcom/views.py index f30b32e42..c98700796 100644 --- a/ietf/nomcom/views.py +++ b/ietf/nomcom/views.py @@ -1,17 +1,88 @@ -from django.shortcuts import get_object_or_404, render_to_response +from django.shortcuts import render_to_response from django.template import RequestContext from django.http import HttpResponseForbidden from django.contrib.auth.decorators import login_required +from django.template.loader import render_to_string +from ietf.nomcom.utils import get_nomcom_by_year, HOME_TEMPLATE from ietf.nomcom.forms import EditPublicKeyForm, NominateForm -from ietf.nomcom.models import NomCom + + +def index(request, year): + nomcom = get_nomcom_by_year(year) + home_template = '/nomcom/%s/%s' % (nomcom.group.acronym, HOME_TEMPLATE) + template = render_to_string(home_template, {}) + return render_to_response('nomcom/index.html', + {'nomcom': nomcom, + 'year': year, + 'selected': 'index', + 'template': template}, RequestContext(request)) + + +def requirements(request, year): + nomcom = get_nomcom_by_year(year) + return render_to_response('nomcom/requirements.html', + {'nomcom': nomcom, + 'year': year, + 'selected': 'requirements'}, RequestContext(request)) + + +def questionnaires(request, year): + nomcom = get_nomcom_by_year(year) + return render_to_response('nomcom/questionnaires.html', + {'nomcom': nomcom, + 'year': year, + 'selected': 'questionnaires'}, RequestContext(request)) + + +def questionnaire_detail(request, year, name): + nomcom = get_nomcom_by_year(year) + return render_to_response('nomcom/questionnaire_detail.html', + {'nomcom': nomcom, + 'year': year, + 'selected': 'questionnaires'}, RequestContext(request)) + + +def requirement_detail(request, year, name): + nomcom = get_nomcom_by_year(year) + return render_to_response('nomcom/requirement_detail.html', + {'nomcom': nomcom, + 'year': year, + 'selected': 'requirements'}, RequestContext(request)) + + +@login_required +def nominate(request, year): + nomcom = get_nomcom_by_year(year) + message = None + if request.method == 'POST': + form = NominateForm(data=request.POST, nomcom=nomcom, user=request.user) + if form.is_valid(): + form.save() + message = ('success', 'Your nomination has been registered. Thank you for the nomination.') + else: + form = NominateForm(nomcom=nomcom, user=request.user) + + return render_to_response('nomcom/nominate.html', + {'form': form, + 'message': message, + 'nomcom': nomcom, + 'year': year, + 'selected': 'nominate'}, RequestContext(request)) + + +@login_required +def comments(request, year): + nomcom = get_nomcom_by_year(year) + return render_to_response('nomcom/comments.html', + {'nomcom': nomcom, + 'year': year, + 'selected': 'comments'}, RequestContext(request)) @login_required def edit_publickey(request, year): - nomcom = get_object_or_404(NomCom, - group__acronym__icontains=year, - group__state__slug='active') + nomcom = get_nomcom_by_year(year) is_group_chair = nomcom.group.is_chair(request.user) if not is_group_chair: return HttpResponseForbidden("Must be group chair") @@ -32,22 +103,3 @@ def edit_publickey(request, year): {'form': form, 'group': nomcom.group, 'message': message}, RequestContext(request)) - - -@login_required -def nominate(request, year): - nomcom = get_object_or_404(NomCom, - group__acronym__icontains=year, - group__state__slug='active') - message = None - if request.method == 'POST': - form = NominateForm(data=request.POST, nomcom=nomcom, user=request.user) - if form.is_valid(): - form.save() - message = ('success', 'Your nomination has been registered. Thank you for the nomination.') - else: - form = NominateForm(nomcom=nomcom, user=request.user) - - return render_to_response('nomcom/nominate.html', - {'form': form, - 'message': message}, RequestContext(request)) diff --git a/ietf/templates/nomcom/comments.html b/ietf/templates/nomcom/comments.html new file mode 100644 index 000000000..f92a60d71 --- /dev/null +++ b/ietf/templates/nomcom/comments.html @@ -0,0 +1,3 @@ +{% extends "nomcom/nomcom_base.html" %} + +{% block title %} {{ nomcom }} - Provide comments{% endblock %} diff --git a/ietf/templates/nomcom/index.html b/ietf/templates/nomcom/index.html new file mode 100644 index 000000000..e4904ae69 --- /dev/null +++ b/ietf/templates/nomcom/index.html @@ -0,0 +1,7 @@ +{% extends "nomcom/nomcom_base.html" %} + +{% block subtitle %} - Home {% endblock %} + +{% block nomcom_content %} + {{ template|safe }} +{% endblock %} diff --git a/ietf/templates/nomcom/nomcom_base.html b/ietf/templates/nomcom/nomcom_base.html new file mode 100644 index 000000000..a60e4da12 --- /dev/null +++ b/ietf/templates/nomcom/nomcom_base.html @@ -0,0 +1,19 @@ +{% extends "base.html" %} + +{% block title %}Nomcom {{ year }}{% block subtitle %}{% endblock %}{% endblock %} + +{% block content %} + +

Nomcom {{ year }} Pages

+ +
+{% if selected == "index" %}Home{% else %}Home{% endif %} | +{% if selected == "nominate" %}Nominate{% else %}Nominate{% endif %} | +{% if selected == "requirements" %}Requirements{% else %}Requirements{% endif %} | +{% if selected == "questionnaires" %}Questionnaires{% else %}Questionnaires{% endif %} | +{% if selected == "comments" %}Provide Comments{% else %}Provide Comments{% endif %} +
+ +{% block nomcom_content %} +{% endblock %} +{% endblock %} diff --git a/ietf/templates/nomcom/nominate.html b/ietf/templates/nomcom/nominate.html index 9ce57e37d..328692457 100644 --- a/ietf/templates/nomcom/nominate.html +++ b/ietf/templates/nomcom/nominate.html @@ -1,9 +1,9 @@ -{% extends "base.html" %} +{% extends "nomcom/nomcom_base.html" %} -{% block title %}Nominate{% endblock %} +{% block subtitle %} - Nominate{% endblock %} -{% block content %} -

Nominate

+{% block nomcom_content %} +

Nominate

{% if message %}
{{ message.1 }}
diff --git a/ietf/templates/nomcom/questionnaires.html b/ietf/templates/nomcom/questionnaires.html new file mode 100644 index 000000000..8022e5c12 --- /dev/null +++ b/ietf/templates/nomcom/questionnaires.html @@ -0,0 +1,6 @@ +{% extends "nomcom/nomcom_base.html" %} + +{% block subtitle %} - Questionnaires {% endblock %} + +{% block nomcom_content %} +{% endblock %} diff --git a/ietf/templates/nomcom/requirements.html b/ietf/templates/nomcom/requirements.html new file mode 100644 index 000000000..28d2db6c0 --- /dev/null +++ b/ietf/templates/nomcom/requirements.html @@ -0,0 +1,6 @@ +{% extends "nomcom/nomcom_base.html" %} + +{% block subtitle %} - Requirements {% endblock %} + +{% block nomcom_content %} +{% endblock %} diff --git a/static/css/base2.css b/static/css/base2.css index 24c710db7..928c424e0 100644 --- a/static/css/base2.css +++ b/static/css/base2.css @@ -64,6 +64,16 @@ body { margin: 0; } .ietf-navbar #wgs .bd { background-color: #edf5ff; } .ietf-navbar #wgs > .bd { border: 0;} +.ietf-navset { + background:#214197 url(/images/yui/sprite.png) repeat-x left -1400px; + color:white; + border:1px solid black; + padding:4px; +} +.ietf-navset .selected { font-weight:bold; padding: 0 3px; } +.ietf-navset a, .ietf-navset a:visited { color: white; padding:0 3px; } + + .ietf-ballot .left { background: #edf5ff; width:160px; padding-left: 10px; } .ietf-ballot .right { padding-left: 15px; padding-right:15px; width:610px;padding-top:0px;} .ietf-ballot h2.ballot_ad { background: #2647A0; color:white; padding: 2px 4px; font-size: 108%; margin-top: 0;}