diff --git a/ietf/doc/models.py b/ietf/doc/models.py index 6fb9e9036..bfaf0d354 100644 --- a/ietf/doc/models.py +++ b/ietf/doc/models.py @@ -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"), diff --git a/ietf/group/admin.py b/ietf/group/admin.py index ed08b74e9..2538dbfa8 100644 --- a/ietf/group/admin.py +++ b/ietf/group/admin.py @@ -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) diff --git a/ietf/group/migrations/0001_initial.py b/ietf/group/migrations/0001_initial.py new file mode 100644 index 000000000..6e9852f5d --- /dev/null +++ b/ietf/group/migrations/0001_initial.py @@ -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'] diff --git a/ietf/group/migrations/0002_auto__add_milestonegroupevent__del_field_groupmilestone_expected_due_d.py b/ietf/group/migrations/0002_auto__add_milestonegroupevent__del_field_groupmilestone_expected_due_d.py new file mode 100644 index 000000000..f79b03b18 --- /dev/null +++ b/ietf/group/migrations/0002_auto__add_milestonegroupevent__del_field_groupmilestone_expected_due_d.py @@ -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'] diff --git a/ietf/group/migrations/0003_fixup_milestone.py b/ietf/group/migrations/0003_fixup_milestone.py new file mode 100644 index 000000000..8abdc3d6f --- /dev/null +++ b/ietf/group/migrations/0003_fixup_milestone.py @@ -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'] diff --git a/ietf/group/migrations/0004_auto__del_field_groupmilestone_done_date__del_field_groupmilestone_don.py b/ietf/group/migrations/0004_auto__del_field_groupmilestone_done_date__del_field_groupmilestone_don.py new file mode 100644 index 000000000..e08a26e94 --- /dev/null +++ b/ietf/group/migrations/0004_auto__del_field_groupmilestone_done_date__del_field_groupmilestone_don.py @@ -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'] diff --git a/ietf/group/migrations/0005_auto__add_groupmilestonehistory.py b/ietf/group/migrations/0005_auto__add_groupmilestonehistory.py new file mode 100644 index 000000000..394e83cd3 --- /dev/null +++ b/ietf/group/migrations/0005_auto__add_groupmilestonehistory.py @@ -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'] diff --git a/ietf/group/migrations/__init__.py b/ietf/group/migrations/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/ietf/group/models.py b/ietf/group/models.py index b44fa98a1..0283dbd0c 100644 --- a/ietf/group/models.py +++ b/ietf/group/models.py @@ -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) diff --git a/ietf/group/utils.py b/ietf/group/utils.py index e0a10ef54..fe69c85d3 100644 --- a/ietf/group/utils.py +++ b/ietf/group/utils.py @@ -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 diff --git a/ietf/idrfc/views_doc.py b/ietf/idrfc/views_doc.py index f9ee5e0e2..a852432a9 100644 --- a/ietf/idrfc/views_doc.py +++ b/ietf/idrfc/views_doc.py @@ -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)) diff --git a/ietf/name/fixtures/names.xml b/ietf/name/fixtures/names.xml index dad67e3a5..bb3a387dc 100644 --- a/ietf/name/fixtures/names.xml +++ b/ietf/name/fixtures/names.xml @@ -19,7 +19,7 @@ True 3 - False + True Block @@ -307,35 +307,29 @@ True 0 - - No + + Active True - 0 + 1 - - Yes + + Deleted True - 0 + 2 - - Abstain + + For review True - 0 + 3 - - Block + + Chartering/rechartering True - 0 - - - No record - - True - 0 + 4 BOF @@ -628,7 +622,7 @@ Draft Standard - True + False 0 @@ -1630,25 +1624,34 @@ Ready for external review Is this charter ready for external review? True - 0 + 1 - - charter - approve - Approve - Do we approve of this charter? - True - 0 - - - + draft approve Approve True - 0 + 1 + + charter + r-wo-ext + Ready w/o external review + Is this charter ready for external review? Is this charter ready for approval without external review? + True + 2 + + + + charter + approve + Approve + Do we approve of this charter? + True + 3 + + \ No newline at end of file diff --git a/ietf/name/migrations/0003_auto__del_groupballotpositionname__add_groupmilestonestatename.py b/ietf/name/migrations/0003_auto__del_groupballotpositionname__add_groupmilestonestatename.py new file mode 100644 index 000000000..c7ab6cd25 --- /dev/null +++ b/ietf/name/migrations/0003_auto__del_groupballotpositionname__add_groupmilestonestatename.py @@ -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'] diff --git a/ietf/name/migrations/0004_add_groupmilestonestatenames.py b/ietf/name/migrations/0004_add_groupmilestonestatenames.py new file mode 100644 index 000000000..323f20f7a --- /dev/null +++ b/ietf/name/migrations/0004_add_groupmilestonestatenames.py @@ -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'] diff --git a/ietf/name/models.py b/ietf/name/models.py index 672b57004..2c8b15e3d 100644 --- a/ietf/name/models.py +++ b/ietf/name/models.py @@ -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): diff --git a/ietf/person/forms.py b/ietf/person/forms.py index 039d0cb1b..22bc2d0ea 100644 --- a/ietf/person/forms.py +++ b/ietf/person/forms.py @@ -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) diff --git a/ietf/templates/idrfc/document_charter.html b/ietf/templates/idrfc/document_charter.html index e9f092b87..c95f31607 100644 --- a/ietf/templates/idrfc/document_charter.html +++ b/ietf/templates/idrfc/document_charter.html @@ -44,7 +44,7 @@ {% if not snapshot and user|has_role:"Area Director,Secretariat" %} - {% if chartering %} + {% if chartering %} - Abandon effort {% if request.user|has_role:"Secretariat" %} @@ -118,11 +118,25 @@ {% endif %} -{% if doc.rev %} +{% if doc.rev != "" %} {{ content|safe|linebreaksbr|keep_spacing|sanitize_html|safe }} {% endif %} +{% if not snapshot and chartering %} +Proposed Milestones +{% if user|has_role:"Area Director,Secretariat" %} +Edit charter milestones +{% endif %} + + +{% if milestones %} +{% include "wginfo/milestones.html" %} +{% else %} +No milestones for charter found. +{% endif %} +{% endif %} + {% endblock %} diff --git a/ietf/templates/wginfo/edit.html b/ietf/templates/wginfo/edit.html index 5a740b3de..08c21b0a9 100644 --- a/ietf/templates/wginfo/edit.html +++ b/ietf/templates/wginfo/edit.html @@ -75,7 +75,7 @@ Start chartering new WG {% block content_end %} - + + + + + + +{% endblock %} diff --git a/ietf/templates/wginfo/milestone_form.html b/ietf/templates/wginfo/milestone_form.html new file mode 100644 index 000000000..f08c898c5 --- /dev/null +++ b/ietf/templates/wginfo/milestone_form.html @@ -0,0 +1,45 @@ +{# assumes group, form, needs_review are in the context #} + +{{ form.id }} +{{ form.expanded_for_editing }} + + + + {{ form.desc.label_tag }}: + + + {% if needs_review and form.milestone and form.milestone.state_id != "review" %} + {{ form.milestone.desc }} {{ form.desc.as_hidden }} + {% else %} + {{ form.desc }} + {% endif %} + + {{ form.delete }} {{ form.delete.label_tag }} + + + {% if form.desc.errors %}{{ form.desc.errors }}{% endif %} + + {{ form.due.label_tag }}: + {{ form.due }} {{ form.due.errors }} + {{ form.resolved_checkbox }} {{ form.resolved_checkbox.label_tag }} {{ form.resolved }} + {{ form.resolved.errors }} + + + + Drafts: + + {{ form.docs.errors }} + + + {% if form.needs_review %} + + Review: + This milestone is not public yet, awaiting AD acceptance. + + {% if not needs_review %} + {{ form.accept }} {{ form.accept.label_tag }} + {% endif %} + + + {% endif %} + diff --git a/ietf/templates/wginfo/milestones.html b/ietf/templates/wginfo/milestones.html new file mode 100644 index 000000000..8ff043f9d --- /dev/null +++ b/ietf/templates/wginfo/milestones.html @@ -0,0 +1,12 @@ +{# assumes milestones is in context #} + + +{% for milestone in milestones %} + + + {% if milestone.resolved %}{{ milestone.resolved }}{% else %}{{ milestone.due|date:"M Y" }}{% endif %} + + {{ milestone.desc|escape }} + +{% endfor %} + diff --git a/ietf/templates/wginfo/reset_charter_milestones.html b/ietf/templates/wginfo/reset_charter_milestones.html new file mode 100644 index 000000000..eb7b08212 --- /dev/null +++ b/ietf/templates/wginfo/reset_charter_milestones.html @@ -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 %} +Reset Charter Milestones for {{ group.acronym }} {{ group.type.name }} + +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 %} + + + +{% for milestone in current_milestones %} + + + + + {% if milestone.resolved %}{{ milestone.resolved }}{% else %}{{ milestone.due|date:"M Y" }}{% endif %} + + {{ milestone.desc }} + + +{% endfor %} + + + Back + + + +{% endblock %} diff --git a/ietf/templates/wginfo/wg-charterREDESIGN.txt b/ietf/templates/wginfo/wg-charterREDESIGN.txt index ef99aa2ef..a46bb0b08 100644 --- a/ietf/templates/wginfo/wg-charterREDESIGN.txt +++ b/ietf/templates/wginfo/wg-charterREDESIGN.txt @@ -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) diff --git a/ietf/templates/wginfo/wg_charter.html b/ietf/templates/wginfo/wg_charter.html index c4aa2fcaa..56635994c 100644 --- a/ietf/templates/wginfo/wg_charter.html +++ b/ietf/templates/wginfo/wg_charter.html @@ -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 %} {% if concluded %} Note: The data for concluded WGs is occasionally incorrect. {% endif %} - - -Personnel - - + Group - -Chair{{ wg.chairs.count|pluralize:",s" }}: - -{% for chair in wg.chairs %} -{{ chair.person|escape }} <{{ chair.person.email.1 }}> -{% endfor %} - -Area Director: - -{% ifequal wg.area_director.person.email.1 "noreply@ietf.org" %}?{%else%} -{{ wg.area_director.person }} <{{wg.area_director.person.email.1 }}>{% endifequal %} - - -{% if wg.wgtechadvisor_set.count %} - -Tech Advisor{{ wg.wgtechadvisor_set.count|pluralize:",s" }}: - -{% for techadvisor in wg.wgtechadvisor_set.all %} -{{ techadvisor.person }} <{{ techadvisor.person.email.1 }}> -{% endfor %} - -{% endif %} -{% if wg.wgeditor_set.count %} -Editor{{ wg.wgeditor_set.count|pluralize:",s" }}: - -{% for editor in wg.wgeditor_set.all %} -{{ editor.person }} <{{ editor.person.email.1 }}> -{% endfor %} - -{% endif %} -{% if wg.secretaries %} -Secretar{{ wg.secretaries.count|pluralize:"y,ies" }}: - -{% for secretary in wg.secretaries %} -{{ secretary.person }} <{{ secretary.person.email.1 }}> -{% endfor %} - -{% endif %} + + Name: + {{ wg.name }} + - - -Mailing List - - + Acronym:{{ wg.acronym }} -Address:{{ wg.email_address|urlize }} -To Subscribe:{{ wg.email_subscribe|urlize }} -Archive:{{ wg.clean_email_archive|urlize }} + {% if wg.parent %} + Area:{{ wg.parent.name }} ({{ wg.parent.acronym }}) + {% endif %} -{% if not concluded %} - - -Jabber Chat - - + + State: + {{ wg.state.name }} + {% if requested_close %} + (but in the process of being closed) + {% endif %} + + -Room Address:xmpp:{{wg}}@jabber.ietf.org -Logs:http://jabber.ietf.org/logs/{{wg}}/ -{% endif %} + + Charter: + + {% if wg.charter %} + {{ wg.charter.name }}-{{ wg.charter.rev }} ({{ wg.charter.get_state.name }}) + {% else %} + none + {% if user|has_role:"Area Director,Secretariat" %} + - Submit Charter + {% endif %} + {% endif %} + + + + Personnel + + + Chair{{ wg.chairs|pluralize }}: + + {% for chair in wg.chairs %} + {{ chair.person.plain_name }} <{{ chair.address }}> + {% endfor %} + + + + Area Director: + + {% if not wg.ad %}?{% else %} + {{ wg.ad.plain_name }} <{{ wg.areadirector.address }}>{% endif %} + + + {% if wg.techadvisors %} + + Tech Advisor{{ wg.techadvisors|pluralize }}: + + {% for techadvisor in wg.techadvisors %} + {{ techadvisor.person.plain_name }} <{{ techadvisor.address }}> + {% endfor %} + + + {% endif %} + {% if wg.editors %} + Editor{{ wg.editors|pluralize }}: + + {% for editor in wg.editors %} + {{ editor.person.plain_name }} <{{ editor.address }}> + {% endfor %} + + {% endif %} + {% if wg.secretaries %} + + Secretar{{ wg.secretaries|pluralize:"y,ies" }}: + + {% for secretary in wg.secretaries %} + {{ secretary.person.plain_name }} <{{ secretary.address }}> + {% endfor %} + + + {% endif %} + + Mailing List + + Address:{{ wg.email_address|urlize }} + To Subscribe:{{ wg.email_subscribe|urlize }} + Archive:{{ wg.clean_email_archive|urlize }} + + {% if not concluded %} + Jabber Chat + + Room Address:xmpp:{{ wg.acronym }}@jabber.ietf.org + Logs:http://jabber.ietf.org/logs/{{ wg.acronym }}/ + {% endif %} + +{% if user|has_role:"Area Director,Secretariat" %} + + {% for name, url in actions %} + {{ name }} + {% if not forloop.last %}|{% endif %} + {% endfor %} + +{% endif %} {% if wg.additional_urls %} 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 %} -{{ url.description}}{% if not forloop.last %}, {% endif %} +{{ url.name }}{% if not forloop.last %}, {% endif %} {% endfor %} {% endif %} @@ -123,31 +165,16 @@ is occasionally incorrect. Description of Working Group {{ wg.charter_text|escape|format_charter|safe }} -Goals and Milestones - -{% for milestone in wg.milestones %} - - - {% 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 %} - - {{ milestone.description|escape }} - -{% endfor %} - -{% endblock wg_content %} +Goals and Milestones +{% if user|has_role:"Area Director,Secretariat" or is_chair %} +Add or edit milestones +{% endif %} + +{% with wg.milestones as milestones %}{% include "wginfo/milestones.html" %}{% endwith %} + +{% if milestones_in_review %} +{{ milestones_in_review|length }} new milestone{{ milestones_in_review|pluralize }} +under review. +{% endif %} +{% endblock wg_content %} diff --git a/ietf/templates/wginfo/wg_charterREDESIGN.html b/ietf/templates/wginfo/wg_charterREDESIGN.html deleted file mode 100644 index 3076315d8..000000000 --- a/ietf/templates/wginfo/wg_charterREDESIGN.html +++ /dev/null @@ -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 - -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 %} - -{% if concluded %} -Note: The data for concluded WGs -is occasionally incorrect. -{% endif %} - - Group - - - Name: - {{ wg.name }} - - - Acronym:{{ wg.acronym }} - - {% if wg.parent %} - Area:{{ wg.parent.name }} ({{ wg.parent.acronym }}) - {% endif %} - - - State: - {{ wg.state.name }} - {% if requested_close %} - (but in the process of being closed) - {% endif %} - - - - - Charter: - - {% if wg.charter %} - {{ wg.charter.name }}-{{ wg.charter.rev }} ({{ wg.charter.get_state.name }}) - {% else %} - none - {% if user|has_role:"Area Director,Secretariat" %} - - Submit Charter - {% endif %} - {% endif %} - - - - Personnel - - - Chair{{ wg.chairs|pluralize }}: - - {% for chair in wg.chairs %} - {{ chair.person.plain_name }} <{{ chair.address }}> - {% endfor %} - - - - Area Director: - - {% if not wg.ad %}?{% else %} - {{ wg.ad.plain_name }} <{{ wg.areadirector.address }}>{% endif %} - - - {% if wg.techadvisors %} - - Tech Advisor{{ wg.techadvisors|pluralize }}: - - {% for techadvisor in wg.techadvisors %} - {{ techadvisor.person.plain_name }} <{{ techadvisor.address }}> - {% endfor %} - - - {% endif %} - {% if wg.editors %} - Editor{{ wg.editors|pluralize }}: - - {% for editor in wg.editors %} - {{ editor.person.plain_name }} <{{ editor.address }}> - {% endfor %} - - {% endif %} - {% if wg.secretaries %} - - Secretar{{ wg.secretaries|pluralize:"y,ies" }}: - - {% for secretary in wg.secretaries %} - {{ secretary.person.plain_name }} <{{ secretary.address }}> - {% endfor %} - - - {% endif %} - - Mailing List - - Address:{{ wg.email_address|urlize }} - To Subscribe:{{ wg.email_subscribe|urlize }} - Archive:{{ wg.clean_email_archive|urlize }} - - {% if not concluded %} - Jabber Chat - - Room Address:xmpp:{{ wg.acronym }}@jabber.ietf.org - Logs:http://jabber.ietf.org/logs/{{ wg.acronym }}/ - {% endif %} - - - -{% if user|has_role:"Area Director,Secretariat" %} - - {% for name, url in actions %} - {{ name }} - {% if not forloop.last %}|{% endif %} - {% endfor %} - -{% endif %} - - -{% if wg.additional_urls %} -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 %} -{{ url.name }}{% if not forloop.last %}, {% endif %} -{% endfor %} - -{% endif %} - -Description of Working Group -{{ wg.charter_text|escape|format_charter|safe }} - -Goals and Milestones - -{% for milestone in wg.milestones %} - - - {% if milestone.done %}Done{% else %}{{ milestone.expected_due_date|date:"M Y" }}{% endif %} - - {{ milestone.desc|escape }} - -{% endfor %} - -{% endblock wg_content %} diff --git a/ietf/utils/history.py b/ietf/utils/history.py index e0b790044..09e1adaa4 100644 --- a/ietf/utils/history.py +++ b/ietf/utils/history.py @@ -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()) diff --git a/ietf/wginfo/milestones.py b/ietf/wginfo/milestones.py new file mode 100644 index 000000000..a95712429 --- /dev/null +++ b/ietf/wginfo/milestones.py @@ -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') diff --git a/ietf/wginfo/tests.py b/ietf/wginfo/tests.py index 66e89db51..04a5a8385 100644 --- a/ietf/wginfo/tests.py +++ b/ietf/wginfo/tests.py @@ -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 diff --git a/ietf/wginfo/urls.py b/ietf/wginfo/urls.py index 5979386a9..dc3721a18 100644 --- a/ietf/wginfo/urls.py +++ b/ietf/wginfo/urls.py @@ -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[a-zA-Z0-9-]+)/documents/txt/$', views.wg_documents_txt), (r'^(?P[a-zA-Z0-9-]+)/$', views.wg_documents_html), (r'^(?P[a-zA-Z0-9-]+)/charter/$', views.wg_charter, None, 'wg_charter'), - (r'^(?P[a-zA-Z0-9-]+)/history/', views.history), - (r'^(?P[a-zA-Z0-9-]+)/edit/', edit.edit, {'action': "edit"}, "wg_edit"), - (r'^(?P[a-zA-Z0-9-]+)/conclude/', edit.conclude, None, "wg_conclude"), + (r'^(?P[a-zA-Z0-9-]+)/history/$', views.history), + (r'^(?P[a-zA-Z0-9-]+)/edit/$', edit.edit, {'action': "edit"}, "wg_edit"), + (r'^(?P[a-zA-Z0-9-]+)/conclude/$', edit.conclude, None, "wg_conclude"), + (r'^(?P[a-zA-Z0-9-]+)/milestones/$', milestones.edit_milestones, {'milestone_set': "current"}, "wg_edit_milestones"), + (r'^(?P[a-zA-Z0-9-]+)/milestones/charter/$', milestones.edit_milestones, {'milestone_set': "charter"}, "wg_edit_charter_milestones"), + (r'^(?P[a-zA-Z0-9-]+)/milestones/charter/reset/$', milestones.reset_charter_milestones, None, "wg_reset_charter_milestones"), + (r'^(?P[a-zA-Z0-9-]+)/ajax/searchdocs/$', milestones.ajax_search_docs, None, "wg_ajax_search_docs"), (r'^(?P[^/]+)/management/', include('ietf.wgchairs.urls')), ) diff --git a/ietf/wginfo/views.py b/ietf/wginfo/views.py index b9188af36..a048d93d6 100644 --- a/ietf/wginfo/views.py +++ b/ietf/wginfo/views.py @@ -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 diff --git a/static/css/token-input.css b/static/css/token-input.css index 03bb01c4d..39fdc5d4d 100644 --- a/static/css/token-input.css +++ b/static/css/token-input.css @@ -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; } diff --git a/static/js/edit-milestones.js b/static/js/edit-milestones.js new file mode 100644 index 000000000..6a2867b76 --- /dev/null +++ b/static/js/edit-milestones.js @@ -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(); + }); +}); diff --git a/static/js/emails-field.js b/static/js/emails-field.js deleted file mode 100644 index 6c5c770cb..000000000 --- a/static/js/emails-field.js +++ /dev/null @@ -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 - }); - }); -}); diff --git a/static/js/lib/jquery.maskedinput.js b/static/js/lib/jquery.maskedinput.js new file mode 100644 index 000000000..af6760426 --- /dev/null +++ b/static/js/lib/jquery.maskedinput.js @@ -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); diff --git a/static/js/tokenized-field.js b/static/js/tokenized-field.js new file mode 100644 index 000000000..962f64369 --- /dev/null +++ b/static/js/tokenized-field.js @@ -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)); }); +});
No milestones for charter found.
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 %} +
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 %} -{{ url.description}}{% if not forloop.last %}, {% endif %} +{{ url.name }}{% if not forloop.last %}, {% endif %} {% endfor %}
{{ wg.charter_text|escape|format_charter|safe }}
{{ milestones_in_review|length }} new milestone{{ milestones_in_review|pluralize }} +under review.
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 %} -{{ url.name }}{% if not forloop.last %}, {% endif %} -{% endfor %} -