From 1e301207106b7df740b952c630b6f4c0e9791a61 Mon Sep 17 00:00:00 2001 From: Robert Sparks Date: Thu, 30 Apr 2015 15:57:48 +0000 Subject: [PATCH] checkpoint. Model changes done and UI tweaked to match. - Legacy-Id: 9588 --- ietf/bin/create-break-sessions | 4 ++-- ietf/doc/tests.py | 1 + ietf/doc/tests_material.py | 1 + ietf/meeting/ajax.py | 2 ++ ietf/meeting/helpers.py | 13 ++++++++----- ietf/meeting/models.py | 17 ++++++++++++++--- ietf/meeting/test_data.py | 8 +++++--- ietf/meeting/tests_api.py | 2 +- ietf/meeting/views.py | 4 ++-- ietf/secr/meetings/views.py | 12 +++++++++--- ietf/secr/proceedings/tests.py | 2 +- ietf/secr/proceedings/views.py | 4 +++- ietf/secr/sreq/views.py | 12 +++++++++--- ietf/templates/meeting/agenda.csv | 2 +- ietf/templates/meeting/agenda.txt | 2 +- static/css/agenda/agenda.css | 3 ++- 16 files changed, 62 insertions(+), 27 deletions(-) diff --git a/ietf/bin/create-break-sessions b/ietf/bin/create-break-sessions index db12bf684..842c9c251 100755 --- a/ietf/bin/create-break-sessions +++ b/ietf/bin/create-break-sessions @@ -22,8 +22,8 @@ scheduled = SessionStatusName.objects.get(slug='sched') for meeting in Meeting.objects.filter(type="ietf").order_by("date"): print "Checking %s schedules ..." % meeting - brk, __ = Session.objects.get_or_create(meeting=meeting, group=secretariat, requested_by=system, status=scheduled, name='Break', ) - reg, __ = Session.objects.get_or_create(meeting=meeting, group=secretariat, requested_by=system, status=scheduled, name='Registration', ) + brk, __ = Session.objects.get_or_create(meeting=meeting, group=secretariat, requested_by=system, status=scheduled, name='Break', type_id='break',) + reg, __ = Session.objects.get_or_create(meeting=meeting, group=secretariat, requested_by=system, status=scheduled, name='Registration', type_id='reg',) for schedule in meeting.schedule_set.all(): print " Checking for missing Break and Reg sessions in %s" % schedule diff --git a/ietf/doc/tests.py b/ietf/doc/tests.py index 7dd8b3b4d..e865b2066 100644 --- a/ietf/doc/tests.py +++ b/ietf/doc/tests.py @@ -527,6 +527,7 @@ class DocTestCase(TestCase): status = SessionStatusName.objects.create(slug='scheduled', name='Scheduled'), modified = datetime.datetime.now(), requested_by = Person.objects.get(user__username="marschairman"), + type_id = "session", ) SessionPresentation.objects.create(session=session, document=doc, rev=doc.rev) diff --git a/ietf/doc/tests_material.py b/ietf/doc/tests_material.py index ea88ba8c2..47569fa0a 100644 --- a/ietf/doc/tests_material.py +++ b/ietf/doc/tests_material.py @@ -148,6 +148,7 @@ class GroupMaterialTests(TestCase): status = SessionStatusName.objects.create(slug='scheduled', name='Scheduled'), modified = datetime.datetime.now(), requested_by = Person.objects.get(user__username="marschairman"), + type_id="session", ) SessionPresentation.objects.create(session=session, document=doc, rev=doc.rev) diff --git a/ietf/meeting/ajax.py b/ietf/meeting/ajax.py index 0465f3d23..27cd4d79e 100644 --- a/ietf/meeting/ajax.py +++ b/ietf/meeting/ajax.py @@ -158,6 +158,8 @@ AddSlotForm = modelform_factory(TimeSlot, exclude=('meeting','name','location',' # no authorization required to list. def timeslot_slotlist(request, mtg): slots = mtg.timeslot_set.all() + # Restrict graphical editing to slots of type 'session' for now + slots = slots.filter(type__slug='session') json_array=[] for slot in slots: json_array.append(slot.json_dict(request.build_absolute_uri('/'))) diff --git a/ietf/meeting/helpers.py b/ietf/meeting/helpers.py index 2f964c3ee..24a697b17 100644 --- a/ietf/meeting/helpers.py +++ b/ietf/meeting/helpers.py @@ -85,13 +85,16 @@ def build_all_agenda_slices(meeting): time_slices.sort() return time_slices,date_slices -def get_scheduledsessions_from_schedule(schedule): - ss = schedule.scheduledsession_set.filter(timeslot__location__isnull = False).exclude(session__isnull = True).order_by('timeslot__time','timeslot__name','session__group__group') - - return ss +# Not Used +#def get_scheduledsessions_from_schedule(schedule): +# ss = schedule.scheduledsession_set.filter(timeslot__location__isnull = False).exclude(session__isnull = True).order_by('timeslot__time','timeslot__name','session__group__group') +# +# return ss def get_all_scheduledsessions_from_schedule(schedule): - ss = schedule.scheduledsession_set.filter(timeslot__location__isnull = False).order_by('timeslot__time','timeslot__name') + ss = schedule.scheduledsession_set.filter(timeslot__location__isnull = False) + ss = ss.filter(session__type__slug='session') + ss = ss.order_by('timeslot__time','timeslot__name') return ss diff --git a/ietf/meeting/models.py b/ietf/meeting/models.py index bfd3a2f78..680654c78 100644 --- a/ietf/meeting/models.py +++ b/ietf/meeting/models.py @@ -161,7 +161,10 @@ class Meeting(models.Model): @property def sessions_that_can_meet(self): - return self.session_set.exclude(status__slug='notmeet').exclude(status__slug='disappr').exclude(status__slug='deleted').exclude(status__slug='apprw') + qs = self.session_set.exclude(status__slug='notmeet').exclude(status__slug='disappr').exclude(status__slug='deleted').exclude(status__slug='apprw') + # Restrict graphical scheduling to meeting requests (Sessions) of type 'session' for now + qs = qs.filter(type__slug='session') + return qs def sessions_that_can_be_placed(self): from django.db.models import Q @@ -286,6 +289,7 @@ class Room(models.Model): name = models.CharField(max_length=255) capacity = models.IntegerField(null=True, blank=True) resources = models.ManyToManyField(ResourceAssociation, blank = True) + session_types = models.ManyToManyField(TimeSlotTypeName, blank = True) def __unicode__(self): return "%s size: %s" % (self.name, self.capacity) @@ -851,7 +855,8 @@ class Session(models.Model): meeting = models.ForeignKey(Meeting) name = models.CharField(blank=True, max_length=255, help_text="Name of session, in case the session has a purpose rather than just being a group meeting.") short = models.CharField(blank=True, max_length=32, help_text="Short version of 'name' above, for use in filenames.") - group = models.ForeignKey(Group) # The group type determines the session type. BOFs also need to be added as a group. + type = models.ForeignKey(TimeSlotTypeName) + group = models.ForeignKey(Group) # The group type historically determined the session type. BOFs also need to be added as a group. Note that not all meeting requests have a natural group to associate with. attendees = models.IntegerField(null=True, blank=True) agenda_note = models.CharField(blank=True, max_length=255) requested = models.DateTimeField(default=datetime.datetime.now) @@ -1007,7 +1012,13 @@ class Session(models.Model): else: return "The agenda has not been uploaded yet." - def type(self): + # FIXME - This used to be called 'type'. It is only used in agenda.csv and agenda.txt. + # It will return the _wrong thing_ if you look back at an agenda of an earlier meeting + # where group X was a BOF at the time, but is now a WG. + # It also doesn't return anything useful for RG, area sessions, or anything that's not group type 'wg'. + # A better thing to do is find a way to note when a meeting was a BoF meeting and use that, removing this + # function altogether. + def lame_description(self): if self.group.type.slug in [ "wg" ]: return "BOF" if self.group.state.slug in ["bof", "bof-conc"] else "WG" else: diff --git a/ietf/meeting/test_data.py b/ietf/meeting/test_data.py index a3879fab8..0aa18d10f 100644 --- a/ietf/meeting/test_data.py +++ b/ietf/meeting/test_data.py @@ -21,6 +21,8 @@ def make_meeting_test_data(): projector = ResourceAssociation.objects.create(name=pname,icon="notfound.png",desc="Basic projector") room = Room.objects.create(meeting=meeting, name="Test Room", capacity=123) breakfast_room = Room.objects.create(meeting=meeting, name="Breakfast Room", capacity=40) + room.session_types.add("session") + breakfast_room.session_types.add("lead") room.resources = [projector] # mars WG @@ -30,7 +32,7 @@ def make_meeting_test_data(): mars_session = Session.objects.create(meeting=meeting, group=mars, attendees=10, requested_by=system_person, requested_duration=20, status_id="schedw", - scheduled=datetime.datetime.now()) + scheduled=datetime.datetime.now(),type_id="session") mars_session.resources = [projector] ScheduledSession.objects.create(timeslot=slot, session=mars_session, schedule=schedule) @@ -40,7 +42,7 @@ def make_meeting_test_data(): ames_session = Session.objects.create(meeting=meeting, group=Group.objects.get(acronym="ames"), attendees=10, requested_by=system_person, requested_duration=20, status_id="schedw", - scheduled=datetime.datetime.now()) + scheduled=datetime.datetime.now(),type_id="session") ScheduledSession.objects.create(timeslot=slot, session=ames_session, schedule=schedule) # IESG breakfast @@ -51,7 +53,7 @@ def make_meeting_test_data(): name="IESG Breakfast", attendees=25, requested_by=system_person, requested_duration=20, status_id="schedw", - scheduled=datetime.datetime.now()) + scheduled=datetime.datetime.now(),type_id="lead") ScheduledSession.objects.create(timeslot=breakfast_slot, session=iesg_session, schedule=schedule) meeting.agenda = schedule diff --git a/ietf/meeting/tests_api.py b/ietf/meeting/tests_api.py index 6d6def084..5c3fe0fd8 100644 --- a/ietf/meeting/tests_api.py +++ b/ietf/meeting/tests_api.py @@ -204,7 +204,7 @@ class ApiTests(TestCase): r = self.client.get(url) self.assertEqual(r.status_code, 200) info = json.loads(r.content) - self.assertEqual(set([x['short_name'] for x in info]),set([s.session.short_name for s in meeting.agenda.scheduledsession_set.all()])) + self.assertEqual(set([x['short_name'] for x in info]),set([s.session.short_name for s in meeting.agenda.scheduledsession_set.filter(session__type_id='session')])) schedule = meeting.agenda url = urlreverse("ietf.meeting.ajax.scheduledsessions_json", diff --git a/ietf/meeting/views.py b/ietf/meeting/views.py index 04d132422..bf198ae36 100644 --- a/ietf/meeting/views.py +++ b/ietf/meeting/views.py @@ -261,7 +261,7 @@ def edit_agenda(request, num=None, owner=None, name=None): #rooms = meeting.room_set.order_by("capacity") #rooms = rooms.all() - rooms = meeting.room_set.filter(timeslot__type__slug='session').distinct().order_by("capacity") + rooms = meeting.room_set.filter(session_types__slug='session').distinct().order_by("capacity") saveas = SaveAsForm() saveasurl=reverse(edit_agenda, args=[meeting.number, schedule.owner_email(), schedule.name]) @@ -644,7 +644,7 @@ def ical_agenda(request, num=None, name=None, ext=None): def meeting_requests(request, num=None) : meeting = get_meeting(num) - sessions = Session.objects.filter(meeting__number=meeting.number,group__parent__isnull = False).exclude(requested_by=0).order_by("group__parent__acronym","status__slug","group__acronym") + sessions = Session.objects.filter(meeting__number=meeting.number, type__slug='session', group__parent__isnull = False).exclude(requested_by=0).order_by("group__parent__acronym","status__slug","group__acronym") groups_not_meeting = Group.objects.filter(state='Active',type__in=['WG','RG','BOF']).exclude(acronym__in = [session.group.acronym for session in sessions]).order_by("parent__acronym","acronym") diff --git a/ietf/secr/meetings/views.py b/ietf/secr/meetings/views.py index 7985bfc23..e1b42e930 100644 --- a/ietf/secr/meetings/views.py +++ b/ietf/secr/meetings/views.py @@ -105,13 +105,17 @@ def build_nonsession(meeting,schedule): short=get_session(slot).short, group=get_session(slot).group, requested_by=system, - status_id='sched') + status_id='sched', + type=slot.type, + ) else: session, __ = Session.objects.get_or_create(meeting=meeting, name=slot.name, group=secretariat, requested_by=system, - status_id='sched') + status_id='sched', + type=slot.type, + ) session.save() ts = TimeSlot.objects.create(type=slot.type, @@ -469,7 +473,9 @@ def non_session(request, meeting_id, schedule_name): short=short, group=group, requested_by=Person.objects.get(name='(system)'), - status_id='sched') + status_id='sched', + type=type, + ) session.save() # create association diff --git a/ietf/secr/proceedings/tests.py b/ietf/secr/proceedings/tests.py index e70258956..640d43188 100644 --- a/ietf/secr/proceedings/tests.py +++ b/ietf/secr/proceedings/tests.py @@ -75,7 +75,7 @@ class BluesheetTestCase(TestCase): make_test_data() meeting = Meeting.objects.filter(type='interim').first() group = Group.objects.get(acronym='mars') - Session.objects.create(meeting=meeting,group=group,requested_by_id=1,status_id='sched') + Session.objects.create(meeting=meeting,group=group,requested_by_id=1,status_id='sched',type_id='session') url = reverse('proceedings_upload_unified', kwargs={'meeting_num':meeting.number,'acronym':'mars'}) upfile = StringIO('dummy file') upfile.name = "scan1.pdf" diff --git a/ietf/secr/proceedings/views.py b/ietf/secr/proceedings/views.py index 9e38f0aff..aadc8253d 100644 --- a/ietf/secr/proceedings/views.py +++ b/ietf/secr/proceedings/views.py @@ -438,7 +438,9 @@ def interim(request, acronym): Session.objects.create(meeting=meeting, group=group, requested_by=request.user.person, - status_id='sched') + status_id='sched', + type_id='session', + ) create_interim_directory() make_directories(meeting) diff --git a/ietf/secr/sreq/views.py b/ietf/secr/sreq/views.py index 92ce65e74..292fff87f 100644 --- a/ietf/secr/sreq/views.py +++ b/ietf/secr/sreq/views.py @@ -270,7 +270,9 @@ def confirm(request, acronym): requested_by=login, requested_duration=datetime.timedelta(0,int(duration)), comments=form['comments'], - status=SessionStatusName.objects.get(slug=slug)) + status=SessionStatusName.objects.get(slug=slug), + type_id='session', + ) session_save(new_session) if 'resources' in form: new_session.resources = form['resources'] @@ -383,7 +385,9 @@ def edit_mtg(request, num, acronym): requested_by=login, requested_duration=duration, comments=form.cleaned_data['comments'], - status=SessionStatusName.objects.get(slug='schedw')) + status=SessionStatusName.objects.get(slug='schedw'), + type_id='session', + ) new_session.save() else: duration = datetime.timedelta(0,int(form.cleaned_data['length_session2'])) @@ -405,7 +409,9 @@ def edit_mtg(request, num, acronym): requested_by=login, requested_duration=duration, comments=form.cleaned_data['comments'], - status=SessionStatusName.objects.get(slug='apprw')) + status=SessionStatusName.objects.get(slug='apprw'), + type_id='session', + ) new_session.save() else: duration = datetime.timedelta(0,int(form.cleaned_data['length_session3'])) diff --git a/ietf/templates/meeting/agenda.csv b/ietf/templates/meeting/agenda.csv index 537a97ace..93f78720a 100644 --- a/ietf/templates/meeting/agenda.csv +++ b/ietf/templates/meeting/agenda.csv @@ -3,5 +3,5 @@ {% endif %}{% if item.timeslot.type.slug == "reg" %}"{{ item.timeslot.time|date:"Y-m-d" }}","{{ item.timeslot.time_desc|slice:":4" }}","{{ item.timeslot.time_desc|slice:"5:9" }}","{{ item.timeslot.type.name }}","{{ schedule.meeting.reg_area }}","","","","{{ item.timeslot.name }}","r{{item.timeslot.pk}}","","" {% endif %}{% if item.timeslot.type.slug == "other" %}"{{ item.timeslot.time|date:"Y-m-d" }}","{{ item.timeslot.time_desc|slice:":4" }}","{{ item.timeslot.time_desc|slice:"5:9" }}","None","{{ item.timeslot.location.name }}","","{{ item.session.group.acronym }}","{% if item.session.group.parent %}{{item.session.group.parent.acronym|upper}}{% endif %}","{{ item.session.name }}","{{item.session.pk}}","","" {% endif %}{% if item.timeslot.type.slug == "plenary" %}"{{ item.timeslot.time|date:"Y-m-d" }}","{{ item.timeslot.time_desc|slice:":4" }}","{{ item.timeslot.time_desc|slice:"5:9" }}","{{ item.session.name }}","{{ item.timeslot.location.name }}","","{{ item.session.group.acronym }}","","{{ item.session.name }}","{{item.session.pk}}","{% if item.session.agenda %}http://www.ietf.org/proceedings/{{ schedule.meeting.number }}/agenda/{{ item.session.agenda.external_url }}{% endif %}","{% if item.session.slides %}{% for slide in item.session.slides %}http://www.ietf.org/proceedings/{{ schedule.meeting.number }}/slides/{{ slide.external_url }}{% if not forloop.last %}|{% endif %}{% endfor %}{% endif %}" -{% endif %}{% if item.timeslot.type.slug == "session" and item.session.group %}"{{ item.timeslot.time|date:"Y-m-d" }}","{{ item.timeslot.time_desc|slice:":4" }}","{{ item.timeslot.time_desc|slice:"5:9" }}","{{ item.timeslot.name }}","{{ item.timeslot.location.name }}","{{ item.session.group.parent.acronym|upper }}","{{ item.session.group.acronym }}","{{ item.session.type }}","{{ item.session.group.name }}","{{ item.session.pk}}","{% if item.session.agenda %}http://www.ietf.org/proceedings/{{ schedule.meeting.number }}/agenda/{{ item.session.agenda.external_url }}{% endif %}","{% if item.session.slides %}{% for slide in item.session.slides %}http://www.ietf.org/proceedings/{{ schedule.meeting.number }}/slides/{{ slide.external_url }}{% if not forloop.last %}|{% endif %}{% endfor %}{% endif %}" +{% endif %}{% if item.timeslot.type.slug == "session" and item.session.group %}"{{ item.timeslot.time|date:"Y-m-d" }}","{{ item.timeslot.time_desc|slice:":4" }}","{{ item.timeslot.time_desc|slice:"5:9" }}","{{ item.timeslot.name }}","{{ item.timeslot.location.name }}","{{ item.session.group.parent.acronym|upper }}","{{ item.session.group.acronym }}","{{ item.session.lame_description }}","{{ item.session.group.name }}","{{ item.session.pk}}","{% if item.session.agenda %}http://www.ietf.org/proceedings/{{ schedule.meeting.number }}/agenda/{{ item.session.agenda.external_url }}{% endif %}","{% if item.session.slides %}{% for slide in item.session.slides %}http://www.ietf.org/proceedings/{{ schedule.meeting.number }}/slides/{{ slide.external_url }}{% if not forloop.last %}|{% endif %}{% endfor %}{% endif %}" {% endif %}{% endfor %}{% endautoescape %} diff --git a/ietf/templates/meeting/agenda.txt b/ietf/templates/meeting/agenda.txt index 2601c2de0..a7fd9119a 100644 --- a/ietf/templates/meeting/agenda.txt +++ b/ietf/templates/meeting/agenda.txt @@ -20,7 +20,7 @@ {% endif %}{% if item.timeslot.type.slug == "session" %}{% if item.session.group %}{% ifchanged %} {{ item.timeslot.time_desc }} {{ item.timeslot.name }} -{% endifchanged %}{{ item.timeslot.location.name|ljust:14 }} {{ item.session.group.parent.acronym|upper|ljust:4 }} {{ item.session.group.acronym|ljust:10 }} {{ item.session.group.name }} {{ item.session.type }}{% if item.session.agenda_note %} - {{ item.session.agenda_note }}{% endif %} +{% endifchanged %}{{ item.timeslot.location.name|ljust:14 }} {{ item.session.group.parent.acronym|upper|ljust:4 }} {{ item.session.group.acronym|ljust:10 }} {{ item.session.group.name }} {{ item.session.lame_description }}{% if item.session.agenda_note %} - {{ item.session.agenda_note }}{% endif %} {% endif %}{% endif %}{% if item.timeslot.type.slug == "break" %} {{ item.timeslot.time_desc }} {{ item.timeslot.name }}{% if schedule.meeting.break_area and item.timeslot.show_location %} - {{ schedule.meeting.break_area }}{% endif %}{% endif %}{% if item.timeslot.type.slug == "other" %} {{ item.timeslot.time_desc }} {{ item.timeslot.name }} - {{ item.timeslot.location.name }}{% endif %}{% endfor %} diff --git a/static/css/agenda/agenda.css b/static/css/agenda/agenda.css index 56f7207bd..3b5f40959 100644 --- a/static/css/agenda/agenda.css +++ b/static/css/agenda/agenda.css @@ -71,6 +71,7 @@ background-color:#2647A0; width:100px; /* otherwise we get overlap */ min-width:100px; + min-height:40px; font-size:12px; position:absolute; /* makes it float independent of scroll */ z-index:100; /* meeting events will be on top otherwise */ @@ -244,7 +245,7 @@ tr.agenda_slot{ td.agenda_slot{ /* overflow-y:auto; */ /* height:20px; */ - height: 40px; + height: 45px; /* min-height:20px; */ }