checkpoint: added room functional description, backfilled ietf92 meeting data, repaired session material views, added tests

- Legacy-Id: 9596
This commit is contained in:
Robert Sparks 2015-05-01 22:31:30 +00:00
parent 303e886ee5
commit 17b928b94b
11 changed files with 315 additions and 15 deletions

View file

@ -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,
),
]

View file

@ -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),
]

View file

@ -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)
]

View file

@ -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:

View file

@ -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))

View file

@ -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)

View file

@ -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()

View file

@ -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",

View file

@ -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

View file

@ -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%; }
<ul class="daylist">
{% for day,sessions in ss_by_day.items %}
<li class="daylistentry {% cycle 'even' 'odd' %}">{{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 %}
<ul class="roomlist">
{% for room in room_list %}
<li class="roomlistentry">{{room.grouper|default:"Location Unavailable"}}
<ul class="sessionlist">
{% for ss in room.list %}
<li class="sessionlistentry {{ss.timeslot.type.slug}}">{{ss.timeslot.time|date:"H:i"}}-{{ss.timeslot.end_time|date:"H:i"}} {{ss.session.short_name}}</li>
<li class="sessionlistentry type-{{ss.timeslot.type.slug}}">{{ss.timeslot.time|date:"H:i"}}-{{ss.timeslot.end_time|date:"H:i"}} {{ss.session.short_name}}</li>
{% endfor %}
</ul>
</li>

View file

@ -12,11 +12,11 @@
<h2>{{ session.name }}</h2>
{% endif %}
{% if session.sessionpresentation_set.all.count %}
{% if filtered_sessionpresentation_set %}
<p>Materials:</p>
<ul>
{% for pres in session.sessionpresentation_set.all %}
{% for pres in filtered_sessionpresentation_set %}
<li><a href="{% url 'doc_view' name=pres.document.name rev=pres.rev%}">{{ pres.document.name }}-{{ pres.rev }}</a></li>
{% endfor %}
</ul>