From 75b94bd114589b858470be389be7e3acb36e5cf4 Mon Sep 17 00:00:00 2001 From: Robert Sparks <rjsparks@nostrum.com> Date: Tue, 9 Sep 2014 21:56:33 +0000 Subject: [PATCH 01/18] sketch that uses a through table, preserving most, but not all, of the current interface - Legacy-Id: 8302 --- .../migrations/0019_version_materials.py | 340 ++++++++++++++++++ .../0020_snapshot_material_revisions.py | 338 +++++++++++++++++ ietf/meeting/models.py | 15 +- ietf/meeting/test_data.py | 8 +- ietf/secr/proceedings/views.py | 6 +- 5 files changed, 698 insertions(+), 9 deletions(-) create mode 100644 ietf/meeting/migrations/0019_version_materials.py create mode 100644 ietf/meeting/migrations/0020_snapshot_material_revisions.py diff --git a/ietf/meeting/migrations/0019_version_materials.py b/ietf/meeting/migrations/0019_version_materials.py new file mode 100644 index 000000000..c53ef7c8c --- /dev/null +++ b/ietf/meeting/migrations/0019_version_materials.py @@ -0,0 +1,340 @@ +# -*- coding: utf-8 -*- +from south.v2 import SchemaMigration +from south.db import db + + +class Migration(SchemaMigration): + + def forwards(self, orm): + db.add_column('meeting_session_materials', 'rev', + self.gf('django.db.models.fields.CharField')(max_length=16, blank=True) + ) + + + def backwards(self, orm): + db.delete_column('meeting_session_materials', 'rev' ) + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + u'doc.document': { + 'Meta': {'object_name': 'Document'}, + 'abstract': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'ad': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'ad_document_set'", 'null': 'True', 'to': u"orm['person.Person']"}), + 'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['person.Email']", 'symmetrical': 'False', 'through': u"orm['doc.DocumentAuthor']", 'blank': 'True'}), + 'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'external_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}), + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['group.Group']", 'null': 'True', 'blank': 'True'}), + 'intended_std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.IntendedStdLevelName']", 'null': 'True', 'blank': 'True'}), + 'internal_comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'primary_key': 'True'}), + 'note': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'notify': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '1', 'blank': 'True'}), + 'pages': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'rev': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}), + 'shepherd': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'shepherd_document_set'", 'null': 'True', 'to': u"orm['person.Person']"}), + 'states': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}), + 'std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.StdLevelName']", 'null': 'True', 'blank': 'True'}), + 'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.StreamName']", 'null': 'True', 'blank': 'True'}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['name.DocTagName']", 'null': 'True', 'blank': 'True'}), + 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'}) + }, + u'doc.documentauthor': { + 'Meta': {'ordering': "['document', 'order']", 'object_name': 'DocumentAuthor'}, + 'author': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Email']"}), + 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.Document']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '1'}) + }, + u'doc.state': { + 'Meta': {'ordering': "['type', 'order']", 'object_name': 'State'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'next_states': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'previous_states'", 'blank': 'True', 'to': u"orm['doc.State']"}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}), + 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.StateType']"}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'doc.statetype': { + 'Meta': {'object_name': 'StateType'}, + 'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '30', 'primary_key': 'True'}) + }, + u'group.group': { + 'Meta': {'object_name': 'Group'}, + 'acronym': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '40'}), + 'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']", 'null': 'True', 'blank': 'True'}), + 'charter': ('django.db.models.fields.related.OneToOneField', [], {'blank': 'True', 'related_name': "'chartered_group'", 'unique': 'True', 'null': 'True', 'to': u"orm['doc.Document']"}), + 'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'list_archive': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'list_email': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), + 'list_subscribe': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['group.Group']", 'null': 'True', 'blank': 'True'}), + 'state': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.GroupStateName']", 'null': 'True'}), + 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.GroupTypeName']", 'null': 'True'}), + 'unused_states': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}), + 'unused_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['name.DocTagName']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'meeting.constraint': { + 'Meta': {'object_name': 'Constraint'}, + 'day': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'meeting': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['meeting.Meeting']"}), + 'name': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.ConstraintName']"}), + 'person': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']", 'null': 'True', 'blank': 'True'}), + 'source': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'constraint_source_set'", 'to': u"orm['group.Group']"}), + 'target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'constraint_target_set'", 'null': 'True', 'to': u"orm['group.Group']"}) + }, + u'meeting.meeting': { + 'Meta': {'ordering': "['-date']", 'object_name': 'Meeting'}, + 'agenda': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': u"orm['meeting.Schedule']"}), + 'agenda_note': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'break_area': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'city': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'country': ('django.db.models.fields.CharField', [], {'max_length': '2', 'blank': 'True'}), + 'date': ('django.db.models.fields.DateField', [], {}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'number': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'}), + 'reg_area': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'time_zone': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.MeetingTypeName']"}), + 'venue_addr': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'venue_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}) + }, + u'meeting.resourceassociation': { + 'Meta': {'object_name': 'ResourceAssociation'}, + 'desc': ('django.db.models.fields.CharField', [], {'max_length': '256'}), + 'icon': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.RoomResourceName']"}) + }, + u'meeting.room': { + 'Meta': {'object_name': 'Room'}, + 'capacity': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'meeting': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['meeting.Meeting']"}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'resources': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['meeting.ResourceAssociation']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'meeting.schedule': { + 'Meta': {'object_name': 'Schedule'}, + 'badness': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'meeting': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['meeting.Meeting']", 'null': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']"}), + 'public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'visible': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'meeting.scheduledsession': { + 'Meta': {'ordering': "['timeslot__time', 'session__group__parent__name', 'session__group__acronym', 'session__name']", 'object_name': 'ScheduledSession'}, + 'badness': ('django.db.models.fields.IntegerField', [], {'default': '0', 'null': 'True', 'blank': 'True'}), + 'extendedfrom': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['meeting.ScheduledSession']", 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'notes': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'pinned': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'schedule': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'assignments'", 'to': u"orm['meeting.Schedule']"}), + 'session': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['meeting.Session']", 'null': 'True'}), + 'timeslot': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['meeting.TimeSlot']"}) + }, + u'meeting.session': { + 'Meta': {'object_name': 'Session'}, + 'agenda_note': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'attendees': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['group.Group']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'materials': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['doc.Document']", 'symmetrical': 'False', 'through': u"orm['meeting.VersionedMaterials']", 'blank': 'True'}), + 'meeting': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['meeting.Meeting']"}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'requested': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'requested_by': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']"}), + 'requested_duration': ('ietf.meeting.timedeltafield.TimedeltaField', [], {'default': '0'}), + 'resources': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['meeting.ResourceAssociation']", 'symmetrical': 'False'}), + 'scheduled': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'short': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}), + 'status': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.SessionStatusName']"}) + }, + u'meeting.timeslot': { + 'Meta': {'object_name': 'TimeSlot'}, + 'duration': ('ietf.meeting.timedeltafield.TimedeltaField', [], {}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'location': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['meeting.Room']", 'null': 'True', 'blank': 'True'}), + 'meeting': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['meeting.Meeting']"}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'sessions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'slots'", 'to': u"orm['meeting.Session']", 'through': u"orm['meeting.ScheduledSession']", 'blank': 'True', 'symmetrical': 'False', 'null': 'True'}), + 'show_location': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'time': ('django.db.models.fields.DateTimeField', [], {}), + 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.TimeSlotTypeName']"}) + }, + u'meeting.versionedmaterials': { + 'Meta': {'object_name': 'VersionedMaterials', 'db_table': "'meeting_session_materials'"}, + 'doc': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.Document']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'rev': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}), + 'session': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['meeting.Session']"}) + }, + u'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'}), + 'penalty': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.doctagname': { + 'Meta': {'ordering': "['order']", 'object_name': 'DocTagName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.doctypename': { + 'Meta': {'ordering': "['order']", 'object_name': 'DocTypeName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.groupstatename': { + 'Meta': {'ordering': "['order']", 'object_name': 'GroupStateName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.grouptypename': { + 'Meta': {'ordering': "['order']", 'object_name': 'GroupTypeName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.intendedstdlevelname': { + 'Meta': {'ordering': "['order']", 'object_name': 'IntendedStdLevelName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.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': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.roomresourcename': { + 'Meta': {'ordering': "['order']", 'object_name': 'RoomResourceName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.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': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.stdlevelname': { + 'Meta': {'ordering': "['order']", 'object_name': 'StdLevelName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.streamname': { + 'Meta': {'ordering': "['order']", 'object_name': 'StreamName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'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': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'person.email': { + 'Meta': {'object_name': 'Email'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'address': ('django.db.models.fields.CharField', [], {'max_length': '64', 'primary_key': 'True'}), + 'person': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']", 'null': 'True'}), + 'time': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}) + }, + u'person.person': { + 'Meta': {'object_name': 'Person'}, + 'address': ('django.db.models.fields.TextField', [], {'max_length': '255', 'blank': 'True'}), + 'affiliation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'ascii': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'ascii_short': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['auth.User']", 'unique': 'True', 'null': 'True', 'blank': 'True'}) + } + } + + complete_apps = ['meeting'] diff --git a/ietf/meeting/migrations/0020_snapshot_material_revisions.py b/ietf/meeting/migrations/0020_snapshot_material_revisions.py new file mode 100644 index 000000000..088e6a8ac --- /dev/null +++ b/ietf/meeting/migrations/0020_snapshot_material_revisions.py @@ -0,0 +1,338 @@ +# -*- coding: utf-8 -*- +from south.v2 import DataMigration + +class Migration(DataMigration): + + def forwards(self, orm): + for vm in orm['meeting.VersionedMaterials'].objects.all(): + vm.rev = vm.document.rev + vm.save() + + def backwards(self, orm): + pass + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + u'doc.document': { + 'Meta': {'object_name': 'Document'}, + 'abstract': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'ad': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'ad_document_set'", 'null': 'True', 'to': u"orm['person.Person']"}), + 'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['person.Email']", 'symmetrical': 'False', 'through': u"orm['doc.DocumentAuthor']", 'blank': 'True'}), + 'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'external_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}), + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['group.Group']", 'null': 'True', 'blank': 'True'}), + 'intended_std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.IntendedStdLevelName']", 'null': 'True', 'blank': 'True'}), + 'internal_comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'primary_key': 'True'}), + 'note': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'notify': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '1', 'blank': 'True'}), + 'pages': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'rev': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}), + 'shepherd': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'shepherd_document_set'", 'null': 'True', 'to': u"orm['person.Person']"}), + 'states': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}), + 'std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.StdLevelName']", 'null': 'True', 'blank': 'True'}), + 'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.StreamName']", 'null': 'True', 'blank': 'True'}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['name.DocTagName']", 'null': 'True', 'blank': 'True'}), + 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'}) + }, + u'doc.documentauthor': { + 'Meta': {'ordering': "['document', 'order']", 'object_name': 'DocumentAuthor'}, + 'author': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Email']"}), + 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.Document']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '1'}) + }, + u'doc.state': { + 'Meta': {'ordering': "['type', 'order']", 'object_name': 'State'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'next_states': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'previous_states'", 'blank': 'True', 'to': u"orm['doc.State']"}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}), + 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.StateType']"}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'doc.statetype': { + 'Meta': {'object_name': 'StateType'}, + 'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '30', 'primary_key': 'True'}) + }, + u'group.group': { + 'Meta': {'object_name': 'Group'}, + 'acronym': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '40'}), + 'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']", 'null': 'True', 'blank': 'True'}), + 'charter': ('django.db.models.fields.related.OneToOneField', [], {'blank': 'True', 'related_name': "'chartered_group'", 'unique': 'True', 'null': 'True', 'to': u"orm['doc.Document']"}), + 'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'list_archive': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'list_email': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), + 'list_subscribe': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['group.Group']", 'null': 'True', 'blank': 'True'}), + 'state': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.GroupStateName']", 'null': 'True'}), + 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.GroupTypeName']", 'null': 'True'}), + 'unused_states': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}), + 'unused_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['name.DocTagName']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'meeting.constraint': { + 'Meta': {'object_name': 'Constraint'}, + 'day': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'meeting': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['meeting.Meeting']"}), + 'name': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.ConstraintName']"}), + 'person': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']", 'null': 'True', 'blank': 'True'}), + 'source': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'constraint_source_set'", 'to': u"orm['group.Group']"}), + 'target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'constraint_target_set'", 'null': 'True', 'to': u"orm['group.Group']"}) + }, + u'meeting.meeting': { + 'Meta': {'ordering': "['-date']", 'object_name': 'Meeting'}, + 'agenda': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': u"orm['meeting.Schedule']"}), + 'agenda_note': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'break_area': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'city': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'country': ('django.db.models.fields.CharField', [], {'max_length': '2', 'blank': 'True'}), + 'date': ('django.db.models.fields.DateField', [], {}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'number': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'}), + 'reg_area': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'time_zone': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.MeetingTypeName']"}), + 'venue_addr': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'venue_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}) + }, + u'meeting.resourceassociation': { + 'Meta': {'object_name': 'ResourceAssociation'}, + 'desc': ('django.db.models.fields.CharField', [], {'max_length': '256'}), + 'icon': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.RoomResourceName']"}) + }, + u'meeting.room': { + 'Meta': {'object_name': 'Room'}, + 'capacity': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'meeting': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['meeting.Meeting']"}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'resources': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['meeting.ResourceAssociation']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'meeting.schedule': { + 'Meta': {'object_name': 'Schedule'}, + 'badness': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'meeting': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['meeting.Meeting']", 'null': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']"}), + 'public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'visible': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'meeting.scheduledsession': { + 'Meta': {'ordering': "['timeslot__time', 'session__group__parent__name', 'session__group__acronym', 'session__name']", 'object_name': 'ScheduledSession'}, + 'badness': ('django.db.models.fields.IntegerField', [], {'default': '0', 'null': 'True', 'blank': 'True'}), + 'extendedfrom': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['meeting.ScheduledSession']", 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'notes': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'pinned': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'schedule': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'assignments'", 'to': u"orm['meeting.Schedule']"}), + 'session': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['meeting.Session']", 'null': 'True'}), + 'timeslot': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['meeting.TimeSlot']"}) + }, + u'meeting.session': { + 'Meta': {'object_name': 'Session'}, + 'agenda_note': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'attendees': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['group.Group']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'materials': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['doc.Document']", 'symmetrical': 'False', 'through': u"orm['meeting.VersionedMaterials']", 'blank': 'True'}), + 'meeting': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['meeting.Meeting']"}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'requested': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'requested_by': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']"}), + 'requested_duration': ('ietf.meeting.timedeltafield.TimedeltaField', [], {'default': '0'}), + 'resources': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['meeting.ResourceAssociation']", 'symmetrical': 'False'}), + 'scheduled': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'short': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}), + 'status': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.SessionStatusName']"}) + }, + u'meeting.timeslot': { + 'Meta': {'object_name': 'TimeSlot'}, + 'duration': ('ietf.meeting.timedeltafield.TimedeltaField', [], {}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'location': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['meeting.Room']", 'null': 'True', 'blank': 'True'}), + 'meeting': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['meeting.Meeting']"}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'sessions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'slots'", 'to': u"orm['meeting.Session']", 'through': u"orm['meeting.ScheduledSession']", 'blank': 'True', 'symmetrical': 'False', 'null': 'True'}), + 'show_location': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'time': ('django.db.models.fields.DateTimeField', [], {}), + 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.TimeSlotTypeName']"}) + }, + u'meeting.versionedmaterials': { + 'Meta': {'object_name': 'VersionedMaterials', 'db_table': "'meeting_session_materials'"}, + 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.Document']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'rev': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}), + 'session': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['meeting.Session']"}) + }, + u'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'}), + 'penalty': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.doctagname': { + 'Meta': {'ordering': "['order']", 'object_name': 'DocTagName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.doctypename': { + 'Meta': {'ordering': "['order']", 'object_name': 'DocTypeName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.groupstatename': { + 'Meta': {'ordering': "['order']", 'object_name': 'GroupStateName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.grouptypename': { + 'Meta': {'ordering': "['order']", 'object_name': 'GroupTypeName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.intendedstdlevelname': { + 'Meta': {'ordering': "['order']", 'object_name': 'IntendedStdLevelName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.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': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.roomresourcename': { + 'Meta': {'ordering': "['order']", 'object_name': 'RoomResourceName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.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': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.stdlevelname': { + 'Meta': {'ordering': "['order']", 'object_name': 'StdLevelName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.streamname': { + 'Meta': {'ordering': "['order']", 'object_name': 'StreamName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'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': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'person.email': { + 'Meta': {'object_name': 'Email'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'address': ('django.db.models.fields.CharField', [], {'max_length': '64', 'primary_key': 'True'}), + 'person': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']", 'null': 'True'}), + 'time': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}) + }, + u'person.person': { + 'Meta': {'object_name': 'Person'}, + 'address': ('django.db.models.fields.TextField', [], {'max_length': '255', 'blank': 'True'}), + 'affiliation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'ascii': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'ascii_short': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['auth.User']", 'unique': 'True', 'null': 'True', 'blank': 'True'}) + } + } + + complete_apps = ['meeting'] + symmetrical = True diff --git a/ietf/meeting/models.py b/ietf/meeting/models.py index 02300c04b..bb62596a0 100644 --- a/ietf/meeting/models.py +++ b/ietf/meeting/models.py @@ -776,6 +776,18 @@ class Constraint(models.Model): ct1['meeting_href'] = urljoin(host_scheme, self.meeting.json_url()) return ct1 + +class VersionedMaterials(models.Model): + session = models.ForeignKey('Session') + document = models.ForeignKey(Document) + rev = models.CharField(verbose_name="revision", max_length=16, blank=True) + + class Meta: + db_table = 'meeting_session_materials' + + def __unicode__(self): + return u"%s -> %s-%s" % (self.session, self.document.name, self.rev) + constraint_cache_uses = 0 constraint_cache_initials = 0 @@ -799,7 +811,7 @@ class Session(models.Model): scheduled = models.DateTimeField(null=True, blank=True) modified = models.DateTimeField(default=datetime.datetime.now) - materials = models.ManyToManyField(Document, blank=True) + materials = models.ManyToManyField(Document, through=VersionedMaterials, blank=True) resources = models.ManyToManyField(ResourceAssociation) unique_constraints_dict = None @@ -1171,4 +1183,3 @@ class Session(models.Model): if self.badness_test(1): self.badness_log(1, "badgroup: %s badness = %u\n" % (self.group.acronym, badness)) return badness - diff --git a/ietf/meeting/test_data.py b/ietf/meeting/test_data.py index 17225f046..c568cbe21 100644 --- a/ietf/meeting/test_data.py +++ b/ietf/meeting/test_data.py @@ -2,7 +2,7 @@ import datetime from ietf.doc.models import Document, State from ietf.group.models import Group -from ietf.meeting.models import Meeting, Room, TimeSlot, Session, Schedule, ScheduledSession, ResourceAssociation +from ietf.meeting.models import Meeting, Room, TimeSlot, Session, Schedule, ScheduledSession, ResourceAssociation, VersionedMaterials from ietf.name.models import RoomResourceName from ietf.person.models import Person from ietf.utils.test_data import make_test_data @@ -46,15 +46,15 @@ def make_meeting_test_data(): doc = Document.objects.create(name='agenda-mars-ietf-42', type_id='agenda', title="Agenda", external_url="agenda-mars") doc.set_state(State.objects.get(type=doc.type_id, slug="active")) - mars_session.materials.add(doc) + mars_session.versionedmaterials_set.add(VersionedMaterials(session=mars_session,document=doc,rev=doc.rev)) doc = Document.objects.create(name='minutes-mars-ietf-42', type_id='minutes', title="Minutes", external_url="minutes-mars") doc.set_state(State.objects.get(type=doc.type_id, slug="active")) - mars_session.materials.add(doc) + mars_session.versionedmaterials_set.add(VersionedMaterials(session=mars_session,document=doc,rev=doc.rev)) doc = Document.objects.create(name='slides-mars-ietf-42', type_id='slides', title="Slideshow", external_url="slides-mars") doc.set_state(State.objects.get(type=doc.type_id, slug="active")) - mars_session.materials.add(doc) + mars_session.versionedmaterials_set.add(VersionedMaterials(session=mars_session,document=doc,rev=doc.rev)) return meeting diff --git a/ietf/secr/proceedings/views.py b/ietf/secr/proceedings/views.py index f4a42430b..58636c00d 100644 --- a/ietf/secr/proceedings/views.py +++ b/ietf/secr/proceedings/views.py @@ -23,7 +23,7 @@ from ietf.secr.utils.meeting import get_upload_root, get_material, get_timeslot from ietf.doc.models import Document, DocAlias, DocEvent, State, NewRevisionDocEvent from ietf.group.models import Group from ietf.ietfauth.utils import has_role -from ietf.meeting.models import Meeting, Session, TimeSlot, ScheduledSession +from ietf.meeting.models import Meeting, Session, TimeSlot, ScheduledSession, VersionedMaterials from ietf.secr.proceedings.forms import EditSlideForm, InterimMeetingForm, ReplaceSlideForm, UnifiedUploadForm from ietf.secr.proceedings.proc_utils import ( gen_acknowledgement, gen_agenda, gen_areas, gen_attendees, gen_group_pages, gen_index, gen_irtf, gen_overview, gen_plenaries, gen_progress, gen_research, @@ -842,9 +842,9 @@ def upload_unified(request, meeting_num, acronym=None, session_id=None): # for the current meeting (until tools support different materials for diff sessions) if sessions: for s in sessions: - s.materials.add(doc) + s.materials.versionedmaterials_set.add(VersionedMaterials(session=s,document=doc,rev=doc.rev)) else: - session.materials.add(doc) + session.materials.versionedmaterials_set.add(VersionedMaterials(session=session,document=doc,rev=doc.rev)) # create NewRevisionDocEvent instead of uploaded, per Ole NewRevisionDocEvent.objects.create(type='new_revision', From c3f460cbe902da19cf2f9219f2a15399938f5131 Mon Sep 17 00:00:00 2001 From: Robert Sparks <rjsparks@nostrum.com> Date: Fri, 19 Sep 2014 21:33:30 +0000 Subject: [PATCH 02/18] Refactored history snippets for general use Moved from VersionedMaterials to SessionPresentation for the through table name Added the abstract and most recent presentation to the documents on the group materials page Working snapshot before building historic edu-team documents - Legacy-Id: 8349 --- ietf/doc/templatetags/ietf_filters.py | 6 +++++- ietf/group/info.py | 5 ++++- ietf/meeting/migrations/0019_version_materials.py | 6 +++--- .../migrations/0020_snapshot_material_revisions.py | 8 ++++---- ietf/meeting/models.py | 4 ++-- ietf/meeting/test_data.py | 8 ++++---- ietf/secr/proceedings/views.py | 6 +++--- ietf/templates/doc/document_history.html | 2 +- ietf/templates/group/history.html | 2 +- ietf/templates/group/materials.html | 11 ++++++++++- static/css/base2.css | 2 +- static/js/{history.js => snippet.js} | 2 +- 12 files changed, 39 insertions(+), 23 deletions(-) rename static/js/{history.js => snippet.js} (61%) diff --git a/ietf/doc/templatetags/ietf_filters.py b/ietf/doc/templatetags/ietf_filters.py index 2d03d55f4..fd9bb2df7 100644 --- a/ietf/doc/templatetags/ietf_filters.py +++ b/ietf/doc/templatetags/ietf_filters.py @@ -447,7 +447,11 @@ def format_history_text(text): if text.startswith("This was part of a ballot set with:"): full = urlize_ietf_docs(full) - full = mark_safe(keep_spacing(linebreaksbr(urlize(sanitize_html(full))))) + return format_snippet(full) + +@register.filter +def format_snippet(text): + full = mark_safe(keep_spacing(linebreaksbr(urlize(sanitize_html(text))))) snippet = truncatewords_html(full, 25) if snippet != full: return mark_safe(u'<div class="snippet">%s<span class="show-all">[show all]</span></div><div style="display:none" class="full">%s</div>' % (snippet, full)) diff --git a/ietf/group/info.py b/ietf/group/info.py index cff40b125..4beacd9e2 100644 --- a/ietf/group/info.py +++ b/ietf/group/info.py @@ -267,7 +267,8 @@ def concluded_groups(request): dict(group_types=group_types)) def get_group_materials(group): - return Document.objects.filter(group=group, type__in=group.features.material_types, session=None).exclude(states__slug="deleted") +# return Document.objects.filter(group=group, type__in=group.features.material_types, session=None).exclude(states__slug="deleted") + return Document.objects.filter(group=group, type__in=group.features.material_types).exclude(states__slug="deleted") def construct_group_menu_context(request, group, selected, group_type, others): """Return context with info for the group menu filled in.""" @@ -450,6 +451,8 @@ def materials(request, acronym, group_type=None): if d.type not in doc_types: doc_types[d.type] = [] doc_types[d.type].append(d) + # This needs to be better - probably looking at ScheduledSession, and perhaps ignoring future Sessions + d.last_presented = d.sessionpresentation_set.order_by('-session__meeting__date').first() return render(request, 'group/materials.html', construct_group_menu_context(request, group, "materials", group_type, { diff --git a/ietf/meeting/migrations/0019_version_materials.py b/ietf/meeting/migrations/0019_version_materials.py index c53ef7c8c..f699c6847 100644 --- a/ietf/meeting/migrations/0019_version_materials.py +++ b/ietf/meeting/migrations/0019_version_materials.py @@ -188,7 +188,7 @@ class Migration(SchemaMigration): 'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}), 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['group.Group']"}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'materials': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['doc.Document']", 'symmetrical': 'False', 'through': u"orm['meeting.VersionedMaterials']", 'blank': 'True'}), + 'materials': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['doc.Document']", 'symmetrical': 'False', 'through': u"orm['meeting.SessionPresentation']", 'blank': 'True'}), 'meeting': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['meeting.Meeting']"}), 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), @@ -213,8 +213,8 @@ class Migration(SchemaMigration): 'time': ('django.db.models.fields.DateTimeField', [], {}), 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.TimeSlotTypeName']"}) }, - u'meeting.versionedmaterials': { - 'Meta': {'object_name': 'VersionedMaterials', 'db_table': "'meeting_session_materials'"}, + u'meeting.sessionpresentation': { + 'Meta': {'object_name': 'SessionPresentation', 'db_table': "'meeting_session_materials'"}, 'doc': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.Document']"}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'rev': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}), diff --git a/ietf/meeting/migrations/0020_snapshot_material_revisions.py b/ietf/meeting/migrations/0020_snapshot_material_revisions.py index 088e6a8ac..ee26a3902 100644 --- a/ietf/meeting/migrations/0020_snapshot_material_revisions.py +++ b/ietf/meeting/migrations/0020_snapshot_material_revisions.py @@ -4,7 +4,7 @@ from south.v2 import DataMigration class Migration(DataMigration): def forwards(self, orm): - for vm in orm['meeting.VersionedMaterials'].objects.all(): + for vm in orm['meeting.SessionPresentation'].objects.all(): vm.rev = vm.document.rev vm.save() @@ -185,7 +185,7 @@ class Migration(DataMigration): 'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}), 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['group.Group']"}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'materials': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['doc.Document']", 'symmetrical': 'False', 'through': u"orm['meeting.VersionedMaterials']", 'blank': 'True'}), + 'materials': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['doc.Document']", 'symmetrical': 'False', 'through': u"orm['meeting.SessionPresentation']", 'blank': 'True'}), 'meeting': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['meeting.Meeting']"}), 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), @@ -210,8 +210,8 @@ class Migration(DataMigration): 'time': ('django.db.models.fields.DateTimeField', [], {}), 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.TimeSlotTypeName']"}) }, - u'meeting.versionedmaterials': { - 'Meta': {'object_name': 'VersionedMaterials', 'db_table': "'meeting_session_materials'"}, + u'meeting.sessionpresentation': { + 'Meta': {'object_name': 'SessionPresentation', 'db_table': "'meeting_session_materials'"}, 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.Document']"}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'rev': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}), diff --git a/ietf/meeting/models.py b/ietf/meeting/models.py index bb62596a0..6ac604027 100644 --- a/ietf/meeting/models.py +++ b/ietf/meeting/models.py @@ -777,7 +777,7 @@ class Constraint(models.Model): return ct1 -class VersionedMaterials(models.Model): +class SessionPresentation(models.Model): session = models.ForeignKey('Session') document = models.ForeignKey(Document) rev = models.CharField(verbose_name="revision", max_length=16, blank=True) @@ -811,7 +811,7 @@ class Session(models.Model): scheduled = models.DateTimeField(null=True, blank=True) modified = models.DateTimeField(default=datetime.datetime.now) - materials = models.ManyToManyField(Document, through=VersionedMaterials, blank=True) + materials = models.ManyToManyField(Document, through=SessionPresentation, blank=True) resources = models.ManyToManyField(ResourceAssociation) unique_constraints_dict = None diff --git a/ietf/meeting/test_data.py b/ietf/meeting/test_data.py index c568cbe21..e7a877f76 100644 --- a/ietf/meeting/test_data.py +++ b/ietf/meeting/test_data.py @@ -2,7 +2,7 @@ import datetime from ietf.doc.models import Document, State from ietf.group.models import Group -from ietf.meeting.models import Meeting, Room, TimeSlot, Session, Schedule, ScheduledSession, ResourceAssociation, VersionedMaterials +from ietf.meeting.models import Meeting, Room, TimeSlot, Session, Schedule, ScheduledSession, ResourceAssociation, SessionPresentation from ietf.name.models import RoomResourceName from ietf.person.models import Person from ietf.utils.test_data import make_test_data @@ -46,15 +46,15 @@ def make_meeting_test_data(): doc = Document.objects.create(name='agenda-mars-ietf-42', type_id='agenda', title="Agenda", external_url="agenda-mars") doc.set_state(State.objects.get(type=doc.type_id, slug="active")) - mars_session.versionedmaterials_set.add(VersionedMaterials(session=mars_session,document=doc,rev=doc.rev)) + mars_session.sessionpresentation_set.add(SessionPresentation(session=mars_session,document=doc,rev=doc.rev)) doc = Document.objects.create(name='minutes-mars-ietf-42', type_id='minutes', title="Minutes", external_url="minutes-mars") doc.set_state(State.objects.get(type=doc.type_id, slug="active")) - mars_session.versionedmaterials_set.add(VersionedMaterials(session=mars_session,document=doc,rev=doc.rev)) + mars_session.sessionpresentation_set.add(SessionPresentation(session=mars_session,document=doc,rev=doc.rev)) doc = Document.objects.create(name='slides-mars-ietf-42', type_id='slides', title="Slideshow", external_url="slides-mars") doc.set_state(State.objects.get(type=doc.type_id, slug="active")) - mars_session.versionedmaterials_set.add(VersionedMaterials(session=mars_session,document=doc,rev=doc.rev)) + mars_session.sessionpresentation_set.add(SessionPresentation(session=mars_session,document=doc,rev=doc.rev)) return meeting diff --git a/ietf/secr/proceedings/views.py b/ietf/secr/proceedings/views.py index 58636c00d..3afce1325 100644 --- a/ietf/secr/proceedings/views.py +++ b/ietf/secr/proceedings/views.py @@ -23,7 +23,7 @@ from ietf.secr.utils.meeting import get_upload_root, get_material, get_timeslot from ietf.doc.models import Document, DocAlias, DocEvent, State, NewRevisionDocEvent from ietf.group.models import Group from ietf.ietfauth.utils import has_role -from ietf.meeting.models import Meeting, Session, TimeSlot, ScheduledSession, VersionedMaterials +from ietf.meeting.models import Meeting, Session, TimeSlot, ScheduledSession, SessionPresentation from ietf.secr.proceedings.forms import EditSlideForm, InterimMeetingForm, ReplaceSlideForm, UnifiedUploadForm from ietf.secr.proceedings.proc_utils import ( gen_acknowledgement, gen_agenda, gen_areas, gen_attendees, gen_group_pages, gen_index, gen_irtf, gen_overview, gen_plenaries, gen_progress, gen_research, @@ -842,9 +842,9 @@ def upload_unified(request, meeting_num, acronym=None, session_id=None): # for the current meeting (until tools support different materials for diff sessions) if sessions: for s in sessions: - s.materials.versionedmaterials_set.add(VersionedMaterials(session=s,document=doc,rev=doc.rev)) + s.materials.sessionpresentation_set.add(SessionPresentation(session=s,document=doc,rev=doc.rev)) else: - session.materials.versionedmaterials_set.add(VersionedMaterials(session=session,document=doc,rev=doc.rev)) + session.materials.sessionpresentation_set.add(SessionPresentation(session=session,document=doc,rev=doc.rev)) # create NewRevisionDocEvent instead of uploaded, per Ole NewRevisionDocEvent.objects.create(type='new_revision', diff --git a/ietf/templates/doc/document_history.html b/ietf/templates/doc/document_history.html index ec50b9cee..c2de18b59 100644 --- a/ietf/templates/doc/document_history.html +++ b/ietf/templates/doc/document_history.html @@ -77,5 +77,5 @@ {% endblock content %} {% block content_end %} -<script type="text/javascript" src="/js/history.js"></script> +<script type="text/javascript" src="/js/snippet.js"></script> {% endblock content_end %} diff --git a/ietf/templates/group/history.html b/ietf/templates/group/history.html index 66d2b0a8d..b59871d53 100644 --- a/ietf/templates/group/history.html +++ b/ietf/templates/group/history.html @@ -22,5 +22,5 @@ {% endblock %} {% block content_end %} -<script src="/js/history.js" type="text/javascript"></script> +<script src="/js/snippet.js" type="text/javascript"></script> {% endblock %} diff --git a/ietf/templates/group/materials.html b/ietf/templates/group/materials.html index 221e00e1f..afa04ff3d 100644 --- a/ietf/templates/group/materials.html +++ b/ietf/templates/group/materials.html @@ -6,6 +6,7 @@ {% block morecss %} {{ block.super }} .materials .edit-options { float: right; margin-left: 2em; font-style: italic; } + .materials .snippable { width:25em; } {% endblock %} {% block group_content %} @@ -19,15 +20,19 @@ <tr> <th>Title</th> - <th>Rev.</th> + <th>Abstract</th> + <th>Curr. Rev.</th> <th>Date</th> + <th>Last Presented</th> </tr> {% for d in docs %} <tr class="{% cycle "evenrow" "oddrow" %}"> <td><a class="title-link" href="{% url "doc_view" name=d.name %}">{{ d.title }}</a></td> + <td class='snippable'>{{ d.abstract|format_snippet }} </td> <td>{{ d.rev }}</td> <td>{{ d.time|date:"Y-m-d" }}</td> + <td>{% if d.last_presented %}-{{ d.last_presented.rev }} at {{d.last_presented.session.meeting}}{% endif %}</td> </tr> {% endfor %} </table> @@ -39,3 +44,7 @@ {% endif %} {% endblock %} + +{% block content_end %} +<script src="/js/snippet.js" type="text/javascript"></script> +{% endblock %} diff --git a/static/css/base2.css b/static/css/base2.css index 1bd01acd8..1824c97d0 100644 --- a/static/css/base2.css +++ b/static/css/base2.css @@ -154,7 +154,7 @@ table.ietf-table { border-collapse:collapse; border:1px solid #7f7f7f; } .ietf-divider { background: #2647a0; color: white; font-size:116%; padding:0.5em 1em; } -table.history .snippet .show-all { color: blue; cursor: pointer; } +table .snippet .show-all { color: blue; cursor: pointer; } .error-text { font-size: 1.095em; diff --git a/static/js/history.js b/static/js/snippet.js similarity index 61% rename from static/js/history.js rename to static/js/snippet.js index 3b44400e6..411af9144 100644 --- a/static/js/history.js +++ b/static/js/snippet.js @@ -1,5 +1,5 @@ jQuery(function () { - jQuery("table.history .snippet .show-all").click(function () { + jQuery("table .snippet .show-all").click(function () { jQuery(this).parents(".snippet").hide().siblings(".full").show(); }); }); From 81119d6f37a3e42259eef5817ea971faa8fce9ee Mon Sep 17 00:00:00 2001 From: Robert Sparks <rjsparks@nostrum.com> Date: Tue, 23 Sep 2014 15:34:10 +0000 Subject: [PATCH 03/18] checkpoint before migrating forward to 5.6.4-dev0 - Legacy-Id: 8352 --- ietf/doc/migrations/0020_archive_slides.py | 398 +++++++++++++++++++++ ietf/doc/models.py | 9 + 2 files changed, 407 insertions(+) create mode 100644 ietf/doc/migrations/0020_archive_slides.py diff --git a/ietf/doc/migrations/0020_archive_slides.py b/ietf/doc/migrations/0020_archive_slides.py new file mode 100644 index 000000000..110b3c6fd --- /dev/null +++ b/ietf/doc/migrations/0020_archive_slides.py @@ -0,0 +1,398 @@ +# -*- coding: utf-8 -*- +from south.v2 import DataMigration + +class Migration(DataMigration): + + def set_state(self, doc, state): + ''' snapshot of DocumentInfo.set_state ''' + already_set = doc.states.filter(type=state.type) + others = [s for s in already_set if s != state] + if others: + doc.states.remove(*others) + if state not in already_set: + doc.states.add(state) + doc.state_cache = None + + def forwards(self, orm): + + orm.State.objects.filter(type='slides',slug='deleted').update(order=4) + + slidetype = orm.StateType.objects.get(slug='slides') + + orm.State.objects.create(type=slidetype, + slug='sessonly', + name='Session Only', + used=True, + desc='This document is active only for the sessions at an upcoming meeting', + order=2) + + arch = orm.State.objects.create(type=slidetype, + slug='archived', + name='Archived', + used=True, + desc='This document is not active, but is available in the archives', + order=3) + + for doc in orm.Document.objects.filter(type='slides').exclude(group__type='team'): + self.set_state(doc,arch) + + def backwards(self, orm): + + active = orm.State.objects.get(type='slides',slug='active') + for doc in orm.Document.objects.filter(type='slides',states__slug='archived').exclude(group__type='team'): + self.set_state(doc,active) + orm.State.objects.filter(type='slides',slug='deleted').update(order=2) + orm.State.objects.filter(type='slides',slug__in=['sessonly','archived']).delete() + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + u'doc.ballotdocevent': { + 'Meta': {'ordering': "['-time', '-id']", 'object_name': 'BallotDocEvent', '_ormbases': [u'doc.DocEvent']}, + 'ballot_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.BallotType']"}), + u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}) + }, + u'doc.ballotpositiondocevent': { + 'Meta': {'ordering': "['-time', '-id']", 'object_name': 'BallotPositionDocEvent', '_ormbases': [u'doc.DocEvent']}, + 'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']"}), + 'ballot': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['doc.BallotDocEvent']", 'null': 'True'}), + 'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'comment_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'discuss': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'discuss_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}), + 'pos': ('django.db.models.fields.related.ForeignKey', [], {'default': "'norecord'", 'to': u"orm['name.BallotPositionName']"}) + }, + u'doc.ballottype': { + 'Meta': {'ordering': "['order']", 'object_name': 'BallotType'}, + 'doc_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'positions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['name.BallotPositionName']", 'symmetrical': 'False', 'blank': 'True'}), + 'question': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'doc.consensusdocevent': { + 'Meta': {'ordering': "['-time', '-id']", 'object_name': 'ConsensusDocEvent', '_ormbases': [u'doc.DocEvent']}, + 'consensus': ('django.db.models.fields.NullBooleanField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), + u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}) + }, + u'doc.deletedevent': { + 'Meta': {'object_name': 'DeletedEvent'}, + 'by': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']"}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'json': ('django.db.models.fields.TextField', [], {}), + 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}) + }, + u'doc.docalias': { + 'Meta': {'object_name': 'DocAlias'}, + 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.Document']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}) + }, + u'doc.docevent': { + 'Meta': {'ordering': "['-time', '-id']", 'object_name': 'DocEvent'}, + 'by': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']"}), + 'desc': ('django.db.models.fields.TextField', [], {}), + 'doc': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.Document']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'db_index': 'True'}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'doc.dochistory': { + 'Meta': {'object_name': 'DocHistory'}, + 'abstract': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'ad': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'ad_dochistory_set'", 'null': 'True', 'to': u"orm['person.Person']"}), + 'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['person.Email']", 'symmetrical': 'False', 'through': u"orm['doc.DocHistoryAuthor']", 'blank': 'True'}), + 'doc': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'history_set'", 'to': u"orm['doc.Document']"}), + 'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'external_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}), + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['group.Group']", 'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'intended_std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.IntendedStdLevelName']", 'null': 'True', 'blank': 'True'}), + 'internal_comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'note': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'notify': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '1', 'blank': 'True'}), + 'pages': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'related': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['doc.DocAlias']", 'symmetrical': 'False', 'through': u"orm['doc.RelatedDocHistory']", 'blank': 'True'}), + 'rev': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}), + 'shepherd': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'shepherd_dochistory_set'", 'null': 'True', 'to': u"orm['person.Person']"}), + 'states': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}), + 'std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.StdLevelName']", 'null': 'True', 'blank': 'True'}), + 'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.StreamName']", 'null': 'True', 'blank': 'True'}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['name.DocTagName']", 'null': 'True', 'blank': 'True'}), + 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'}) + }, + u'doc.dochistoryauthor': { + 'Meta': {'ordering': "['document', 'order']", 'object_name': 'DocHistoryAuthor'}, + 'author': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Email']"}), + 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.DocHistory']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'order': ('django.db.models.fields.IntegerField', [], {}) + }, + u'doc.docreminder': { + 'Meta': {'object_name': 'DocReminder'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'due': ('django.db.models.fields.DateTimeField', [], {}), + 'event': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.DocEvent']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.DocReminderTypeName']"}) + }, + u'doc.document': { + 'Meta': {'object_name': 'Document'}, + 'abstract': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'ad': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'ad_document_set'", 'null': 'True', 'to': u"orm['person.Person']"}), + 'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['person.Email']", 'symmetrical': 'False', 'through': u"orm['doc.DocumentAuthor']", 'blank': 'True'}), + 'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'external_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}), + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['group.Group']", 'null': 'True', 'blank': 'True'}), + 'intended_std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.IntendedStdLevelName']", 'null': 'True', 'blank': 'True'}), + 'internal_comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'primary_key': 'True'}), + 'note': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'notify': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '1', 'blank': 'True'}), + 'pages': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'rev': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}), + 'shepherd': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'shepherd_document_set'", 'null': 'True', 'to': u"orm['person.Person']"}), + 'states': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}), + 'std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.StdLevelName']", 'null': 'True', 'blank': 'True'}), + 'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.StreamName']", 'null': 'True', 'blank': 'True'}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['name.DocTagName']", 'null': 'True', 'blank': 'True'}), + 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'}) + }, + u'doc.documentauthor': { + 'Meta': {'ordering': "['document', 'order']", 'object_name': 'DocumentAuthor'}, + 'author': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Email']"}), + 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.Document']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '1'}) + }, + u'doc.initialreviewdocevent': { + 'Meta': {'ordering': "['-time', '-id']", 'object_name': 'InitialReviewDocEvent', '_ormbases': [u'doc.DocEvent']}, + u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}), + 'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}) + }, + u'doc.lastcalldocevent': { + 'Meta': {'ordering': "['-time', '-id']", 'object_name': 'LastCallDocEvent', '_ormbases': [u'doc.DocEvent']}, + u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}), + 'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}) + }, + u'doc.newrevisiondocevent': { + 'Meta': {'ordering': "['-time', '-id']", 'object_name': 'NewRevisionDocEvent', '_ormbases': [u'doc.DocEvent']}, + u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}), + 'rev': ('django.db.models.fields.CharField', [], {'max_length': '16'}) + }, + u'doc.relateddochistory': { + 'Meta': {'object_name': 'RelatedDocHistory'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'relationship': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.DocRelationshipName']"}), + 'source': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.DocHistory']"}), + 'target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reversely_related_document_history_set'", 'to': u"orm['doc.DocAlias']"}) + }, + u'doc.relateddocument': { + 'Meta': {'object_name': 'RelatedDocument'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'relationship': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.DocRelationshipName']"}), + 'source': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.Document']"}), + 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.DocAlias']"}) + }, + u'doc.state': { + 'Meta': {'ordering': "['type', 'order']", 'object_name': 'State'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'next_states': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'previous_states'", 'blank': 'True', 'to': u"orm['doc.State']"}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}), + 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.StateType']"}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'doc.statedocevent': { + 'Meta': {'ordering': "['-time', '-id']", 'object_name': 'StateDocEvent', '_ormbases': [u'doc.DocEvent']}, + u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}), + 'state': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.State']", 'null': 'True', 'blank': 'True'}), + 'state_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.StateType']"}) + }, + u'doc.statetype': { + 'Meta': {'object_name': 'StateType'}, + 'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '30', 'primary_key': 'True'}) + }, + u'doc.telechatdocevent': { + 'Meta': {'ordering': "['-time', '-id']", 'object_name': 'TelechatDocEvent', '_ormbases': [u'doc.DocEvent']}, + u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}), + 'returning_item': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'telechat_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}) + }, + u'doc.writeupdocevent': { + 'Meta': {'ordering': "['-time', '-id']", 'object_name': 'WriteupDocEvent', '_ormbases': [u'doc.DocEvent']}, + u'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}), + 'text': ('django.db.models.fields.TextField', [], {'blank': 'True'}) + }, + u'group.group': { + 'Meta': {'object_name': 'Group'}, + 'acronym': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '40'}), + 'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']", 'null': 'True', 'blank': 'True'}), + 'charter': ('django.db.models.fields.related.OneToOneField', [], {'blank': 'True', 'related_name': "'chartered_group'", 'unique': 'True', 'null': 'True', 'to': u"orm['doc.Document']"}), + 'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'list_archive': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'list_email': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), + 'list_subscribe': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['group.Group']", 'null': 'True', 'blank': 'True'}), + 'state': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.GroupStateName']", 'null': 'True'}), + 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.GroupTypeName']", 'null': 'True'}), + 'unused_states': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}), + 'unused_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['name.DocTagName']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'name.ballotpositionname': { + 'Meta': {'ordering': "['order']", 'object_name': 'BallotPositionName'}, + 'blocking': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.docrelationshipname': { + 'Meta': {'ordering': "['order']", 'object_name': 'DocRelationshipName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'revname': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.docremindertypename': { + 'Meta': {'ordering': "['order']", 'object_name': 'DocReminderTypeName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.doctagname': { + 'Meta': {'ordering': "['order']", 'object_name': 'DocTagName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.doctypename': { + 'Meta': {'ordering': "['order']", 'object_name': 'DocTypeName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.groupstatename': { + 'Meta': {'ordering': "['order']", 'object_name': 'GroupStateName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.grouptypename': { + 'Meta': {'ordering': "['order']", 'object_name': 'GroupTypeName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.intendedstdlevelname': { + 'Meta': {'ordering': "['order']", 'object_name': 'IntendedStdLevelName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.stdlevelname': { + 'Meta': {'ordering': "['order']", 'object_name': 'StdLevelName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.streamname': { + 'Meta': {'ordering': "['order']", 'object_name': 'StreamName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'person.email': { + 'Meta': {'object_name': 'Email'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'address': ('django.db.models.fields.CharField', [], {'max_length': '64', 'primary_key': 'True'}), + 'person': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']", 'null': 'True'}), + 'time': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}) + }, + u'person.person': { + 'Meta': {'object_name': 'Person'}, + 'address': ('django.db.models.fields.TextField', [], {'max_length': '255', 'blank': 'True'}), + 'affiliation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'ascii': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'ascii_short': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['auth.User']", 'unique': 'True', 'null': 'True', 'blank': 'True'}) + } + } + + complete_apps = ['doc'] + symmetrical = True diff --git a/ietf/doc/models.py b/ietf/doc/models.py index 8fd884866..5ff1c6fa8 100644 --- a/ietf/doc/models.py +++ b/ietf/doc/models.py @@ -171,6 +171,15 @@ class DocumentInfo(models.Model): return None def meeting_related(self): + if self.type_id in ("agenda","minutes",): + return (self.name.split("-")[1] == "interim" + or (self.session_set.exists() if isinstance(self, Document) else self.doc.session_set.exists())) + elif self.type_id in ("slides",): + return (self.name.split("-")[1] == "interim" + or (self.get_state('slides') in ("sessonly","archived") )) + else: + return False + return(self.type_id in ("agenda", "minutes", "slides") and ( self.name.split("-")[1] == "interim" or (self.session_set.exists() if isinstance(self, Document) else self.doc.session_set.exists()))) From 754ee8001655765f0643107a0aab66825807a8df Mon Sep 17 00:00:00 2001 From: Robert Sparks <rjsparks@nostrum.com> Date: Fri, 26 Sep 2014 20:47:13 +0000 Subject: [PATCH 04/18] snapshot before SIPit - have a working session presentation edit form - Legacy-Id: 8358 --- ietf/doc/models.py | 18 +++++++ ietf/doc/urls_material.py | 1 + ietf/doc/views_doc.py | 4 ++ ietf/doc/views_material.py | 54 +++++++++++++++++++ ietf/group/info.py | 4 +- ietf/templates/doc/document_material.html | 25 +++++++++ .../doc/material/material_presentations.html | 23 ++++++++ ietf/templates/group/materials.html | 4 +- 8 files changed, 129 insertions(+), 4 deletions(-) create mode 100644 ietf/templates/doc/material/material_presentations.html diff --git a/ietf/doc/models.py b/ietf/doc/models.py index 5ff1c6fa8..d80feaf8c 100644 --- a/ietf/doc/models.py +++ b/ietf/doc/models.py @@ -184,6 +184,24 @@ class DocumentInfo(models.Model): self.name.split("-")[1] == "interim" or (self.session_set.exists() if isinstance(self, Document) else self.doc.session_set.exists()))) + def future_presentations(self): + """ returns related SessionPresentation objects for meetings that + have not yet ended. This implementation allows for 2 week meetings """ + candidate_presentations = self.sessionpresentation_set.filter(session__meeting__date__gte=datetime.date.today()-datetime.timedelta(days=15)) + return [pres for pres in candidate_presentations if pres.session.meeting.end_date()>=datetime.date.today()] + + def last_presented(self): + """ returns related SessionPresentation objects for the most recent meeting in the past""" + # Assumes no two meetings have the same start date - if the assumption is violated, one will be chosen arbitrariy + candidate_presentations = self.sessionpresentation_set.filter(session__meeting__date__lte=datetime.date.today()) + candidate_meetings = set([p.session.meeting for p in candidate_presentations if p.session.meeting.end_date()<datetime.date.today()]) + if candidate_meetings: + mtg = sorted(list(candidate_meetings),key=lambda x:x.date,reverse=True)[0] + return self.sessionpresentation_set.filter(session__meeting=mtg) + else: + return None + + class Meta: abstract = True diff --git a/ietf/doc/urls_material.py b/ietf/doc/urls_material.py index 01aa922fd..32272cbd5 100644 --- a/ietf/doc/urls_material.py +++ b/ietf/doc/urls_material.py @@ -2,5 +2,6 @@ from django.conf.urls import patterns, url urlpatterns = patterns('ietf.doc.views_material', url(r'^(?P<action>state|title|revise)/$', "edit_material", name="material_edit"), + url(r'^sessions/$', "material_presentations", name="material_presentations"), ) diff --git a/ietf/doc/views_doc.py b/ietf/doc/views_doc.py index d3756c733..dd163cc29 100644 --- a/ietf/doc/views_doc.py +++ b/ietf/doc/views_doc.py @@ -493,6 +493,9 @@ def document_main(request, name, rev=None): if doc.type_id in ("slides", "agenda", "minutes"): can_manage_material = can_manage_materials(request.user, doc.group) + presentations = None + if doc.type_id=='slides' and doc.get_state_slug('slides') in ['sessonly','active']: + presentations = doc.future_presentations() if doc.meeting_related(): # disallow editing meeting-related stuff through this # interface for the time being @@ -530,6 +533,7 @@ def document_main(request, name, rev=None): snapshot=snapshot, can_manage_material=can_manage_material, other_types=other_types, + presentations=presentations, ), context_instance=RequestContext(request)) diff --git a/ietf/doc/views_material.py b/ietf/doc/views_material.py index d7e75c587..ac71c0cc9 100644 --- a/ietf/doc/views_material.py +++ b/ietf/doc/views_material.py @@ -17,6 +17,7 @@ from ietf.doc.models import NewRevisionDocEvent, save_document_in_history from ietf.doc.utils import add_state_change_event, check_common_doc_name_rules from ietf.group.models import Group from ietf.group.utils import can_manage_materials +from ietf.meeting.models import Session @login_required def choose_material_type(request, acronym): @@ -168,3 +169,56 @@ def edit_material(request, name=None, acronym=None, action=None, doc_type=None): 'document_type': document_type, 'doc_name': doc.name if doc else "", }) + +class MaterialPresentationForm(forms.Form): + + sesspres = forms.MultipleChoiceField(required=False,widget=forms.CheckboxSelectMultiple,label='Place this document on the agenda for the selected sessions') + + def __init__(self,*args,**kwargs): + choices = kwargs.pop('choices') + super(MaterialPresentationForm,self).__init__(*args,**kwargs) + self.fields['sesspres'].choices=choices + +@login_required +def material_presentations(request, name): + + doc = get_object_or_404(Document, name=name) + if not (doc.type_id=='slides' and doc.get_state('slides').slug=='active'): + raise Http404 + + group = doc.group + if not (group.features.has_materials and can_manage_materials(request.user,group)): + raise Http404 + + # Find all the sessions for meetings that haven't ended that the user could affect + # This motif is also in Document.future_presentations - it would be nice to consolodate it somehow + candidate_sessions = Session.objects.filter(meeting__date__gte=datetime.date.today()-datetime.timedelta(days=15)) + refined_candidates = [ sess for sess in candidate_sessions if sess.meeting.end_date()>=datetime.date.today()] + changeable_sessions = [ sess for sess in refined_candidates if can_manage_materials(request.user, sess.group) ] + for sess in changeable_sessions: + sess.has_presentation = sess.sessionpresentation_set.filter(document=doc) + sorted_sessions = sorted(changeable_sessions,key=lambda x:'%s%s%s'%('0' if x.has_presentation else '1',x.meeting,x.short_name)) + + choices=[(sess.pk,'%s: %s'%(sess.meeting,sess.short_name)) for sess in sorted_sessions] + initial = {'sesspres': [sess.pk for sess in sorted_sessions if sess.has_presentation]} + + if request.method == 'POST': + form = MaterialPresentationForm(request.POST,choices=choices) + if form.is_valid(): + print "STUFF",request.POST.get("action","nothing to be gotten") + if request.POST.get("action", "") == "Save": + new_selections = form.cleaned_data['sesspres'] + doc.sessionpresentation_set.filter(session_id__in=(set(initial['sesspres'])-set(new_selections))).delete() + for sess_pk in set(new_selections)-set(initial['sesspres']): + doc.sessionpresentation_set.create(session_id=sess_pk,rev=doc.rev) + return redirect('doc_view',name=doc.name) + else: + form = MaterialPresentationForm(choices=choices, + initial=initial, + ) + + return render(request, 'doc/material/material_presentations.html', { + 'sessions' : sorted_sessions, + 'doc': doc, + 'form': form, + }) diff --git a/ietf/group/info.py b/ietf/group/info.py index 4beacd9e2..8030a1af5 100644 --- a/ietf/group/info.py +++ b/ietf/group/info.py @@ -268,7 +268,7 @@ def concluded_groups(request): def get_group_materials(group): # return Document.objects.filter(group=group, type__in=group.features.material_types, session=None).exclude(states__slug="deleted") - return Document.objects.filter(group=group, type__in=group.features.material_types).exclude(states__slug="deleted") + return Document.objects.filter(group=group, type__in=group.features.material_types).exclude(states__slug__in=['deleted','archived']) def construct_group_menu_context(request, group, selected, group_type, others): """Return context with info for the group menu filled in.""" @@ -451,8 +451,6 @@ def materials(request, acronym, group_type=None): if d.type not in doc_types: doc_types[d.type] = [] doc_types[d.type].append(d) - # This needs to be better - probably looking at ScheduledSession, and perhaps ignoring future Sessions - d.last_presented = d.sessionpresentation_set.order_by('-session__meeting__date').first() return render(request, 'group/materials.html', construct_group_menu_context(request, group, "materials", group_type, { diff --git a/ietf/templates/doc/document_material.html b/ietf/templates/doc/document_material.html index e1d13b40c..5c27972d5 100644 --- a/ietf/templates/doc/document_material.html +++ b/ietf/templates/doc/document_material.html @@ -26,6 +26,13 @@ </td> </tr> + {% if doc.abstract %} + <tr> + <td>Abstract:</td> + <td> {{ doc.abstract | format_snippet }} </td> + </tr> + {% endif %} + <tr> <td>State:</td> <td> @@ -44,6 +51,21 @@ </tr> {% endif %} + {% if presentations or can_manage_material %} + <tr> + <td>On Agenda:</td> + <td> + <a {% if not snapshot and can_manage_material %} class="editlink" href="{% url "material_presentations" name=doc.name %}"{%endif%}> + {% if presentations %} + {% for pres in presentations %}{{pres.session.short_name}} at {{pres.session.meeting}} {% if pres.rev != doc.rev %}(version -{{pres.rev}}){% endif %}{% if not forloop.last %}, {% endif %}{% endfor %} + {% else %} + None + {% endif %} + </a> + </td> + </tr> + {% endif %} + <tr> <td>Last updated:</td> <td>{{ doc.time|date:"Y-m-d" }}</td> @@ -74,3 +96,6 @@ {% endblock %} +{% block content_end %} +<script src="/js/snippet.js" type="text/javascript"></script> +{% endblock %} diff --git a/ietf/templates/doc/material/material_presentations.html b/ietf/templates/doc/material/material_presentations.html new file mode 100644 index 000000000..e7196819e --- /dev/null +++ b/ietf/templates/doc/material/material_presentations.html @@ -0,0 +1,23 @@ +{% extends "base.html" %} + +{% block title %} +Edit Upcoming Presentations +{% endblock %} + +{% block morecss %} +{{ block.super }} +ul#id_sesspres { list-style-type: none; padding: 0px; margin: 0px; } +{% endblock %} + +{% block content %} +{% load ietf_filters %} + +<h1>Edit Upcoming Presentations of<br/>{{doc.title}}<br/>{{doc.name}}</h1> + +<form class="session-presentations" action="" method="post">{% csrf_token %} +{{form.as_p}} +<input style="button" type="submit" name="action" value="Save"> +<input style="button" type="submit" name="action" value="Cancel"> +</form> + +{% endblock content %} diff --git a/ietf/templates/group/materials.html b/ietf/templates/group/materials.html index afa04ff3d..1c3f709c6 100644 --- a/ietf/templates/group/materials.html +++ b/ietf/templates/group/materials.html @@ -24,6 +24,7 @@ <th>Curr. Rev.</th> <th>Date</th> <th>Last Presented</th> + <th>On Agenda</th> </tr> {% for d in docs %} @@ -32,7 +33,8 @@ <td class='snippable'>{{ d.abstract|format_snippet }} </td> <td>{{ d.rev }}</td> <td>{{ d.time|date:"Y-m-d" }}</td> - <td>{% if d.last_presented %}-{{ d.last_presented.rev }} at {{d.last_presented.session.meeting}}{% endif %}</td> + <td>{% for p in d.last_presented %}{{p.session.meeting}}{% if d.rev != p.rev %} (-{{ p.rev }}){% endif %}{%if not forloop.last%}, {% endif %}{% endfor %}</td> + <td>{% for p in d.future_presentations %}{{p.session.meeting}}{% if d.rev != p.rev %} (-{{p.rev}}){%endif%}{%if not forloop.last%}, {%endif%}{%endfor%}</td> </tr> {% endfor %} </table> From b86d5c1d09966c1e3a20981a73cb7e0f9f3857b7 Mon Sep 17 00:00:00 2001 From: Robert Sparks <rjsparks@nostrum.com> Date: Thu, 16 Oct 2014 16:01:16 +0000 Subject: [PATCH 05/18] renumber migration to resolve prefix collision after merge - Legacy-Id: 8433 --- .../migrations/{0020_archive_slides.py => 0021_archive_slides.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename ietf/doc/migrations/{0020_archive_slides.py => 0021_archive_slides.py} (100%) diff --git a/ietf/doc/migrations/0020_archive_slides.py b/ietf/doc/migrations/0021_archive_slides.py similarity index 100% rename from ietf/doc/migrations/0020_archive_slides.py rename to ietf/doc/migrations/0021_archive_slides.py From 2f56de622386ccbcc9de3a6faecef8b701fa490f Mon Sep 17 00:00:00 2001 From: Robert Sparks <rjsparks@nostrum.com> Date: Thu, 16 Oct 2014 16:27:51 +0000 Subject: [PATCH 06/18] added abstract to the upload form - Legacy-Id: 8434 --- ietf/doc/views_material.py | 4 ++++ ietf/templates/doc/material/edit_material.html | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ietf/doc/views_material.py b/ietf/doc/views_material.py index ac71c0cc9..26b031b14 100644 --- a/ietf/doc/views_material.py +++ b/ietf/doc/views_material.py @@ -33,6 +33,7 @@ def choose_material_type(request, acronym): class UploadMaterialForm(forms.Form): title = forms.CharField(max_length=Document._meta.get_field("title").max_length) name = forms.CharField(max_length=Document._meta.get_field("name").max_length) + abstract = forms.CharField(max_length=Document._meta.get_field("abstract").max_length,widget=forms.Textarea) state = forms.ModelChoiceField(State.objects.all(), empty_label=None) material = forms.FileField(label='File', help_text="PDF or text file (ASCII/UTF-8)") @@ -121,6 +122,9 @@ def edit_material(request, name=None, acronym=None, action=None, doc_type=None): if "title" in form.cleaned_data: doc.title = form.cleaned_data["title"] + if "abstract" in form.cleaned_data: + doc.abstract = form.cleaned_data["abstract"] + doc.time = datetime.datetime.now() if "material" in form.fields: diff --git a/ietf/templates/doc/material/edit_material.html b/ietf/templates/doc/material/edit_material.html index 735761e50..cd20331ca 100644 --- a/ietf/templates/doc/material/edit_material.html +++ b/ietf/templates/doc/material/edit_material.html @@ -5,7 +5,7 @@ {% block morecss %} {{ block.super }} form.upload-material td { padding-bottom: 0.6em; } -form.upload-material #id_title, form.upload-material #id_name { width: 30em; } +form.upload-material #id_title, form.upload-material #id_name, form.upload-material #id_abstract { width: 30em; } form.upload-material .submit-row td { padding-top: 1em; text-align: right; } {% endblock %} From 31f687b343b9eb2014d916bfb4016090ab168dad Mon Sep 17 00:00:00 2001 From: Robert Sparks <rjsparks@nostrum.com> Date: Thu, 16 Oct 2014 16:46:38 +0000 Subject: [PATCH 07/18] allow editing of abstract for existing material - Legacy-Id: 8435 --- ietf/doc/urls_material.py | 2 +- ietf/doc/views_material.py | 10 ++++------ ietf/templates/doc/document_material.html | 6 +++++- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/ietf/doc/urls_material.py b/ietf/doc/urls_material.py index 32272cbd5..22cf0de6c 100644 --- a/ietf/doc/urls_material.py +++ b/ietf/doc/urls_material.py @@ -1,7 +1,7 @@ from django.conf.urls import patterns, url urlpatterns = patterns('ietf.doc.views_material', - url(r'^(?P<action>state|title|revise)/$', "edit_material", name="material_edit"), + url(r'^(?P<action>state|title|abstract|revise)/$', "edit_material", name="material_edit"), url(r'^sessions/$', "material_presentations", name="material_presentations"), ) diff --git a/ietf/doc/views_material.py b/ietf/doc/views_material.py index 26b031b14..9ddcf6b0e 100644 --- a/ietf/doc/views_material.py +++ b/ietf/doc/views_material.py @@ -55,16 +55,14 @@ class UploadMaterialForm(forms.Form): del self.fields["name"] self.fields["title"].initial = doc.title + self.fields["abstract"].initial = doc.abstract self.fields["state"].initial = doc.get_state().pk if doc.get_state() else None if doc.get_state_slug() == "deleted": self.fields["state"].help_text = "Note: If you wish to revise this document, you may wish to change the state so it's not deleted." - if action == "title": - del self.fields["state"] - del self.fields["material"] - elif action == "state": - del self.fields["title"] - del self.fields["material"] + for fieldname in ["title","state","material","abstract"]: + if fieldname != action: + del self.fields[fieldname] def clean_name(self): name = self.cleaned_data["name"].strip().rstrip("-") diff --git a/ietf/templates/doc/document_material.html b/ietf/templates/doc/document_material.html index 5c27972d5..be36ed394 100644 --- a/ietf/templates/doc/document_material.html +++ b/ietf/templates/doc/document_material.html @@ -29,7 +29,11 @@ {% if doc.abstract %} <tr> <td>Abstract:</td> - <td> {{ doc.abstract | format_snippet }} </td> + <td> + <a {% if not snapshot and can_manage_material %} class="editlink" href="{% url "material_edit" name=doc.name action="abstract" name=doc.name %}"{% endif %}> + {{ doc.abstract | format_snippet }} + </a> + </td> </tr> {% endif %} From 7e60f910d4ee89267fecf51ec9bbbae3f460586f Mon Sep 17 00:00:00 2001 From: Robert Sparks <rjsparks@nostrum.com> Date: Thu, 16 Oct 2014 17:39:52 +0000 Subject: [PATCH 08/18] rework filters to avoid conflict in editing vs showing all - Legacy-Id: 8436 --- ietf/doc/templatetags/ietf_filters.py | 13 +++++++++++++ ietf/templates/doc/document_material.html | 7 +++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/ietf/doc/templatetags/ietf_filters.py b/ietf/doc/templatetags/ietf_filters.py index da342e785..404e73313 100644 --- a/ietf/doc/templatetags/ietf_filters.py +++ b/ietf/doc/templatetags/ietf_filters.py @@ -458,6 +458,19 @@ def format_snippet(text): return mark_safe(u'<div class="snippet">%s<span class="show-all">[show all]</span></div><div style="display:none" class="full">%s</div>' % (snippet, full)) return full +@register.filter +def format_editable_snippet(text,link): + full = mark_safe(keep_spacing(linebreaksbr(urlize(sanitize_html(text))))) + snippet = truncatewords_html(full, 25) + if snippet != full: + return mark_safe(u'<div class="snippet">%s<span class="show-all">[show all]</span></div><div style="display:none" class="full">%s' % (format_editable(snippet,link),format_editable(full,link)) ) + else: + return format_editable(full,link) + +@register.filter +def format_editable(text,link): + return mark_safe(u'<a class="editlink" href="%s">%s</a>' % (link,text)) + @register.filter def textify(text): text = re.sub("</?b>", "*", text) diff --git a/ietf/templates/doc/document_material.html b/ietf/templates/doc/document_material.html index be36ed394..d1b87c340 100644 --- a/ietf/templates/doc/document_material.html +++ b/ietf/templates/doc/document_material.html @@ -30,9 +30,12 @@ <tr> <td>Abstract:</td> <td> - <a {% if not snapshot and can_manage_material %} class="editlink" href="{% url "material_edit" name=doc.name action="abstract" name=doc.name %}"{% endif %}> + {% if not snapshot and can_manage_material %} + {% url "material_edit" name=doc.name action="abstract" as editurl %} + {{ doc.abstract | format_editable_snippet:editurl }} + {% else %} {{ doc.abstract | format_snippet }} - </a> + {% endif %} </td> </tr> {% endif %} From 0db5b308c92ddb4aaa20d807a919dded6bbfb49a Mon Sep 17 00:00:00 2001 From: Robert Sparks <rjsparks@nostrum.com> Date: Thu, 16 Oct 2014 17:58:45 +0000 Subject: [PATCH 09/18] take advantage of new filters to simplify page a little - Legacy-Id: 8437 --- ietf/templates/doc/document_material.html | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/ietf/templates/doc/document_material.html b/ietf/templates/doc/document_material.html index d1b87c340..0b7b070f9 100644 --- a/ietf/templates/doc/document_material.html +++ b/ietf/templates/doc/document_material.html @@ -22,7 +22,12 @@ <tr> <td>Title:</td> <td> - <a {% if not snapshot and can_manage_material %} class="editlink" href="{% url "material_edit" name=doc.name action="title" name=doc.name %}"{% endif %}>{{ doc.title }}</a> + {% if not snapshot and can_manage_material %} + {% url "material_edit" name=doc.name action="title" as editurl %} + {{ doc.title | format_editable:editurl }} + {% else %} + {{ doc.title }} + {% endif %} </td> </tr> @@ -43,7 +48,12 @@ <tr> <td>State:</td> <td> - <a title="{{ doc.get_state.desc }}"{% if not snapshot and can_manage_material %} class="editlink" href="{% url "material_edit" name=doc.name action="state" %}"{% endif %}>{{ doc.get_state.name }}</a> + {% if not snapshot and can_manage_material %} + {% url "material_edit" name=doc.name action="state" as editurl %} + {{ doc.get_state.name | format_editable:editurl }} + {% else %} + {{ doc.get_state.name }} + {% endif %} </td> </tr> @@ -65,9 +75,9 @@ <a {% if not snapshot and can_manage_material %} class="editlink" href="{% url "material_presentations" name=doc.name %}"{%endif%}> {% if presentations %} {% for pres in presentations %}{{pres.session.short_name}} at {{pres.session.meeting}} {% if pres.rev != doc.rev %}(version -{{pres.rev}}){% endif %}{% if not forloop.last %}, {% endif %}{% endfor %} - {% else %} + {% else %} None - {% endif %} + {% endif %} </a> </td> </tr> From 9a46f471685804515f19104f29e03f914cc61d0c Mon Sep 17 00:00:00 2001 From: Robert Sparks <rjsparks@nostrum.com> Date: Thu, 16 Oct 2014 18:58:13 +0000 Subject: [PATCH 10/18] fix diffable bug, improve form grooming, remove too restrictive help text from form - Legacy-Id: 8439 --- ietf/doc/views_doc.py | 2 +- ietf/doc/views_material.py | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/ietf/doc/views_doc.py b/ietf/doc/views_doc.py index 1586aabc5..afefe11b8 100644 --- a/ietf/doc/views_doc.py +++ b/ietf/doc/views_doc.py @@ -549,7 +549,7 @@ def document_history(request, name): diff_revisions = [] diffable = [ name.startswith(prefix) for prefix in ["rfc", "draft", "charter", "conflict-review", "status-change", ]] - if diffable: + if any(diffable): diff_documents = [ doc ] diff_documents.extend(Document.objects.filter(docalias__relateddocument__source=doc, docalias__relateddocument__relationship="replaces")) diff --git a/ietf/doc/views_material.py b/ietf/doc/views_material.py index 9ddcf6b0e..4ccd1d175 100644 --- a/ietf/doc/views_material.py +++ b/ietf/doc/views_material.py @@ -35,7 +35,7 @@ class UploadMaterialForm(forms.Form): name = forms.CharField(max_length=Document._meta.get_field("name").max_length) abstract = forms.CharField(max_length=Document._meta.get_field("abstract").max_length,widget=forms.Textarea) state = forms.ModelChoiceField(State.objects.all(), empty_label=None) - material = forms.FileField(label='File', help_text="PDF or text file (ASCII/UTF-8)") + material = forms.FileField(label='File') def __init__(self, doc_type, action, group, doc, *args, **kwargs): super(UploadMaterialForm, self).__init__(*args, **kwargs) @@ -60,9 +60,10 @@ class UploadMaterialForm(forms.Form): if doc.get_state_slug() == "deleted": self.fields["state"].help_text = "Note: If you wish to revise this document, you may wish to change the state so it's not deleted." - for fieldname in ["title","state","material","abstract"]: - if fieldname != action: - del self.fields[fieldname] + if action in ["title","state","abstract"]: + for fieldname in ["title","state","material","abstract"]: + if fieldname != action: + del self.fields[fieldname] def clean_name(self): name = self.cleaned_data["name"].strip().rstrip("-") From 2f6799ece6b3f1928a0ce825533d30aa1f692cfc Mon Sep 17 00:00:00 2001 From: Robert Sparks <rjsparks@nostrum.com> Date: Tue, 21 Oct 2014 21:16:27 +0000 Subject: [PATCH 11/18] Have working selectors for sessions related to a meeting and sessions related to a document, views for listing such sections that can be edited, and an edit form for changing the presented version. Checkpointing before big refactor to move the URI components around - Legacy-Id: 8453 --- ietf/doc/tests_material.py | 2 + ietf/doc/urls_material.py | 6 + ietf/doc/views_material.py | 121 +++++++++++++----- ietf/meeting/models.py | 6 +- ietf/meeting/urls.py | 7 + ietf/meeting/views.py | 63 ++++++++- .../doc/material/material_presentations.html | 29 +++-- 7 files changed, 189 insertions(+), 45 deletions(-) diff --git a/ietf/doc/tests_material.py b/ietf/doc/tests_material.py index 7fe5216ad..07072ea93 100644 --- a/ietf/doc/tests_material.py +++ b/ietf/doc/tests_material.py @@ -66,6 +66,7 @@ class GroupMaterialTests(TestCase): # post r = self.client.post(url, dict(title="Test File - with fancy title", + abstract = "Test Abstract", name="slides-%s-test-file" % group.acronym, state=State.objects.get(type="slides", slug="active").pk, material=test_file)) @@ -125,6 +126,7 @@ class GroupMaterialTests(TestCase): # post r = self.client.post(url, dict(title="New title", + abstract="New abstract", state=State.objects.get(type="slides", slug="active").pk, material=test_file)) self.assertEqual(r.status_code, 302) diff --git a/ietf/doc/urls_material.py b/ietf/doc/urls_material.py index 22cf0de6c..09e2645bd 100644 --- a/ietf/doc/urls_material.py +++ b/ietf/doc/urls_material.py @@ -3,5 +3,11 @@ from django.conf.urls import patterns, url urlpatterns = patterns('ietf.doc.views_material', url(r'^(?P<action>state|title|abstract|revise)/$', "edit_material", name="material_edit"), url(r'^sessions/$', "material_presentations", name="material_presentations"), + (r'^sessions/(?P<seq>\d+)/$', "material_presentations"), + (r'^sessions/(?P<acronym>[A-Za-z0-9_\-\+]+)/$', "material_presentations"), + (r'^sessions/(?P<acronym>[A-Za-z0-9_\-\+]+)/(?P<seq>\d+)/$', "material_presentations"), + (r'^sessions/(?P<acronym>[A-Za-z0-9_\-\+]+)/(?P<week_day>[a-zA-Z]+)/$', "material_presentations"), + (r'^sessions/(?P<acronym>[A-Za-z0-9_\-\+]+)/(?P<date>\d{4}-\d{2}-\d{2}(-\d{4})?)/$', "material_presentations"), + (r'^sessions/(?P<acronym>[A-Za-z0-9_\-\+]+)/(?P<date>\d{4}-\d{2}-\d{2}(-\d{4})?)/(?P<seq>\d+)/$', "material_presentations"), ) diff --git a/ietf/doc/views_material.py b/ietf/doc/views_material.py index 4ccd1d175..10a73130d 100644 --- a/ietf/doc/views_material.py +++ b/ietf/doc/views_material.py @@ -173,17 +173,18 @@ def edit_material(request, name=None, acronym=None, action=None, doc_type=None): 'doc_name': doc.name if doc else "", }) -class MaterialPresentationForm(forms.Form): +class MaterialVersionForm(forms.Form): - sesspres = forms.MultipleChoiceField(required=False,widget=forms.CheckboxSelectMultiple,label='Place this document on the agenda for the selected sessions') + version = forms.ChoiceField(required=False, + label='Which version of this document will be presented at this session') - def __init__(self,*args,**kwargs): + def __init__(self, *args, **kwargs): choices = kwargs.pop('choices') - super(MaterialPresentationForm,self).__init__(*args,**kwargs) - self.fields['sesspres'].choices=choices + super(MaterialVersionForm,self).__init__(*args,**kwargs) + self.fields['version'].choices = choices @login_required -def material_presentations(request, name): +def material_presentations(request, name, acronym=None, date=None, seq=None, week_day=None): doc = get_object_or_404(Document, name=name) if not (doc.type_id=='slides' and doc.get_state('slides').slug=='active'): @@ -197,31 +198,93 @@ def material_presentations(request, name): # This motif is also in Document.future_presentations - it would be nice to consolodate it somehow candidate_sessions = Session.objects.filter(meeting__date__gte=datetime.date.today()-datetime.timedelta(days=15)) refined_candidates = [ sess for sess in candidate_sessions if sess.meeting.end_date()>=datetime.date.today()] + + if acronym: + refined_candidates = [ sess for sess in refined_candidates if sess.group.acronym==acronym] + + if date: + if len(date)==15: + start = datetime.datetime.strptime(date,"%Y-%m-%d-%H%M") + refined_candidates = [ sess for sess in refined_candidates if sess.scheduledsession_set.filter(schedule=sess.meeting.agenda,timeslot__time=start) ] + else: + start = datetime.datetime.strptime(date,"%Y-%m-%d").date() + end = start+datetime.timedelta(days=1) + refined_candidates = [ sess for sess in refined_candidates if sess.scheduledsession_set.filter(schedule=sess.meeting.agenda,timeslot__time__range=(start,end)) ] + + if week_day: + try: + dow = ['sun','mon','tue','wed','thu','fri','sat'].index(week_day.lower()[:3]) + 1 + except ValueError: + raise Http404 + refined_candidates = [ sess for sess in refined_candidates if sess.scheduledsession_set.filter(schedule=sess.meeting.agenda,timeslot__time__week_day=dow) ] + changeable_sessions = [ sess for sess in refined_candidates if can_manage_materials(request.user, sess.group) ] + + if not changeable_sessions: + raise Http404 + for sess in changeable_sessions: - sess.has_presentation = sess.sessionpresentation_set.filter(document=doc) - sorted_sessions = sorted(changeable_sessions,key=lambda x:'%s%s%s'%('0' if x.has_presentation else '1',x.meeting,x.short_name)) + sess.has_presentation = bool(sess.sessionpresentation_set.filter(document=doc)) + if sess.has_presentation: + sess.version = sess.sessionpresentation_set.get(document=doc).rev - choices=[(sess.pk,'%s: %s'%(sess.meeting,sess.short_name)) for sess in sorted_sessions] - initial = {'sesspres': [sess.pk for sess in sorted_sessions if sess.has_presentation]} + # Since Python 2.2 sorts are stable, so this series results in a list sorted first by whether + # the session has any presentations, then by the meeting 'number', then by session's group + # acronym, then by scheduled time (or the time of the session request if the session isn't + # scheduled). + + def time_sort_key(session): + official_sessions = session.scheduledsession_set.filter(schedule=session.meeting.agenda) + if official_sessions: + return official_sessions.first().timeslot.time + else: + return session.requested + + time_sorted = sorted(changeable_sessions,key=time_sort_key) + acronym_sorted = sorted(time_sorted,key=lambda x: x.group.acronym) + meeting_sorted = sorted(acronym_sorted,key=lambda x: x.meeting.number) + sorted_sessions = sorted(meeting_sorted,key=lambda x: '0' if x.has_presentation else '1') + + if seq: + iseq = int(seq) - 1 + if not iseq in range(0,len(sorted_sessions)): + raise Http404 + else: + sorted_sessions = [sorted_sessions[iseq]] + + for index,session in enumerate(sorted_sessions): + session.sequence = index+1 + + if len(sorted_sessions)==1: + session = sorted_sessions[0] + choices = [('notpresented','Not Presented')] + choices.extend([(x,x) for x in doc.docevent_set.filter(type='new_revision').values_list('newrevisiondocevent__rev',flat=True)]) + initial = {'version' : session.version if hasattr(session,'version') else 'notpresented'} + + if request.method == 'POST': + form = MaterialVersionForm(request.POST,choices=choices) + if form.is_valid(): + if request.POST.get("action", "") == "Save": + new_selection = form.cleaned_data['version'] + if initial['version'] != new_selection: + if initial['version'] == 'notpresented': + doc.sessionpresentation_set.create(session=session,rev=new_selection) + elif new_selection == 'notpresented': + doc.sessionpresentation_set.filter(session=session).delete() + else: + doc.sessionpresentation_set.filter(session=session).update(rev=new_selection) + return redirect('doc_view',name=doc.name) + else: + form = MaterialVersionForm(choices=choices,initial=initial) + + return render(request, 'doc/material/edit_material_presentations.html', { + 'session': session, + 'doc': doc, + 'form': form, + }) - if request.method == 'POST': - form = MaterialPresentationForm(request.POST,choices=choices) - if form.is_valid(): - print "STUFF",request.POST.get("action","nothing to be gotten") - if request.POST.get("action", "") == "Save": - new_selections = form.cleaned_data['sesspres'] - doc.sessionpresentation_set.filter(session_id__in=(set(initial['sesspres'])-set(new_selections))).delete() - for sess_pk in set(new_selections)-set(initial['sesspres']): - doc.sessionpresentation_set.create(session_id=sess_pk,rev=doc.rev) - return redirect('doc_view',name=doc.name) else: - form = MaterialPresentationForm(choices=choices, - initial=initial, - ) - - return render(request, 'doc/material/material_presentations.html', { - 'sessions' : sorted_sessions, - 'doc': doc, - 'form': form, - }) + return render(request, 'doc/material/material_presentations.html', { + 'sessions' : sorted_sessions, + 'doc': doc, + }) diff --git a/ietf/meeting/models.py b/ietf/meeting/models.py index 1c6f035c5..5fe9adbbe 100644 --- a/ietf/meeting/models.py +++ b/ietf/meeting/models.py @@ -839,10 +839,10 @@ class Session(models.Model): return self.meeting.number ss0name = "(unscheduled)" - ss = self.scheduledsession_set.order_by('timeslot__time') + ss = self.scheduledsession_set.filter(schedule=self.meeting.agenda).order_by('timeslot__time') if ss: - ss0name = ss[0].timeslot.time.strftime("%H%M") - return u"%s: %s %s[%u]" % (self.meeting, self.group.acronym, ss0name, self.pk) + ss0name = ','.join([x.timeslot.time.strftime("%a-%H%M") for x in ss]) + return u"%s: %s %s %s" % (self.meeting, self.group.acronym, self.name, ss0name) def is_bof(self): return self.group.is_bof(); diff --git a/ietf/meeting/urls.py b/ietf/meeting/urls.py index a4443f1fe..f8cce53f7 100644 --- a/ietf/meeting/urls.py +++ b/ietf/meeting/urls.py @@ -53,6 +53,13 @@ urlpatterns = patterns('', (r'^(?P<num>\d+)/sessions.json', ajax.sessions_json), (r'^(?P<num>\d+)/session/(?P<sessionid>\d+).json', ajax.session_json), (r'^(?P<num>\d+)/session/(?P<sessionid>\d+)/constraints.json', ajax.session_constraints), + + (r'^(?P<num>\d+)/session/(?P<acronym>[A-Za-z0-9_\-\+]+)/$', views.session_details), + (r'^(?P<num>\d+)/session/(?P<acronym>[A-Za-z0-9_\-\+]+)/(?P<seq>\d+)/$', views.session_details), + (r'^(?P<num>\d+)/session/(?P<acronym>[A-Za-z0-9_\-\+]+)/(?P<week_day>[a-zA-Z]+)/$', views.session_details), + (r'^(?P<num>\d+)/session/(?P<acronym>[A-Za-z0-9_\-\+]+)/(?P<date>\d{4}-\d{2}-\d{2}(-\d{4})?)/$', views.session_details), + (r'^(?P<num>\d+)/session/(?P<acronym>[A-Za-z0-9_\-\+]+)/(?P<date>\d{4}-\d{2}-\d{2}(-\d{4})?)/(?P<seq>\d+)/$', views.session_details), + (r'^(?P<num>\d+)/constraint/(?P<constraintid>\d+).json', ajax.constraint_json), (r'^(?P<num>\d+).json$', ajax.meeting_json), (r'^$', views.current_materials), diff --git a/ietf/meeting/views.py b/ietf/meeting/views.py index ceaae58b8..556b34e27 100644 --- a/ietf/meeting/views.py +++ b/ietf/meeting/views.py @@ -10,7 +10,7 @@ from tempfile import mkstemp import debug # pyflakes:ignore from django import forms -from django.shortcuts import render_to_response, redirect +from django.shortcuts import render, render_to_response, redirect from django.http import HttpResponse, HttpResponseRedirect, HttpResponseForbidden, Http404 from django.core.urlresolvers import reverse from django.db.models import Q @@ -616,3 +616,64 @@ def meeting_requests(request, num=None) : "groups_not_meeting": groups_not_meeting}, context_instance=RequestContext(request)) +def session_details(request, num, acronym, date=None, week_day=None, seq=None) : + meeting = get_meeting(num) + sessions = Session.objects.filter(meeting=meeting,group__acronym=acronym) + + if not sessions: + sessions = Session.objects.filter(meeting=meeting,short=acronym) + + if date: + if len(date)==15: + start = datetime.datetime.strptime(date,"%Y-%m-%d-%H%M") + sessions = sessions.filter(scheduledsession__schedule=meeting.agenda,scheduledsession__timeslot__time=start) + else: + start = datetime.datetime.strptime(date,"%Y-%m-%d").date() + end = start+datetime.timedelta(days=1) + sessions = sessions.filter(scheduledsession__schedule=meeting.agenda,scheduledsession__timeslot__time__range=(start,end)) + + if week_day: + try: + dow = ['sun','mon','tue','wed','thu','fri','sat'].index(week_day.lower()[:3]) + 1 + except ValueError: + raise Http404 + sessions = sessions.filter(scheduledsession__schedule=meeting.agenda,scheduledsession__timeslot__time__week_day=dow) + + + def sort_key(session): + official_sessions = session.scheduledsession_set.filter(schedule=session.meeting.agenda) + if official_sessions: + return official_sessions.first().timeslot.time + else: + return session.requested + + sessions = sorted(sessions,key=sort_key) + + if seq: + iseq = int(seq) - 1 + if not iseq in range(0,len(sessions)): + raise Http404 + else: + sessions= [sessions[iseq]] + + if not sessions: + raise Http404 + + if len(sessions)==1: + session = sessions[0] + scheduled_time = "Not yet scheduled" + ss = session.scheduledsession_set.filter(schedule=meeting.agenda).order_by('timeslot__time') + if ss: + scheduled_time = ','.join([x.timeslot.time.strftime("%A %b-%d %H%M") for x in ss]) + return render(request, "meeting/session_details.html", + { 'session':sessions[0] , + 'meeting' :meeting , + 'acronym' :acronym, + 'time': scheduled_time, + }) + else: + return render(request, "meeting/session_list.html", + { 'sessions':sessions , + 'meeting' :meeting , + 'acronym' :acronym, + }) diff --git a/ietf/templates/doc/material/material_presentations.html b/ietf/templates/doc/material/material_presentations.html index e7196819e..f84f14013 100644 --- a/ietf/templates/doc/material/material_presentations.html +++ b/ietf/templates/doc/material/material_presentations.html @@ -1,23 +1,28 @@ {% extends "base.html" %} {% block title %} -Edit Upcoming Presentations -{% endblock %} - -{% block morecss %} -{{ block.super }} -ul#id_sesspres { list-style-type: none; padding: 0px; margin: 0px; } +Upcoming Presentations {% endblock %} {% block content %} {% load ietf_filters %} -<h1>Edit Upcoming Presentations of<br/>{{doc.title}}<br/>{{doc.name}}</h1> +<h1>Upcoming Presentations of<br/>{{doc.title}}<br/>{{doc.name}}</h1> -<form class="session-presentations" action="" method="post">{% csrf_token %} -{{form.as_p}} -<input style="button" type="submit" name="action" value="Save"> -<input style="button" type="submit" name="action" value="Cancel"> -</form> +<ul> +{% regroup sessions by has_presentation as is_scheduled_list %} + {% for is_scheduled in is_scheduled_list %} + <li> {{ is_scheduled.grouper|yesno:"Presentation Scheduled,Presentation Not Scheduled"}} + <ul> + {% for session in is_scheduled.list %} + <li> + <a href="{{session.sequence}}">{{ session }}</a> + {% if session.versions %} (version{{session.versions|pluralize}} {{session.versions|join:','}}) {% endif %} + </li> + {% endfor %} + </ul> + </li> + {% endfor %} +</ul> {% endblock content %} From c05d734cf33dc8d5e6d076b428a0eabee7eb1972 Mon Sep 17 00:00:00 2001 From: Robert Sparks <rjsparks@nostrum.com> Date: Tue, 21 Oct 2014 22:38:06 +0000 Subject: [PATCH 12/18] one more tweak before refactoring - Legacy-Id: 8455 --- ietf/doc/views_material.py | 3 ++- ietf/meeting/models.py | 11 +++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/ietf/doc/views_material.py b/ietf/doc/views_material.py index 10a73130d..faf9a158a 100644 --- a/ietf/doc/views_material.py +++ b/ietf/doc/views_material.py @@ -196,7 +196,8 @@ def material_presentations(request, name, acronym=None, date=None, seq=None, wee # Find all the sessions for meetings that haven't ended that the user could affect # This motif is also in Document.future_presentations - it would be nice to consolodate it somehow - candidate_sessions = Session.objects.filter(meeting__date__gte=datetime.date.today()-datetime.timedelta(days=15)) + + candidate_sessions = Session.objects.exclude(status__in=['canceled','disappr','notmeet','deleted']).filter(meeting__date__gte=datetime.date.today()-datetime.timedelta(days=15)) refined_candidates = [ sess for sess in candidate_sessions if sess.meeting.end_date()>=datetime.date.today()] if acronym: diff --git a/ietf/meeting/models.py b/ietf/meeting/models.py index 5fe9adbbe..1fdd1c238 100644 --- a/ietf/meeting/models.py +++ b/ietf/meeting/models.py @@ -838,10 +838,13 @@ class Session(models.Model): if self.meeting.type_id == "interim": return self.meeting.number - ss0name = "(unscheduled)" - ss = self.scheduledsession_set.filter(schedule=self.meeting.agenda).order_by('timeslot__time') - if ss: - ss0name = ','.join([x.timeslot.time.strftime("%a-%H%M") for x in ss]) + if self.status.slug in ('canceled','disappr','notmeet','deleted'): + ss0name = "(%s)" % self.status.name + else: + ss0name = "(unscheduled)" + ss = self.scheduledsession_set.filter(schedule=self.meeting.agenda).order_by('timeslot__time') + if ss: + ss0name = ','.join([x.timeslot.time.strftime("%a-%H%M") for x in ss]) return u"%s: %s %s %s" % (self.meeting, self.group.acronym, self.name, ss0name) def is_bof(self): From b7d8ed8491d97eed4a6739714b035e9189198332 Mon Sep 17 00:00:00 2001 From: Robert Sparks <rjsparks@nostrum.com> Date: Wed, 5 Nov 2014 21:49:44 +0000 Subject: [PATCH 13/18] add missing templates - Legacy-Id: 8590 --- .../material/edit_material_presentations.html | 23 +++++++++++++++++ ietf/templates/meeting/session_details.html | 25 +++++++++++++++++++ ietf/templates/meeting/session_list.html | 13 ++++++++++ 3 files changed, 61 insertions(+) create mode 100644 ietf/templates/doc/material/edit_material_presentations.html create mode 100644 ietf/templates/meeting/session_details.html create mode 100644 ietf/templates/meeting/session_list.html diff --git a/ietf/templates/doc/material/edit_material_presentations.html b/ietf/templates/doc/material/edit_material_presentations.html new file mode 100644 index 000000000..657a7cfad --- /dev/null +++ b/ietf/templates/doc/material/edit_material_presentations.html @@ -0,0 +1,23 @@ +{% extends "base.html" %} + +{% block title %} +Edit Upcoming Presentations +{% endblock %} + +{% block morecss %} +{{ block.super }} +ul#id_versions { list-style-type: none; padding: 0px; margin: 0px; } +{% endblock %} + +{% block content %} +{% load ietf_filters %} + +<h1>Edit Upcoming Presentations of<br/>{{doc.title}}<br/>{{doc.name}}<br/>at {{session}}</h1> + +<form method="post">{% csrf_token %} +{{form.as_p}} +<input style="button" type="submit" name="action" value="Save"/> +<input style="button" type="submit" name="action" value="Cancel"/> +</form> + +{% endblock content %} diff --git a/ietf/templates/meeting/session_details.html b/ietf/templates/meeting/session_details.html new file mode 100644 index 000000000..dc1e8028e --- /dev/null +++ b/ietf/templates/meeting/session_details.html @@ -0,0 +1,25 @@ +{% extends "base.html" %} + +{% block title %} {{meeting}} : {{acronym}} {% endblock %} + +{% block morecss %} +.timeheader {font-size:120%;} +{% endblock %} + +{% block content %} +<h1> {{ meeting }} : {{ acronym }} : {{ time }} </h1> +{% if session.name %} +<h2> {{session.name}} </h2> +{% endif %} + +{% if session.sessionpresentation_set.all.count %} +<p>Materials: +<ul> +{% for pres in session.sessionpresentation_set.all %} +<li><a href="{% url 'doc_view' name=pres.document.name rev=pres.rev%}">{{pres.document.name}}-{{pres.rev}}</a></li> +{% endfor %} +</ul> +</p> +{% endif %} + +{% endblock %} diff --git a/ietf/templates/meeting/session_list.html b/ietf/templates/meeting/session_list.html new file mode 100644 index 000000000..222127acf --- /dev/null +++ b/ietf/templates/meeting/session_list.html @@ -0,0 +1,13 @@ +{% extends "base.html" %} + +{% block title %} {{meeting}} : {{acronym}} {% endblock %} + +{% block content %} +<h1> {{ meeting }} : {{acronym}} </h1> + +<ul> +{% for session in sessions %} + <li> <a href="{{forloop.counter}}">{{session}}</a></li> +{% endfor %} +</ul> +{% endblock %} From 5f1663530c398a39a43cfb4602aee6b0c5c6038e Mon Sep 17 00:00:00 2001 From: Robert Sparks <rjsparks@nostrum.com> Date: Mon, 24 Nov 2014 19:54:25 +0000 Subject: [PATCH 14/18] Added comment docevents when changing SessionPresentation objects. Reworked group materials page to be more helpful when there are multiple SessionPresentations withing a given Meeting - Legacy-Id: 8705 --- ietf/doc/models.py | 2 +- ietf/doc/views_material.py | 9 +++++++++ ietf/templates/group/materials.html | 31 +++++++++++++++++++++++++++-- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/ietf/doc/models.py b/ietf/doc/models.py index cfb3e2c2f..fb89f643e 100644 --- a/ietf/doc/models.py +++ b/ietf/doc/models.py @@ -203,7 +203,7 @@ class DocumentInfo(models.Model): """ returns related SessionPresentation objects for meetings that have not yet ended. This implementation allows for 2 week meetings """ candidate_presentations = self.sessionpresentation_set.filter(session__meeting__date__gte=datetime.date.today()-datetime.timedelta(days=15)) - return [pres for pres in candidate_presentations if pres.session.meeting.end_date()>=datetime.date.today()] + return sorted([pres for pres in candidate_presentations if pres.session.meeting.end_date()>=datetime.date.today()], key=lambda x:x.session.meeting.date) def last_presented(self): """ returns related SessionPresentation objects for the most recent meeting in the past""" diff --git a/ietf/doc/views_material.py b/ietf/doc/views_material.py index faf9a158a..f0c655f12 100644 --- a/ietf/doc/views_material.py +++ b/ietf/doc/views_material.py @@ -270,10 +270,19 @@ def material_presentations(request, name, acronym=None, date=None, seq=None, wee if initial['version'] != new_selection: if initial['version'] == 'notpresented': doc.sessionpresentation_set.create(session=session,rev=new_selection) + c = DocEvent(type="added_comment", doc=doc, by=request.user.person) + c.desc = "Added version %s to session: %s" % (new_selection,session) + c.save() elif new_selection == 'notpresented': doc.sessionpresentation_set.filter(session=session).delete() + c = DocEvent(type="added_comment", doc=doc, by=request.user.person) + c.desc = "Removed from session: %s" % (session) + c.save() else: doc.sessionpresentation_set.filter(session=session).update(rev=new_selection) + c = DocEvent(type="added_comment", doc=doc, by=request.user.person) + c.desc = "Revision for session %s changed to %s" % (session,new_selection) + c.save() return redirect('doc_view',name=doc.name) else: form = MaterialVersionForm(choices=choices,initial=initial) diff --git a/ietf/templates/group/materials.html b/ietf/templates/group/materials.html index 1c3f709c6..c8742eacc 100644 --- a/ietf/templates/group/materials.html +++ b/ietf/templates/group/materials.html @@ -33,8 +33,35 @@ <td class='snippable'>{{ d.abstract|format_snippet }} </td> <td>{{ d.rev }}</td> <td>{{ d.time|date:"Y-m-d" }}</td> - <td>{% for p in d.last_presented %}{{p.session.meeting}}{% if d.rev != p.rev %} (-{{ p.rev }}){% endif %}{%if not forloop.last%}, {% endif %}{% endfor %}</td> - <td>{% for p in d.future_presentations %}{{p.session.meeting}}{% if d.rev != p.rev %} (-{{p.rev}}){%endif%}{%if not forloop.last%}, {%endif%}{%endfor%}</td> + <td>{% regroup d.last_presented by session.meeting as past_pres_list %} + {% for p in past_pres_list %} + {{ p.grouper }} + {% if p.list|length > 1 %} + ( {{ p.list|length }} sessions ) + {% else %} + {% for pr in p.list %} + {% if pr.rev != d.rev %} + (-{{ pr.rev }}) + {% endif %} + {% endfor %} + {% endif %} + {% if not forloop.last %}, {% endif %} + {% endfor %} + <td>{% regroup d.future_presentations by session.meeting as meeting_pres_list %} + {% for p in meeting_pres_list %} + {{ p.grouper }} + {% if p.list|length > 1 %} + ( {{ p.list|length }} sessions ) + {% else %} + {% for pr in p.list %} + {% if pr.rev != d.rev %} + (-{{ pr.rev }}) + {% endif %} + {% endfor %} + {% endif %} + {% if not forloop.last %}, {% endif %} + {% endfor %} + </td> </tr> {% endfor %} </table> From 2d0eb1e0115c494a3ba5bc35aec870f48eba7038 Mon Sep 17 00:00:00 2001 From: Robert Sparks <rjsparks@nostrum.com> Date: Mon, 24 Nov 2014 20:53:36 +0000 Subject: [PATCH 15/18] Reworked URLs to explicitly invoke edit. Build list of possible sessions using group acronym and sequence variant of urls, not just sequence alone - Legacy-Id: 8706 --- ietf/doc/urls_material.py | 6 + ietf/doc/views_material.py | 120 ++++++++++-------- .../doc/material/material_presentations.html | 13 +- 3 files changed, 84 insertions(+), 55 deletions(-) diff --git a/ietf/doc/urls_material.py b/ietf/doc/urls_material.py index 09e2645bd..d61b5faaf 100644 --- a/ietf/doc/urls_material.py +++ b/ietf/doc/urls_material.py @@ -3,6 +3,12 @@ from django.conf.urls import patterns, url urlpatterns = patterns('ietf.doc.views_material', url(r'^(?P<action>state|title|abstract|revise)/$', "edit_material", name="material_edit"), url(r'^sessions/$', "material_presentations", name="material_presentations"), + (r'^sessions/(?P<seq>\d+)/edit/$', "edit_material_presentations"), + (r'^sessions/(?P<acronym>[A-Za-z0-9_\-\+]+)/edit/$', "edit_material_presentations"), + (r'^sessions/(?P<acronym>[A-Za-z0-9_\-\+]+)/(?P<seq>\d+)/edit/$', "edit_material_presentations"), + (r'^sessions/(?P<acronym>[A-Za-z0-9_\-\+]+)/(?P<week_day>[a-zA-Z]+)/edit/$', "edit_material_presentations"), + (r'^sessions/(?P<acronym>[A-Za-z0-9_\-\+]+)/(?P<date>\d{4}-\d{2}-\d{2}(-\d{4})?)/edit/$', "edit_material_presentations"), + (r'^sessions/(?P<acronym>[A-Za-z0-9_\-\+]+)/(?P<date>\d{4}-\d{2}-\d{2}(-\d{4})?)/(?P<seq>\d+)/edit/$', "edit_material_presentations"), (r'^sessions/(?P<seq>\d+)/$', "material_presentations"), (r'^sessions/(?P<acronym>[A-Za-z0-9_\-\+]+)/$', "material_presentations"), (r'^sessions/(?P<acronym>[A-Za-z0-9_\-\+]+)/(?P<seq>\d+)/$', "material_presentations"), diff --git a/ietf/doc/views_material.py b/ietf/doc/views_material.py index f0c655f12..29ed7e48c 100644 --- a/ietf/doc/views_material.py +++ b/ietf/doc/views_material.py @@ -183,16 +183,7 @@ class MaterialVersionForm(forms.Form): super(MaterialVersionForm,self).__init__(*args,**kwargs) self.fields['version'].choices = choices -@login_required -def material_presentations(request, name, acronym=None, date=None, seq=None, week_day=None): - - doc = get_object_or_404(Document, name=name) - if not (doc.type_id=='slides' and doc.get_state('slides').slug=='active'): - raise Http404 - - group = doc.group - if not (group.features.has_materials and can_manage_materials(request.user,group)): - raise Http404 +def get_upcoming_manageable_sessions(user, doc, acronym=None, date=None, seq=None, week_day = None): # Find all the sessions for meetings that haven't ended that the user could affect # This motif is also in Document.future_presentations - it would be nice to consolodate it somehow @@ -219,7 +210,7 @@ def material_presentations(request, name, acronym=None, date=None, seq=None, wee raise Http404 refined_candidates = [ sess for sess in refined_candidates if sess.scheduledsession_set.filter(schedule=sess.meeting.agenda,timeslot__time__week_day=dow) ] - changeable_sessions = [ sess for sess in refined_candidates if can_manage_materials(request.user, sess.group) ] + changeable_sessions = [ sess for sess in refined_candidates if can_manage_materials(user, sess.group) ] if not changeable_sessions: raise Http404 @@ -253,48 +244,77 @@ def material_presentations(request, name, acronym=None, date=None, seq=None, wee else: sorted_sessions = [sorted_sessions[iseq]] - for index,session in enumerate(sorted_sessions): - session.sequence = index+1 + return sorted_sessions - if len(sorted_sessions)==1: - session = sorted_sessions[0] - choices = [('notpresented','Not Presented')] - choices.extend([(x,x) for x in doc.docevent_set.filter(type='new_revision').values_list('newrevisiondocevent__rev',flat=True)]) - initial = {'version' : session.version if hasattr(session,'version') else 'notpresented'} +@login_required +def edit_material_presentations(request, name, acronym=None, date=None, seq=None, week_day=None): - if request.method == 'POST': - form = MaterialVersionForm(request.POST,choices=choices) - if form.is_valid(): - if request.POST.get("action", "") == "Save": - new_selection = form.cleaned_data['version'] - if initial['version'] != new_selection: - if initial['version'] == 'notpresented': - doc.sessionpresentation_set.create(session=session,rev=new_selection) - c = DocEvent(type="added_comment", doc=doc, by=request.user.person) - c.desc = "Added version %s to session: %s" % (new_selection,session) - c.save() - elif new_selection == 'notpresented': - doc.sessionpresentation_set.filter(session=session).delete() - c = DocEvent(type="added_comment", doc=doc, by=request.user.person) - c.desc = "Removed from session: %s" % (session) - c.save() - else: - doc.sessionpresentation_set.filter(session=session).update(rev=new_selection) - c = DocEvent(type="added_comment", doc=doc, by=request.user.person) - c.desc = "Revision for session %s changed to %s" % (session,new_selection) - c.save() - return redirect('doc_view',name=doc.name) - else: - form = MaterialVersionForm(choices=choices,initial=initial) + doc = get_object_or_404(Document, name=name) + if not (doc.type_id=='slides' and doc.get_state('slides').slug=='active'): + raise Http404 - return render(request, 'doc/material/edit_material_presentations.html', { - 'session': session, - 'doc': doc, - 'form': form, - }) + group = doc.group + if not (group.features.has_materials and can_manage_materials(request.user,group)): + raise Http404 + sorted_sessions = get_upcoming_manageable_sessions(request.user, doc, acronym, date, seq, week_day) + + if len(sorted_sessions)!=1: + raise Http404 + + session = sorted_sessions[0] + choices = [('notpresented','Not Presented')] + choices.extend([(x,x) for x in doc.docevent_set.filter(type='new_revision').values_list('newrevisiondocevent__rev',flat=True)]) + initial = {'version' : session.version if hasattr(session,'version') else 'notpresented'} + + if request.method == 'POST': + form = MaterialVersionForm(request.POST,choices=choices) + if form.is_valid(): + if request.POST.get("action", "") == "Save": + new_selection = form.cleaned_data['version'] + if initial['version'] != new_selection: + if initial['version'] == 'notpresented': + doc.sessionpresentation_set.create(session=session,rev=new_selection) + c = DocEvent(type="added_comment", doc=doc, by=request.user.person) + c.desc = "Added version %s to session: %s" % (new_selection,session) + c.save() + elif new_selection == 'notpresented': + doc.sessionpresentation_set.filter(session=session).delete() + c = DocEvent(type="added_comment", doc=doc, by=request.user.person) + c.desc = "Removed from session: %s" % (session) + c.save() + else: + doc.sessionpresentation_set.filter(session=session).update(rev=new_selection) + c = DocEvent(type="added_comment", doc=doc, by=request.user.person) + c.desc = "Revision for session %s changed to %s" % (session,new_selection) + c.save() + return redirect('doc_view',name=doc.name) else: - return render(request, 'doc/material/material_presentations.html', { - 'sessions' : sorted_sessions, - 'doc': doc, + form = MaterialVersionForm(choices=choices,initial=initial) + + return render(request, 'doc/material/edit_material_presentations.html', { + 'session': session, + 'doc': doc, + 'form': form, + }) + +@login_required +def material_presentations(request, name, acronym=None, date=None, seq=None, week_day=None): + + doc = get_object_or_404(Document, name=name) + if not (doc.type_id=='slides' and doc.get_state('slides').slug=='active'): + raise Http404 + + group = doc.group + if not (group.features.has_materials and can_manage_materials(request.user,group)): + raise Http404 + + sorted_sessions = get_upcoming_manageable_sessions(request.user, doc, acronym, date, seq, week_day) + + #for index,session in enumerate(sorted_sessions): + # session.sequence = index+1 + + return render(request, 'doc/material/material_presentations.html', { + 'sessions' : sorted_sessions, + 'doc': doc, }) diff --git a/ietf/templates/doc/material/material_presentations.html b/ietf/templates/doc/material/material_presentations.html index f84f14013..fd093e269 100644 --- a/ietf/templates/doc/material/material_presentations.html +++ b/ietf/templates/doc/material/material_presentations.html @@ -14,11 +14,14 @@ Upcoming Presentations {% for is_scheduled in is_scheduled_list %} <li> {{ is_scheduled.grouper|yesno:"Presentation Scheduled,Presentation Not Scheduled"}} <ul> - {% for session in is_scheduled.list %} - <li> - <a href="{{session.sequence}}">{{ session }}</a> - {% if session.versions %} (version{{session.versions|pluralize}} {{session.versions|join:','}}) {% endif %} - </li> + {% regroup is_scheduled.list by group as group_list %} + {% for group in group_list %} + {% for session in group.list %} + <li> + <a href="{% url 'ietf.doc.views_material.edit_material_presentations' name=doc.name acronym=group.grouper.acronym seq=forloop.counter %}">{{ session }}</a> + {% if session.versions %} (version{{session.versions|pluralize}} {{session.versions|join:','}}) {% endif %} + </li> + {% endfor %} {% endfor %} </ul> </li> From 986768bf73910aec3d714154d3ce971c3831acf9 Mon Sep 17 00:00:00 2001 From: Robert Sparks <rjsparks@nostrum.com> Date: Mon, 24 Nov 2014 21:06:58 +0000 Subject: [PATCH 16/18] Cleaned up issues with date and weekday variants of the session views - Legacy-Id: 8707 --- ietf/doc/urls_material.py | 2 ++ ietf/doc/views_material.py | 2 ++ ietf/templates/doc/material/material_presentations.html | 8 +++++++- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/ietf/doc/urls_material.py b/ietf/doc/urls_material.py index d61b5faaf..40fb7fd6c 100644 --- a/ietf/doc/urls_material.py +++ b/ietf/doc/urls_material.py @@ -7,12 +7,14 @@ urlpatterns = patterns('ietf.doc.views_material', (r'^sessions/(?P<acronym>[A-Za-z0-9_\-\+]+)/edit/$', "edit_material_presentations"), (r'^sessions/(?P<acronym>[A-Za-z0-9_\-\+]+)/(?P<seq>\d+)/edit/$', "edit_material_presentations"), (r'^sessions/(?P<acronym>[A-Za-z0-9_\-\+]+)/(?P<week_day>[a-zA-Z]+)/edit/$', "edit_material_presentations"), + (r'^sessions/(?P<acronym>[A-Za-z0-9_\-\+]+)/(?P<week_day>[a-zA-Z]+)/(?P<seq>\d+)/edit/$', "edit_material_presentations"), (r'^sessions/(?P<acronym>[A-Za-z0-9_\-\+]+)/(?P<date>\d{4}-\d{2}-\d{2}(-\d{4})?)/edit/$', "edit_material_presentations"), (r'^sessions/(?P<acronym>[A-Za-z0-9_\-\+]+)/(?P<date>\d{4}-\d{2}-\d{2}(-\d{4})?)/(?P<seq>\d+)/edit/$', "edit_material_presentations"), (r'^sessions/(?P<seq>\d+)/$', "material_presentations"), (r'^sessions/(?P<acronym>[A-Za-z0-9_\-\+]+)/$', "material_presentations"), (r'^sessions/(?P<acronym>[A-Za-z0-9_\-\+]+)/(?P<seq>\d+)/$', "material_presentations"), (r'^sessions/(?P<acronym>[A-Za-z0-9_\-\+]+)/(?P<week_day>[a-zA-Z]+)/$', "material_presentations"), + (r'^sessions/(?P<acronym>[A-Za-z0-9_\-\+]+)/(?P<week_day>[a-zA-Z]+)/(?P<seq>\d+)/$', "material_presentations"), (r'^sessions/(?P<acronym>[A-Za-z0-9_\-\+]+)/(?P<date>\d{4}-\d{2}-\d{2}(-\d{4})?)/$', "material_presentations"), (r'^sessions/(?P<acronym>[A-Za-z0-9_\-\+]+)/(?P<date>\d{4}-\d{2}-\d{2}(-\d{4})?)/(?P<seq>\d+)/$', "material_presentations"), ) diff --git a/ietf/doc/views_material.py b/ietf/doc/views_material.py index 29ed7e48c..0f2c6b374 100644 --- a/ietf/doc/views_material.py +++ b/ietf/doc/views_material.py @@ -317,4 +317,6 @@ def material_presentations(request, name, acronym=None, date=None, seq=None, wee return render(request, 'doc/material/material_presentations.html', { 'sessions' : sorted_sessions, 'doc': doc, + 'date': date, + 'week_day': week_day, }) diff --git a/ietf/templates/doc/material/material_presentations.html b/ietf/templates/doc/material/material_presentations.html index fd093e269..02cb1cb1d 100644 --- a/ietf/templates/doc/material/material_presentations.html +++ b/ietf/templates/doc/material/material_presentations.html @@ -18,7 +18,13 @@ Upcoming Presentations {% for group in group_list %} {% for session in group.list %} <li> - <a href="{% url 'ietf.doc.views_material.edit_material_presentations' name=doc.name acronym=group.grouper.acronym seq=forloop.counter %}">{{ session }}</a> + {% if week_day %} + <a href="{% url 'ietf.doc.views_material.edit_material_presentations' name=doc.name acronym=group.grouper.acronym seq=forloop.counter week_day=week_day %}">{{ session }}</a> + {% elif date %} + <a href="{% url 'ietf.doc.views_material.edit_material_presentations' name=doc.name acronym=group.grouper.acronym seq=forloop.counter date=date %}">{{ session }}</a> + {% else %} + <a href="{% url 'ietf.doc.views_material.edit_material_presentations' name=doc.name acronym=group.grouper.acronym seq=forloop.counter %}">{{ session }}</a> + {% endif %} {% if session.versions %} (version{{session.versions|pluralize}} {{session.versions|join:','}}) {% endif %} </li> {% endfor %} From e5e6b1337d7cc6de3dd1486aa65939049c17bd78 Mon Sep 17 00:00:00 2001 From: Robert Sparks <rjsparks@nostrum.com> Date: Mon, 24 Nov 2014 21:40:49 +0000 Subject: [PATCH 17/18] Added a materials manager (matman) Role, and populated it for the edu team - Legacy-Id: 8708 --- .../migrations/0008_materials_managers.py | 306 ++++++++++++++++++ ietf/group/utils.py | 2 +- 2 files changed, 307 insertions(+), 1 deletion(-) create mode 100644 ietf/group/migrations/0008_materials_managers.py diff --git a/ietf/group/migrations/0008_materials_managers.py b/ietf/group/migrations/0008_materials_managers.py new file mode 100644 index 000000000..09887a4f7 --- /dev/null +++ b/ietf/group/migrations/0008_materials_managers.py @@ -0,0 +1,306 @@ +# -*- coding: utf-8 -*- +from south.utils import datetime_utils as datetime +from south.db import db +from south.v2 import DataMigration +from django.db import models + +class Migration(DataMigration): + + def forwards(self, orm): + matman = orm['name.RoleName'].objects.create(slug='matman', name='Materials Manager', used=True, order=13) + edu = orm.Group.objects.get(acronym='edu') + for existing_role in orm.Role.objects.filter(group=edu,name__in=['member','chair']): + orm.Role.objects.create(name=matman, group=edu, person=existing_role.person, email=existing_role.email) + + def backwards(self, orm): + orm['name.RoleName'].objects.filter(slug='matman').delete() + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + u'doc.document': { + 'Meta': {'object_name': 'Document'}, + 'abstract': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'ad': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'ad_document_set'", 'null': 'True', 'to': u"orm['person.Person']"}), + 'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['person.Email']", 'symmetrical': 'False', 'through': u"orm['doc.DocumentAuthor']", 'blank': 'True'}), + 'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'external_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}), + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['group.Group']", 'null': 'True', 'blank': 'True'}), + 'intended_std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.IntendedStdLevelName']", 'null': 'True', 'blank': 'True'}), + 'internal_comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'primary_key': 'True'}), + 'note': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'notify': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '1', 'blank': 'True'}), + 'pages': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'rev': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}), + 'shepherd': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'shepherd_document_set'", 'null': 'True', 'to': u"orm['person.Email']"}), + 'states': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}), + 'std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.StdLevelName']", 'null': 'True', 'blank': 'True'}), + 'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.StreamName']", 'null': 'True', 'blank': 'True'}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['name.DocTagName']", 'null': 'True', 'blank': 'True'}), + 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'}) + }, + u'doc.documentauthor': { + 'Meta': {'ordering': "['document', 'order']", 'object_name': 'DocumentAuthor'}, + 'author': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Email']"}), + 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.Document']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '1'}) + }, + u'doc.state': { + 'Meta': {'ordering': "['type', 'order']", 'object_name': 'State'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'next_states': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'previous_states'", 'blank': 'True', 'to': u"orm['doc.State']"}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}), + 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.StateType']"}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'doc.statetype': { + 'Meta': {'object_name': 'StateType'}, + 'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '30', 'primary_key': 'True'}) + }, + u'group.changestategroupevent': { + 'Meta': {'ordering': "['-time', 'id']", 'object_name': 'ChangeStateGroupEvent', '_ormbases': [u'group.GroupEvent']}, + u'groupevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['group.GroupEvent']", 'unique': 'True', 'primary_key': 'True'}), + 'state': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.GroupStateName']"}) + }, + u'group.group': { + 'Meta': {'object_name': 'Group'}, + 'acronym': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '40'}), + 'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']", 'null': 'True', 'blank': 'True'}), + 'charter': ('django.db.models.fields.related.OneToOneField', [], {'blank': 'True', 'related_name': "'chartered_group'", 'unique': 'True', 'null': 'True', 'to': u"orm['doc.Document']"}), + 'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'list_archive': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'list_email': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), + 'list_subscribe': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['group.Group']", 'null': 'True', 'blank': 'True'}), + 'state': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.GroupStateName']", 'null': 'True'}), + 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.GroupTypeName']", 'null': 'True'}), + 'unused_states': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}), + 'unused_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['name.DocTagName']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'group.groupevent': { + 'Meta': {'ordering': "['-time', 'id']", 'object_name': 'GroupEvent'}, + 'by': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']"}), + 'desc': ('django.db.models.fields.TextField', [], {}), + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['group.Group']"}), + u'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'}) + }, + u'group.grouphistory': { + 'Meta': {'object_name': 'GroupHistory'}, + 'acronym': ('django.db.models.fields.CharField', [], {'max_length': '40'}), + 'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']", 'null': 'True', 'blank': 'True'}), + 'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'group': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'history_set'", 'to': u"orm['group.Group']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'list_archive': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'list_email': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), + 'list_subscribe': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['group.Group']", 'null': 'True', 'blank': 'True'}), + 'state': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.GroupStateName']", 'null': 'True'}), + 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.GroupTypeName']", 'null': 'True'}), + 'unused_states': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}), + 'unused_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['name.DocTagName']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'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': u"orm['doc.Document']", 'symmetrical': 'False', 'blank': 'True'}), + 'due': ('django.db.models.fields.DateField', [], {}), + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['group.Group']"}), + u'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': u"orm['name.GroupMilestoneStateName']"}), + 'time': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) + }, + u'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': u"orm['doc.Document']", 'symmetrical': 'False', 'blank': 'True'}), + 'due': ('django.db.models.fields.DateField', [], {}), + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['group.Group']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'milestone': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'history_set'", 'to': u"orm['group.GroupMilestone']"}), + 'resolved': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}), + 'state': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.GroupMilestoneStateName']"}), + 'time': ('django.db.models.fields.DateTimeField', [], {}) + }, + u'group.groupstatetransitions': { + 'Meta': {'object_name': 'GroupStateTransitions'}, + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['group.Group']"}), + u'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': u"orm['doc.State']"}), + 'state': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.State']"}) + }, + u'group.groupurl': { + 'Meta': {'object_name': 'GroupURL'}, + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['group.Group']"}), + u'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'}) + }, + u'group.milestonegroupevent': { + 'Meta': {'ordering': "['-time', 'id']", 'object_name': 'MilestoneGroupEvent', '_ormbases': [u'group.GroupEvent']}, + u'groupevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['group.GroupEvent']", 'unique': 'True', 'primary_key': 'True'}), + 'milestone': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['group.GroupMilestone']"}) + }, + u'group.role': { + 'Meta': {'object_name': 'Role'}, + 'email': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Email']"}), + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['group.Group']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.RoleName']"}), + 'person': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']"}) + }, + u'group.rolehistory': { + 'Meta': {'object_name': 'RoleHistory'}, + 'email': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Email']"}), + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['group.GroupHistory']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.RoleName']"}), + 'person': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']"}) + }, + u'name.doctagname': { + 'Meta': {'ordering': "['order']", 'object_name': 'DocTagName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.doctypename': { + 'Meta': {'ordering': "['order']", 'object_name': 'DocTypeName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.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': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.groupstatename': { + 'Meta': {'ordering': "['order']", 'object_name': 'GroupStateName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.grouptypename': { + 'Meta': {'ordering': "['order']", 'object_name': 'GroupTypeName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.intendedstdlevelname': { + 'Meta': {'ordering': "['order']", 'object_name': 'IntendedStdLevelName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.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': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.stdlevelname': { + 'Meta': {'ordering': "['order']", 'object_name': 'StdLevelName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.streamname': { + 'Meta': {'ordering': "['order']", 'object_name': 'StreamName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'person.email': { + 'Meta': {'object_name': 'Email'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'address': ('django.db.models.fields.CharField', [], {'max_length': '64', 'primary_key': 'True'}), + 'person': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']", 'null': 'True'}), + 'time': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}) + }, + u'person.person': { + 'Meta': {'object_name': 'Person'}, + 'address': ('django.db.models.fields.TextField', [], {'max_length': '255', 'blank': 'True'}), + 'affiliation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'ascii': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'ascii_short': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['auth.User']", 'unique': 'True', 'null': 'True', 'blank': 'True'}) + } + } + + complete_apps = ['group'] + symmetrical = True diff --git a/ietf/group/utils.py b/ietf/group/utils.py index 28086e103..b9edb5d99 100644 --- a/ietf/group/utils.py +++ b/ietf/group/utils.py @@ -108,7 +108,7 @@ def milestone_reviewer_for_group_type(group_type): return "Area Director" def can_manage_materials(user, group): - return has_role(user, 'Secretariat') or group.has_role(user, ("chair", "delegate", "secr")) + return has_role(user, 'Secretariat') or group.has_role(user, ("chair", "delegate", "secr", "matman")) def get_group_or_404(acronym, group_type): """Helper to overcome the schism between group-type prefixed URLs and generic.""" From 8a8da7a3977fc5a3db6698c200d88bae40705952 Mon Sep 17 00:00:00 2001 From: Robert Sparks <rjsparks@nostrum.com> Date: Mon, 24 Nov 2014 21:51:51 +0000 Subject: [PATCH 18/18] cleaned out boilerplate migration imports that arent actually used - Legacy-Id: 8709 --- ietf/group/migrations/0008_materials_managers.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/ietf/group/migrations/0008_materials_managers.py b/ietf/group/migrations/0008_materials_managers.py index 09887a4f7..ea3924eeb 100644 --- a/ietf/group/migrations/0008_materials_managers.py +++ b/ietf/group/migrations/0008_materials_managers.py @@ -1,8 +1,5 @@ # -*- coding: utf-8 -*- -from south.utils import datetime_utils as datetime -from south.db import db from south.v2 import DataMigration -from django.db import models class Migration(DataMigration):