diff --git a/ietf/community/__init__.py b/ietf/community/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/ietf/community/constants.py b/ietf/community/constants.py
new file mode 100644
index 000000000..9bcad3fb5
--- /dev/null
+++ b/ietf/community/constants.py
@@ -0,0 +1,23 @@
+SIGNIFICANT_STATES = [
+ 'Adopted by a WG',
+ 'In WG Last Call',
+ 'WG Consensus: Waiting for Write-Up',
+ 'Parked WG Document',
+ 'Dead WG Document',
+ 'Active IAB Document',
+ 'Community Review',
+ 'Sent to the RFC Editor',
+ 'Active RG Document',
+ 'In RG Last Call',
+ 'Awaiting IRSG Reviews',
+ 'In IESG Review',
+ 'Document on Hold Based On IESG Request',
+ 'Submission Received',
+ 'In ISE Review',
+ 'In IESG Review',
+ 'RFC Published',
+ 'Dead',
+ 'IESG Evaluation',
+ 'Publication Requested',
+ 'In Last Call',
+]
diff --git a/ietf/community/display.py b/ietf/community/display.py
new file mode 100644
index 000000000..a84a8c306
--- /dev/null
+++ b/ietf/community/display.py
@@ -0,0 +1,173 @@
+import datetime
+
+from django.db.models import Q
+from ietf.ietfworkflows.utils import get_state_for_draft
+
+from redesign.doc.models import DocAlias, DocEvent
+
+
+class DisplayField(object):
+
+ codename = ''
+ description = ''
+
+ def get_value(self, document, raw=False):
+ return None
+
+
+class FilenameField(DisplayField):
+ codename = 'filename'
+ description = 'I-D filename'
+
+ def get_value(self, document, raw=False):
+ if not raw:
+ return '%s' % (document.get_absolute_url(), document.canonical_name())
+ else:
+ return document.canonical_name()
+
+
+class TitleField(DisplayField):
+ codename = 'title'
+ description = 'I-D title'
+
+ def get_value(self, document, raw=False):
+ return document.title
+
+
+class DateField(DisplayField):
+ codename = 'date'
+ description = 'Date of current I-D'
+
+ def get_value(self, document, raw=False):
+ date = document.latest_event(type='new_revision')
+ if date:
+ return date.time.strftime('%Y-%m-%d')
+ return document.time.strftime('%Y-%m-%d')
+
+
+class StatusField(DisplayField):
+ codename = 'status'
+ description = 'Status in the IETF process'
+
+ def get_value(self, document, raw=False):
+ for i in ('draft', 'draft-stream-ietf', 'draft-stream-irtf', 'draft-stream-ise', 'draft-stream-iab', 'draft'):
+ state = document.get_state(i)
+ if state:
+ return state
+ return ''
+
+
+class WGField(DisplayField):
+ codename = 'wg_rg'
+ description = 'Associated WG or RG'
+
+ def get_value(self, document, raw=False):
+ return document.group or ''
+
+
+class ADField(DisplayField):
+ codename = 'ad'
+ description = 'Associated AD, if any'
+
+ def get_value(self, document, raw=False):
+ return document.ad or ''
+
+
+class OneDayField(DisplayField):
+ codename = '1_day'
+ description = 'Changed within the last 1 day'
+
+ def get_value(self, document, raw=False):
+ now = datetime.datetime.now()
+ last = now - datetime.timedelta(days=1)
+ if document.docevent_set.filter(time__gte=last):
+ return raw and 'YES' or '✔'
+ return ''
+
+
+class TwoDaysField(DisplayField):
+ codename = '2_days'
+ description = 'Changed within the last 2 days'
+
+ def get_value(self, document, raw=False):
+ now = datetime.datetime.now()
+ last = now - datetime.timedelta(days=2)
+ if document.docevent_set.filter(time__gte=last):
+ return raw and 'YES' or '✔'
+ return ''
+
+
+class SevenDaysField(DisplayField):
+ codename = '7_days'
+ description = 'Changed within the last 7 days'
+
+ def get_value(self, document, raw=False):
+ now = datetime.datetime.now()
+ last = now - datetime.timedelta(days=7)
+ if document.docevent_set.filter(time__gte=last):
+ return raw and 'YES' or '✔'
+ return ''
+
+
+TYPES_OF_DISPLAY_FIELDS = [(i.codename, i.description) for i in DisplayField.__subclasses__()]
+
+
+class SortMethod(object):
+ codename = ''
+ description = ''
+
+ def get_sort_field(self):
+ return 'pk'
+
+
+class FilenameSort(SortMethod):
+ codename = 'by_filename'
+ description = 'Alphabetical by I-D filename and RFC number'
+
+ def get_sort_field(self):
+ return 'name'
+
+ def get_full_rfc_sort(self, documents):
+ return [i.document for i in DocAlias.objects.filter(document__in=documents, name__startswith='rfc').order_by('name')]
+
+
+class TitleSort(SortMethod):
+ codename = 'by_title'
+ description = 'Alphabetical by document title'
+
+ def get_sort_field(self):
+ return 'title'
+
+
+class WGSort(SortMethod):
+ codename = 'by_wg'
+ description = 'Alphabetical by associated WG'
+
+ def get_sort_field(self):
+ return 'group__name'
+
+
+class PublicationSort(SortMethod):
+ codename = 'date_publication'
+ description = 'Date of publication of current version of the document'
+
+ def get_sort_field(self):
+ return '-documentchangedates__new_version_date'
+
+class ChangeSort(SortMethod):
+ codename = 'recent_change'
+ description = 'Date of most recent change of status of any type'
+
+ def get_sort_field(self):
+ return '-documentchangedates__normal_change_date'
+
+
+class SignificantSort(SortMethod):
+ codename = 'recent_significant'
+ description = 'Date of most recent significant change of status'
+
+ def get_sort_field(self):
+ return '-documentchangedates__significant_change_date'
+
+
+TYPES_OF_SORT = [(i.codename, i.description) for i in SortMethod.__subclasses__()]
diff --git a/ietf/community/forms.py b/ietf/community/forms.py
new file mode 100644
index 000000000..63d5b9bf6
--- /dev/null
+++ b/ietf/community/forms.py
@@ -0,0 +1,101 @@
+import hashlib
+import datetime
+
+from django import forms
+from django.conf import settings
+from django.contrib.sites.models import Site
+
+from ietf.utils.mail import send_mail
+from ietf.community.models import Rule, DisplayConfiguration, RuleManager
+from ietf.community.display import DisplayField
+
+
+class RuleForm(forms.ModelForm):
+
+ class Meta:
+ model = Rule
+ fields = ('rule_type', 'value')
+
+ def __init__(self, *args, **kwargs):
+ self.clist = kwargs.pop('clist', None)
+ super(RuleForm, self).__init__(*args, **kwargs)
+
+ def save(self):
+ self.instance.community_list = self.clist
+ super(RuleForm, self).save()
+
+ def get_all_options(self):
+ result = []
+ for i in RuleManager.__subclasses__():
+ options = i(None).options()
+ if options:
+ result.append({'type': i.codename,
+ 'options': options})
+ return result
+
+
+class DisplayForm(forms.ModelForm):
+
+ class Meta:
+ model = DisplayConfiguration
+ fields = ('sort_method', )
+
+ def save(self):
+ data = self.data
+ fields = []
+ for i in DisplayField.__subclasses__():
+ if data.get(i.codename, None):
+ fields.append(i.codename)
+ self.instance.display_fields = ','.join(fields)
+ super(DisplayForm, self).save()
+
+
+class SubscribeForm(forms.Form):
+
+ email = forms.EmailField("Your email")
+
+ def __init__(self, *args, **kwargs):
+ self.clist = kwargs.pop('clist')
+ self.significant = kwargs.pop('significant')
+ super(SubscribeForm, self).__init__(*args, **kwargs)
+
+ def save(self, *args, **kwargs):
+ self.send_email()
+ return True
+
+ def send_email(self):
+ domain = Site.objects.get_current().domain
+ today = datetime.date.today().strftime('%Y%m%d')
+ subject = 'Confirm list subscription: %s' % self.clist
+ from_email = settings.DEFAULT_FROM_EMAIL
+ to_email = self.cleaned_data['email']
+ auth = hashlib.md5('%s%s%s%s%s' % (settings.SECRET_KEY, today, to_email, 'subscribe', self.significant)).hexdigest()
+ context = {
+ 'domain': domain,
+ 'clist': self.clist,
+ 'today': today,
+ 'auth': auth,
+ 'to_email': to_email,
+ 'significant': self.significant,
+ }
+ send_mail(None, to_email, from_email, subject, 'community/public/subscribe_email.txt', context)
+
+
+class UnSubscribeForm(SubscribeForm):
+
+ def send_email(self):
+ domain = Site.objects.get_current().domain
+ today = datetime.date.today().strftime('%Y%m%d')
+ subject = 'Confirm list subscription cancelation: %s' % self.clist
+ from_email = settings.DEFAULT_FROM_EMAIL
+ to_email = self.cleaned_data['email']
+ auth = hashlib.md5('%s%s%s%s%s' % (settings.SECRET_KEY, today, to_email, 'unsubscribe', self.significant)).hexdigest()
+ context = {
+ 'domain': domain,
+ 'clist': self.clist,
+ 'today': today,
+ 'auth': auth,
+ 'to_email': to_email,
+ 'significant': self.significant,
+ }
+ send_mail(None, to_email, from_email, subject, 'community/public/unsubscribe_email.txt', context)
diff --git a/ietf/community/management/__init__.py b/ietf/community/management/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/ietf/community/management/commands/__init__.py b/ietf/community/management/commands/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/ietf/community/management/commands/update_community_lists.py b/ietf/community/management/commands/update_community_lists.py
new file mode 100644
index 000000000..936a6dcee
--- /dev/null
+++ b/ietf/community/management/commands/update_community_lists.py
@@ -0,0 +1,36 @@
+import sys
+import datetime
+
+from django.core.management.base import BaseCommand
+
+from ietf.community.models import Rule, CommunityList
+
+
+class Command(BaseCommand):
+ help = (u"Update drafts in community lists by reviewing their rules")
+
+
+ def handle(self, *args, **options):
+ now = datetime.datetime.now()
+
+ rules = Rule.objects.filter(last_updated__lt=now - datetime.timedelta(hours=12))
+ count = rules.count()
+ index = 1
+ for rule in rules:
+ sys.stdout.write('Updating rule [%s/%s]\r' % (index, count))
+ sys.stdout.flush()
+ rule.save()
+ index += 1
+ if index > 1:
+ print
+ cls = CommunityList.objects.filter(cached__isnull=False)
+ count = cls.count()
+ index = 1
+ for cl in cls:
+ sys.stdout.write('Clearing community list cache [%s/%s]\r' % (index, count))
+ sys.stdout.flush()
+ cl.cached = None
+ cl.save()
+ index += 1
+ if index > 1:
+ print
diff --git a/ietf/community/management/commands/update_doc_change_dates.py b/ietf/community/management/commands/update_doc_change_dates.py
new file mode 100644
index 000000000..825edb539
--- /dev/null
+++ b/ietf/community/management/commands/update_doc_change_dates.py
@@ -0,0 +1,39 @@
+import sys
+
+from django.core.management.base import BaseCommand
+from django.db.models import Q
+
+from ietf.community.constants import SIGNIFICANT_STATES
+from ietf.community.models import DocumentChangeDates
+from redesign.doc.models import Document
+
+
+class Command(BaseCommand):
+ help = (u"Update drafts in community lists by reviewing their rules")
+
+ def handle(self, *args, **options):
+ documents = Document.objects.filter(Q(type__name='Draft') | Q(states__name='rfc')).distinct()
+ index = 1
+ total = documents.count()
+
+ for doc in documents:
+ (changes, created) = DocumentChangeDates.objects.get_or_create(document=doc)
+ new_version = doc.latest_event(type='new_revision')
+ normal_change = doc.latest_event()
+ significant_change = None
+ for event in doc.docevent_set.filter(type='changed_document'):
+ for state in SIGNIFICANT_STATES:
+ if ('%s' % state) in event.desc:
+ significant_change = event
+ break
+
+ changes.new_version_date = new_version and new_version.time.date()
+ changes.normal_change_date = normal_change and normal_change.time.date()
+ changes.significant_change_date = significant_change and significant_change.time.date()
+
+ changes.save()
+
+ sys.stdout.write('Document %s/%s\r' % (index, total))
+ sys.stdout.flush()
+ index += 1
+ print
diff --git a/ietf/community/migrations/0001_initial_migration.py b/ietf/community/migrations/0001_initial_migration.py
new file mode 100644
index 000000000..df84340f4
--- /dev/null
+++ b/ietf/community/migrations/0001_initial_migration.py
@@ -0,0 +1,257 @@
+
+from south.db import db
+from django.db import models
+from ietf.community.models import *
+
+class Migration:
+
+ def forwards(self, orm):
+
+ # Adding model 'Rule'
+ db.create_table('community_rule', (
+ ('id', orm['community.Rule:id']),
+ ('community_list', orm['community.Rule:community_list']),
+ ('rule_type', orm['community.Rule:rule_type']),
+ ('value', orm['community.Rule:value']),
+ ('last_updated', orm['community.Rule:last_updated']),
+ ))
+ db.send_create_signal('community', ['Rule'])
+
+ # Adding model 'CommunityList'
+ db.create_table('community_communitylist', (
+ ('id', orm['community.CommunityList:id']),
+ ('user', orm['community.CommunityList:user']),
+ ('group', orm['community.CommunityList:group']),
+ ))
+ db.send_create_signal('community', ['CommunityList'])
+
+ # Adding ManyToManyField 'Rule.cached_ids'
+ db.create_table('community_rule_cached_ids', (
+ ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
+ ('rule', models.ForeignKey(orm.Rule, null=False)),
+ ('document', models.ForeignKey(orm['doc.Document'], null=False))
+ ))
+
+ # Adding ManyToManyField 'CommunityList.added_ids'
+ db.create_table('community_communitylist_added_ids', (
+ ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
+ ('communitylist', models.ForeignKey(orm.CommunityList, null=False)),
+ ('document', models.ForeignKey(orm['doc.Document'], null=False))
+ ))
+
+
+
+ def backwards(self, orm):
+
+ # Deleting model 'Rule'
+ db.delete_table('community_rule')
+
+ # Deleting model 'CommunityList'
+ db.delete_table('community_communitylist')
+
+ # Dropping ManyToManyField 'Rule.cached_ids'
+ db.delete_table('community_rule_cached_ids')
+
+ # Dropping ManyToManyField 'CommunityList.added_ids'
+ db.delete_table('community_communitylist_added_ids')
+
+
+
+ models = {
+ 'auth.group': {
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})
+ },
+ 'auth.permission': {
+ 'Meta': {'unique_together': "(('content_type', 'codename'),)"},
+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'auth.user': {
+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'community.communitylist': {
+ 'added_ids': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.Document']"}),
+ 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'})
+ },
+ 'community.rule': {
+ 'cached_ids': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.Document']"}),
+ 'community_list': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['community.CommunityList']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'last_updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+ 'rule_type': ('django.db.models.fields.CharField', [], {'max_length': '30'}),
+ 'value': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+ },
+ 'contenttypes.contenttype': {
+ 'Meta': {'unique_together': "(('app_label', 'model'),)", 'db_table': "'django_content_type'"},
+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+ },
+ 'doc.docalias': {
+ 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'})
+ },
+ 'doc.document': {
+ 'abstract': ('django.db.models.fields.TextField', [], {}),
+ 'ad': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'ad_document_set'", 'null': 'True', 'to': "orm['person.Person']"}),
+ 'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['person.Email']", 'blank': 'True'}),
+ 'external_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
+ 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
+ 'iana_state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.IanaDocStateName']", 'null': 'True', 'blank': 'True'}),
+ 'iesg_state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.IesgDocStateName']", 'null': 'True', 'blank': 'True'}),
+ 'intended_std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.IntendedStdLevelName']", 'null': 'True', 'blank': 'True'}),
+ 'internal_comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'primary_key': 'True'}),
+ 'note': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'notify': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+ 'pages': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+ 'related': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.DocAlias']", 'blank': 'True'}),
+ 'rev': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}),
+ 'rfc_state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.RfcDocStateName']", 'null': 'True', 'blank': 'True'}),
+ 'shepherd': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'shepherd_document_set'", 'null': 'True', 'to': "orm['person.Person']"}),
+ 'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocStateName']", 'null': 'True', 'blank': 'True'}),
+ 'std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StdLevelName']", 'null': 'True', 'blank': 'True'}),
+ 'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocStreamName']", 'null': 'True', 'blank': 'True'}),
+ 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['name.DocInfoTagName']", 'null': 'True', 'blank': 'True'}),
+ 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'}),
+ 'wg_state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.WgDocStateName']", 'null': 'True', 'blank': 'True'})
+ },
+ 'group.group': {
+ 'acronym': ('django.db.models.fields.CharField', [], {'max_length': '16', 'db_index': 'True'}),
+ 'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True', 'blank': 'True'}),
+ 'charter': ('django.db.models.fields.related.OneToOneField', [], {'blank': 'True', 'related_name': "'chartered_group'", 'unique': 'True', 'null': 'True', 'to': "orm['doc.Document']"}),
+ 'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'list_archive': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+ 'list_email': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
+ 'list_subscribe': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
+ 'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
+ 'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupStateName']", 'null': 'True'}),
+ 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupTypeName']", 'null': 'True'})
+ },
+ 'name.docinfotagname': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.docstatename': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.docstreamname': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.doctypename': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.groupstatename': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.grouptypename': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.ianadocstatename': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.iesgdocstatename': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.intendedstdlevelname': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.rfcdocstatename': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.stdlevelname': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.wgdocstatename': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'person.email': {
+ 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+ 'address': ('django.db.models.fields.CharField', [], {'max_length': '64', 'primary_key': 'True'}),
+ 'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True'}),
+ 'time': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'})
+ },
+ 'person.person': {
+ 'address': ('django.db.models.fields.TextField', [], {'max_length': '255', 'blank': 'True'}),
+ 'ascii': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'ascii_short': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
+ 'time': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'null': 'True', 'blank': 'True'})
+ }
+ }
+
+ complete_apps = ['community']
diff --git a/ietf/community/migrations/0002_add_display_config.py b/ietf/community/migrations/0002_add_display_config.py
new file mode 100644
index 000000000..27661721b
--- /dev/null
+++ b/ietf/community/migrations/0002_add_display_config.py
@@ -0,0 +1,231 @@
+
+from south.db import db
+from django.db import models
+from ietf.community.models import *
+
+class Migration:
+
+ def forwards(self, orm):
+
+ # Adding model 'DisplayConfiguration'
+ db.create_table('community_displayconfiguration', (
+ ('id', orm['community.displayconfiguration:id']),
+ ('community_list', orm['community.displayconfiguration:community_list']),
+ ('sort_method', orm['community.displayconfiguration:sort_method']),
+ ('display_fields', orm['community.displayconfiguration:display_fields']),
+ ))
+ db.send_create_signal('community', ['DisplayConfiguration'])
+
+
+
+ def backwards(self, orm):
+
+ # Deleting model 'DisplayConfiguration'
+ db.delete_table('community_displayconfiguration')
+
+
+
+ models = {
+ 'auth.group': {
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})
+ },
+ 'auth.permission': {
+ 'Meta': {'unique_together': "(('content_type', 'codename'),)"},
+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'auth.user': {
+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'community.communitylist': {
+ 'added_ids': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.Document']"}),
+ 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'})
+ },
+ 'community.displayconfiguration': {
+ 'community_list': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['community.CommunityList']"}),
+ 'display_fields': ('django.db.models.fields.TextField', [], {}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'sort_method': ('django.db.models.fields.CharField', [], {'default': "'by_filename'", 'max_length': '100'})
+ },
+ 'community.rule': {
+ 'cached_ids': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.Document']"}),
+ 'community_list': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['community.CommunityList']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'last_updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+ 'rule_type': ('django.db.models.fields.CharField', [], {'max_length': '30'}),
+ 'value': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+ },
+ 'contenttypes.contenttype': {
+ 'Meta': {'unique_together': "(('app_label', 'model'),)", 'db_table': "'django_content_type'"},
+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+ },
+ 'doc.docalias': {
+ 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'})
+ },
+ 'doc.document': {
+ 'abstract': ('django.db.models.fields.TextField', [], {}),
+ 'ad': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'ad_document_set'", 'null': 'True', 'to': "orm['person.Person']"}),
+ 'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['person.Email']", 'blank': 'True'}),
+ 'external_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
+ 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
+ 'iana_state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.IanaDocStateName']", 'null': 'True', 'blank': 'True'}),
+ 'iesg_state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.IesgDocStateName']", 'null': 'True', 'blank': 'True'}),
+ 'intended_std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.IntendedStdLevelName']", 'null': 'True', 'blank': 'True'}),
+ 'internal_comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'primary_key': 'True'}),
+ 'note': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'notify': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+ 'pages': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+ 'related': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.DocAlias']", 'blank': 'True'}),
+ 'rev': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}),
+ 'rfc_state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.RfcDocStateName']", 'null': 'True', 'blank': 'True'}),
+ 'shepherd': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'shepherd_document_set'", 'null': 'True', 'to': "orm['person.Person']"}),
+ 'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocStateName']", 'null': 'True', 'blank': 'True'}),
+ 'std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StdLevelName']", 'null': 'True', 'blank': 'True'}),
+ 'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocStreamName']", 'null': 'True', 'blank': 'True'}),
+ 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['name.DocInfoTagName']", 'null': 'True', 'blank': 'True'}),
+ 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'}),
+ 'wg_state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.WgDocStateName']", 'null': 'True', 'blank': 'True'})
+ },
+ 'group.group': {
+ 'acronym': ('django.db.models.fields.CharField', [], {'max_length': '16', 'db_index': 'True'}),
+ 'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True', 'blank': 'True'}),
+ 'charter': ('django.db.models.fields.related.OneToOneField', [], {'blank': 'True', 'related_name': "'chartered_group'", 'unique': 'True', 'null': 'True', 'to': "orm['doc.Document']"}),
+ 'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'list_archive': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+ 'list_email': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
+ 'list_subscribe': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
+ 'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
+ 'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupStateName']", 'null': 'True'}),
+ 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupTypeName']", 'null': 'True'})
+ },
+ 'name.docinfotagname': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.docstatename': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.docstreamname': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.doctypename': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.groupstatename': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.grouptypename': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.ianadocstatename': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.iesgdocstatename': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.intendedstdlevelname': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.rfcdocstatename': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.stdlevelname': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.wgdocstatename': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'person.email': {
+ 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+ 'address': ('django.db.models.fields.CharField', [], {'max_length': '64', 'primary_key': 'True'}),
+ 'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True'}),
+ 'time': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'})
+ },
+ 'person.person': {
+ 'address': ('django.db.models.fields.TextField', [], {'max_length': '255', 'blank': 'True'}),
+ 'ascii': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'ascii_short': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
+ 'time': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'null': 'True', 'blank': 'True'})
+ }
+ }
+
+ complete_apps = ['community']
diff --git a/ietf/community/migrations/0003_add_notifications.py b/ietf/community/migrations/0003_add_notifications.py
new file mode 100644
index 000000000..7b97730e6
--- /dev/null
+++ b/ietf/community/migrations/0003_add_notifications.py
@@ -0,0 +1,295 @@
+
+from south.db import db
+from django.db import models
+from ietf.community.models import *
+
+class Migration:
+
+ def forwards(self, orm):
+
+ # Adding model 'ListNotification'
+ db.create_table('community_listnotification', (
+ ('id', orm['community.listnotification:id']),
+ ('document', orm['community.listnotification:document']),
+ ('notification_date', orm['community.listnotification:notification_date']),
+ ('desc', orm['community.listnotification:desc']),
+ ('significant', orm['community.listnotification:significant']),
+ ))
+ db.send_create_signal('community', ['ListNotification'])
+
+ # Adding model 'EmailSubscription'
+ db.create_table('community_emailsubscription', (
+ ('id', orm['community.emailsubscription:id']),
+ ('community_list', orm['community.emailsubscription:community_list']),
+ ('email', orm['community.emailsubscription:email']),
+ ('significant', orm['community.emailsubscription:significant']),
+ ))
+ db.send_create_signal('community', ['EmailSubscription'])
+
+ # Adding model 'DocumentChangeDates'
+ db.create_table('community_documentchangedates', (
+ ('id', orm['community.documentchangedates:id']),
+ ('document', orm['community.documentchangedates:document']),
+ ('new_version_date', orm['community.documentchangedates:new_version_date']),
+ ('normal_change_date', orm['community.documentchangedates:normal_change_date']),
+ ('significant_change_date', orm['community.documentchangedates:significant_change_date']),
+ ))
+ db.send_create_signal('community', ['DocumentChangeDates'])
+
+ # Adding model 'ExpectedChange'
+ db.create_table('community_expectedchange', (
+ ('id', orm['community.expectedchange:id']),
+ ('community_list', orm['community.expectedchange:community_list']),
+ ('document', orm['community.expectedchange:document']),
+ ('expected_date', orm['community.expectedchange:expected_date']),
+ ))
+ db.send_create_signal('community', ['ExpectedChange'])
+
+
+
+ def backwards(self, orm):
+
+ # Deleting model 'ListNotification'
+ db.delete_table('community_listnotification')
+
+ # Deleting model 'EmailSubscription'
+ db.delete_table('community_emailsubscription')
+
+ # Deleting model 'DocumentChangeDates'
+ db.delete_table('community_documentchangedates')
+
+ # Deleting model 'ExpectedChange'
+ db.delete_table('community_expectedchange')
+
+
+
+ models = {
+ 'auth.group': {
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})
+ },
+ 'auth.permission': {
+ 'Meta': {'unique_together': "(('content_type', 'codename'),)"},
+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'auth.user': {
+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'community.communitylist': {
+ 'added_ids': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.Document']"}),
+ 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'})
+ },
+ 'community.displayconfiguration': {
+ 'community_list': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['community.CommunityList']"}),
+ 'display_fields': ('django.db.models.fields.TextField', [], {}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'sort_method': ('django.db.models.fields.CharField', [], {'default': "'by_filename'", 'max_length': '100'})
+ },
+ 'community.documentchangedates': {
+ 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'new_version_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'normal_change_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'significant_change_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
+ },
+ 'community.emailsubscription': {
+ 'community_list': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['community.CommunityList']"}),
+ 'email': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'significant': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})
+ },
+ 'community.expectedchange': {
+ 'community_list': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['community.CommunityList']"}),
+ 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
+ 'expected_date': ('django.db.models.fields.DateField', [], {}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
+ },
+ 'community.listnotification': {
+ 'desc': ('django.db.models.fields.TextField', [], {}),
+ 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'notification_date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+ 'significant': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})
+ },
+ 'community.rule': {
+ 'cached_ids': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.Document']"}),
+ 'community_list': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['community.CommunityList']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'last_updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+ 'rule_type': ('django.db.models.fields.CharField', [], {'max_length': '30'}),
+ 'value': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+ },
+ 'contenttypes.contenttype': {
+ 'Meta': {'unique_together': "(('app_label', 'model'),)", 'db_table': "'django_content_type'"},
+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+ },
+ 'doc.docalias': {
+ 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'})
+ },
+ 'doc.document': {
+ 'abstract': ('django.db.models.fields.TextField', [], {}),
+ 'ad': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'ad_document_set'", 'null': 'True', 'to': "orm['person.Person']"}),
+ 'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['person.Email']", 'blank': 'True'}),
+ 'external_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
+ 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
+ 'iana_state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.IanaDocStateName']", 'null': 'True', 'blank': 'True'}),
+ 'iesg_state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.IesgDocStateName']", 'null': 'True', 'blank': 'True'}),
+ 'intended_std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.IntendedStdLevelName']", 'null': 'True', 'blank': 'True'}),
+ 'internal_comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'primary_key': 'True'}),
+ 'note': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'notify': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+ 'pages': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+ 'related': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.DocAlias']", 'blank': 'True'}),
+ 'rev': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}),
+ 'rfc_state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.RfcDocStateName']", 'null': 'True', 'blank': 'True'}),
+ 'shepherd': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'shepherd_document_set'", 'null': 'True', 'to': "orm['person.Person']"}),
+ 'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocStateName']", 'null': 'True', 'blank': 'True'}),
+ 'std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StdLevelName']", 'null': 'True', 'blank': 'True'}),
+ 'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocStreamName']", 'null': 'True', 'blank': 'True'}),
+ 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['name.DocInfoTagName']", 'null': 'True', 'blank': 'True'}),
+ 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'}),
+ 'wg_state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.WgDocStateName']", 'null': 'True', 'blank': 'True'})
+ },
+ 'group.group': {
+ 'acronym': ('django.db.models.fields.CharField', [], {'max_length': '16', 'db_index': 'True'}),
+ 'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True', 'blank': 'True'}),
+ 'charter': ('django.db.models.fields.related.OneToOneField', [], {'blank': 'True', 'related_name': "'chartered_group'", 'unique': 'True', 'null': 'True', 'to': "orm['doc.Document']"}),
+ 'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'list_archive': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+ 'list_email': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
+ 'list_subscribe': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
+ 'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
+ 'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupStateName']", 'null': 'True'}),
+ 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupTypeName']", 'null': 'True'})
+ },
+ 'name.docinfotagname': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.docstatename': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.docstreamname': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.doctypename': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.groupstatename': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.grouptypename': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.ianadocstatename': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.iesgdocstatename': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.intendedstdlevelname': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.rfcdocstatename': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.stdlevelname': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.wgdocstatename': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'person.email': {
+ 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+ 'address': ('django.db.models.fields.CharField', [], {'max_length': '64', 'primary_key': 'True'}),
+ 'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True'}),
+ 'time': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'})
+ },
+ 'person.person': {
+ 'address': ('django.db.models.fields.TextField', [], {'max_length': '255', 'blank': 'True'}),
+ 'ascii': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'ascii_short': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
+ 'time': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'null': 'True', 'blank': 'True'})
+ }
+ }
+
+ complete_apps = ['community']
diff --git a/ietf/community/migrations/0004_refactor_notifications_with_docevent.py b/ietf/community/migrations/0004_refactor_notifications_with_docevent.py
new file mode 100644
index 000000000..f1bf69725
--- /dev/null
+++ b/ietf/community/migrations/0004_refactor_notifications_with_docevent.py
@@ -0,0 +1,262 @@
+
+from south.db import db
+from django.db import models
+from ietf.community.models import *
+
+class Migration:
+
+ def forwards(self, orm):
+
+ # Adding field 'ListNotification.event'
+ db.add_column('community_listnotification', 'event', orm['community.listnotification:event'])
+
+ # Deleting field 'ListNotification.document'
+ db.delete_column('community_listnotification', 'document_id')
+
+ # Deleting field 'ListNotification.notification_date'
+ db.delete_column('community_listnotification', 'notification_date')
+
+ # Deleting field 'ListNotification.desc'
+ db.delete_column('community_listnotification', 'desc')
+
+
+
+ def backwards(self, orm):
+
+ # Deleting field 'ListNotification.event'
+ db.delete_column('community_listnotification', 'event_id')
+
+ # Adding field 'ListNotification.document'
+ db.add_column('community_listnotification', 'document', orm['community.listnotification:document'])
+
+ # Adding field 'ListNotification.notification_date'
+ db.add_column('community_listnotification', 'notification_date', orm['community.listnotification:notification_date'])
+
+ # Adding field 'ListNotification.desc'
+ db.add_column('community_listnotification', 'desc', orm['community.listnotification:desc'])
+
+
+
+ models = {
+ 'auth.group': {
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})
+ },
+ 'auth.permission': {
+ 'Meta': {'unique_together': "(('content_type', 'codename'),)"},
+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'auth.user': {
+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'})
+ },
+ 'community.communitylist': {
+ 'added_ids': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.Document']"}),
+ 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'})
+ },
+ 'community.displayconfiguration': {
+ 'community_list': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['community.CommunityList']"}),
+ 'display_fields': ('django.db.models.fields.TextField', [], {'default': "'filename,title,date'"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'sort_method': ('django.db.models.fields.CharField', [], {'default': "'by_filename'", 'max_length': '100'})
+ },
+ 'community.documentchangedates': {
+ 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'new_version_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'normal_change_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'significant_change_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
+ },
+ 'community.emailsubscription': {
+ 'community_list': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['community.CommunityList']"}),
+ 'email': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'significant': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})
+ },
+ 'community.expectedchange': {
+ 'community_list': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['community.CommunityList']"}),
+ 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
+ 'expected_date': ('django.db.models.fields.DateField', [], {}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
+ },
+ 'community.listnotification': {
+ 'event': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.DocEvent']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'significant': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})
+ },
+ 'community.rule': {
+ 'cached_ids': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.Document']"}),
+ 'community_list': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['community.CommunityList']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'last_updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+ 'rule_type': ('django.db.models.fields.CharField', [], {'max_length': '30'}),
+ 'value': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+ },
+ 'contenttypes.contenttype': {
+ 'Meta': {'unique_together': "(('app_label', 'model'),)", 'db_table': "'django_content_type'"},
+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+ },
+ 'doc.docalias': {
+ 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'})
+ },
+ 'doc.docevent': {
+ 'by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"}),
+ 'desc': ('django.db.models.fields.TextField', [], {}),
+ 'doc': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'type': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'doc.document': {
+ 'abstract': ('django.db.models.fields.TextField', [], {}),
+ 'ad': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'ad_document_set'", 'null': 'True', 'to': "orm['person.Person']"}),
+ 'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['person.Email']", 'blank': 'True'}),
+ 'external_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
+ 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
+ 'intended_std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.IntendedStdLevelName']", 'null': 'True', 'blank': 'True'}),
+ 'internal_comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'primary_key': 'True'}),
+ 'note': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'notify': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '1'}),
+ 'pages': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+ 'related': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.DocAlias']", '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': "orm['person.Person']"}),
+ 'states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'blank': 'True'}),
+ 'std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StdLevelName']", 'null': 'True', 'blank': 'True'}),
+ 'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocStreamName']", 'null': 'True', 'blank': 'True'}),
+ 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['name.DocTagName']", 'null': 'True', 'blank': 'True'}),
+ 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'})
+ },
+ 'doc.state': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'next_states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']"}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}),
+ 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.StateType']"}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'doc.statetype': {
+ 'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '30', 'primary_key': 'True'})
+ },
+ 'group.group': {
+ 'acronym': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '16', 'blank': 'True'}),
+ 'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True', 'blank': 'True'}),
+ 'charter': ('django.db.models.fields.related.OneToOneField', [], {'blank': 'True', 'related_name': "'chartered_group'", 'unique': 'True', 'null': 'True', 'to': "orm['doc.Document']"}),
+ 'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'iesg_state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.IesgGroupStateName']", 'null': 'True', 'blank': 'True'}),
+ 'list_archive': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+ 'list_email': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
+ 'list_subscribe': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
+ 'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
+ 'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupStateName']", 'null': 'True'}),
+ 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupTypeName']", 'null': 'True'}),
+ 'unused_states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']"}),
+ 'unused_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['name.DocTagName']"})
+ },
+ 'name.docstreamname': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.doctagname': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.doctypename': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.groupstatename': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.grouptypename': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.iesggroupstatename': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.intendedstdlevelname': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.stdlevelname': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'person.email': {
+ 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+ 'address': ('django.db.models.fields.CharField', [], {'max_length': '64', 'primary_key': 'True'}),
+ 'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True'}),
+ 'time': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'})
+ },
+ 'person.person': {
+ 'address': ('django.db.models.fields.TextField', [], {'max_length': '255', 'blank': 'True'}),
+ 'affiliation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+ 'ascii': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'ascii_short': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
+ 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'null': 'True', 'blank': 'True'})
+ }
+ }
+
+ complete_apps = ['community']
diff --git a/ietf/community/migrations/0005_auto__add_field_communitylist_secret.py b/ietf/community/migrations/0005_auto__add_field_communitylist_secret.py
new file mode 100644
index 000000000..1ea3cf4bf
--- /dev/null
+++ b/ietf/community/migrations/0005_auto__add_field_communitylist_secret.py
@@ -0,0 +1,245 @@
+
+from south.db import db
+from django.db import models
+from ietf.community.models import *
+
+class Migration:
+
+ def forwards(self, orm):
+
+ # Adding field 'CommunityList.secret'
+ db.add_column('community_communitylist', 'secret', orm['community.communitylist:secret'])
+
+
+
+ def backwards(self, orm):
+
+ # Deleting field 'CommunityList.secret'
+ db.delete_column('community_communitylist', 'secret')
+
+
+
+ models = {
+ 'auth.group': {
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})
+ },
+ 'auth.permission': {
+ 'Meta': {'unique_together': "(('content_type', 'codename'),)"},
+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'auth.user': {
+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'})
+ },
+ 'community.communitylist': {
+ 'added_ids': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.Document']"}),
+ 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'secret': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'})
+ },
+ 'community.displayconfiguration': {
+ 'community_list': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['community.CommunityList']"}),
+ 'display_fields': ('django.db.models.fields.TextField', [], {'default': "'filename,title,date'"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'sort_method': ('django.db.models.fields.CharField', [], {'default': "'by_filename'", 'max_length': '100'})
+ },
+ 'community.documentchangedates': {
+ 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'new_version_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'normal_change_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'significant_change_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
+ },
+ 'community.emailsubscription': {
+ 'community_list': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['community.CommunityList']"}),
+ 'email': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'significant': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})
+ },
+ 'community.expectedchange': {
+ 'community_list': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['community.CommunityList']"}),
+ 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
+ 'expected_date': ('django.db.models.fields.DateField', [], {}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
+ },
+ 'community.listnotification': {
+ 'event': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.DocEvent']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'significant': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})
+ },
+ 'community.rule': {
+ 'cached_ids': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.Document']"}),
+ 'community_list': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['community.CommunityList']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'last_updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+ 'rule_type': ('django.db.models.fields.CharField', [], {'max_length': '30'}),
+ 'value': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+ },
+ 'contenttypes.contenttype': {
+ 'Meta': {'unique_together': "(('app_label', 'model'),)", 'db_table': "'django_content_type'"},
+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+ },
+ 'doc.docalias': {
+ 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'})
+ },
+ 'doc.docevent': {
+ 'by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"}),
+ 'desc': ('django.db.models.fields.TextField', [], {}),
+ 'doc': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'type': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'doc.document': {
+ 'abstract': ('django.db.models.fields.TextField', [], {}),
+ 'ad': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'ad_document_set'", 'null': 'True', 'to': "orm['person.Person']"}),
+ 'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['person.Email']", 'blank': 'True'}),
+ 'external_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
+ 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
+ 'intended_std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.IntendedStdLevelName']", 'null': 'True', 'blank': 'True'}),
+ 'internal_comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'primary_key': 'True'}),
+ 'note': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'notify': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '1'}),
+ 'pages': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+ 'related': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.DocAlias']", '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': "orm['person.Person']"}),
+ 'states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'blank': 'True'}),
+ 'std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StdLevelName']", 'null': 'True', 'blank': 'True'}),
+ 'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocStreamName']", 'null': 'True', 'blank': 'True'}),
+ 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['name.DocTagName']", 'null': 'True', 'blank': 'True'}),
+ 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'})
+ },
+ 'doc.state': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'next_states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']"}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}),
+ 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.StateType']"}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'doc.statetype': {
+ 'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '30', 'primary_key': 'True'})
+ },
+ 'group.group': {
+ 'acronym': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '16', 'blank': 'True'}),
+ 'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True', 'blank': 'True'}),
+ 'charter': ('django.db.models.fields.related.OneToOneField', [], {'blank': 'True', 'related_name': "'chartered_group'", 'unique': 'True', 'null': 'True', 'to': "orm['doc.Document']"}),
+ 'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'iesg_state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.IesgGroupStateName']", 'null': 'True', 'blank': 'True'}),
+ 'list_archive': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+ 'list_email': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
+ 'list_subscribe': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
+ 'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
+ 'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupStateName']", 'null': 'True'}),
+ 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupTypeName']", 'null': 'True'}),
+ 'unused_states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']"}),
+ 'unused_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['name.DocTagName']"})
+ },
+ 'name.docstreamname': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.doctagname': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.doctypename': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.groupstatename': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.grouptypename': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.iesggroupstatename': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.intendedstdlevelname': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.stdlevelname': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'person.email': {
+ 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+ 'address': ('django.db.models.fields.CharField', [], {'max_length': '64', 'primary_key': 'True'}),
+ 'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True'}),
+ 'time': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'})
+ },
+ 'person.person': {
+ 'address': ('django.db.models.fields.TextField', [], {'max_length': '255', 'blank': 'True'}),
+ 'affiliation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+ 'ascii': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'ascii_short': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
+ 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'null': 'True', 'blank': 'True'})
+ }
+ }
+
+ complete_apps = ['community']
diff --git a/ietf/community/migrations/0006_auto__add_field_communitylist_cached.py b/ietf/community/migrations/0006_auto__add_field_communitylist_cached.py
new file mode 100644
index 000000000..d566e2758
--- /dev/null
+++ b/ietf/community/migrations/0006_auto__add_field_communitylist_cached.py
@@ -0,0 +1,246 @@
+
+from south.db import db
+from django.db import models
+from ietf.community.models import *
+
+class Migration:
+
+ def forwards(self, orm):
+
+ # Adding field 'CommunityList.cached'
+ db.add_column('community_communitylist', 'cached', orm['community.communitylist:cached'])
+
+
+
+ def backwards(self, orm):
+
+ # Deleting field 'CommunityList.cached'
+ db.delete_column('community_communitylist', 'cached')
+
+
+
+ models = {
+ 'auth.group': {
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})
+ },
+ 'auth.permission': {
+ 'Meta': {'unique_together': "(('content_type', 'codename'),)"},
+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'auth.user': {
+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'})
+ },
+ 'community.communitylist': {
+ 'added_ids': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.Document']"}),
+ 'cached': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'secret': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'})
+ },
+ 'community.displayconfiguration': {
+ 'community_list': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['community.CommunityList']"}),
+ 'display_fields': ('django.db.models.fields.TextField', [], {'default': "'filename,title,date'"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'sort_method': ('django.db.models.fields.CharField', [], {'default': "'by_filename'", 'max_length': '100'})
+ },
+ 'community.documentchangedates': {
+ 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'new_version_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'normal_change_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'significant_change_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
+ },
+ 'community.emailsubscription': {
+ 'community_list': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['community.CommunityList']"}),
+ 'email': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'significant': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})
+ },
+ 'community.expectedchange': {
+ 'community_list': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['community.CommunityList']"}),
+ 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
+ 'expected_date': ('django.db.models.fields.DateField', [], {}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
+ },
+ 'community.listnotification': {
+ 'event': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.DocEvent']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'significant': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})
+ },
+ 'community.rule': {
+ 'cached_ids': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.Document']"}),
+ 'community_list': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['community.CommunityList']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'last_updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+ 'rule_type': ('django.db.models.fields.CharField', [], {'max_length': '30'}),
+ 'value': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+ },
+ 'contenttypes.contenttype': {
+ 'Meta': {'unique_together': "(('app_label', 'model'),)", 'db_table': "'django_content_type'"},
+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+ },
+ 'doc.docalias': {
+ 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'})
+ },
+ 'doc.docevent': {
+ 'by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"}),
+ 'desc': ('django.db.models.fields.TextField', [], {}),
+ 'doc': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'type': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'doc.document': {
+ 'abstract': ('django.db.models.fields.TextField', [], {}),
+ 'ad': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'ad_document_set'", 'null': 'True', 'to': "orm['person.Person']"}),
+ 'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['person.Email']", 'blank': 'True'}),
+ 'external_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
+ 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
+ 'intended_std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.IntendedStdLevelName']", 'null': 'True', 'blank': 'True'}),
+ 'internal_comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'primary_key': 'True'}),
+ 'note': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'notify': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '1'}),
+ 'pages': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+ 'related': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.DocAlias']", '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': "orm['person.Person']"}),
+ 'states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'blank': 'True'}),
+ 'std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StdLevelName']", 'null': 'True', 'blank': 'True'}),
+ 'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocStreamName']", 'null': 'True', 'blank': 'True'}),
+ 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['name.DocTagName']", 'null': 'True', 'blank': 'True'}),
+ 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'})
+ },
+ 'doc.state': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'next_states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']"}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}),
+ 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.StateType']"}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'doc.statetype': {
+ 'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '30', 'primary_key': 'True'})
+ },
+ 'group.group': {
+ 'acronym': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '16', 'blank': 'True'}),
+ 'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True', 'blank': 'True'}),
+ 'charter': ('django.db.models.fields.related.OneToOneField', [], {'blank': 'True', 'related_name': "'chartered_group'", 'unique': 'True', 'null': 'True', 'to': "orm['doc.Document']"}),
+ 'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'iesg_state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.IesgGroupStateName']", 'null': 'True', 'blank': 'True'}),
+ 'list_archive': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+ 'list_email': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
+ 'list_subscribe': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
+ 'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
+ 'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupStateName']", 'null': 'True'}),
+ 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupTypeName']", 'null': 'True'}),
+ 'unused_states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']"}),
+ 'unused_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['name.DocTagName']"})
+ },
+ 'name.docstreamname': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.doctagname': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.doctypename': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.groupstatename': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.grouptypename': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.iesggroupstatename': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.intendedstdlevelname': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'name.stdlevelname': {
+ 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
+ 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'person.email': {
+ 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+ 'address': ('django.db.models.fields.CharField', [], {'max_length': '64', 'primary_key': 'True'}),
+ 'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True'}),
+ 'time': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'})
+ },
+ 'person.person': {
+ 'address': ('django.db.models.fields.TextField', [], {'max_length': '255', 'blank': 'True'}),
+ 'affiliation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+ 'ascii': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'ascii_short': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
+ 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'null': 'True', 'blank': 'True'})
+ }
+ }
+
+ complete_apps = ['community']
diff --git a/ietf/community/migrations/__init__.py b/ietf/community/migrations/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/ietf/community/models.py b/ietf/community/models.py
new file mode 100644
index 000000000..6062e87e0
--- /dev/null
+++ b/ietf/community/models.py
@@ -0,0 +1,262 @@
+import hashlib
+
+from django.conf import settings
+from django.contrib.auth.models import User
+from django.core.urlresolvers import reverse
+from django.db import models
+from django.db.models import signals, Q
+
+from ietf.utils.mail import send_mail
+from redesign.doc.models import Document, DocEvent
+from redesign.group.models import Group, Role
+
+from ietf.community.rules import TYPES_OF_RULES, RuleManager
+from ietf.community.display import (TYPES_OF_SORT, DisplayField,
+ SortMethod)
+from ietf.community.constants import SIGNIFICANT_STATES
+
+
+class CommunityList(models.Model):
+
+ user = models.ForeignKey(User, blank=True, null=True)
+ group = models.ForeignKey(Group, blank=True, null=True)
+ added_ids = models.ManyToManyField(Document)
+ secret = models.CharField(max_length=255, null=True, blank=True)
+ cached = models.TextField(null=True, blank=True)
+
+ def check_manager(self, user):
+ if user == self.user:
+ return True
+ if not self.group or self.group.type.slug not in ('area', 'wg'):
+ return False
+ try:
+ person = user.get_profile()
+ except:
+ return False
+ if self.group.type.slug == 'area':
+ return bool(Role.objects.filter(name__slug='ad', email__in=person.email_set.all(), group=self.group).count())
+ elif self.group.type.slug == 'wg':
+ return bool(Role.objects.filter(name__slug='chair', email__in=person.email_set.all(), group=self.group).count())
+ return False
+
+ def short_name(self):
+ if self.user:
+ return 'Personal list'
+ else:
+ return '%s list' % self.group.acronym
+
+ def long_name(self):
+ if self.user:
+ return 'Personal ID list of %s' % self.user.username
+ else:
+ return 'ID list for %s' % self.group.name
+
+ def __unicode__(self):
+ return self.long_name()
+
+ def get_public_url(self):
+ if self.user:
+ return reverse('view_personal_list', None, args=(self.user.username, ))
+ else:
+ return reverse('view_group_list', None, args=(self.group.acronym, ))
+
+ def get_manage_url(self):
+ if self.user:
+ return reverse('manage_personal_list', None, args=())
+ else:
+ return reverse('manage_group_list', None, args=(self.group.acronym, ))
+
+ def get_display_config(self):
+ dconfig = getattr(self, '_cached_dconfig', None)
+ if not dconfig:
+ self._cached_dconfig = DisplayConfiguration.objects.get_or_create(community_list=self)[0]
+ return self._cached_dconfig
+ return self._cached_dconfig
+
+ def get_documents(self):
+ if hasattr(self, '_cached_documents'):
+ return self._cached_documents
+ docs = self.added_ids.all().distinct().select_related('type', 'group', 'ad')
+ for rule in self.rule_set.all():
+ docs = docs | rule.cached_ids.all().distinct()
+ sort_field = self.get_display_config().get_sort_method().get_sort_field()
+ docs = docs.distinct().order_by(sort_field)
+ self._cached_documents = docs
+ return self._cached_documents
+
+ def get_rfcs_and_drafts(self):
+ if hasattr(self, '_cached_rfcs_and_drafts'):
+ return self._cached_rfcs_and_drafts
+ docs = self.get_documents()
+ sort_method = self.get_display_config().get_sort_method()
+ sort_field = sort_method.get_sort_field()
+ if hasattr(sort_method, 'get_full_rfc_sort'):
+ rfcs = sort_method.get_full_rfc_sort(docs.filter(states__name='rfc').distinct())
+ else:
+ rfcs = docs.filter(states__name='rfc').distinct().order_by(sort_field)
+ if hasattr(sort_method, 'get_full_draft_sort'):
+ drafts = sort_method.get_full_draft_sort(docs.exclude(pk__in=rfcs).distinct())
+ else:
+ drafts = docs.exclude(pk__in=rfcs).distinct().order_by(sort_field)
+ self._cached_rfcs_and_drafts = (rfcs, drafts)
+ return self._cached_rfcs_and_drafts
+
+ def add_subscriptor(self, email, significant):
+ self.emailsubscription_set.get_or_create(email=email, significant=significant)
+
+ def save(self, *args, **kwargs):
+ super(CommunityList, self).save(*args, **kwargs)
+ if not self.secret:
+ self.secret = hashlib.md5('%s%s%s%s' % (settings.SECRET_KEY, self.id, self.user and self.user.id or '', self.group and self.group.id or '')).hexdigest()
+ self.save()
+
+ def update(self):
+ self.cached=None
+ self.save()
+
+
+class Rule(models.Model):
+
+ community_list = models.ForeignKey(CommunityList)
+ cached_ids = models.ManyToManyField(Document)
+
+ rule_type = models.CharField(
+ max_length=30,
+ choices=TYPES_OF_RULES)
+ value = models.CharField(
+ max_length=255)
+
+ last_updated = models.DateTimeField(
+ auto_now=True)
+
+ def get_callable_rule(self):
+ for i in RuleManager.__subclasses__():
+ if i.codename == self.rule_type:
+ return i(self.value)
+ return RuleManager(self.value)
+
+ def save(self, *args, **kwargs):
+ super(Rule, self).save(*args, **kwargs)
+ rule = self.get_callable_rule()
+ self.cached_ids = rule.get_documents()
+ self.community_list.update()
+
+ def delete(self):
+ self.community_list.update()
+ super(Rule, self).delete()
+
+
+class DisplayConfiguration(models.Model):
+
+ community_list = models.ForeignKey(CommunityList)
+ sort_method = models.CharField(
+ max_length=100,
+ choices=TYPES_OF_SORT,
+ default='by_filename',
+ blank=False,
+ null=False)
+ display_fields = models.TextField(
+ default='filename,title,date')
+
+ def get_display_fields_config(self):
+ fields = self.display_fields and self.display_fields.split(',') or []
+ config = []
+ for i in DisplayField.__subclasses__():
+ config.append({
+ 'codename': i.codename,
+ 'description': i.description,
+ 'active': i.codename in fields,
+ })
+ return config
+
+ def get_active_fields(self):
+ fields = self.display_fields and self.display_fields.split(',') or ''
+ active_fields = [i for i in DisplayField.__subclasses__() if i.codename in fields]
+ return active_fields
+
+ def get_all_fields(self):
+ all_fields = [i for i in DisplayField.__subclasses__()]
+ return all_fields
+
+ def get_sort_method(self):
+ for i in SortMethod.__subclasses__():
+ if i.codename == self.sort_method:
+ return i()
+ return SortMethod()
+
+ def save(self, *args, **kwargs):
+ super(DisplayConfiguration, self).save(*args, **kwargs)
+ self.community_list.update()
+
+ def delete(self):
+ self.community_list.update()
+ super(DisplayConfiguration, self).delete()
+
+
+class ExpectedChange(models.Model):
+
+ community_list = models.ForeignKey(CommunityList)
+ document = models.ForeignKey(Document)
+ expected_date = models.DateField(
+ verbose_name='Expected date'
+ )
+
+
+class EmailSubscription(models.Model):
+ community_list = models.ForeignKey(CommunityList)
+ email = models.CharField(max_length=200)
+ significant = models.BooleanField(default=False)
+
+
+class ListNotification(models.Model):
+
+ event = models.ForeignKey(DocEvent)
+ significant = models.BooleanField(default=False)
+
+ def notify_by_email(self):
+ clists = CommunityList.objects.filter(
+ Q(added_ids=self.event.doc) | Q(rule__cached_ids=self.event.doc)).distinct()
+ from_email = settings.DEFAULT_FROM_EMAIL
+ for l in clists:
+ subject = '%s notification: Changes on %s' % (l.long_name(), self.event.doc.name)
+ context = {'notification': self.event,
+ 'clist': l}
+ to_email = ''
+ filter_subscription = {'community_list': l}
+ if not self.significant:
+ filter_subscription['significant'] = False
+ bcc = ','.join(list(set([i.email for i in EmailSubscription.objects.filter(**filter_subscription)])))
+ send_mail(None, to_email, from_email, subject, 'community/public/notification_email.txt', context, bcc=bcc)
+
+
+def notify_events(sender, instance, **kwargs):
+ if not isinstance(instance, DocEvent):
+ return
+ if instance.doc.type.slug != 'draft' or instance.type == 'added_comment':
+ return
+ (changes, created) = DocumentChangeDates.objects.get_or_create(document=instance.doc)
+ changes.normal_change_date = instance.time
+ significant = False
+ if instance.type == 'changed_document' and 'tate changed' in instance.desc:
+ for i in SIGNIFICANT_STATES:
+ if ('%s' % i) in instance.desc:
+ significant = True
+ changes.significant_change_date = instance.time
+ break
+ elif instance.type == 'new_revision':
+ changes.new_version_date = instance.time
+ changes.save()
+ notification = ListNotification.objects.create(
+ event=instance,
+ significant=significant,
+ )
+ notification.notify_by_email()
+signals.post_save.connect(notify_events)
+
+
+class DocumentChangeDates(models.Model):
+
+ document = models.ForeignKey(Document)
+ new_version_date = models.DateTimeField(blank=True, null=True)
+ normal_change_date = models.DateTimeField(blank=True, null=True)
+ significant_change_date = models.DateTimeField(blank=True, null=True)
diff --git a/ietf/community/rules.py b/ietf/community/rules.py
new file mode 100644
index 000000000..2607e5ea3
--- /dev/null
+++ b/ietf/community/rules.py
@@ -0,0 +1,139 @@
+from django.db.models import Q
+
+from ietf.community.utils import get_documents_with
+
+from redesign.doc.models import Document
+from redesign.group.models import Group
+from redesign.person.models import Person
+
+
+class RuleManager(object):
+
+ codename = ''
+ description = ''
+
+ def __init__(self, value):
+ self.value = self.get_value(value)
+
+ def get_value(self, value):
+ return value
+
+ def get_documents(self):
+ return Document.objects.none()
+
+ def options(self):
+ return None
+
+ def show_value(self):
+ return self.value
+
+
+class WgAsociatedRule(RuleManager):
+ codename = 'wg_asociated'
+ description = 'All I-Ds associated with a particular WG'
+
+ def get_documents(self):
+ return Document.objects.filter(Q(type__name='Draft') | Q(states__name='rfc')).filter(group__acronym=self.value).distinct()
+
+ def options(self):
+ return [(i.acronym, i.name) for i in Group.objects.filter(type='wg', state='active').distinct().order_by('name')]
+
+ def show_value(self):
+ try:
+ return Group.objects.get(acronym=self.value).name
+ except Group.DoesNotExist:
+ return self.value
+
+
+class AreaAsociatedRule(RuleManager):
+ codename = 'area_asociated'
+ description = 'All I-Ds associated with all WGs in a particular Area'
+
+ def get_documents(self):
+ return Document.objects.filter(Q(type__name='Draft') | Q(states__name='rfc')).filter(group__parent__acronym=self.value, group__parent__type='area').distinct()
+
+ def options(self):
+ return [(i.acronym, i.name) for i in Group.objects.filter(type='area', state='active').distinct().order_by('name')]
+
+ def show_value(self):
+ try:
+ return Group.objects.get(acronym=self.value).name
+ except Group.DoesNotExist:
+ return self.value
+
+
+class AdResponsibleRule(RuleManager):
+ codename = 'ad_responsible'
+ description = 'All I-Ds with a particular responsible AD'
+
+ def get_documents(self):
+ return Document.objects.filter(Q(type__name='Draft') | Q(states__name='rfc')).filter(ad=self.value).distinct()
+
+ def options(self):
+ return [(i.pk, i.name) for i in Person.objects.filter(role__name='ad').distinct().order_by('name')]
+
+ def show_value(self):
+ try:
+ return Person.objects.get(pk=self.value).name
+ except Person.DoesNotExist:
+ return self.value
+
+
+class AuthorRule(RuleManager):
+ codename = 'author'
+ description = 'All I-Ds with a particular author'
+
+ def get_documents(self):
+ return Document.objects.filter(Q(type__name='Draft') | Q(states__name='rfc')).filter(authors__person__name__icontains=self.value).distinct()
+
+
+class ShepherdRule(RuleManager):
+ codename = 'shepherd'
+ description = 'All I-Ds with a particular document shepherd'
+
+ def get_documents(self):
+ return Document.objects.filter(Q(type__name='Draft') | Q(states__name='rfc')).filter(shepherd__name__icontains=self.value).distinct()
+
+
+class ReferenceToRFCRule(RuleManager):
+ codename = 'reference_to_rfc'
+ description = 'All I-Ds that have a reference to a particular RFC'
+
+ def get_documents(self):
+ return Document.objects.filter(Q(type__name='Draft') | Q(states__name='rfc')).filter(relateddocument__target__document__states__name='rfc', relateddocument__target__document__name__icontains=self.value).distinct()
+
+
+class ReferenceToIDRule(RuleManager):
+ codename = 'reference_to_id'
+ description = 'All I-Ds that have a reference to a particular I-D'
+
+ def get_documents(self):
+ return Document.objects.filter(Q(type__name='Draft') | Q(states__name='rfc')).filter(relateddocument__target__document__type__name='Draft', relateddocument__target__document__name__icontains=self.value).distinct()
+
+
+class ReferenceFromRFCRule(RuleManager):
+ codename = 'reference_from_rfc'
+ description = 'All I-Ds that are referenced by a particular RFC'
+
+ def get_documents(self):
+ return Document.objects.filter(Q(type__name='Draft') | Q(states__name='rfc')).filter(relateddocument__source__states__name='rfc', relateddocument__source__name__icontains=self.value).distinct()
+
+
+
+class ReferenceFromIDRule(RuleManager):
+ codename = 'reference_from_id'
+ description = 'All I-Ds that are referenced by a particular I-D'
+
+ def get_documents(self):
+ return Document.objects.filter(Q(type__name='Draft') | Q(states__name='rfc')).filter(relateddocument__source__type__name='Draft', relateddocument__source__name__icontains=self.value).distinct()
+
+
+class WithTextRule(RuleManager):
+ codename = 'with_text'
+ description = 'All I-Ds that contain a particular text string'
+
+ def get_documents(self):
+ return get_documents_with(self.value).distinct()
+
+
+TYPES_OF_RULES = [(i.codename, i.description) for i in RuleManager.__subclasses__()]
diff --git a/ietf/community/templatetags/__init__.py b/ietf/community/templatetags/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/ietf/community/templatetags/community_tags.py b/ietf/community/templatetags/community_tags.py
new file mode 100644
index 000000000..9a9bb0e18
--- /dev/null
+++ b/ietf/community/templatetags/community_tags.py
@@ -0,0 +1,80 @@
+from django import template
+from django.template.loader import render_to_string
+
+from ietf.community.models import CommunityList
+from redesign.group.models import Role
+
+
+register = template.Library()
+
+
+class CommunityListNode(template.Node):
+
+ def __init__(self, user, var_name):
+ self.user = user
+ self.var_name = var_name
+
+ def render(self, context):
+ user = self.user.resolve(context)
+ if not user or not user.is_authenticated():
+ return ''
+ lists = {'personal': CommunityList.objects.get_or_create(user=user)[0]}
+ try:
+ person = user.get_profile()
+ groups = []
+ managed_areas = [i.group for i in Role.objects.filter(name__slug='ad', email__in=person.email_set.all())]
+ for area in managed_areas:
+ groups.append(CommunityList.objects.get_or_create(group=area)[0])
+ managed_wg = [i.group for i in Role.objects.filter(name__slug='chair', group__type__slug='wg', email__in=person.email_set.all())]
+ for wg in managed_wg:
+ groups.append(CommunityList.objects.get_or_create(group=wg)[0])
+ lists['group'] = groups
+ except:
+ pass
+ context.update({self.var_name: lists})
+ return ''
+
+
+@register.tag
+def get_user_managed_lists(parser, token):
+ firstbits = token.contents.split(None, 2)
+ if len(firstbits) != 3:
+ raise template.TemplateSyntaxError("'get_user_managed_lists' tag takes three arguments")
+ user = parser.compile_filter(firstbits[1])
+ lastbits_reversed = firstbits[2][::-1].split(None, 2)
+ if lastbits_reversed[1][::-1] != 'as':
+ raise template.TemplateSyntaxError("next-to-last argument to 'get_user_managed_lists' tag must"
+ " be 'as'")
+ var_name = lastbits_reversed[0][::-1]
+ return CommunityListNode(user, var_name)
+
+
+@register.inclusion_tag('community/display_field.html', takes_context=False)
+def show_field(field, doc):
+ return {'field': field,
+ 'value': field().get_value(doc),
+ }
+
+
+class CommunityListViewNode(template.Node):
+
+ def __init__(self, clist):
+ self.clist = clist
+
+ def render(self, context):
+ clist = self.clist.resolve(context)
+ if not clist.cached:
+ clist.cached = render_to_string('community/raw_view.html',
+ {'cl': clist,
+ 'dc': clist.get_display_config()})
+ clist.save()
+ return clist.cached
+
+
+@register.tag
+def get_clist_view(parser, token):
+ firstbits = token.contents.split(None, 1)
+ if len(firstbits) != 2:
+ raise template.TemplateSyntaxError("'get_clist_view' tag takes one argument")
+ clist = parser.compile_filter(firstbits[1])
+ return CommunityListViewNode(clist)
diff --git a/ietf/community/urls.py b/ietf/community/urls.py
new file mode 100644
index 000000000..4f066c7d8
--- /dev/null
+++ b/ietf/community/urls.py
@@ -0,0 +1,32 @@
+from django.conf.urls.defaults import patterns, url
+
+
+urlpatterns = patterns('ietf.community.views',
+ url(r'^personal/$', 'manage_personal_list', name='manage_personal_list'),
+ url(r'^personal/csv/$', 'csv_personal_list', name='csv_personal_list'),
+ url(r'^personal/(?P[a-f0-9]+)/view/$', 'view_personal_list', name='view_personal_list'),
+ url(r'^personal/(?P[a-f0-9]+)/changes/feed/$', 'changes_personal_list', name='changes_personal_list'),
+ url(r'^personal/(?P[a-f0-9]+)/changes/significant/feed/$', 'significant_personal_list', name='significant_personal_list'),
+ url(r'^personal/(?P[a-f0-9]+)/subscribe/$', 'subscribe_personal_list', {'significant': False}, name='subscribe_personal_list'),
+ url(r'^personal/(?P[a-f0-9]+)/subscribe/significant/$', 'subscribe_personal_list', {'significant': True}, name='subscribe_significant_personal_list'),
+ url(r'^personal/(?P[a-f0-9]+)/unsubscribe/$', 'unsubscribe_personal_list', {'significant': False}, name='unsubscribe_personal_list'),
+ url(r'^personal/(?P[a-f0-9]+)/unsubscribe/significant/$', 'unsubscribe_personal_list', {'significant': True}, name='unsubscribe_significant_personal_list'),
+
+ url(r'^group/(?P[\w.@+-]+)/$', 'manage_group_list', name='manage_group_list'),
+ url(r'^group/(?P[\w.@+-]+)/view/$', 'view_group_list', name='view_group_list'),
+ url(r'^group/(?P[\w.@+-]+)/changes/feed/$', 'changes_group_list', name='changes_group_list'),
+ url(r'^group/(?P[\w.@+-]+)/changes/significant/feed/$', 'significant_group_list', name='significant_group_list'),
+ url(r'^group/(?P[\w.@+-]+)/csv/$', 'csv_group_list', name='csv_group_list'),
+ url(r'^group/(?P[\w.@+-]+)/subscribe/$', 'subscribe_group_list', {'significant': False}, name='subscribe_group_list'),
+ url(r'^group/(?P[\w.@+-]+)/subscribe/significant/$', 'subscribe_group_list', {'significant': True}, name='subscribe_significant_group_list'),
+ url(r'^group/(?P[\w.@+-]+)/unsubscribe/$', 'unsubscribe_group_list', {'significant': False}, name='unsubscribe_group_list'),
+ url(r'^group/(?P[\w.@+-]+)/unsubscribe/significant/$', 'unsubscribe_group_list', {'significant': True}, name='unsubscribe_significant_group_list'),
+
+ url(r'^add_document/(?P[^/]+)/$', 'add_document', name='community_add_document'),
+ url(r'^(?P[\d]+)/remove_document/(?P[^/]+)/$', 'remove_document', name='community_remove_document'),
+ url(r'^(?P[\d]+)/remove_rule/(?P[^/]+)/$', 'remove_rule', name='community_remove_rule'),
+ url(r'^(?P[\d]+)/subscribe/confirm/(?P[\w.@+-]+)/(?P[\d]+)/(?P[a-f0-9]+)/$', 'confirm_subscription', name='confirm_subscription'),
+ url(r'^(?P[\d]+)/subscribe/significant/confirm/(?P[\w.@+-]+)/(?P[\d]+)/(?P[a-f0-9]+)/$', 'confirm_significant_subscription', name='confirm_significant_subscription'),
+ url(r'^(?P[\d]+)/unsubscribe/confirm/(?P[\w.@+-]+)/(?P[\d]+)/(?P[a-f0-9]+)/$', 'confirm_unsubscription', name='confirm_unsubscription'),
+ url(r'^(?P[\d]+)/unsubscribe/significant/confirm/(?P[\w.@+-]+)/(?P[\d]+)/(?P[a-f0-9]+)/$', 'confirm_significant_unsubscription', name='confirm_significant_unsubscription'),
+)
diff --git a/ietf/community/utils.py b/ietf/community/utils.py
new file mode 100644
index 000000000..7b4f325e0
--- /dev/null
+++ b/ietf/community/utils.py
@@ -0,0 +1,43 @@
+import subprocess
+
+from django.conf import settings
+
+from redesign.doc.models import Document
+
+
+def search_files(files, text):
+ p = subprocess.Popen(['grep', "-l", text] + files, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ stdout, stderr = p.communicate()
+ paths = stdout.strip().split('\n')
+ return paths
+
+
+def get_drafts_with(text):
+ draft_dir = settings.INTERNET_DRAFT_PATH
+ last_files = ['%s%s-%s.txt' % (draft_dir, i.name, i.rev) for i in Document.objects.filter(type='draft')]
+ paths = search_files(last_files, text)
+ result = []
+ for i in paths:
+ result.append(i.replace(draft_dir, '')[:-7])
+ return Document.objects.filter(type='draft', name__in=result)
+
+def search_in_path(path, text):
+ p = subprocess.Popen(['grep', "-rl", text, path], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ stdout, stderr = p.communicate()
+ paths = stdout.strip().split('\n')
+ return paths
+
+def get_rfcs_with(text):
+ rfc_dir = settings.RFC_PATH
+ paths = search_in_path(rfc_dir, text)
+ result = []
+ for i in paths:
+ if i.endswith('.txt'):
+ result.append(i.replace(rfc_dir, '')[:-4])
+ return Document.objects.filter(type='draft', docalias__name__in=result)
+
+def get_documents_with(text):
+ drafts = get_drafts_with(text)
+ rfcs = get_rfcs_with(text)
+ documents = drafts | rfcs
+ return documents.distinct()
diff --git a/ietf/community/views.py b/ietf/community/views.py
new file mode 100644
index 000000000..5efb3abf9
--- /dev/null
+++ b/ietf/community/views.py
@@ -0,0 +1,329 @@
+import csv
+import uuid
+import datetime
+import hashlib
+
+from django.conf import settings
+from django.contrib.auth import REDIRECT_FIELD_NAME
+from django.contrib.auth.models import User
+from django.http import HttpResponse, Http404, HttpResponseRedirect
+from django.shortcuts import get_object_or_404, render_to_response
+from django.template import RequestContext
+from django.utils import simplejson
+from django.utils.http import urlquote
+
+from ietf.community.models import CommunityList, Rule, EmailSubscription, ListNotification
+from ietf.community.forms import RuleForm, DisplayForm, SubscribeForm, UnSubscribeForm
+from redesign.group.models import Group
+from redesign.doc.models import Document, DocEvent
+
+
+def _manage_list(request, clist):
+ display_config = clist.get_display_config()
+ if request.method == 'POST' and request.POST.get('save_rule', None):
+ rule_form = RuleForm(request.POST, clist=clist)
+ display_form = DisplayForm(instance=display_config)
+ if rule_form.is_valid():
+ rule_form.save()
+ rule_form = RuleForm(clist=clist)
+ display_form = DisplayForm(instance=display_config)
+ elif request.method == 'POST' and request.POST.get('save_display', None):
+ display_form = DisplayForm(request.POST, instance=display_config)
+ rule_form = RuleForm(clist=clist)
+ if display_form.is_valid():
+ display_form.save()
+ rule_form = RuleForm(clist=clist)
+ display_form = DisplayForm(instance=display_config)
+ else:
+ rule_form = RuleForm(clist=clist)
+ display_form = DisplayForm(instance=display_config)
+ clist = CommunityList.objects.get(id=clist.id)
+ return render_to_response('community/manage_clist.html',
+ {'cl': clist,
+ 'dc': display_config,
+ 'display_form': display_form,
+ 'rule_form': rule_form},
+ context_instance=RequestContext(request))
+
+
+def manage_personal_list(request):
+ user = request.user
+ if not user.is_authenticated():
+ path = urlquote(request.get_full_path())
+ tup = settings.LOGIN_URL, REDIRECT_FIELD_NAME, path
+ return HttpResponseRedirect('%s?%s=%s' % tup)
+ clist = CommunityList.objects.get_or_create(user=request.user)[0]
+ if not clist.check_manager(request.user):
+ path = urlquote(request.get_full_path())
+ tup = settings.LOGIN_URL, REDIRECT_FIELD_NAME, path
+ return HttpResponseRedirect('%s?%s=%s' % tup)
+ return _manage_list(request, clist)
+
+
+def manage_group_list(request, acronym):
+ group = get_object_or_404(Group, acronym=acronym)
+ if group.type.slug not in ('area', 'wg'):
+ raise Http404
+ clist = CommunityList.objects.get_or_create(group=group)[0]
+ if not clist.check_manager(request.user):
+ path = urlquote(request.get_full_path())
+ tup = settings.LOGIN_URL, REDIRECT_FIELD_NAME, path
+ return HttpResponseRedirect('%s?%s=%s' % tup)
+ return _manage_list(request, clist)
+
+
+def add_document(request, document_name):
+ if not request.user.is_authenticated():
+ path = urlquote(request.get_full_path())
+ tup = settings.LOGIN_URL, REDIRECT_FIELD_NAME, path
+ return HttpResponseRedirect('%s?%s=%s' % tup)
+ doc = get_object_or_404(Document, name=document_name)
+ clist = CommunityList.objects.get_or_create(user=request.user)[0]
+ clist.update()
+ return add_document_to_list(request, clist, doc)
+
+
+def remove_document(request, list_id, document_name):
+ clist = get_object_or_404(CommunityList, pk=list_id)
+ if not clist.check_manager(request.user):
+ path = urlquote(request.get_full_path())
+ tup = settings.LOGIN_URL, REDIRECT_FIELD_NAME, path
+ return HttpResponseRedirect('%s?%s=%s' % tup)
+ doc = get_object_or_404(Document, name=document_name)
+ clist.added_ids.remove(doc)
+ clist.update()
+ return HttpResponseRedirect(clist.get_manage_url())
+
+
+def add_document_to_list(request, clist, doc):
+ if not clist.check_manager(request.user):
+ path = urlquote(request.get_full_path())
+ tup = settings.LOGIN_URL, REDIRECT_FIELD_NAME, path
+ return HttpResponseRedirect('%s?%s=%s' % tup)
+ clist.added_ids.add(doc)
+ return HttpResponse(simplejson.dumps({'success': True}), mimetype='text/plain')
+
+
+def remove_rule(request, list_id, rule_id):
+ clist = get_object_or_404(CommunityList, pk=list_id)
+ if not clist.check_manager(request.user):
+ path = urlquote(request.get_full_path())
+ tup = settings.LOGIN_URL, REDIRECT_FIELD_NAME, path
+ return HttpResponseRedirect('%s?%s=%s' % tup)
+ rule = get_object_or_404(Rule, pk=rule_id)
+ rule.delete()
+ return HttpResponseRedirect(clist.get_manage_url())
+
+
+def _view_list(request, clist):
+ display_config = clist.get_display_config()
+ return render_to_response('community/public/view_list.html',
+ {'cl': clist,
+ 'dc': display_config,
+ },
+ context_instance=RequestContext(request))
+
+
+def view_personal_list(request, secret):
+ clist = get_object_or_404(CommunityList, secret=secret)
+ return _view_list(request, clist)
+
+
+def view_group_list(request, acronym):
+ group = get_object_or_404(Group, acronym=acronym)
+ clist = get_object_or_404(CommunityList, group=group)
+ return _view_list(request, clist)
+
+
+def _atom_view(request, clist, significant=False):
+ documents = [i['pk'] for i in clist.get_documents().values('pk')]
+ notifications = DocEvent.objects.filter(doc__pk__in=documents)\
+ .distinct()\
+ .order_by('-time', '-id')
+ if significant:
+ notifications = notifications.filter(listnotification__significant=True)
+
+ host = request.get_host()
+ feed_url = 'http://%s%s' % (host, request.get_full_path())
+ feed_id = uuid.uuid5(uuid.NAMESPACE_URL, feed_url.encode('utf-8'))
+ title = '%s RSS Feed' % clist.long_name()
+ if significant:
+ subtitle = 'Document significant changes'
+ else:
+ subtitle = 'Document changes'
+
+ return render_to_response('community/public/atom.xml',
+ {'cl': clist,
+ 'entries': notifications[:20],
+ 'title': title,
+ 'subtitle': subtitle,
+ 'id': feed_id.get_urn(),
+ 'updated': datetime.datetime.today(),
+ },
+ mimetype='text/xml',
+ context_instance=RequestContext(request))
+
+
+def changes_personal_list(request, secret):
+ clist = get_object_or_404(CommunityList, secret=secret)
+ return _atom_view(request, clist)
+
+
+def changes_group_list(request, acronym):
+ group = get_object_or_404(Group, acronym=acronym)
+ clist = get_object_or_404(CommunityList, group=group)
+ return _atom_view(request, clist)
+
+
+def significant_personal_list(request, secret):
+ clist = get_object_or_404(CommunityList, secret=secret)
+ return _atom_view(request, clist, significant=True)
+
+
+def significant_group_list(request, acronym):
+ group = get_object_or_404(Group, acronym=acronym)
+ clist = get_object_or_404(CommunityList, group=group)
+ return _atom_view(request, clist, significant=True)
+
+
+def _csv_list(request, clist):
+ display_config = clist.get_display_config()
+ response = HttpResponse(mimetype='text/csv')
+ response['Content-Disposition'] = 'attachment; filename=draft-list.csv'
+
+ writer = csv.writer(response, dialect=csv.excel, delimiter=',')
+ header = []
+ fields = display_config.get_all_fields()
+ for field in fields:
+ header.append(field.description)
+ writer.writerow(header)
+
+ for doc in clist.get_documents():
+ row = []
+ for field in fields:
+ row.append(field().get_value(doc, raw=True))
+ writer.writerow(row)
+ return response
+
+
+def csv_personal_list(request):
+ user = request.user
+ if not user.is_authenticated():
+ path = urlquote(request.get_full_path())
+ tup = settings.LOGIN_URL, REDIRECT_FIELD_NAME, path
+ return HttpResponseRedirect('%s?%s=%s' % tup)
+ clist = CommunityList.objects.get_or_create(user=user)[0]
+ if not clist.check_manager(user):
+ path = urlquote(request.get_full_path())
+ tup = settings.LOGIN_URL, REDIRECT_FIELD_NAME, path
+ return HttpResponseRedirect('%s?%s=%s' % tup)
+ return _csv_list(request, clist)
+
+
+def csv_group_list(request, acronym):
+ group = get_object_or_404(Group, acronym=acronym)
+ if group.type.slug not in ('area', 'wg'):
+ raise Http404
+ clist = CommunityList.objects.get_or_create(group=group)[0]
+ if not clist.check_manager(request.user):
+ path = urlquote(request.get_full_path())
+ tup = settings.LOGIN_URL, REDIRECT_FIELD_NAME, path
+ return HttpResponseRedirect('%s?%s=%s' % tup)
+ return _csv_list(request, clist)
+
+
+def _subscribe_list(request, clist, significant):
+ success = False
+ if request.method == 'POST':
+ form = SubscribeForm(data=request.POST, clist=clist, significant=significant)
+ if form.is_valid():
+ form.save()
+ success = True
+ else:
+ form = SubscribeForm(clist=clist, significant=significant)
+ return render_to_response('community/public/subscribe.html',
+ {'cl': clist,
+ 'form': form,
+ 'success': success,
+ },
+ context_instance=RequestContext(request))
+
+
+def _unsubscribe_list(request, clist, significant):
+ success = False
+ if request.method == 'POST':
+ form = UnSubscribeForm(data=request.POST, clist=clist, significant=significant)
+ if form.is_valid():
+ form.save()
+ success = True
+ else:
+ form = UnSubscribeForm(clist=clist, significant=significant)
+ return render_to_response('community/public/unsubscribe.html',
+ {'cl': clist,
+ 'form': form,
+ 'success': success,
+ 'significant': significant,
+ },
+ context_instance=RequestContext(request))
+
+
+def subscribe_personal_list(request, secret, significant=False):
+ clist = get_object_or_404(CommunityList, secret=secret)
+ return _subscribe_list(request, clist, significant=significant)
+
+
+def subscribe_group_list(request, acronym, significant=False):
+ group = get_object_or_404(Group, acronym=acronym)
+ clist = get_object_or_404(CommunityList, group=group)
+ return _subscribe_list(request, clist, significant=significant)
+
+
+def unsubscribe_personal_list(request, secret, significant=False):
+ clist = get_object_or_404(CommunityList, secret=secret)
+ return _unsubscribe_list(request, clist, significant=significant)
+
+
+def unsubscribe_group_list(request, acronym, significant=False):
+ group = get_object_or_404(Group, acronym=acronym)
+ clist = get_object_or_404(CommunityList, group=group)
+ return _unsubscribe_list(request, clist, significant=significant)
+
+
+def confirm_subscription(request, list_id, email, date, confirm_hash, significant=False):
+ clist = get_object_or_404(CommunityList, pk=list_id)
+ valid = hashlib.md5('%s%s%s%s%s' % (settings.SECRET_KEY, date, email, 'subscribe', significant)).hexdigest() == confirm_hash
+ if not valid:
+ raise Http404
+ (subscription, created) = EmailSubscription.objects.get_or_create(
+ community_list=clist,
+ email=email,
+ significant=significant)
+ return render_to_response('community/public/subscription_confirm.html',
+ {'cl': clist,
+ 'significant': significant,
+ },
+ context_instance=RequestContext(request))
+
+
+def confirm_significant_subscription(request, list_id, email, date, confirm_hash):
+ return confirm_subscription(request, list_id, email, date, confirm_hash, significant=True)
+
+
+def confirm_unsubscription(request, list_id, email, date, confirm_hash, significant=False):
+ clist = get_object_or_404(CommunityList, pk=list_id)
+ valid = hashlib.md5('%s%s%s%s%s' % (settings.SECRET_KEY, date, email, 'unsubscribe', significant)).hexdigest() == confirm_hash
+ if not valid:
+ raise Http404
+ EmailSubscription.objects.filter(
+ community_list=clist,
+ email=email,
+ significant=significant).delete()
+ return render_to_response('community/public/unsubscription_confirm.html',
+ {'cl': clist,
+ 'significant': significant,
+ },
+ context_instance=RequestContext(request))
+
+
+def confirm_significant_unsubscription(request, list_id, email, date, confirm_hash):
+ return confirm_unsubscription(request, list_id, email, date, confirm_hash, significant=True)
diff --git a/ietf/settings.py b/ietf/settings.py
index 3baeaef27..a2af787c3 100644
--- a/ietf/settings.py
+++ b/ietf/settings.py
@@ -44,12 +44,12 @@ DATABASES = {
'USER': 'ietf',
#'PASSWORD': 'ietf',
},
- 'legacy': {
- 'NAME': 'ietf',
- 'ENGINE': 'django.db.backends.mysql',
- 'USER': 'ietf',
- #'PASSWORD': 'ietf',
- },
+# 'legacy': {
+# 'NAME': 'ietf',
+# 'ENGINE': 'django.db.backends.mysql',
+# 'USER': 'ietf',
+# #'PASSWORD': 'ietf',
+# },
}
# Local time zone for this installation. Choices can be found here:
@@ -86,7 +86,7 @@ ADMIN_MEDIA_PREFIX = '/media/'
AUTH_PROFILE_MODULE = 'person.Person'
AUTHENTICATION_BACKENDS = ( 'django.contrib.auth.backends.RemoteUserBackend', )
-DATABASE_ROUTERS = ["ietf.legacy_router.LegacyRouter"]
+#DATABASE_ROUTERS = ["ietf.legacy_router.LegacyRouter"]
SESSION_COOKIE_AGE = 43200 # 12 hours
SESSION_EXPIRE_AT_BROWSER_CLOSE = True