Expose views for concluded nomcoms. Close feedback and nomination. Initial work on factory-boy based testing. Partially addresses #1856
- Legacy-Id: 10520
This commit is contained in:
parent
2197259102
commit
e81b473282
10
ietf/group/factories.py
Normal file
10
ietf/group/factories.py
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import factory
|
||||||
|
|
||||||
|
from ietf.group.models import Group
|
||||||
|
|
||||||
|
class GroupFactory(factory.DjangoModelFactory):
|
||||||
|
class Meta:
|
||||||
|
model = Group
|
||||||
|
|
||||||
|
name = factory.Faker('sentence',nb_words=6)
|
||||||
|
acronym = factory.Faker('word')
|
|
@ -64,9 +64,9 @@ def has_role(user, role_names, *args, **kwargs):
|
||||||
"RG Secretary": Q(person=person,name="secr", group__type="rg", group__state__in=["active","proposed"]),
|
"RG Secretary": Q(person=person,name="secr", group__type="rg", group__state__in=["active","proposed"]),
|
||||||
"AG Secretary": Q(person=person,name="secr", group__type="ag", group__state__in=["active"]),
|
"AG Secretary": Q(person=person,name="secr", group__type="ag", group__state__in=["active"]),
|
||||||
"Team Chair": Q(person=person,name="chair", group__type="team", group__state="active"),
|
"Team Chair": Q(person=person,name="chair", group__type="team", group__state="active"),
|
||||||
"Nomcom Chair": Q(person=person, name="chair", group__type="nomcom", group__state="active", group__acronym__icontains=kwargs.get('year', '0000')),
|
"Nomcom Chair": Q(person=person, name="chair", group__type="nomcom", group__acronym__icontains=kwargs.get('year', '0000')),
|
||||||
"Nomcom Advisor": Q(person=person, name="advisor", group__type="nomcom", group__state="active", group__acronym__icontains=kwargs.get('year', '0000')),
|
"Nomcom Advisor": Q(person=person, name="advisor", group__type="nomcom", group__acronym__icontains=kwargs.get('year', '0000')),
|
||||||
"Nomcom": Q(person=person, group__type="nomcom", group__state="active", group__acronym__icontains=kwargs.get('year', '0000')),
|
"Nomcom": Q(person=person, group__type="nomcom", group__acronym__icontains=kwargs.get('year', '0000')),
|
||||||
"Liaison Manager": Q(person=person,name="liaiman",group__type="sdo",group__state="active", ),
|
"Liaison Manager": Q(person=person,name="liaiman",group__type="sdo",group__state="active", ),
|
||||||
"Authorized Individual": Q(person=person,name="auth",group__type="sdo",group__state="active", ),
|
"Authorized Individual": Q(person=person,name="auth",group__type="sdo",group__state="active", ),
|
||||||
}
|
}
|
||||||
|
|
125
ietf/nomcom/factories.py
Normal file
125
ietf/nomcom/factories.py
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
import factory
|
||||||
|
import random
|
||||||
|
|
||||||
|
from ietf.nomcom.models import NomCom, Position, Nominee, NomineePosition
|
||||||
|
from ietf.group.factories import GroupFactory
|
||||||
|
from ietf.person.factories import PersonFactory
|
||||||
|
|
||||||
|
import debug # pyflakes:ignore
|
||||||
|
|
||||||
|
cert = '''-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDHjCCAgagAwIBAgIJAKDCCjbQboJzMA0GCSqGSIb3DQEBCwUAMBMxETAPBgNV
|
||||||
|
BAMMCE5vbUNvbTE1MB4XDTE0MDQwNDIxMTQxNFoXDTE2MDQwMzIxMTQxNFowEzER
|
||||||
|
MA8GA1UEAwwITm9tQ29tMTUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
|
||||||
|
AQC2QXCsAitYSOgPYor77zQnEeHuVqlcuhpH1wpKB+N6WcScA5N3AnX9uZEFOt6M
|
||||||
|
cJ+MCiHECdqDlH6npQTJlpCpIVgAD4B6xzjRBRww8d3lClA/kKwsKzuX93RS0Uv3
|
||||||
|
0hAD6q9wjqK/m6vR5Y1SsvJYV0y+Yu5j9xUEsojMH7O3NlXWAYOb6oH+f/X7PX27
|
||||||
|
IhtiCwfICMmVWh/hKeXuFx6HSOcH3gZ6Tlk1llfDbE/ArpsZ6JmnLn73+64yqIoO
|
||||||
|
ZOc4JJUPrdsmbNwXoxQSQhrpwjN8NpSkQaJbHGB3G+OWvP4fpqcweFHxlEq1Hhef
|
||||||
|
uR9E6jc3qwxVQfwjbcq6N/4JAgMBAAGjdTBzMB0GA1UdDgQWBBTJow+TJynRWsTQ
|
||||||
|
LzoS861FGb/rxDAOBgNVHQ8BAf8EBAMCBLAwDwYDVR0TAQH/BAUwAwEB/zAcBgNV
|
||||||
|
HREEFTATgRFub21jb20xNUBpZXRmLm9yZzATBgNVHSUEDDAKBggrBgEFBQcDBDAN
|
||||||
|
BgkqhkiG9w0BAQsFAAOCAQEAJwLapB9u5N3iK6SCTqh+PVkigZeB2YMVBW8WA3Ut
|
||||||
|
iRPBj+jHWOpF5pzZHTOcNaAxDEG9lyIlcWqc93A24K/Gen11Tx0hO4FAPOG0+PP8
|
||||||
|
4lx7F6xeeyUNR44pInrB93G2q0jl+3wjZH8uhBKlGji4UTMpDPpEl6uiyQCbkMMm
|
||||||
|
Vr7HZH5Dv/lsjGHHf8uJO7+mcMh+tqxLn3DzPrm61OfeWdkoVX2pTz0imRQ3Es+8
|
||||||
|
I7zNMk+fNNaEEyPnEyHfuWq0uD/qKeP27NZIoINy6E3INQ5QaE2uc1nQULg5y7uJ
|
||||||
|
toX3j+FUe2UiUak3ACXdrOPSsFP0KRrFwuMnuHHXkGj/Uw==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
'''
|
||||||
|
|
||||||
|
key = '''-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC2QXCsAitYSOgP
|
||||||
|
Yor77zQnEeHuVqlcuhpH1wpKB+N6WcScA5N3AnX9uZEFOt6McJ+MCiHECdqDlH6n
|
||||||
|
pQTJlpCpIVgAD4B6xzjRBRww8d3lClA/kKwsKzuX93RS0Uv30hAD6q9wjqK/m6vR
|
||||||
|
5Y1SsvJYV0y+Yu5j9xUEsojMH7O3NlXWAYOb6oH+f/X7PX27IhtiCwfICMmVWh/h
|
||||||
|
KeXuFx6HSOcH3gZ6Tlk1llfDbE/ArpsZ6JmnLn73+64yqIoOZOc4JJUPrdsmbNwX
|
||||||
|
oxQSQhrpwjN8NpSkQaJbHGB3G+OWvP4fpqcweFHxlEq1HhefuR9E6jc3qwxVQfwj
|
||||||
|
bcq6N/4JAgMBAAECggEAb5SS4YwWc193S2v+QQ2KdVz6YEuINq/tRQw/TWGVACQT
|
||||||
|
PZzm3FaSXDsOsRAAjiSpWTgewgFyWVpBTGu4CZ73g8RZNvhGpWRwwW8KemCpg/8T
|
||||||
|
cEcnUYdKXdhuzAE9LETb7znwHM4Gj55DzCZopjfOLQ2Ne4XgAy2THaQcIjRKd6Bw
|
||||||
|
3mteJ2ityDj3iFN7cq9ntDzp+2BqLOi7AZmLntmUZxtkPCT6k5/dcKFYQW9Eb3bt
|
||||||
|
MON+BIYVzqhAijkP/cAWmbgZAP9EFng5PpE1lc/shl0W8eX4yvjNoMPRq3wphS4j
|
||||||
|
L16VncUeDep3vR0CECx7gnTfR0uCDEgKow50pzGQAQKBgQDaQWwK/o39zI3lCGzy
|
||||||
|
oSNJRNQJ/iZBkbbwpCCaka7VnBfd0ZH54VEWL3oMTkkWRSZtjsPAqT+ndwZitm0D
|
||||||
|
Kww9FUDMP7j/tMOwAUHYfjYFqFTn6ipkBuby9tbZtL7lgJO6Iu2Qk3afqADD0kcP
|
||||||
|
zRLxcYSLjrmp9NyUlNnpswR4CQKBgQDVxjwG/orCmiuyA1Bu4u1hdUD0w9CKnyjp
|
||||||
|
VTbkv8lxk5V3pYzms2Awb0X43W2OioYGBk5yw+9GCF//xCrfbGV7BLZnDTGShjkJ
|
||||||
|
8oTpLPGBsDSfaKVXE3Hko4LVLBMQIm0tDyuPD1Naia7ZknYn906skonEG8WgHUyp
|
||||||
|
c/BgkvzWAQKBgBdojuL6/FWtO8bFyZGYUMWJ+Uf9FzNPIpTatZh+aYcFj9W9pW9s
|
||||||
|
iBreCrQJLXOTBRUZC8u9G1Olw2yQ7k45rr1aazG83+WlCJv29o32s2qV7E1XYyaJ
|
||||||
|
SvniGZcN+K96w91h46Lu/fkPts1J309FinOU3kdtjmI5HfNdp6WWCrOpAoGBAMjc
|
||||||
|
TEaeIK8cwPWwG4E1A6pQy8mvu2Ckj4I+KSfh9FsdOpGDIdMas8SOqQZet7P5AFjk
|
||||||
|
0A0RgN8iu2DMZyQq62cdVG2bffqY1zs7fhrBueILOEaXwtMAWEFmSWYW1YqRbleq
|
||||||
|
K1luIvms6HdSIGcI/gk0XvG+zn/VR9ToNPHo6lwBAoGBAIrYGYPf+cjZ1V/tNqnL
|
||||||
|
IecEZb4Gkp1hVhOpNT4U+T2LROxrZtFxxsw2vuIRa5a5FtMbDq9Xyhkm0QppliBd
|
||||||
|
KQ38jTT0EaD2+vstTqL8vxupo25RQWV1XsmLL4pLbKnm2HnnwB3vEtsiokWKW0q0
|
||||||
|
Tdb0MiLc+r/zvx8oXtgDjDUa
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
|
'''
|
||||||
|
|
||||||
|
def nomcom_kwargs_for_year(year=None, *args, **kwargs):
|
||||||
|
if not year:
|
||||||
|
year = random.randint(1980,2100)
|
||||||
|
if 'group__state_id' not in kwargs:
|
||||||
|
kwargs['group__state_id']='active'
|
||||||
|
if 'group__acronym' not in kwargs:
|
||||||
|
kwargs['group__acronym'] = 'nomcom%d'%year
|
||||||
|
if 'group__name' not in kwargs:
|
||||||
|
kwargs['group__name'] = 'TEST VERSION of IAB/IESG Nominating Committee %d/%d'%(year,year+1)
|
||||||
|
return kwargs
|
||||||
|
|
||||||
|
|
||||||
|
class NomComFactory(factory.DjangoModelFactory):
|
||||||
|
class Meta:
|
||||||
|
model = NomCom
|
||||||
|
|
||||||
|
group = factory.SubFactory(GroupFactory,type_id='nomcom')
|
||||||
|
|
||||||
|
public_key = factory.django.FileField(data=cert)
|
||||||
|
|
||||||
|
@factory.post_generation
|
||||||
|
def populate_positions(self, create, extracted, **kwargs):
|
||||||
|
'''
|
||||||
|
Create a set of nominees and positions unless NomcomFactory is called
|
||||||
|
with populate_positions=False
|
||||||
|
'''
|
||||||
|
if extracted is None:
|
||||||
|
extracted = True
|
||||||
|
if create and extracted:
|
||||||
|
nominees = [Nominee.objects.create(nomcom=self, email=PersonFactory().email_set.first()) for i in range(2)]
|
||||||
|
positions = [PositionFactory(nomcom=self) for i in range(3)]
|
||||||
|
|
||||||
|
def npc(x,y):
|
||||||
|
return NomineePosition.objects.create(position=x,
|
||||||
|
nominee=y,
|
||||||
|
state_id='accepted')
|
||||||
|
# This gives us positions with 0, 1 and 2 nominees, and
|
||||||
|
# one person who's been nomminated for more than one position
|
||||||
|
npc(positions[0],nominees[0])
|
||||||
|
npc(positions[1],nominees[0])
|
||||||
|
npc(positions[1],nominees[1])
|
||||||
|
|
||||||
|
@factory.post_generation
|
||||||
|
def populate_personnel(self, create, extracted, **kwargs):
|
||||||
|
'''
|
||||||
|
Create a default set of role holders, unless the factory is called
|
||||||
|
with populate_personnel=False
|
||||||
|
'''
|
||||||
|
if extracted is None:
|
||||||
|
extracted = True
|
||||||
|
if create and extracted:
|
||||||
|
#roles= ['chair', 'advisor'] + ['member']*10
|
||||||
|
roles = ['chair', 'advisor', 'member']
|
||||||
|
for role in roles:
|
||||||
|
p = PersonFactory()
|
||||||
|
self.group.role_set.create(name_id=role,person=p,email=p.email_set.first())
|
||||||
|
|
||||||
|
class PositionFactory(factory.DjangoModelFactory):
|
||||||
|
class Meta:
|
||||||
|
model = Position
|
||||||
|
|
||||||
|
name = factory.Faker('sentence',nb_words=10)
|
||||||
|
description = factory.Faker('paragraph',nb_sentences=4)
|
||||||
|
is_open = True
|
||||||
|
|
|
@ -66,6 +66,14 @@ class NomCom(models.Model):
|
||||||
if created:
|
if created:
|
||||||
initialize_templates_for_group(self)
|
initialize_templates_for_group(self)
|
||||||
|
|
||||||
|
def year(self):
|
||||||
|
year = getattr(self,'_cached_year',None)
|
||||||
|
if year is None:
|
||||||
|
if self.group and self.group.acronym.startswith('nomcom'):
|
||||||
|
year = int(self.group.acronym[6:])
|
||||||
|
self._cached_year = year
|
||||||
|
return year
|
||||||
|
|
||||||
|
|
||||||
def delete_nomcom(sender, **kwargs):
|
def delete_nomcom(sender, **kwargs):
|
||||||
nomcom = kwargs.get('instance', None)
|
nomcom = kwargs.get('instance', None)
|
||||||
|
|
|
@ -30,6 +30,9 @@ from ietf.nomcom.forms import EditMembersForm, EditMembersFormPreview
|
||||||
from ietf.nomcom.utils import get_nomcom_by_year, get_or_create_nominee
|
from ietf.nomcom.utils import get_nomcom_by_year, get_or_create_nominee
|
||||||
from ietf.nomcom.management.commands.send_reminders import Command, is_time_to_send
|
from ietf.nomcom.management.commands.send_reminders import Command, is_time_to_send
|
||||||
|
|
||||||
|
from ietf.nomcom.factories import NomComFactory, nomcom_kwargs_for_year
|
||||||
|
from ietf.person.factories import PersonFactory
|
||||||
|
|
||||||
client_test_cert_files = None
|
client_test_cert_files = None
|
||||||
|
|
||||||
def get_cert_files():
|
def get_cert_files():
|
||||||
|
@ -920,3 +923,51 @@ class ReminderTest(TestCase):
|
||||||
self.assertEqual(len(outbox), messages_before + 1)
|
self.assertEqual(len(outbox), messages_before + 1)
|
||||||
self.assertTrue('nominee1@' in outbox[-1]['To'])
|
self.assertTrue('nominee1@' in outbox[-1]['To'])
|
||||||
|
|
||||||
|
class InactiveNomcomTests(TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.nc = NomComFactory.create(**nomcom_kwargs_for_year(group__state_id='conclude'))
|
||||||
|
self.plain_person = PersonFactory.create()
|
||||||
|
|
||||||
|
def test_feedback_closed(self):
|
||||||
|
for view in ['nomcom_public_feedback', 'nomcom_private_feedback']:
|
||||||
|
url = reverse(view, kwargs={'year': self.nc.year()})
|
||||||
|
who = self.plain_person if 'public' in view else self.nc.group.role_set.filter(name='member').first().person
|
||||||
|
login_testing_unauthorized(self, who.user.username, url)
|
||||||
|
response = self.client.get(url)
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
q = PyQuery(response.content)
|
||||||
|
self.assertTrue( '(Concluded)' in q('h1').text())
|
||||||
|
self.assertTrue( 'closed' in q('#instructions').text())
|
||||||
|
self.assertTrue( q('#nominees a') )
|
||||||
|
self.assertFalse( q('#nominees a[href]') )
|
||||||
|
|
||||||
|
url += "?nominee=%d&position=%d" % (self.nc.nominee_set.first().id, self.nc.nominee_set.first().nomineeposition_set.first().position.id)
|
||||||
|
response = self.client.get(url)
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
q = PyQuery(response.content)
|
||||||
|
self.assertFalse( q('#feedbackform'))
|
||||||
|
|
||||||
|
empty_outbox()
|
||||||
|
fb_before = self.nc.feedback_set.count()
|
||||||
|
test_data = {'comments': u'Test feedback view. Comments with accents äöåÄÖÅ éáíóú âêîôû ü àèìòù.',
|
||||||
|
'nominator_email': self.plain_person.email_set.first().address,
|
||||||
|
'confirmation': True}
|
||||||
|
response = self.client.post(url, test_data)
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
q = PyQuery(response.content)
|
||||||
|
self.assertTrue( 'closed' in q('#instructions').text())
|
||||||
|
self.assertEqual( len(outbox), 0 )
|
||||||
|
self.assertEqual( fb_before, self.nc.feedback_set.count() )
|
||||||
|
|
||||||
|
def test_nominations_closed(self):
|
||||||
|
for view in ['nomcom_public_nominate', 'nomcom_private_nominate']:
|
||||||
|
url = reverse(view, kwargs={'year': self.nc.year() })
|
||||||
|
who = self.plain_person if 'public' in view else self.nc.group.role_set.filter(name='member').first().person
|
||||||
|
login_testing_unauthorized(self, who.user.username, url)
|
||||||
|
response = self.client.get(url)
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
q = PyQuery(response.content)
|
||||||
|
self.assertTrue( '(Concluded)' in q('h1').text())
|
||||||
|
self.assertTrue( 'closed' in q('.alert-warning').text())
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,7 @@ def get_nomcom_by_year(year):
|
||||||
from ietf.nomcom.models import NomCom
|
from ietf.nomcom.models import NomCom
|
||||||
return get_object_or_404(NomCom,
|
return get_object_or_404(NomCom,
|
||||||
group__acronym__icontains=year,
|
group__acronym__icontains=year,
|
||||||
group__state__slug='active')
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_year_by_nomcom(nomcom):
|
def get_year_by_nomcom(nomcom):
|
||||||
|
|
|
@ -322,6 +322,14 @@ def nominate(request, year, public):
|
||||||
'year': year,
|
'year': year,
|
||||||
'selected': 'nominate'}, RequestContext(request))
|
'selected': 'nominate'}, RequestContext(request))
|
||||||
|
|
||||||
|
if nomcom.group.state_id == 'conclude':
|
||||||
|
message = ('warning', "Nominations to this Nomcom are closed.")
|
||||||
|
return render_to_response(template,
|
||||||
|
{'message': message,
|
||||||
|
'nomcom': nomcom,
|
||||||
|
'year': year,
|
||||||
|
'selected': 'nominate'}, RequestContext(request))
|
||||||
|
|
||||||
message = None
|
message = None
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
form = NominateForm(data=request.POST, nomcom=nomcom, user=request.user, public=public)
|
form = NominateForm(data=request.POST, nomcom=nomcom, user=request.user, public=public)
|
||||||
|
@ -355,11 +363,12 @@ def feedback(request, year, public):
|
||||||
has_publickey = nomcom.public_key and True or False
|
has_publickey = nomcom.public_key and True or False
|
||||||
nominee = None
|
nominee = None
|
||||||
position = None
|
position = None
|
||||||
selected_nominee = request.GET.get('nominee')
|
if nomcom.group.state_id != 'conclude':
|
||||||
selected_position = request.GET.get('position')
|
selected_nominee = request.GET.get('nominee')
|
||||||
if selected_nominee and selected_position:
|
selected_position = request.GET.get('position')
|
||||||
nominee = get_object_or_404(Nominee, id=selected_nominee)
|
if selected_nominee and selected_position:
|
||||||
position = get_object_or_404(Position, id=selected_position)
|
nominee = get_object_or_404(Nominee, id=selected_nominee)
|
||||||
|
position = get_object_or_404(Position, id=selected_position)
|
||||||
|
|
||||||
positions = Position.objects.get_by_nomcom(nomcom=nomcom).opened()
|
positions = Position.objects.get_by_nomcom(nomcom=nomcom).opened()
|
||||||
|
|
||||||
|
@ -379,7 +388,7 @@ def feedback(request, year, public):
|
||||||
})
|
})
|
||||||
|
|
||||||
message = None
|
message = None
|
||||||
if request.method == 'POST':
|
if nominee and position and request.method == 'POST':
|
||||||
form = FeedbackForm(data=request.POST,
|
form = FeedbackForm(data=request.POST,
|
||||||
nomcom=nomcom, user=request.user,
|
nomcom=nomcom, user=request.user,
|
||||||
public=public, position=position, nominee=nominee)
|
public=public, position=position, nominee=nominee)
|
||||||
|
|
56
ietf/person/factories.py
Normal file
56
ietf/person/factories.py
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
import factory
|
||||||
|
import faker
|
||||||
|
|
||||||
|
from unidecode import unidecode
|
||||||
|
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
from ietf.person.models import Person, Alias, Email
|
||||||
|
|
||||||
|
fake = faker.Factory.create()
|
||||||
|
|
||||||
|
class UserFactory(factory.DjangoModelFactory):
|
||||||
|
class Meta:
|
||||||
|
model = User
|
||||||
|
django_get_or_create = ('username',)
|
||||||
|
|
||||||
|
first_name = factory.Faker('first_name')
|
||||||
|
last_name = factory.Faker('last_name')
|
||||||
|
email = factory.LazyAttribute(lambda u: '%s.%s@%s'%(u.first_name,u.last_name,fake.domain_name()))
|
||||||
|
username = factory.LazyAttribute(lambda u: u.email)
|
||||||
|
|
||||||
|
@factory.post_generation
|
||||||
|
def set_password(self, create, extracted, **kwargs):
|
||||||
|
self.set_password( '%s+password' % self.username )
|
||||||
|
|
||||||
|
class PersonFactory(factory.DjangoModelFactory):
|
||||||
|
class Meta:
|
||||||
|
model = Person
|
||||||
|
|
||||||
|
user = factory.SubFactory(UserFactory)
|
||||||
|
name = factory.LazyAttribute(lambda p: '%s %s'%(p.user.first_name,p.user.last_name))
|
||||||
|
ascii = factory.LazyAttribute(lambda p: unidecode(p.name))
|
||||||
|
|
||||||
|
@factory.post_generation
|
||||||
|
def default_aliases(self, create, extracted, **kwargs):
|
||||||
|
make_alias = getattr(AliasFactory, 'create' if create else 'build')
|
||||||
|
make_alias(person=self,name=self.name)
|
||||||
|
make_alias(person=self,name=self.ascii)
|
||||||
|
|
||||||
|
@factory.post_generation
|
||||||
|
def default_emails(self, create, extracted, **kwargs):
|
||||||
|
make_email = getattr(EmailFactory, 'create' if create else 'build')
|
||||||
|
make_email(person=self,address=self.user.email)
|
||||||
|
|
||||||
|
class AliasFactory(factory.DjangoModelFactory):
|
||||||
|
class Meta:
|
||||||
|
model = Alias
|
||||||
|
django_get_or_create = ('name',)
|
||||||
|
|
||||||
|
name = factory.Faker('name')
|
||||||
|
|
||||||
|
class EmailFactory(factory.DjangoModelFactory):
|
||||||
|
class Meta:
|
||||||
|
model = Email
|
||||||
|
django_get_or_create = ('address',)
|
||||||
|
|
||||||
|
address = '%s.%s@%s' % (factory.Faker('first_name'),factory.Faker('last_name'),factory.Faker('domain_name'))
|
|
@ -9,8 +9,12 @@
|
||||||
|
|
||||||
{% block nomcom_content %}
|
{% block nomcom_content %}
|
||||||
{% origin %}
|
{% origin %}
|
||||||
<p class="alert alert-info">
|
<p id="instructions" class="alert alert-info">
|
||||||
Select a nominee from the list of nominees to the right to obtain a new feedback form.
|
{% if nomcom.group.state_id == 'conclude' %}
|
||||||
|
Feedback to this nomcom is closed.
|
||||||
|
{% else %}
|
||||||
|
Select a nominee from the list of nominees to the right to obtain a new feedback form.
|
||||||
|
{% endif %}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
{% if message %}
|
{% if message %}
|
||||||
|
@ -21,7 +25,7 @@
|
||||||
|
|
||||||
{% if nomcom|has_publickey %}
|
{% if nomcom|has_publickey %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-4 col-sm-push-8">
|
<div id="nominees" class="col-sm-4 col-sm-push-8">
|
||||||
<h3>Nominees</h3>
|
<h3>Nominees</h3>
|
||||||
|
|
||||||
{% for p in positions %}
|
{% for p in positions %}
|
||||||
|
@ -29,7 +33,7 @@
|
||||||
<h4>{{ p.name }}</h4>
|
<h4>{{ p.name }}</h4>
|
||||||
<div class="btn-group-vertical form-group">
|
<div class="btn-group-vertical form-group">
|
||||||
{% for np in p.nomineeposition_set.accepted.not_duplicated %}
|
{% for np in p.nomineeposition_set.accepted.not_duplicated %}
|
||||||
<a class="btn btn-default btn-xs" href="?nominee={{np.nominee.id}}&position={{ np.position.id}}">
|
<a class="btn btn-default btn-xs" {% if nomcom.group.state_id != 'conclude' %}href="?nominee={{np.nominee.id}}&position={{ np.position.id}}"{% endif %}>
|
||||||
{{ np.nominee }}
|
{{ np.nominee }}
|
||||||
{% add_num_nominations user np.position np.nominee %}
|
{% add_num_nominations user np.position np.nominee %}
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% origin %}
|
{% origin %}
|
||||||
|
|
||||||
<h1>NomCom {{ year }} <small>Private area {% if is_chair_task %}- Chair/Advisors only{% endif %}</small></h1>
|
<h1>NomCom {{ year }} {% if nomcom.group.state_id == 'conclude' %}(Concluded){% endif %} <small>Private area {% if is_chair_task %}- Chair/Advisors only{% endif %}</small></h1>
|
||||||
|
|
||||||
<ul class="nav nav-tabs" role="tablist">
|
<ul class="nav nav-tabs" role="tablist">
|
||||||
<li {% if selected == "index" %}class="active"{% endif %}><a href="{% url "nomcom_private_index" year %}">Nominees</a></li>
|
<li {% if selected == "index" %}class="active"{% endif %}><a href="{% url "nomcom_private_index" year %}">Nominees</a></li>
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% origin %}
|
{% origin %}
|
||||||
|
|
||||||
<h1>NomCom {{ year }}</h1>
|
<h1>NomCom {{ year }} {% if nomcom.group.state_id == 'conclude' %}(Concluded){% endif %}</h1>
|
||||||
|
|
||||||
<ul class="nav nav-tabs" role="tablist">
|
<ul class="nav nav-tabs" role="tablist">
|
||||||
<li {% if selected == "index" %}class="active"{% endif %}><a href="{% url "nomcom_year_index" year %}">Home</a></li>
|
<li {% if selected == "index" %}class="active"{% endif %}><a href="{% url "nomcom_year_index" year %}">Home</a></li>
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
<p class="alert alert-{{ message.0 }}">{{ message.1 }}</p>
|
<p class="alert alert-{{ message.0 }}">{{ message.1 }}</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if nomcom|has_publickey %}
|
{% if form %}
|
||||||
|
|
||||||
<form id="nominate-form" method="post">
|
<form id="nominate-form" method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
{% bootstrap_messages %}
|
{% bootstrap_messages %}
|
||||||
|
|
||||||
{% if nomcom|has_publickey %}
|
{% if form %}
|
||||||
<form id="nominate-form" method="post">
|
<form id="nominate-form" method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{% bootstrap_form form %}
|
{% bootstrap_form form %}
|
||||||
|
|
|
@ -25,3 +25,5 @@ six>=1.8.0
|
||||||
wsgiref>=0.1.2
|
wsgiref>=0.1.2
|
||||||
xml2rfc>=2.5.0
|
xml2rfc>=2.5.0
|
||||||
django>=1.7.10,<1.8
|
django>=1.7.10,<1.8
|
||||||
|
factory-boy>=2.6.0
|
||||||
|
Unidecode>=0.4.18
|
||||||
|
|
Loading…
Reference in a new issue