Allow people to volunteer for NomCom via the datatracker. Commit ready for merge.
- Legacy-Id: 19104
This commit is contained in:
parent
c8ed251ae3
commit
86102b9980
|
@ -39,7 +39,7 @@ def permission_names_to_objects(names):
|
|||
result.append(Permission.objects.get(content_type__app_label=app_label,
|
||||
codename=codename))
|
||||
except Permission.DoesNotExist:
|
||||
print "NO SUCH PERMISSION: %s, %s" % (app_label, codename)
|
||||
print ("NO SUCH PERMISSION: %s, %s" % (app_label, codename))
|
||||
raise
|
||||
|
||||
return result
|
||||
|
@ -61,6 +61,7 @@ def main():
|
|||
'group.add_groupevent','group.change_groupevent','group.delete_groupevent',
|
||||
'iesg.add_telechatagendaitem','iesg.change_telechatagendaitem','iesg.delete_telechatagendaitem',
|
||||
'iesg.add_telechatdate','iesg.change_telechatdate','iesg.delete_telechatdate',
|
||||
'liaisons.add_liaisonstatementgroupcontacts', 'liaisons.change_liaisonstatementgroupcontacts', 'liaisons.delete_liaisonstatementgroupcontacts',
|
||||
'mailinglists.add_list','mailinglists.change_list','mailinglists.delete_list',
|
||||
'mailtrigger.add_mailtrigger','mailtrigger.change_mailtrigger','mailtrigger.delete_mailtrigger',
|
||||
'mailtrigger.add_recipient','mailtrigger.change_recipient','mailtrigger.delete_recipient',
|
||||
|
@ -71,6 +72,7 @@ def main():
|
|||
'meeting.add_urlresource','meeting.change_urlresource','meeting.delete_urlresource',
|
||||
'message.add_announcementfrom','message.change_announcementfrom','message.delete_announcementfrom',
|
||||
'nomcom.add_nomcom','nomcom.change_nomcom','nomcom.delete_nomcom',
|
||||
'nomcom.add_volunteer','nomcom.change_volunteer','nomcom.delete_volunteer',
|
||||
'person.add_person','person.change_person','person.delete_person',
|
||||
'person.add_alias','person.change_alias','person.delete_alias',
|
||||
'person.add_email','person.change_email','person.delete_email',
|
||||
|
|
|
@ -1097,7 +1097,7 @@ class RegenerateLastCallTestCase(TestCase):
|
|||
lc_text = draft.latest_event(WriteupDocEvent, type="changed_last_call_text").text
|
||||
self.assertTrue("contains these normative down" in lc_text)
|
||||
self.assertTrue("rfc6666" in lc_text)
|
||||
self.assertTrue("Independent Submission Editor stream" in lc_text)
|
||||
self.assertTrue("Independent Submission" in lc_text)
|
||||
|
||||
draft.relateddocument_set.create(target=rfc.docalias.get(name='rfc6666'),relationship_id='downref-approval')
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ from ietf.group.models import Group, Role, RoleName
|
|||
from ietf.ietfauth.htpasswd import update_htpasswd_file
|
||||
from ietf.mailinglists.models import Subscribed
|
||||
from ietf.meeting.factories import MeetingFactory
|
||||
from ietf.nomcom.factories import NomComFactory
|
||||
from ietf.person.factories import PersonFactory, EmailFactory
|
||||
from ietf.person.models import Person, Email, PersonalApiKey
|
||||
from ietf.review.factories import ReviewRequestFactory, ReviewAssignmentFactory
|
||||
|
@ -333,6 +334,33 @@ class IetfAuthTests(TestCase):
|
|||
self.assertEqual(updated_roles[0].email_id, new_email_address)
|
||||
|
||||
|
||||
def test_nomcom_dressing_on_profile(self):
|
||||
url = urlreverse('ietf.ietfauth.views.profile')
|
||||
|
||||
nobody = PersonFactory()
|
||||
login_testing_unauthorized(self, nobody.user.username, url)
|
||||
r = self.client.get(url)
|
||||
self.assertEqual(r.status_code,200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertFalse(q('#volunteer-button'))
|
||||
self.assertFalse(q('#volunteered'))
|
||||
|
||||
year = datetime.date.today().year
|
||||
nomcom = NomComFactory(group__acronym=f'nomcom{year}',is_accepting_volunteers=True)
|
||||
r = self.client.get(url)
|
||||
self.assertEqual(r.status_code,200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertTrue(q('#volunteer-button'))
|
||||
self.assertFalse(q('#volunteered'))
|
||||
|
||||
nomcom.volunteer_set.create(person=nobody)
|
||||
r = self.client.get(url)
|
||||
self.assertEqual(r.status_code,200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertFalse(q('#volunteer-button'))
|
||||
self.assertTrue(q('#volunteered'))
|
||||
|
||||
|
||||
def test_reset_password(self):
|
||||
url = urlreverse(ietf.ietfauth.views.password_reset)
|
||||
|
||||
|
|
|
@ -67,6 +67,7 @@ from ietf.ietfauth.htpasswd import update_htpasswd_file
|
|||
from ietf.ietfauth.utils import role_required, has_role
|
||||
from ietf.mailinglists.models import Subscribed, Whitelisted
|
||||
from ietf.name.models import ExtResourceName
|
||||
from ietf.nomcom.models import NomCom
|
||||
from ietf.person.models import Person, Email, Alias, PersonalApiKey, PERSON_API_KEY_VALUES
|
||||
from ietf.review.models import ReviewerSettings, ReviewWish, ReviewAssignment
|
||||
from ietf.review.utils import unavailable_periods_to_list, get_default_filter_re
|
||||
|
@ -210,6 +211,14 @@ def profile(request):
|
|||
emails = Email.objects.filter(person=person).exclude(address__startswith='unknown-email-').order_by('-active','-time')
|
||||
new_email_forms = []
|
||||
|
||||
nc = NomCom.objects.filter(group__acronym__icontains=Date.today().year).first()
|
||||
if nc and nc.volunteer_set.filter(person=person).exists():
|
||||
volunteer_status = 'volunteered'
|
||||
elif nc and nc.is_accepting_volunteers:
|
||||
volunteer_status = 'allow'
|
||||
else:
|
||||
volunteer_status = 'deny'
|
||||
|
||||
if request.method == 'POST':
|
||||
person_form = get_person_form(request.POST, instance=person)
|
||||
for r in roles:
|
||||
|
@ -287,6 +296,8 @@ def profile(request):
|
|||
'roles': roles,
|
||||
'emails': emails,
|
||||
'new_email_forms': new_email_forms,
|
||||
'nomcom': nc,
|
||||
'volunteer_status': volunteer_status,
|
||||
'settings':settings,
|
||||
})
|
||||
|
||||
|
|
|
@ -2499,10 +2499,10 @@
|
|||
"is_schedulable": true,
|
||||
"material_types": "[\n \"slides\"\n]",
|
||||
"matman_roles": "[\n \"chair\",\n \"lead\",\n \"delegate\",\n \"matman\"\n]",
|
||||
"need_parent": false,
|
||||
"parent_types": [
|
||||
"ietf"
|
||||
],
|
||||
"need_parent": false,
|
||||
"req_subm_approval": true,
|
||||
"role_order": "[\n \"chair\",\n \"lead\",\n \"delegate\",\n \"matman\"\n]",
|
||||
"show_on_agenda": true
|
||||
|
@ -2536,8 +2536,8 @@
|
|||
"is_schedulable": false,
|
||||
"material_types": "[\n \"slides\"\n]",
|
||||
"matman_roles": "[\n \"chair\"\n]",
|
||||
"parent_types": [],
|
||||
"need_parent": false,
|
||||
"parent_types": [],
|
||||
"req_subm_approval": false,
|
||||
"role_order": "[\n \"chair\"\n]",
|
||||
"show_on_agenda": false
|
||||
|
@ -2571,11 +2571,11 @@
|
|||
"is_schedulable": true,
|
||||
"material_types": "[\n \"slides\"\n]",
|
||||
"matman_roles": "[\n \"ad\",\n \"chair\",\n \"delegate\",\n \"secr\"\n]",
|
||||
"need_parent": false,
|
||||
"parent_types": [
|
||||
"area",
|
||||
"ietf"
|
||||
],
|
||||
"need_parent": false,
|
||||
"req_subm_approval": true,
|
||||
"role_order": "[\n \"chair\",\n \"secr\"\n]",
|
||||
"show_on_agenda": true
|
||||
|
@ -2609,10 +2609,10 @@
|
|||
"is_schedulable": false,
|
||||
"material_types": "[\n \"slides\"\n]",
|
||||
"matman_roles": "[\n \"ad\",\n \"chair\",\n \"delegate\",\n \"secr\"\n]",
|
||||
"need_parent": true,
|
||||
"parent_types": [
|
||||
"ietf"
|
||||
],
|
||||
"need_parent": true,
|
||||
"req_subm_approval": true,
|
||||
"role_order": "[\n \"chair\",\n \"secr\"\n]",
|
||||
"show_on_agenda": false
|
||||
|
@ -2646,10 +2646,10 @@
|
|||
"is_schedulable": false,
|
||||
"material_types": "[\n \"slides\"\n]",
|
||||
"matman_roles": "[\n \"ad\",\n \"chair\",\n \"delegate\",\n \"secr\"\n]",
|
||||
"need_parent": true,
|
||||
"parent_types": [
|
||||
"area"
|
||||
],
|
||||
"need_parent": true,
|
||||
"req_subm_approval": true,
|
||||
"role_order": "[\n \"chair\",\n \"secr\"\n]",
|
||||
"show_on_agenda": false
|
||||
|
@ -2683,10 +2683,10 @@
|
|||
"is_schedulable": false,
|
||||
"material_types": "[\n \"slides\"\n]",
|
||||
"matman_roles": "[\n \"chair\",\n \"delegate\"\n]",
|
||||
"need_parent": false,
|
||||
"parent_types": [
|
||||
"ietf"
|
||||
],
|
||||
"need_parent": false,
|
||||
"req_subm_approval": true,
|
||||
"role_order": "[\n \"chair\",\n \"secr\"\n]",
|
||||
"show_on_agenda": true
|
||||
|
@ -2720,8 +2720,8 @@
|
|||
"is_schedulable": false,
|
||||
"material_types": "[\n \"slides\"\n]",
|
||||
"matman_roles": "[\n \"chair\"\n]",
|
||||
"parent_types": [],
|
||||
"need_parent": false,
|
||||
"parent_types": [],
|
||||
"req_subm_approval": false,
|
||||
"role_order": "[\n \"chair\"\n]",
|
||||
"show_on_agenda": false
|
||||
|
@ -2755,8 +2755,8 @@
|
|||
"is_schedulable": false,
|
||||
"material_types": "\"[]\"",
|
||||
"matman_roles": "[\n \"chair\",\n \"delegate\",\n \"member\"\n]",
|
||||
"parent_types": [],
|
||||
"need_parent": false,
|
||||
"parent_types": [],
|
||||
"req_subm_approval": true,
|
||||
"role_order": "[\n \"chair\",\n \"delegate\",\n \"member\"\n]",
|
||||
"show_on_agenda": false
|
||||
|
@ -2790,10 +2790,10 @@
|
|||
"is_schedulable": false,
|
||||
"material_types": "[\n \"slides\"\n]",
|
||||
"matman_roles": "[\n \"chair\",\n \"delegate\"\n]",
|
||||
"need_parent": false,
|
||||
"parent_types": [
|
||||
"ietf"
|
||||
],
|
||||
"need_parent": false,
|
||||
"req_subm_approval": true,
|
||||
"role_order": "[\n \"chair\",\n \"secr\"\n]",
|
||||
"show_on_agenda": false
|
||||
|
@ -2827,10 +2827,10 @@
|
|||
"is_schedulable": false,
|
||||
"material_types": "[\n \"slides\"\n]",
|
||||
"matman_roles": "[]",
|
||||
"need_parent": true,
|
||||
"parent_types": [
|
||||
"area"
|
||||
],
|
||||
"need_parent": true,
|
||||
"req_subm_approval": false,
|
||||
"role_order": "[\n \"chair\",\n \"secr\"\n]",
|
||||
"show_on_agenda": false
|
||||
|
@ -2864,10 +2864,10 @@
|
|||
"is_schedulable": false,
|
||||
"material_types": "[\n \"slides\"\n]",
|
||||
"matman_roles": "[\n \"chair\",\n \"delegate\",\n \"secr\"\n]",
|
||||
"need_parent": false,
|
||||
"parent_types": [
|
||||
"irtf"
|
||||
],
|
||||
"need_parent": false,
|
||||
"req_subm_approval": true,
|
||||
"role_order": "[\n \"chair\",\n \"secr\"\n]",
|
||||
"show_on_agenda": false
|
||||
|
@ -2901,8 +2901,8 @@
|
|||
"is_schedulable": false,
|
||||
"material_types": "[\n \"slides\"\n]",
|
||||
"matman_roles": "[\n \"chair\",\n \"delegate\"\n]",
|
||||
"parent_types": [],
|
||||
"need_parent": false,
|
||||
"parent_types": [],
|
||||
"req_subm_approval": true,
|
||||
"role_order": "[\n \"chair\",\n \"delegate\"\n]",
|
||||
"show_on_agenda": false
|
||||
|
@ -2936,10 +2936,10 @@
|
|||
"is_schedulable": false,
|
||||
"material_types": "[\n \"slides\"\n]",
|
||||
"matman_roles": "[\n \"chair\",\n \"secr\"\n]",
|
||||
"need_parent": false,
|
||||
"parent_types": [
|
||||
"isoc"
|
||||
],
|
||||
"need_parent": false,
|
||||
"req_subm_approval": true,
|
||||
"role_order": "[\n \"chair\",\n \"secr\"\n]",
|
||||
"show_on_agenda": false
|
||||
|
@ -2973,10 +2973,10 @@
|
|||
"is_schedulable": false,
|
||||
"material_types": "[\n \"slides\"\n]",
|
||||
"matman_roles": "[\n \"chair\"\n]",
|
||||
"need_parent": false,
|
||||
"parent_types": [
|
||||
"area"
|
||||
],
|
||||
"need_parent": false,
|
||||
"req_subm_approval": true,
|
||||
"role_order": "[\n \"chair\",\n \"member\",\n \"advisor\"\n]",
|
||||
"show_on_agenda": false
|
||||
|
@ -3010,10 +3010,10 @@
|
|||
"is_schedulable": false,
|
||||
"material_types": "[\n \"slides\"\n]",
|
||||
"matman_roles": "[\n \"lead\",\n \"chair\",\n \"secr\"\n]",
|
||||
"need_parent": false,
|
||||
"parent_types": [
|
||||
"ietf"
|
||||
],
|
||||
"need_parent": false,
|
||||
"req_subm_approval": false,
|
||||
"role_order": "[\n \"lead\",\n \"chair\",\n \"secr\"\n]",
|
||||
"show_on_agenda": false
|
||||
|
@ -3047,10 +3047,10 @@
|
|||
"is_schedulable": true,
|
||||
"material_types": "[\n \"slides\"\n]",
|
||||
"matman_roles": "[\n \"chair\",\n \"delegate\",\n \"secr\"\n]",
|
||||
"need_parent": false,
|
||||
"parent_types": [
|
||||
"irtf"
|
||||
],
|
||||
"need_parent": false,
|
||||
"req_subm_approval": true,
|
||||
"role_order": "[\n \"chair\",\n \"secr\"\n]",
|
||||
"show_on_agenda": true
|
||||
|
@ -3063,7 +3063,7 @@
|
|||
"about_page": "ietf.group.views.group_about",
|
||||
"acts_like_wg": false,
|
||||
"admin_roles": "[\n \"chair\",\n \"secr\"\n]",
|
||||
"agenda_type": null,
|
||||
"agenda_type": "ietf",
|
||||
"create_wiki": true,
|
||||
"custom_group_roles": true,
|
||||
"customize_workflow": false,
|
||||
|
@ -3076,7 +3076,7 @@
|
|||
"has_chartering_process": false,
|
||||
"has_default_jabber": false,
|
||||
"has_documents": false,
|
||||
"has_meetings": false,
|
||||
"has_meetings": true,
|
||||
"has_milestones": false,
|
||||
"has_nonsession_materials": false,
|
||||
"has_reviews": true,
|
||||
|
@ -3084,10 +3084,10 @@
|
|||
"is_schedulable": false,
|
||||
"material_types": "[\n \"slides\"\n]",
|
||||
"matman_roles": "[\n \"ad\",\n \"secr\"\n]",
|
||||
"need_parent": true,
|
||||
"parent_types": [
|
||||
"area"
|
||||
],
|
||||
"need_parent": true,
|
||||
"req_subm_approval": true,
|
||||
"role_order": "[\n \"chair\",\n \"secr\"\n]",
|
||||
"show_on_agenda": false
|
||||
|
@ -3121,8 +3121,8 @@
|
|||
"is_schedulable": false,
|
||||
"material_types": "[\n \"slides\"\n]",
|
||||
"matman_roles": "[]",
|
||||
"parent_types": [],
|
||||
"need_parent": false,
|
||||
"parent_types": [],
|
||||
"req_subm_approval": true,
|
||||
"role_order": "[\n \"chair\",\n \"secr\"\n]",
|
||||
"show_on_agenda": false
|
||||
|
@ -3156,10 +3156,10 @@
|
|||
"is_schedulable": true,
|
||||
"material_types": "[\n \"slides\"\n]",
|
||||
"matman_roles": "[\n \"chair\",\n \"delegate\",\n \"secr\"\n]",
|
||||
"need_parent": true,
|
||||
"parent_types": [
|
||||
"irtf"
|
||||
],
|
||||
"need_parent": true,
|
||||
"req_subm_approval": true,
|
||||
"role_order": "[\n \"chair\",\n \"delegate\",\n \"secr\"\n]",
|
||||
"show_on_agenda": true
|
||||
|
@ -3193,11 +3193,11 @@
|
|||
"is_schedulable": false,
|
||||
"material_types": "[\n \"slides\"\n]",
|
||||
"matman_roles": "[]",
|
||||
"need_parent": false,
|
||||
"parent_types": [
|
||||
"area",
|
||||
"sdo"
|
||||
],
|
||||
"need_parent": false,
|
||||
"req_subm_approval": true,
|
||||
"role_order": "[\n \"liaiman\"\n]",
|
||||
"show_on_agenda": false
|
||||
|
@ -3231,10 +3231,10 @@
|
|||
"is_schedulable": false,
|
||||
"material_types": "[\n \"slides\"\n]",
|
||||
"matman_roles": "[\n \"chair\",\n \"matman\"\n]",
|
||||
"need_parent": false,
|
||||
"parent_types": [
|
||||
"area"
|
||||
],
|
||||
"need_parent": false,
|
||||
"req_subm_approval": false,
|
||||
"role_order": "[\n \"chair\",\n \"member\",\n \"matman\"\n]",
|
||||
"show_on_agenda": false
|
||||
|
@ -3268,10 +3268,10 @@
|
|||
"is_schedulable": true,
|
||||
"material_types": "[\n \"slides\"\n]",
|
||||
"matman_roles": "[\n \"ad\",\n \"chair\",\n \"delegate\",\n \"secr\"\n]",
|
||||
"need_parent": false,
|
||||
"parent_types": [
|
||||
"area"
|
||||
],
|
||||
"need_parent": false,
|
||||
"req_subm_approval": true,
|
||||
"role_order": "[\n \"chair\",\n \"secr\",\n \"delegate\"\n]",
|
||||
"show_on_agenda": true
|
||||
|
@ -4165,6 +4165,7 @@
|
|||
"fields": {
|
||||
"cc": [
|
||||
"liaison_cc",
|
||||
"liaison_coordinators",
|
||||
"liaison_response_contacts",
|
||||
"liaison_technical_contacts"
|
||||
],
|
||||
|
@ -5503,6 +5504,14 @@
|
|||
"model": "mailtrigger.recipient",
|
||||
"pk": "liaison_cc"
|
||||
},
|
||||
{
|
||||
"fields": {
|
||||
"desc": "The IAB liaison coordination team members",
|
||||
"template": "<liaison-coordination@iab.org>"
|
||||
},
|
||||
"model": "mailtrigger.recipient",
|
||||
"pk": "liaison_coordinators"
|
||||
},
|
||||
{
|
||||
"fields": {
|
||||
"desc": "The assigned liaison manager for an external group ",
|
||||
|
@ -10003,6 +10012,7 @@
|
|||
"auth",
|
||||
"aut-appr",
|
||||
"grp-appr",
|
||||
"ad-appr",
|
||||
"manual",
|
||||
"cancel"
|
||||
],
|
||||
|
@ -12050,7 +12060,7 @@
|
|||
"fields": {
|
||||
"desc": "",
|
||||
"name": "Liaison CC Contact",
|
||||
"order": 0,
|
||||
"order": 9,
|
||||
"used": true
|
||||
},
|
||||
"model": "name.rolename",
|
||||
|
@ -12060,7 +12070,7 @@
|
|||
"fields": {
|
||||
"desc": "",
|
||||
"name": "Liaison Contact",
|
||||
"order": 0,
|
||||
"order": 8,
|
||||
"used": true
|
||||
},
|
||||
"model": "name.rolename",
|
||||
|
@ -12488,7 +12498,7 @@
|
|||
},
|
||||
{
|
||||
"fields": {
|
||||
"desc": "IAB stream",
|
||||
"desc": "Internet Architecture Board (IAB)",
|
||||
"name": "IAB",
|
||||
"order": 4,
|
||||
"used": true
|
||||
|
@ -12498,7 +12508,7 @@
|
|||
},
|
||||
{
|
||||
"fields": {
|
||||
"desc": "IETF stream",
|
||||
"desc": "Internet Engineering Task Force (IETF)",
|
||||
"name": "IETF",
|
||||
"order": 1,
|
||||
"used": true
|
||||
|
@ -12508,7 +12518,7 @@
|
|||
},
|
||||
{
|
||||
"fields": {
|
||||
"desc": "IRTF Stream",
|
||||
"desc": "Internet Research Task Force (IRTF)",
|
||||
"name": "IRTF",
|
||||
"order": 3,
|
||||
"used": true
|
||||
|
@ -12518,7 +12528,7 @@
|
|||
},
|
||||
{
|
||||
"fields": {
|
||||
"desc": "Independent Submission Editor stream",
|
||||
"desc": "Independent Submission",
|
||||
"name": "ISE",
|
||||
"order": 2,
|
||||
"used": true
|
||||
|
@ -15243,9 +15253,9 @@
|
|||
"fields": {
|
||||
"command": "xym",
|
||||
"switch": "--version",
|
||||
"time": "2020-11-14T00:10:15.888",
|
||||
"time": "2021-06-08T00:12:46.324",
|
||||
"used": true,
|
||||
"version": "xym 0.4.8"
|
||||
"version": "xym 0.5"
|
||||
},
|
||||
"model": "utils.versioninfo",
|
||||
"pk": 1
|
||||
|
@ -15254,7 +15264,7 @@
|
|||
"fields": {
|
||||
"command": "pyang",
|
||||
"switch": "--version",
|
||||
"time": "2020-11-14T00:10:17.069",
|
||||
"time": "2021-06-08T00:12:48.137",
|
||||
"used": true,
|
||||
"version": "pyang 2.4.0"
|
||||
},
|
||||
|
@ -15265,7 +15275,7 @@
|
|||
"fields": {
|
||||
"command": "yanglint",
|
||||
"switch": "--version",
|
||||
"time": "2020-11-14T00:10:17.405",
|
||||
"time": "2021-06-08T00:12:48.465",
|
||||
"used": true,
|
||||
"version": "yanglint SO 1.6.7"
|
||||
},
|
||||
|
@ -15276,9 +15286,9 @@
|
|||
"fields": {
|
||||
"command": "xml2rfc",
|
||||
"switch": "--version",
|
||||
"time": "2020-11-14T00:10:19.405",
|
||||
"time": "2021-06-08T00:12:51.318",
|
||||
"used": true,
|
||||
"version": "xml2rfc 3.4.0"
|
||||
"version": "xml2rfc 3.8.0"
|
||||
},
|
||||
"model": "utils.versioninfo",
|
||||
"pk": 4
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
# Copyright The IETF Trust 2012-2020, All Rights Reserved
|
||||
# Copyright The IETF Trust 2012-2021, All Rights Reserved
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
from django.contrib import admin
|
||||
|
||||
from ietf.nomcom.models import ( ReminderDates, NomCom, Nomination, Nominee, NomineePosition,
|
||||
Position, Feedback, FeedbackLastSeen, TopicFeedbackLastSeen)
|
||||
Position, Feedback, FeedbackLastSeen, TopicFeedbackLastSeen,
|
||||
Volunteer, )
|
||||
|
||||
|
||||
class ReminderDatesAdmin(admin.ModelAdmin):
|
||||
|
@ -68,4 +69,10 @@ class TopicFeedbackLastSeenAdmin(admin.ModelAdmin):
|
|||
raw_id_fields = ['reviewer']
|
||||
admin.site.register(TopicFeedbackLastSeen, TopicFeedbackLastSeenAdmin)
|
||||
|
||||
class VolunteerAdmin(admin.ModelAdmin):
|
||||
list_display = ['nomcom','person','affiliation']
|
||||
list_filter = ['nomcom']
|
||||
raw_id_fields = ['person']
|
||||
admin.site.register(Volunteer, VolunteerAdmin)
|
||||
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ from django.forms.widgets import FileInput
|
|||
from ietf.dbtemplate.forms import DBTemplateForm
|
||||
from ietf.name.models import FeedbackTypeName, NomineePositionStateName
|
||||
from ietf.nomcom.models import ( NomCom, Nomination, Nominee, NomineePosition,
|
||||
Position, Feedback, ReminderDates, Topic )
|
||||
Position, Feedback, ReminderDates, Topic, Volunteer )
|
||||
from ietf.nomcom.utils import (NOMINATION_RECEIPT_TEMPLATE, FEEDBACK_RECEIPT_TEMPLATE,
|
||||
get_user_email, validate_private_key, validate_public_key,
|
||||
make_nomineeposition, make_nomineeposition_for_newperson,
|
||||
|
@ -833,3 +833,22 @@ class EditNomineeForm(forms.ModelForm):
|
|||
class NominationResponseCommentForm(forms.Form):
|
||||
comments = forms.CharField(widget=forms.Textarea,required=False,help_text="Any comments provided will be encrypted and will only be visible to the NomCom.", strip=False)
|
||||
|
||||
class NomcomVolunteerMultipleChoiceField(forms.ModelMultipleChoiceField):
|
||||
def label_from_instance(self, obj):
|
||||
year = obj.year()
|
||||
return f'Volunteer for the {year}/{year+1} Nominating Committee'
|
||||
|
||||
class VolunteerForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Volunteer
|
||||
fields = ('affiliation',)
|
||||
|
||||
nomcoms = NomcomVolunteerMultipleChoiceField(queryset=NomCom.objects.none(),widget=forms.CheckboxSelectMultiple)
|
||||
field_order = ('nomcoms','affiliation')
|
||||
|
||||
def __init__(self, person, *args, **kargs):
|
||||
super().__init__(*args, **kargs)
|
||||
self.fields['nomcoms'].queryset = NomCom.objects.filter(is_accepting_volunteers=True).exclude(volunteer__person=person)
|
||||
self.fields['nomcoms'].help_text = 'You may volunteer even if the datatracker does not currently calculate that you are eligible. Eligibility will be assessed when the selection process is performed.'
|
||||
self.fields['affiliation'].help_text = 'Affiliation to show in the volunteer list'
|
||||
self.fields['affiliation'].required = True
|
||||
|
|
30
ietf/nomcom/migrations/0011_volunteers.py
Normal file
30
ietf/nomcom/migrations/0011_volunteers.py
Normal file
|
@ -0,0 +1,30 @@
|
|||
# Generated by Django 2.2.24 on 2021-06-09 12:15
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import ietf.utils.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('person', '0019_auto_20210604_1443'),
|
||||
('nomcom', '0010_nomcom_first_call_for_volunteers'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='nomcom',
|
||||
name='is_accepting_volunteers',
|
||||
field=models.BooleanField(default=False, help_text='Is this nomcom is currently accepting volunteers?', verbose_name='Accepting volunteers'),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Volunteer',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('affiliation', models.CharField(blank=True, max_length=255)),
|
||||
('nomcom', ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='nomcom.NomCom')),
|
||||
('person', ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='person.Person')),
|
||||
],
|
||||
),
|
||||
]
|
102
ietf/nomcom/migrations/0012_populate_volunteers.py
Normal file
102
ietf/nomcom/migrations/0012_populate_volunteers.py
Normal file
|
@ -0,0 +1,102 @@
|
|||
# Copyright The IETF Trust 2021 All Rights Reserved
|
||||
# Generated by Django 2.2.24 on 2021-06-10 12:50
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
def forward(apps, schema_editor):
|
||||
Volunteer = apps.get_model('nomcom','Volunteer')
|
||||
NomCom = apps.get_model('nomcom','NomCom')
|
||||
nc = NomCom.objects.get(group__acronym='nomcom2021')
|
||||
|
||||
nc.is_accepting_volunteers = True
|
||||
nc.save()
|
||||
|
||||
volunteers = [
|
||||
(21684, 'Futurewei Technologies'), # Barry Leiba
|
||||
(117988, 'Google LLC'), # Benjamin M. Schwartz
|
||||
(122671, 'Fastmail Pty Ltd'), # Bron Gondwana
|
||||
(124329, 'Huawei'), # Cheng Li
|
||||
(113580, 'China Mobile'), # Weiqiang Cheng
|
||||
(22933, 'LabN Consulting'), # Christian Hopps
|
||||
(102391, 'Futurewei Technologies, Inc'), # Donald E. Eastlake 3rd
|
||||
(111477, 'Huawei'), # Dhruv Dhody
|
||||
(12695, 'Mozilla'), # Eric Rescorla
|
||||
(17141, 'APNIC'), # George G. Michaelson
|
||||
(108833, 'Huawei'), # Luigi Iannone
|
||||
(118908, 'Huawei Technologies'), # Giuseppe Fioccola
|
||||
(5376, 'Vigil Security, LLC'), # Russ Housley
|
||||
(118100, 'Equinix'), # Ignas Bagdonas
|
||||
(107287, 'rtfm llp'), # Jim Reid
|
||||
(123344, 'Netflix'), # Theresa Enghardt
|
||||
(109226, 'Huawei'), # Italo Busi
|
||||
(113152, 'Ericsson'), # Jaime Jimenez
|
||||
(111354, 'Juniper Networks'), # John Drake
|
||||
(112342, 'Cisco Systems, Inc.'), # Jakob Heitz
|
||||
(109207, 'Huawei Technologies Co., Ltd.'), # 江元龙
|
||||
(110737, 'Huawei Technologies'), # Jie Dong
|
||||
(109330, 'Ericsson'), # John Preuß Mattsson
|
||||
(123589, 'Nokia'), # Julien Maisonneuve
|
||||
(124655, 'UK National Cyber Security Centre (NCSC)'), # Kirsty Paine
|
||||
(119463, 'Akamai Technologies, Inc.'), # Kyle Rose
|
||||
(109983, 'Huawei Technologies Co.,Ltd.'), # Bo Wu
|
||||
(2097, 'Cisco Systems'), # Eliot Lear
|
||||
(567, 'UCLA'), # Lixia Zhang
|
||||
(107762, 'Huawei'), # Mach Chen
|
||||
(125198, 'Juniper Networks'), # Melchior Aelmans
|
||||
(104294, 'Ericsson'), # Magnus Westerlund
|
||||
(104495, 'Impedance Mismatch LLC'), # Marc Petit-Huguenin
|
||||
(119947, 'Painless Security, LLC'), # Margaret Cullen
|
||||
(102830, 'Independent'), # Mary Barnes
|
||||
(116593, 'Fastly'), # Patrick McManus
|
||||
(102254, 'Sandelman Software Works'), # Michael Richardson
|
||||
(20356, 'Apple'), # Ted Lemon
|
||||
(103881, 'Fastly'), # Mark Nottingham
|
||||
(106741, 'NthPermutation Security'), # Michael StJohns
|
||||
(116323, 'Moulay Ismail University of Meknes, Morocco'), # Nabil Benamar
|
||||
(20106, 'W3C/MIT'), # Samuel Weiler
|
||||
(105691, 'cisco'), # Ole Trøan
|
||||
(121160, 'Independent, Amazon'), # Padma Pillay-Esnault
|
||||
(115824, 'Cisco Systems'), # Pascal Thubert
|
||||
(122637, 'Huawei Technologies Co.,Ltd.'), # Shuping Peng
|
||||
(112952, 'Huawei'), # Haibo Wang
|
||||
(5234, 'IIJ Research Lab & Arrcus Inc'), # Randy Bush
|
||||
(101568, 'Juniper Networks'), # Ron Bonica
|
||||
(123443, 'Huawei Technologies Co.,Ltd.'), # Bing Liu (Remy)
|
||||
(18321, 'Episteme Technology Consulting LLC'), # Pete Resnick
|
||||
(18427, 'Akamai'), # Rich Salz
|
||||
(126259, 'Huawei Technologies Co.,Ltd.'), # Fan Yang
|
||||
(115724, 'Juniper Networks'), # Shraddha Hegde
|
||||
(125509, 'Tencent'), # Shuai Zhao
|
||||
(110614, 'Huawei'), # Tal Mizrahi
|
||||
(123395, 'APNIC'), # Tom Harrison
|
||||
(116516, 'Juniper Networks'), # Tarek Saad
|
||||
(11834, 'Futurewei USA'), # Toerless Eckert
|
||||
(123962, 'Open-Xchange'), # Vittorio Bertola
|
||||
(126530, 'Huawei'), # Yali Wang
|
||||
(106199, 'Ericsson'), # Wassim Haddad
|
||||
(125173, 'Huawei'), # Wei Pan
|
||||
(111299, 'ZTE Corporation'), # Xiao Min
|
||||
(113285, 'Huawei Technologies'), # XiPeng Xiao
|
||||
(116337, 'Futurewei Technologies Inc.'), # Yingzhen Qu
|
||||
(123974, 'ZTE'), # Zheng Zhang
|
||||
(117500, 'Huawei'), # Guangying Zheng
|
||||
(115934, 'Huawei Technologies'), # Haomian Zheng
|
||||
(110966, 'Juniper'), # Zhaohui (Jeffrey) Zhang
|
||||
]
|
||||
|
||||
for pk, affiliation in volunteers:
|
||||
nc.volunteer_set.create(person_id=pk, affiliation=affiliation)
|
||||
|
||||
def reverse(apps, schema_editor):
|
||||
Volunteer = apps.get_model('nomcom','Volunteer')
|
||||
Volunteer.objects.all().delete()
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('nomcom', '0011_volunteers'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(forward,reverse)
|
||||
]
|
|
@ -59,6 +59,8 @@ class NomCom(models.Model):
|
|||
help_text='Display pictures of each nominee (if available) on the feedback pages')
|
||||
show_accepted_nominees = models.BooleanField(verbose_name='Show accepted nominees', default=True,
|
||||
help_text='Show accepted nominees on the public nomination page')
|
||||
is_accepting_volunteers = models.BooleanField(verbose_name="Accepting volunteers", default=False,
|
||||
help_text='Is this nomcom is currently accepting volunteers?')
|
||||
first_call_for_volunteers = models.DateField(verbose_name='Date of the first call for volunteers', blank=True, null=True)
|
||||
|
||||
class Meta:
|
||||
|
@ -310,4 +312,12 @@ class TopicFeedbackLastSeen(models.Model):
|
|||
reviewer = ForeignKey(Person)
|
||||
topic = ForeignKey(Topic)
|
||||
time = models.DateTimeField(auto_now=True)
|
||||
|
||||
class Volunteer(models.Model):
|
||||
nomcom = ForeignKey('NomCom')
|
||||
person = ForeignKey(Person)
|
||||
affiliation = models.CharField(blank=True, max_length=255)
|
||||
|
||||
def __str__(self):
|
||||
return f'{self.person} for {self.nomcom}'
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ from tastypie.cache import SimpleCache
|
|||
from ietf import api
|
||||
|
||||
from ietf.nomcom.models import (NomCom, Position, Nominee, ReminderDates, NomineePosition,
|
||||
Feedback, Nomination, FeedbackLastSeen, Topic, TopicFeedbackLastSeen, )
|
||||
Feedback, Nomination, FeedbackLastSeen, Topic, TopicFeedbackLastSeen, Volunteer, )
|
||||
|
||||
from ietf.group.resources import GroupResource
|
||||
class NomComResource(ModelResource):
|
||||
|
@ -226,3 +226,22 @@ class TopicFeedbackLastSeenResource(ModelResource):
|
|||
"topic": ALL_WITH_RELATIONS,
|
||||
}
|
||||
api.nomcom.register(TopicFeedbackLastSeenResource())
|
||||
|
||||
|
||||
from ietf.person.resources import PersonResource
|
||||
class VolunteerResource(ModelResource):
|
||||
nomcom = ToOneField(NomComResource, 'nomcom')
|
||||
person = ToOneField(PersonResource, 'person')
|
||||
class Meta:
|
||||
queryset = Volunteer.objects.all()
|
||||
serializer = api.Serializer()
|
||||
cache = SimpleCache()
|
||||
#resource_name = 'volunteer'
|
||||
ordering = ['id', ]
|
||||
filtering = {
|
||||
"id": ALL,
|
||||
"affiliation": ALL,
|
||||
"nomcom": ALL_WITH_RELATIONS,
|
||||
"person": ALL_WITH_RELATIONS,
|
||||
}
|
||||
api.nomcom.register(VolunteerResource())
|
||||
|
|
|
@ -23,7 +23,8 @@ import debug # pyflakes:ignore
|
|||
|
||||
from ietf.dbtemplate.factories import DBTemplateFactory
|
||||
from ietf.dbtemplate.models import DBTemplate
|
||||
from ietf.doc.factories import DocEventFactory, WgDocumentAuthorFactory
|
||||
from ietf.doc.factories import DocEventFactory, WgDocumentAuthorFactory, \
|
||||
NewRevisionDocEventFactory, DocumentAuthorFactory
|
||||
from ietf.group.factories import GroupFactory, GroupHistoryFactory, RoleFactory, RoleHistoryFactory
|
||||
from ietf.group.models import Group, Role
|
||||
from ietf.meeting.factories import MeetingFactory
|
||||
|
@ -40,7 +41,7 @@ from ietf.nomcom.factories import NomComFactory, FeedbackFactory, TopicFactory,
|
|||
key
|
||||
from ietf.nomcom.utils import get_nomcom_by_year, make_nomineeposition, \
|
||||
get_hash_nominee_position, is_eligible, list_eligible, \
|
||||
get_eligibility_date
|
||||
get_eligibility_date, suggest_affiliation
|
||||
from ietf.person.factories import PersonFactory, EmailFactory
|
||||
from ietf.person.models import Email, Person
|
||||
from ietf.stats.models import MeetingRegistration
|
||||
|
@ -1833,11 +1834,42 @@ Junk body for testing
|
|||
continue
|
||||
first_name, last_name = ascii.rsplit(None, 1)
|
||||
MeetingRegistration.objects.create(meeting=meeting, first_name=first_name, last_name=last_name, person=person, country_code='WO', email=email, attended=True)
|
||||
# test the page
|
||||
url = reverse('ietf.nomcom.views.eligible',kwargs={'year':self.nc.year()})
|
||||
login_testing_unauthorized(self,self.chair.user.username,url)
|
||||
response = self.client.get(url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
for view in ('public_eligible','private_eligible'):
|
||||
url = reverse(f'ietf.nomcom.views.{view}',kwargs={'year':self.nc.year()})
|
||||
for username in (self.chair.user.username,'secretary'):
|
||||
login_testing_unauthorized(self,username,url)
|
||||
response = self.client.get(url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.client.logout()
|
||||
self.client.login(username='plain',password='plain+password')
|
||||
response = self.client.get(url)
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
def test_volunteers(self):
|
||||
year = self.nc.year()
|
||||
def first_meeting_of_year(year):
|
||||
assert isinstance(year, int)
|
||||
assert year >= 1991
|
||||
return (year-1985)*3+2
|
||||
people = PersonFactory.create_batch(10)
|
||||
meeting_start = first_meeting_of_year(year-2)
|
||||
for number in range(meeting_start, meeting_start+8):
|
||||
m = MeetingFactory.create(type_id='ietf', number=number)
|
||||
for p in people:
|
||||
m.meetingregistration_set.create(person=p)
|
||||
for p in people:
|
||||
self.nc.volunteer_set.create(person=p,affiliation='something')
|
||||
for view in ('public_volunteers','private_volunteers'):
|
||||
url = reverse(f'ietf.nomcom.views.{view}', kwargs=dict(year=self.nc.year()))
|
||||
for username in (self.chair.user.username,'secretary'):
|
||||
login_testing_unauthorized(self,username,url)
|
||||
response = self.client.get(url)
|
||||
self.assertContains(response,people[-1].email(),status_code=200)
|
||||
self.client.logout()
|
||||
self.client.login(username='plain',password='plain+password')
|
||||
response = self.client.get(url)
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
|
||||
|
||||
class NomComIndexTests(TestCase):
|
||||
|
@ -2424,3 +2456,76 @@ class rfc8989EligibilityTests(TestCase):
|
|||
self.assertFalse(is_eligible(person,self.nomcom))
|
||||
|
||||
self.assertEqual(set(list_eligible(nomcom=self.nomcom)),set(eligible))
|
||||
|
||||
class VolunteerTests(TestCase):
|
||||
|
||||
def test_volunteer(self):
|
||||
url = reverse('ietf.nomcom.views.volunteer')
|
||||
|
||||
person = PersonFactory()
|
||||
login_testing_unauthorized(self, person.user.username, url)
|
||||
r = self.client.get(url)
|
||||
self.assertContains(r, 'NomCom is not accepting volunteers at this time', status_code=200)
|
||||
|
||||
year = datetime.date.today().year
|
||||
nomcom = NomComFactory(group__acronym=f'nomcom{year}', is_accepting_volunteers=False)
|
||||
r = self.client.get(url)
|
||||
self.assertContains(r, 'NomCom is not accepting volunteers at this time', status_code=200)
|
||||
nomcom.is_accepting_volunteers = True
|
||||
nomcom.save()
|
||||
MeetingRegistrationFactory(person=person, affiliation='mtg_affiliation')
|
||||
r = self.client.get(url)
|
||||
self.assertContains(r, 'Volunteer for NomCom', status_code=200)
|
||||
self.assertContains(r, 'mtg_affiliation')
|
||||
r=self.client.post(url, dict(nomcoms=[nomcom.pk], affiliation=''))
|
||||
self.assertEqual(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertTrue(q('form div.has-error #id_affiliation'))
|
||||
r=self.client.post(url, dict(nomcoms=[], affiliation='something'))
|
||||
q = PyQuery(r.content)
|
||||
self.assertTrue(q('form div.has-error #id_nomcoms'))
|
||||
r=self.client.post(url, dict(nomcoms=[nomcom.pk], affiliation='something'))
|
||||
self.assertRedirects(r, reverse('ietf.ietfauth.views.profile'))
|
||||
self.assertEqual(person.volunteer_set.get(nomcom=nomcom).affiliation, 'something')
|
||||
r=self.client.get(url)
|
||||
self.assertContains(r, 'already volunteered', status_code=200)
|
||||
|
||||
person.volunteer_set.all().delete()
|
||||
nomcom2 = NomComFactory(group__acronym=f'nomcom{year-1}', is_accepting_volunteers=True)
|
||||
r = self.client.get(url)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertEqual(len(q('#id_nomcoms div.checkbox')), 2)
|
||||
r = self.client.post(url, dict(nomcoms=[nomcom.pk, nomcom2.pk], affiliation='something'))
|
||||
self.assertRedirects(r, reverse('ietf.ietfauth.views.profile'))
|
||||
self.assertEqual(person.volunteer_set.count(), 2)
|
||||
r = self.client.get(url)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertFalse(q('form div#id_nomcoms'))
|
||||
self.assertIn(f'{nomcom.year()}/', q('#already-volunteered').text())
|
||||
self.assertIn(f'{nomcom2.year()}/', q('#already-volunteered').text())
|
||||
|
||||
person.volunteer_set.all().delete()
|
||||
r=self.client.post(url, dict(nomcoms=[nomcom2.pk], affiliation='something'))
|
||||
self.assertRedirects(r, reverse('ietf.ietfauth.views.profile'))
|
||||
self.assertEqual(person.volunteer_set.count(), 1)
|
||||
self.assertEqual(person.volunteer_set.first().nomcom, nomcom2)
|
||||
r = self.client.get(url)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertEqual(len(q('#id_nomcoms div.checkbox')), 1)
|
||||
self.assertNotIn(f'{nomcom.year()}/', q('#already-volunteered').text())
|
||||
self.assertIn(f'{nomcom2.year()}/', q('#already-volunteered').text())
|
||||
|
||||
def test_suggest_affiliation(self):
|
||||
person = PersonFactory()
|
||||
self.assertEqual(suggest_affiliation(person), '')
|
||||
da = DocumentAuthorFactory(person=person,affiliation='auth_affil')
|
||||
NewRevisionDocEventFactory(doc=da.document)
|
||||
self.assertEqual(suggest_affiliation(person), 'auth_affil')
|
||||
nc = NomComFactory()
|
||||
nc.volunteer_set.create(person=person,affiliation='volunteer_affil')
|
||||
self.assertEqual(suggest_affiliation(person), 'volunteer_affil')
|
||||
MeetingRegistrationFactory(person=person, affiliation='meeting_affil')
|
||||
self.assertEqual(suggest_affiliation(person), 'meeting_affil')
|
||||
|
|
|
@ -7,6 +7,7 @@ urlpatterns = [
|
|||
url(r'^$', views.index),
|
||||
url(r'^ann/$', views.announcements),
|
||||
url(r'^history/$', views.history),
|
||||
url(r'^volunteer/$', views.volunteer),
|
||||
url(r'^(?P<year>\d{4})/private/$', views.private_index),
|
||||
url(r'^(?P<year>\d{4})/private/key/$', views.private_key),
|
||||
url(r'^(?P<year>\d{4})/private/help/$', views.configuration_help),
|
||||
|
@ -37,7 +38,8 @@ urlpatterns = [
|
|||
url(r'^(?P<year>\d{4})/private/chair/topic/add/$', views.edit_topic),
|
||||
url(r'^(?P<year>\d{4})/private/chair/topic/(?P<topic_id>\d+)/$', views.edit_topic),
|
||||
url(r'^(?P<year>\d{4})/private/chair/topic/(?P<topic_id>\d+)/remove/$', views.remove_topic),
|
||||
url(r'^(?P<year>\d{4})/private/chair/eligible/$', views.eligible ),
|
||||
url(r'^(?P<year>\d{4})/private/chair/eligible/$', views.private_eligible),
|
||||
url(r'^(?P<year>\d{4})/private/chair/volunteers/$', views.private_volunteers),
|
||||
|
||||
url(r'^(?P<year>\d{4})/$', views.year_index),
|
||||
url(r'^(?P<year>\d{4})/requirements/$', views.requirements),
|
||||
|
@ -47,6 +49,8 @@ urlpatterns = [
|
|||
url(r'^(?P<year>\d{4})/nominate/$', views.public_nominate),
|
||||
url(r'^(?P<year>\d{4})/nominate/newperson$', views.public_nominate_newperson),
|
||||
url(r'^(?P<year>\d{4})/process-nomination-status/(?P<nominee_position_id>\d+)/(?P<state>[\w]+)/(?P<date>[\d]+)/(?P<hash>[a-f0-9]+)/$', views.process_nomination_status),
|
||||
url(r'^(?P<year>\d{4})/eligible/$', views.public_eligible),
|
||||
url(r'^(?P<year>\d{4})/volunteers/$', views.public_volunteers),
|
||||
# use the generic view from message
|
||||
url(r'^ann/(?P<message_id>\d+)/$', message_views.message, {'group_type': "nomcom" }),
|
||||
]
|
||||
|
|
|
@ -22,7 +22,7 @@ from django.template.loader import render_to_string
|
|||
from django.shortcuts import get_object_or_404
|
||||
|
||||
from ietf.dbtemplate.models import DBTemplate
|
||||
from ietf.doc.models import DocEvent
|
||||
from ietf.doc.models import DocEvent, NewRevisionDocEvent
|
||||
from ietf.group.models import Group, Role
|
||||
from ietf.person.models import Email, Person
|
||||
from ietf.mailtrigger.utils import gather_address_lists
|
||||
|
@ -589,4 +589,16 @@ def three_of_five_eligible(previous_five, queryset=None):
|
|||
queryset = Person.objects.all()
|
||||
return queryset.filter(meetingregistration__meeting__in=list(previous_five),meetingregistration__attended=True).annotate(mtg_count=Count('meetingregistration')).filter(mtg_count__gte=3)
|
||||
|
||||
def suggest_affiliation(person):
|
||||
recent_meeting = person.meetingregistration_set.order_by('-meeting__date').first()
|
||||
affiliation = recent_meeting.affiliation if recent_meeting else ''
|
||||
if not affiliation:
|
||||
recent_volunteer = person.volunteer_set.order_by('-nomcom__group__acronym').first()
|
||||
if recent_volunteer:
|
||||
affiliation = recent_volunteer.affiliation
|
||||
if not affiliation:
|
||||
recent_draft_revision = NewRevisionDocEvent.objects.filter(doc__type_id='draft',doc__documentauthor__person=person).order_by('-time').first()
|
||||
if recent_draft_revision:
|
||||
affiliation = recent_draft_revision.doc.documentauthor_set.filter(person=person).first().affiliation
|
||||
return affiliation
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ from django.contrib import messages
|
|||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
|
||||
from django.forms.models import modelformset_factory, inlineformset_factory
|
||||
from django.forms.models import modelformset_factory, inlineformset_factory
|
||||
from django.http import Http404, HttpResponseRedirect
|
||||
from django.shortcuts import render, get_object_or_404, redirect
|
||||
from django.template.loader import render_to_string
|
||||
|
@ -31,10 +31,10 @@ from ietf.nomcom.forms import (NominateForm, NominateNewPersonForm, FeedbackForm
|
|||
PrivateKeyForm, EditNomcomForm, EditNomineeForm,
|
||||
PendingFeedbackForm, ReminderDatesForm, FullFeedbackFormSet,
|
||||
FeedbackEmailForm, NominationResponseCommentForm, TopicForm,
|
||||
NewEditMembersForm,)
|
||||
NewEditMembersForm, VolunteerForm, )
|
||||
from ietf.nomcom.models import (Position, NomineePosition, Nominee, Feedback, NomCom, ReminderDates,
|
||||
FeedbackLastSeen, Topic, TopicFeedbackLastSeen, )
|
||||
from ietf.nomcom.utils import (get_nomcom_by_year, store_nomcom_private_key,
|
||||
from ietf.nomcom.utils import (get_nomcom_by_year, store_nomcom_private_key, suggest_affiliation,
|
||||
get_hash_nominee_position, send_reminder_to_nominees, list_eligible,
|
||||
HOME_TEMPLATE, NOMINEE_ACCEPT_REMINDER_TEMPLATE,NOMINEE_QUESTIONNAIRE_REMINDER_TEMPLATE, )
|
||||
|
||||
|
@ -1269,8 +1269,33 @@ def extract_email_lists(request, year):
|
|||
'bypos': bypos,
|
||||
})
|
||||
|
||||
@login_required
|
||||
def volunteer(request):
|
||||
nomcoms = NomCom.objects.filter(is_accepting_volunteers=True)
|
||||
if not nomcoms.exists():
|
||||
return render(request, 'nomcom/volunteers_not_accepted.html')
|
||||
person = request.user.person
|
||||
already_volunteered = nomcoms.filter(volunteer__person=person)
|
||||
can_volunteer = nomcoms.exclude(volunteer__person=person)
|
||||
|
||||
if request.method=='POST':
|
||||
form = VolunteerForm(person=person, data=request.POST)
|
||||
if form.is_valid():
|
||||
for nc in form.cleaned_data['nomcoms']:
|
||||
nc.volunteer_set.create(person=person, affiliation=form.cleaned_data['affiliation'])
|
||||
return redirect('ietf.ietfauth.views.profile')
|
||||
else:
|
||||
form = VolunteerForm(person=person,initial=dict(nomcoms=can_volunteer, affiliation=suggest_affiliation(person)))
|
||||
return render(request, 'nomcom/volunteer.html', {'form':form, 'can_volunteer': can_volunteer, 'already_volunteered': already_volunteered})
|
||||
|
||||
def public_eligible(request, year):
|
||||
return eligible(request=request, year=year, public=True)
|
||||
|
||||
def private_eligible(request, year):
|
||||
return eligible(request=request, year=year, public=False)
|
||||
|
||||
@role_required("Nomcom Chair", "Nomcom Advisor", "Secretariat")
|
||||
def eligible(request, year):
|
||||
def eligible(request, year, public=False):
|
||||
nomcom = get_nomcom_by_year(year)
|
||||
|
||||
eligible_persons = list(list_eligible(nomcom=nomcom))
|
||||
|
@ -1281,3 +1306,23 @@ def eligible(request, year):
|
|||
'year':year,
|
||||
'eligible_persons':eligible_persons,
|
||||
})
|
||||
|
||||
def public_volunteers(request, year):
|
||||
return volunteers(request=request, year=year, public=True)
|
||||
|
||||
def private_volunteers(request, year):
|
||||
return volunteers(request=request, year=year, public=False)
|
||||
|
||||
@role_required("Nomcom Chair", "Nomcom Advisor", "Secretariat")
|
||||
def volunteers(request, year, public=False):
|
||||
nomcom = get_nomcom_by_year(year)
|
||||
# pull list of volunteers
|
||||
# get queryset of all eligible (from utils)
|
||||
# decorate members of the list with eligibility
|
||||
volunteers = nomcom.volunteer_set.all()
|
||||
eligible = list_eligible(nomcom)
|
||||
for v in volunteers:
|
||||
v.eligible = v.person in eligible
|
||||
volunteers = sorted(volunteers,key=lambda v:(not v.eligible,v.person.last_name()))
|
||||
return render(request, 'nomcom/volunteers.html', dict(year=year, nomcom=nomcom, volunteers=volunteers, public=public))
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{% extends "nomcom/nomcom_private_base.html" %}
|
||||
{% extends public|yesno:"nomcom/nomcom_public_base.html,nomcom/nomcom_private_base.html" %}
|
||||
{# Copyright The IETF Trust 2015, All Rights Reserved #}
|
||||
{% load origin %}
|
||||
{% load bootstrap3 %}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
{% load origin %}
|
||||
|
||||
{% load nomcom_tags %}
|
||||
{% load ietf_filters %}
|
||||
|
||||
{% block title %}NomCom {{ year }} Private{% block subtitle %}{% endblock %}{% endblock %}
|
||||
|
||||
|
@ -46,7 +47,6 @@
|
|||
{% if nomcom.group.state_id == 'active' %}
|
||||
<li {% if selected == "edit_members" %}class="active"{% endif %}><a href="{% url 'ietf.nomcom.views.edit_members' year %}">Edit Members</a></li>
|
||||
{% endif %}
|
||||
<li {% if selected == "view_eligible" %}class="active"{% endif %}><a href="{% url 'ietf.nomcom.views.eligible' year %}">View Eligible</a></li>
|
||||
<li {% if selected == "help" %}class="active"{% endif %}><a href="{% url 'ietf.nomcom.views.configuration_help' year %}">Configuration Help</a></li>
|
||||
<li role="presentation" class="dropdown-header">Other Tools</li>
|
||||
<li {% if selected == "announce" %}class="active"{% endif %}><a href="{% url 'ietf.secr.announcement.views.main'%}">Announcement Tool</a></li>
|
||||
|
@ -55,6 +55,15 @@
|
|||
</ul>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if user|is_chair_or_advisor:year or user|has_role:"Secretariat" %}
|
||||
<li class="dropdown">
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">Volunteers<span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li {% if selected == "view_eligible" %}class="active"{% endif %}><a href="{% url 'ietf.nomcom.views.private_eligible' year %}">View Eligible</a></li>
|
||||
<li {% if selected == "view_volunteers" %}class="active"{% endif %}><a href="{% url 'ietf.nomcom.views.private_volunteers' year %}">View Volunteers</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
||||
{% block nomcom_content %}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
{% load origin %}
|
||||
|
||||
{% load nomcom_tags %}
|
||||
{% load ietf_filters %}
|
||||
|
||||
{% block title %}NomCom {{ year }}{% block subtitle %}{% endblock %}{% endblock %}
|
||||
|
||||
|
@ -19,6 +20,15 @@
|
|||
{% endif %}
|
||||
<li {% if selected == "requirements" %}class="active"{% endif %}><a href="{% url 'ietf.nomcom.views.requirements' year %}">Desired expertise</a></li>
|
||||
<li {% if selected == "questionnaires" %}class="active"{% endif %}><a href="{% url 'ietf.nomcom.views.questionnaires' year %}">Questionnaires</a></li>
|
||||
{% if user|is_chair_or_advisor:year or user|has_role:"Secretariat" %}
|
||||
<li class="dropdown">
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">Volunteers<span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li {% if selected == "view_eligible" %}class="active"{% endif %}><a href="{% url 'ietf.nomcom.views.public_eligible' year %}">View Eligible</a></li>
|
||||
<li {% if selected == "view_volunteers" %}class="active"{% endif %}><a href="{% url 'ietf.nomcom.views.public_volunteers' year %}">View Volunteers</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
||||
{% block nomcom_content %}
|
||||
|
|
32
ietf/templates/nomcom/volunteer.html
Normal file
32
ietf/templates/nomcom/volunteer.html
Normal file
|
@ -0,0 +1,32 @@
|
|||
{% extends "base.html" %}
|
||||
{# Copyright The IETF Trust 2021, All Rights Reserved #}
|
||||
{% load origin %}
|
||||
{% load bootstrap3 %}
|
||||
|
||||
{% block title %}Volunteer for NomCom{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% origin %}
|
||||
<h1>Volunteer for NomCom</h1>
|
||||
|
||||
{% if can_volunteer.exists %}
|
||||
<form method="post" >
|
||||
{% csrf_token %}
|
||||
|
||||
{% bootstrap_form form %}
|
||||
|
||||
{% buttons %}
|
||||
<button type="submit" class="btn btn-primary">Submit</button>
|
||||
{% endbuttons %}
|
||||
</form>
|
||||
{% endif %}
|
||||
|
||||
{% if already_volunteered.exists %}
|
||||
<div class="alert alert-info" id="already-volunteered">
|
||||
You have already volunteered for the {% for nc in already_volunteered %}{{nc.year}}/{{nc.year|add:1}}{% if not forloop.last %}, {% endif %}{% endfor %} Nominating Committee{{already_volunteered|pluralize}}.
|
||||
To modify your volunteer status, contact the NomCom chair.
|
||||
</div>
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
40
ietf/templates/nomcom/volunteers.html
Normal file
40
ietf/templates/nomcom/volunteers.html
Normal file
|
@ -0,0 +1,40 @@
|
|||
{% extends public|yesno:"nomcom/nomcom_public_base.html,nomcom/nomcom_private_base.html" %}
|
||||
{# Copyright The IETF Trust 2021, All Rights Reserved #}
|
||||
{% load origin %}
|
||||
{% load bootstrap3 %}
|
||||
{% load static %}
|
||||
|
||||
{% block subtitle %} - Volunteers{% endblock %}
|
||||
|
||||
{% block pagehead %}
|
||||
<link rel="stylesheet" href="{% static "jquery.tablesorter/css/theme.bootstrap.min.css" %}">
|
||||
{% endblock %}
|
||||
|
||||
{% block nomcom_content %}
|
||||
{% origin %}
|
||||
<h2>Volunteers for {{ nomcom.group }}</h2>
|
||||
|
||||
<table class="table table-condensed table-striped tablesorter">
|
||||
<thead>
|
||||
<th>Eligible</th>
|
||||
<th>Last Name</th>
|
||||
<th>First Name</th>
|
||||
<th>Affiliation</th>
|
||||
<th>Email Addresses</th>
|
||||
</thead>
|
||||
|
||||
{% for v in volunteers %}
|
||||
<tr>
|
||||
<td>{{v.eligible|yesno}}
|
||||
<td><a href="{% url 'ietf.person.views.profile' v.person.name %}">{{v.person.last_name}}</a></td>
|
||||
<td>{{v.person.first_name}}</td>
|
||||
<td>{{v.affiliation}}</td>
|
||||
<td>{% for e in v.person.email_set.all %}{{e.address}}{% if not forloop.last %}, {% endif %}{% endfor %}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endblock nomcom_content %}
|
||||
|
||||
{% block js %}
|
||||
<script src="{% static "jquery.tablesorter/js/jquery.tablesorter.combined.min.js" %}"></script>
|
||||
{% endblock %}
|
10
ietf/templates/nomcom/volunteers_not_accepted.html
Normal file
10
ietf/templates/nomcom/volunteers_not_accepted.html
Normal file
|
@ -0,0 +1,10 @@
|
|||
{% extends "base.html" %}
|
||||
{# Copyright The IETF Trust 2021, All Rights Reserved #}
|
||||
{% load origin %}
|
||||
|
||||
{% block title %}Not Accepting Volunteers{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% origin %}
|
||||
<h1> NomCom is not accepting volunteers at this time</h1>
|
||||
{% endblock %}
|
|
@ -66,7 +66,14 @@
|
|||
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label">Nomcom Eligible</label>
|
||||
<div class="col-sm-1 form-control-static">{{person|is_nomcom_eligible|yesno:'Yes,No,No'}}</div>
|
||||
<div class="col-sm-1 form-control-static">
|
||||
{{person|is_nomcom_eligible|yesno:'Yes,No,No'}}
|
||||
{% if volunteer_status == 'allow' %}
|
||||
<br>
|
||||
<a id="volunteer-button" class="btn btn-primary" href="{% url "ietf.nomcom.views.volunteer" %}">Volunteer</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="col-sm-9">
|
||||
<p class="alert alert-info form-control-static">
|
||||
If you believe this calculation is incorrect, make sure you've added all the
|
||||
|
@ -80,6 +87,9 @@
|
|||
for eligibility requirements.
|
||||
For the 2021 nomcom, see also <a href="{% url 'ietf.doc.views_doc.document_main' name='rfc8989' %}">RFC 8989</a>.
|
||||
|
||||
{% if volunteer_status == 'volunteered' %}
|
||||
<br/><strong id='volunteered'>You have volunteered for the {{nomcom.group.name}}.</strong> To modify your volunteer status, contact the NomCom chair.
|
||||
{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -89,7 +99,9 @@
|
|||
<div class="col-sm-10 form-control-static">
|
||||
{% for extres in person.personextresource_set.all %}
|
||||
<div class="row">
|
||||
<div class="col-sm-1"><span title="{{ extres.name.name}}">{% firstof extres.display_name extres.name.name %}</span></div>
|
||||
<div class="col-sm-1">
|
||||
<span title="{{ extres.name.name}}">{% firstof extres.display_name extres.name.name %}</span>
|
||||
</div>
|
||||
<div class="col-sm-11">{{extres.value}}
|
||||
{% if forloop.first %} <a href="{% url 'ietf.ietfauth.views.edit_person_externalresources' %}"><span class="fa fa-pencil"></span></a>{% endif %}
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue