Merged in branch/iola/people-cleanup @ [8471] from olau@iola.dk, which
enhances a number of pages in the datatracker where forms contain fields
where a person should be chosen, such as for instance when choosing the
shepherd of a document, so that they uniformly display choices which show
both email address and name.
Furthermore, changes have been made so as to make the email address
uniformly act as reference to the person record.
Autocompletion is now consistently provided when looking for the email
address or name of the person to choose.
This solves a number of issues where it has been difficult to choose the
correct Person/Email combination, and where the correct email address to use
for an association has been unavailable previously.
- Legacy-Id: 8472
Note: SVN reference [8471] has been migrated to Git commit d62f2343e8
This commit is contained in:
commit
704589b4c7
|
@ -15,7 +15,7 @@ ietfdb (5.7.0) ietf; urgency=medium
|
|||
correct Person/Email combination, and where the correct email address to use
|
||||
for an association has been unavailable previously.
|
||||
|
||||
-- Henrik Levkowetz <henrik@levkowetz.com> 25 Oct 2014 13:53:37 -0700
|
||||
-- Henrik Levkowetz <henrik@levkowetz.com> 25 Oct 2014 13:49:49 -0200
|
||||
|
||||
ietfdb (5.6.5) ietf; urgency=medium
|
||||
|
||||
|
|
|
@ -89,7 +89,7 @@ class ShepherdRule(RuleManager):
|
|||
description = 'All I-Ds with a particular document shepherd'
|
||||
|
||||
def get_documents(self):
|
||||
return Document.objects.filter(type='draft', states__slug='active').filter(shepherd__name__icontains=self.value).distinct()
|
||||
return Document.objects.filter(type='draft', states__slug='active').filter(shepherd__person__name__icontains=self.value).distinct()
|
||||
|
||||
|
||||
# class ReferenceToRFCRule(RuleManager):
|
||||
|
|
|
@ -32,9 +32,9 @@ def email_stream_changed(request, doc, old_stream, new_stream, text=""):
|
|||
|
||||
# These use comprehension to deal with conditions when there might be more than one chair listed for a stream
|
||||
if old_stream:
|
||||
to.extend([x.person.formatted_email() for x in Role.objects.filter(group__acronym=old_stream.slug,name='chair')])
|
||||
to.extend([r.formatted_email() for r in Role.objects.filter(group__acronym=old_stream.slug, name='chair')])
|
||||
if new_stream:
|
||||
to.extend([x.person.formatted_email() for x in Role.objects.filter(group__acronym=new_stream.slug,name='chair')])
|
||||
to.extend([r.formatted_email() for r in Role.objects.filter(group__acronym=new_stream.slug, name='chair')])
|
||||
|
||||
if not to:
|
||||
return
|
||||
|
@ -443,10 +443,10 @@ def stream_state_email_recipients(doc, extra_recipients=[]):
|
|||
res.append(email.formatted_email())
|
||||
persons.add(email.person)
|
||||
|
||||
for p in extra_recipients:
|
||||
if not p in persons:
|
||||
res.append(p.formatted_email())
|
||||
persons.add(p)
|
||||
for e in extra_recipients:
|
||||
if e.person not in persons:
|
||||
res.append(e.formatted_email())
|
||||
persons.add(e.person)
|
||||
|
||||
return res
|
||||
|
||||
|
|
|
@ -0,0 +1,380 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
# Adding field 'Document.shepherd_email'
|
||||
db.add_column(u'doc_document', 'shepherd_email',
|
||||
self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='shepherd_document_set', null=True, to=orm['person.Email']),
|
||||
keep_default=False)
|
||||
|
||||
# Adding field 'DocHistory.shepherd_email'
|
||||
db.add_column(u'doc_dochistory', 'shepherd_email',
|
||||
self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='shepherd_dochistory_set', null=True, to=orm['person.Email']),
|
||||
keep_default=False)
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
# Deleting field 'Document.shepherd_email'
|
||||
db.delete_column(u'doc_document', 'shepherd_email_id')
|
||||
|
||||
# Deleting field 'DocHistory.shepherd_email'
|
||||
db.delete_column(u'doc_dochistory', 'shepherd_email_id')
|
||||
|
||||
|
||||
models = {
|
||||
u'auth.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
u'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': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
u'auth.permission': {
|
||||
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
|
||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
u'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', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
|
||||
u'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', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
|
||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'})
|
||||
},
|
||||
u'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'}),
|
||||
u'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'})
|
||||
},
|
||||
u'doc.ballotdocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'BallotDocEvent', '_ormbases': [u'doc.DocEvent']},
|
||||
'ballot_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.BallotType']"}),
|
||||
u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'})
|
||||
},
|
||||
u'doc.ballotpositiondocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'BallotPositionDocEvent', '_ormbases': [u'doc.DocEvent']},
|
||||
'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']"}),
|
||||
'ballot': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['doc.BallotDocEvent']", 'null': 'True'}),
|
||||
'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'comment_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'discuss': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'discuss_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'pos': ('django.db.models.fields.related.ForeignKey', [], {'default': "'norecord'", 'to': u"orm['name.BallotPositionName']"})
|
||||
},
|
||||
u'doc.ballottype': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'BallotType'},
|
||||
'doc_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'positions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['name.BallotPositionName']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'question': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
u'doc.consensusdocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'ConsensusDocEvent', '_ormbases': [u'doc.DocEvent']},
|
||||
'consensus': ('django.db.models.fields.NullBooleanField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}),
|
||||
u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'})
|
||||
},
|
||||
u'doc.deletedevent': {
|
||||
'Meta': {'object_name': 'DeletedEvent'},
|
||||
'by': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']"}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'json': ('django.db.models.fields.TextField', [], {}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})
|
||||
},
|
||||
u'doc.docalias': {
|
||||
'Meta': {'object_name': 'DocAlias'},
|
||||
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.Document']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'})
|
||||
},
|
||||
u'doc.docevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'DocEvent'},
|
||||
'by': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']"}),
|
||||
'desc': ('django.db.models.fields.TextField', [], {}),
|
||||
'doc': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.Document']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'db_index': 'True'}),
|
||||
'type': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
u'doc.dochistory': {
|
||||
'Meta': {'object_name': 'DocHistory'},
|
||||
'abstract': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'ad': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'ad_dochistory_set'", 'null': 'True', 'to': u"orm['person.Person']"}),
|
||||
'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['person.Email']", 'symmetrical': 'False', 'through': u"orm['doc.DocHistoryAuthor']", 'blank': 'True'}),
|
||||
'doc': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'history_set'", 'to': u"orm['doc.Document']"}),
|
||||
'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': u"orm['group.Group']", 'null': 'True', 'blank': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'intended_std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': u"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'}),
|
||||
'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', [], {'to': u"orm['doc.DocAlias']", 'symmetrical': 'False', 'through': u"orm['doc.RelatedDocHistory']", 'blank': 'True'}),
|
||||
'rev': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}),
|
||||
'shepherd': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'shepherd_dochistory_set'", 'null': 'True', 'to': u"orm['person.Person']"}),
|
||||
'shepherd_email': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'shepherd_dochistory_set'", 'null': 'True', 'to': u"orm['person.Email']"}),
|
||||
'states': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.StdLevelName']", 'null': 'True', 'blank': 'True'}),
|
||||
'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.StreamName']", 'null': 'True', 'blank': 'True'}),
|
||||
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"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': u"orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
u'doc.dochistoryauthor': {
|
||||
'Meta': {'ordering': "['document', 'order']", 'object_name': 'DocHistoryAuthor'},
|
||||
'author': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Email']"}),
|
||||
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.DocHistory']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {})
|
||||
},
|
||||
u'doc.docreminder': {
|
||||
'Meta': {'object_name': 'DocReminder'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'due': ('django.db.models.fields.DateTimeField', [], {}),
|
||||
'event': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.DocEvent']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.DocReminderTypeName']"})
|
||||
},
|
||||
u'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': u"orm['person.Person']"}),
|
||||
'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['person.Email']", 'symmetrical': 'False', 'through': u"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': u"orm['group.Group']", 'null': 'True', 'blank': 'True'}),
|
||||
'intended_std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': u"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'}),
|
||||
'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': u"orm['person.Person']"}),
|
||||
'shepherd_email': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'shepherd_document_set'", 'null': 'True', 'to': u"orm['person.Email']"}),
|
||||
'states': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.StdLevelName']", 'null': 'True', 'blank': 'True'}),
|
||||
'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.StreamName']", 'null': 'True', 'blank': 'True'}),
|
||||
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"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': u"orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
u'doc.documentauthor': {
|
||||
'Meta': {'ordering': "['document', 'order']", 'object_name': 'DocumentAuthor'},
|
||||
'author': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Email']"}),
|
||||
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.Document']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '1'})
|
||||
},
|
||||
u'doc.initialreviewdocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'InitialReviewDocEvent', '_ormbases': [u'doc.DocEvent']},
|
||||
u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
u'doc.lastcalldocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'LastCallDocEvent', '_ormbases': [u'doc.DocEvent']},
|
||||
u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
u'doc.newrevisiondocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'NewRevisionDocEvent', '_ormbases': [u'doc.DocEvent']},
|
||||
u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'rev': ('django.db.models.fields.CharField', [], {'max_length': '16'})
|
||||
},
|
||||
u'doc.relateddochistory': {
|
||||
'Meta': {'object_name': 'RelatedDocHistory'},
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'relationship': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.DocRelationshipName']"}),
|
||||
'source': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.DocHistory']"}),
|
||||
'target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reversely_related_document_history_set'", 'to': u"orm['doc.DocAlias']"})
|
||||
},
|
||||
u'doc.relateddocument': {
|
||||
'Meta': {'object_name': 'RelatedDocument'},
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'relationship': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.DocRelationshipName']"}),
|
||||
'source': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.Document']"}),
|
||||
'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.DocAlias']"})
|
||||
},
|
||||
u'doc.state': {
|
||||
'Meta': {'ordering': "['type', 'order']", 'object_name': 'State'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
u'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', [], {'symmetrical': 'False', 'related_name': "'previous_states'", 'blank': 'True', 'to': u"orm['doc.State']"}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
|
||||
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.StateType']"}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
u'doc.statedocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'StateDocEvent', '_ormbases': [u'doc.DocEvent']},
|
||||
u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.State']", 'null': 'True', 'blank': 'True'}),
|
||||
'state_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.StateType']"})
|
||||
},
|
||||
u'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'})
|
||||
},
|
||||
u'doc.telechatdocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'TelechatDocEvent', '_ormbases': [u'doc.DocEvent']},
|
||||
u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'returning_item': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'telechat_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
u'doc.writeupdocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'WriteupDocEvent', '_ormbases': [u'doc.DocEvent']},
|
||||
u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'text': ('django.db.models.fields.TextField', [], {'blank': 'True'})
|
||||
},
|
||||
u'group.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
'acronym': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '40'}),
|
||||
'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': u"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': u"orm['doc.Document']"}),
|
||||
'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
u'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': u"orm['group.Group']", 'null': 'True', 'blank': 'True'}),
|
||||
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.GroupStateName']", 'null': 'True'}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.GroupTypeName']", 'null': 'True'}),
|
||||
'unused_states': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'unused_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['name.DocTagName']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
u'name.ballotpositionname': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'BallotPositionName'},
|
||||
'blocking': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'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': '32', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
u'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'}),
|
||||
'revname': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
u'name.docremindertypename': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'DocReminderTypeName'},
|
||||
'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': '32', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
u'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': '32', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
u'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': '32', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
u'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': '32', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
u'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': '32', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
u'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': '32', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
u'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': '32', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
u'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': '32', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
u'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': u"orm['person.Person']", 'null': 'True'}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'})
|
||||
},
|
||||
u'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'}),
|
||||
u'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': u"orm['auth.User']", 'unique': 'True', 'null': 'True', 'blank': 'True'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['doc']
|
377
ietf/doc/migrations/0022_fill_in_shepherd_email.py
Normal file
377
ietf/doc/migrations/0022_fill_in_shepherd_email.py
Normal file
|
@ -0,0 +1,377 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from south.v2 import DataMigration
|
||||
|
||||
class Migration(DataMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
# figure out person -> email mapping
|
||||
shepherds = set(orm.Document.objects.values_list("shepherd", flat=True).distinct())
|
||||
shepherds.update(orm.DocHistory.objects.values_list("shepherd", flat=True).distinct())
|
||||
|
||||
for person_id in shepherds:
|
||||
emails = orm['person.Email'].objects.filter(person=person_id).order_by("-active", "-time")[:1]
|
||||
if not emails:
|
||||
print "ERROR: no emails for", person_id
|
||||
|
||||
email = emails[0]
|
||||
|
||||
orm.Document.objects.filter(shepherd=person_id, shepherd_email=None).update(shepherd_email=email)
|
||||
orm.DocHistory.objects.filter(shepherd=person_id, shepherd_email=None).update(shepherd_email=email)
|
||||
|
||||
def backwards(self, orm):
|
||||
pass
|
||||
|
||||
models = {
|
||||
u'auth.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
u'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': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
u'auth.permission': {
|
||||
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
|
||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
u'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', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
|
||||
u'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', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
|
||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'})
|
||||
},
|
||||
u'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'}),
|
||||
u'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'})
|
||||
},
|
||||
u'doc.ballotdocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'BallotDocEvent', '_ormbases': [u'doc.DocEvent']},
|
||||
'ballot_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.BallotType']"}),
|
||||
u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'})
|
||||
},
|
||||
u'doc.ballotpositiondocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'BallotPositionDocEvent', '_ormbases': [u'doc.DocEvent']},
|
||||
'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']"}),
|
||||
'ballot': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['doc.BallotDocEvent']", 'null': 'True'}),
|
||||
'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'comment_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'discuss': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'discuss_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'pos': ('django.db.models.fields.related.ForeignKey', [], {'default': "'norecord'", 'to': u"orm['name.BallotPositionName']"})
|
||||
},
|
||||
u'doc.ballottype': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'BallotType'},
|
||||
'doc_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'positions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['name.BallotPositionName']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'question': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
u'doc.consensusdocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'ConsensusDocEvent', '_ormbases': [u'doc.DocEvent']},
|
||||
'consensus': ('django.db.models.fields.NullBooleanField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}),
|
||||
u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'})
|
||||
},
|
||||
u'doc.deletedevent': {
|
||||
'Meta': {'object_name': 'DeletedEvent'},
|
||||
'by': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']"}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'json': ('django.db.models.fields.TextField', [], {}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})
|
||||
},
|
||||
u'doc.docalias': {
|
||||
'Meta': {'object_name': 'DocAlias'},
|
||||
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.Document']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'})
|
||||
},
|
||||
u'doc.docevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'DocEvent'},
|
||||
'by': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']"}),
|
||||
'desc': ('django.db.models.fields.TextField', [], {}),
|
||||
'doc': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.Document']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'db_index': 'True'}),
|
||||
'type': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
u'doc.dochistory': {
|
||||
'Meta': {'object_name': 'DocHistory'},
|
||||
'abstract': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'ad': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'ad_dochistory_set'", 'null': 'True', 'to': u"orm['person.Person']"}),
|
||||
'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['person.Email']", 'symmetrical': 'False', 'through': u"orm['doc.DocHistoryAuthor']", 'blank': 'True'}),
|
||||
'doc': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'history_set'", 'to': u"orm['doc.Document']"}),
|
||||
'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': u"orm['group.Group']", 'null': 'True', 'blank': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'intended_std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': u"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'}),
|
||||
'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', [], {'to': u"orm['doc.DocAlias']", 'symmetrical': 'False', 'through': u"orm['doc.RelatedDocHistory']", 'blank': 'True'}),
|
||||
'rev': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}),
|
||||
'shepherd': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'shepherd_dochistory_set'", 'null': 'True', 'to': u"orm['person.Person']"}),
|
||||
'shepherd_email': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'shepherd_dochistory_set'", 'null': 'True', 'to': u"orm['person.Email']"}),
|
||||
'states': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.StdLevelName']", 'null': 'True', 'blank': 'True'}),
|
||||
'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.StreamName']", 'null': 'True', 'blank': 'True'}),
|
||||
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"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': u"orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
u'doc.dochistoryauthor': {
|
||||
'Meta': {'ordering': "['document', 'order']", 'object_name': 'DocHistoryAuthor'},
|
||||
'author': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Email']"}),
|
||||
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.DocHistory']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {})
|
||||
},
|
||||
u'doc.docreminder': {
|
||||
'Meta': {'object_name': 'DocReminder'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'due': ('django.db.models.fields.DateTimeField', [], {}),
|
||||
'event': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.DocEvent']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.DocReminderTypeName']"})
|
||||
},
|
||||
u'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': u"orm['person.Person']"}),
|
||||
'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['person.Email']", 'symmetrical': 'False', 'through': u"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': u"orm['group.Group']", 'null': 'True', 'blank': 'True'}),
|
||||
'intended_std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': u"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'}),
|
||||
'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': u"orm['person.Person']"}),
|
||||
'shepherd_email': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'shepherd_document_set'", 'null': 'True', 'to': u"orm['person.Email']"}),
|
||||
'states': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.StdLevelName']", 'null': 'True', 'blank': 'True'}),
|
||||
'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.StreamName']", 'null': 'True', 'blank': 'True'}),
|
||||
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"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': u"orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
u'doc.documentauthor': {
|
||||
'Meta': {'ordering': "['document', 'order']", 'object_name': 'DocumentAuthor'},
|
||||
'author': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Email']"}),
|
||||
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.Document']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '1'})
|
||||
},
|
||||
u'doc.initialreviewdocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'InitialReviewDocEvent', '_ormbases': [u'doc.DocEvent']},
|
||||
u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
u'doc.lastcalldocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'LastCallDocEvent', '_ormbases': [u'doc.DocEvent']},
|
||||
u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
u'doc.newrevisiondocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'NewRevisionDocEvent', '_ormbases': [u'doc.DocEvent']},
|
||||
u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'rev': ('django.db.models.fields.CharField', [], {'max_length': '16'})
|
||||
},
|
||||
u'doc.relateddochistory': {
|
||||
'Meta': {'object_name': 'RelatedDocHistory'},
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'relationship': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.DocRelationshipName']"}),
|
||||
'source': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.DocHistory']"}),
|
||||
'target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reversely_related_document_history_set'", 'to': u"orm['doc.DocAlias']"})
|
||||
},
|
||||
u'doc.relateddocument': {
|
||||
'Meta': {'object_name': 'RelatedDocument'},
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'relationship': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.DocRelationshipName']"}),
|
||||
'source': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.Document']"}),
|
||||
'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.DocAlias']"})
|
||||
},
|
||||
u'doc.state': {
|
||||
'Meta': {'ordering': "['type', 'order']", 'object_name': 'State'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
u'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', [], {'symmetrical': 'False', 'related_name': "'previous_states'", 'blank': 'True', 'to': u"orm['doc.State']"}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
|
||||
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.StateType']"}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
u'doc.statedocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'StateDocEvent', '_ormbases': [u'doc.DocEvent']},
|
||||
u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.State']", 'null': 'True', 'blank': 'True'}),
|
||||
'state_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.StateType']"})
|
||||
},
|
||||
u'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'})
|
||||
},
|
||||
u'doc.telechatdocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'TelechatDocEvent', '_ormbases': [u'doc.DocEvent']},
|
||||
u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'returning_item': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'telechat_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
u'doc.writeupdocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'WriteupDocEvent', '_ormbases': [u'doc.DocEvent']},
|
||||
u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'text': ('django.db.models.fields.TextField', [], {'blank': 'True'})
|
||||
},
|
||||
u'group.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
'acronym': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '40'}),
|
||||
'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': u"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': u"orm['doc.Document']"}),
|
||||
'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
u'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': u"orm['group.Group']", 'null': 'True', 'blank': 'True'}),
|
||||
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.GroupStateName']", 'null': 'True'}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.GroupTypeName']", 'null': 'True'}),
|
||||
'unused_states': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'unused_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['name.DocTagName']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
u'name.ballotpositionname': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'BallotPositionName'},
|
||||
'blocking': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'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': '32', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
u'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'}),
|
||||
'revname': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
u'name.docremindertypename': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'DocReminderTypeName'},
|
||||
'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': '32', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
u'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': '32', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
u'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': '32', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
u'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': '32', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
u'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': '32', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
u'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': '32', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
u'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': '32', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
u'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': '32', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
u'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': u"orm['person.Person']", 'null': 'True'}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'})
|
||||
},
|
||||
u'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'}),
|
||||
u'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': u"orm['auth.User']", 'unique': 'True', 'null': 'True', 'blank': 'True'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['doc']
|
||||
symmetrical = True
|
|
@ -0,0 +1,375 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
db.delete_column(u'doc_document', 'shepherd_id')
|
||||
db.rename_column(u'doc_document', 'shepherd_email_id', 'shepherd_id')
|
||||
db.delete_column(u'doc_dochistory', 'shepherd_id')
|
||||
db.rename_column(u'doc_dochistory', 'shepherd_email_id', 'shepherd_id')
|
||||
|
||||
def backwards(self, orm):
|
||||
db.rename_column(u'doc_document', 'shepherd_id', 'shepherd_email_id')
|
||||
db.add_column(u'doc_document', 'shepherd',
|
||||
self.gf('django.db.models.fields.related.ForeignKey')(related_name='shepherd_document_set', null=True, to=orm['person.Person'], blank=True),
|
||||
keep_default=False)
|
||||
|
||||
db.rename_column(u'doc_dochistory', 'shepherd_id', 'shepherd_email_id')
|
||||
db.add_column(u'doc_dochistory', 'shepherd',
|
||||
self.gf('django.db.models.fields.related.ForeignKey')(related_name='shepherd_document_set', null=True, to=orm['person.Person'], blank=True),
|
||||
keep_default=False)
|
||||
|
||||
models = {
|
||||
u'auth.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
u'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': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
u'auth.permission': {
|
||||
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
|
||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
u'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', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
|
||||
u'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', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
|
||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'})
|
||||
},
|
||||
u'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'}),
|
||||
u'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'})
|
||||
},
|
||||
u'doc.ballotdocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'BallotDocEvent', '_ormbases': [u'doc.DocEvent']},
|
||||
'ballot_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.BallotType']"}),
|
||||
u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'})
|
||||
},
|
||||
u'doc.ballotpositiondocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'BallotPositionDocEvent', '_ormbases': [u'doc.DocEvent']},
|
||||
'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']"}),
|
||||
'ballot': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['doc.BallotDocEvent']", 'null': 'True'}),
|
||||
'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'comment_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'discuss': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'discuss_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'pos': ('django.db.models.fields.related.ForeignKey', [], {'default': "'norecord'", 'to': u"orm['name.BallotPositionName']"})
|
||||
},
|
||||
u'doc.ballottype': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'BallotType'},
|
||||
'doc_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'positions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['name.BallotPositionName']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'question': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
u'doc.consensusdocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'ConsensusDocEvent', '_ormbases': [u'doc.DocEvent']},
|
||||
'consensus': ('django.db.models.fields.NullBooleanField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}),
|
||||
u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'})
|
||||
},
|
||||
u'doc.deletedevent': {
|
||||
'Meta': {'object_name': 'DeletedEvent'},
|
||||
'by': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']"}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'json': ('django.db.models.fields.TextField', [], {}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})
|
||||
},
|
||||
u'doc.docalias': {
|
||||
'Meta': {'object_name': 'DocAlias'},
|
||||
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.Document']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'})
|
||||
},
|
||||
u'doc.docevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'DocEvent'},
|
||||
'by': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']"}),
|
||||
'desc': ('django.db.models.fields.TextField', [], {}),
|
||||
'doc': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.Document']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'db_index': 'True'}),
|
||||
'type': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
u'doc.dochistory': {
|
||||
'Meta': {'object_name': 'DocHistory'},
|
||||
'abstract': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'ad': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'ad_dochistory_set'", 'null': 'True', 'to': u"orm['person.Person']"}),
|
||||
'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['person.Email']", 'symmetrical': 'False', 'through': u"orm['doc.DocHistoryAuthor']", 'blank': 'True'}),
|
||||
'doc': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'history_set'", 'to': u"orm['doc.Document']"}),
|
||||
'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': u"orm['group.Group']", 'null': 'True', 'blank': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'intended_std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': u"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'}),
|
||||
'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', [], {'to': u"orm['doc.DocAlias']", 'symmetrical': 'False', 'through': u"orm['doc.RelatedDocHistory']", 'blank': 'True'}),
|
||||
'rev': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}),
|
||||
'shepherd': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'shepherd_dochistory_set'", 'null': 'True', 'to': u"orm['person.Email']"}),
|
||||
'states': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.StdLevelName']", 'null': 'True', 'blank': 'True'}),
|
||||
'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.StreamName']", 'null': 'True', 'blank': 'True'}),
|
||||
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"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': u"orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
u'doc.dochistoryauthor': {
|
||||
'Meta': {'ordering': "['document', 'order']", 'object_name': 'DocHistoryAuthor'},
|
||||
'author': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Email']"}),
|
||||
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.DocHistory']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {})
|
||||
},
|
||||
u'doc.docreminder': {
|
||||
'Meta': {'object_name': 'DocReminder'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'due': ('django.db.models.fields.DateTimeField', [], {}),
|
||||
'event': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.DocEvent']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.DocReminderTypeName']"})
|
||||
},
|
||||
u'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': u"orm['person.Person']"}),
|
||||
'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['person.Email']", 'symmetrical': 'False', 'through': u"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': u"orm['group.Group']", 'null': 'True', 'blank': 'True'}),
|
||||
'intended_std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': u"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'}),
|
||||
'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': u"orm['person.Email']"}),
|
||||
'states': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.StdLevelName']", 'null': 'True', 'blank': 'True'}),
|
||||
'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.StreamName']", 'null': 'True', 'blank': 'True'}),
|
||||
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"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': u"orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
u'doc.documentauthor': {
|
||||
'Meta': {'ordering': "['document', 'order']", 'object_name': 'DocumentAuthor'},
|
||||
'author': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Email']"}),
|
||||
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.Document']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '1'})
|
||||
},
|
||||
u'doc.initialreviewdocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'InitialReviewDocEvent', '_ormbases': [u'doc.DocEvent']},
|
||||
u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
u'doc.lastcalldocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'LastCallDocEvent', '_ormbases': [u'doc.DocEvent']},
|
||||
u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
u'doc.newrevisiondocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'NewRevisionDocEvent', '_ormbases': [u'doc.DocEvent']},
|
||||
u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'rev': ('django.db.models.fields.CharField', [], {'max_length': '16'})
|
||||
},
|
||||
u'doc.relateddochistory': {
|
||||
'Meta': {'object_name': 'RelatedDocHistory'},
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'relationship': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.DocRelationshipName']"}),
|
||||
'source': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.DocHistory']"}),
|
||||
'target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reversely_related_document_history_set'", 'to': u"orm['doc.DocAlias']"})
|
||||
},
|
||||
u'doc.relateddocument': {
|
||||
'Meta': {'object_name': 'RelatedDocument'},
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'relationship': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.DocRelationshipName']"}),
|
||||
'source': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.Document']"}),
|
||||
'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.DocAlias']"})
|
||||
},
|
||||
u'doc.state': {
|
||||
'Meta': {'ordering': "['type', 'order']", 'object_name': 'State'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
u'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', [], {'symmetrical': 'False', 'related_name': "'previous_states'", 'blank': 'True', 'to': u"orm['doc.State']"}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
|
||||
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.StateType']"}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
u'doc.statedocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'StateDocEvent', '_ormbases': [u'doc.DocEvent']},
|
||||
u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.State']", 'null': 'True', 'blank': 'True'}),
|
||||
'state_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.StateType']"})
|
||||
},
|
||||
u'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'})
|
||||
},
|
||||
u'doc.telechatdocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'TelechatDocEvent', '_ormbases': [u'doc.DocEvent']},
|
||||
u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'returning_item': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'telechat_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
u'doc.writeupdocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'WriteupDocEvent', '_ormbases': [u'doc.DocEvent']},
|
||||
u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'text': ('django.db.models.fields.TextField', [], {'blank': 'True'})
|
||||
},
|
||||
u'group.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
'acronym': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '40'}),
|
||||
'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': u"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': u"orm['doc.Document']"}),
|
||||
'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
u'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': u"orm['group.Group']", 'null': 'True', 'blank': 'True'}),
|
||||
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.GroupStateName']", 'null': 'True'}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.GroupTypeName']", 'null': 'True'}),
|
||||
'unused_states': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'unused_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['name.DocTagName']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
u'name.ballotpositionname': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'BallotPositionName'},
|
||||
'blocking': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'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': '32', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
u'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'}),
|
||||
'revname': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
u'name.docremindertypename': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'DocReminderTypeName'},
|
||||
'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': '32', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
u'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': '32', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
u'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': '32', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
u'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': '32', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
u'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': '32', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
u'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': '32', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
u'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': '32', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
u'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': '32', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
u'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': u"orm['person.Person']", 'null': 'True'}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'})
|
||||
},
|
||||
u'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'}),
|
||||
u'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': u"orm['auth.User']", 'unique': 'True', 'null': 'True', 'blank': 'True'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['doc']
|
|
@ -64,7 +64,7 @@ class DocumentInfo(models.Model):
|
|||
intended_std_level = models.ForeignKey(IntendedStdLevelName, verbose_name="Intended standardization level", blank=True, null=True)
|
||||
std_level = models.ForeignKey(StdLevelName, verbose_name="Standardization level", blank=True, null=True)
|
||||
ad = models.ForeignKey(Person, verbose_name="area director", related_name='ad_%(class)s_set', blank=True, null=True)
|
||||
shepherd = models.ForeignKey(Person, related_name='shepherd_%(class)s_set', blank=True, null=True)
|
||||
shepherd = models.ForeignKey(Email, related_name='shepherd_%(class)s_set', blank=True, null=True)
|
||||
expires = models.DateTimeField(blank=True, null=True)
|
||||
notify = models.CharField(max_length=255, blank=True)
|
||||
external_url = models.URLField(blank=True) # Should be set for documents with type 'External'.
|
||||
|
|
|
@ -819,6 +819,9 @@ class IndividualInfoFormsTests(TestCase):
|
|||
self.assertTrue(self.doc.latest_event(DocEvent,type="added_comment").desc.startswith('Shepherding AD changed'))
|
||||
|
||||
def test_doc_change_shepherd(self):
|
||||
self.doc.shepherd = None
|
||||
self.doc.save()
|
||||
|
||||
url = urlreverse('doc_edit_shepherd',kwargs=dict(name=self.docname))
|
||||
|
||||
login_testing_unauthorized(self, "plain", url)
|
||||
|
@ -835,23 +838,51 @@ class IndividualInfoFormsTests(TestCase):
|
|||
self.assertEqual(len(q('form input[id=id_shepherd]')),1)
|
||||
|
||||
# change the shepherd
|
||||
plain = Person.objects.get(name='Plain Man')
|
||||
plain_email = plain.email_set.all()[0]
|
||||
r = self.client.post(url,dict(shepherd=plain_email))
|
||||
plain_email = Email.objects.get(person__name="Plain Man")
|
||||
r = self.client.post(url, dict(shepherd=plain_email.pk))
|
||||
self.assertEqual(r.status_code,302)
|
||||
self.doc = Document.objects.get(name=self.docname)
|
||||
self.assertEqual(self.doc.shepherd,plain)
|
||||
self.assertEqual(self.doc.shepherd, plain_email)
|
||||
comments = '::'.join([x.desc for x in self.doc.docevent_set.filter(time=self.doc.time,type="added_comment")])
|
||||
self.assertTrue('Document shepherd changed to Plain Man' in comments)
|
||||
self.assertTrue('Notification list changed' in comments)
|
||||
|
||||
# test buggy change
|
||||
ad = Person.objects.get(name='Aread Irector')
|
||||
two_answers = "%s,%s" % (plain_email, ad.email_set.all()[0])
|
||||
r = self.client.post(url,(dict(shepherd=two_answers)))
|
||||
self.assertEqual(r.status_code,200)
|
||||
r = self.client.post(url, dict(shepherd=two_answers))
|
||||
self.assertEqual(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertTrue(len(q('form ul.errorlist')) > 0)
|
||||
|
||||
def test_doc_change_shepherd_email(self):
|
||||
self.doc.shepherd = None
|
||||
self.doc.save()
|
||||
|
||||
url = urlreverse('doc_change_shepherd_email',kwargs=dict(name=self.docname))
|
||||
r = self.client.get(url)
|
||||
self.assertEqual(r.status_code, 404)
|
||||
|
||||
self.doc.shepherd = Email.objects.get(person__user__username="ad1")
|
||||
self.doc.save()
|
||||
|
||||
login_testing_unauthorized(self, "plain", url)
|
||||
|
||||
self.doc.shepherd = Email.objects.get(person__user__username="plain")
|
||||
self.doc.save()
|
||||
|
||||
new_email = Email.objects.create(address="anotheremail@example.com", person=self.doc.shepherd.person)
|
||||
|
||||
r = self.client.get(url)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
|
||||
# change the shepherd email
|
||||
r = self.client.post(url, dict(shepherd=new_email))
|
||||
self.assertEqual(r.status_code, 302)
|
||||
self.doc = Document.objects.get(name=self.docname)
|
||||
self.assertEqual(self.doc.shepherd, new_email)
|
||||
self.assertTrue(self.doc.latest_event(DocEvent, type="added_comment").desc.startswith('Document shepherd email changed'))
|
||||
|
||||
def test_doc_view_shepherd_writeup(self):
|
||||
url = urlreverse('doc_shepherd_writeup',kwargs=dict(name=self.docname))
|
||||
|
||||
|
|
|
@ -81,6 +81,7 @@ urlpatterns = patterns('',
|
|||
url(r'^(?P<name>[A-Za-z0-9._+-]+)/edit/ad/$', views_draft.edit_ad, name='doc_change_ad'),
|
||||
url(r'^(?P<name>[A-Za-z0-9._+-]+)/edit/consensus/$', views_draft.edit_consensus, name='doc_edit_consensus'),
|
||||
url(r'^(?P<name>[A-Za-z0-9._+-]+)/edit/shepherd/$', views_draft.edit_shepherd, name='doc_edit_shepherd'),
|
||||
url(r'^(?P<name>[A-Za-z0-9._+-]+)/edit/shepherdemail/$', views_draft.change_shepherd_email, name='doc_change_shepherd_email'),
|
||||
url(r'^(?P<name>[A-Za-z0-9._+-]+)/edit/shepherdwriteup/$', views_draft.edit_shepherd_writeup, name='doc_edit_shepherd_writeup'),
|
||||
url(r'^(?P<name>[A-Za-z0-9._+-]+)/edit/requestpublication/$', views_draft.request_publication, name='doc_request_publication'),
|
||||
url(r'^(?P<name>[A-Za-z0-9._+-]+)/edit/adopt/$', views_draft.adopt_draft, name='doc_adopt_draft'),
|
||||
|
|
|
@ -366,7 +366,7 @@ def start_review_sanity_check(request, name):
|
|||
def build_notify_addresses(doc_to_review):
|
||||
# Take care to do the right thing during ietf chair and stream owner transitions
|
||||
notify_addresses = []
|
||||
notify_addresses.extend([x.person.formatted_email() for x in Role.objects.filter(group__acronym=doc_to_review.stream.slug,name='chair')])
|
||||
notify_addresses.extend([r.formatted_email() for r in Role.objects.filter(group__acronym=doc_to_review.stream.slug, name='chair')])
|
||||
notify_addresses.append("%s@%s" % (doc_to_review.name, settings.TOOLS_SERVER))
|
||||
return notify_addresses
|
||||
|
||||
|
|
|
@ -41,6 +41,8 @@ from django.core.urlresolvers import reverse as urlreverse
|
|||
from django.conf import settings
|
||||
from django import forms
|
||||
|
||||
import debug # pyflakes:ignore
|
||||
|
||||
from ietf.doc.models import ( Document, DocAlias, DocHistory, DocEvent, BallotDocEvent,
|
||||
ConsensusDocEvent, NewRevisionDocEvent, TelechatDocEvent, WriteupDocEvent,
|
||||
IESG_BALLOT_ACTIVE_STATES, STATUSCHANGE_RELATIONS )
|
||||
|
@ -263,7 +265,7 @@ def document_main(request, name, rev=None):
|
|||
shepherd_writeup = doc.latest_event(WriteupDocEvent, type="changed_protocol_writeup")
|
||||
|
||||
can_edit_stream_info = is_authorized_in_doc_stream(request.user, doc)
|
||||
can_edit_shepherd_writeup = can_edit_stream_info or user_is_person(request.user, doc.shepherd) or has_role(request.user, ["Area Director"])
|
||||
can_edit_shepherd_writeup = can_edit_stream_info or user_is_person(request.user, doc.shepherd and doc.shepherd.person) or has_role(request.user, ["Area Director"])
|
||||
can_edit_consensus = False
|
||||
|
||||
consensus = None
|
||||
|
@ -351,6 +353,7 @@ def document_main(request, name, rev=None):
|
|||
can_edit=can_edit,
|
||||
can_change_stream=can_change_stream,
|
||||
can_edit_stream_info=can_edit_stream_info,
|
||||
is_shepherd = user_is_person(request.user, doc.shepherd and doc.shepherd.person),
|
||||
can_edit_shepherd_writeup=can_edit_shepherd_writeup,
|
||||
can_edit_iana_state=can_edit_iana_state,
|
||||
can_edit_consensus=can_edit_consensus,
|
||||
|
@ -659,7 +662,7 @@ def document_shepherd_writeup(request, name):
|
|||
writeup_text = "(There is no shepherd's writeup available for this document)"
|
||||
|
||||
can_edit_stream_info = is_authorized_in_doc_stream(request.user, doc)
|
||||
can_edit_shepherd_writeup = can_edit_stream_info or user_is_person(request.user, doc.shepherd) or has_role(request.user, ["Area Director"])
|
||||
can_edit_shepherd_writeup = can_edit_stream_info or user_is_person(request.user, doc.shepherd and doc.shepherd.person) or has_role(request.user, ["Area Director"])
|
||||
|
||||
return render_to_response("doc/shepherd_writeup.html",
|
||||
dict(doc=doc,
|
||||
|
|
|
@ -4,7 +4,7 @@ import datetime, json
|
|||
|
||||
from django import forms
|
||||
from django.http import HttpResponseRedirect, HttpResponseForbidden, Http404
|
||||
from django.shortcuts import render_to_response, get_object_or_404, redirect
|
||||
from django.shortcuts import render_to_response, get_object_or_404, redirect, render
|
||||
from django.template.loader import render_to_string
|
||||
from django.template import RequestContext
|
||||
from django.conf import settings
|
||||
|
@ -29,8 +29,8 @@ from ietf.ietfauth.utils import has_role, is_authorized_in_doc_stream, user_is_p
|
|||
from ietf.ietfauth.utils import role_required
|
||||
from ietf.message.models import Message
|
||||
from ietf.name.models import IntendedStdLevelName, DocTagName, StreamName
|
||||
from ietf.person.forms import EmailsField
|
||||
from ietf.person.models import Person
|
||||
from ietf.person.fields import AutocompletedEmailField
|
||||
from ietf.person.models import Person, Email
|
||||
from ietf.secr.lib.template import jsonapi
|
||||
from ietf.utils.mail import send_mail, send_mail_message
|
||||
from ietf.utils.textupload import get_cleaned_text_file_content
|
||||
|
@ -301,10 +301,8 @@ def collect_email_addresses(emails, doc):
|
|||
for role in doc.group.parent.role_set.filter(name='chair'):
|
||||
if role.email.address not in emails:
|
||||
emails[role.email.address] = '"%s"' % (role.person.name)
|
||||
if doc.shepherd:
|
||||
address = doc.shepherd.email_address();
|
||||
if address not in emails:
|
||||
emails[address] = '"%s"' % (doc.shepherd.name)
|
||||
if doc.shepherd and doc.shepherd.address not in emails:
|
||||
emails[doc.shepherd.address] = u'"%s"' % (doc.shepherd.person.name or "")
|
||||
return emails
|
||||
|
||||
class ReplacesForm(forms.Form):
|
||||
|
@ -941,13 +939,7 @@ def edit_shepherd_writeup(request, name):
|
|||
context_instance=RequestContext(request))
|
||||
|
||||
class ShepherdForm(forms.Form):
|
||||
shepherd = EmailsField(label="Shepherd", required=False)
|
||||
|
||||
def clean_shepherd(self):
|
||||
data = self.cleaned_data['shepherd']
|
||||
if len(data)>1:
|
||||
raise forms.ValidationError("Please choose at most one shepherd.")
|
||||
return data
|
||||
shepherd = AutocompletedEmailField(required=False, only_users=True)
|
||||
|
||||
def edit_shepherd(request, name):
|
||||
"""Change the shepherd for a Document"""
|
||||
|
@ -955,30 +947,29 @@ def edit_shepherd(request, name):
|
|||
doc = get_object_or_404(Document, type="draft", name=name)
|
||||
|
||||
can_edit_stream_info = is_authorized_in_doc_stream(request.user, doc)
|
||||
|
||||
if not can_edit_stream_info:
|
||||
return HttpResponseForbidden("You do not have the necessary permissions to view this page")
|
||||
|
||||
if request.method == 'POST':
|
||||
form = ShepherdForm(request.POST)
|
||||
if form.is_valid():
|
||||
save_document_in_history(doc)
|
||||
|
||||
if form.cleaned_data['shepherd']:
|
||||
doc.shepherd = form.cleaned_data['shepherd'][0].person
|
||||
else:
|
||||
doc.shepherd = None
|
||||
if form.cleaned_data['shepherd'] != doc.shepherd:
|
||||
doc.shepherd = form.cleaned_data['shepherd']
|
||||
doc.save()
|
||||
|
||||
login = request.user.person
|
||||
c = DocEvent(type="added_comment", doc=doc, by=login)
|
||||
c.desc = "Document shepherd changed to "+ (doc.shepherd.name if doc.shepherd else "(None)")
|
||||
c.save()
|
||||
c = DocEvent(type="added_comment", doc=doc, by=request.user.person)
|
||||
c.desc = "Document shepherd changed to "+ (doc.shepherd.person.name if doc.shepherd else "(None)")
|
||||
c.save()
|
||||
|
||||
if doc.shepherd.formatted_email() not in doc.notify:
|
||||
login = request.user.person
|
||||
addrs = doc.notify
|
||||
if addrs:
|
||||
addrs += ', '
|
||||
addrs += doc.shepherd.formatted_email()
|
||||
e = make_notify_changed_event(request, doc, login, addrs, c.time)
|
||||
make_notify_changed_event(request, doc, login, addrs, c.time)
|
||||
doc.notify = addrs
|
||||
|
||||
doc.time = c.time
|
||||
|
@ -987,19 +978,55 @@ def edit_shepherd(request, name):
|
|||
return redirect('doc_view', name=doc.name)
|
||||
|
||||
else:
|
||||
current_shepherd = None
|
||||
if doc.shepherd:
|
||||
e = doc.shepherd.email_set.order_by("-active", "-time")
|
||||
if e:
|
||||
current_shepherd=e[0].pk
|
||||
init = { "shepherd": current_shepherd}
|
||||
form = ShepherdForm(initial=init)
|
||||
form = ShepherdForm(initial={ "shepherd": doc.shepherd_id })
|
||||
|
||||
return render_to_response('doc/change_shepherd.html',
|
||||
{'form': form,
|
||||
'doc': doc,
|
||||
},
|
||||
context_instance = RequestContext(request))
|
||||
return render(request, 'doc/change_shepherd.html', {
|
||||
'form': form,
|
||||
'doc': doc,
|
||||
})
|
||||
|
||||
class ChangeShepherdEmailForm(forms.Form):
|
||||
shepherd = forms.ModelChoiceField(queryset=Email.objects.all(), label="Shepherd email", empty_label=None)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ChangeShepherdEmailForm, self).__init__(*args, **kwargs)
|
||||
self.fields["shepherd"].queryset = self.fields["shepherd"].queryset.filter(person__email=self.initial["shepherd"]).distinct()
|
||||
|
||||
def change_shepherd_email(request, name):
|
||||
"""Change the shepherd email address for a Document"""
|
||||
doc = get_object_or_404(Document, name=name)
|
||||
|
||||
if not doc.shepherd:
|
||||
raise Http404
|
||||
|
||||
can_edit_stream_info = is_authorized_in_doc_stream(request.user, doc)
|
||||
is_shepherd = user_is_person(request.user, doc.shepherd and doc.shepherd.person)
|
||||
if not can_edit_stream_info and not is_shepherd:
|
||||
return HttpResponseForbidden("You do not have the necessary permissions to view this page")
|
||||
|
||||
initial = { "shepherd": doc.shepherd_id }
|
||||
if request.method == 'POST':
|
||||
form = ChangeShepherdEmailForm(request.POST, initial=initial)
|
||||
if form.is_valid():
|
||||
if form.cleaned_data['shepherd'] != doc.shepherd:
|
||||
save_document_in_history(doc)
|
||||
|
||||
doc.shepherd = form.cleaned_data['shepherd']
|
||||
doc.save()
|
||||
|
||||
c = DocEvent(type="added_comment", doc=doc, by=request.user.person)
|
||||
c.desc = "Document shepherd email changed"
|
||||
c.save()
|
||||
|
||||
return redirect('doc_view', name=doc.name)
|
||||
|
||||
else:
|
||||
form = ChangeShepherdEmailForm(initial=initial)
|
||||
|
||||
return render(request, 'doc/change_shepherd_email.html', {
|
||||
'form': form,
|
||||
'doc': doc,
|
||||
})
|
||||
|
||||
class AdForm(forms.Form):
|
||||
ad = forms.ModelChoiceField(Person.objects.filter(role__name="ad", role__group__state="active").order_by('name'),
|
||||
|
|
|
@ -19,7 +19,7 @@ from ietf.group.models import ( Group, Role, GroupEvent, GroupHistory, GroupStat
|
|||
from ietf.group.utils import save_group_in_history, can_manage_group_type
|
||||
from ietf.group.utils import get_group_or_404
|
||||
from ietf.ietfauth.utils import has_role
|
||||
from ietf.person.forms import EmailsField
|
||||
from ietf.person.fields import AutocompletedEmailsField
|
||||
from ietf.person.models import Person, Email
|
||||
from ietf.group.mails import email_iesg_secretary_re_charter
|
||||
|
||||
|
@ -29,10 +29,11 @@ class GroupForm(forms.Form):
|
|||
name = forms.CharField(max_length=255, label="Name", required=True)
|
||||
acronym = forms.CharField(max_length=10, label="Acronym", required=True)
|
||||
state = forms.ModelChoiceField(GroupStateName.objects.all(), label="State", required=True)
|
||||
chairs = EmailsField(label="Chairs", required=False)
|
||||
secretaries = EmailsField(label="Secretaries", required=False)
|
||||
techadv = EmailsField(label="Technical Advisors", required=False)
|
||||
delegates = EmailsField(label="Delegates", required=False, help_text=mark_safe("Type in name to search for person<br>Chairs can delegate the authority to update the state of group documents - max %s persons at a given time" % MAX_GROUP_DELEGATES))
|
||||
chairs = AutocompletedEmailsField(required=False, only_users=True)
|
||||
secretaries = AutocompletedEmailsField(required=False, only_users=True)
|
||||
techadv = AutocompletedEmailsField(label="Technical Advisors", required=False, only_users=True)
|
||||
delegates = AutocompletedEmailsField(required=False, only_users=True, max_entries=MAX_GROUP_DELEGATES,
|
||||
help_text=mark_safe("Chairs can delegate the authority to update the state of group documents - max %s persons at a given time" % MAX_GROUP_DELEGATES))
|
||||
ad = forms.ModelChoiceField(Person.objects.filter(role__name="ad", role__group__state="active").order_by('name'), label="Shepherding AD", empty_label="(None)", required=False)
|
||||
parent = forms.ModelChoiceField(Group.objects.filter(state="active").order_by('name'), empty_label="(None)", required=False)
|
||||
list_email = forms.CharField(max_length=64, required=False)
|
||||
|
|
|
@ -10,7 +10,7 @@ from ietf.group.models import Group, GroupEvent, Role
|
|||
from ietf.group.utils import save_group_in_history
|
||||
from ietf.ietfauth.utils import has_role
|
||||
from ietf.name.models import StreamName
|
||||
from ietf.person.forms import EmailsField
|
||||
from ietf.person.fields import AutocompletedEmailsField
|
||||
from ietf.person.models import Email
|
||||
|
||||
import debug # pyflakes:ignore
|
||||
|
@ -31,7 +31,7 @@ def stream_documents(request, acronym):
|
|||
return render_to_response('group/stream_documents.html', {'stream':stream, 'docs':docs, 'meta':meta }, context_instance=RequestContext(request))
|
||||
|
||||
class StreamEditForm(forms.Form):
|
||||
delegates = EmailsField(label="Delegates", required=False, help_text=u"Type in name to search for person")
|
||||
delegates = AutocompletedEmailsField(required=False, only_users=True)
|
||||
|
||||
def stream_edit(request, acronym):
|
||||
group = get_object_or_404(Group, acronym=acronym)
|
||||
|
|
|
@ -13,7 +13,7 @@ from ietf.doc.models import Document, DocEvent, DocumentAuthor, RelatedDocument,
|
|||
from ietf.doc.models import LastCallDocEvent, NewRevisionDocEvent
|
||||
from ietf.doc.models import IESG_SUBSTATE_TAGS
|
||||
from ietf.group.models import Group
|
||||
from ietf.person.models import Person
|
||||
from ietf.person.models import Person, Email
|
||||
|
||||
def all_id_txt():
|
||||
# this returns a lot of data so try to be efficient
|
||||
|
@ -125,8 +125,8 @@ def all_id2_txt():
|
|||
else:
|
||||
l.append(a.author.person.plain_name())
|
||||
|
||||
shepherds = dict((p.pk, p.formatted_email().replace('"', ''))
|
||||
for p in Person.objects.filter(shepherd_document_set__type="draft").distinct())
|
||||
shepherds = dict((e.pk, e.formatted_email().replace('"', ''))
|
||||
for e in Email.objects.filter(shepherd_document_set__type="draft").select_related("person").distinct())
|
||||
ads = dict((p.pk, p.formatted_email().replace('"', ''))
|
||||
for p in Person.objects.filter(ad_document_set__type="draft").distinct())
|
||||
|
||||
|
|
|
@ -97,7 +97,7 @@ class IndexTests(TestCase):
|
|||
self.assertEqual(t[13], draft.title)
|
||||
author = draft.documentauthor_set.order_by("order").get()
|
||||
self.assertEqual(t[14], "%s <%s>" % (author.author.person.name, author.author.address))
|
||||
self.assertEqual(t[15], "%s <%s>" % (draft.shepherd, draft.shepherd.email_address()))
|
||||
self.assertEqual(t[15], "%s <%s>" % (draft.shepherd.person.name, draft.shepherd.address))
|
||||
self.assertEqual(t[16], "%s <%s>" % (draft.ad, draft.ad.email_address()))
|
||||
|
||||
|
||||
|
|
|
@ -17,7 +17,8 @@ from ietf.nomcom.utils import (NOMINATION_RECEIPT_TEMPLATE, FEEDBACK_RECEIPT_TEM
|
|||
get_user_email, validate_private_key, validate_public_key,
|
||||
get_or_create_nominee, create_feedback_email)
|
||||
from ietf.person.models import Email
|
||||
from ietf.utils import fields as custom_fields
|
||||
from ietf.person.fields import AutocompletedEmailField
|
||||
from ietf.utils.fields import MultiEmailField
|
||||
from ietf.utils.mail import send_mail
|
||||
|
||||
|
||||
|
@ -31,10 +32,6 @@ def get_nomcom_group_or_404(year):
|
|||
nomcom__isnull=False)
|
||||
|
||||
|
||||
def get_list(string):
|
||||
return map(unicode.strip, string.replace('\r\n', '').split(','))
|
||||
|
||||
|
||||
class PositionNomineeField(forms.ChoiceField):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
@ -109,7 +106,7 @@ class BaseNomcomForm(object):
|
|||
|
||||
class EditMembersForm(BaseNomcomForm, forms.Form):
|
||||
|
||||
members = custom_fields.MultiEmailField(label="Members email", required=False)
|
||||
members = MultiEmailField(label="Members email", required=False, widget=forms.Textarea)
|
||||
|
||||
fieldsets = [('Members', ('members',))]
|
||||
|
||||
|
@ -133,7 +130,7 @@ class EditMembersFormPreview(FormPreview):
|
|||
|
||||
def preview_get(self, request):
|
||||
"Displays the form"
|
||||
f = self.form(auto_id=AUTO_ID)
|
||||
f = self.form(auto_id=self.get_auto_id(), initial=self.get_initial(request))
|
||||
return render_to_response(self.form_template,
|
||||
{'form': f,
|
||||
'stage_field': self.unused_name('stage'),
|
||||
|
@ -143,14 +140,14 @@ class EditMembersFormPreview(FormPreview):
|
|||
'selected': 'edit_members'},
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
def parse_params(self, *args, **kwargs):
|
||||
def get_initial(self, request):
|
||||
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])
|
||||
return { "members": ",\r\n".join(role.email.address for role in members) }
|
||||
return {}
|
||||
|
||||
def process_preview(self, request, form, context):
|
||||
members_email = get_list(form.cleaned_data['members'])
|
||||
members_email = form.cleaned_data['members']
|
||||
|
||||
members_info = []
|
||||
emails_not_found = []
|
||||
|
@ -233,10 +230,11 @@ class EditChairFormPreview(FormPreview):
|
|||
|
||||
return super(EditChairFormPreview, self).__call__(request, *args, **kwargs)
|
||||
|
||||
def parse_params(self, *args, **kwargs):
|
||||
def get_initial(self, request):
|
||||
chair = self.group.get_chair()
|
||||
if chair:
|
||||
self.form.base_fields['chair'].initial = chair.email.address
|
||||
return { "chair": chair.email.address }
|
||||
return {}
|
||||
|
||||
def process_preview(self, request, form, context):
|
||||
chair_email = form.cleaned_data['chair']
|
||||
|
@ -297,8 +295,8 @@ class EditNomcomForm(BaseNomcomForm, forms.ModelForm):
|
|||
|
||||
class MergeForm(BaseNomcomForm, forms.Form):
|
||||
|
||||
secondary_emails = custom_fields.MultiEmailField(label="Secondary email addresses",
|
||||
help_text="Provide a comma separated list of email addresses. Nominations already received with any of these email address will be moved to show under the primary address")
|
||||
secondary_emails = MultiEmailField(label="Secondary email addresses",
|
||||
help_text="Provide a comma separated list of email addresses. Nominations already received with any of these email address will be moved to show under the primary address", widget=forms.Textarea)
|
||||
primary_email = forms.EmailField(label="Primary email address",
|
||||
widget=forms.TextInput(attrs={'size': '40'}))
|
||||
|
||||
|
@ -312,22 +310,21 @@ class MergeForm(BaseNomcomForm, forms.Form):
|
|||
email = self.cleaned_data['primary_email']
|
||||
nominees = Nominee.objects.get_by_nomcom(self.nomcom).not_duplicated().filter(email__address=email)
|
||||
if not nominees:
|
||||
msg = "Does not exist a nomiee with this email"
|
||||
msg = "No nominee with this email exists"
|
||||
self._errors["primary_email"] = self.error_class([msg])
|
||||
|
||||
return email
|
||||
|
||||
def clean_secondary_emails(self):
|
||||
data = self.cleaned_data['secondary_emails']
|
||||
emails = get_list(data)
|
||||
emails = self.cleaned_data['secondary_emails']
|
||||
for email in emails:
|
||||
nominees = Nominee.objects.get_by_nomcom(self.nomcom).not_duplicated().filter(email__address=email)
|
||||
if not nominees:
|
||||
msg = "Does not exist a nomiee with email %s" % email
|
||||
msg = "No nominee with email %s exists" % email
|
||||
self._errors["primary_email"] = self.error_class([msg])
|
||||
break
|
||||
|
||||
return data
|
||||
return emails
|
||||
|
||||
def clean(self):
|
||||
primary_email = self.cleaned_data.get("primary_email")
|
||||
|
@ -340,7 +337,7 @@ class MergeForm(BaseNomcomForm, forms.Form):
|
|||
|
||||
def save(self):
|
||||
primary_email = self.cleaned_data.get("primary_email")
|
||||
secondary_emails = get_list(self.cleaned_data.get("secondary_emails"))
|
||||
secondary_emails = self.cleaned_data.get("secondary_emails")
|
||||
|
||||
primary_nominee = Nominee.objects.get_by_nomcom(self.nomcom).get(email__address=primary_email)
|
||||
while primary_nominee.duplicated:
|
||||
|
@ -659,6 +656,8 @@ class PositionForm(BaseNomcomForm, forms.ModelForm):
|
|||
fieldsets = [('Position', ('name', 'description',
|
||||
'is_open', 'incumbent'))]
|
||||
|
||||
incumbent = AutocompletedEmailField(required=False)
|
||||
|
||||
class Meta:
|
||||
model = Position
|
||||
fields = ('name', 'description', 'is_open', 'incumbent')
|
||||
|
|
123
ietf/person/fields.py
Normal file
123
ietf/person/fields.py
Normal file
|
@ -0,0 +1,123 @@
|
|||
import json
|
||||
|
||||
from django.utils.html import escape
|
||||
from django import forms
|
||||
from django.core.urlresolvers import reverse as urlreverse
|
||||
|
||||
import debug # pyflakes:ignore
|
||||
|
||||
from ietf.person.models import Email, Person
|
||||
|
||||
def tokeninput_id_name_json(objs):
|
||||
def format_email(e):
|
||||
return escape(u"%s <%s>" % (e.person.name, e.address))
|
||||
def format_person(p):
|
||||
return escape(p.name)
|
||||
|
||||
formatter = format_email if objs and isinstance(objs[0], Email) else format_person
|
||||
|
||||
return json.dumps([{ "id": o.pk, "name": formatter(o) } for o in objs])
|
||||
|
||||
class AutocompletedPersonsField(forms.CharField):
|
||||
"""Tokenizing autocompleted multi-select field for choosing
|
||||
persons/emails or just persons using jquery.tokeninput.js.
|
||||
|
||||
The field operates on either Email or Person models. In the case
|
||||
of Email models, the person name is shown next to the email address.
|
||||
|
||||
The field uses a comma-separated list of primary keys in a
|
||||
CharField element as its API, the tokeninput Javascript adds some
|
||||
selection magic on top of this so we have to pass it a JSON
|
||||
representation of ids and user-understandable labels."""
|
||||
|
||||
def __init__(self,
|
||||
max_entries=None, # max number of selected objs
|
||||
only_users=False, # only select persons who also have a user
|
||||
model=Person, # or Email
|
||||
hint_text="Type in name to search for person",
|
||||
*args, **kwargs):
|
||||
kwargs["max_length"] = 1000
|
||||
self.max_entries = max_entries
|
||||
self.only_users = only_users
|
||||
self.model = model
|
||||
|
||||
super(AutocompletedPersonsField, self).__init__(*args, **kwargs)
|
||||
|
||||
self.widget.attrs["class"] = "tokenized-field"
|
||||
self.widget.attrs["data-hint-text"] = hint_text
|
||||
if self.max_entries != None:
|
||||
self.widget.attrs["data-max-entries"] = self.max_entries
|
||||
|
||||
def parse_tokenized_value(self, value):
|
||||
return [x.strip() for x in value.split(",") if x.strip()]
|
||||
|
||||
def prepare_value(self, value):
|
||||
if not value:
|
||||
value = ""
|
||||
if isinstance(value, basestring):
|
||||
pks = self.parse_tokenized_value(value)
|
||||
value = self.model.objects.filter(pk__in=pks).select_related("person")
|
||||
if isinstance(value, self.model):
|
||||
value = [value]
|
||||
|
||||
self.widget.attrs["data-pre"] = tokeninput_id_name_json(value)
|
||||
|
||||
# doing this in the constructor is difficult because the URL
|
||||
# patterns may not have been fully constructed there yet
|
||||
self.widget.attrs["data-ajax-url"] = urlreverse("ajax_tokeninput_search", kwargs={ "model_name": self.model.__name__.lower() })
|
||||
if self.only_users:
|
||||
self.widget.attrs["data-ajax-url"] += "?user=1" # require a Datatracker account
|
||||
|
||||
return ",".join(e.address for e in value)
|
||||
|
||||
def clean(self, value):
|
||||
value = super(AutocompletedPersonsField, self).clean(value)
|
||||
pks = self.parse_tokenized_value(value)
|
||||
|
||||
objs = self.model.objects.filter(pk__in=pks)
|
||||
if self.model == Email:
|
||||
objs = objs.exclude(person=None).select_related("person")
|
||||
|
||||
# there are still a couple of active roles without accounts so don't disallow those yet
|
||||
#if self.only_users:
|
||||
# objs = objs.exclude(person__user=None)
|
||||
|
||||
found_pks = [str(o.pk) for o in objs]
|
||||
failed_pks = [x for x in pks if x not in found_pks]
|
||||
if failed_pks:
|
||||
raise forms.ValidationError(u"Could not recognize the following {model_name}s: {pks}. You can only input {model_name}s already registered in the Datatracker.".format(pks=", ".join(failed_pks), model_name=self.model.__name__.lower()))
|
||||
|
||||
if self.max_entries != None and len(objs) > self.max_entries:
|
||||
raise forms.ValidationError(u"You can select at most %s entries only." % self.max_entries)
|
||||
|
||||
return objs
|
||||
|
||||
class AutocompletedPersonField(AutocompletedPersonsField):
|
||||
"""Version of AutocompletedPersonsField specialized to a single object."""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs["max_entries"] = 1
|
||||
super(AutocompletedPersonField, self).__init__(*args, **kwargs)
|
||||
|
||||
def clean(self, value):
|
||||
return super(AutocompletedPersonField, self).clean(value).first()
|
||||
|
||||
|
||||
class AutocompletedEmailsField(AutocompletedPersonsField):
|
||||
"""Version of AutocompletedPersonsField with the defaults right for Emails."""
|
||||
|
||||
def __init__(self, model=Email, hint_text="Type in name or email to search for person and email address",
|
||||
*args, **kwargs):
|
||||
super(AutocompletedEmailsField, self).__init__(model=model, hint_text=hint_text, *args, **kwargs)
|
||||
|
||||
class AutocompletedEmailField(AutocompletedEmailsField):
|
||||
"""Version of AutocompletedEmailsField specialized to a single object."""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs["max_entries"] = 1
|
||||
super(AutocompletedEmailField, self).__init__(*args, **kwargs)
|
||||
|
||||
def clean(self, value):
|
||||
return super(AutocompletedEmailField, self).clean(value).first()
|
||||
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
import json
|
||||
|
||||
from django.utils.html import escape
|
||||
from django.utils.functional import lazy
|
||||
from django import forms
|
||||
from django.core.urlresolvers import reverse as urlreverse
|
||||
|
||||
import debug # pyflakes:ignore
|
||||
|
||||
from ietf.person.models import Email
|
||||
|
||||
def json_emails(emails):
|
||||
if isinstance(emails, basestring):
|
||||
emails = Email.objects.filter(address__in=[x.strip() for x in emails.split(",") if x.strip()]).select_related("person")
|
||||
return json.dumps([{"id": e.address + "", "name": escape(u"%s <%s>" % (e.person.name, e.address))} for e in emails])
|
||||
|
||||
class EmailsField(forms.CharField):
|
||||
"""Multi-select field using jquery.tokeninput.js. Since the API of
|
||||
tokeninput" is asymmetric, we have to pass it a JSON
|
||||
representation on the way out and parse the ids coming back as a
|
||||
comma-separated list on the way in."""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs["max_length"] = 1000
|
||||
if not "help_text" in kwargs:
|
||||
kwargs["help_text"] = "Type in name to search for person"
|
||||
super(EmailsField, self).__init__(*args, **kwargs)
|
||||
self.widget.attrs["class"] = "tokenized-field"
|
||||
self.widget.attrs["data-ajax-url"] = lazy(urlreverse, str)("ajax_search_emails") # make this lazy to prevent initialization problem
|
||||
|
||||
def parse_tokenized_value(self, value):
|
||||
return Email.objects.filter(address__in=[x.strip() for x in value.split(",") if x.strip()]).select_related("person")
|
||||
|
||||
def prepare_value(self, value):
|
||||
if not value:
|
||||
return ""
|
||||
if isinstance(value, str) or isinstance(value, unicode):
|
||||
value = self.parse_tokenized_value(value)
|
||||
return json_emails(value)
|
||||
|
||||
def clean(self, value):
|
||||
value = super(EmailsField, self).clean(value)
|
||||
return self.parse_tokenized_value(value)
|
||||
|
|
@ -56,15 +56,15 @@ class PersonInfo(models.Model):
|
|||
return e[0]
|
||||
return None
|
||||
def email_address(self):
|
||||
e = self.email_set.filter(active=True).order_by("-time")
|
||||
e = self.email_set.filter(active=True).order_by("-time").first()
|
||||
if e:
|
||||
return e[0].address
|
||||
return e.address
|
||||
else:
|
||||
return ""
|
||||
def formatted_email(self):
|
||||
e = self.email_set.order_by("-active", "-time")
|
||||
e = self.email_set.order_by("-active", "-time").first()
|
||||
if e:
|
||||
return e[0].formatted_email()
|
||||
return e.formatted_email()
|
||||
else:
|
||||
return ""
|
||||
def full_name_as_key(self):
|
||||
|
|
|
@ -11,7 +11,7 @@ class PersonTests(TestCase):
|
|||
draft = make_test_data()
|
||||
person = draft.ad
|
||||
|
||||
r = self.client.get(urlreverse("ietf.person.views.ajax_search_emails"), dict(q=person.name))
|
||||
r = self.client.get(urlreverse("ietf.person.views.ajax_tokeninput_search", kwargs={ "model_name": "email"}), dict(q=person.name))
|
||||
self.assertEqual(r.status_code, 200)
|
||||
data = json.loads(r.content)
|
||||
self.assertEqual(data[0]["id"], person.email_address())
|
||||
|
|
|
@ -2,6 +2,6 @@ from django.conf.urls import patterns
|
|||
from ietf.person import ajax
|
||||
|
||||
urlpatterns = patterns('',
|
||||
(r'^search/$', "ietf.person.views.ajax_search_emails", None, 'ajax_search_emails'),
|
||||
(r'^search/(?P<model_name>(person|email))/$', "ietf.person.views.ajax_tokeninput_search", None, 'ajax_tokeninput_search'),
|
||||
(r'^(?P<personid>[a-z0-9]+).json$', ajax.person_json),
|
||||
)
|
||||
|
|
|
@ -1,8 +1,44 @@
|
|||
from django.http import HttpResponse
|
||||
from django.db.models import Q
|
||||
|
||||
from ietf.person.models import Email
|
||||
from ietf.person.forms import json_emails
|
||||
from ietf.person.models import Email, Person
|
||||
from ietf.person.fields import tokeninput_id_name_json
|
||||
|
||||
def ajax_search_emails(request):
|
||||
emails = Email.objects.filter(person__alias__name__icontains=request.GET.get('q','')).filter(active='true').order_by('person__name').distinct()[:10]
|
||||
return HttpResponse(json_emails(emails), content_type='application/json')
|
||||
def ajax_tokeninput_search(request, model_name):
|
||||
if model_name == "email":
|
||||
model = Email
|
||||
else:
|
||||
model = Person
|
||||
|
||||
q = [w.strip() for w in request.GET.get('q', '').split() if w.strip()]
|
||||
|
||||
if not q:
|
||||
objs = model.objects.none()
|
||||
else:
|
||||
query = Q()
|
||||
for t in q:
|
||||
if model == Email:
|
||||
query &= Q(person__alias__name__icontains=t) | Q(address__icontains=t)
|
||||
elif model == Person:
|
||||
if "@" in t: # allow searching email address if there's a @ in the search term
|
||||
query &= Q(alias__name__icontains=t) | Q(email__address__icontains=t)
|
||||
else:
|
||||
query &= Q(alias__name__icontains=t)
|
||||
|
||||
objs = model.objects.filter(query)
|
||||
|
||||
# require an account at the Datatracker
|
||||
only_users = request.GET.get("user") == "1"
|
||||
|
||||
if model == Email:
|
||||
objs = objs.filter(active=True).order_by('person__name').exclude(person=None)
|
||||
if only_users:
|
||||
objs = objs.exclude(person__user=None)
|
||||
elif model == Person:
|
||||
objs = objs.order_by("name")
|
||||
if only_users:
|
||||
objs = objs.exclude(user=None)
|
||||
|
||||
objs = objs.distinct()[:10]
|
||||
|
||||
return HttpResponse(tokeninput_id_name_json(objs), content_type='application/json')
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
from django import forms
|
||||
from django.core.validators import validate_email
|
||||
|
||||
from ietf.group.models import Group, Role
|
||||
from ietf.ietfauth.utils import has_role
|
||||
from ietf.message.models import Message
|
||||
from ietf.secr.utils.group import current_nomcom
|
||||
from ietf.utils.fields import MultiEmailField
|
||||
|
||||
# ---------------------------------------------
|
||||
# Globals
|
||||
|
@ -42,33 +42,6 @@ TO_LIST = ('IETF Announcement List <ietf-announce@ietf.org>',
|
|||
'Working Group Chairs <wgchairs@ietf.org>',
|
||||
'BoF Chairs <bofchairs@ietf.org>',
|
||||
'Other...')
|
||||
# ---------------------------------------------
|
||||
# Custom Fields
|
||||
# ---------------------------------------------
|
||||
|
||||
class MultiEmailField(forms.Field):
|
||||
def to_python(self, value):
|
||||
"Normalize data to a list of strings."
|
||||
|
||||
# Return an empty list if no input was given.
|
||||
if not value:
|
||||
return []
|
||||
|
||||
import types
|
||||
if isinstance(value, types.StringTypes):
|
||||
values = value.split(',')
|
||||
return [ x.strip() for x in values ]
|
||||
else:
|
||||
return value
|
||||
|
||||
def validate(self, value):
|
||||
"Check if value consists only of valid emails."
|
||||
|
||||
# Use the parent's handling of required fields, etc.
|
||||
super(MultiEmailField, self).validate(value)
|
||||
|
||||
for email in value:
|
||||
validate_email(email)
|
||||
|
||||
# ---------------------------------------------
|
||||
# Helper Functions
|
||||
|
|
|
@ -154,7 +154,7 @@ def get_fullcc_list(draft):
|
|||
|
||||
# add sheperd
|
||||
if draft.shepherd:
|
||||
emails[draft.shepherd.email_address()] = '"%s"' % (draft.shepherd.name)
|
||||
emails[draft.shepherd.address] = '"%s"' % (draft.shepherd.person.name)
|
||||
|
||||
# use sort so we get consistently ordered lists
|
||||
result_list = []
|
||||
|
|
|
@ -8,6 +8,7 @@ from ietf.doc.models import Document, DocAlias, State
|
|||
from ietf.name.models import IntendedStdLevelName, DocRelationshipName
|
||||
from ietf.group.models import Group
|
||||
from ietf.person.models import Person, Email
|
||||
from ietf.person.fields import AutocompletedEmailField
|
||||
from ietf.secr.groups.forms import get_person
|
||||
|
||||
|
||||
|
@ -131,7 +132,7 @@ class EditModelForm(forms.ModelForm):
|
|||
iesg_state = forms.ModelChoiceField(queryset=State.objects.filter(type='draft-iesg'),required=False)
|
||||
group = GroupModelChoiceField(required=True)
|
||||
review_by_rfc_editor = forms.BooleanField(required=False)
|
||||
shepherd = forms.CharField(max_length=100,widget=forms.TextInput(attrs={'class':'name-autocomplete'}),help_text="To see a list of people type the first name, or last name, or both.",required=False)
|
||||
shepherd = AutocompletedEmailField(required=False, only_users=True)
|
||||
|
||||
class Meta:
|
||||
model = Document
|
||||
|
@ -148,8 +149,6 @@ class EditModelForm(forms.ModelForm):
|
|||
self.initial['state'] = self.instance.get_state().pk
|
||||
if self.instance.get_state('draft-iesg'):
|
||||
self.initial['iesg_state'] = self.instance.get_state('draft-iesg').pk
|
||||
if self.instance.shepherd:
|
||||
self.initial['shepherd'] = "%s - (%s)" % (self.instance.shepherd.name, self.instance.shepherd.id)
|
||||
|
||||
# setup special fields
|
||||
if self.instance:
|
||||
|
@ -191,16 +190,6 @@ class EditModelForm(forms.ModelForm):
|
|||
raise forms.ValidationError("ERROR: Draft does not exist")
|
||||
return name
|
||||
|
||||
# check for id within parenthesis to ensure name was selected from the list
|
||||
def clean_shepherd(self):
|
||||
person = self.cleaned_data.get('shepherd', '')
|
||||
m = re.search(r'(\d+)', person)
|
||||
if person and not m:
|
||||
raise forms.ValidationError("You must select an entry from the list!")
|
||||
|
||||
# return person object
|
||||
return get_person(person)
|
||||
|
||||
def clean(self):
|
||||
super(EditModelForm, self).clean()
|
||||
cleaned_data = self.cleaned_data
|
||||
|
|
|
@ -7,7 +7,7 @@ from django.conf import settings
|
|||
from django.contrib import messages
|
||||
from django.db.models import Max
|
||||
from django.forms.formsets import formset_factory
|
||||
from django.shortcuts import render_to_response, get_object_or_404, redirect
|
||||
from django.shortcuts import render_to_response, get_object_or_404, redirect, render
|
||||
from django.template import RequestContext
|
||||
from django.template.loader import render_to_string
|
||||
|
||||
|
@ -799,10 +799,9 @@ def edit(request, id):
|
|||
else:
|
||||
form = EditModelForm(instance=draft)
|
||||
|
||||
return render_to_response('drafts/edit.html', {
|
||||
return render(request, 'drafts/edit.html', {
|
||||
'form': form,
|
||||
'draft': draft},
|
||||
RequestContext(request, {}),
|
||||
)
|
||||
|
||||
def email(request, id):
|
||||
|
|
|
@ -2,7 +2,7 @@ from django import forms
|
|||
|
||||
from ietf.group.models import Group
|
||||
from ietf.meeting.models import ResourceAssociation
|
||||
from ietf.person.forms import EmailsField
|
||||
from ietf.person.fields import AutocompletedPersonsField
|
||||
|
||||
|
||||
# -------------------------------------------------
|
||||
|
@ -67,7 +67,7 @@ class SessionForm(forms.Form):
|
|||
wg_selector3 = forms.ChoiceField(choices=WG_CHOICES,required=False)
|
||||
third_session = forms.BooleanField(required=False)
|
||||
resources = forms.MultipleChoiceField(choices=[(x.pk,x.desc) for x in ResourceAssociation.objects.all()], widget=forms.CheckboxSelectMultiple,required=False)
|
||||
bethere = EmailsField(label="Must be present", required=False)
|
||||
bethere = AutocompletedPersonsField(label="Must be present", required=False)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(SessionForm, self).__init__(*args, **kwargs)
|
||||
|
|
|
@ -16,7 +16,7 @@ from ietf.secr.utils.decorators import check_permissions, sec_only
|
|||
from ietf.secr.utils.group import groups_by_session
|
||||
from ietf.secr.utils.mail import get_ad_email_list, get_chair_email_list, get_cc_list
|
||||
from ietf.utils.mail import send_mail
|
||||
from ietf.person.models import Email
|
||||
from ietf.person.models import Person
|
||||
|
||||
# -------------------------------------------------
|
||||
# Globals
|
||||
|
@ -48,15 +48,8 @@ def get_initial_session(sessions):
|
|||
group = sessions[0].group
|
||||
conflicts = group.constraint_source_set.filter(meeting=meeting)
|
||||
|
||||
bethere_people = [x.person for x in sessions[0].constraints().filter(name='bethere')]
|
||||
bethere_email = []
|
||||
for person in bethere_people:
|
||||
e = person.email_set.order_by("-active","-time").first()
|
||||
if e:
|
||||
bethere_email.append(e)
|
||||
|
||||
# even if there are three sessions requested, the old form has 2 in this field
|
||||
initial['num_session'] = sessions.count() if sessions.count() <= 2 else 2
|
||||
initial['num_session'] = min(sessions.count(), 2)
|
||||
|
||||
# accessing these foreign key fields throw errors if they are unset so we
|
||||
# need to catch these
|
||||
|
@ -72,7 +65,7 @@ def get_initial_session(sessions):
|
|||
initial['conflict3'] = ' '.join([ c.target.acronym for c in conflicts.filter(name__slug='conflic3') ])
|
||||
initial['comments'] = sessions[0].comments
|
||||
initial['resources'] = sessions[0].resources.all()
|
||||
initial['bethere'] = bethere_email
|
||||
initial['bethere'] = [x.person for x in sessions[0].constraints().filter(name='bethere').select_related("person")]
|
||||
return initial
|
||||
|
||||
def get_lock_message(meeting=None):
|
||||
|
@ -234,6 +227,7 @@ def confirm(request, acronym):
|
|||
This view displays details of the new session that has been requested for the user
|
||||
to confirm for submission.
|
||||
'''
|
||||
# FIXME: this should be using form.is_valid/form.cleaned_data - invalid input will make it crash
|
||||
querydict = request.session.get('session_form',None)
|
||||
if not querydict:
|
||||
raise Http404
|
||||
|
@ -241,7 +235,7 @@ def confirm(request, acronym):
|
|||
if 'resources' in form:
|
||||
form['resources'] = [ ResourceAssociation.objects.get(pk=pk) for pk in form['resources'].split(',')]
|
||||
if 'bethere' in form:
|
||||
form['bethere'] = [Email.objects.get(address=addr) for addr in form['bethere'].split(',')]
|
||||
form['bethere'] = Person.objects.filter(pk__in=form['bethere'].split(','))
|
||||
meeting = get_meeting()
|
||||
group = get_object_or_404(Group,acronym=acronym)
|
||||
login = request.user.person
|
||||
|
@ -285,8 +279,8 @@ def confirm(request, acronym):
|
|||
|
||||
if 'bethere' in form:
|
||||
bethere_cn = ConstraintName.objects.get(slug='bethere')
|
||||
for email in form['bethere']:
|
||||
Constraint.objects.create(name=bethere_cn,source=group,person=email.person,meeting=new_session.meeting)
|
||||
for p in form['bethere']:
|
||||
Constraint.objects.create(name=bethere_cn, source=group, person=p, meeting=new_session.meeting)
|
||||
|
||||
# deprecated in new schema
|
||||
# log activity
|
||||
|
@ -318,14 +312,8 @@ def add_essential_people(group,initial):
|
|||
people = set()
|
||||
if 'bethere' in initial:
|
||||
people.update(initial['bethere'])
|
||||
for role in group.role_set.filter(name='chair'):
|
||||
e = role.person.email_set.order_by("-active","-time").first()
|
||||
if e:
|
||||
people.add(e)
|
||||
if group.ad:
|
||||
e = group.ad.email_set.order_by("-active","-time").first()
|
||||
if e:
|
||||
people.add(e)
|
||||
people.update(Person.objects.filter(role__group=group, role__name='chair'))
|
||||
people.add(group.ad)
|
||||
initial['bethere'] = list(people)
|
||||
|
||||
|
||||
|
@ -447,8 +435,8 @@ def edit_mtg(request, num, acronym):
|
|||
if 'bethere' in form.changed_data and set(form.cleaned_data['bethere'])!=set(initial['bethere']):
|
||||
session.constraints().filter(name='bethere').delete()
|
||||
bethere_cn = ConstraintName.objects.get(slug='bethere')
|
||||
for email in form.cleaned_data['bethere']:
|
||||
Constraint.objects.create(name=bethere_cn,source=group,person=email.person,meeting=session.meeting)
|
||||
for p in form.cleaned_data['bethere']:
|
||||
Constraint.objects.create(name=bethere_cn, source=group, person=p, meeting=session.meeting)
|
||||
|
||||
# deprecated
|
||||
# log activity
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
To: {{ to }}
|
||||
From: {{ message.frm }}
|
||||
Cc: {{ message.cc }}
|
||||
Bcc: {{ message.bccc }}
|
||||
Bcc: {{ message.bcc }}
|
||||
Reply To: {{ message.reply_to }}
|
||||
Subject: {{ message.subject }}
|
||||
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
<link rel="stylesheet" type="text/css" href="{{ SECR_STATIC_URL }}css/jquery.ui.autocomplete.css" />
|
||||
<script type="text/javascript" src="{{ SECR_STATIC_URL }}js/jquery-ui-1.8.1.custom.min.js"></script>
|
||||
<script type="text/javascript" src="{{ SECR_STATIC_URL }}js/utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/css/token-input.css"></link>
|
||||
<script type="text/javascript" src="/js/lib/jquery.tokeninput.js"></script>
|
||||
<script type="text/javascript" src="/js/tokenized-field.js"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block breadcrumbs %}{{ block.super }}
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
<tr><td>Area:</td><td>{% if draft.group.parent %}<a href="{% url "areas_view" name=draft.group.parent.acronym %}">{{ draft.group.parent }}{% endif %}</td></tr>
|
||||
<tr><td>Group:</td><td>{% if draft.group %}<a href="{% url "groups_view" acronym=draft.group.acronym %}">{{ draft.group.acronym }}{% endif %}</td></tr>
|
||||
<tr><td>Area Director:</td><td>{{ draft.ad }}</td></tr>
|
||||
<tr><td>Shepherd:</td><td>{{ draft.shepherd }}</td></tr>
|
||||
<tr><td>Shepherd:</td><td>{% if draft.shepherd %}{{ draft.shepherd.person }} <{{ draft.shepherd.address }}>{% else %}None{% endif %}</td></tr>
|
||||
<tr><td>Notify:</td><td>{{ draft.notify }}</td></tr>
|
||||
<tr><td>Document State:</td><td>{{ draft.get_state }}</td></tr>
|
||||
<tr><td>IESG State:</td><td>{{ draft.iesg_state }}</td></tr>
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
</tr>
|
||||
<tr class="row1">
|
||||
<td>People who must be present:</td>
|
||||
<td>{% if session.bethere %}<ul>{% for email in session.bethere %}<li>{{ email.person }}</li>{% endfor %}</ul>{% else %}<i>None</i>{% endif %}</td>
|
||||
<td>{% if session.bethere %}<ul>{% for person in session.bethere %}<li>{{ person }}</li>{% endfor %}</ul>{% else %}<i>None</i>{% endif %}</td>
|
||||
{% autoescape off %}
|
||||
<tr class="row2"><td>Special Requests:</td><td>{{ session.comments }}</td></tr>
|
||||
{% endautoescape %}
|
||||
|
|
|
@ -33,8 +33,8 @@
|
|||
<type>{{ entry.type }}</type>
|
||||
{% if entry.doc.stream.slug %}<stream>{{ entry.doc.stream.slug }}</stream>{% endif %}
|
||||
<group>{{ entry.doc.group.acronym }}</group>
|
||||
{% if entry.doc.shepherd.name %}<shepherd>{{entry.doc.shepherd.name }}</shepherd>{% endif %}
|
||||
{% if entry.doc.ad.name %}<ad>{{entry.doc.ad.name}}</ad>{% endif %}
|
||||
{% if entry.doc.shepherd %}<shepherd>{{ entry.doc.shepherd.person.name }}</shepherd>{% endif %}
|
||||
{% if entry.doc.ad %}<ad>{{entry.doc.ad.name}}</ad>{% endif %}
|
||||
{% for state in entry.doc.states.all %}
|
||||
<state type="{{ state.type }}">{{ state.slug }}</state>
|
||||
{% endfor %}
|
||||
|
|
|
@ -18,7 +18,10 @@ Change the document shepherd for {{ doc.name }}-{{ doc.rev }}
|
|||
{% block content %}
|
||||
<h1>Change the document shepherd for {{ doc.name }}-{{ doc.rev }}</h1>
|
||||
|
||||
<form class="edit-info" action="" enctype="multipart/form-data" method="post">{% csrf_token %}
|
||||
<p>The shepherd needs to have a Datatracker account. A new account can be
|
||||
<a href="{% url "create_account" %}">created here</a>.</p>
|
||||
|
||||
<form class="edit-info" action="" method="post">{% csrf_token %}
|
||||
<table>
|
||||
{% for field in form.visible_fields %}
|
||||
<tr>
|
||||
|
@ -33,8 +36,8 @@ Change the document shepherd for {{ doc.name }}-{{ doc.rev }}
|
|||
<tr>
|
||||
<td></td>
|
||||
<td class="actions">
|
||||
<a href="{% url "doc_view" name=doc.name %}">Back</a>
|
||||
<input type="submit" value="Submit"/>
|
||||
<a class="button" href="{% url "doc_view" name=doc.name %}">Cancel</a>
|
||||
<input class="button" type="submit" value="Save"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
26
ietf/templates/doc/change_shepherd_email.html
Normal file
26
ietf/templates/doc/change_shepherd_email.html
Normal file
|
@ -0,0 +1,26 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}
|
||||
Change the document shepherd email for {{ doc.name }}-{{ doc.rev }}
|
||||
{% endblock %}
|
||||
|
||||
{% block pagehead %}
|
||||
<link rel="stylesheet" type="text/css" href="/css/token-input.css"></link>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Change the document shepherd email for {{ doc.name }}-{{ doc.rev }}</h1>
|
||||
|
||||
<form class="edit-info" method="post">{% csrf_token %}
|
||||
<table>
|
||||
{{ form.as_table }}
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="actions">
|
||||
<a class="button" href="{% url "doc_view" name=doc.name %}">Cancel</a>
|
||||
<input class="button" type="submit" value="Save"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
{% endblock %}
|
|
@ -131,8 +131,8 @@
|
|||
<tr>
|
||||
<td>Document shepherd:</td>
|
||||
<td>
|
||||
<a {% if can_edit_stream_info %}class="editlink" href="{% url "doc_edit_shepherd" name=doc.name %}"{% endif %}>
|
||||
{{ doc.shepherd|default:"No shepherd assigned" }}
|
||||
<a {% if can_edit_stream_info or is_shepherd %}class="editlink" href="{% if can_edit_stream_info %}{% url "doc_edit_shepherd" name=doc.name %}{% elif is_shepherd %}{% url "doc_change_shepherd_email" name=doc.name %}{% endif %}"{% endif %}>
|
||||
{% if doc.shepherd %}{{ doc.shepherd.person }}{% else %}No shepherd assigned{% endif %}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
@ -78,7 +78,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
</td>
|
||||
|
||||
{% if ad_name == None or ad_name != doc.ad.plain_name %}
|
||||
<td class="ad">{{ doc.ad|default:"" }}<div class="search-text-shepherd">{{doc.shepherd|default:""}}</div></td>
|
||||
<td class="ad">{{ doc.ad|default:"" }}<div class="search-text-shepherd">{% if doc.shepherd %}{{ doc.shepherd.person }}{% endif %}</div></td>
|
||||
{% endif %}
|
||||
|
||||
</tr>
|
||||
|
|
|
@ -29,7 +29,7 @@ Please verify the following information:
|
|||
<tr>
|
||||
<td>Document Shepherd:</td>
|
||||
<td>{% if warn.shepherd %}<img src="/images/warning.png"/>{% endif %}</td>
|
||||
<td>{{doc.shepherd}}</td>
|
||||
<td>{% if doc.shepherd %}{{ doc.shepherd.person }}{% endif %}</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
|
|
|
@ -1,5 +1,14 @@
|
|||
{% extends "nomcom/nomcom_private_base.html" %}
|
||||
|
||||
{% block pagehead %}
|
||||
<link rel="stylesheet" type="text/css" href="/css/token-input.css"></link>
|
||||
{% endblock %}
|
||||
|
||||
{% block content_end %}
|
||||
<script type="text/javascript" src="/js/lib/jquery.tokeninput.js"></script>
|
||||
<script type="text/javascript" src="/js/tokenized-field.js"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block nomcom_content %}
|
||||
<h3>{% if position %}Edit{% else %}Add{% endif %} position</h3>
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<dt>Description:</dt>
|
||||
<dd>{{ position.description }}</dd>
|
||||
<dt>Incumbent:</dt>
|
||||
<dd>{{ position.incumbent }}</dd>
|
||||
<dd>{% if position.incumbent %}{{ position.incumbent.person }} <{{ position.incumbent.address }}>{% else %}None{% endif %}</dd>
|
||||
<dt>Is open:</dt>
|
||||
<dd>{{ position.is_open }}</dd>
|
||||
<dt>Templates:</dt>
|
||||
|
|
|
@ -1,23 +1,25 @@
|
|||
from django import forms
|
||||
from django.core.validators import validate_email, ValidationError
|
||||
from django.core.validators import validate_email
|
||||
|
||||
class MultiEmailField(forms.Field):
|
||||
def to_python(self, value):
|
||||
"Normalize data to a list of strings."
|
||||
|
||||
class MultiEmailField(forms.CharField):
|
||||
widget = forms.widgets.Textarea
|
||||
|
||||
def clean(self, value):
|
||||
super(MultiEmailField, self).clean(value)
|
||||
# Return an empty list if no input was given.
|
||||
if not value:
|
||||
return []
|
||||
|
||||
if isinstance(value, basestring):
|
||||
values = value.split(',')
|
||||
return [ x.strip() for x in values if x.strip() ]
|
||||
else:
|
||||
return value
|
||||
|
||||
if value.endswith(','):
|
||||
value = value[:-1]
|
||||
emails = [v.strip() for v in value.split(',') if v.strip()]
|
||||
def validate(self, value):
|
||||
"Check if value consists only of valid emails."
|
||||
|
||||
for email in emails:
|
||||
try:
|
||||
validate_email(email)
|
||||
except ValidationError:
|
||||
raise ValidationError("This is not a valid comma separated email list.")
|
||||
# Use the parent's handling of required fields, etc.
|
||||
super(MultiEmailField, self).validate(value)
|
||||
|
||||
return value
|
||||
for email in value:
|
||||
validate_email(email)
|
||||
|
|
|
@ -172,7 +172,7 @@ def make_test_data():
|
|||
u.set_password("plain+password")
|
||||
u.save()
|
||||
plainman = Person.objects.create(name="Plain Man", ascii="Plain Man", user=u)
|
||||
email = Email.objects.create(address="plain@example.com", person=plainman) # pyflakes:ignore
|
||||
email = Email.objects.create(address="plain@example.com", person=plainman)
|
||||
|
||||
# group personnel
|
||||
create_person(mars_wg, "chair", name="WG Chair Man", username="marschairman")
|
||||
|
@ -194,7 +194,7 @@ def make_test_data():
|
|||
rev="01",
|
||||
pages=2,
|
||||
intended_std_level_id="ps",
|
||||
shepherd=plainman,
|
||||
shepherd=email,
|
||||
ad=ad,
|
||||
expires=datetime.datetime.now() + datetime.timedelta(days=settings.INTERNET_DRAFT_DAYS_TO_EXPIRE),
|
||||
notify="aliens@example.mars",
|
||||
|
|
|
@ -310,6 +310,10 @@ div.prompt { border: 1px dashed red; background-color: #ffeeaa; padding: 1em 2em
|
|||
margin-left: 150px;
|
||||
}
|
||||
|
||||
.baseform .fieldWidget ul.token-input-list {
|
||||
clear: none;
|
||||
}
|
||||
|
||||
#feedbackformset .fieldWidget {
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* jQuery Plugin: Tokenizing Autocomplete Text Entry
|
||||
* Version 1.5.0
|
||||
* Version 1.6.0
|
||||
*
|
||||
* Copyright (c) 2009 James Smith (http://loopj.com)
|
||||
* Licensed jointly under the GPL and MIT licenses,
|
||||
|
@ -11,26 +11,46 @@
|
|||
(function ($) {
|
||||
// Default settings
|
||||
var DEFAULT_SETTINGS = {
|
||||
// Search settings
|
||||
method: "GET",
|
||||
contentType: "json",
|
||||
queryParam: "q",
|
||||
searchDelay: 300,
|
||||
minChars: 1,
|
||||
propertyToSearch: "name",
|
||||
jsonContainer: null,
|
||||
|
||||
// Display settings
|
||||
hintText: "Type in a search term",
|
||||
noResultsText: "No results",
|
||||
searchingText: "Searching...",
|
||||
deleteText: "×",
|
||||
searchDelay: 300,
|
||||
minChars: 1,
|
||||
animateDropdown: true,
|
||||
|
||||
// Tokenization settings
|
||||
tokenLimit: null,
|
||||
jsonContainer: null,
|
||||
method: "GET",
|
||||
contentType: "json",
|
||||
queryParam: "q",
|
||||
tokenDelimiter: ",",
|
||||
preventDuplicates: false,
|
||||
|
||||
// Output settings
|
||||
tokenValue: "id",
|
||||
|
||||
// Prepopulation settings
|
||||
prePopulate: null,
|
||||
processPrePopulate: false,
|
||||
animateDropdown: true,
|
||||
|
||||
// Manipulation settings
|
||||
idPrefix: "token-input-",
|
||||
|
||||
// Formatters
|
||||
resultsFormatter: function(item){ return "<li>" + item[this.propertyToSearch]+ "</li>" },
|
||||
tokenFormatter: function(item) { return "<li><p>" + item[this.propertyToSearch] + "</p></li>" },
|
||||
|
||||
// Callbacks
|
||||
onResult: null,
|
||||
onAdd: null,
|
||||
onDelete: null,
|
||||
idPrefix: "token-input-"
|
||||
onReady: null
|
||||
};
|
||||
|
||||
// Default classes to use when theming
|
||||
|
@ -93,7 +113,10 @@ var methods = {
|
|||
remove: function(item) {
|
||||
this.data("tokenInputObject").remove(item);
|
||||
return this;
|
||||
}
|
||||
},
|
||||
get: function() {
|
||||
return this.data("tokenInputObject").getTokens();
|
||||
}
|
||||
}
|
||||
|
||||
// Expose the .tokenInput function to jQuery as a plugin
|
||||
|
@ -113,16 +136,19 @@ $.TokenList = function (input, url_or_data, settings) {
|
|||
//
|
||||
|
||||
// Configure the data source
|
||||
if(typeof(url_or_data) === "string") {
|
||||
if($.type(url_or_data) === "string" || $.type(url_or_data) === "function") {
|
||||
// Set the url to query against
|
||||
settings.url = url_or_data;
|
||||
|
||||
// If the URL is a function, evaluate it here to do our initalization work
|
||||
var url = computeURL();
|
||||
|
||||
// Make a smart guess about cross-domain if it wasn't explicitly specified
|
||||
if(settings.crossDomain === undefined) {
|
||||
if(settings.url.indexOf("://") === -1) {
|
||||
if(url.indexOf("://") === -1) {
|
||||
settings.crossDomain = false;
|
||||
} else {
|
||||
settings.crossDomain = (location.href.split(/\/+/g)[1] !== settings.url.split(/\/+/g)[1]);
|
||||
settings.crossDomain = (location.href.split(/\/+/g)[1] !== url.split(/\/+/g)[1]);
|
||||
}
|
||||
}
|
||||
} else if(typeof(url_or_data) === "object") {
|
||||
|
@ -223,6 +249,7 @@ $.TokenList = function (input, url_or_data, settings) {
|
|||
if(!$(this).val().length) {
|
||||
if(selected_token) {
|
||||
delete_token($(selected_token));
|
||||
hidden_input.change();
|
||||
} else if(previous_token.length) {
|
||||
select_token($(previous_token.get(0)));
|
||||
}
|
||||
|
@ -242,6 +269,7 @@ $.TokenList = function (input, url_or_data, settings) {
|
|||
case KEY.COMMA:
|
||||
if(selected_dropdown_item) {
|
||||
add_token($(selected_dropdown_item).data("tokeninput"));
|
||||
hidden_input.change();
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
@ -346,6 +374,10 @@ $.TokenList = function (input, url_or_data, settings) {
|
|||
});
|
||||
}
|
||||
|
||||
// Initialization is done
|
||||
if($.isFunction(settings.onReady)) {
|
||||
settings.onReady.call();
|
||||
}
|
||||
|
||||
//
|
||||
// Public functions
|
||||
|
@ -380,6 +412,10 @@ $.TokenList = function (input, url_or_data, settings) {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.getTokens = function() {
|
||||
return saved_tokens;
|
||||
}
|
||||
|
||||
//
|
||||
// Private functions
|
||||
|
@ -390,8 +426,6 @@ $.TokenList = function (input, url_or_data, settings) {
|
|||
input_box.hide();
|
||||
hide_dropdown();
|
||||
return;
|
||||
} else {
|
||||
input_box.focus();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -413,7 +447,8 @@ $.TokenList = function (input, url_or_data, settings) {
|
|||
|
||||
// Inner function to a token to the list
|
||||
function insert_token(item) {
|
||||
var this_token = $("<li><p>"+ item.name +"</p></li>")
|
||||
var this_token = settings.tokenFormatter(item);
|
||||
this_token = $(this_token)
|
||||
.addClass(settings.classes.token)
|
||||
.insertBefore(input_token);
|
||||
|
||||
|
@ -423,11 +458,13 @@ $.TokenList = function (input, url_or_data, settings) {
|
|||
.appendTo(this_token)
|
||||
.click(function () {
|
||||
delete_token($(this).parent());
|
||||
hidden_input.change();
|
||||
return false;
|
||||
});
|
||||
|
||||
// Store data on the token
|
||||
var token_data = {"id": item.id, "name": item.name};
|
||||
var token_data = {"id": item.id};
|
||||
token_data[settings.propertyToSearch] = item[settings.propertyToSearch];
|
||||
$.data(this_token.get(0), "tokeninput", item);
|
||||
|
||||
// Save this token for duplicate checking
|
||||
|
@ -435,13 +472,16 @@ $.TokenList = function (input, url_or_data, settings) {
|
|||
selected_token_index++;
|
||||
|
||||
// Update the hidden input
|
||||
var token_ids = $.map(saved_tokens, function (el) {
|
||||
return el.id;
|
||||
});
|
||||
hidden_input.val(token_ids.join(settings.tokenDelimiter));
|
||||
update_hidden_input(saved_tokens, hidden_input);
|
||||
|
||||
token_count += 1;
|
||||
|
||||
// Check the token limit
|
||||
if(settings.tokenLimit !== null && token_count >= settings.tokenLimit) {
|
||||
input_box.hide();
|
||||
hide_dropdown();
|
||||
}
|
||||
|
||||
return this_token;
|
||||
}
|
||||
|
||||
|
@ -470,8 +510,10 @@ $.TokenList = function (input, url_or_data, settings) {
|
|||
}
|
||||
|
||||
// Insert the new tokens
|
||||
insert_token(item);
|
||||
checkTokenLimit();
|
||||
if(settings.tokenLimit == null || token_count < settings.tokenLimit) {
|
||||
insert_token(item);
|
||||
checkTokenLimit();
|
||||
}
|
||||
|
||||
// Clear input box
|
||||
input_box.val("");
|
||||
|
@ -553,10 +595,7 @@ $.TokenList = function (input, url_or_data, settings) {
|
|||
if(index < selected_token_index) selected_token_index--;
|
||||
|
||||
// Update the hidden input
|
||||
var token_ids = $.map(saved_tokens, function (el) {
|
||||
return el.id;
|
||||
});
|
||||
hidden_input.val(token_ids.join(settings.tokenDelimiter));
|
||||
update_hidden_input(saved_tokens, hidden_input);
|
||||
|
||||
token_count -= 1;
|
||||
|
||||
|
@ -573,6 +612,15 @@ $.TokenList = function (input, url_or_data, settings) {
|
|||
}
|
||||
}
|
||||
|
||||
// Update the hidden input box value
|
||||
function update_hidden_input(saved_tokens, hidden_input) {
|
||||
var token_values = $.map(saved_tokens, function (el) {
|
||||
return el[settings.tokenValue];
|
||||
});
|
||||
hidden_input.val(token_values.join(settings.tokenDelimiter));
|
||||
|
||||
}
|
||||
|
||||
// Hide and clear the results dropdown
|
||||
function hide_dropdown () {
|
||||
dropdown.hide().empty();
|
||||
|
@ -608,6 +656,10 @@ $.TokenList = function (input, url_or_data, settings) {
|
|||
function highlight_term(value, term) {
|
||||
return value.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + term + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<b>$1</b>");
|
||||
}
|
||||
|
||||
function find_value_and_highlight_term(template, value, term) {
|
||||
return template.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + value + ")(?![^<>]*>)(?![^&;]+;)", "g"), highlight_term(value, term));
|
||||
}
|
||||
|
||||
// Populate the results dropdown with some results
|
||||
function populate_dropdown (query, results) {
|
||||
|
@ -620,14 +672,18 @@ $.TokenList = function (input, url_or_data, settings) {
|
|||
})
|
||||
.mousedown(function (event) {
|
||||
add_token($(event.target).closest("li").data("tokeninput"));
|
||||
hidden_input.change();
|
||||
return false;
|
||||
})
|
||||
.hide();
|
||||
|
||||
$.each(results, function(index, value) {
|
||||
var this_li = $("<li>" + highlight_term(value.name, query) + "</li>")
|
||||
.appendTo(dropdown_ul);
|
||||
|
||||
var this_li = settings.resultsFormatter(value);
|
||||
|
||||
this_li = find_value_and_highlight_term(this_li ,value[settings.propertyToSearch], query);
|
||||
|
||||
this_li = $(this_li).appendTo(dropdown_ul);
|
||||
|
||||
if(index % 2) {
|
||||
this_li.addClass(settings.classes.dropdownItem);
|
||||
} else {
|
||||
|
@ -699,17 +755,19 @@ $.TokenList = function (input, url_or_data, settings) {
|
|||
|
||||
// Do the actual search
|
||||
function run_search(query) {
|
||||
var cached_results = cache.get(query);
|
||||
var cache_key = query + computeURL();
|
||||
var cached_results = cache.get(cache_key);
|
||||
if(cached_results) {
|
||||
populate_dropdown(query, cached_results);
|
||||
} else {
|
||||
// Are we doing an ajax search or local data search?
|
||||
if(settings.url) {
|
||||
var url = computeURL();
|
||||
// Extract exisiting get params
|
||||
var ajax_params = {};
|
||||
ajax_params.data = {};
|
||||
if(settings.url.indexOf("?") > -1) {
|
||||
var parts = settings.url.split("?");
|
||||
if(url.indexOf("?") > -1) {
|
||||
var parts = url.split("?");
|
||||
ajax_params.url = parts[0];
|
||||
|
||||
var param_array = parts[1].split("&");
|
||||
|
@ -718,7 +776,7 @@ $.TokenList = function (input, url_or_data, settings) {
|
|||
ajax_params.data[kv[0]] = kv[1];
|
||||
});
|
||||
} else {
|
||||
ajax_params.url = settings.url;
|
||||
ajax_params.url = url;
|
||||
}
|
||||
|
||||
// Prepare the request
|
||||
|
@ -734,7 +792,7 @@ $.TokenList = function (input, url_or_data, settings) {
|
|||
if($.isFunction(settings.onResult)) {
|
||||
results = settings.onResult.call(hidden_input, results);
|
||||
}
|
||||
cache.add(query, settings.jsonContainer ? results[settings.jsonContainer] : results);
|
||||
cache.add(cache_key, settings.jsonContainer ? results[settings.jsonContainer] : results);
|
||||
|
||||
// only populate the dropdown if the results are associated with the active search query
|
||||
if(input_box.val().toLowerCase() === query) {
|
||||
|
@ -747,17 +805,26 @@ $.TokenList = function (input, url_or_data, settings) {
|
|||
} else if(settings.local_data) {
|
||||
// Do the search through local data
|
||||
var results = $.grep(settings.local_data, function (row) {
|
||||
return row.name.toLowerCase().indexOf(query.toLowerCase()) > -1;
|
||||
return row[settings.propertyToSearch].toLowerCase().indexOf(query.toLowerCase()) > -1;
|
||||
});
|
||||
|
||||
if($.isFunction(settings.onResult)) {
|
||||
results = settings.onResult.call(hidden_input, results);
|
||||
}
|
||||
cache.add(query, results);
|
||||
cache.add(cache_key, results);
|
||||
populate_dropdown(query, results);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// compute the dynamic URL
|
||||
function computeURL() {
|
||||
var url = settings.url;
|
||||
if(typeof settings.url == 'function') {
|
||||
url = settings.url.call();
|
||||
}
|
||||
return url;
|
||||
}
|
||||
};
|
||||
|
||||
// Really basic cache for the results
|
||||
|
|
|
@ -3,15 +3,15 @@ function setupTokenizedField(field) {
|
|||
return; // don't tokenize hidden template snippets
|
||||
|
||||
var pre = [];
|
||||
if (field.val())
|
||||
pre = JSON.parse((field.val() || "").replace(/"/g, '"'));
|
||||
else if (field.data("pre"))
|
||||
if (field.attr("data-pre"))
|
||||
pre = JSON.parse((field.attr("data-pre") || "").replace(/"/g, '"'));
|
||||
|
||||
field.tokenInput(field.attr("data-ajax-url"), {
|
||||
hintText: "",
|
||||
preventDuplicates: true,
|
||||
prePopulate: pre
|
||||
prePopulate: pre,
|
||||
tokenLimit: field.attr("data-max-entries"),
|
||||
noResultsText: "No results - cannot use this entry",
|
||||
hintText: field.attr("data-hint-text")
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -211,8 +211,8 @@ $(document).ready(function() {
|
|||
minLength: 3,
|
||||
select: function(event, ui) {
|
||||
//match number inside paren and then strip paren
|
||||
id = ui.item.label.match(/\(\d+\)/);
|
||||
val = id[0].replace(/[\(\)]/g, "");
|
||||
var id = ui.item.label.match(/\(\d+\)/);
|
||||
var val = id[0].replace(/[\(\)]/g, "");
|
||||
//alert(id,val);
|
||||
//alert(id.match(/\d+/));
|
||||
$.getJSON('/secr/areas/getemails/',{"id":val},function(data) {
|
||||
|
|
Loading…
Reference in a new issue