diff --git a/ietf/nomcom/admin.py b/ietf/nomcom/admin.py new file mode 100644 index 000000000..35db6010d --- /dev/null +++ b/ietf/nomcom/admin.py @@ -0,0 +1,11 @@ +from django.contrib import admin + +from ietf.group.admin import GroupAdmin +from ietf.nomcom.models import NomComGroup + + +class NomComGroupAdmin(GroupAdmin): + exclude = ('type',) + + +admin.site.register(NomComGroup, NomComGroupAdmin) diff --git a/ietf/nomcom/forms.py b/ietf/nomcom/forms.py index e219d8146..eabd121be 100644 --- a/ietf/nomcom/forms.py +++ b/ietf/nomcom/forms.py @@ -1,61 +1,58 @@ from django import forms from django.contrib.formtools.preview import FormPreview from django.http import HttpResponseRedirect, HttpResponseForbidden +from django.shortcuts import get_object_or_404 from django.core.urlresolvers import reverse +from django.conf import settings from ietf.ietfauth.decorators import has_role from ietf.utils import fields as custom_fields -from ietf.group.models import Group, Role +from ietf.group.models import Role +from ietf.nomcom.models import NomComGroup from ietf.name.models import RoleName from ietf.person.models import Email -class ManageGroupForm(forms.Form): +ROLODEX_URL = getattr(settings, 'ROLODEX_URL', None) + + +class EditMembersForm(forms.Form): - chair = forms.EmailField(label="Chair email", required=False, - widget=forms.TextInput(attrs={'size': '40'})) members = custom_fields.MultiEmailField(label="Members email", required=False) - def __init__(self, *args, **kwargs): - super(ManageGroupForm, self).__init__(*args, **kwargs) +class EditMembersFormPreview(FormPreview): + form_template = 'nomcom/edit_members.html' + preview_template = 'nomcom/edit_members_preview.html' -class ManageGroupFormPreview(FormPreview): - form_template = 'nomcom/manage_group.html' - preview_template = 'nomcom/manage_group_review.html' + def __call__(self, request, *args, **kwargs): + year = kwargs['year'] + group = get_object_or_404(NomComGroup, + acronym__icontains=year, + state__slug='active') + is_group_chair = bool(group.role_set.filter(person__user=request.user, name__slug='chair')[:1]) + is_secretariat = has_role(request.user, "Secretariat") + if not is_secretariat and not is_group_chair: + return HttpResponseForbidden("Must be a secretariat or group chair") - def preview_get(self, request): - if not has_role(request.user, "Secretariat"): - return HttpResponseForbidden("Must be a secretariat") - - return super(ManageGroupFormPreview, self).preview_get(request) + self.state['group'] = group + self.state['rolodex_url'] = ROLODEX_URL + self.group = group + self.year = year + return super(EditMembersFormPreview, self).__call__(request, *args, **kwargs) def parse_params(self, *args, **kwargs): - group_acronym = kwargs['acronym'] - group = Group.objects.get(acronym=group_acronym) - chairs = group.role_set.filter(name__slug='chair') - members = group.role_set.filter(name__slug='member') - if chairs: - self.form.base_fields['chair'].initial = chairs[0].email.address + members = self.group.role_set.filter(name__slug='member') + if members: self.form.base_fields['members'].initial = ',\r\n'.join([role.email.address for role in members]) - self.state['group'] = group def process_preview(self, request, form, context): - chair_email = form.cleaned_data['chair'] members_email = form.cleaned_data['members'].replace('\r\n', '').replace(' ', '').split(',') + members_info = [] emails_not_found = [] - try: - chair_email_obj = Email.objects.get(address=chair_email) - chair_person = chair_email_obj.person - except Email.DoesNotExist: - chair_person = None - chair_email_obj = None - chair_info = {'email': chair_email, - 'email_obj': chair_email_obj, - 'person': chair_person} for email in members_email: try: @@ -69,29 +66,76 @@ class ManageGroupFormPreview(FormPreview): 'person': person}) else: emails_not_found.append(email) - self.state.update({'chair_info': chair_info, - 'members_info': members_info, + self.state.update({'members_info': members_info, 'emails_not_found': emails_not_found}) def done(self, request, cleaned_data): - group = self.state['group'] - chair_info = self.state['chair_info'] members_info = self.state['members_info'] members_email = [member['email'] for member in self.state['members_info']] - members_excluded = group.role_set.filter(name__slug='member').exclude(email__address__in=members_email) + members_excluded = self.group.role_set.filter(name__slug='member').exclude(email__address__in=members_email) members_excluded.delete() for member in members_info: Role.objects.get_or_create(name=RoleName.objects.get(slug="member"), - group=group, + group=self.group, person=member['person'], email=member['email_obj']) - chair_exclude = group.role_set.filter(name__slug='chair').exclude(email__address=chair_info['email']) + return HttpResponseRedirect(reverse('edit_members', kwargs={'year': self.year})) + + +class EditChairForm(forms.Form): + + chair = forms.EmailField(label="Chair email", required=False, + widget=forms.TextInput(attrs={'size': '40'})) + + +class EditChairFormPreview(FormPreview): + form_template = 'nomcom/edit_chair.html' + preview_template = 'nomcom/edit_chair_preview.html' + + def __call__(self, request, *args, **kwargs): + year = kwargs['year'] + group = get_object_or_404(NomComGroup, + acronym__icontains=year, + state__slug='active') + is_secretariat = has_role(request.user, "Secretariat") + if not is_secretariat: + return HttpResponseForbidden("Must be a secretariat") + + self.state['group'] = group + self.state['rolodex_url'] = ROLODEX_URL + self.group = group + self.year = year + + return super(EditChairFormPreview, self).__call__(request, *args, **kwargs) + + def parse_params(self, *args, **kwargs): + chairs = self.group.role_set.filter(name__slug='chair') + if chairs: + self.form.base_fields['chair'].initial = chairs[0].email.address + + def process_preview(self, request, form, context): + chair_email = form.cleaned_data['chair'] + try: + chair_email_obj = Email.objects.get(address=chair_email) + chair_person = chair_email_obj.person + except Email.DoesNotExist: + chair_person = None + chair_email_obj = None + chair_info = {'email': chair_email, + 'email_obj': chair_email_obj, + 'person': chair_person} + + self.state.update({'chair_info': chair_info}) + + def done(self, request, cleaned_data): + chair_info = self.state['chair_info'] + chair_exclude = self.group.role_set.filter(name__slug='chair').exclude(email__address=chair_info['email']) chair_exclude.delete() if chair_info['email_obj'] and chair_info['person']: Role.objects.get_or_create(name=RoleName.objects.get(slug="chair"), - group=group, + group=self.group, person=chair_info['person'], email=chair_info['email_obj']) - return HttpResponseRedirect(reverse('manage_group', kwargs={'acronym': group.acronym})) + return HttpResponseRedirect(reverse('edit_chair', kwargs={'year': self.year})) diff --git a/ietf/nomcom/migrations/0001_initial.py b/ietf/nomcom/migrations/0001_initial.py new file mode 100644 index 000000000..3b7e978a0 --- /dev/null +++ b/ietf/nomcom/migrations/0001_initial.py @@ -0,0 +1,228 @@ +# encoding: utf-8 +from south.db import db +from south.v2 import SchemaMigration + + +class Migration(SchemaMigration): + + def forwards(self, orm): + + # Adding model 'NomComGroup' + db.create_table('nomcom_nomcomgroup', ( + ('group_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['group.Group'], unique=True, primary_key=True)), + ('public_key', self.gf('django.db.models.fields.TextField')(blank=True)), + )) + db.send_create_signal('nomcom', ['NomComGroup']) + + def backwards(self, orm): + + # Deleting model 'NomComGroup' + db.delete_table('nomcom_nomcomgroup') + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'doc.docalias': { + 'Meta': {'object_name': 'DocAlias'}, + 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}) + }, + 'doc.document': { + 'Meta': {'object_name': 'Document'}, + 'abstract': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'ad': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'ad_document_set'", 'null': 'True', 'to': "orm['person.Person']"}), + 'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['person.Email']", 'symmetrical': 'False', 'through': "orm['doc.DocumentAuthor']", 'blank': 'True'}), + 'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'external_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}), + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}), + 'intended_std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.IntendedStdLevelName']", 'null': 'True', 'blank': 'True'}), + 'internal_comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'primary_key': 'True'}), + 'note': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'notify': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '1', 'blank': 'True'}), + 'pages': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'related': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'reversely_related_document_set'", 'blank': 'True', 'through': "orm['doc.RelatedDocument']", 'to': "orm['doc.DocAlias']"}), + 'rev': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}), + 'shepherd': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'shepherd_document_set'", 'null': 'True', 'to': "orm['person.Person']"}), + 'states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}), + 'std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StdLevelName']", 'null': 'True', 'blank': 'True'}), + 'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StreamName']", 'null': 'True', 'blank': 'True'}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['name.DocTagName']", 'null': 'True', 'blank': 'True'}), + 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'}) + }, + 'doc.documentauthor': { + 'Meta': {'ordering': "['document', 'order']", 'object_name': 'DocumentAuthor'}, + 'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Email']"}), + 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '1'}) + }, + 'doc.relateddocument': { + 'Meta': {'object_name': 'RelatedDocument'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'relationship': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocRelationshipName']"}), + 'source': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}), + 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.DocAlias']"}) + }, + 'doc.state': { + 'Meta': {'ordering': "['type', 'order']", 'object_name': 'State'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'next_states': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'previous_states'", 'symmetrical': 'False', 'to': "orm['doc.State']"}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}), + 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.StateType']"}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + 'doc.statetype': { + 'Meta': {'object_name': 'StateType'}, + 'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '30', 'primary_key': 'True'}) + }, + 'group.group': { + 'Meta': {'object_name': 'Group'}, + 'acronym': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '40', 'db_index': 'True'}), + 'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True', 'blank': 'True'}), + 'charter': ('django.db.models.fields.related.OneToOneField', [], {'blank': 'True', 'related_name': "'chartered_group'", 'unique': 'True', 'null': 'True', 'to': "orm['doc.Document']"}), + 'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'list_archive': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'list_email': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), + 'list_subscribe': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}), + 'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupStateName']", 'null': 'True'}), + 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupTypeName']", 'null': 'True'}), + 'unused_states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}), + 'unused_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['name.DocTagName']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'name.docrelationshipname': { + 'Meta': {'ordering': "['order']", 'object_name': 'DocRelationshipName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + 'name.doctagname': { + 'Meta': {'ordering': "['order']", 'object_name': 'DocTagName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + 'name.doctypename': { + 'Meta': {'ordering': "['order']", 'object_name': 'DocTypeName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + 'name.groupstatename': { + 'Meta': {'ordering': "['order']", 'object_name': 'GroupStateName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + 'name.grouptypename': { + 'Meta': {'ordering': "['order']", 'object_name': 'GroupTypeName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + 'name.intendedstdlevelname': { + 'Meta': {'ordering': "['order']", 'object_name': 'IntendedStdLevelName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + 'name.stdlevelname': { + 'Meta': {'ordering': "['order']", 'object_name': 'StdLevelName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + 'name.streamname': { + 'Meta': {'ordering': "['order']", 'object_name': 'StreamName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + 'nomcom.nomcomgroup': { + 'Meta': {'object_name': 'NomComGroup', '_ormbases': ['group.Group']}, + 'group_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['group.Group']", 'unique': 'True', 'primary_key': 'True'}), + 'public_key': ('django.db.models.fields.TextField', [], {'blank': 'True'}) + }, + 'person.email': { + 'Meta': {'object_name': 'Email'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'address': ('django.db.models.fields.CharField', [], {'max_length': '64', 'primary_key': 'True'}), + 'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True'}), + 'time': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}) + }, + 'person.person': { + 'Meta': {'object_name': 'Person'}, + 'address': ('django.db.models.fields.TextField', [], {'max_length': '255', 'blank': 'True'}), + 'affiliation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'ascii': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'ascii_short': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'null': 'True', 'blank': 'True'}) + } + } + + complete_apps = ['nomcom'] diff --git a/ietf/nomcom/migrations/__init__.py b/ietf/nomcom/migrations/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/ietf/nomcom/models.py b/ietf/nomcom/models.py index 71a836239..d97716e41 100644 --- a/ietf/nomcom/models.py +++ b/ietf/nomcom/models.py @@ -1,3 +1,21 @@ from django.db import models -# Create your models here. +from ietf.group.models import Group +from ietf.name.models import GroupTypeName + + +class NomComGroup(Group): + public_key = models.TextField(verbose_name="Public Key", blank=True) + + class Meta: + verbose_name_plural = "NomCom groups" + verbose_name = "NomCom group" + + def save(self, *args, **kwargs): + if not self.id: + try: + self.type = GroupTypeName.objects.get(slug='nomcom') + except GroupTypeName.DoesNotExist: + pass + + super(NomComGroup, self).save(*args, **kwargs) diff --git a/ietf/nomcom/urls.py b/ietf/nomcom/urls.py index 1de15f3ae..c138219ad 100644 --- a/ietf/nomcom/urls.py +++ b/ietf/nomcom/urls.py @@ -1,7 +1,8 @@ from django.conf.urls.defaults import patterns, url -from ietf.nomcom.forms import ManageGroupForm, ManageGroupFormPreview +from ietf.nomcom.forms import EditChairForm, EditChairFormPreview, \ + EditMembersForm, EditMembersFormPreview urlpatterns = patterns('ietf.nomcom.views', - - url(r'^group/(?P[\w.@+-]+)/$', ManageGroupFormPreview(ManageGroupForm), name='manage_group'), + url(r'^(?P\d{4})/edit-chair/$', EditChairFormPreview(EditChairForm), name='edit_chair'), + url(r'^(?P\d{4})/edit-members/$', EditMembersFormPreview(EditMembersForm), name='edit_members'), ) diff --git a/ietf/settings.py b/ietf/settings.py index b04f5e571..d2ef2d255 100644 --- a/ietf/settings.py +++ b/ietf/settings.py @@ -84,7 +84,7 @@ MEDIA_URL = '' ADMIN_MEDIA_PREFIX = '/media/' AUTH_PROFILE_MODULE = 'person.Person' -AUTHENTICATION_BACKENDS = ( 'django.contrib.auth.backends.RemoteUserBackend', ) +#AUTHENTICATION_BACKENDS = ( 'django.contrib.auth.backends.RemoteUserBackend', ) #DATABASE_ROUTERS = ["ietf.legacy_router.LegacyRouter"] @@ -160,6 +160,7 @@ INSTALLED_APPS = ( 'ietf.wgchairs', 'ietf.wgcharter', 'ietf.community', + 'ietf.nomcom', ) INTERNAL_IPS = ( @@ -256,6 +257,9 @@ IDSUBMIT_TO_EMAIL = 'internet-drafts@ietf.org' IDSUBMIT_ANNOUNCE_FROM_EMAIL = 'internet-drafts@ietf.org' IDSUBMIT_ANNOUNCE_LIST_EMAIL = 'i-d-announce@ietf.org' +# NomCom Tool settings +ROLODEX_URL = "" + # Days from meeting to cut off dates on submit FIRST_CUTOFF_DAYS = 19 SECOND_CUTOFF_DAYS = 12 diff --git a/ietf/templates/nomcom/edit_chair.html b/ietf/templates/nomcom/edit_chair.html new file mode 100644 index 000000000..1fb22de49 --- /dev/null +++ b/ietf/templates/nomcom/edit_chair.html @@ -0,0 +1,18 @@ +{% extends "base.html" %} + +{% block title %}Edit {{ state.group.acronym }} chair{% endblock %} + +{% block content %} +

Edit {{ state.group.acronym }} chair

+ +{% if form.errors %}

Please correct the following errors

{% endif %} + +
{% csrf_token %} + +{{ form }} +
+ +

+
+ +{% endblock %} diff --git a/ietf/templates/nomcom/edit_chair_preview.html b/ietf/templates/nomcom/edit_chair_preview.html new file mode 100644 index 000000000..04bb844e8 --- /dev/null +++ b/ietf/templates/nomcom/edit_chair_preview.html @@ -0,0 +1,44 @@ +{% extends "base.html" %} + +{% block title %}Edit {{ state.group.acronym }} chair{% endblock %} + +{% block content %} +

Edit {{ state.group.acronym }} chair

+ +

Chair info

+

+{% if state.chair_info.person %} +

    +
  • Email: {{ state.chair_info.email }}
  • +
  • Person name: {{ state.chair_info.person.name }}
  • +
+{% else %} +

Person with {{ state.chair_info.email }} not exists. {% if state.rolodex_url %} Please go to {{ state.rolodex_url }} to add this person.{% endif %}

+{% endif %} +

+ +{% if state.chair_info.person %} + + {% csrf_token %} + {% for field in form %}{{ field.as_hidden }} + {% endfor %} + + +

+ +{% endif %} + + +

Edit it again

+ + {% csrf_token %} +
+ {{ form }} +
+ +

+ + + + +{% endblock %} diff --git a/ietf/templates/nomcom/manage_group.html b/ietf/templates/nomcom/edit_members.html similarity index 75% rename from ietf/templates/nomcom/manage_group.html rename to ietf/templates/nomcom/edit_members.html index 54a23db08..ceaa902db 100644 --- a/ietf/templates/nomcom/manage_group.html +++ b/ietf/templates/nomcom/edit_members.html @@ -1,9 +1,9 @@ {% extends "base.html" %} -{% block title %}Manage group {{ state.group.acronym }}{% endblock %} +{% block title %}Edit {{ state.group.acronym }} members{% endblock %} {% block content %} -

Manage group {{ state.group.acronym }}

+

Edit {{ state.group.acronym }} members

{% if form.errors %}

Please correct the following errors

{% endif %} diff --git a/ietf/templates/nomcom/manage_group_review.html b/ietf/templates/nomcom/edit_members_preview.html similarity index 63% rename from ietf/templates/nomcom/manage_group_review.html rename to ietf/templates/nomcom/edit_members_preview.html index 86b379fb2..e99228732 100644 --- a/ietf/templates/nomcom/manage_group_review.html +++ b/ietf/templates/nomcom/edit_members_preview.html @@ -1,19 +1,9 @@ {% extends "base.html" %} -{% block title %}Preview group {{ state.group.acronym }} {% endblock %} +{% block title %}Edit {{ state.group.acronym }} members{% endblock %} {% block content %} -

Preview group {{ state.group.acronym }}

- -

Chair info

-{% if state.chair_info.person.name %} -
    -
  • Email: {{ state.chair_info.email }}
  • -
  • Person name: {{ state.chair_info.person.name }}
  • -
-{% else %} - email {{ state.chair_info.email }} not found -{% endif %} +

Edit {{ state.group.acronym }} members

{% if state.members_info %}

Members info

@@ -25,12 +15,13 @@ {% endif %} {% if state.emails_not_found %} -

Members not found

-
    -{% for email in state.emails_not_found %} -
  • {{ email }}
  • -{% endfor %} -
+

Members not found

+
    + {% for email in state.emails_not_found %} +
  • {{ email }}
  • + {% endfor %} +
+ {% if state.rolodex_url %}Please go to {{ state.rolodex_url }} to add these people.{% endif %} {% endif %} diff --git a/ietf/utils/fields.py b/ietf/utils/fields.py index acc814ef1..a564f9ba5 100644 --- a/ietf/utils/fields.py +++ b/ietf/utils/fields.py @@ -9,6 +9,8 @@ class MultiEmailField(forms.CharField): def clean(self, value): super(MultiEmailField, self).clean(value) if value: + if value.endswith(','): + value = value[:-1] emails = map(unicode.strip, value.split(',')) else: return value