From 8686fd2a4e9e390e02fd0fb2990d5c780d1dd9e9 Mon Sep 17 00:00:00 2001 From: Robert Sparks Date: Fri, 23 Jan 2015 17:31:04 +0000 Subject: [PATCH 01/15] simple display fix, already in trunk - Legacy-Id: 8902 --- ietf/meeting/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ietf/meeting/models.py b/ietf/meeting/models.py index 1fdd1c238..1f209676b 100644 --- a/ietf/meeting/models.py +++ b/ietf/meeting/models.py @@ -240,7 +240,7 @@ class Room(models.Model): resources = models.ManyToManyField(ResourceAssociation, blank = True) def __unicode__(self): - return "%s size: %u" % (self.name, self.capacity) + return "%s size: %s" % (self.name, self.capacity) def delete_timeslots(self): for ts in self.timeslot_set.all(): From 47901e8555a796a0f89fe8959bebaab2c21e3d85 Mon Sep 17 00:00:00 2001 From: Robert Sparks Date: Tue, 27 Jan 2015 19:15:25 +0000 Subject: [PATCH 02/15] Checkpoint: by-room view and basic leadership meetings support - Legacy-Id: 8930 --- ietf/meeting/helpers.py | 2 ++ ietf/meeting/models.py | 6 +++++- ietf/meeting/test_data.py | 12 ++++++++++++ ietf/meeting/tests_views.py | 9 ++++++++- ietf/meeting/urls.py | 1 + ietf/meeting/views.py | 15 +++++++++++++++ 6 files changed, 43 insertions(+), 2 deletions(-) diff --git a/ietf/meeting/helpers.py b/ietf/meeting/helpers.py index 12e82b857..5e25d12b0 100644 --- a/ietf/meeting/helpers.py +++ b/ietf/meeting/helpers.py @@ -67,6 +67,8 @@ def build_all_agenda_slices(meeting): date_slices = {} for ts in meeting.timeslot_set.exclude(type__in=['reg','break']).order_by('time','name'): + #for ts in meeting.timeslot_set.exclude(type__in=['reg','break','other']).order_by('time','name'): + #for ts in meeting.timeslot_set.order_by('time','name'): ymd = ts.time.date() if ymd not in date_slices and ts.location != None: diff --git a/ietf/meeting/models.py b/ietf/meeting/models.py index 1f209676b..bdde2ebfd 100644 --- a/ietf/meeting/models.py +++ b/ietf/meeting/models.py @@ -322,7 +322,7 @@ class TimeSlot(models.Model): return u"%s: %s-%s %s, %s" % (self.meeting.number, self.time.strftime("%m-%d %H:%M"), (self.time + self.duration).strftime("%H:%M"), self.name, location) def end_time(self): return self.time + self.duration - def get_location(self): + def get_hidden_location(self): location = self.location if location: location = location.name @@ -330,6 +330,10 @@ class TimeSlot(models.Model): location = self.meeting.reg_area elif self.type_id == "break": location = self.meeting.break_area + return location + + def get_location(self): + location = self.get_hidden_location() if not self.show_location: location = "" return location diff --git a/ietf/meeting/test_data.py b/ietf/meeting/test_data.py index e7a877f76..c4eaa2fc1 100644 --- a/ietf/meeting/test_data.py +++ b/ietf/meeting/test_data.py @@ -20,6 +20,7 @@ def make_meeting_test_data(): pname = RoomResourceName.objects.create(name='projector',slug='proj') 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.resources = [projector] # mars WG @@ -41,6 +42,17 @@ def make_meeting_test_data(): scheduled=datetime.datetime.now()) ScheduledSession.objects.create(timeslot=slot, session=ames_session, schedule=schedule) + # IESG breakfast + breakfast_slot = TimeSlot.objects.create(meeting=meeting, type_id="lead", duration=90 * 60, + location=breakfast_room, + time=datetime.datetime.combine(datetime.date.today(),datetime.time(7,0))) + iesg_session = Session.objects.create(meeting=meeting, group=Group.objects.get(acronym="iesg"), + name="IESG Breakfast", + attendees=25, requested_by=system_person, + requested_duration=20, status_id="schedw", + scheduled=datetime.datetime.now()) + ScheduledSession.objects.create(timeslot=breakfast_slot, session=iesg_session, schedule=schedule) + meeting.agenda = schedule meeting.save() diff --git a/ietf/meeting/tests_views.py b/ietf/meeting/tests_views.py index 736c18ff4..afe82785e 100644 --- a/ietf/meeting/tests_views.py +++ b/ietf/meeting/tests_views.py @@ -11,7 +11,7 @@ from pyquery import PyQuery from ietf.doc.models import Document from ietf.meeting.models import Session, TimeSlot from ietf.meeting.test_data import make_meeting_test_data -from ietf.utils.test_utils import TestCase +from ietf.utils.test_utils import TestCase, login_testing_unauthorized class MeetingTests(TestCase): def setUp(self): @@ -98,6 +98,13 @@ class MeetingTests(TestCase): self.assertTrue(session.group.acronym in agenda_content) self.assertTrue(slot.location.name in agenda_content) + def test_agenda_by_room(self): + meeting = make_meeting_test_data() + url = urlreverse("ietf.meeting.views.agenda_by_room",kwargs=dict(num=meeting.number)) + login_testing_unauthorized(self,"secretary",url) + r = self.client.get(url,kwargs=dict(num=meeting.number)) + self.assertTrue(all([x in r.content for x in ['mars','IESG Breakfast','Test Room','Breakfast Room']])) + def test_materials(self): meeting = make_meeting_test_data() session = Session.objects.filter(meeting=meeting, group__acronym="mars").first() diff --git a/ietf/meeting/urls.py b/ietf/meeting/urls.py index f8cce53f7..56a35dd58 100644 --- a/ietf/meeting/urls.py +++ b/ietf/meeting/urls.py @@ -35,6 +35,7 @@ urlpatterns = patterns('', (r'^(?P\d+)/agenda(?P.txt)$', views.agenda), (r'^(?P\d+)/agenda.ics$', views.ical_agenda), (r'^(?P\d+)/agenda(?P.csv)$', views.agenda), + (r'^(?P\d+)/agenda/by-room$', views.agenda_by_room), (r'^(?P\d+)/agendas/edit$', views.edit_agendas), (r'^(?P\d+)/timeslots/edit$', views.edit_timeslots), (r'^(?P\d+)/rooms$', ajax.timeslot_roomsurl), diff --git a/ietf/meeting/views.py b/ietf/meeting/views.py index 4ea3c54cc..79452846c 100644 --- a/ietf/meeting/views.py +++ b/ietf/meeting/views.py @@ -6,6 +6,7 @@ import re import tarfile import urllib from tempfile import mkstemp +from collections import OrderedDict import debug # pyflakes:ignore @@ -376,6 +377,20 @@ def agenda(request, num=None, name=None, base=None, ext=None): return HttpResponse(render_to_string("meeting/"+base+ext, {"schedule":schedule, "updated": updated}, RequestContext(request)), content_type=mimetype[ext]) +#TODO - let the IAB in +@role_required('Area Director','Secretariat') +@ensure_csrf_cookie +def agenda_by_room(request,num=None): + meeting = get_meeting(num) + schedule = get_schedule(meeting) + ss_by_day = OrderedDict() + for day in schedule.scheduledsession_set.dates('timeslot__time','day'): + ss_by_day[day]=[] + for ss in schedule.scheduledsession_set.order_by('timeslot__location','timeslot__time'): + day = ss.timeslot.time.date() + ss_by_day[day].append(ss) + return render(request,"meeting/agenda_by_room.html",{"meeting":meeting,"ss_by_day":ss_by_day}) + def read_agenda_file(num, doc): # XXXX FIXME: the path fragment in the code below should be moved to # settings.py. The *_PATH settings should be generalized to format() From 3f6503722c4cddc31cb4a5f20ac39884438962fe Mon Sep 17 00:00:00 2001 From: Robert Sparks Date: Tue, 27 Jan 2015 21:22:45 +0000 Subject: [PATCH 03/15] Get the leadership timeslots to show in the secr pages - Legacy-Id: 8931 --- ietf/secr/meetings/forms.py | 1 + ietf/secr/meetings/views.py | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/ietf/secr/meetings/forms.py b/ietf/secr/meetings/forms.py index d3ee39e2e..1954fa93c 100644 --- a/ietf/secr/meetings/forms.py +++ b/ietf/secr/meetings/forms.py @@ -180,6 +180,7 @@ class TimeSlotForm(forms.Form): class NonSessionForm(TimeSlotForm): short = forms.CharField(max_length=32,label='Short Name',help_text='Enter an abbreviated session name (used for material file names)',required=False) type = forms.ModelChoiceField(queryset=TimeSlotTypeName.objects.filter(slug__in=('other','reg','break','plenary')),empty_label=None) + type = forms.ModelChoiceField(queryset=TimeSlotTypeName.objects.filter(used=True).exclude(slug__in=('session',)),empty_label=None) group = forms.ModelChoiceField(queryset=Group.objects.filter(acronym__in=('edu','ietf','iepg','tools','iesg','iab','iaoc')),help_text='Required for Session types: other, plenary',required=False) show_location = forms.BooleanField(required=False) diff --git a/ietf/secr/meetings/views.py b/ietf/secr/meetings/views.py index 1b2e7eed9..371a95bb1 100644 --- a/ietf/secr/meetings/views.py +++ b/ietf/secr/meetings/views.py @@ -95,7 +95,7 @@ def build_nonsession(meeting,schedule): system = Person.objects.get(name='(system)') secretariat = Group.objects.get(acronym='secretariat') - for slot in TimeSlot.objects.filter(meeting=last_meeting,type__in=('break','reg','other','plenary')): + for slot in TimeSlot.objects.filter(meeting=last_meeting,type__in=('break','reg','other','plenary','lead')): new_time = slot.time + delta session = None # create Session object for Tutorials to hold materials @@ -128,7 +128,7 @@ def check_nonsession(meeting,schedule): Ensure non-session timeslots exist and have appropriate ScheduledSession objects for the specified schedule. ''' - slots = TimeSlot.objects.filter(meeting=meeting,type__in=('break','reg','other','plenary')) + slots = TimeSlot.objects.filter(meeting=meeting,type__in=('break','reg','other','plenary','lead')) if not slots: build_nonsession(meeting,schedule) return None @@ -435,7 +435,7 @@ def non_session(request, meeting_id, schedule_name): check_nonsession(meeting,schedule) - slots = TimeSlot.objects.filter(meeting=meeting,type__in=('break','reg','other','plenary')).order_by('-type__name','time') + slots = TimeSlot.objects.filter(meeting=meeting,type__in=('break','reg','other','plenary','lead')).order_by('-type__name','time') if request.method == 'POST': form = NonSessionForm(request.POST) @@ -458,7 +458,7 @@ def non_session(request, meeting_id, schedule_name): duration=duration, show_location=form.cleaned_data['show_location']) - if timeslot.type.slug not in ('other','plenary'): + if timeslot.type.slug not in ('other','plenary','lead'): group = Group.objects.get(acronym='secretariat') # create associated Session object @@ -501,7 +501,7 @@ def non_session_delete(request, meeting_id, schedule_name, slot_id): meeting = get_object_or_404(Meeting, number=meeting_id) # schedule = get_object_or_404(Schedule, meeting=meeting, name=schedule_name) slot = get_object_or_404(TimeSlot, id=slot_id) - if slot.type_id in ('other','plenary'): + if slot.type_id in ('other','plenary','lead'): scheduledsessions = slot.scheduledsession_set.filter(schedule__meeting=meeting) session_objects = [ x.session for x in scheduledsessions ] for session in session_objects: From 61a0059d066fccbeadc8a03995af59a07f7074e1 Mon Sep 17 00:00:00 2001 From: Robert Sparks Date: Wed, 4 Feb 2015 20:47:40 +0000 Subject: [PATCH 04/15] checkpoint before trying to fix the static agenda page - Legacy-Id: 8972 --- ietf/meeting/helpers.py | 1 + static/js/agenda/agenda_objects.js | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ietf/meeting/helpers.py b/ietf/meeting/helpers.py index 5e25d12b0..1d3b2afc0 100644 --- a/ietf/meeting/helpers.py +++ b/ietf/meeting/helpers.py @@ -69,6 +69,7 @@ def build_all_agenda_slices(meeting): for ts in meeting.timeslot_set.exclude(type__in=['reg','break']).order_by('time','name'): #for ts in meeting.timeslot_set.exclude(type__in=['reg','break','other']).order_by('time','name'): #for ts in meeting.timeslot_set.order_by('time','name'): + #for ts in meeting.timeslot_set.filter(type='offagenda').order_by('time','name'): ymd = ts.time.date() if ymd not in date_slices and ts.location != None: diff --git a/static/js/agenda/agenda_objects.js b/static/js/agenda/agenda_objects.js index 1cc85af09..7f2f728b7 100644 --- a/static/js/agenda/agenda_objects.js +++ b/static/js/agenda/agenda_objects.js @@ -1172,6 +1172,10 @@ Session.prototype.event_template = function() { } //console.log("acronym", groupacronym, this.group.acronym, this.visible_title()); + var durationstring=""; + if (this.requested_duration!="0.0") { + durationstring = " ("+this.requested_duration+")" + } // see comment in ietf.ccs, and // http://stackoverflow.com/questions/5148041/does-firefox-support-position-relative-on-table-elements return "
"+ this.visible_title()+ - " ("+this.requested_duration+")" + + "" + durationstring + "" + ""+pinned+"
"+ area_mark +"
"; }; From 9421ea9b93329b686616930eadda42a13a6a5385 Mon Sep 17 00:00:00 2001 From: Robert Sparks Date: Thu, 5 Feb 2015 21:16:56 +0000 Subject: [PATCH 05/15] Unbroke week-view, but only by compromising on whether to show things like the terminal room - Legacy-Id: 9004 --- ietf/meeting/models.py | 2 +- ietf/meeting/views.py | 6 ++++-- ietf/templates/meeting/agenda.csv | 4 ++-- ietf/templates/meeting/agenda.html | 2 +- ietf/templates/meeting/agenda.txt | 2 +- ietf/templates/meeting/week-view.html | 2 +- 6 files changed, 10 insertions(+), 8 deletions(-) diff --git a/ietf/meeting/models.py b/ietf/meeting/models.py index bdde2ebfd..1f4cd0756 100644 --- a/ietf/meeting/models.py +++ b/ietf/meeting/models.py @@ -582,7 +582,7 @@ class Schedule(models.Model): .distinct() ) def groups(self): - return Group.objects.filter(type__slug__in=['wg', 'rg', 'ag', 'iab'], session__scheduledsession__schedule=self).distinct().order_by('parent__acronym', 'acronym') + return Group.objects.filter(type__slug__in=['wg', 'rg', 'ag', 'iab'], session__scheduledsession__schedule=self).exclude(session__scheduledsession__timeslot__type__in=['lead','offagenda']).distinct().order_by('parent__acronym', 'acronym') # calculate badness of entire schedule def calc_badness(self): diff --git a/ietf/meeting/views.py b/ietf/meeting/views.py index 79452846c..1f0967e6a 100644 --- a/ietf/meeting/views.py +++ b/ietf/meeting/views.py @@ -366,6 +366,7 @@ def agenda(request, num=None, name=None, base=None, ext=None): ext = ext if ext else '.html' if 'iPhone' in get_user_agent(request) and ext == ".html": base = 'm_agenda' + # This is misleading - urls.py doesn't send ics through here anymore mimetype = {".html":"text/html", ".txt": "text/plain", ".ics":"text/calendar", ".csv":"text/csv"} meeting = get_meeting(num) schedule = get_schedule(meeting, name) @@ -374,8 +375,9 @@ def agenda(request, num=None, name=None, base=None, ext=None): {'meeting':meeting }, RequestContext(request)), content_type=mimetype[ext]) updated = meeting_updated(meeting) + filtered_assignments = schedule.assignments.exclude(timeslot__type__in=['lead','offagenda']) return HttpResponse(render_to_string("meeting/"+base+ext, - {"schedule":schedule, "updated": updated}, RequestContext(request)), content_type=mimetype[ext]) + {"schedule":schedule, "filtered_assignments":filtered_assignments, "updated": updated}, RequestContext(request)), content_type=mimetype[ext]) #TODO - let the IAB in @role_required('Area Director','Secretariat') @@ -619,7 +621,7 @@ def ical_agenda(request, num=None, name=None, ext=None): elif item[0] == '~': include_types |= set([item[1:]]) - assignments = schedule.assignments.filter( + assignments = schedule.assignments.exclude(timeslot__type__in=['lead','offagenda']).filter( Q(timeslot__type__slug__in = include_types) | Q(session__group__acronym__in = include) | Q(session__group__parent__acronym__in = include) diff --git a/ietf/templates/meeting/agenda.csv b/ietf/templates/meeting/agenda.csv index c1563f6bc..537a97ace 100644 --- a/ietf/templates/meeting/agenda.csv +++ b/ietf/templates/meeting/agenda.csv @@ -1,7 +1,7 @@ {% load humanize %}{% autoescape off %}{% load ietf_filters %}"Date","Start","End","Session","Room","Area","Acronym","Type","Description","Session ID","Agenda","Slides" -{% for item in schedule.assignments.all.distinct %}{% if item.timeslot.type.slug == "break" %}"{{ item.timeslot.time|date:"Y-m-d" }}","{{ item.timeslot.time_desc|slice:":4" }}","{{ item.timeslot.time_desc|slice:"5:9" }}","Break","{{ schedule.meeting.break_area}}","","","","{{ item.timeslot.name }}","b{{ item.timeslot.pk }}","","" +{% for item in filtered_assignments.all.distinct %}{% if item.timeslot.type.slug == "break" %}"{{ item.timeslot.time|date:"Y-m-d" }}","{{ item.timeslot.time_desc|slice:":4" }}","{{ item.timeslot.time_desc|slice:"5:9" }}","Break","{{ schedule.meeting.break_area}}","","","","{{ item.timeslot.name }}","b{{ item.timeslot.pk }}","","" {% 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 %}{% endfor %}{% endautoescape %} \ No newline at end of file +{% endif %}{% endfor %}{% endautoescape %} diff --git a/ietf/templates/meeting/agenda.html b/ietf/templates/meeting/agenda.html index 7d59a8384..1019d72dd 100644 --- a/ietf/templates/meeting/agenda.html +++ b/ietf/templates/meeting/agenda.html @@ -142,7 +142,7 @@ You can customize the agenda below to show only selected working group sessions. {% if schedule.meeting.agenda_note %}

{{ schedule.meeting.agenda_note|safe }}

{% endif %} -{% for item in schedule.assignments.all %} +{% for item in filtered_assignments.all %} {% ifchanged %}
diff --git a/ietf/templates/meeting/agenda.txt b/ietf/templates/meeting/agenda.txt index fabc00145..2601c2de0 100644 --- a/ietf/templates/meeting/agenda.txt +++ b/ietf/templates/meeting/agenda.txt @@ -8,7 +8,7 @@ {% filter center:72 %}Updated {{ updated|date:"Y-m-d H:i:s T" }}{% endfilter %} {% filter center:72 %}IETF agendas are subject to change, up to and during the meeting.{% endfilter %} -{% for item in schedule.assignments.all.distinct %}{% ifchanged %} +{% for item in filtered_assignments.all.distinct %}{% ifchanged %} {{ item.timeslot.time|date:"l"|upper }}, {{ item.timeslot.time|date:"F j, Y" }} diff --git a/ietf/templates/meeting/week-view.html b/ietf/templates/meeting/week-view.html index 28b9f65cd..4d79193f7 100644 --- a/ietf/templates/meeting/week-view.html +++ b/ietf/templates/meeting/week-view.html @@ -9,7 +9,7 @@ var items = new Array(); {% autoescape off %} {% for slot in timeslots %} {% if slot.type.name in render_types %} -items.push({key:"{{slot.pk}}",day:{{slot.time|date:"w"}}, time:"{{slot.time|date:"Hi"}}-{{slot.end_time|date:"Hi"}}", duration:{{slot.duration.seconds}}, time_id:"{{slot.time|date:"mdHi"}}", type:"{{slot.type}}", {% if slot.session.name %}name:"{{slot.session.name}}",{% if slot.session.group.acronym %} wg:"{{slot.session.group.acronym}}",{%endif%}{% else %}{% if slot.type.name == "Break" %}name:"{{slot.name}}", area:"break", wg:"break",{% else %}name:"{{slot.session.group.name}}{%if slot.session.group.state.name = "BOF"%} BOF{%endif%}",wg:"{{slot.session.group.acronym}}",state:"{{slot.session.group.state}}",area:"{{slot.session.group.parent.acronym}}",{% endif %}{% endif %} {% if slot.show_location %}room:"{{slot.get_location}}",{% endif %} dayname:"{{ slot.time|date:"l"|upper }}, {{ slot.time|date:"F j, Y" }}"{% if slot.session.agenda %}, agenda:"{{slot.session.agenda.get_absolute_url}}"{% endif %} });{% endif %}{% endfor %} +items.push({key:"{{slot.pk}}",day:{{slot.time|date:"w"}}, time:"{{slot.time|date:"Hi"}}-{{slot.end_time|date:"Hi"}}", duration:{{slot.duration.seconds}}, time_id:"{{slot.time|date:"mdHi"}}", type:"{{slot.type}}", {% if slot.session.name %}name:"{{slot.session.name|escapejs}}",{% if slot.session.group.acronym %} wg:"{{slot.session.group.acronym}}",{%endif%}{% else %}{% if slot.type.name == "Break" %}name:"{{slot.name}}", area:"break", wg:"break",{% else %}name:"{{slot.session.group.name|escapejs}}{%if slot.session.group.state.name = "BOF"%} BOF{%endif%}",wg:"{{slot.session.group.acronym}}",state:"{{slot.session.group.state}}",area:"{{slot.session.group.parent.acronym}}",{% endif %}{% endif %} {% if slot.show_location %}room:"{{slot.get_location}}",{% endif %} dayname:"{{ slot.time|date:"l"|upper }}, {{ slot.time|date:"F j, Y" }}"{% if slot.session.agenda %}, agenda:"{{slot.session.agenda.get_absolute_url}}"{% endif %} });{% endif %}{% endfor %} {% endautoescape %} /* Saturday events need to be moved to the day -1 */ From 65f0fed7a770201c815c273e4dcb8100ae3dc275 Mon Sep 17 00:00:00 2001 From: Robert Sparks Date: Wed, 29 Apr 2015 14:39:17 +0000 Subject: [PATCH 06/15] checkpointing some css/html noodling before tearing into models - Legacy-Id: 9587 --- ietf/meeting/helpers.py | 4 +++- ietf/meeting/views.py | 5 +++-- ietf/templates/meeting/landscape_edit.html | 13 ++++++++++--- static/css/agenda/agenda.css | 2 ++ 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/ietf/meeting/helpers.py b/ietf/meeting/helpers.py index d5b75bcf9..2f964c3ee 100644 --- a/ietf/meeting/helpers.py +++ b/ietf/meeting/helpers.py @@ -66,7 +66,9 @@ def build_all_agenda_slices(meeting): time_slices = [] date_slices = {} - for ts in meeting.timeslot_set.exclude(type__in=['reg','break']).order_by('time','name'): + #for ts in meeting.timeslot_set.exclude(type__in=['reg','break']).order_by('time','name'): + #for ts in meeting.timeslot_set.exclude(type__in=['reg','break','lead','offagenda','other']).order_by('time','name'): + for ts in meeting.timeslot_set.filter(type__in=['session',]).order_by('time','name'): #for ts in meeting.timeslot_set.exclude(type__in=['reg','break','other']).order_by('time','name'): #for ts in meeting.timeslot_set.order_by('time','name'): #for ts in meeting.timeslot_set.filter(type='offagenda').order_by('time','name'): diff --git a/ietf/meeting/views.py b/ietf/meeting/views.py index 05d450219..04d132422 100644 --- a/ietf/meeting/views.py +++ b/ietf/meeting/views.py @@ -259,8 +259,9 @@ def edit_agenda(request, num=None, owner=None, name=None): meeting_base_url = request.build_absolute_uri(meeting.base_url()) site_base_url = request.build_absolute_uri('/')[:-1] # skip the trailing slash - rooms = meeting.room_set.order_by("capacity") - rooms = rooms.all() + #rooms = meeting.room_set.order_by("capacity") + #rooms = rooms.all() + rooms = meeting.room_set.filter(timeslot__type__slug='session').distinct().order_by("capacity") saveas = SaveAsForm() saveasurl=reverse(edit_agenda, args=[meeting.number, schedule.owner_email(), schedule.name]) diff --git a/ietf/templates/meeting/landscape_edit.html b/ietf/templates/meeting/landscape_edit.html index 916a602f9..4cfe34a58 100644 --- a/ietf/templates/meeting/landscape_edit.html +++ b/ietf/templates/meeting/landscape_edit.html @@ -110,6 +110,8 @@ promiselist.push(ss_promise);

Please save this agenda to your account first.

+
{% comment %} For preserving styling across the facelift {% endcomment %} +
@@ -206,10 +208,11 @@ promiselist.push(ss_promise);
- +{%comment%}
{%endcomment%} +
- + {% comment %}{% endcomment %} {% for day in time_slices %} - + {% comment %}{% endcomment %} {% for day in time_slices %} {% for slot in date_slices|lookup:day %} @@ -246,6 +249,7 @@ promiselist.push(ss_promise);
X
{{r.name}} ({{r.capacity}})
+{% comment 'The secretariat is not using these features' %} +{% endcomment %} {% for day in time_slices %} {% for slot in date_slices|lookup:day %} @@ -372,4 +377,6 @@ promiselist.push(ss_promise); + {% comment %} End of .content div {% endcomment %} + {% endblock %} diff --git a/static/css/agenda/agenda.css b/static/css/agenda/agenda.css index 44d419395..56f7207bd 100644 --- a/static/css/agenda/agenda.css +++ b/static/css/agenda/agenda.css @@ -18,6 +18,8 @@ .content table { border-collapse: separate; border-spacing: 2px; } +.container-fluid {padding-right: 0; padding-left:0;} + .ietf-navbar { background-color: #edf5ff; padding:0; border: 1px solid #89d; margin-top:4px; width: 130px; } .ietf-navbar ul { padding: 0; margin: 0; } .ietf-navbar ul li { list-style: none; padding: 0; margin: 0; font-size: 93%; padding: 2px 0px 2px 0px; } From 1e301207106b7df740b952c630b6f4c0e9791a61 Mon Sep 17 00:00:00 2001 From: Robert Sparks Date: Thu, 30 Apr 2015 15:57:48 +0000 Subject: [PATCH 07/15] 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; */ } From 72b85fc1c77dd27314e40364375d85adf1c3f98d Mon Sep 17 00:00:00 2001 From: Robert Sparks Date: Thu, 30 Apr 2015 21:44:45 +0000 Subject: [PATCH 08/15] checkpoint: views by type working - Legacy-Id: 9592 --- .../migrations/0005_auto_20150318_1116.py | 2 +- .../migrations/0006_auto_20150429_1224.py | 31 +++++++++++ .../migrations/0007_auto_20150429_1346.py | 30 +++++++++++ ietf/meeting/urls.py | 3 ++ ietf/meeting/views.py | 20 ++++++- ietf/secr/meetings/views.py | 7 ++- ietf/templates/meeting/agenda_by_type.html | 54 +++++++++++++++++++ 7 files changed, 144 insertions(+), 3 deletions(-) create mode 100644 ietf/meeting/migrations/0006_auto_20150429_1224.py create mode 100644 ietf/meeting/migrations/0007_auto_20150429_1346.py create mode 100644 ietf/templates/meeting/agenda_by_type.html diff --git a/ietf/meeting/migrations/0005_auto_20150318_1116.py b/ietf/meeting/migrations/0005_auto_20150318_1116.py index 1068f49df..2d28d53d5 100644 --- a/ietf/meeting/migrations/0005_auto_20150318_1116.py +++ b/ietf/meeting/migrations/0005_auto_20150318_1116.py @@ -67,7 +67,7 @@ def backfill_91_other_meetings(apps, schema_editor): ( 9, 17, 0, 120, 'offagenda', [secr], sea_pearl_12, 'Reception', "Companion's Reception"), # Should this appear on agenda? ( 9, 19, 0, 180, 'offagenda', [isocfell], rainbow_23, 'Dinner', 'ISOC Fellows Reception/Dinner'), ( 9, 19, 0, 180, 'offagenda', [secr], lehua_suite, 'Meeting', 'Huawei'), - ( 9, 21, 0, 180, 'lead', [secr], sea_pearl_12, 'Gathering', 'AMS/IESG/IABIAOC Gathering'), + ( 9, 21, 0, 180, 'lead', [secr], sea_pearl_12, 'Gathering', 'AMS/IESG/IAB/IAOC Gathering'), ( 10, 0, 0, 1440, 'offagenda', [secr], south_pacific_1, 'Terminal Room', 'Terminal Room Open to Attendees'), ( 10, 7, 0, 120, 'lead', [iesg,iab], south_pacific_2, 'Breakfast', 'IESG/IAB Breakfast'), ( 10, 7, 0, 120, 'lead', [nomcom], iolani_67, 'Breakfast', 'Nomcom Breakfast'), diff --git a/ietf/meeting/migrations/0006_auto_20150429_1224.py b/ietf/meeting/migrations/0006_auto_20150429_1224.py new file mode 100644 index 000000000..45e8f37b0 --- /dev/null +++ b/ietf/meeting/migrations/0006_auto_20150429_1224.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + +def extract_session_type_values(apps, schema_editor): + + Session = apps.get_model('meeting', 'Session') + + for s in Session.objects.all(): + t = s.scheduledsession_set.filter(schedule=models.F('schedule__meeting__agenda')).first() + if t and t.timeslot.type.slug != 'session': + s.type = t.timeslot.type + s.save() + +class Migration(migrations.Migration): + + dependencies = [ + ('name', '0004_auto_20150318_1140'), + ('meeting', '0005_auto_20150318_1116'), + ] + + operations = [ + migrations.AddField( + model_name='session', + name='type', + field=models.ForeignKey(default='session', to='name.TimeSlotTypeName'), + preserve_default=False, + ), + migrations.RunPython(extract_session_type_values), + ] diff --git a/ietf/meeting/migrations/0007_auto_20150429_1346.py b/ietf/meeting/migrations/0007_auto_20150429_1346.py new file mode 100644 index 000000000..a68a68f4e --- /dev/null +++ b/ietf/meeting/migrations/0007_auto_20150429_1346.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + +def extract_room_session_type_values(apps, schema_editor): + + Room = apps.get_model('meeting', 'Room') + + for r in Room.objects.all(): + for ts in r.timeslot_set.all(): + if ts.scheduledsession_set.filter(schedule=models.F('schedule__meeting__agenda')): + r.session_types.add(ts.type) + +class Migration(migrations.Migration): + + dependencies = [ + ('name', '0004_auto_20150318_1140'), + ('meeting', '0006_auto_20150429_1224'), + ] + + operations = [ + migrations.AddField( + model_name='room', + name='session_types', + field=models.ManyToManyField(to='name.TimeSlotTypeName', blank=True), + preserve_default=True, + ), + migrations.RunPython(extract_room_session_type_values), + ] diff --git a/ietf/meeting/urls.py b/ietf/meeting/urls.py index 429f8d723..351f3ab5b 100644 --- a/ietf/meeting/urls.py +++ b/ietf/meeting/urls.py @@ -34,6 +34,9 @@ urlpatterns = patterns('', (r'^(?P\d+)/agenda.ics$', views.ical_agenda), (r'^(?P\d+)/agenda(?P.csv)$', views.agenda), (r'^(?P\d+)/agenda/by-room$', views.agenda_by_room), + (r'^(?P\d+)/agenda/by-type$', views.agenda_by_type), + (r'^(?P\d+)/agenda/by-type/(?P[a-z]+)$', views.agenda_by_type), + (r'^(?P\d+)/agenda/by-type/(?P[a-z]+)/ics$', views.agenda_by_type_ics), (r'^(?P\d+)/agendas/edit$', views.edit_agendas), (r'^(?P\d+)/timeslots/edit$', views.edit_timeslots), (r'^(?P\d+)/rooms$', ajax.timeslot_roomsurl), diff --git a/ietf/meeting/views.py b/ietf/meeting/views.py index bf198ae36..ca02fdc85 100644 --- a/ietf/meeting/views.py +++ b/ietf/meeting/views.py @@ -388,7 +388,6 @@ def agenda(request, num=None, name=None, base=None, ext=None): #TODO - let the IAB in @role_required('Area Director','Secretariat') -@ensure_csrf_cookie def agenda_by_room(request,num=None): meeting = get_meeting(num) schedule = get_schedule(meeting) @@ -400,6 +399,25 @@ def agenda_by_room(request,num=None): ss_by_day[day].append(ss) return render(request,"meeting/agenda_by_room.html",{"meeting":meeting,"ss_by_day":ss_by_day}) +@role_required('Area Director','Secretariat') +def agenda_by_type(request,num=None,type=None): + meeting = get_meeting(num) + schedule = get_schedule(meeting) + scheduledsessions = schedule.scheduledsession_set.order_by('session__type__slug','timeslot__time') + if type: + scheduledsessions = scheduledsessions.filter(session__type__slug=type) + return render(request,"meeting/agenda_by_type.html",{"meeting":meeting,"scheduledsessions":scheduledsessions}) + +@role_required('Area Director','Secretariat') +def agenda_by_type_ics(request,num=None,type=None): + meeting = get_meeting(num) + schedule = get_schedule(meeting) + scheduledsessions = schedule.scheduledsession_set.order_by('session__type__slug','timeslot__time') + if type: + scheduledsessions = scheduledsessions.filter(session__type__slug=type) + updated = meeting_updated(meeting) + return render(request,"meeting/agenda.ics",{"schedule":schedule,"updated":updated,"assignments":scheduledsessions},content_type="text/calendar") + def read_agenda_file(num, doc): # XXXX FIXME: the path fragment in the code below should be moved to # settings.py. The *_PATH settings should be generalized to format() diff --git a/ietf/secr/meetings/views.py b/ietf/secr/meetings/views.py index e1b42e930..8b0ae1c98 100644 --- a/ietf/secr/meetings/views.py +++ b/ietf/secr/meetings/views.py @@ -53,10 +53,15 @@ def build_timeslots(meeting,room=None): or adding a room. ''' slots = meeting.timeslot_set.filter(type='session') + + # Don't do anything if the room is not capable of handling sessions + if not room.session_types.filter(slug='session'): + return + if room: rooms = [room] else: - rooms = meeting.room_set.all() + rooms = meeting.room_set.filter(session_types__slug='session') if not slots or room: # if we are just building timeslots for a new room, the room argument was passed, # then we need to use current meeting times as a template, not the last meeting times diff --git a/ietf/templates/meeting/agenda_by_type.html b/ietf/templates/meeting/agenda_by_type.html new file mode 100644 index 000000000..046154d02 --- /dev/null +++ b/ietf/templates/meeting/agenda_by_type.html @@ -0,0 +1,54 @@ +{% extends "base.html" %} +{% block morecss %} + +ul.typelist { list-style:none; padding-left:0; } +li.typelistentry { font-size:162%; font-weight:700; } +li.even { background-color:#EDF5FF; } +li.odd { background-color:white; } +ul.daylist {list-style:none; padding-left:0; margin-bottom:20px;} +li.daylistentry { margin-left:2em; font-weight: 400; } + +.sessiontable {margin-left:2em; font-size:62%;} +.sessiontable td {padding-right: 1em;} + +.typelabel { font-size:162%; font-weight:700; } +.daylabel { font-size:162%; font-weight:400; } +.even { background-color:#EDF5FF; } +.odd { background-color:white; } +{% comment %}li.sessionlistentry { font-size:62%; }{% endcomment %} + +.type-lead:after { content: " (DO NOT POST)"; color:red; } +.type-offagenda:after { content:" (not published on agenda)"; } + +{% endblock %} + +{% block title %}Agenda for {{meeting}} by Session Type{% endblock %} + +{% block content %} +

Agenda for {{meeting}} by Session Type

+{% regroup scheduledsessions by session.type.slug as type_list %} +
    +{% for type in type_list %} +
  • + {{type.grouper}} Download to Calendar +
      + {% regroup type.list by timeslot.time|date:"l Y-M-d" as daylist %} + {% for day in daylist %} +
    • + {{ day.grouper }} +
x
@@ -226,7 +229,7 @@ promiselist.push(ss_promise);
{{slot.0|date:'Hi'}}-{{slot.1|date:'Hi'}}
{% for resource in r.resources.all %} @@ -255,6 +259,7 @@ promiselist.push(ss_promise); {% endfor %}
+ {% for ss in day.list %} + + + + + + {% endfor %} +
{{ss.timeslot.time|date:"H:i"}}-{{ss.timeslot.end_time|date:"H:i"}}{{ss.timeslot.get_hidden_location}}{{ss.session.short_name}}
+ + {% endfor %} + + +{% endfor %} + +{% endblock %} From 303e886ee5f85dd6b81e9015e311b9c8c4183106 Mon Sep 17 00:00:00 2001 From: Robert Sparks Date: Thu, 30 Apr 2015 22:12:18 +0000 Subject: [PATCH 09/15] pulled several migrations from trunk and reordered the ones here to match - Legacy-Id: 9594 --- .../migrations/0004_auto_20150430_0847.py | 62 ++++++++++++++++ .../ipr/migrations/0003_auto_20150430_0847.py | 56 ++++++++++++++ .../migrations/0005_auto_20150430_0847.py | 74 +++++++++++++++++++ ...318_1116.py => 0006_auto_20150318_1116.py} | 4 +- ...429_1224.py => 0007_auto_20150429_1224.py} | 2 +- ...429_1346.py => 0008_auto_20150429_1346.py} | 2 +- .../migrations/0002_auto_20150430_0909.py | 26 +++++++ ietf/nomcom/models.py | 6 +- .../migrations/0002_auto_20150430_0847.py | 26 +++++++ 9 files changed, 251 insertions(+), 7 deletions(-) create mode 100644 ietf/group/migrations/0004_auto_20150430_0847.py create mode 100644 ietf/ipr/migrations/0003_auto_20150430_0847.py create mode 100644 ietf/meeting/migrations/0005_auto_20150430_0847.py rename ietf/meeting/migrations/{0005_auto_20150318_1116.py => 0006_auto_20150318_1116.py} (99%) rename ietf/meeting/migrations/{0006_auto_20150429_1224.py => 0007_auto_20150429_1224.py} (94%) rename ietf/meeting/migrations/{0007_auto_20150429_1346.py => 0008_auto_20150429_1346.py} (94%) create mode 100644 ietf/nomcom/migrations/0002_auto_20150430_0909.py create mode 100644 ietf/submit/migrations/0002_auto_20150430_0847.py diff --git a/ietf/group/migrations/0004_auto_20150430_0847.py b/ietf/group/migrations/0004_auto_20150430_0847.py new file mode 100644 index 000000000..71ce2d71b --- /dev/null +++ b/ietf/group/migrations/0004_auto_20150430_0847.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('group', '0003_auto_20150304_0743'), + ] + + operations = [ + migrations.AlterField( + model_name='group', + name='unused_states', + field=models.ManyToManyField(help_text=b'Document states that have been disabled for the group.', to='doc.State', blank=True), + preserve_default=True, + ), + migrations.AlterField( + model_name='group', + name='unused_tags', + field=models.ManyToManyField(help_text=b'Document tags that have been disabled for the group.', to='name.DocTagName', blank=True), + preserve_default=True, + ), + migrations.AlterField( + model_name='grouphistory', + name='unused_states', + field=models.ManyToManyField(help_text=b'Document states that have been disabled for the group.', to='doc.State', blank=True), + preserve_default=True, + ), + migrations.AlterField( + model_name='grouphistory', + name='unused_tags', + field=models.ManyToManyField(help_text=b'Document tags that have been disabled for the group.', to='name.DocTagName', blank=True), + preserve_default=True, + ), + migrations.AlterField( + model_name='groupmilestone', + name='resolved', + field=models.CharField(help_text=b'Explanation of why milestone is resolved (usually "Done"), or empty if still due.', max_length=50, blank=True), + preserve_default=True, + ), + migrations.AlterField( + model_name='groupmilestonehistory', + name='resolved', + field=models.CharField(help_text=b'Explanation of why milestone is resolved (usually "Done"), or empty if still due.', max_length=50, blank=True), + preserve_default=True, + ), + migrations.AlterField( + model_name='role', + name='email', + field=models.ForeignKey(help_text=b'Email address used by person for this role.', to='person.Email'), + preserve_default=True, + ), + migrations.AlterField( + model_name='rolehistory', + name='email', + field=models.ForeignKey(help_text=b'Email address used by person for this role.', to='person.Email'), + preserve_default=True, + ), + ] diff --git a/ietf/ipr/migrations/0003_auto_20150430_0847.py b/ietf/ipr/migrations/0003_auto_20150430_0847.py new file mode 100644 index 000000000..01e987e4c --- /dev/null +++ b/ietf/ipr/migrations/0003_auto_20150430_0847.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('ipr', '0002_remove_legacy_models'), + ] + + operations = [ + migrations.AlterField( + model_name='genericiprdisclosure', + name='holder_contact_info', + field=models.TextField(help_text=b'Address, phone, etc.', blank=True), + preserve_default=True, + ), + migrations.AlterField( + model_name='holderiprdisclosure', + name='holder_contact_info', + field=models.TextField(help_text=b'Address, phone, etc.', blank=True), + preserve_default=True, + ), + migrations.AlterField( + model_name='iprdisclosurebase', + name='compliant', + field=models.BooleanField(default=True, verbose_name=b'Complies to RFC3979'), + preserve_default=True, + ), + migrations.AlterField( + model_name='iprdisclosurebase', + name='notes', + field=models.TextField(verbose_name=b'Additional notes', blank=True), + preserve_default=True, + ), + migrations.AlterField( + model_name='iprdisclosurebase', + name='other_designations', + field=models.CharField(max_length=255, verbose_name=b'Designations for other contributions', blank=True), + preserve_default=True, + ), + migrations.AlterField( + model_name='nondocspecificiprdisclosure', + name='holder_contact_info', + field=models.TextField(help_text=b'Address, phone, etc.', blank=True), + preserve_default=True, + ), + migrations.AlterField( + model_name='thirdpartyiprdisclosure', + name='ietfer_contact_info', + field=models.TextField(help_text=b'Address, phone, etc.', blank=True), + preserve_default=True, + ), + ] diff --git a/ietf/meeting/migrations/0005_auto_20150430_0847.py b/ietf/meeting/migrations/0005_auto_20150430_0847.py new file mode 100644 index 000000000..06fbf34ba --- /dev/null +++ b/ietf/meeting/migrations/0005_auto_20150430_0847.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('meeting', '0004_auto_20150308_0446'), + ] + + operations = [ + migrations.AlterField( + model_name='meeting', + name='agenda_note', + field=models.TextField(help_text=b'Text in this field will be placed at the top of the html agenda page for the meeting. HTML can be used, but will not be validated.', blank=True), + preserve_default=True, + ), + migrations.AlterField( + model_name='schedule', + name='public', + field=models.BooleanField(default=True, help_text='Make this agenda publically available.'), + preserve_default=True, + ), + migrations.AlterField( + model_name='schedule', + name='visible', + field=models.BooleanField(default=True, help_text='Make this agenda available to those who know about it.'), + preserve_default=True, + ), + migrations.AlterField( + model_name='scheduledsession', + name='extendedfrom', + field=models.ForeignKey(default=None, to='meeting.ScheduledSession', help_text='Timeslot this session is an extension of.', null=True), + preserve_default=True, + ), + migrations.AlterField( + model_name='scheduledsession', + name='pinned', + field=models.BooleanField(default=False, help_text=b'Do not move session during automatic placement.'), + preserve_default=True, + ), + migrations.AlterField( + model_name='scheduledsession', + name='session', + field=models.ForeignKey(default=None, to='meeting.Session', help_text='Scheduled session.', null=True), + preserve_default=True, + ), + migrations.AlterField( + model_name='session', + name='name', + field=models.CharField(help_text=b'Name of session, in case the session has a purpose rather than just being a group meeting.', max_length=255, blank=True), + preserve_default=True, + ), + migrations.AlterField( + model_name='session', + name='short', + field=models.CharField(help_text=b"Short version of 'name' above, for use in filenames.", max_length=32, blank=True), + preserve_default=True, + ), + migrations.AlterField( + model_name='timeslot', + name='sessions', + field=models.ManyToManyField(related_name='slots', to='meeting.Session', through='meeting.ScheduledSession', blank=True, help_text='Scheduled session, if any.', null=True), + preserve_default=True, + ), + migrations.AlterField( + model_name='timeslot', + name='show_location', + field=models.BooleanField(default=True, help_text=b'Show location in agenda.'), + preserve_default=True, + ), + ] diff --git a/ietf/meeting/migrations/0005_auto_20150318_1116.py b/ietf/meeting/migrations/0006_auto_20150318_1116.py similarity index 99% rename from ietf/meeting/migrations/0005_auto_20150318_1116.py rename to ietf/meeting/migrations/0006_auto_20150318_1116.py index 2d28d53d5..b61bb3c8c 100644 --- a/ietf/meeting/migrations/0005_auto_20150318_1116.py +++ b/ietf/meeting/migrations/0006_auto_20150318_1116.py @@ -130,9 +130,9 @@ def backfill_91_other_meetings(apps, schema_editor): class Migration(migrations.Migration): dependencies = [ - ('meeting', '0004_auto_20150308_0446'), + ('meeting', '0005_auto_20150430_0847'), ('name', '0004_auto_20150318_1140'), - ('group', '0003_auto_20150304_0743'), + ('group', '0004_auto_20150430_0847'), ('person', '0004_auto_20150308_0440'), ] diff --git a/ietf/meeting/migrations/0006_auto_20150429_1224.py b/ietf/meeting/migrations/0007_auto_20150429_1224.py similarity index 94% rename from ietf/meeting/migrations/0006_auto_20150429_1224.py rename to ietf/meeting/migrations/0007_auto_20150429_1224.py index 45e8f37b0..43717f149 100644 --- a/ietf/meeting/migrations/0006_auto_20150429_1224.py +++ b/ietf/meeting/migrations/0007_auto_20150429_1224.py @@ -17,7 +17,7 @@ class Migration(migrations.Migration): dependencies = [ ('name', '0004_auto_20150318_1140'), - ('meeting', '0005_auto_20150318_1116'), + ('meeting', '0006_auto_20150318_1116'), ] operations = [ diff --git a/ietf/meeting/migrations/0007_auto_20150429_1346.py b/ietf/meeting/migrations/0008_auto_20150429_1346.py similarity index 94% rename from ietf/meeting/migrations/0007_auto_20150429_1346.py rename to ietf/meeting/migrations/0008_auto_20150429_1346.py index a68a68f4e..24485e2fd 100644 --- a/ietf/meeting/migrations/0007_auto_20150429_1346.py +++ b/ietf/meeting/migrations/0008_auto_20150429_1346.py @@ -16,7 +16,7 @@ class Migration(migrations.Migration): dependencies = [ ('name', '0004_auto_20150318_1140'), - ('meeting', '0006_auto_20150429_1224'), + ('meeting', '0007_auto_20150429_1224'), ] operations = [ diff --git a/ietf/nomcom/migrations/0002_auto_20150430_0909.py b/ietf/nomcom/migrations/0002_auto_20150430_0909.py new file mode 100644 index 000000000..7a15833ac --- /dev/null +++ b/ietf/nomcom/migrations/0002_auto_20150430_0909.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('nomcom', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='nomcom', + name='reminder_interval', + field=models.PositiveIntegerField(help_text=b'If the nomcom user sets the interval field then a cron command will send reminders to the nominees who have not responded using the following formula: (today - nomination_date) % interval == 0.', null=True, blank=True), + preserve_default=True, + ), + migrations.AlterField( + model_name='nomcom', + name='send_questionnaire', + field=models.BooleanField(default=False, help_text=b'If you check this box, questionnaires are sent automatically after nominations.', verbose_name=b'Send questionnaires automatically'), + preserve_default=True, + ), + ] diff --git a/ietf/nomcom/models.py b/ietf/nomcom/models.py index 712230635..bece016f7 100644 --- a/ietf/nomcom/models.py +++ b/ietf/nomcom/models.py @@ -38,9 +38,9 @@ class NomCom(models.Model): group = models.ForeignKey(Group) send_questionnaire = models.BooleanField(verbose_name='Send questionnaires automatically', default=False, help_text='If you check this box, questionnaires are sent automatically after nominations.') - reminder_interval = models.PositiveIntegerField(help_text='If the nomcom user sets the interval field then a cron command will \ - send reminders to the nominees who have not responded using \ - the following formula: (today - nomination_date) % interval == 0.', + reminder_interval = models.PositiveIntegerField(help_text='If the nomcom user sets the interval field then a cron command will ' + 'send reminders to the nominees who have not responded using ' + 'the following formula: (today - nomination_date) % interval == 0.', blank=True, null=True) initial_text = models.TextField(verbose_name='Help text for nomination form', blank=True) diff --git a/ietf/submit/migrations/0002_auto_20150430_0847.py b/ietf/submit/migrations/0002_auto_20150430_0847.py new file mode 100644 index 000000000..9fa60bc2d --- /dev/null +++ b/ietf/submit/migrations/0002_auto_20150430_0847.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('submit', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='submission', + name='authors', + field=models.TextField(help_text=b'List of author names and emails, one author per line, e.g. "John Doe <john@example.org>".', blank=True), + preserve_default=True, + ), + migrations.AlterField( + model_name='submission', + name='submitter', + field=models.CharField(help_text=b'Name and email of submitter, e.g. "John Doe <john@example.org>".', max_length=255, blank=True), + preserve_default=True, + ), + ] From 17b928b94bca46b3f0ec1742be5c9190be25d1ca Mon Sep 17 00:00:00 2001 From: Robert Sparks Date: Fri, 1 May 2015 22:31:30 +0000 Subject: [PATCH 10/15] checkpoint: added room functional description, backfilled ietf92 meeting data, repaired session material views, added tests - Legacy-Id: 9596 --- .../migrations/0009_room_functional_name.py | 20 ++ .../migrations/0010_auto_20150501_0732.py | 49 +++++ .../migrations/0011_ietf92_meetings.py | 191 ++++++++++++++++++ ietf/meeting/models.py | 12 ++ ietf/meeting/test_data.py | 8 +- ietf/meeting/tests_api.py | 2 +- ietf/meeting/tests_views.py | 27 ++- ietf/meeting/views.py | 7 +- ietf/secr/meetings/tests.py | 2 +- ietf/templates/meeting/agenda_by_room.html | 8 +- ietf/templates/meeting/session_details.html | 4 +- 11 files changed, 315 insertions(+), 15 deletions(-) create mode 100644 ietf/meeting/migrations/0009_room_functional_name.py create mode 100644 ietf/meeting/migrations/0010_auto_20150501_0732.py create mode 100644 ietf/meeting/migrations/0011_ietf92_meetings.py diff --git a/ietf/meeting/migrations/0009_room_functional_name.py b/ietf/meeting/migrations/0009_room_functional_name.py new file mode 100644 index 000000000..4170f3b59 --- /dev/null +++ b/ietf/meeting/migrations/0009_room_functional_name.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('meeting', '0008_auto_20150429_1346'), + ] + + operations = [ + migrations.AddField( + model_name='room', + name='functional_name', + field=models.CharField(default='', max_length=255, blank=True), + preserve_default=False, + ), + ] diff --git a/ietf/meeting/migrations/0010_auto_20150501_0732.py b/ietf/meeting/migrations/0010_auto_20150501_0732.py new file mode 100644 index 000000000..7c52f7634 --- /dev/null +++ b/ietf/meeting/migrations/0010_auto_20150501_0732.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations + + +def add_91_room_functional_names(apps, schema_editor): + + map = { + 'Hibiscus': 'Breakout 3', + 'South Pacific 2': 'Meeting Room #6', + 'South Pacific 1': 'Terminal Room', + 'Coral 1': 'Breakout 4', + 'Coral 2': 'Breakout 5', + 'Coral 5': 'Breakout 6', + 'Coral 4': 'Breakout 7', + 'Coral 3': 'Breakout 8', + 'Great Lawn': 'Welcome Reception', + 'Rainbow Suite': 'Not Used', + 'Lehua Suite': 'Breakout 1', + 'Kahili': 'Breakout 2', + 'Rainbow Suite 1/2': 'Meeting Room #2 (IESG Meeting Room)', + 'Village Green': 'Meet and Greet', + 'South Pacific 3': 'Meeting Room #4 (IAOC/IAD Office)', + 'Rainbow Suite 3': 'Meeting Room #7', + 'Rainbow Suite 2/3': 'ISOC Dinner', + 'South Pacific 3/4': 'ISOC AC Meeting', + 'Iolani 6/7': 'Meeting Room #5 (NomCom Office)', + 'Sea Pearl 1/2': 'Reception', + 'Sea Pearl 2': 'Meeting Room #1 (IAB Meeting Room)', + 'Coral Lounge': 'Registration Area and Breaks', + 'Tiare Suite': 'Meeting Room #8 (RFC Office)', + } + + Room = apps.get_model('meeting', 'Room') + + for name,functional_name in map.items(): + Room.objects.filter(meeting__number=91,name=name).update(functional_name=functional_name) + +class Migration(migrations.Migration): + + dependencies = [ + ('meeting', '0009_room_functional_name'), + ] + + operations = [ + migrations.RunPython(add_91_room_functional_names), + ] + diff --git a/ietf/meeting/migrations/0011_ietf92_meetings.py b/ietf/meeting/migrations/0011_ietf92_meetings.py new file mode 100644 index 000000000..7d61d205a --- /dev/null +++ b/ietf/meeting/migrations/0011_ietf92_meetings.py @@ -0,0 +1,191 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +import datetime +from django.db import migrations + + +def backfill_92_other_meetings(apps, schema_editor): + + Meeting = apps.get_model('meeting', 'Meeting') + Schedule = apps.get_model('meeting', 'Schedule') + ScheduledSession = apps.get_model('meeting', 'ScheduledSession') + Room = apps.get_model('meeting', 'Room') + Session = apps.get_model('meeting', 'Session') + Group = apps.get_model('group', 'Group') + Person = apps.get_model('person', 'Person') + + ietf92 = Meeting.objects.filter(number=92).first() + + if not ietf92: + print "IETF92 not found, no data changed" + else: + + # Clear out one orphaned ill-configured Session object + qs = Session.objects.filter(meeting__number=92,name__icontains='beverage break').exclude(type_id='break') + if qs.count()==1: + qs.delete() + + agenda92 = Schedule.objects.get(meeting=ietf92,pk=ietf92.agenda.pk) + + map_existing = { + 'Regency Ballroom': 'Lounge', + 'Garden Terrace Level': 'Meet and Greet', + 'Royal': 'Breakout 1', + 'Continental': 'Breakout 2', + 'Far East': 'Breakout 3', + 'Oak ': 'Breakout 4', + 'Parisian': 'Breakout 5', + 'Venetian': 'Breakout 6', + 'Gold': 'Breakout 7', + 'International': 'Breakout 8', + 'Brasserie': 'Terminal Room', + 'State': 'Office #3 (Secretariat Office)', + 'French': 'Meeting Room #2 (IESG Meeting Room)', + } + + for name,functional_name in map_existing.items(): + Room.objects.filter(meeting__number=92,name=name).update(functional_name=functional_name) + + regency = Room.objects.get(meeting=ietf92,name='Regency Ballroom') + garden = Room.objects.get(meeting=ietf92,name='Garden Terrace Level') + royal = Room.objects.get(meeting=ietf92,name='Royal') + continental = Room.objects.get(meeting=ietf92,name='Continental') + far_east = Room.objects.get(meeting=ietf92,name='Far East') + oak = Room.objects.get(meeting=ietf92,name='Oak ') + #parisian = Room.objects.get(meeting=ietf92,name='Parisian') + #venetian = Room.objects.get(meeting=ietf92,name='Venetian') + #gold = Room.objects.get(meeting=ietf92,name='Gold') + #international = Room.objects.get(meeting=ietf92,name='International') + brasserie = Room.objects.get(meeting=ietf92,name='Brasserie') + state = Room.objects.get(meeting=ietf92,name='State') + #french = Room.objects.get(meeting=ietf92,name='French') + + executive = Room.objects.create(meeting=ietf92,name='Executive',functional_name='Meeting Room #4 (IAOC/IAD)',capacity=20) + regency_foyer = Room.objects.create(meeting=ietf92,name='Regency Foyer',functional_name='Registration',capacity=1200) + florentine = Room.objects.create(meeting=ietf92,name='Florentine',functional_name='Meeting Room #1 (IAB)', capacity=40) + pavilion = Room.objects.create(meeting=ietf92,name='Pavilion',functional_name='Meeting Room #6', capacity=80) + terrace = Room.objects.create(meeting=ietf92,name='Terrace',functional_name='Meeting Room #7', capacity=80) + panorama = Room.objects.create(meeting=ietf92,name='Panorama',functional_name='Companion Reception', capacity=200) + + regency.session_types.add('offagenda') + pavilion.session_types.add('offagenda') + pavilion.session_types.add('lead') + garden.session_types.add('lead') + panorama.session_types.add('offagenda') + executive.session_types.add('lead') + executive.session_types.add('offagenda') + regency_foyer.session_types.add('offagenda') + oak.session_types.add('offagenda') + continental.session_types.add('offagenda') + state.session_types.add('offagenda') + florentine.session_types.add('offagenda') + terrace.session_types.add('lead') + terrace.session_types.add('offagenda') + far_east.session_types.add('offagenda') + brasserie.session_types.add('offagenda') + royal.session_types.add('offagenda') + + iesg = Group.objects.get(acronym='iesg') + iab = Group.objects.get(acronym='iab') + iaoc = Group.objects.get(acronym='iaoc') + secr = Group.objects.get(acronym='secretariat') + + system = Person.objects.get(name='(System)') + + for d, h, m, duration, type_id, groups, room, slotname, label in [ + ( 20, 13, 0, 480, 'offagenda', [secr], brasserie, 'Setup', 'Hackathon: Setup'), + ( 20, 8, 0, 540, 'offagenda', [secr], executive, 'Meeting', 'DNS OARC Meeting'), + ( 21, 8, 0, 540, 'offagenda', [secr], executive, 'Meeting', 'DNS OARC Meeting'), + ( 22, 12, 0, 720, 'offagenda', [secr], brasserie, 'Terminal Room', 'Terminal Room Open to Attendees'), + ( 22, 11, 0, 480, 'offagenda', [secr], regency_foyer, 'T-Shirt Distribution', 'T-shirt Distribution'), + ( 22, 19, 0, 120, 'offagenda', [secr], state, 'Meeting', 'CJK Generation Panel coordination informal meeting'), + ( 22, 19, 0, 120, 'offagenda', [iab], florentine, 'Meeting', 'IAB PrivSec program'), + ( 22, 8, 30, 90, 'lead', [iesg], pavilion, 'Breakfast', None), + ( 22, 9, 0, 150, 'lead', [iesg], pavilion, 'Meeting', None), + ( 22, 11, 30, 150, 'lead', [iab,iesg], pavilion, 'Lunch', 'IESG/IAB Lunch'), + ( 22, 14, 0, 180, 'lead', [iab], pavilion, 'Meeting', None), + ( 22, 9, 0, 480, 'offagenda', [secr], terrace, 'Meeting', 'RootOPS'), + ( 22, 16, 30, 60, 'offagenda', [secr], panorama, 'Reception', "Companion's Reception"), # Should this appear on agenda? + ( 22, 21, 0, 180, 'lead', [secr], garden, 'Gathering', 'AMS/IESG/IAB/IAOC Gathering'), + ( 22, 9, 0, 480, 'offagenda', [secr], royal, 'ICNRG', 'ICNRG'), + ( 22, 19, 0, 180, 'offagenda', [secr], royal, 'Meeting', 'Huawei'), + ( 22, 12, 30, 240, 'offagenda', [secr], continental, 'Meeting', 'Verisign ROA Workshop'), + ( 22, 15, 15, 165, 'offagenda', [secr], far_east, 'Meeting', 'RSSAC'), + ( 22, 9, 0, 150, 'offagenda', [secr], oak, 'Meeting', 'Ericsson'), + ( 23, 0, 0, 1440, 'offagenda', [secr], brasserie, 'Terminal Room', 'Terminal Room Open to Attendees'), + ( 23, 8, 0, 600, 'offagenda', [secr], regency_foyer, 'T-Shirt Distribution', 'T-shirt Distribution'), + ( 23, 0, 0, 1440, 'offagenda', [secr], regency, 'Lounge', 'Lounge'), + ( 23, 11, 30, 180, 'offagenda', [secr], executive, 'Lunch', 'ICANN Lunch'), + ( 23, 7, 0, 120, 'lead', [iab,iesg], pavilion, 'Breakfast', 'IESG/IAB Breakfast'), + ( 23, 11, 30, 90, 'offagenda', [secr], pavilion, 'Meeting', 'OPS Directorate Meeting'), + ( 23, 19, 0, 120, 'offagenda', [secr], pavilion, 'Meeting', 'ACE'), + ( 23, 7, 30, 90, 'offagenda', [secr], terrace, 'Meeting', 'NRO ECG'), + ( 23, 11, 30, 90, 'offagenda', [secr], terrace, 'Meeting', 'IETF/3GPP Meeting'), + ( 23, 19, 0, 120, 'offagenda', [secr], terrace, 'Meeting', 'I2NSF'), + ( 23, 18, 50, 60, 'offagenda', [secr], royal, 'Meeting', 'Captive Portal Bar BOF'), + ( 24, 0, 0, 1440, 'offagenda', [secr], brasserie, 'Terminal Room', 'Terminal Room Open to Attendees'), + ( 24, 8, 0, 600, 'offagenda', [secr], regency_foyer, 'T-Shirt Distribution', 'T-shirt Distribution'), + ( 24, 0, 0, 1440, 'offagenda', [secr], regency, 'Lounge', 'Lounge'), + ( 24, 11, 30, 90, 'offagenda', [secr], state, 'Meeting', 'HIAPS'), + ( 24, 16, 30, 120, 'offagenda', [secr], state, 'Meeting', 'PDF Draft Review'), + ( 24, 7, 0, 120, 'lead', [iesg], pavilion, 'Breakfast', None), + ( 24, 11, 30, 90, 'offagenda', [secr], pavilion, 'Meeting', 'SECdir Meeting'), + ( 24, 7, 0, 120, 'lead', [iab], terrace, 'Breakfast', None), + ( 24, 9, 0, 120, 'offagenda', [secr], terrace, 'Meeting', 'ICNN DRZK Design Team'), + ( 24, 11, 30, 90, 'offagenda', [secr], terrace, 'Lunch', 'RSAG/ISEB Lunch'), + ( 24, 13, 0, 120, 'offagenda', [secr], terrace, 'Meeting', 'SACM'), + ( 24, 15, 0, 90, 'offagenda', [secr], terrace, 'Meeting', 'RSOC Meeting'), + ( 24, 17, 30, 60, 'offagenda', [secr], terrace, 'Meeting', 'SACM'), + ( 24, 11, 30, 90, 'offagenda', [secr], royal, 'Meeting', 'IoT Directorate'), + ( 25, 0, 0, 1440, 'offagenda', [secr], brasserie, 'Terminal Room', 'Terminal Room Open to Attendees'), + ( 25, 8, 0, 600, 'offagenda', [secr], regency_foyer, 'T-Shirt Distribution', 'T-shirt Distribution'), + ( 25, 0, 0, 1440, 'offagenda', [secr], regency, 'Lounge', 'Lounge'), + ( 25, 8, 0, 60, 'offagenda', [secr], state, 'Meeting', 'SFC Control Plane Offline Discussion'), + ( 25, 19, 0, 240, 'offagenda', [secr], state, 'Meeting', 'WWG'), + ( 25, 8, 0, 60, 'offagenda', [secr], florentine, 'Meeting', 'IAB Name Resolution'), + ( 25, 6, 45, 135, 'lead', [iaoc], executive, 'Breakfast', None), + ( 25, 11, 30, 90, 'offagenda', [secr], pavilion, 'Meeting', 'RMCAT'), + ( 25, 19, 0, 120, 'offagenda', [secr], pavilion, 'Meeting', 'I2NSF'), + ( 25, 8, 0, 60, 'offagenda', [secr], terrace, 'Meeting', 'IETF/IEEE 802 Coordination'), + ( 25, 11, 30, 90, 'offagenda', [secr], terrace, 'Lunch', 'RFC Editor Lunch'), + ( 25, 19, 30, 120, 'offagenda', [secr], terrace, 'Dinner', 'SSAC Dinner'), + ( 26, 0, 0, 1440, 'offagenda', [secr], brasserie, 'Terminal Room', 'Terminal Room Open to Attendees'), + ( 26, 8, 0, 600, 'offagenda', [secr], regency_foyer, 'T-Shirt Distribution', 'T-shirt Distribution'), + ( 26, 0, 0, 1440, 'offagenda', [secr], regency, 'Lounge', 'Lounge'), + ( 26, 7, 30, 90, 'offagenda', [secr], state, 'Breakfast', 'EDU Team Breakfast'), + ( 26, 14, 0, 120, 'offagenda', [secr], state, 'Meeting', 'JJB'), + ( 26, 11, 30, 90, 'offagenda', [secr], florentine, 'Meeting', 'IAB Liaison Oversight'), + ( 26, 18, 0, 150, 'offagenda', [secr], pavilion, 'Meeting', '6LO Security Discussion'), + ( 26, 7, 0, 120, 'lead', [iab], terrace, 'Breakfast', None), + ( 26, 17, 40, 60, 'offagenda', [secr], terrace, 'Meeting', 'SACM'), + ( 26, 19, 30, 150, 'offagenda', [secr], royal, 'Meeting', 'Lavabit'), + ( 27, 0, 0, 900, 'offagenda', [secr], brasserie, 'Terminal Room', 'Terminal Room Open to Attendees'), + ( 27, 7, 30, 90, 'offagenda', [secr], executive, 'Meeting', 'Post-Con with Ray'), + ( 27, 13, 30, 90, 'lead', [iab,iesg], pavilion, 'Lunch', 'IESG/IAB Lunch'), + ]: + + ts = ietf92.timeslot_set.create(type_id=type_id, name=slotname, + time=datetime.datetime(2015,3,d,h,m,0), + duration=datetime.timedelta(minutes=duration), + location=room,show_location=(type_id not in ['lead','offagenda'])) + for group in groups: + session = ietf92.session_set.create(name= label or "%s %s"%(group.acronym.upper(),slotname), + group=group, attendees=25, + requested=datetime.datetime(2014,11,1,0,0,0), + requested_by=system, status_id='sched',type_id=type_id) + ScheduledSession.objects.create(schedule=agenda92, timeslot=ts, session=session) + + +class Migration(migrations.Migration): + + dependencies = [ + ('meeting', '0010_auto_20150501_0732'), + ('name', '0004_auto_20150318_1140'), + ('group', '0004_auto_20150430_0847'), + ('person', '0004_auto_20150308_0440'), + ] + + operations = [ + migrations.RunPython(backfill_92_other_meetings) + ] diff --git a/ietf/meeting/models.py b/ietf/meeting/models.py index 680654c78..bcecac490 100644 --- a/ietf/meeting/models.py +++ b/ietf/meeting/models.py @@ -287,6 +287,7 @@ class ResourceAssociation(models.Model): class Room(models.Model): meeting = models.ForeignKey(Meeting) name = models.CharField(max_length=255) + functional_name = models.CharField(max_length=255, blank = True) capacity = models.IntegerField(null=True, blank=True) resources = models.ManyToManyField(ResourceAssociation, blank = True) session_types = models.ManyToManyField(TimeSlotTypeName, blank = True) @@ -374,6 +375,7 @@ class TimeSlot(models.Model): return u"%s: %s-%s %s, %s" % (self.meeting.number, self.time.strftime("%m-%d %H:%M"), (self.time + self.duration).strftime("%H:%M"), self.name, location) def end_time(self): return self.time + self.duration + def get_hidden_location(self): location = self.location if location: @@ -390,6 +392,16 @@ class TimeSlot(models.Model): location = "" return location + def get_functional_location(self): + name_parts = [] + room = self.location + if room and room.functional_name: + name_parts.append(room.functional_name) + location = self.get_hidden_location() + if location: + name_parts.append(location) + return ' - '.join(name_parts) + @property def tz(self): if self.meeting.time_zone: diff --git a/ietf/meeting/test_data.py b/ietf/meeting/test_data.py index 0aa18d10f..0053eb558 100644 --- a/ietf/meeting/test_data.py +++ b/ietf/meeting/test_data.py @@ -59,20 +59,20 @@ def make_meeting_test_data(): meeting.agenda = schedule meeting.save() - doc = Document.objects.create(name='agenda-mars-ietf-42', type_id='agenda', title="Agenda", external_url="agenda-mars.txt",group=mars) + doc = Document.objects.create(name='agenda-mars-ietf-42', type_id='agenda', title="Agenda", external_url="agenda-mars.txt",group=mars,rev='00') doc.set_state(State.objects.get(type=doc.type_id, slug="active")) 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.txt",group=mars) + doc = Document.objects.create(name='minutes-mars-ietf-42', type_id='minutes', title="Minutes", external_url="minutes-mars.txt",group=mars,rev='00') doc.set_state(State.objects.get(type=doc.type_id, slug="active")) 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.txt",group=mars) + doc = Document.objects.create(name='slides-mars-ietf-42', type_id='slides', title="Slideshow", external_url="slides-mars.txt",group=mars,rev='00') doc.set_state(State.objects.get(type=doc.type_id, slug="active")) doc.set_state(State.objects.get(type='reuse_policy',slug='single')) mars_session.sessionpresentation_set.add(SessionPresentation(session=mars_session,document=doc,rev=doc.rev)) - doc = Document.objects.create(name='slides-mars-ietf-42-deleted', type_id='slides', title="Bad Slideshow", external_url="slides-mars-deleted.txt",group=mars) + doc = Document.objects.create(name='slides-mars-ietf-42-deleted', type_id='slides', title="Bad Slideshow", external_url="slides-mars-deleted.txt",group=mars,rev='00') doc.set_state(State.objects.get(type=doc.type_id, slug="deleted")) doc.set_state(State.objects.get(type='reuse_policy',slug='single')) mars_session.sessionpresentation_set.add(SessionPresentation(session=mars_session,document=doc,rev=doc.rev)) diff --git a/ietf/meeting/tests_api.py b/ietf/meeting/tests_api.py index 5c3fe0fd8..5953c928b 100644 --- a/ietf/meeting/tests_api.py +++ b/ietf/meeting/tests_api.py @@ -138,7 +138,7 @@ class ApiTests(TestCase): timeslots_before = meeting.timeslot_set.count() url = urlreverse("ietf.meeting.ajax.timeslot_roomsurl", kwargs=dict(num=meeting.number)) - post_data = { "name": "new room", "capacity": "50" , "resources": []} + post_data = { "name": "new room", "capacity": "50" , "resources": [], "session_types":["session"]} # unauthorized post r = self.client.post(url, post_data) diff --git a/ietf/meeting/tests_views.py b/ietf/meeting/tests_views.py index a1db83d9a..1e48885b3 100644 --- a/ietf/meeting/tests_views.py +++ b/ietf/meeting/tests_views.py @@ -128,9 +128,34 @@ class MeetingTests(TestCase): meeting = make_meeting_test_data() url = urlreverse("ietf.meeting.views.agenda_by_room",kwargs=dict(num=meeting.number)) login_testing_unauthorized(self,"secretary",url) - r = self.client.get(url,kwargs=dict(num=meeting.number)) + r = self.client.get(url) self.assertTrue(all([x in r.content for x in ['mars','IESG Breakfast','Test Room','Breakfast Room']])) + def test_agenda_by_type(self): + meeting = make_meeting_test_data() + + url = urlreverse("ietf.meeting.views.agenda_by_type",kwargs=dict(num=meeting.number)) + login_testing_unauthorized(self,"secretary",url) + r = self.client.get(url) + self.assertTrue(all([x in r.content for x in ['mars','IESG Breakfast','Test Room','Breakfast Room']])) + + url = urlreverse("ietf.meeting.views.agenda_by_type",kwargs=dict(num=meeting.number,type='session')) + r = self.client.get(url) + self.assertTrue(all([x in r.content for x in ['mars','Test Room']])) + self.assertFalse(any([x in r.content for x in ['IESG Breakfast','Breakfast Room']])) + + url = urlreverse("ietf.meeting.views.agenda_by_type",kwargs=dict(num=meeting.number,type='lead')) + r = self.client.get(url) + self.assertFalse(any([x in r.content for x in ['mars','Test Room']])) + self.assertTrue(all([x in r.content for x in ['IESG Breakfast','Breakfast Room']])) + + def test_session_details(self): + meeting = make_meeting_test_data() + url = urlreverse("ietf.meeting.views.session_details", kwargs=dict(num=meeting.number, acronym="mars")) + r = self.client.get(url) + self.assertTrue(all([x in r.content for x in ('slides','agenda','minutes')])) + self.assertFalse('deleted' in r.content) + def test_materials(self): meeting = make_meeting_test_data() session = Session.objects.filter(meeting=meeting, group__acronym="mars").first() diff --git a/ietf/meeting/views.py b/ietf/meeting/views.py index ca02fdc85..a5c202599 100644 --- a/ietf/meeting/views.py +++ b/ietf/meeting/views.py @@ -394,7 +394,7 @@ def agenda_by_room(request,num=None): ss_by_day = OrderedDict() for day in schedule.scheduledsession_set.dates('timeslot__time','day'): ss_by_day[day]=[] - for ss in schedule.scheduledsession_set.order_by('timeslot__location','timeslot__time'): + for ss in schedule.scheduledsession_set.order_by('timeslot__location__functional_name','timeslot__location__name','timeslot__time'): day = ss.timeslot.time.date() ss_by_day[day].append(ss) return render(request,"meeting/agenda_by_room.html",{"meeting":meeting,"ss_by_day":ss_by_day}) @@ -673,7 +673,7 @@ def meeting_requests(request, num=None) : 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) + sessions = Session.objects.filter(meeting=meeting,group__acronym=acronym,type__in=['session','plenary','other']) if not sessions: sessions = Session.objects.filter(meeting=meeting,short=acronym) @@ -720,11 +720,14 @@ def session_details(request, num, acronym, date=None, week_day=None, seq=None) : 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]) + # TODO FIXME Deleted materials shouldn't be in the sessionpresentation_set + filtered_sessionpresentation_set = [p for p in session.sessionpresentation_set.all() if p.document.get_state_slug(p.document.type_id)!='deleted'] return render(request, "meeting/session_details.html", { 'session':sessions[0] , 'meeting' :meeting , 'acronym' :acronym, 'time': scheduled_time, + 'filtered_sessionpresentation_set': filtered_sessionpresentation_set }) else: return render(request, "meeting/session_list.html", diff --git a/ietf/secr/meetings/tests.py b/ietf/secr/meetings/tests.py index ad9a1eb3f..5e8eb6bbe 100644 --- a/ietf/secr/meetings/tests.py +++ b/ietf/secr/meetings/tests.py @@ -147,7 +147,7 @@ class MainTestCase(TestCase): response = self.client.get(url) self.assertEqual(response.status_code, 200) q = PyQuery(response.content) - self.assertEqual(len(q("#id_rooms_table tr input[type='text']")),meeting.room_set.count()) + self.assertEqual(len(q("#id_rooms_table tr input[type='checkbox']")),meeting.room_set.count()) # test delete # first unschedule sessions so we can delete diff --git a/ietf/templates/meeting/agenda_by_room.html b/ietf/templates/meeting/agenda_by_room.html index 399c6f841..7871af1ab 100644 --- a/ietf/templates/meeting/agenda_by_room.html +++ b/ietf/templates/meeting/agenda_by_room.html @@ -9,8 +9,8 @@ li.roomlistentry { font-weight: 400; } ul.sessionlist { list-style:none; padding-left:2em; margin-bottom:10px;} li.sessionlistentry { font-size:62%; } -.lead:after { content: " (DO NOT POST)"; color:red; } -.offagenda:after { content:" (not published on agenda)"; } +.type-lead:after { content: " (DO NOT POST)"; color:red; } +.type-offagenda:after { content:" (not published on agenda)"; } {% endblock %} @@ -21,13 +21,13 @@ li.sessionlistentry { font-size:62%; }
    {% for day,sessions in ss_by_day.items %}
  • {{day|date:'l, j F Y'}} -{% regroup sessions by timeslot.get_hidden_location as room_list %} +{% regroup sessions by timeslot.get_functional_location as room_list %}
      {% for room in room_list %}
    • {{room.grouper|default:"Location Unavailable"}}
        {% for ss in room.list %} -
      • {{ss.timeslot.time|date:"H:i"}}-{{ss.timeslot.end_time|date:"H:i"}} {{ss.session.short_name}}
      • +
      • {{ss.timeslot.time|date:"H:i"}}-{{ss.timeslot.end_time|date:"H:i"}} {{ss.session.short_name}}
      • {% endfor %}
    • diff --git a/ietf/templates/meeting/session_details.html b/ietf/templates/meeting/session_details.html index 68cc580b9..fe86627c6 100644 --- a/ietf/templates/meeting/session_details.html +++ b/ietf/templates/meeting/session_details.html @@ -12,11 +12,11 @@

      {{ session.name }}

      {% endif %} - {% if session.sessionpresentation_set.all.count %} + {% if filtered_sessionpresentation_set %}

      Materials:

      From 525ad030abb5ebd153447dd20c89ffc02071cfed Mon Sep 17 00:00:00 2001 From: Robert Sparks Date: Mon, 4 May 2015 13:09:41 +0000 Subject: [PATCH 11/15] some tweaks to the history - Legacy-Id: 9597 --- ietf/meeting/migrations/0006_auto_20150318_1116.py | 9 ++++++--- ietf/meeting/migrations/0011_ietf92_meetings.py | 10 +++++++--- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/ietf/meeting/migrations/0006_auto_20150318_1116.py b/ietf/meeting/migrations/0006_auto_20150318_1116.py index b61bb3c8c..1049d26d9 100644 --- a/ietf/meeting/migrations/0006_auto_20150318_1116.py +++ b/ietf/meeting/migrations/0006_auto_20150318_1116.py @@ -60,7 +60,8 @@ def backfill_91_other_meetings(apps, schema_editor): ( 9, 9, 0, 360, 'offagenda', [secr], hibiscus, 'Meeting', 'RootOPS'), ( 9, 9, 30, 360, 'offagenda', [secr], kahili, 'TLS Interim', 'TLS WG Interim'), ( 9, 11, 0, 480, 'offagenda', [secr], coral_lounge, 'T-Shirt Distribution', 'T-shirt Distribution'), - ( 9, 11, 30, 150, 'lead', [iesg,iab], south_pacific_2, 'Lunch', 'IAB/IESG Lunch'), + ( 9, 11, 30, 150, 'lead', [iesg], south_pacific_2, 'Lunch', 'IESG Lunch with the IAB'), + ( 9, 11, 30, 150, 'lead', [iab], south_pacific_2, 'Lunch', 'IAB Lunch with the IESG'), ( 9, 12, 0, 360, 'offagenda', [secr], south_pacific_1, 'Terminal Room', 'Terminal Room Open to Attendees'), ( 9, 14, 0, 180, 'lead', [iab], south_pacific_2, 'Meeting', None), ( 9, 16, 0, 120, 'offagenda', [secr], coral_2, 'Meeting', 'Web Object Encryption'), @@ -69,7 +70,8 @@ def backfill_91_other_meetings(apps, schema_editor): ( 9, 19, 0, 180, 'offagenda', [secr], lehua_suite, 'Meeting', 'Huawei'), ( 9, 21, 0, 180, 'lead', [secr], sea_pearl_12, 'Gathering', 'AMS/IESG/IAB/IAOC Gathering'), ( 10, 0, 0, 1440, 'offagenda', [secr], south_pacific_1, 'Terminal Room', 'Terminal Room Open to Attendees'), - ( 10, 7, 0, 120, 'lead', [iesg,iab], south_pacific_2, 'Breakfast', 'IESG/IAB Breakfast'), + ( 10, 7, 0, 120, 'lead', [iesg], south_pacific_2, 'Breakfast', 'IESG Breakfast with the IAB'), + ( 10, 7, 0, 120, 'lead', [iab], south_pacific_2, 'Breakfast', 'IAB Breakfast with the IESG'), ( 10, 7, 0, 120, 'lead', [nomcom], iolani_67, 'Breakfast', 'Nomcom Breakfast'), ( 10, 8, 0, 600, 'offagenda', [secr], coral_lounge, 'T-shirt Distribution', 'T-shirt Distribution'), ( 10, 11, 30, 90, 'offagenda', [secr], south_pacific_2, 'Meeting', 'OPS Directorate Meeting'), @@ -103,7 +105,8 @@ def backfill_91_other_meetings(apps, schema_editor): ( 14, 0, 0, 900, 'offagenda', [secr], south_pacific_1, 'Terminal Room', 'Terminal Room Open to Attendees'), ( 14, 7, 0, 120, 'lead', [nomcom], iolani_67, 'Breakfast', 'Nomcom Breakfast'), ( 14, 11, 0, 360, 'offagenda', [isoc], south_pacific_34,'Meeeting', 'ISOC AC Meeting'), - ( 14, 13, 30, 90, 'lead', [iesg,iab], south_pacific_2, 'Lunch', 'IESG/IAB Lunch'), + ( 14, 13, 30, 90, 'lead', [iesg], south_pacific_2, 'Lunch', 'IESG Lunch with the IAB'), + ( 14, 13, 30, 90, 'lead', [iab], south_pacific_2, 'Lunch', 'IAB Lunch with the IESG'), ( 14, 18, 0, 60, 'offagenda', [isocbot], rainbow_23, 'Reception', 'ISOC Board Reception for IETF Leadership'), ( 14, 19, 0, 180, 'offagenda', [isocbot], rainbow_23, 'Dinner', 'ISOC Board Dinner for IETF Leadership'), ( 15, 8, 0, 60, 'offagenda', [isocbot], rainbow_12, 'Breakfast', 'ISOC Board of Trustees Breakfast'), diff --git a/ietf/meeting/migrations/0011_ietf92_meetings.py b/ietf/meeting/migrations/0011_ietf92_meetings.py index 7d61d205a..20b20caa6 100644 --- a/ietf/meeting/migrations/0011_ietf92_meetings.py +++ b/ietf/meeting/migrations/0011_ietf92_meetings.py @@ -103,7 +103,8 @@ def backfill_92_other_meetings(apps, schema_editor): ( 22, 19, 0, 120, 'offagenda', [iab], florentine, 'Meeting', 'IAB PrivSec program'), ( 22, 8, 30, 90, 'lead', [iesg], pavilion, 'Breakfast', None), ( 22, 9, 0, 150, 'lead', [iesg], pavilion, 'Meeting', None), - ( 22, 11, 30, 150, 'lead', [iab,iesg], pavilion, 'Lunch', 'IESG/IAB Lunch'), + ( 22, 11, 30, 150, 'lead', [iab], pavilion, 'Lunch', 'IAB Lunch with the IESG'), + ( 22, 11, 30, 150, 'lead', [iesg], pavilion, 'Lunch', 'IESG Lunch with the IAB'), ( 22, 14, 0, 180, 'lead', [iab], pavilion, 'Meeting', None), ( 22, 9, 0, 480, 'offagenda', [secr], terrace, 'Meeting', 'RootOPS'), ( 22, 16, 30, 60, 'offagenda', [secr], panorama, 'Reception', "Companion's Reception"), # Should this appear on agenda? @@ -117,7 +118,8 @@ def backfill_92_other_meetings(apps, schema_editor): ( 23, 8, 0, 600, 'offagenda', [secr], regency_foyer, 'T-Shirt Distribution', 'T-shirt Distribution'), ( 23, 0, 0, 1440, 'offagenda', [secr], regency, 'Lounge', 'Lounge'), ( 23, 11, 30, 180, 'offagenda', [secr], executive, 'Lunch', 'ICANN Lunch'), - ( 23, 7, 0, 120, 'lead', [iab,iesg], pavilion, 'Breakfast', 'IESG/IAB Breakfast'), + ( 23, 7, 0, 120, 'lead', [iesg], pavilion, 'Breakfast', 'IESG Breakfast with the IAB'), + ( 23, 7, 0, 120, 'lead', [iab], pavilion, 'Breakfast', 'IAB Breakfast with the IESG'), ( 23, 11, 30, 90, 'offagenda', [secr], pavilion, 'Meeting', 'OPS Directorate Meeting'), ( 23, 19, 0, 120, 'offagenda', [secr], pavilion, 'Meeting', 'ACE'), ( 23, 7, 30, 90, 'offagenda', [secr], terrace, 'Meeting', 'NRO ECG'), @@ -162,7 +164,9 @@ def backfill_92_other_meetings(apps, schema_editor): ( 26, 19, 30, 150, 'offagenda', [secr], royal, 'Meeting', 'Lavabit'), ( 27, 0, 0, 900, 'offagenda', [secr], brasserie, 'Terminal Room', 'Terminal Room Open to Attendees'), ( 27, 7, 30, 90, 'offagenda', [secr], executive, 'Meeting', 'Post-Con with Ray'), - ( 27, 13, 30, 90, 'lead', [iab,iesg], pavilion, 'Lunch', 'IESG/IAB Lunch'), + ( 27, 7, 30, 75, 'offagenda', [secr], state, 'Breakfast', 'Gen-art'), + ( 27, 13, 30, 90, 'lead', [iab], pavilion, 'Lunch', 'IAB Lunch with the IESG'), + ( 27, 13, 30, 90, 'lead', [iesg], pavilion, 'Lunch', 'IESG Lunch with the IAB'), ]: ts = ietf92.timeslot_set.create(type_id=type_id, name=slotname, From 0ba095e229f8667f34ab3f8188c3e2c9c1ef87e5 Mon Sep 17 00:00:00 2001 From: Robert Sparks Date: Mon, 4 May 2015 13:25:57 +0000 Subject: [PATCH 12/15] remove some dead code - Legacy-Id: 9598 --- ietf/meeting/helpers.py | 11 ----------- ietf/meeting/views.py | 2 -- 2 files changed, 13 deletions(-) diff --git a/ietf/meeting/helpers.py b/ietf/meeting/helpers.py index 24a697b17..bac9695b3 100644 --- a/ietf/meeting/helpers.py +++ b/ietf/meeting/helpers.py @@ -66,12 +66,7 @@ def build_all_agenda_slices(meeting): time_slices = [] date_slices = {} - #for ts in meeting.timeslot_set.exclude(type__in=['reg','break']).order_by('time','name'): - #for ts in meeting.timeslot_set.exclude(type__in=['reg','break','lead','offagenda','other']).order_by('time','name'): for ts in meeting.timeslot_set.filter(type__in=['session',]).order_by('time','name'): - #for ts in meeting.timeslot_set.exclude(type__in=['reg','break','other']).order_by('time','name'): - #for ts in meeting.timeslot_set.order_by('time','name'): - #for ts in meeting.timeslot_set.filter(type='offagenda').order_by('time','name'): ymd = ts.time.date() if ymd not in date_slices and ts.location != None: @@ -85,12 +80,6 @@ def build_all_agenda_slices(meeting): time_slices.sort() return time_slices,date_slices -# 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) ss = ss.filter(session__type__slug='session') diff --git a/ietf/meeting/views.py b/ietf/meeting/views.py index a5c202599..5da690c45 100644 --- a/ietf/meeting/views.py +++ b/ietf/meeting/views.py @@ -259,8 +259,6 @@ def edit_agenda(request, num=None, owner=None, name=None): meeting_base_url = request.build_absolute_uri(meeting.base_url()) site_base_url = request.build_absolute_uri('/')[:-1] # skip the trailing slash - #rooms = meeting.room_set.order_by("capacity") - #rooms = rooms.all() rooms = meeting.room_set.filter(session_types__slug='session').distinct().order_by("capacity") saveas = SaveAsForm() saveasurl=reverse(edit_agenda, From 3bf1beb0300a70b0247708a265a14520d3656600 Mon Sep 17 00:00:00 2001 From: Robert Sparks Date: Mon, 4 May 2015 15:10:18 +0000 Subject: [PATCH 13/15] fix a bug discovered with adhoc testing - Legacy-Id: 9599 --- ietf/secr/meetings/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ietf/secr/meetings/views.py b/ietf/secr/meetings/views.py index 8b0ae1c98..7a66eb622 100644 --- a/ietf/secr/meetings/views.py +++ b/ietf/secr/meetings/views.py @@ -55,7 +55,7 @@ def build_timeslots(meeting,room=None): slots = meeting.timeslot_set.filter(type='session') # Don't do anything if the room is not capable of handling sessions - if not room.session_types.filter(slug='session'): + if room and not room.session_types.filter(slug='session'): return if room: From 4e1b3b2888a8c5a723f64d323403a5095809ae47 Mon Sep 17 00:00:00 2001 From: Robert Sparks Date: Mon, 4 May 2015 15:10:34 +0000 Subject: [PATCH 14/15] let the IAB see the new pages - Legacy-Id: 9600 --- .../migrations/0005_auto_20150504_0726.py | 42 +++++++++++++++++++ ietf/ietfauth/utils.py | 1 + ietf/meeting/views.py | 7 ++-- 3 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 ietf/group/migrations/0005_auto_20150504_0726.py diff --git a/ietf/group/migrations/0005_auto_20150504_0726.py b/ietf/group/migrations/0005_auto_20150504_0726.py new file mode 100644 index 000000000..ce53f1bc0 --- /dev/null +++ b/ietf/group/migrations/0005_auto_20150504_0726.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + +def create_iab_roles(apps, schema_editor): + Role = apps.get_model('group','Role') + Group = apps.get_model('group','Group') + Person = apps.get_model('person','Person') + + iab = Group.objects.get(acronym='iab') + + iab_names = [ + 'Jari Arkko', + 'Mary Barnes', + 'Marc Blanchet', + 'Ralph Droms', + 'Ted Hardie', + 'Joe Hildebrand', + 'Russ Housley', + 'Erik Nordmark', + 'Robert Sparks', + 'Andrew Sullivan', + 'Dave Thaler', + 'Brian Trammell', + 'Suzanne Woolf', + ] + + for name in iab_names: + person = Person.objects.get(name=name) + person.role_set.add(Role(name_id='member',group=iab,person=person,email_id=person.email_set.filter(active=True).order_by('-time').first().address)) + + +class Migration(migrations.Migration): + + dependencies = [ + ('group', '0004_auto_20150430_0847'), + ] + + operations = [ + migrations.RunPython(create_iab_roles), + ] diff --git a/ietf/ietfauth/utils.py b/ietf/ietfauth/utils.py index f871bc006..fc9647093 100644 --- a/ietf/ietfauth/utils.py +++ b/ietf/ietfauth/utils.py @@ -46,6 +46,7 @@ def has_role(user, role_names, *args, **kwargs): role_qs = { "Area Director": Q(person=person, name__in=("pre-ad", "ad"), group__type="area", group__state="active"), "Secretariat": Q(person=person, name="secr", group__acronym="secretariat"), + "IAB" : Q(person=person, name="member", group__acronym="iab"), "IANA": Q(person=person, name="auth", group__acronym="iana"), "RFC Editor": Q(person=person, name="auth", group__acronym="rfceditor"), "ISE" : Q(person=person, name="chair", group__acronym="ise"), diff --git a/ietf/meeting/views.py b/ietf/meeting/views.py index 5da690c45..52c8d7562 100644 --- a/ietf/meeting/views.py +++ b/ietf/meeting/views.py @@ -384,8 +384,7 @@ def agenda(request, num=None, name=None, base=None, ext=None): filtered_assignments = schedule.assignments.exclude(timeslot__type__in=['lead','offagenda']) return render(request, "meeting/"+base+ext, {"schedule":schedule, "filtered_assignments":filtered_assignments, "updated": updated}, content_type=mimetype[ext]) -#TODO - let the IAB in -@role_required('Area Director','Secretariat') +@role_required('Area Director','Secretariat','IAB') def agenda_by_room(request,num=None): meeting = get_meeting(num) schedule = get_schedule(meeting) @@ -397,7 +396,7 @@ def agenda_by_room(request,num=None): ss_by_day[day].append(ss) return render(request,"meeting/agenda_by_room.html",{"meeting":meeting,"ss_by_day":ss_by_day}) -@role_required('Area Director','Secretariat') +@role_required('Area Director','Secretariat','IAB') def agenda_by_type(request,num=None,type=None): meeting = get_meeting(num) schedule = get_schedule(meeting) @@ -406,7 +405,7 @@ def agenda_by_type(request,num=None,type=None): scheduledsessions = scheduledsessions.filter(session__type__slug=type) return render(request,"meeting/agenda_by_type.html",{"meeting":meeting,"scheduledsessions":scheduledsessions}) -@role_required('Area Director','Secretariat') +@role_required('Area Director','Secretariat','IAB') def agenda_by_type_ics(request,num=None,type=None): meeting = get_meeting(num) schedule = get_schedule(meeting) From 547a1ae7a81fd09763c043f17844caf1ccbda149 Mon Sep 17 00:00:00 2001 From: Robert Sparks Date: Mon, 4 May 2015 15:36:00 +0000 Subject: [PATCH 15/15] deflake - Legacy-Id: 9601 --- ietf/group/migrations/0005_auto_20150504_0726.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ietf/group/migrations/0005_auto_20150504_0726.py b/ietf/group/migrations/0005_auto_20150504_0726.py index ce53f1bc0..5690ad9f4 100644 --- a/ietf/group/migrations/0005_auto_20150504_0726.py +++ b/ietf/group/migrations/0005_auto_20150504_0726.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals -from django.db import models, migrations +from django.db import migrations def create_iab_roles(apps, schema_editor): Role = apps.get_model('group','Role')