Merged in changes from former milestones branch

- Legacy-Id: 4516
This commit is contained in:
Ole Laursen 2012-06-26 18:09:43 +00:00
commit 8929413a71
35 changed files with 3649 additions and 380 deletions

View file

@ -314,6 +314,7 @@ EVENT_TYPES = [
# WG events
("changed_group", "Changed group"),
("changed_protocol_writeup", "Changed protocol writeup"),
("changed_charter_milestone", "Changed charter milestone"),
# charter events
("initial_review", "Set initial review time"),

View file

@ -116,8 +116,8 @@ class GroupHistoryAdmin(admin.ModelAdmin):
admin.site.register(GroupHistory, GroupHistoryAdmin)
class GroupMilestoneAdmin(admin.ModelAdmin):
list_display = ["group", "desc", "expected_due_date", "time"]
search_fields = ["group__name", "group__acronym", "desc"]
list_display = ["group", "desc", "due", "resolved", "time"]
search_fields = ["group__name", "group__acronym", "desc", "resolved"]
raw_id_fields = ["group"]
admin.site.register(GroupMilestone, GroupMilestoneAdmin)

View file

@ -0,0 +1,481 @@
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding model 'Group'
db.create_table('group_group', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('time', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),
('name', self.gf('django.db.models.fields.CharField')(max_length=80)),
('state', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['name.GroupStateName'], null=True)),
('type', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['name.GroupTypeName'], null=True)),
('parent', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['group.Group'], null=True, blank=True)),
('ad', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['person.Person'], null=True, blank=True)),
('list_email', self.gf('django.db.models.fields.CharField')(max_length=64, blank=True)),
('list_subscribe', self.gf('django.db.models.fields.CharField')(max_length=255, blank=True)),
('list_archive', self.gf('django.db.models.fields.CharField')(max_length=255, blank=True)),
('comments', self.gf('django.db.models.fields.TextField')(blank=True)),
('acronym', self.gf('django.db.models.fields.SlugField')(unique=True, max_length=40, db_index=True)),
('charter', self.gf('django.db.models.fields.related.OneToOneField')(blank=True, related_name='chartered_group', unique=True, null=True, to=orm['doc.Document'])),
))
db.send_create_signal('group', ['Group'])
# Adding M2M table for field unused_states on 'Group'
db.create_table('group_group_unused_states', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('group', models.ForeignKey(orm['group.group'], null=False)),
('state', models.ForeignKey(orm['doc.state'], null=False))
))
db.create_unique('group_group_unused_states', ['group_id', 'state_id'])
# Adding M2M table for field unused_tags on 'Group'
db.create_table('group_group_unused_tags', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('group', models.ForeignKey(orm['group.group'], null=False)),
('doctagname', models.ForeignKey(orm['name.doctagname'], null=False))
))
db.create_unique('group_group_unused_tags', ['group_id', 'doctagname_id'])
# Adding model 'GroupHistory'
db.create_table('group_grouphistory', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('time', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),
('name', self.gf('django.db.models.fields.CharField')(max_length=80)),
('state', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['name.GroupStateName'], null=True)),
('type', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['name.GroupTypeName'], null=True)),
('parent', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['group.Group'], null=True, blank=True)),
('ad', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['person.Person'], null=True, blank=True)),
('list_email', self.gf('django.db.models.fields.CharField')(max_length=64, blank=True)),
('list_subscribe', self.gf('django.db.models.fields.CharField')(max_length=255, blank=True)),
('list_archive', self.gf('django.db.models.fields.CharField')(max_length=255, blank=True)),
('comments', self.gf('django.db.models.fields.TextField')(blank=True)),
('group', self.gf('django.db.models.fields.related.ForeignKey')(related_name='history_set', to=orm['group.Group'])),
('acronym', self.gf('django.db.models.fields.CharField')(max_length=40)),
))
db.send_create_signal('group', ['GroupHistory'])
# Adding M2M table for field unused_states on 'GroupHistory'
db.create_table('group_grouphistory_unused_states', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('grouphistory', models.ForeignKey(orm['group.grouphistory'], null=False)),
('state', models.ForeignKey(orm['doc.state'], null=False))
))
db.create_unique('group_grouphistory_unused_states', ['grouphistory_id', 'state_id'])
# Adding M2M table for field unused_tags on 'GroupHistory'
db.create_table('group_grouphistory_unused_tags', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('grouphistory', models.ForeignKey(orm['group.grouphistory'], null=False)),
('doctagname', models.ForeignKey(orm['name.doctagname'], null=False))
))
db.create_unique('group_grouphistory_unused_tags', ['grouphistory_id', 'doctagname_id'])
# Adding model 'GroupURL'
db.create_table('group_groupurl', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('group', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['group.Group'])),
('name', self.gf('django.db.models.fields.CharField')(max_length=255)),
('url', self.gf('django.db.models.fields.URLField')(max_length=200)),
))
db.send_create_signal('group', ['GroupURL'])
# Adding model 'GroupMilestone'
db.create_table('group_groupmilestone', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('group', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['group.Group'])),
('desc', self.gf('django.db.models.fields.TextField')()),
('expected_due_date', self.gf('django.db.models.fields.DateField')()),
('done', self.gf('django.db.models.fields.BooleanField')(default=False)),
('done_date', self.gf('django.db.models.fields.DateField')(null=True, blank=True)),
('time', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)),
))
db.send_create_signal('group', ['GroupMilestone'])
# Adding model 'GroupStateTransitions'
db.create_table('group_groupstatetransitions', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('group', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['group.Group'])),
('state', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['doc.State'])),
))
db.send_create_signal('group', ['GroupStateTransitions'])
# Adding M2M table for field next_states on 'GroupStateTransitions'
db.create_table('group_groupstatetransitions_next_states', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('groupstatetransitions', models.ForeignKey(orm['group.groupstatetransitions'], null=False)),
('state', models.ForeignKey(orm['doc.state'], null=False))
))
db.create_unique('group_groupstatetransitions_next_states', ['groupstatetransitions_id', 'state_id'])
# Adding model 'GroupEvent'
db.create_table('group_groupevent', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('group', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['group.Group'])),
('time', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),
('type', self.gf('django.db.models.fields.CharField')(max_length=50)),
('by', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['person.Person'])),
('desc', self.gf('django.db.models.fields.TextField')()),
))
db.send_create_signal('group', ['GroupEvent'])
# Adding model 'ChangeStateGroupEvent'
db.create_table('group_changestategroupevent', (
('groupevent_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['group.GroupEvent'], unique=True, primary_key=True)),
('state', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['name.GroupStateName'])),
))
db.send_create_signal('group', ['ChangeStateGroupEvent'])
# Adding model 'Role'
db.create_table('group_role', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('name', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['name.RoleName'])),
('group', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['group.Group'])),
('person', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['person.Person'])),
('email', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['person.Email'])),
))
db.send_create_signal('group', ['Role'])
# Adding model 'RoleHistory'
db.create_table('group_rolehistory', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('name', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['name.RoleName'])),
('group', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['group.GroupHistory'])),
('person', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['person.Person'])),
('email', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['person.Email'])),
))
db.send_create_signal('group', ['RoleHistory'])
def backwards(self, orm):
# Deleting model 'Group'
db.delete_table('group_group')
# Removing M2M table for field unused_states on 'Group'
db.delete_table('group_group_unused_states')
# Removing M2M table for field unused_tags on 'Group'
db.delete_table('group_group_unused_tags')
# Deleting model 'GroupHistory'
db.delete_table('group_grouphistory')
# Removing M2M table for field unused_states on 'GroupHistory'
db.delete_table('group_grouphistory_unused_states')
# Removing M2M table for field unused_tags on 'GroupHistory'
db.delete_table('group_grouphistory_unused_tags')
# Deleting model 'GroupURL'
db.delete_table('group_groupurl')
# Deleting model 'GroupMilestone'
db.delete_table('group_groupmilestone')
# Deleting model 'GroupStateTransitions'
db.delete_table('group_groupstatetransitions')
# Removing M2M table for field next_states on 'GroupStateTransitions'
db.delete_table('group_groupstatetransitions_next_states')
# Deleting model 'GroupEvent'
db.delete_table('group_groupevent')
# Deleting model 'ChangeStateGroupEvent'
db.delete_table('group_changestategroupevent')
# Deleting model 'Role'
db.delete_table('group_role')
# Deleting model 'RoleHistory'
db.delete_table('group_rolehistory')
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'doc.docalias': {
'Meta': {'object_name': 'DocAlias'},
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'})
},
'doc.document': {
'Meta': {'object_name': 'Document'},
'abstract': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'ad': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'ad_document_set'", 'null': 'True', 'to': "orm['person.Person']"}),
'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['person.Email']", 'symmetrical': 'False', 'through': "orm['doc.DocumentAuthor']", 'blank': 'True'}),
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'external_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
'intended_std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.IntendedStdLevelName']", 'null': 'True', 'blank': 'True'}),
'internal_comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'primary_key': 'True'}),
'note': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'notify': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '1', 'blank': 'True'}),
'pages': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'related': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'reversely_related_document_set'", 'blank': 'True', 'through': "orm['doc.RelatedDocument']", 'to': "orm['doc.DocAlias']"}),
'rev': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}),
'shepherd': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'shepherd_document_set'", 'null': 'True', 'to': "orm['person.Person']"}),
'states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
'std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StdLevelName']", 'null': 'True', 'blank': 'True'}),
'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StreamName']", 'null': 'True', 'blank': 'True'}),
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['name.DocTagName']", 'null': 'True', 'blank': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'})
},
'doc.documentauthor': {
'Meta': {'ordering': "['document', 'order']", 'object_name': 'DocumentAuthor'},
'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Email']"}),
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '1'})
},
'doc.relateddocument': {
'Meta': {'object_name': 'RelatedDocument'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'relationship': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocRelationshipName']"}),
'source': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
'target': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.DocAlias']"})
},
'doc.state': {
'Meta': {'ordering': "['type', 'order']", 'object_name': 'State'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'next_states': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'previous_states'", 'symmetrical': 'False', 'to': "orm['doc.State']"}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}),
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.StateType']"}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'doc.statetype': {
'Meta': {'object_name': 'StateType'},
'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '30', 'primary_key': 'True'})
},
'group.changestategroupevent': {
'Meta': {'ordering': "['-time', 'id']", 'object_name': 'ChangeStateGroupEvent', '_ormbases': ['group.GroupEvent']},
'groupevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['group.GroupEvent']", 'unique': 'True', 'primary_key': 'True'}),
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupStateName']"})
},
'group.group': {
'Meta': {'object_name': 'Group'},
'acronym': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '40', 'db_index': 'True'}),
'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True', 'blank': 'True'}),
'charter': ('django.db.models.fields.related.OneToOneField', [], {'blank': 'True', 'related_name': "'chartered_group'", 'unique': 'True', 'null': 'True', 'to': "orm['doc.Document']"}),
'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'list_archive': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'list_email': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
'list_subscribe': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupStateName']", 'null': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupTypeName']", 'null': 'True'}),
'unused_states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
'unused_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['name.DocTagName']", 'symmetrical': 'False', 'blank': 'True'})
},
'group.groupevent': {
'Meta': {'ordering': "['-time', 'id']", 'object_name': 'GroupEvent'},
'by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"}),
'desc': ('django.db.models.fields.TextField', [], {}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']"}),
'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'})
},
'group.grouphistory': {
'Meta': {'object_name': 'GroupHistory'},
'acronym': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True', 'blank': 'True'}),
'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'history_set'", 'to': "orm['group.Group']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'list_archive': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'list_email': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
'list_subscribe': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupStateName']", 'null': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupTypeName']", 'null': 'True'}),
'unused_states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
'unused_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['name.DocTagName']", 'symmetrical': 'False', 'blank': 'True'})
},
'group.groupmilestone': {
'Meta': {'ordering': "['expected_due_date']", 'object_name': 'GroupMilestone'},
'desc': ('django.db.models.fields.TextField', [], {}),
'done': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'done_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'expected_due_date': ('django.db.models.fields.DateField', [], {}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
},
'group.groupstatetransitions': {
'Meta': {'object_name': 'GroupStateTransitions'},
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'next_states': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'previous_groupstatetransitions_states'", 'symmetrical': 'False', 'to': "orm['doc.State']"}),
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.State']"})
},
'group.groupurl': {
'Meta': {'object_name': 'GroupURL'},
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'url': ('django.db.models.fields.URLField', [], {'max_length': '200'})
},
'group.role': {
'Meta': {'object_name': 'Role'},
'email': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Email']"}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.RoleName']"}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"})
},
'group.rolehistory': {
'Meta': {'object_name': 'RoleHistory'},
'email': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Email']"}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.GroupHistory']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.RoleName']"}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"})
},
'name.docrelationshipname': {
'Meta': {'ordering': "['order']", 'object_name': 'DocRelationshipName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.doctagname': {
'Meta': {'ordering': "['order']", 'object_name': 'DocTagName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.doctypename': {
'Meta': {'ordering': "['order']", 'object_name': 'DocTypeName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.groupstatename': {
'Meta': {'ordering': "['order']", 'object_name': 'GroupStateName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.grouptypename': {
'Meta': {'ordering': "['order']", 'object_name': 'GroupTypeName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.intendedstdlevelname': {
'Meta': {'ordering': "['order']", 'object_name': 'IntendedStdLevelName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.rolename': {
'Meta': {'ordering': "['order']", 'object_name': 'RoleName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.stdlevelname': {
'Meta': {'ordering': "['order']", 'object_name': 'StdLevelName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.streamname': {
'Meta': {'ordering': "['order']", 'object_name': 'StreamName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'person.email': {
'Meta': {'object_name': 'Email'},
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'address': ('django.db.models.fields.CharField', [], {'max_length': '64', 'primary_key': 'True'}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'})
},
'person.person': {
'Meta': {'object_name': 'Person'},
'address': ('django.db.models.fields.TextField', [], {'max_length': '255', 'blank': 'True'}),
'affiliation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'ascii': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'ascii_short': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'null': 'True', 'blank': 'True'})
}
}
complete_apps = ['group']

View file

@ -0,0 +1,361 @@
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
depends_on = (
("name", "0004_add_groupmilestonestatenames"),
)
def forwards(self, orm):
# Adding model 'MilestoneGroupEvent'
db.create_table('group_milestonegroupevent', (
('groupevent_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['group.GroupEvent'], unique=True, primary_key=True)),
('milestone', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['group.GroupMilestone'])),
))
db.send_create_signal('group', ['MilestoneGroupEvent'])
# rename expected_due_date
db.rename_column('group_groupmilestone', 'expected_due_date', "due")
# Adding field 'GroupMilestone.resolved'
db.add_column('group_groupmilestone', 'resolved', self.gf('django.db.models.fields.CharField')(default='', max_length=50, blank=True), keep_default=False)
# Adding field 'GroupMilestone.state'
db.add_column('group_groupmilestone', 'state', self.gf('django.db.models.fields.related.ForeignKey')(default='active', to=orm['name.GroupMilestoneStateName']), keep_default=False)
# Adding M2M table for field docs on 'GroupMilestone'
db.create_table('group_groupmilestone_docs', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('groupmilestone', models.ForeignKey(orm['group.groupmilestone'], null=False)),
('document', models.ForeignKey(orm['doc.document'], null=False))
))
db.create_unique('group_groupmilestone_docs', ['groupmilestone_id', 'document_id'])
# Changing field 'GroupMilestone.desc'
db.alter_column('group_groupmilestone', 'desc', self.gf('django.db.models.fields.CharField')(max_length=500))
def backwards(self, orm):
# Deleting model 'MilestoneGroupEvent'
db.delete_table('group_milestonegroupevent')
# rename due
db.rename_column('group_groupmilestone', 'due', "expected_due_date")
# Deleting field 'GroupMilestone.resolved'
db.delete_column('group_groupmilestone', 'resolved')
# Deleting field 'GroupMilestone.state'
db.delete_column('group_groupmilestone', 'state_id')
# Removing M2M table for field docs on 'GroupMilestone'
db.delete_table('group_groupmilestone_docs')
# Changing field 'GroupMilestone.desc'
db.alter_column('group_groupmilestone', 'desc', self.gf('django.db.models.fields.TextField')())
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'doc.docalias': {
'Meta': {'object_name': 'DocAlias'},
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'})
},
'doc.document': {
'Meta': {'object_name': 'Document'},
'abstract': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'ad': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'ad_document_set'", 'null': 'True', 'to': "orm['person.Person']"}),
'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['person.Email']", 'symmetrical': 'False', 'through': "orm['doc.DocumentAuthor']", 'blank': 'True'}),
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'external_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
'intended_std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.IntendedStdLevelName']", 'null': 'True', 'blank': 'True'}),
'internal_comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'primary_key': 'True'}),
'note': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'notify': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '1', 'blank': 'True'}),
'pages': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'related': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'reversely_related_document_set'", 'blank': 'True', 'through': "orm['doc.RelatedDocument']", 'to': "orm['doc.DocAlias']"}),
'rev': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}),
'shepherd': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'shepherd_document_set'", 'null': 'True', 'to': "orm['person.Person']"}),
'states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
'std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StdLevelName']", 'null': 'True', 'blank': 'True'}),
'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StreamName']", 'null': 'True', 'blank': 'True'}),
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['name.DocTagName']", 'null': 'True', 'blank': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'})
},
'doc.documentauthor': {
'Meta': {'ordering': "['document', 'order']", 'object_name': 'DocumentAuthor'},
'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Email']"}),
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '1'})
},
'doc.relateddocument': {
'Meta': {'object_name': 'RelatedDocument'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'relationship': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocRelationshipName']"}),
'source': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
'target': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.DocAlias']"})
},
'doc.state': {
'Meta': {'ordering': "['type', 'order']", 'object_name': 'State'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'next_states': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'previous_states'", 'symmetrical': 'False', 'to': "orm['doc.State']"}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}),
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.StateType']"}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'doc.statetype': {
'Meta': {'object_name': 'StateType'},
'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '30', 'primary_key': 'True'})
},
'group.changestategroupevent': {
'Meta': {'ordering': "['-time', 'id']", 'object_name': 'ChangeStateGroupEvent', '_ormbases': ['group.GroupEvent']},
'groupevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['group.GroupEvent']", 'unique': 'True', 'primary_key': 'True'}),
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupStateName']"})
},
'group.group': {
'Meta': {'object_name': 'Group'},
'acronym': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '40', 'db_index': 'True'}),
'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True', 'blank': 'True'}),
'charter': ('django.db.models.fields.related.OneToOneField', [], {'blank': 'True', 'related_name': "'chartered_group'", 'unique': 'True', 'null': 'True', 'to': "orm['doc.Document']"}),
'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'list_archive': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'list_email': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
'list_subscribe': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupStateName']", 'null': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupTypeName']", 'null': 'True'}),
'unused_states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
'unused_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['name.DocTagName']", 'symmetrical': 'False', 'blank': 'True'})
},
'group.groupevent': {
'Meta': {'ordering': "['-time', 'id']", 'object_name': 'GroupEvent'},
'by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"}),
'desc': ('django.db.models.fields.TextField', [], {}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']"}),
'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'})
},
'group.grouphistory': {
'Meta': {'object_name': 'GroupHistory'},
'acronym': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True', 'blank': 'True'}),
'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'history_set'", 'to': "orm['group.Group']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'list_archive': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'list_email': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
'list_subscribe': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupStateName']", 'null': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupTypeName']", 'null': 'True'}),
'unused_states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
'unused_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['name.DocTagName']", 'symmetrical': 'False', 'blank': 'True'})
},
'group.groupmilestone': {
'Meta': {'ordering': "['due', 'id']", 'object_name': 'GroupMilestone'},
'desc': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
'docs': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.Document']", 'symmetrical': 'False', 'blank': 'True'}),
'done': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'done_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'due': ('django.db.models.fields.DateField', [], {}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'resolved': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupMilestoneStateName']"}),
'time': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
},
'group.groupstatetransitions': {
'Meta': {'object_name': 'GroupStateTransitions'},
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'next_states': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'previous_groupstatetransitions_states'", 'symmetrical': 'False', 'to': "orm['doc.State']"}),
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.State']"})
},
'group.groupurl': {
'Meta': {'object_name': 'GroupURL'},
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'url': ('django.db.models.fields.URLField', [], {'max_length': '200'})
},
'group.milestonegroupevent': {
'Meta': {'ordering': "['-time', 'id']", 'object_name': 'MilestoneGroupEvent', '_ormbases': ['group.GroupEvent']},
'groupevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['group.GroupEvent']", 'unique': 'True', 'primary_key': 'True'}),
'milestone': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.GroupMilestone']"})
},
'group.role': {
'Meta': {'object_name': 'Role'},
'email': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Email']"}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.RoleName']"}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"})
},
'group.rolehistory': {
'Meta': {'object_name': 'RoleHistory'},
'email': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Email']"}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.GroupHistory']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.RoleName']"}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"})
},
'name.docrelationshipname': {
'Meta': {'ordering': "['order']", 'object_name': 'DocRelationshipName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.doctagname': {
'Meta': {'ordering': "['order']", 'object_name': 'DocTagName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.doctypename': {
'Meta': {'ordering': "['order']", 'object_name': 'DocTypeName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.groupmilestonestatename': {
'Meta': {'ordering': "['order']", 'object_name': 'GroupMilestoneStateName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.groupstatename': {
'Meta': {'ordering': "['order']", 'object_name': 'GroupStateName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.grouptypename': {
'Meta': {'ordering': "['order']", 'object_name': 'GroupTypeName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.intendedstdlevelname': {
'Meta': {'ordering': "['order']", 'object_name': 'IntendedStdLevelName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.rolename': {
'Meta': {'ordering': "['order']", 'object_name': 'RoleName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.stdlevelname': {
'Meta': {'ordering': "['order']", 'object_name': 'StdLevelName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.streamname': {
'Meta': {'ordering': "['order']", 'object_name': 'StreamName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'person.email': {
'Meta': {'object_name': 'Email'},
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'address': ('django.db.models.fields.CharField', [], {'max_length': '64', 'primary_key': 'True'}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'})
},
'person.person': {
'Meta': {'object_name': 'Person'},
'address': ('django.db.models.fields.TextField', [], {'max_length': '255', 'blank': 'True'}),
'affiliation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'ascii': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'ascii_short': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'null': 'True', 'blank': 'True'})
}
}
complete_apps = ['group']

View file

@ -0,0 +1,331 @@
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import DataMigration
from django.db import models
class Migration(DataMigration):
def forwards(self, orm):
"Write your forwards methods here."
system_person = orm["person.Person"].objects.get(name="(System)")
for m in orm.GroupMilestone.objects.all():
if m.done:
m.resolved = "Done"
m.save()
orm.MilestoneGroupEvent.objects.get_or_create(
group_id=m.group_id,
type="changed_milestone",
time=datetime.datetime.combine(m.done_date, datetime.time(0, 0, 0)),
by=system_person,
desc='Changed milestone "%s", resolved as "%s"' % (m.desc, m.resolved),
milestone=m,
)
def backwards(self, orm):
"Write your backwards methods here."
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'doc.docalias': {
'Meta': {'object_name': 'DocAlias'},
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'})
},
'doc.document': {
'Meta': {'object_name': 'Document'},
'abstract': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'ad': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'ad_document_set'", 'null': 'True', 'to': "orm['person.Person']"}),
'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['person.Email']", 'symmetrical': 'False', 'through': "orm['doc.DocumentAuthor']", 'blank': 'True'}),
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'external_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
'intended_std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.IntendedStdLevelName']", 'null': 'True', 'blank': 'True'}),
'internal_comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'primary_key': 'True'}),
'note': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'notify': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '1', 'blank': 'True'}),
'pages': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'related': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'reversely_related_document_set'", 'blank': 'True', 'through': "orm['doc.RelatedDocument']", 'to': "orm['doc.DocAlias']"}),
'rev': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}),
'shepherd': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'shepherd_document_set'", 'null': 'True', 'to': "orm['person.Person']"}),
'states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
'std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StdLevelName']", 'null': 'True', 'blank': 'True'}),
'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StreamName']", 'null': 'True', 'blank': 'True'}),
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['name.DocTagName']", 'null': 'True', 'blank': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'})
},
'doc.documentauthor': {
'Meta': {'ordering': "['document', 'order']", 'object_name': 'DocumentAuthor'},
'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Email']"}),
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '1'})
},
'doc.relateddocument': {
'Meta': {'object_name': 'RelatedDocument'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'relationship': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocRelationshipName']"}),
'source': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
'target': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.DocAlias']"})
},
'doc.state': {
'Meta': {'ordering': "['type', 'order']", 'object_name': 'State'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'next_states': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'previous_states'", 'symmetrical': 'False', 'to': "orm['doc.State']"}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}),
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.StateType']"}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'doc.statetype': {
'Meta': {'object_name': 'StateType'},
'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '30', 'primary_key': 'True'})
},
'group.changestategroupevent': {
'Meta': {'ordering': "['-time', 'id']", 'object_name': 'ChangeStateGroupEvent', '_ormbases': ['group.GroupEvent']},
'groupevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['group.GroupEvent']", 'unique': 'True', 'primary_key': 'True'}),
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupStateName']"})
},
'group.group': {
'Meta': {'object_name': 'Group'},
'acronym': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '40', 'db_index': 'True'}),
'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True', 'blank': 'True'}),
'charter': ('django.db.models.fields.related.OneToOneField', [], {'blank': 'True', 'related_name': "'chartered_group'", 'unique': 'True', 'null': 'True', 'to': "orm['doc.Document']"}),
'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'list_archive': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'list_email': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
'list_subscribe': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupStateName']", 'null': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupTypeName']", 'null': 'True'}),
'unused_states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
'unused_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['name.DocTagName']", 'symmetrical': 'False', 'blank': 'True'})
},
'group.groupevent': {
'Meta': {'ordering': "['-time', 'id']", 'object_name': 'GroupEvent'},
'by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"}),
'desc': ('django.db.models.fields.TextField', [], {}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']"}),
'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'})
},
'group.grouphistory': {
'Meta': {'object_name': 'GroupHistory'},
'acronym': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True', 'blank': 'True'}),
'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'history_set'", 'to': "orm['group.Group']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'list_archive': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'list_email': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
'list_subscribe': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupStateName']", 'null': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupTypeName']", 'null': 'True'}),
'unused_states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
'unused_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['name.DocTagName']", 'symmetrical': 'False', 'blank': 'True'})
},
'group.groupmilestone': {
'Meta': {'ordering': "['due', 'id']", 'object_name': 'GroupMilestone'},
'desc': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
'docs': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.Document']", 'symmetrical': 'False', 'blank': 'True'}),
'done': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'done_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'due': ('django.db.models.fields.DateField', [], {}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'resolved': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupMilestoneStateName']"}),
'time': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
},
'group.groupstatetransitions': {
'Meta': {'object_name': 'GroupStateTransitions'},
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'next_states': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'previous_groupstatetransitions_states'", 'symmetrical': 'False', 'to': "orm['doc.State']"}),
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.State']"})
},
'group.groupurl': {
'Meta': {'object_name': 'GroupURL'},
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'url': ('django.db.models.fields.URLField', [], {'max_length': '200'})
},
'group.milestonegroupevent': {
'Meta': {'ordering': "['-time', 'id']", 'object_name': 'MilestoneGroupEvent', '_ormbases': ['group.GroupEvent']},
'groupevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['group.GroupEvent']", 'unique': 'True', 'primary_key': 'True'}),
'milestone': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.GroupMilestone']"})
},
'group.role': {
'Meta': {'object_name': 'Role'},
'email': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Email']"}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.RoleName']"}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"})
},
'group.rolehistory': {
'Meta': {'object_name': 'RoleHistory'},
'email': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Email']"}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.GroupHistory']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.RoleName']"}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"})
},
'name.docrelationshipname': {
'Meta': {'ordering': "['order']", 'object_name': 'DocRelationshipName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.doctagname': {
'Meta': {'ordering': "['order']", 'object_name': 'DocTagName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.doctypename': {
'Meta': {'ordering': "['order']", 'object_name': 'DocTypeName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.groupmilestonestatename': {
'Meta': {'ordering': "['order']", 'object_name': 'GroupMilestoneStateName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.groupstatename': {
'Meta': {'ordering': "['order']", 'object_name': 'GroupStateName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.grouptypename': {
'Meta': {'ordering': "['order']", 'object_name': 'GroupTypeName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.intendedstdlevelname': {
'Meta': {'ordering': "['order']", 'object_name': 'IntendedStdLevelName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.rolename': {
'Meta': {'ordering': "['order']", 'object_name': 'RoleName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.stdlevelname': {
'Meta': {'ordering': "['order']", 'object_name': 'StdLevelName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.streamname': {
'Meta': {'ordering': "['order']", 'object_name': 'StreamName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'person.email': {
'Meta': {'object_name': 'Email'},
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'address': ('django.db.models.fields.CharField', [], {'max_length': '64', 'primary_key': 'True'}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'})
},
'person.person': {
'Meta': {'object_name': 'Person'},
'address': ('django.db.models.fields.TextField', [], {'max_length': '255', 'blank': 'True'}),
'affiliation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'ascii': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'ascii_short': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'null': 'True', 'blank': 'True'})
}
}
complete_apps = ['group']

View file

@ -0,0 +1,322 @@
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Deleting field 'GroupMilestone.done_date'
db.delete_column('group_groupmilestone', 'done_date')
# Deleting field 'GroupMilestone.done'
db.delete_column('group_groupmilestone', 'done')
def backwards(self, orm):
# Adding field 'GroupMilestone.done_date'
db.add_column('group_groupmilestone', 'done_date', self.gf('django.db.models.fields.DateField')(null=True, blank=True), keep_default=False)
# Adding field 'GroupMilestone.done'
db.add_column('group_groupmilestone', 'done', self.gf('django.db.models.fields.BooleanField')(default=False), keep_default=False)
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'doc.docalias': {
'Meta': {'object_name': 'DocAlias'},
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'})
},
'doc.document': {
'Meta': {'object_name': 'Document'},
'abstract': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'ad': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'ad_document_set'", 'null': 'True', 'to': "orm['person.Person']"}),
'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['person.Email']", 'symmetrical': 'False', 'through': "orm['doc.DocumentAuthor']", 'blank': 'True'}),
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'external_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
'intended_std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.IntendedStdLevelName']", 'null': 'True', 'blank': 'True'}),
'internal_comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'primary_key': 'True'}),
'note': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'notify': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '1', 'blank': 'True'}),
'pages': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'related': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'reversely_related_document_set'", 'blank': 'True', 'through': "orm['doc.RelatedDocument']", 'to': "orm['doc.DocAlias']"}),
'rev': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}),
'shepherd': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'shepherd_document_set'", 'null': 'True', 'to': "orm['person.Person']"}),
'states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
'std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StdLevelName']", 'null': 'True', 'blank': 'True'}),
'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StreamName']", 'null': 'True', 'blank': 'True'}),
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['name.DocTagName']", 'null': 'True', 'blank': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'})
},
'doc.documentauthor': {
'Meta': {'ordering': "['document', 'order']", 'object_name': 'DocumentAuthor'},
'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Email']"}),
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '1'})
},
'doc.relateddocument': {
'Meta': {'object_name': 'RelatedDocument'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'relationship': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocRelationshipName']"}),
'source': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
'target': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.DocAlias']"})
},
'doc.state': {
'Meta': {'ordering': "['type', 'order']", 'object_name': 'State'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'next_states': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'previous_states'", 'symmetrical': 'False', 'to': "orm['doc.State']"}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}),
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.StateType']"}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'doc.statetype': {
'Meta': {'object_name': 'StateType'},
'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '30', 'primary_key': 'True'})
},
'group.changestategroupevent': {
'Meta': {'ordering': "['-time', 'id']", 'object_name': 'ChangeStateGroupEvent', '_ormbases': ['group.GroupEvent']},
'groupevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['group.GroupEvent']", 'unique': 'True', 'primary_key': 'True'}),
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupStateName']"})
},
'group.group': {
'Meta': {'object_name': 'Group'},
'acronym': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '40', 'db_index': 'True'}),
'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True', 'blank': 'True'}),
'charter': ('django.db.models.fields.related.OneToOneField', [], {'blank': 'True', 'related_name': "'chartered_group'", 'unique': 'True', 'null': 'True', 'to': "orm['doc.Document']"}),
'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'list_archive': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'list_email': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
'list_subscribe': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupStateName']", 'null': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupTypeName']", 'null': 'True'}),
'unused_states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
'unused_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['name.DocTagName']", 'symmetrical': 'False', 'blank': 'True'})
},
'group.groupevent': {
'Meta': {'ordering': "['-time', 'id']", 'object_name': 'GroupEvent'},
'by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"}),
'desc': ('django.db.models.fields.TextField', [], {}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']"}),
'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'})
},
'group.grouphistory': {
'Meta': {'object_name': 'GroupHistory'},
'acronym': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True', 'blank': 'True'}),
'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'history_set'", 'to': "orm['group.Group']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'list_archive': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'list_email': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
'list_subscribe': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupStateName']", 'null': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupTypeName']", 'null': 'True'}),
'unused_states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
'unused_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['name.DocTagName']", 'symmetrical': 'False', 'blank': 'True'})
},
'group.groupmilestone': {
'Meta': {'ordering': "['due', 'id']", 'object_name': 'GroupMilestone'},
'desc': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
'docs': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.Document']", 'symmetrical': 'False', 'blank': 'True'}),
'due': ('django.db.models.fields.DateField', [], {}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'resolved': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupMilestoneStateName']"}),
'time': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
},
'group.groupstatetransitions': {
'Meta': {'object_name': 'GroupStateTransitions'},
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'next_states': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'previous_groupstatetransitions_states'", 'symmetrical': 'False', 'to': "orm['doc.State']"}),
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.State']"})
},
'group.groupurl': {
'Meta': {'object_name': 'GroupURL'},
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'url': ('django.db.models.fields.URLField', [], {'max_length': '200'})
},
'group.milestonegroupevent': {
'Meta': {'ordering': "['-time', 'id']", 'object_name': 'MilestoneGroupEvent', '_ormbases': ['group.GroupEvent']},
'groupevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['group.GroupEvent']", 'unique': 'True', 'primary_key': 'True'}),
'milestone': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.GroupMilestone']"})
},
'group.role': {
'Meta': {'object_name': 'Role'},
'email': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Email']"}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.RoleName']"}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"})
},
'group.rolehistory': {
'Meta': {'object_name': 'RoleHistory'},
'email': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Email']"}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.GroupHistory']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.RoleName']"}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"})
},
'name.docrelationshipname': {
'Meta': {'ordering': "['order']", 'object_name': 'DocRelationshipName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.doctagname': {
'Meta': {'ordering': "['order']", 'object_name': 'DocTagName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.doctypename': {
'Meta': {'ordering': "['order']", 'object_name': 'DocTypeName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.groupmilestonestatename': {
'Meta': {'ordering': "['order']", 'object_name': 'GroupMilestoneStateName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.groupstatename': {
'Meta': {'ordering': "['order']", 'object_name': 'GroupStateName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.grouptypename': {
'Meta': {'ordering': "['order']", 'object_name': 'GroupTypeName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.intendedstdlevelname': {
'Meta': {'ordering': "['order']", 'object_name': 'IntendedStdLevelName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.rolename': {
'Meta': {'ordering': "['order']", 'object_name': 'RoleName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.stdlevelname': {
'Meta': {'ordering': "['order']", 'object_name': 'StdLevelName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.streamname': {
'Meta': {'ordering': "['order']", 'object_name': 'StreamName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'person.email': {
'Meta': {'object_name': 'Email'},
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'address': ('django.db.models.fields.CharField', [], {'max_length': '64', 'primary_key': 'True'}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'})
},
'person.person': {
'Meta': {'object_name': 'Person'},
'address': ('django.db.models.fields.TextField', [], {'max_length': '255', 'blank': 'True'}),
'affiliation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'ascii': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'ascii_short': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'null': 'True', 'blank': 'True'})
}
}
complete_apps = ['group']

View file

@ -0,0 +1,349 @@
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding model 'GroupMilestoneHistory'
db.create_table('group_groupmilestonehistory', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('group', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['group.Group'])),
('state', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['name.GroupMilestoneStateName'])),
('desc', self.gf('django.db.models.fields.CharField')(max_length=500)),
('due', self.gf('django.db.models.fields.DateField')()),
('resolved', self.gf('django.db.models.fields.CharField')(max_length=50, blank=True)),
('time', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)),
('milestone', self.gf('django.db.models.fields.related.ForeignKey')(related_name='history_set', to=orm['group.GroupMilestone'])),
))
db.send_create_signal('group', ['GroupMilestoneHistory'])
# Adding M2M table for field docs on 'GroupMilestoneHistory'
db.create_table('group_groupmilestonehistory_docs', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('groupmilestonehistory', models.ForeignKey(orm['group.groupmilestonehistory'], null=False)),
('document', models.ForeignKey(orm['doc.document'], null=False))
))
db.create_unique('group_groupmilestonehistory_docs', ['groupmilestonehistory_id', 'document_id'])
def backwards(self, orm):
# Deleting model 'GroupMilestoneHistory'
db.delete_table('group_groupmilestonehistory')
# Removing M2M table for field docs on 'GroupMilestoneHistory'
db.delete_table('group_groupmilestonehistory_docs')
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'doc.docalias': {
'Meta': {'object_name': 'DocAlias'},
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'})
},
'doc.document': {
'Meta': {'object_name': 'Document'},
'abstract': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'ad': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'ad_document_set'", 'null': 'True', 'to': "orm['person.Person']"}),
'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['person.Email']", 'symmetrical': 'False', 'through': "orm['doc.DocumentAuthor']", 'blank': 'True'}),
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'external_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
'intended_std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.IntendedStdLevelName']", 'null': 'True', 'blank': 'True'}),
'internal_comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'primary_key': 'True'}),
'note': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'notify': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '1', 'blank': 'True'}),
'pages': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'related': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'reversely_related_document_set'", 'blank': 'True', 'through': "orm['doc.RelatedDocument']", 'to': "orm['doc.DocAlias']"}),
'rev': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}),
'shepherd': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'shepherd_document_set'", 'null': 'True', 'to': "orm['person.Person']"}),
'states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
'std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StdLevelName']", 'null': 'True', 'blank': 'True'}),
'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StreamName']", 'null': 'True', 'blank': 'True'}),
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['name.DocTagName']", 'null': 'True', 'blank': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'})
},
'doc.documentauthor': {
'Meta': {'ordering': "['document', 'order']", 'object_name': 'DocumentAuthor'},
'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Email']"}),
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '1'})
},
'doc.relateddocument': {
'Meta': {'object_name': 'RelatedDocument'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'relationship': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocRelationshipName']"}),
'source': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
'target': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.DocAlias']"})
},
'doc.state': {
'Meta': {'ordering': "['type', 'order']", 'object_name': 'State'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'next_states': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'previous_states'", 'symmetrical': 'False', 'to': "orm['doc.State']"}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}),
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.StateType']"}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'doc.statetype': {
'Meta': {'object_name': 'StateType'},
'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '30', 'primary_key': 'True'})
},
'group.changestategroupevent': {
'Meta': {'ordering': "['-time', 'id']", 'object_name': 'ChangeStateGroupEvent', '_ormbases': ['group.GroupEvent']},
'groupevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['group.GroupEvent']", 'unique': 'True', 'primary_key': 'True'}),
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupStateName']"})
},
'group.group': {
'Meta': {'object_name': 'Group'},
'acronym': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '40', 'db_index': 'True'}),
'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True', 'blank': 'True'}),
'charter': ('django.db.models.fields.related.OneToOneField', [], {'blank': 'True', 'related_name': "'chartered_group'", 'unique': 'True', 'null': 'True', 'to': "orm['doc.Document']"}),
'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'list_archive': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'list_email': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
'list_subscribe': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupStateName']", 'null': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupTypeName']", 'null': 'True'}),
'unused_states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
'unused_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['name.DocTagName']", 'symmetrical': 'False', 'blank': 'True'})
},
'group.groupevent': {
'Meta': {'ordering': "['-time', 'id']", 'object_name': 'GroupEvent'},
'by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"}),
'desc': ('django.db.models.fields.TextField', [], {}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']"}),
'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'})
},
'group.grouphistory': {
'Meta': {'object_name': 'GroupHistory'},
'acronym': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True', 'blank': 'True'}),
'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'history_set'", 'to': "orm['group.Group']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'list_archive': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'list_email': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
'list_subscribe': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupStateName']", 'null': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupTypeName']", 'null': 'True'}),
'unused_states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
'unused_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['name.DocTagName']", 'symmetrical': 'False', 'blank': 'True'})
},
'group.groupmilestone': {
'Meta': {'ordering': "['due', 'id']", 'object_name': 'GroupMilestone'},
'desc': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
'docs': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.Document']", 'symmetrical': 'False', 'blank': 'True'}),
'due': ('django.db.models.fields.DateField', [], {}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'resolved': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupMilestoneStateName']"}),
'time': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
},
'group.groupmilestonehistory': {
'Meta': {'ordering': "['due', 'id']", 'object_name': 'GroupMilestoneHistory'},
'desc': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
'docs': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.Document']", 'symmetrical': 'False', 'blank': 'True'}),
'due': ('django.db.models.fields.DateField', [], {}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'milestone': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'history_set'", 'to': "orm['group.GroupMilestone']"}),
'resolved': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupMilestoneStateName']"}),
'time': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
},
'group.groupstatetransitions': {
'Meta': {'object_name': 'GroupStateTransitions'},
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'next_states': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'previous_groupstatetransitions_states'", 'symmetrical': 'False', 'to': "orm['doc.State']"}),
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.State']"})
},
'group.groupurl': {
'Meta': {'object_name': 'GroupURL'},
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'url': ('django.db.models.fields.URLField', [], {'max_length': '200'})
},
'group.milestonegroupevent': {
'Meta': {'ordering': "['-time', 'id']", 'object_name': 'MilestoneGroupEvent', '_ormbases': ['group.GroupEvent']},
'groupevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['group.GroupEvent']", 'unique': 'True', 'primary_key': 'True'}),
'milestone': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.GroupMilestone']"})
},
'group.role': {
'Meta': {'object_name': 'Role'},
'email': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Email']"}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.RoleName']"}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"})
},
'group.rolehistory': {
'Meta': {'object_name': 'RoleHistory'},
'email': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Email']"}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.GroupHistory']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.RoleName']"}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"})
},
'name.docrelationshipname': {
'Meta': {'ordering': "['order']", 'object_name': 'DocRelationshipName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.doctagname': {
'Meta': {'ordering': "['order']", 'object_name': 'DocTagName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.doctypename': {
'Meta': {'ordering': "['order']", 'object_name': 'DocTypeName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.groupmilestonestatename': {
'Meta': {'ordering': "['order']", 'object_name': 'GroupMilestoneStateName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.groupstatename': {
'Meta': {'ordering': "['order']", 'object_name': 'GroupStateName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.grouptypename': {
'Meta': {'ordering': "['order']", 'object_name': 'GroupTypeName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.intendedstdlevelname': {
'Meta': {'ordering': "['order']", 'object_name': 'IntendedStdLevelName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.rolename': {
'Meta': {'ordering': "['order']", 'object_name': 'RoleName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.stdlevelname': {
'Meta': {'ordering': "['order']", 'object_name': 'StdLevelName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.streamname': {
'Meta': {'ordering': "['order']", 'object_name': 'StreamName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'person.email': {
'Meta': {'object_name': 'Email'},
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'address': ('django.db.models.fields.CharField', [], {'max_length': '64', 'primary_key': 'True'}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'})
},
'person.person': {
'Meta': {'object_name': 'Person'},
'address': ('django.db.models.fields.TextField', [], {'max_length': '255', 'blank': 'True'}),
'affiliation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'ascii': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'ascii_short': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'null': 'True', 'blank': 'True'})
}
}
complete_apps = ['group']

View file

View file

@ -60,17 +60,31 @@ class GroupURL(models.Model):
def __unicode__(self):
return u"%s (%s)" % (self.url, self.name)
class GroupMilestone(models.Model):
class GroupMilestoneInfo(models.Model):
group = models.ForeignKey(Group)
desc = models.TextField(verbose_name="Description")
expected_due_date = models.DateField()
done = models.BooleanField()
done_date = models.DateField(null=True, blank=True)
# a group has two sets of milestones, current milestones
# (active/under review/deleted) and charter milestones (active
# during a charter/recharter event), events for charter milestones
# are stored on the charter document
state = models.ForeignKey(GroupMilestoneStateName)
desc = models.CharField(verbose_name="Description", max_length=500)
due = models.DateField()
resolved = models.CharField(max_length=50, blank=True, help_text="Explanation of why milestone is resolved (usually \"Done\"), or empty if still due")
time = models.DateTimeField(auto_now=True)
docs = models.ManyToManyField('doc.Document', blank=True)
def __unicode__(self):
return self.desc[:20] + "..."
class Meta:
ordering = ['expected_due_date']
abstract = True
ordering = ['due', 'id']
class GroupMilestone(GroupMilestoneInfo):
pass
class GroupMilestoneHistory(GroupMilestoneInfo):
milestone = models.ForeignKey(GroupMilestone, related_name="history_set")
class GroupStateTransitions(models.Model):
"""Captures that a group has overriden the default available
@ -87,6 +101,7 @@ GROUP_EVENT_CHOICES = [
("added_comment", "Added comment"),
("info_changed", "Changed metadata"),
("requested_close", "Requested closing group"),
("changed_milestone", "Changed milestone"),
]
class GroupEvent(models.Model):
@ -106,6 +121,9 @@ class GroupEvent(models.Model):
class ChangeStateGroupEvent(GroupEvent):
state = models.ForeignKey(GroupStateName)
class MilestoneGroupEvent(GroupEvent):
milestone = models.ForeignKey(GroupMilestone)
class Role(models.Model):
name = models.ForeignKey(RoleName)
group = models.ForeignKey(Group)

View file

@ -3,33 +3,21 @@ import os
from django.conf import settings
from ietf.group.models import *
from ietf.utils.history import get_history_object_for, copy_many_to_many_for_history
def save_group_in_history(group):
def get_model_fields_as_dict(obj):
return dict((field.name, getattr(obj, field.name))
for field in obj._meta.fields
if field is not obj._meta.pk)
# copy fields
fields = get_model_fields_as_dict(group)
del fields["charter"] # Charter is saved canonically on Group
fields["group"] = group
grouphist = GroupHistory(**fields)
grouphist.save()
h = get_history_object_for(group)
h.save()
# save RoleHistory
for role in group.role_set.all():
rh = RoleHistory(name=role.name, group=grouphist, email=role.email, person=role.person)
rh.save()
# copy many to many
for field in group._meta.many_to_many:
if field.rel.through and field.rel.through._meta.auto_created:
setattr(grouphist, field.name, getattr(group, field.name).all())
copy_many_to_many_for_history(h, group)
return grouphist
return h
def get_charter_text(group):
# get file path from settings. Syntesize file name from path, acronym, and suffix
@ -55,3 +43,12 @@ def get_charter_text(group):
except BaseException:
desc = 'Error Loading Work Group Description'
return desc
def save_milestone_in_history(milestone):
h = get_history_object_for(milestone)
h.milestone = milestone
h.save()
copy_many_to_many_for_history(h, milestone)
return h

View file

@ -91,7 +91,7 @@ def document_main(request, name, rev=None):
doc = get_object_or_404(Document, docalias__name=name)
group = doc.group
revisions = []
for h in doc.history_set.order_by("time", "id"):
if h.rev and not h.rev in revisions:
@ -136,10 +136,17 @@ def document_main(request, name, rev=None):
if doc.get_state_slug() in ("intrev", "iesgrev"):
ballot_summary = needed_ballot_positions(doc, active_ballot_positions(doc).values())
chartering = get_chartering_type(doc)
# inject milestones from group
milestones = None
if chartering and not snapshot:
milestones = doc.group.groupmilestone_set.filter(state="charter")
return render_to_response("idrfc/document_charter.html",
dict(doc=doc,
top=top,
chartering=get_chartering_type(doc),
chartering=chartering,
content=content,
txt_url=settings.CHARTER_TXT_URL + filename,
revisions=revisions,
@ -147,6 +154,7 @@ def document_main(request, name, rev=None):
telechat=telechat,
ballot_summary=ballot_summary,
group=group,
milestones=milestones,
),
context_instance=RequestContext(request))

View file

@ -19,7 +19,7 @@
<field type="TextField" name="desc"></field>
<field type="BooleanField" name="used">True</field>
<field type="IntegerField" name="order">3</field>
<field type="BooleanField" name="blocking">False</field>
<field type="BooleanField" name="blocking">True</field>
</object>
<object pk="block" model="name.ballotpositionname">
<field type="CharField" name="name">Block</field>
@ -307,35 +307,29 @@
<field type="BooleanField" name="used">True</field>
<field type="IntegerField" name="order">0</field>
</object>
<object pk="no" model="name.groupballotpositionname">
<field type="CharField" name="name">No</field>
<object pk="active" model="name.groupmilestonestatename">
<field type="CharField" name="name">Active</field>
<field type="TextField" name="desc"></field>
<field type="BooleanField" name="used">True</field>
<field type="IntegerField" name="order">0</field>
<field type="IntegerField" name="order">1</field>
</object>
<object pk="yes" model="name.groupballotpositionname">
<field type="CharField" name="name">Yes</field>
<object pk="deleted" model="name.groupmilestonestatename">
<field type="CharField" name="name">Deleted</field>
<field type="TextField" name="desc"></field>
<field type="BooleanField" name="used">True</field>
<field type="IntegerField" name="order">0</field>
<field type="IntegerField" name="order">2</field>
</object>
<object pk="abstain" model="name.groupballotpositionname">
<field type="CharField" name="name">Abstain</field>
<object pk="review" model="name.groupmilestonestatename">
<field type="CharField" name="name">For review</field>
<field type="TextField" name="desc"></field>
<field type="BooleanField" name="used">True</field>
<field type="IntegerField" name="order">0</field>
<field type="IntegerField" name="order">3</field>
</object>
<object pk="block" model="name.groupballotpositionname">
<field type="CharField" name="name">Block</field>
<object pk="charter" model="name.groupmilestonestatename">
<field type="CharField" name="name">Chartering/rechartering</field>
<field type="TextField" name="desc"></field>
<field type="BooleanField" name="used">True</field>
<field type="IntegerField" name="order">0</field>
</object>
<object pk="norecord" model="name.groupballotpositionname">
<field type="CharField" name="name">No record</field>
<field type="TextField" name="desc"></field>
<field type="BooleanField" name="used">True</field>
<field type="IntegerField" name="order">0</field>
<field type="IntegerField" name="order">4</field>
</object>
<object pk="bof" model="name.groupstatename">
<field type="CharField" name="name">BOF</field>
@ -628,7 +622,7 @@
<object pk="ds" model="name.stdlevelname">
<field type="CharField" name="name">Draft Standard</field>
<field type="TextField" name="desc"></field>
<field type="BooleanField" name="used">True</field>
<field type="BooleanField" name="used">False</field>
<field type="IntegerField" name="order">0</field>
</object>
<object pk="ps" model="name.stdlevelname">
@ -1630,25 +1624,34 @@
<field type="CharField" name="name">Ready for external review</field>
<field type="TextField" name="question">Is this charter ready for external review?</field>
<field type="BooleanField" name="used">True</field>
<field type="IntegerField" name="order">0</field>
<field type="IntegerField" name="order">1</field>
<field to="name.ballotpositionname" name="positions" rel="ManyToManyRel"><object pk="yes"></object><object pk="noobj"></object><object pk="block"></object><object pk="abstain"></object><object pk="norecord"></object></field>
</object>
<object pk="2" model="doc.ballottype">
<field to="name.doctypename" name="doc_type" rel="ManyToOneRel">charter</field>
<field type="SlugField" name="slug">approve</field>
<field type="CharField" name="name">Approve</field>
<field type="TextField" name="question">Do we approve of this charter?</field>
<field type="BooleanField" name="used">True</field>
<field type="IntegerField" name="order">0</field>
<field to="name.ballotpositionname" name="positions" rel="ManyToManyRel"><object pk="yes"></object><object pk="noobj"></object><object pk="block"></object><object pk="abstain"></object><object pk="norecord"></object></field>
</object>
<object pk="3" model="doc.ballottype">
<object pk="4" model="doc.ballottype">
<field to="name.doctypename" name="doc_type" rel="ManyToOneRel">draft</field>
<field type="SlugField" name="slug">approve</field>
<field type="CharField" name="name">Approve</field>
<field type="TextField" name="question"></field>
<field type="BooleanField" name="used">True</field>
<field type="IntegerField" name="order">0</field>
<field type="IntegerField" name="order">1</field>
<field to="name.ballotpositionname" name="positions" rel="ManyToManyRel"><object pk="yes"></object><object pk="noobj"></object><object pk="discuss"></object><object pk="abstain"></object><object pk="recuse"></object><object pk="norecord"></object></field>
</object>
<object pk="2" model="doc.ballottype">
<field to="name.doctypename" name="doc_type" rel="ManyToOneRel">charter</field>
<field type="SlugField" name="slug">r-wo-ext</field>
<field type="CharField" name="name">Ready w/o external review</field>
<field type="TextField" name="question">Is this charter ready for external review? Is this charter ready for approval without external review?</field>
<field type="BooleanField" name="used">True</field>
<field type="IntegerField" name="order">2</field>
<field to="name.ballotpositionname" name="positions" rel="ManyToManyRel"><object pk="yes"></object><object pk="noobj"></object><object pk="block"></object><object pk="abstain"></object><object pk="norecord"></object></field>
</object>
<object pk="3" model="doc.ballottype">
<field to="name.doctypename" name="doc_type" rel="ManyToOneRel">charter</field>
<field type="SlugField" name="slug">approve</field>
<field type="CharField" name="name">Approve</field>
<field type="TextField" name="question">Do we approve of this charter?</field>
<field type="BooleanField" name="used">True</field>
<field type="IntegerField" name="order">3</field>
<field to="name.ballotpositionname" name="positions" rel="ManyToManyRel"><object pk="yes"></object><object pk="noobj"></object><object pk="block"></object><object pk="abstain"></object><object pk="norecord"></object></field>
</object>
</django-objects>

View file

@ -0,0 +1,181 @@
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Deleting model 'GroupBallotPositionName'
db.delete_table('name_groupballotpositionname')
# looks like this is actually included at the moment
# Adding model 'GroupMilestoneStateName'
# db.create_table('name_groupmilestonestatename', (
# ('slug', self.gf('django.db.models.fields.CharField')(max_length=8, primary_key=True)),
# ('name', self.gf('django.db.models.fields.CharField')(max_length=255)),
# ('desc', self.gf('django.db.models.fields.TextField')(blank=True)),
# ('used', self.gf('django.db.models.fields.BooleanField')(default=True)),
# ('order', self.gf('django.db.models.fields.IntegerField')(default=0)),
# ))
# db.send_create_signal('name', ['GroupMilestoneStateName'])
def backwards(self, orm):
# Adding model 'GroupBallotPositionName'
db.create_table('name_groupballotpositionname', (
('used', self.gf('django.db.models.fields.BooleanField')(default=True)),
('name', self.gf('django.db.models.fields.CharField')(max_length=255)),
('slug', self.gf('django.db.models.fields.CharField')(max_length=8, primary_key=True)),
('order', self.gf('django.db.models.fields.IntegerField')(default=0)),
('desc', self.gf('django.db.models.fields.TextField')(blank=True)),
))
db.send_create_signal('name', ['GroupBallotPositionName'])
# Deleting model 'GroupMilestoneStateName'
# db.delete_table('name_groupmilestonestatename')
models = {
'name.ballotpositionname': {
'Meta': {'ordering': "['order']", 'object_name': 'BallotPositionName'},
'blocking': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.constraintname': {
'Meta': {'ordering': "['order']", 'object_name': 'ConstraintName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.docrelationshipname': {
'Meta': {'ordering': "['order']", 'object_name': 'DocRelationshipName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.docremindertypename': {
'Meta': {'ordering': "['order']", 'object_name': 'DocReminderTypeName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.doctagname': {
'Meta': {'ordering': "['order']", 'object_name': 'DocTagName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.doctypename': {
'Meta': {'ordering': "['order']", 'object_name': 'DocTypeName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.groupmilestonestatename': {
'Meta': {'ordering': "['order']", 'object_name': 'GroupMilestoneStateName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.groupstatename': {
'Meta': {'ordering': "['order']", 'object_name': 'GroupStateName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.grouptypename': {
'Meta': {'ordering': "['order']", 'object_name': 'GroupTypeName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.intendedstdlevelname': {
'Meta': {'ordering': "['order']", 'object_name': 'IntendedStdLevelName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.liaisonstatementpurposename': {
'Meta': {'ordering': "['order']", 'object_name': 'LiaisonStatementPurposeName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.meetingtypename': {
'Meta': {'ordering': "['order']", 'object_name': 'MeetingTypeName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.rolename': {
'Meta': {'ordering': "['order']", 'object_name': 'RoleName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.sessionstatusname': {
'Meta': {'ordering': "['order']", 'object_name': 'SessionStatusName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.stdlevelname': {
'Meta': {'ordering': "['order']", 'object_name': 'StdLevelName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.streamname': {
'Meta': {'ordering': "['order']", 'object_name': 'StreamName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.timeslottypename': {
'Meta': {'ordering': "['order']", 'object_name': 'TimeSlotTypeName'},
'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'})
}
}
complete_apps = ['name']

View file

@ -0,0 +1,170 @@
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import DataMigration
from django.db import models
class Migration(DataMigration):
def forwards(self, orm):
# add names
orm.GroupMilestoneStateName.objects.get_or_create(slug="active",
name="Active",
order=1)
orm.GroupMilestoneStateName.objects.get_or_create(slug="deleted",
name="Deleted",
order=2)
orm.GroupMilestoneStateName.objects.get_or_create(slug="review",
name="For review",
order=3)
orm.GroupMilestoneStateName.objects.get_or_create(slug="charter",
name="Chartering/rechartering",
order=4)
def backwards(self, orm):
# remove names
orm.GroupMilestoneStateName.objects.filter(slug__in=("active", "deleted", "review", "charter")).delete()
models = {
'name.ballotpositionname': {
'Meta': {'ordering': "['order']", 'object_name': 'BallotPositionName'},
'blocking': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.constraintname': {
'Meta': {'ordering': "['order']", 'object_name': 'ConstraintName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.docrelationshipname': {
'Meta': {'ordering': "['order']", 'object_name': 'DocRelationshipName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.docremindertypename': {
'Meta': {'ordering': "['order']", 'object_name': 'DocReminderTypeName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.doctagname': {
'Meta': {'ordering': "['order']", 'object_name': 'DocTagName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.doctypename': {
'Meta': {'ordering': "['order']", 'object_name': 'DocTypeName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.groupmilestonestatename': {
'Meta': {'ordering': "['order']", 'object_name': 'GroupMilestoneStateName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.groupstatename': {
'Meta': {'ordering': "['order']", 'object_name': 'GroupStateName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.grouptypename': {
'Meta': {'ordering': "['order']", 'object_name': 'GroupTypeName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.intendedstdlevelname': {
'Meta': {'ordering': "['order']", 'object_name': 'IntendedStdLevelName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.liaisonstatementpurposename': {
'Meta': {'ordering': "['order']", 'object_name': 'LiaisonStatementPurposeName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.meetingtypename': {
'Meta': {'ordering': "['order']", 'object_name': 'MeetingTypeName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.rolename': {
'Meta': {'ordering': "['order']", 'object_name': 'RoleName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.sessionstatusname': {
'Meta': {'ordering': "['order']", 'object_name': 'SessionStatusName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.stdlevelname': {
'Meta': {'ordering': "['order']", 'object_name': 'StdLevelName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.streamname': {
'Meta': {'ordering': "['order']", 'object_name': 'StreamName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.timeslottypename': {
'Meta': {'ordering': "['order']", 'object_name': 'TimeSlotTypeName'},
'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'})
}
}
complete_apps = ['name']

View file

@ -20,6 +20,8 @@ class GroupStateName(NameModel):
"""BOF, Proposed, Active, Dormant, Concluded"""
class GroupTypeName(NameModel):
"""IETF, Area, WG, RG, Team, etc."""
class GroupMilestoneStateName(NameModel):
"""Active, Deleted, For Review, Chartering"""
class RoleName(NameModel):
"""AD, Chair"""
class StreamName(NameModel):
@ -44,8 +46,6 @@ class DocReminderTypeName(NameModel):
class BallotPositionName(NameModel):
""" Yes, No Objection, Abstain, Discuss, Block, Recuse """
blocking = models.BooleanField(default=False)
class GroupBallotPositionName(NameModel):
""" Yes, No, Block, Abstain """
class MeetingTypeName(NameModel):
"""IETF, Interim"""
class SessionStatusName(NameModel):

View file

@ -10,22 +10,30 @@ def json_emails(emails):
return simplejson.dumps([{"id": e.address + "", "name": escape(u"%s <%s>" % (e.person.name, e.address))} for e in emails])
class EmailsField(forms.CharField):
"""Multi-select field using jquery.tokeninput.js. Since the API of
tokeninput" is asymmetric, we have to pass it a JSON
representation on the way out and parse the ids coming back as a
comma-separated list on the way in."""
def __init__(self, *args, **kwargs):
kwargs["max_length"] = 1000
if not "help_text" in kwargs:
kwargs["help_text"] = "Type in name to search for person"
super(EmailsField, self).__init__(*args, **kwargs)
self.widget.attrs["class"] = "emails-field"
self.widget.attrs["class"] = "tokenized-field"
self.widget.attrs["data-ajax-url"] = lazy(urlreverse, str)("ajax_search_emails") # make this lazy to prevent initialization problem
def parse_tokenized_value(self, value):
return Email.objects.filter(address__in=[x.strip() for x in value.split(",") if x.strip()]).select_related("person")
def prepare_value(self, value):
if not value:
return ""
if isinstance(value, str):
return value
if isinstance(value, str) or isinstance(value, unicode):
value = self.parse_tokenized_value(value)
return json_emails(value)
def clean(self, value):
value = super(EmailsField, self).clean(value)
return Email.objects.filter(address__in=[x.strip() for x in value.split(",") if x.strip()]).select_related("person")
return self.parse_tokenized_value(value)

View file

@ -44,7 +44,7 @@
{% if not snapshot and user|has_role:"Area Director,Secretariat" %}
{% if chartering %}
{% if chartering %}
- <a href="{% url charter_startstop_process name=doc.name option='abandon' %}">Abandon effort</a>
{% if request.user|has_role:"Secretariat" %}
@ -118,11 +118,25 @@
{% endif %}
</h3>
{% if doc.rev %}
{% if doc.rev != "" %}
<div class="markup_draft">
{{ content|safe|linebreaksbr|keep_spacing|sanitize_html|safe }}
</div>
{% endif %}
{% if not snapshot and chartering %}
<h3>Proposed Milestones
{% if user|has_role:"Area Director,Secretariat" %}
<a class="edit" href="{% url wg_edit_charter_milestones acronym=doc.group.acronym %}">Edit charter milestones</a>
{% endif %}
</h3>
{% if milestones %}
{% include "wginfo/milestones.html" %}
{% else %}
<p>No milestones for charter found.</p>
{% endif %}
{% endif %}
{% endblock %}

View file

@ -75,7 +75,7 @@ Start chartering new WG
{% block content_end %}
<script type="text/javascript" src="/js/lib/jquery.tokeninput.js"></script>
<script type="text/javascript" src="/js/lib/json2.js"></script>
<script type="text/javascript" src="/js/emails-field.js"></script>
<script type="text/javascript" src="/js/tokenized-field.js"></script>
<script>
jQuery(function () {
if (jQuery('input[name="confirmed"]').length > 0) {

View file

@ -0,0 +1,91 @@
{% extends "base.html" %}
{% block title %}{{ title }}{% endblock %}
{% block morecss %}
tr.milestone td { padding: 0.2em 0; cursor: pointer; vertical-align: top; }
tr.milestone:hover { background-color: #e8f0fa; }
td.due { width: 5em; }
.milestone .needs-accept { font-style: italic; display: inline-block; margin-left: 0.5em; color: #2647a0; }
.edit-milestone { display: none; }
.edit-milestone.delete, .edit-milestone.delete input { color: #aaa !important; }
.edit-milestone table { margin: 0.3em 0; }
.edit-milestone table td { padding: 0.1em; }
.edit-milestone .desc input { width: 50em; }
.edit-milestone .due input { width: 6em; }
.edit-milestone input[type=checkbox] { vertical-align: middle; margin: 0 0.2em 0 0.8em;}
.edit-milestone .resolved label { vertical-align: middle; }
.edit-milestone .delete label { vertical-align: middle; }
.edit-milestone .accept label { vertical-align: middle; }
.edit-milestone .docs td { vertical-align: top; }
ul.errorlist { border-width: 0px; padding: 0px; margin: 0px; display: inline-block; }
ul.errorlist li { color: #a00; margin: 0px; padding: 0px; list-style: none; }
p.help { font-style: italic; }
p.error { color: #a00; font-size: larger; }
tr.milestone.add { font-style: italic; }
{% endblock %}
{% block pagehead %}
<link rel="stylesheet" type="text/css" href="/css/token-input.css"></link>
{% endblock %}
{% block content %}
{% load ietf_filters %}
<h1>{{ title }}</h1>
<p class="help">{% if forms %}Click a milestone to edit it.{% endif %}
{% if needs_review %}
Note that as {{ group.type.name }} Chair you cannot edit descriptions of existing
milestones and milestones you add are subject to review by the Area
Director.
{% endif %}
</p>
{% if can_reset %}
<p>
You can <a href="{% url wg_reset_charter_milestones acronym=group.acronym %}">reset
this list</a> to the currently in-use milestones for the {{ group.acronym }} {{ group.type.name }}.
</p>
{% endif %}
{% if form_errors %}
<p class="error">There were errors, see below.</p>
{% endif %}
<form action="" method="post" id="milestones-form">
<table cellspacing="0" cellpadding="0">
{% for form in forms %}
<tr class="milestone">
<td class="due">{% if form.milestone.resolved %}{{ form.milestone.resolved }}{% else %}{{ form.milestone.due|date:"M Y" }}{% endif %}</td>
<td>
{{ form.milestone.desc }}
{% if form.needs_review %}<span class="needs-accept">awaiting accept</span>{% endif %}
</td>
</tr>
<tr class="edit-milestone"><td colspan="2">{% include "wginfo/milestone_form.html" %}</td></tr>
{% endfor %}
<tr class="milestone add"><td></td><td>Add {% if milestone_set == "chartering" %}charter{% endif%} milestone {% if needs_review %}for AD review{% endif %}</td></tr>
<tr class="edit-milestone template"><td colspan="2">{% with empty_form as form %}{% include "wginfo/milestone_form.html" %}{% endwith %}</td></tr>
</table>
<div class="actions">
<a href="{% if milestone_set == "charter" %}{% url doc_view name=group.charter.canonical_name %}{% else %}{% url wg_charter acronym=group.acronym %}{% endif %}">Back</a>
<input type="submit" value="Save"/>
</div>
</form>
{% endblock %}
{% block content_end %}
<script type="text/javascript" src="/js/lib/jquery.tokeninput.js"></script>
<script type="text/javascript" src="/js/lib/json2.js"></script>
<script type="text/javascript" src="/js/lib/jquery.maskedinput.js"></script>
<script type="text/javascript" src="/js/tokenized-field.js"></script>
<script>
var finishedMilestoneText = "{{ finished_milestone_text|escapejs }}";
</script>
<script type="text/javascript" src="/js/edit-milestones.js"></script>
{% endblock %}

View file

@ -0,0 +1,45 @@
{# assumes group, form, needs_review are in the context #}
<input type="hidden" name="prefix" value="{{ form.prefix|default:"" }}"/>
{{ form.id }}
{{ form.expanded_for_editing }}
<table cellspacing="0" cellpadding="0">
<tr>
<td>{{ form.desc.label_tag }}:</td>
<td>
<span class="desc">
{% if needs_review and form.milestone and form.milestone.state_id != "review" %}
{{ form.milestone.desc }} {{ form.desc.as_hidden }}
{% else %}
{{ form.desc }}
{% endif %}
</span>
<span class="delete">{{ form.delete }} {{ form.delete.label_tag }}</span>
</td>
</tr>
{% if form.desc.errors %}<tr><td></td><td colspan="2">{{ form.desc.errors }}</td></tr>{% endif %}
<tr>
<td>{{ form.due.label_tag }}:</td>
<td><span class="due">{{ form.due }}</span> {{ form.due.errors }}
<span class="resolved">{{ form.resolved_checkbox }} {{ form.resolved_checkbox.label_tag }} {{ form.resolved }}</span>
{{ form.resolved.errors }}
</td>
</tr>
<tr class="docs">
<td>Drafts:</td>
<td><input name="{{ form.docs.html_name }}" class="tokenized-field" data-ajax-url="{% url wg_ajax_search_docs group.acronym %}" data-pre="{{ form.docs.prepopulate }}"/>
{{ form.docs.errors }}
</td>
</tr>
{% if form.needs_review %}
<tr class="needs-review">
<td>Review:</td>
<td>This milestone is not public yet, awaiting AD acceptance.
{% if not needs_review %}
<span class="accept">{{ form.accept }} {{ form.accept.label_tag }}</span>
{% endif %}
</td>
</tr>
{% endif %}
</table>

View file

@ -0,0 +1,12 @@
{# assumes milestones is in context #}
<table>
{% for milestone in milestones %}
<tr>
<td width="80px">
{% if milestone.resolved %}{{ milestone.resolved }}{% else %}{{ milestone.due|date:"M Y" }}{% endif %}
</td>
<td>{{ milestone.desc|escape }}</td>
</tr>
{% endfor %}
</table>

View file

@ -0,0 +1,36 @@
{% extends "base.html" %}
{% block title %}Reset Charter Milestones for {{ group.acronym }} {{ group.type.name }}{% endblock %}
{% block morecss %}
#reset-form .date { display: inline-block; min-width: 5em; }
{% endblock %}
{% block content %}
{% load ietf_filters %}
<h1>Reset Charter Milestones for {{ group.acronym }} {{ group.type.name }}</h1>
<p>Select which of the current {{ group.type.name }} milestones you would like to copy to the charter.
{% if charter_milestones %}This will discard {{ charter_milestones|length }} existing charter milestone{{ charter_milestones|pluralize }}{% endif %}
</p>
<form action="" method="post" id="reset-form">
{% for milestone in current_milestones %}
<div>
<label>
<input type="checkbox" name="milestone" value="{{ milestone.id }}" {% if not milestone.resolved %}checked="checked"{% endif %} />
<span class="date">{% if milestone.resolved %}{{ milestone.resolved }}{% else %}{{ milestone.due|date:"M Y" }}{% endif %}</span>
{{ milestone.desc }}
</label>
</div>
{% endfor %}
<div class="actions">
<a href="{% url wg_edit_charter_milestones acronym=group.acronym %}">Back</a>
<input type="submit" value="Reset charter milestones"/>
</div>
</form>
{% endblock %}

View file

@ -34,7 +34,7 @@ Description of Working Group:
{{ wg.charter_text|indent|safe }}
Goals and Milestones:
{% for milestone in wg.milestones %} {% if milestone.done %}Done {% else %}{{ milestone.expected_due_date|date:"M Y" }}{% endif %} - {{ milestone.desc|safe }}
{% for milestone in wg.milestones %} {% if milestone.resolved %}{{ milestone.resolved }} {% else %}{{ milestone.due|date:"M Y" }}{% endif %} - {{ milestone.desc|safe }}
{% endfor %}
Internet-Drafts:
{% for alias in wg.drafts %} - {{alias.document.title|safe}} [{{alias.name}}-{{alias.document.rev}}] ({{ alias.document.pages }} pages)

View file

@ -35,87 +35,129 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{% load ietf_filters %}
{% block wg_titledetail %}Charter{% endblock %}
{% block wg_content %}
{% block morecss %}
{{ block.super }}
h2 a.edit { font-weight: normal; font-size: 13px; display: inline-block; margin-left: 0.5em; }
{% endblock %}
{% block wg_content %}
<div class="ietf-box ietf-wg-details">
{% if concluded %}
<span class="ietf-concluded-warning">Note: The data for concluded WGs
is occasionally incorrect.</span>
{% endif %}
<table>
<tr>
<td colspan="2">
<b>Personnel</b>
</td>
</tr>
<tr><th colspan="2">Group</th></tr>
<tr valign="top">
<td style="width:14ex;">Chair{{ wg.chairs.count|pluralize:",s" }}:</td>
<td>
{% for chair in wg.chairs %}
<a href="mailto:{{ chair.person.email.1 }}">{{ chair.person|escape }} &lt;{{ chair.person.email.1 }}&gt;</a><br/>
{% endfor %}
</td></tr>
<tr><td>Area Director:</td>
<td>
{% ifequal wg.area_director.person.email.1 "noreply@ietf.org" %}?{%else%}
<a href="mailto:{{ wg.area_director.person.email.1 }}">{{ wg.area_director.person }} &lt;{{wg.area_director.person.email.1 }}&gt;</a>{% endifequal %}
</td>
</tr>
{% if wg.wgtechadvisor_set.count %}
<tr>
<td>Tech Advisor{{ wg.wgtechadvisor_set.count|pluralize:",s" }}:</td>
<td>
{% for techadvisor in wg.wgtechadvisor_set.all %}
<a href="mailto:{{ techadvisor.person.email.1 }}">{{ techadvisor.person }} &lt;{{ techadvisor.person.email.1 }}&gt;</a><br/>
{% endfor %}
</td></tr>
{% endif %}
{% if wg.wgeditor_set.count %}
<td>Editor{{ wg.wgeditor_set.count|pluralize:",s" }}:</td>
<td>
{% for editor in wg.wgeditor_set.all %}
<a href="mailto:{{ editor.person.email.1 }}">{{ editor.person }} &lt;{{ editor.person.email.1 }}&gt;</a><br/>
{% endfor %}
</td></tr>
{% endif %}
{% if wg.secretaries %}
<tr><td>Secretar{{ wg.secretaries.count|pluralize:"y,ies" }}:</td>
<td>
{% for secretary in wg.secretaries %}
<a href="mailto:{{ secretary.person.email.1 }}">{{ secretary.person }} &lt;{{ secretary.person.email.1 }}&gt;</a><br/>
{% endfor %}
</td></tr>
{% endif %}
<tr valign="top">
<td style="width:14ex;">Name:</td>
<td>{{ wg.name }}</td>
</tr>
<tr>
<td colspan="2">
<br/><b>Mailing List</b>
</td>
</tr>
<tr><td>Acronym:</td><td>{{ wg.acronym }}</td></tr>
<tr><td>Address:</td><td>{{ wg.email_address|urlize }}</td></tr>
<tr><td>To Subscribe:</td><td>{{ wg.email_subscribe|urlize }}</td></tr>
<tr><td>Archive:</td><td>{{ wg.clean_email_archive|urlize }}</td></tr>
{% if wg.parent %}
<tr><td>Area:</td><td>{{ wg.parent.name }} ({{ wg.parent.acronym }})</td></tr>
{% endif %}
{% if not concluded %}
<tr>
<td colspan="2">
<br/><b>Jabber Chat</b>
</td>
</tr>
<tr>
<td>State:</td>
<td>{{ wg.state.name }}
{% if requested_close %}
(but in the process of being closed)
{% endif %}
</td>
</tr>
<tr><td>Room Address:</td><td><a href="xmpp:{{wg}}@jabber.ietf.org">xmpp:{{wg}}@jabber.ietf.org</a></td></tr>
<tr><td>Logs:</td><td><a href="http://jabber.ietf.org/logs/{{wg}}/">http://jabber.ietf.org/logs/{{wg}}/</a></td></tr>
{% endif %}
<tr>
<td>Charter:</td>
<td>
{% if wg.charter %}
<a href="{% url doc_view name=wg.charter.name %}">{{ wg.charter.name }}-{{ wg.charter.rev }}</a> ({{ wg.charter.get_state.name }})
{% else %}
none
{% if user|has_role:"Area Director,Secretariat" %}
- <a href="{% url wgcharter.views.submit acronym=wg.acronym %}">Submit Charter</a>
{% endif %}
{% endif %}
</td>
</tr>
<tr><th colspan="2">Personnel</th></tr>
<tr valign="top">
<td>Chair{{ wg.chairs|pluralize }}:</td>
<td>
{% for chair in wg.chairs %}
<a href="mailto:{{ chair.address }}">{{ chair.person.plain_name }} &lt;{{ chair.address }}&gt;</a><br/>
{% endfor %}
</td>
</tr>
<tr><td>Area Director:</td>
<td>
{% if not wg.ad %}?{% else %}
<a href="mailto:{{ wg.areadirector.address }}">{{ wg.ad.plain_name }} &lt;{{ wg.areadirector.address }}&gt;</a>{% endif %}
</td>
</tr>
{% if wg.techadvisors %}
<tr>
<td>Tech Advisor{{ wg.techadvisors|pluralize }}:</td>
<td>
{% for techadvisor in wg.techadvisors %}
<a href="mailto:{{ techadvisor.address }}">{{ techadvisor.person.plain_name }} &lt;{{ techadvisor.address }}&gt;</a><br/>
{% endfor %}
</td>
</tr>
{% endif %}
{% if wg.editors %}
<td>Editor{{ wg.editors|pluralize }}:</td>
<td>
{% for editor in wg.editors %}
<a href="mailto:{{ editor.address }}">{{ editor.person.plain_name }} &lt;{{ editor.address }}&gt;</a><br/>
{% endfor %}
</td></tr>
{% endif %}
{% if wg.secretaries %}
<tr>
<td>Secretar{{ wg.secretaries|pluralize:"y,ies" }}:</td>
<td>
{% for secretary in wg.secretaries %}
<a href="mailto:{{ secretary.address }}">{{ secretary.person.plain_name }} &lt;{{ secretary.address }}&gt;</a><br/>
{% endfor %}
</td>
</tr>
{% endif %}
<tr><th colspan="2">Mailing List</th></tr>
<tr><td>Address:</td><td>{{ wg.email_address|urlize }}</td></tr>
<tr><td>To Subscribe:</td><td>{{ wg.email_subscribe|urlize }}</td></tr>
<tr><td>Archive:</td><td>{{ wg.clean_email_archive|urlize }}</td></tr>
{% if not concluded %}
<tr><th colspan="2">Jabber Chat</th></tr>
<tr><td>Room Address:</td><td><a href="xmpp:{{ wg.acronym }}@jabber.ietf.org">xmpp:{{ wg.acronym }}@jabber.ietf.org</a></td></tr>
<tr><td>Logs:</td><td><a href="http://jabber.ietf.org/logs/{{ wg.acronym }}/">http://jabber.ietf.org/logs/{{ wg.acronym }}/</a></td></tr>
{% endif %}
</table>
{% if user|has_role:"Area Director,Secretariat" %}
<div style="margin: 2px; margin-top: 2em;">
{% for name, url in actions %}
<a href="{{ url }}">{{ name }}</a>
{% if not forloop.last %}|{% endif %}
{% endfor %}
</div>
{% endif %}
</div>
{% if wg.additional_urls %}
<p>In addition to the charter maintained by the IETF Secretariat, there is additional information about this working group on the Web at:
{% for url in wg.additional_urls %}
<a href="{{ url.url }}">{{ url.description}}</a>{% if not forloop.last %}, {% endif %}
<a href="{{ url.url }}">{{ url.name }}</a>{% if not forloop.last %}, {% endif %}
{% endfor %}
</p>
{% endif %}
@ -123,31 +165,16 @@ is occasionally incorrect.</span>
<h2>Description of Working Group</h2>
<p>{{ wg.charter_text|escape|format_charter|safe }}</p>
<h2>Goals and Milestones</h2>
<table>
{% for milestone in wg.milestones %}
<tr>
<td width="80px">
{% ifequal milestone.done 'Done' %} Done
{% else %}
{%ifequal milestone.expected_due_date.month 1 %}Jan{% endifequal %}
{%ifequal milestone.expected_due_date.month 2 %}Feb{% endifequal %}
{%ifequal milestone.expected_due_date.month 3 %}Mar{% endifequal %}
{%ifequal milestone.expected_due_date.month 4 %}Apr{% endifequal %}
{%ifequal milestone.expected_due_date.month 5 %}May{% endifequal %}
{%ifequal milestone.expected_due_date.month 6 %}Jun{% endifequal %}
{%ifequal milestone.expected_due_date.month 7 %}Jul{% endifequal %}
{%ifequal milestone.expected_due_date.month 8 %}Aug{% endifequal %}
{%ifequal milestone.expected_due_date.month 9 %}Sep{% endifequal %}
{%ifequal milestone.expected_due_date.month 10 %}Oct{% endifequal %}
{%ifequal milestone.expected_due_date.month 11 %}Nov{% endifequal %}
{%ifequal milestone.expected_due_date.month 12 %}Dec{% endifequal %}
{{ milestone.expected_due_date.year }}
{% endifequal %}
</td>
<td>{{ milestone.description|escape }}
</td></tr>
{% endfor %}
</table>
{% endblock wg_content %}
<h2>Goals and Milestones
{% if user|has_role:"Area Director,Secretariat" or is_chair %}
<a class="edit" href="{% url wg_edit_milestones acronym=wg.acronym %}">Add or edit milestones</a>
{% endif %}
</h2>
{% with wg.milestones as milestones %}{% include "wginfo/milestones.html" %}{% endwith %}
{% if milestones_in_review %}
<p>{{ milestones_in_review|length }} new milestone{{ milestones_in_review|pluralize }}
under review.</p>
{% endif %}
{% endblock wg_content %}

View file

@ -1,174 +0,0 @@
{% extends "wginfo/wg_base.html" %}
{% comment %}
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
All rights reserved. Contact: Pasi Eronen <pasi.eronen@nokia.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of the Nokia Corporation and/or its
subsidiary(-ies) nor the names of its contributors may be used
to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{% endcomment %}
{% load ietf_filters %}
{% block wg_titledetail %}Charter{% endblock %}
{% block wg_content %}
<div class="ietf-box ietf-wg-details">
{% if concluded %}
<span class="ietf-concluded-warning">Note: The data for concluded WGs
is occasionally incorrect.</span>
{% endif %}
<table>
<tr><th colspan="2">Group</th></tr>
<tr valign="top">
<td style="width:14ex;">Name:</td>
<td>{{ wg.name }}</td>
</tr>
<tr><td>Acronym:</td><td>{{ wg.acronym }}</td></tr>
{% if wg.parent %}
<tr><td>Area:</td><td>{{ wg.parent.name }} ({{ wg.parent.acronym }})</td></tr>
{% endif %}
<tr>
<td>State:</td>
<td>{{ wg.state.name }}
{% if requested_close %}
(but in the process of being closed)
{% endif %}
</td>
</tr>
<tr>
<td>Charter:</td>
<td>
{% if wg.charter %}
<a href="{% url doc_view name=wg.charter.name %}">{{ wg.charter.name }}-{{ wg.charter.rev }}</a> ({{ wg.charter.get_state.name }})
{% else %}
none
{% if user|has_role:"Area Director,Secretariat" %}
- <a href="{% url wgcharter.views.submit acronym=wg.acronym %}">Submit Charter</a>
{% endif %}
{% endif %}
</td>
</tr>
<tr><th colspan="2">Personnel</th></tr>
<tr valign="top">
<td>Chair{{ wg.chairs|pluralize }}:</td>
<td>
{% for chair in wg.chairs %}
<a href="mailto:{{ chair.address }}">{{ chair.person.plain_name }} &lt;{{ chair.address }}&gt;</a><br/>
{% endfor %}
</td>
</tr>
<tr><td>Area Director:</td>
<td>
{% if not wg.ad %}?{% else %}
<a href="mailto:{{ wg.areadirector.address }}">{{ wg.ad.plain_name }} &lt;{{ wg.areadirector.address }}&gt;</a>{% endif %}
</td>
</tr>
{% if wg.techadvisors %}
<tr>
<td>Tech Advisor{{ wg.techadvisors|pluralize }}:</td>
<td>
{% for techadvisor in wg.techadvisors %}
<a href="mailto:{{ techadvisor.address }}">{{ techadvisor.person.plain_name }} &lt;{{ techadvisor.address }}&gt;</a><br/>
{% endfor %}
</td>
</tr>
{% endif %}
{% if wg.editors %}
<td>Editor{{ wg.editors|pluralize }}:</td>
<td>
{% for editor in wg.editors %}
<a href="mailto:{{ editor.address }}">{{ editor.person.plain_name }} &lt;{{ editor.address }}&gt;</a><br/>
{% endfor %}
</td></tr>
{% endif %}
{% if wg.secretaries %}
<tr>
<td>Secretar{{ wg.secretaries|pluralize:"y,ies" }}:</td>
<td>
{% for secretary in wg.secretaries %}
<a href="mailto:{{ secretary.address }}">{{ secretary.person.plain_name }} &lt;{{ secretary.address }}&gt;</a><br/>
{% endfor %}
</td>
</tr>
{% endif %}
<tr><th colspan="2">Mailing List</th></tr>
<tr><td>Address:</td><td>{{ wg.email_address|urlize }}</td></tr>
<tr><td>To Subscribe:</td><td>{{ wg.email_subscribe|urlize }}</td></tr>
<tr><td>Archive:</td><td>{{ wg.clean_email_archive|urlize }}</td></tr>
{% if not concluded %}
<tr><th colspan="2">Jabber Chat</th></tr>
<tr><td>Room Address:</td><td><a href="xmpp:{{ wg.acronym }}@jabber.ietf.org">xmpp:{{ wg.acronym }}@jabber.ietf.org</a></td></tr>
<tr><td>Logs:</td><td><a href="http://jabber.ietf.org/logs/{{ wg.acronym }}/">http://jabber.ietf.org/logs/{{ wg.acronym }}/</a></td></tr>
{% endif %}
</table>
{% if user|has_role:"Area Director,Secretariat" %}
<div style="margin: 2px; margin-top: 2em;">
{% for name, url in actions %}
<a href="{{ url }}">{{ name }}</a>
{% if not forloop.last %}|{% endif %}
{% endfor %}
</div>
{% endif %}
</div>
{% if wg.additional_urls %}
<p>In addition to the charter maintained by the IETF Secretariat, there is additional information about this working group on the Web at:
{% for url in wg.additional_urls %}
<a href="{{ url.url }}">{{ url.name }}</a>{% if not forloop.last %}, {% endif %}
{% endfor %}
</p>
{% endif %}
<h2>Description of Working Group</h2>
<p>{{ wg.charter_text|escape|format_charter|safe }}</p>
<h2>Goals and Milestones</h2>
<table>
{% for milestone in wg.milestones %}
<tr>
<td width="80px">
{% if milestone.done %}Done{% else %}{{ milestone.expected_due_date|date:"M Y" }}{% endif %}
</td>
<td>{{ milestone.desc|escape }}
</td></tr>
{% endfor %}
</table>
{% endblock wg_content %}

View file

@ -8,7 +8,7 @@ def find_history_active_at(obj, time):
related_name="history_set" for the foreign key connecting to the
live model, both models must have a "time" DateTimeField and a
history object must be saved with a copy of the old values and
time when the time field changes.
old time when the time field changes.
"""
if obj.time <= time:
return None
@ -20,3 +20,40 @@ def find_history_active_at(obj, time):
return h
return None
def get_history_object_for(obj):
"""Construct history object for obj, i.e. instantiate history
object, copy relevant attributes and set a link to obj, but done
save. Any customizations can be done by the caller afterwards.
Many-to-many fields are not copied.
The history model must use related_name="history_set" for the
foreign key connecting to the live model for this function to be
able to discover it."""
history_model = obj.history_set.model
h = history_model()
# copy attributes shared between history and obj
history_field_names = set(f.name for f in history_model._meta.fields)
for field in obj._meta.fields:
if field is not obj._meta.pk and field.name in history_field_names:
setattr(h, field.name, getattr(obj, field.name))
# try setting foreign key to obj
key_name = obj._meta.object_name.lower()
if key_name in history_field_names:
setattr(h, key_name, obj)
# we can't copy many-to-many fields as h isn't saved yet, leave
# that to caller
return h
def copy_many_to_many_for_history(history_obj, obj):
"""Copy basic many-to-many fields from obj to history_obj."""
# copy many to many
for field in obj._meta.many_to_many:
if field.rel.through and field.rel.through._meta.auto_created:
setattr(history_obj, field.name, getattr(obj, field.name).all())

341
ietf/wginfo/milestones.py Normal file
View file

@ -0,0 +1,341 @@
# WG milestone editing views
import re, os, string, datetime, shutil
from django.shortcuts import render_to_response, get_object_or_404, redirect
from django.core.urlresolvers import reverse
from django.template import RequestContext
from django import forms
from django.http import HttpResponse, HttpResponseForbidden, HttpResponseBadRequest
from django.utils import simplejson
from django.utils.html import mark_safe, escape
from django.utils.functional import lazy
from django.core.urlresolvers import reverse as urlreverse
from ietf.ietfauth.decorators import role_required, has_role
from ietf.doc.models import Document, DocEvent
from ietf.doc.utils import get_chartering_type
from ietf.group.models import *
from ietf.group.utils import save_group_in_history, save_milestone_in_history
def json_doc_names(docs):
return simplejson.dumps([{"id": doc.pk, "name": doc.name } for doc in docs])
def parse_doc_names(s):
return Document.objects.filter(pk__in=[x.strip() for x in s.split(",") if x.strip()], type="draft")
class MilestoneForm(forms.Form):
id = forms.IntegerField(required=True, widget=forms.HiddenInput)
desc = forms.CharField(max_length=500, label="Milestone", required=True)
due = forms.DateField(required=True, label="Due date")
resolved_checkbox = forms.BooleanField(required=False, label="Resolved")
resolved = forms.CharField(max_length=50, required=False)
delete = forms.BooleanField(required=False, initial=False)
docs = forms.CharField(max_length=10000, required=False)
accept = forms.BooleanField(required=False, initial=False)
expanded_for_editing = forms.BooleanField(required=False, initial=False, widget=forms.HiddenInput)
def __init__(self, *args, **kwargs):
m = self.milestone = kwargs.pop("instance", None)
self.needs_review = kwargs.pop("needs_review", False)
if m:
if not "initial" in kwargs:
kwargs["initial"] = {}
kwargs["initial"].update(dict(id=m.pk,
desc=m.desc,
due=m.due,
resolved_checkbox=bool(m.resolved),
resolved=m.resolved,
docs=",".join(m.docs.values_list("pk", flat=True)),
))
kwargs["prefix"] = "m%s" % m.pk
self.needs_review = m.state_id == "review"
super(MilestoneForm, self).__init__(*args, **kwargs)
pre = ""
if not self.is_bound:
pre = self.initial.get("docs", "")
else:
pre = self["docs"].data or ""
self.fields["docs"].prepopulate = json_doc_names(parse_doc_names(pre))
def clean_docs(self):
s = self.cleaned_data["docs"]
return Document.objects.filter(pk__in=[x.strip() for x in s.split(",") if x.strip()], type="draft")
def clean_resolved(self):
r = self.cleaned_data["resolved"].strip()
if self.cleaned_data["resolved_checkbox"]:
if not r:
raise forms.ValidationError('Please provide explanation (like "Done") for why the milestone is no longer due.')
else:
r = ""
return r
@role_required('WG Chair', 'Area Director', 'Secretariat')
def edit_milestones(request, acronym, milestone_set="current"):
# milestones_set + needs_review: we have several paths into this view
# AD/Secr. -> all actions on current + add new
# group chair -> limited actions on current + add new for review
# (re)charter -> all actions on existing in state charter + add new in state charter
#
# For charters we store the history on the charter document to not confuse people.
login = request.user.get_profile()
group = get_object_or_404(Group, acronym=acronym)
needs_review = False
if not has_role(request.user, ("Area Director", "Secretariat")):
if group.role_set.filter(name="chair", person=login):
if milestone_set == "current":
needs_review = True
else:
return HttpResponseForbidden("You are not chair of this group.")
if milestone_set == "current":
title = "Edit milestones for %s %s" % (group.acronym, group.type.name)
milestones = group.groupmilestone_set.filter(state__in=("active", "review"))
elif milestone_set == "charter":
title = "Edit charter milestones for %s %s" % (group.acronym, group.type.name)
milestones = group.groupmilestone_set.filter(state="charter")
forms = []
milestones_dict = dict((str(m.id), m) for m in milestones)
def add_event(m, desc):
if milestone_set == "charter":
DocEvent.objects.create(doc=group.charter, type="changed_charter_milestone",
by=login, desc=desc)
else:
MilestoneGroupEvent.objects.create(group=group, type="changed_milestone",
by=login, desc=desc, milestone=m)
finished_milestone_text = "Done"
form_errors = False
if request.method == 'POST':
for prefix in request.POST.getlist("prefix"):
if not prefix: # empty form
continue
# new milestones have non-existing ids so instance end up as None
instance = milestones_dict.get(request.POST.get(prefix + "-id", ""), None)
f = MilestoneForm(request.POST, prefix=prefix, instance=instance,
needs_review=needs_review)
forms.append(f)
form_errors = form_errors or not f.is_valid()
if not form_errors:
for f in forms:
c = f.cleaned_data
if f.milestone:
m = f.milestone
named_milestone = 'milestone "%s"' % m.desc
if milestone_set == "charter":
named_milestone = "charter " + named_milestone
if c["delete"]:
save_milestone_in_history(m)
m.time = datetime.datetime.now()
m.state_id = "deleted"
m.save()
add_event(m, 'Deleted %s' % named_milestone)
continue
# compute changes
history = None
changes = ['Changed %s' % named_milestone]
if m.state_id == "review" and not needs_review and c["accept"]:
if not history:
history = save_milestone_in_history(m)
m.state_id = "active"
changes.append("changed state from review to active")
if c["desc"] != m.desc and not needs_review:
if not history:
history = save_milestone_in_history(m)
m.desc = c["desc"]
changes.append('changed description to "%s"' % m.desc)
if c["due"] != m.due:
if not history:
history = save_milestone_in_history(m)
m.due = c["due"]
changes.append('changed due date to %s' % m.due.strftime("%Y-%m-%d"))
resolved = c["resolved"]
if resolved != m.resolved:
if resolved and not m.resolved:
changes.append('resolved as "%s"' % resolved)
elif not resolved and m.resolved:
changes.append("reverted to not being resolved")
elif resolved and m.resolved:
changes.append('changed resolution to "%s"' % resolved)
if not history:
history = save_milestone_in_history(m)
m.resolved = resolved
new_docs = set(c["docs"])
old_docs = set(m.docs.all())
if new_docs != old_docs:
added = new_docs - old_docs
if added:
changes.append('added %s to milestone' % ", ".join(d.name for d in added))
removed = old_docs - new_docs
if removed:
changes.append('removed %s from milestone' % ", ".join(d.name for d in removed))
if not history:
history = save_milestone_in_history(m)
m.docs = new_docs
if len(changes) > 1:
add_event(m, ", ".join(changes))
m.save()
else: # new milestone
m = GroupMilestone()
m.group = group
if milestone_set == "current":
if needs_review:
m.state = GroupMilestoneStateName.objects.get(slug="review")
else:
m.state = GroupMilestoneStateName.objects.get(slug="active")
elif milestone_set == "charter":
m.state = GroupMilestoneStateName.objects.get(slug="charter")
m.desc = c["desc"]
m.due = c["due"]
m.resolved = c["resolved"]
m.save()
m.docs = c["docs"]
named_milestone = 'milestone "%s"' % m.desc
if milestone_set == "charter":
named_milestone = "charter " + named_milestone
if m.state_id in ("active", "charter"):
add_event(m, 'Added %s, due %s' % (named_milestone, m.due.strftime("%Y-%m-%d")))
elif m.state_id == "review":
add_event(m, 'Added %s for review, due %s' % (named_milestone, m.due.strftime("%Y-%m-%d")))
if milestone_set == "charter":
return redirect('doc_view', name=group.charter.canonical_name())
else:
return redirect('wg_charter', acronym=group.acronym)
else:
for m in milestones:
forms.append(MilestoneForm(instance=m, needs_review=needs_review))
can_reset = milestone_set == "charter" and get_chartering_type(group.charter) == "rechartering"
empty_form = MilestoneForm(needs_review=needs_review)
return render_to_response('wginfo/edit_milestones.html',
dict(group=group,
title=title,
forms=forms,
form_errors=form_errors,
empty_form=empty_form,
milestone_set=milestone_set,
finished_milestone_text=finished_milestone_text,
needs_review=needs_review,
can_reset=can_reset),
context_instance=RequestContext(request))
@role_required('WG Chair', 'Area Director', 'Secretariat')
def reset_charter_milestones(request, acronym):
"""Reset charter milestones to the currently in-use milestones."""
login = request.user.get_profile()
group = get_object_or_404(Group, acronym=acronym)
if (not has_role(request.user, ("Area Director", "Secretariat")) and
not group.role_set.filter(name="chair", person=login)):
return HttpResponseForbidden("You are not chair of this group.")
current_milestones = group.groupmilestone_set.filter(state="active")
charter_milestones = group.groupmilestone_set.filter(state="charter")
if request.method == 'POST':
try:
milestone_ids = [int(v) for v in request.POST.getlist("milestone")]
except ValueError as e:
return HttpResponseBadRequest("errror in list of ids - %s" % e)
# delete existing
for m in charter_milestones:
save_milestone_in_history(m)
m.time = datetime.datetime.now()
m.state_id = "deleted"
m.save()
DocEvent.objects.create(type="changed_charter_milestone",
doc=group.charter,
desc='Deleted milestone "%s"' % m.desc,
by=login,
)
# add current
for m in current_milestones.filter(id__in=milestone_ids):
m = GroupMilestone.objects.create(group=m.group,
state_id="charter",
desc=m.desc,
due=m.due,
resolved=m.resolved,
time=datetime.datetime.now(),
)
m.docs = m.docs.all()
DocEvent.objects.create(type="changed_charter_milestone",
doc=group.charter,
desc='Added milestone "%s", due %s, from current group milestones' % (m.desc, m.due.strftime("%Y-%m-%d")),
by=login,
)
return redirect('wg_edit_charter_milestones', acronym=group.acronym)
return render_to_response('wginfo/reset_charter_milestones.html',
dict(group=group,
charter_milestones=charter_milestones,
current_milestones=current_milestones,
),
context_instance=RequestContext(request))
def ajax_search_docs(request, acronym):
docs = Document.objects.filter(name__icontains=request.GET.get('q',''), group__acronym=acronym, type="draft").order_by('name').distinct()[:20]
return HttpResponse(json_doc_names(docs), mimetype='application/json')

View file

@ -249,3 +249,252 @@ class WgEditTestCase(django.test.TestCase):
# the WG remains active until the Secretariat takes action
group = Group.objects.get(acronym=group.acronym)
self.assertEquals(group.state_id, "active")
class MilestoneTestCase(django.test.TestCase):
fixtures = ["names"]
def create_test_milestones(self):
draft = make_test_data()
group = Group.objects.get(acronym="mars")
m1 = GroupMilestone.objects.create(group=group,
desc="Test 1",
due=datetime.date.today(),
resolved="",
state_id="active")
m1.docs = [draft]
m2 = GroupMilestone.objects.create(group=group,
desc="Test 2",
due=datetime.date.today(),
resolved="",
state_id="charter")
m2.docs = [draft]
return (m1, m2, group)
def test_milestone_sets(self):
m1, m2, group = self.create_test_milestones()
url = urlreverse('wg_edit_milestones', kwargs=dict(acronym=group.acronym))
login_testing_unauthorized(self, "secretary", url)
r = self.client.get(url)
self.assertEquals(r.status_code, 200)
self.assertTrue(m1.desc in r.content)
self.assertTrue(m2.desc not in r.content)
url = urlreverse('wg_edit_charter_milestones', kwargs=dict(acronym=group.acronym))
r = self.client.get(url)
self.assertEquals(r.status_code, 200)
self.assertTrue(m1.desc not in r.content)
self.assertTrue(m2.desc in r.content)
def test_add_milestone(self):
m1, m2, group = self.create_test_milestones()
url = urlreverse('wg_edit_milestones', kwargs=dict(acronym=group.acronym))
login_testing_unauthorized(self, "secretary", url)
# normal get
r = self.client.get(url)
self.assertEquals(r.status_code, 200)
milestones_before = GroupMilestone.objects.count()
events_before = group.groupevent_set.count()
docs = Document.objects.filter(type="draft").values_list("name", flat=True)
due = datetime.date.today() + datetime.timedelta(days=365)
# faulty post
r = self.client.post(url, { 'prefix': "m-1",
'm-1-id': -1,
'm-1-desc': "", # no description
'm-1-due': due.strftime("%Y-%m-%d"),
'm-1-resolved': "",
'm-1-docs': ",".join(docs),
})
self.assertEquals(r.status_code, 200)
q = PyQuery(r.content)
self.assertTrue(len(q('form ul.errorlist')) > 0)
self.assertEquals(GroupMilestone.objects.count(), milestones_before)
# add
r = self.client.post(url, { 'prefix': "m-1",
'm-1-id': -1,
'm-1-desc': "Test 3",
'm-1-due': due.strftime("%Y-%m-%d"),
'm-1-resolved': "",
'm-1-docs': ",".join(docs),
})
self.assertEquals(r.status_code, 302)
self.assertEquals(GroupMilestone.objects.count(), milestones_before + 1)
self.assertEquals(group.groupevent_set.count(), events_before + 1)
m = GroupMilestone.objects.get(desc="Test 3")
self.assertEquals(m.state_id, "active")
self.assertEquals(m.due, due)
self.assertEquals(m.resolved, "")
self.assertEquals(set(m.docs.values_list("name", flat=True)), set(docs))
self.assertTrue("Added milestone" in m.milestonegroupevent_set.all()[0].desc)
def test_add_milestone_as_chair(self):
m1, m2, group = self.create_test_milestones()
url = urlreverse('wg_edit_milestones', kwargs=dict(acronym=group.acronym))
login_testing_unauthorized(self, "marschairman", url)
# normal get
r = self.client.get(url)
self.assertEquals(r.status_code, 200)
milestones_before = GroupMilestone.objects.count()
events_before = group.groupevent_set.count()
due = datetime.date.today() + datetime.timedelta(days=365)
# add
r = self.client.post(url, { 'prefix': "m-1",
'm-1-id': -1,
'm-1-desc': "Test 3",
'm-1-due': due.strftime("%Y-%m-%d"),
'm-1-resolved': "",
'm-1-docs': "",
})
self.assertEquals(r.status_code, 302)
self.assertEquals(GroupMilestone.objects.count(), milestones_before + 1)
m = GroupMilestone.objects.get(desc="Test 3")
self.assertEquals(m.state_id, "review")
self.assertEquals(group.groupevent_set.count(), events_before + 1)
self.assertTrue("for review" in m.milestonegroupevent_set.all()[0].desc)
def test_accept_milestone(self):
m1, m2, group = self.create_test_milestones()
m1.state_id = "review"
m1.save()
url = urlreverse('wg_edit_milestones', kwargs=dict(acronym=group.acronym))
login_testing_unauthorized(self, "ad", url)
# normal get
r = self.client.get(url)
self.assertEquals(r.status_code, 200)
events_before = group.groupevent_set.count()
due = datetime.date.today() + datetime.timedelta(days=365)
# add
r = self.client.post(url, { 'prefix': "m1",
'm1-id': m1.id,
'm1-desc': m1.desc,
'm1-due': m1.due.strftime("%Y-%m-%d"),
'm1-resolved': m1.resolved,
'm1-docs': ",".join(m1.docs.values_list("name", flat=True)),
'm1-accept': "checked",
})
self.assertEquals(r.status_code, 302)
m = GroupMilestone.objects.get(pk=m1.pk)
self.assertEquals(m.state_id, "active")
self.assertEquals(group.groupevent_set.count(), events_before + 1)
self.assertTrue("from review to active" in m.milestonegroupevent_set.all()[0].desc)
def test_delete_milestone(self):
m1, m2, group = self.create_test_milestones()
url = urlreverse('wg_edit_milestones', kwargs=dict(acronym=group.acronym))
login_testing_unauthorized(self, "secretary", url)
milestones_before = GroupMilestone.objects.count()
events_before = group.groupevent_set.count()
# delete
r = self.client.post(url, { 'prefix': "m1",
'm1-id': m1.id,
'm1-desc': m1.desc,
'm1-due': m1.due.strftime("%Y-%m-%d"),
'm1-resolved': "",
'm1-docs': ",".join(m1.docs.values_list("name", flat=True)),
'm1-delete': "checked",
})
self.assertEquals(r.status_code, 302)
self.assertEquals(GroupMilestone.objects.count(), milestones_before)
self.assertEquals(group.groupevent_set.count(), events_before + 1)
m = GroupMilestone.objects.get(pk=m1.pk)
self.assertEquals(m.state_id, "deleted")
self.assertTrue("Deleted milestone" in m.milestonegroupevent_set.all()[0].desc)
def test_edit_milestone(self):
m1, m2, group = self.create_test_milestones()
url = urlreverse('wg_edit_milestones', kwargs=dict(acronym=group.acronym))
login_testing_unauthorized(self, "secretary", url)
milestones_before = GroupMilestone.objects.count()
events_before = group.groupevent_set.count()
docs = Document.objects.filter(type="draft").values_list("name", flat=True)
due = datetime.date.today() + datetime.timedelta(days=365)
# faulty post
r = self.client.post(url, { 'prefix': "m1",
'm1-id': m1.id,
'm1-desc': "", # no description
'm1-due': due.strftime("%Y-%m-%d"),
'm1-resolved': "",
'm1-docs': ",".join(docs),
})
self.assertEquals(r.status_code, 200)
q = PyQuery(r.content)
self.assertTrue(len(q('form ul.errorlist')) > 0)
m = GroupMilestone.objects.get(pk=m1.pk)
self.assertEquals(GroupMilestone.objects.count(), milestones_before)
self.assertEquals(m.due, m1.due)
# add
r = self.client.post(url, { 'prefix': "m1",
'm1-id': m1.id,
'm1-desc': "Test 2 - changed",
'm1-due': due.strftime("%Y-%m-%d"),
'm1-resolved': "Done",
'm1-resolved_checkbox': "checked",
'm1-docs': ",".join(docs),
})
self.assertEquals(r.status_code, 302)
self.assertEquals(GroupMilestone.objects.count(), milestones_before)
self.assertEquals(group.groupevent_set.count(), events_before + 1)
m = GroupMilestone.objects.get(pk=m1.pk)
self.assertEquals(m.state_id, "active")
self.assertEquals(m.due, due)
self.assertEquals(m.resolved, "Done")
self.assertEquals(set(m.docs.values_list("name", flat=True)), set(docs))
self.assertTrue("Changed milestone" in m.milestonegroupevent_set.all()[0].desc)
def test_reset_charter_milestones(self):
m1, m2, group = self.create_test_milestones()
url = urlreverse('wg_reset_charter_milestones', kwargs=dict(acronym=group.acronym))
login_testing_unauthorized(self, "secretary", url)
# normal get
r = self.client.get(url)
self.assertEquals(r.status_code, 200)
q = PyQuery(r.content)
self.assertEquals(q('input[name=milestone]').val(), str(m1.pk))
events_before = group.charter.docevent_set.count()
# reset
r = self.client.post(url, dict(milestone=[str(m1.pk)]))
self.assertEquals(r.status_code, 302)
self.assertEquals(GroupMilestone.objects.get(pk=m1.pk).state_id, "active")
self.assertEquals(GroupMilestone.objects.get(pk=m2.pk).state_id, "deleted")
self.assertEquals(GroupMilestone.objects.filter(due=m1.due, desc=m1.desc, state="charter").count(), 1)
self.assertEquals(group.charter.docevent_set.count(), events_before + 2) # 1 delete, 1 add

View file

@ -1,7 +1,7 @@
# Copyright The IETF Trust 2008, All Rights Reserved
from django.conf.urls.defaults import patterns, include
from ietf.wginfo import views, edit
from ietf.wginfo import views, edit, milestones
from django.views.generic.simple import redirect_to
@ -19,8 +19,12 @@ urlpatterns = patterns('',
(r'^(?P<acronym>[a-zA-Z0-9-]+)/documents/txt/$', views.wg_documents_txt),
(r'^(?P<acronym>[a-zA-Z0-9-]+)/$', views.wg_documents_html),
(r'^(?P<acronym>[a-zA-Z0-9-]+)/charter/$', views.wg_charter, None, 'wg_charter'),
(r'^(?P<acronym>[a-zA-Z0-9-]+)/history/', views.history),
(r'^(?P<acronym>[a-zA-Z0-9-]+)/edit/', edit.edit, {'action': "edit"}, "wg_edit"),
(r'^(?P<acronym>[a-zA-Z0-9-]+)/conclude/', edit.conclude, None, "wg_conclude"),
(r'^(?P<acronym>[a-zA-Z0-9-]+)/history/$', views.history),
(r'^(?P<acronym>[a-zA-Z0-9-]+)/edit/$', edit.edit, {'action': "edit"}, "wg_edit"),
(r'^(?P<acronym>[a-zA-Z0-9-]+)/conclude/$', edit.conclude, None, "wg_conclude"),
(r'^(?P<acronym>[a-zA-Z0-9-]+)/milestones/$', milestones.edit_milestones, {'milestone_set': "current"}, "wg_edit_milestones"),
(r'^(?P<acronym>[a-zA-Z0-9-]+)/milestones/charter/$', milestones.edit_milestones, {'milestone_set': "charter"}, "wg_edit_charter_milestones"),
(r'^(?P<acronym>[a-zA-Z0-9-]+)/milestones/charter/reset/$', milestones.reset_charter_milestones, None, "wg_reset_charter_milestones"),
(r'^(?P<acronym>[a-zA-Z0-9-]+)/ajax/searchdocs/$', milestones.ajax_search_docs, None, "wg_ajax_search_docs"),
(r'^(?P<acronym>[^/]+)/management/', include('ietf.wgchairs.urls')),
)

View file

@ -55,7 +55,7 @@ def fill_in_charter_info(wg, include_drafts=False):
wg.techadvisors = Email.objects.filter(role__group=wg, role__name="techadv")
wg.editors = Email.objects.filter(role__group=wg, role__name="editor")
wg.secretaries = Email.objects.filter(role__group=wg, role__name="secr")
wg.milestones = wg.groupmilestone_set.all().order_by('expected_due_date')
wg.milestones = wg.groupmilestone_set.filter(state="active").order_by('due')
if include_drafts:
aliases = DocAlias.objects.filter(document__type="draft", document__group=wg).select_related('document').order_by("name")
@ -191,29 +191,28 @@ def wg_charter(request, acronym):
concluded = wg.status_id in [ 2, 3, ]
proposed = (wg.status_id == 4)
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
fill_in_charter_info(wg)
actions = []
fill_in_charter_info(wg)
actions = []
if wg.state_id != "conclude":
actions.append(("Edit WG", urlreverse("wg_edit", kwargs=dict(acronym=wg.acronym))))
e = wg.latest_event(type__in=("changed_state", "requested_close",))
requested_close = wg.state_id != "conclude" and e and e.type == "requested_close"
e = wg.latest_event(type__in=("changed_state", "requested_close",))
requested_close = wg.state_id != "conclude" and e and e.type == "requested_close"
if wg.state_id != "conclude":
actions.append(("Edit WG", urlreverse("wg_edit", kwargs=dict(acronym=wg.acronym))))
if wg.state_id in ("active", "dormant"):
actions.append(("Request closing WG", urlreverse("wg_conclude", kwargs=dict(acronym=wg.acronym))))
if wg.state_id in ("active", "dormant"):
actions.append(("Request closing WG", urlreverse("wg_conclude", kwargs=dict(acronym=wg.acronym))))
context = get_wg_menu_context(wg, "charter")
context.update(dict(
actions=actions,
requested_close=requested_close,
))
context = get_wg_menu_context(wg, "charter")
context.update(dict(
actions=actions,
is_chair=wg.role_set.filter(name="chair", person__user=request.user),
milestones_in_review=wg.groupmilestone_set.filter(state="review"),
requested_close=requested_close,
))
return render_to_response('wginfo/wg_charterREDESIGN.html',
context,
RequestContext(request))
return render_to_response('wginfo/wg_charter.html', {'wg': wg, 'concluded':concluded, 'proposed': proposed, 'selected':'charter'}, RequestContext(request))
return render_to_response('wginfo/wg_charter.html',
context,
RequestContext(request))
def get_wg_menu_context(wg, selected):
# it would probably be better to refactor wginfo into rendering

View file

@ -6,8 +6,6 @@ ul.token-input-list {
width: 400px;
border: 1px solid #999;
cursor: text;
font-size: 12px;
font-family: Verdana;
z-index: 999;
margin: 0;
padding: 0;
@ -34,9 +32,8 @@ li.token-input-token {
height: 1%;
margin: 3px;
padding: 3px 5px;
background-color: #d0efa0;
background-color: #e8f0fa;
color: #000;
font-weight: bold;
cursor: default;
display: block;
}
@ -54,8 +51,8 @@ li.token-input-token span {
}
li.token-input-selected-token {
background-color: #08844e;
color: #fff;
background-color: #d5dde6;
color: #000;
}
li.token-input-selected-token span {
@ -71,15 +68,12 @@ div.token-input-dropdown {
border-right: 1px solid #ccc;
border-bottom: 1px solid #ccc;
cursor: default;
font-size: 12px;
font-family: Verdana;
z-index: 1;
}
div.token-input-dropdown p {
margin: 0;
padding: 5px;
font-weight: bold;
color: #777;
}
@ -108,6 +102,6 @@ div.token-input-dropdown ul li em {
}
div.token-input-dropdown ul li.token-input-selected-dropdown-item {
background-color: #d0efa0;
background-color: #d5dde6;
}

View file

@ -0,0 +1,100 @@
jQuery(function () {
var idCounter = -1;
// make sure we got the lowest number for idCounter
jQuery('#milestones-form .edit-milestone input[name$="-id"]').each(function () {
var v = +this.value;
if (!isNaN(v) && v < idCounter)
idCounter = v - 1;
});
jQuery("tr.milestone").click(function () {
var row = jQuery(this), editRow = row.next("tr.edit-milestone");
if (row.hasClass("add")) {
// move Add milestone row and duplicate hidden template
row.closest("table").append(row).append(editRow.clone());
// fixup template
var newId = idCounter;
--idCounter;
var prefix = "m" + newId;
editRow.find('input[name="prefix"]').val(prefix);
editRow.find("input,select,textarea").each(function () {
if (this.name == "prefix")
return;
if (this.name == "id")
this.value = "" + idCounter;
this.name = prefix + "-" + this.name;
});
editRow.removeClass("template");
setupTokenizedField(editRow.find(".tokenized-field")); // from tokenized-field.js
setInputMasks(editRow);
editRow.show();
}
else {
row.hide();
editRow.show();
}
editRow.find('input[name$="expanded_for_editing"]').val("True");
editRow.find('input[name$="desc"]').focus();
});
function setResolvedState() {
var resolved = jQuery(this).is(":checked");
var label = jQuery(this).siblings("label");
var reason = jQuery(this).siblings("input[type=text]");
if (resolved) {
if (label.text().indexOf(":") == -1)
label.text(label.text() + ":");
reason.show();
if (!reason.val())
reason.val(finishedMilestoneText);
}
else {
if (label.text().indexOf(":") != -1)
label.text(label.text().replace(":", ""));
reason.hide();
reason.val("");
}
}
jQuery("#milestones-form .edit-milestone .resolved input[type=checkbox]")
.each(setResolvedState)
.live("change", setResolvedState);
function setDeleteState() {
var top = jQuery(this).closest(".edit-milestone");
if (jQuery(this).is(":checked")) {
if (+top.find('input[name$="id"]').val() < 0)
top.remove();
else
top.addClass("delete")
}
else
top.removeClass("delete")
}
jQuery("#milestones-form .edit-milestone .delete input[type=checkbox]")
.each(setDeleteState)
.live("change", setDeleteState);
function setInputMasks(editRows) {
editRows.find(".due input").mask("9999-99-99");
}
setInputMasks(jQuery("#milestone-form .edit-milestone").not(".template"));
jQuery('#milestones-form .edit-milestone input[name$="expanded_for_editing"]').each(function () {
if (this.value == "True")
jQuery(this).closest(".edit-milestone").prev().click();
});
});

View file

@ -1,13 +0,0 @@
jQuery(function () {
jQuery(".emails-field").each(function () {
var e = jQuery(this);
var pre = [];
if (e.val())
pre = JSON.parse(e.val());
e.tokenInput(e.data("ajax-url"), {
hintText: "",
preventDuplicates: true,
prePopulate: pre
});
});
});

View file

@ -0,0 +1,258 @@
/*
Masked Input plugin for jQuery
Copyright (c) 2007-@Year Josh Bush (digitalbush.com)
Licensed under the MIT license (http://digitalbush.com/projects/masked-input-plugin/#license)
Version: @version
*/
(function($) {
var pasteEventName = ($.browser.msie ? 'paste' : 'input') + ".mask";
var iPhone = (window.orientation != undefined);
$.mask = {
//Predefined character definitions
definitions: {
'9': "[0-9]",
'a': "[A-Za-z]",
'*': "[A-Za-z0-9]"
},
dataName:"rawMaskFn"
};
$.fn.extend({
//Helper Function for Caret positioning
caret: function(begin, end) {
if (this.length == 0) return;
if (typeof begin == 'number') {
end = (typeof end == 'number') ? end : begin;
return this.each(function() {
if (this.setSelectionRange) {
this.setSelectionRange(begin, end);
} else if (this.createTextRange) {
var range = this.createTextRange();
range.collapse(true);
range.moveEnd('character', end);
range.moveStart('character', begin);
range.select();
}
});
} else {
if (this[0].setSelectionRange) {
begin = this[0].selectionStart;
end = this[0].selectionEnd;
} else if (document.selection && document.selection.createRange) {
var range = document.selection.createRange();
begin = 0 - range.duplicate().moveStart('character', -100000);
end = begin + range.text.length;
}
return { begin: begin, end: end };
}
},
unmask: function() { return this.trigger("unmask"); },
mask: function(mask, settings) {
if (!mask && this.length > 0) {
var input = $(this[0]);
return input.data($.mask.dataName)();
}
settings = $.extend({
placeholder: "_",
completed: null
}, settings);
var defs = $.mask.definitions;
var tests = [];
var partialPosition = mask.length;
var firstNonMaskPos = null;
var len = mask.length;
$.each(mask.split(""), function(i, c) {
if (c == '?') {
len--;
partialPosition = i;
} else if (defs[c]) {
tests.push(new RegExp(defs[c]));
if(firstNonMaskPos==null)
firstNonMaskPos = tests.length - 1;
} else {
tests.push(null);
}
});
return this.trigger("unmask").each(function() {
var input = $(this);
var buffer = $.map(mask.split(""), function(c, i) { if (c != '?') return defs[c] ? settings.placeholder : c });
var focusText = input.val();
function seekNext(pos) {
while (++pos <= len && !tests[pos]);
return pos;
};
function seekPrev(pos) {
while (--pos >= 0 && !tests[pos]);
return pos;
};
function shiftL(begin,end) {
if(begin<0)
return;
for (var i = begin,j = seekNext(end); i < len; i++) {
if (tests[i]) {
if (j < len && tests[i].test(buffer[j])) {
buffer[i] = buffer[j];
buffer[j] = settings.placeholder;
} else
break;
j = seekNext(j);
}
}
writeBuffer();
input.caret(Math.max(firstNonMaskPos, begin));
};
function shiftR(pos) {
for (var i = pos, c = settings.placeholder; i < len; i++) {
if (tests[i]) {
var j = seekNext(i);
var t = buffer[i];
buffer[i] = c;
if (j < len && tests[j].test(t))
c = t;
else
break;
}
}
};
function keydownEvent(e) {
var k=e.which;
//backspace, delete, and escape get special treatment
if(k == 8 || k == 46 || (iPhone && k == 127)){
var pos = input.caret(),
begin = pos.begin,
end = pos.end;
if(end-begin==0){
begin=k!=46?seekPrev(begin):(end=seekNext(begin-1));
end=k==46?seekNext(end):end;
}
clearBuffer(begin, end);
shiftL(begin,end-1);
return false;
} else if (k == 27) {//escape
input.val(focusText);
input.caret(0, checkVal());
return false;
}
};
function keypressEvent(e) {
var k = e.which,
pos = input.caret();
if (e.ctrlKey || e.altKey || e.metaKey || k<32) {//Ignore
return true;
} else if (k) {
if(pos.end-pos.begin!=0){
clearBuffer(pos.begin, pos.end);
shiftL(pos.begin, pos.end-1);
}
var p = seekNext(pos.begin - 1);
if (p < len) {
var c = String.fromCharCode(k);
if (tests[p].test(c)) {
shiftR(p);
buffer[p] = c;
writeBuffer();
var next = seekNext(p);
input.caret(next);
if (settings.completed && next >= len)
settings.completed.call(input);
}
}
return false;
}
};
function clearBuffer(start, end) {
for (var i = start; i < end && i < len; i++) {
if (tests[i])
buffer[i] = settings.placeholder;
}
};
function writeBuffer() { return input.val(buffer.join('')).val(); };
function checkVal(allow) {
//try to place characters where they belong
var test = input.val();
var lastMatch = -1;
for (var i = 0, pos = 0; i < len; i++) {
if (tests[i]) {
buffer[i] = settings.placeholder;
while (pos++ < test.length) {
var c = test.charAt(pos - 1);
if (tests[i].test(c)) {
buffer[i] = c;
lastMatch = i;
break;
}
}
if (pos > test.length)
break;
} else if (buffer[i] == test.charAt(pos) && i!=partialPosition) {
pos++;
lastMatch = i;
}
}
if (!allow && lastMatch + 1 < partialPosition) {
input.val("");
clearBuffer(0, len);
} else if (allow || lastMatch + 1 >= partialPosition) {
writeBuffer();
if (!allow) input.val(input.val().substring(0, lastMatch + 1));
}
return (partialPosition ? i : firstNonMaskPos);
};
input.data($.mask.dataName,function(){
return $.map(buffer, function(c, i) {
return tests[i]&&c!=settings.placeholder ? c : null;
}).join('');
})
if (!input.attr("readonly"))
input
.one("unmask", function() {
input
.unbind(".mask")
.removeData($.mask.dataName);
})
.bind("focus.mask", function() {
focusText = input.val();
var pos = checkVal();
writeBuffer();
var moveCaret=function(){
if (pos == mask.length)
input.caret(0, pos);
else
input.caret(pos);
};
($.browser.msie ? moveCaret:function(){setTimeout(moveCaret,0)})();
})
.bind("blur.mask", function() {
checkVal();
if (input.val() != focusText)
input.change();
})
.bind("keydown.mask", keydownEvent)
.bind("keypress.mask", keypressEvent)
.bind(pasteEventName, function() {
setTimeout(function() { input.caret(checkVal(true)); }, 0);
});
checkVal(); //Perform initial check for existing values
});
}
});
})(jQuery);

View file

@ -0,0 +1,19 @@
function setupTokenizedField(field) {
if (field.parents(".template").length > 0)
return; // don't tokenize hidden template snippets
var pre = [];
if (field.val())
pre = JSON.parse(field.val());
else if (field.data("pre"))
pre = JSON.parse(field.data("pre"));
field.tokenInput(field.data("ajax-url"), {
hintText: "",
preventDuplicates: true,
prePopulate: pre
});
}
jQuery(function () {
jQuery(".tokenized-field").each(function () { setupTokenizedField(jQuery(this)); });
});