Skip to content

Commit b3883b6

Browse files
committed
Allow non-official schedules to be viewed in the same ways the official schedule for a meeting can be viewed. Fixes ietf-tools#1959. Commit ready for merge.
- Legacy-Id: 11500
1 parent 9318efa commit b3883b6

11 files changed

Lines changed: 109 additions & 39 deletions

File tree

ietf/meeting/test_data.py

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ def make_meeting_test_data():
3737

3838
meeting = Meeting.objects.get(number="42", type="ietf")
3939
schedule = Schedule.objects.create(meeting=meeting, owner=plainman, name="test-agenda", visible=True, public=True)
40+
unofficial_schedule = Schedule.objects.create(meeting=meeting, owner=plainman, name="test-unofficial-agenda", visible=True, public=True)
4041
pname = RoomResourceName.objects.create(name='projector',slug='proj')
4142
projector = ResourceAssociation.objects.create(name=pname,icon="notfound.png",desc="Basic projector")
4243
room = Room.objects.create(meeting=meeting, name="Test Room", capacity=123)
@@ -45,40 +46,48 @@ def make_meeting_test_data():
4546
breakfast_room.session_types.add("lead")
4647
room.resources = [projector]
4748

49+
# slots
50+
slot1 = TimeSlot.objects.create(meeting=meeting, type_id="session", duration=30 * 60, location=room,
51+
time=datetime.datetime.combine(datetime.date.today(), datetime.time(9, 30)))
52+
slot2 = TimeSlot.objects.create(meeting=meeting, type_id="session", duration=30 * 60, location=room,
53+
time=datetime.datetime.combine(datetime.date.today(), datetime.time(10, 30)))
54+
breakfast_slot = TimeSlot.objects.create(meeting=meeting, type_id="lead", duration=90 * 60,
55+
location=breakfast_room,
56+
time=datetime.datetime.combine(datetime.date.today(),datetime.time(7,0)))
4857
# mars WG
4958
mars = Group.objects.get(acronym='mars')
50-
slot = TimeSlot.objects.create(meeting=meeting, type_id="session", duration=30 * 60, location=room,
51-
time=datetime.datetime.combine(datetime.date.today(), datetime.time(9, 30)))
5259
mars_session = Session.objects.create(meeting=meeting, group=mars,
5360
attendees=10, requested_by=system_person,
5461
requested_duration=20, status_id="schedw",
5562
scheduled=datetime.datetime.now(),type_id="session")
5663
mars_session.resources = [projector]
57-
SchedTimeSessAssignment.objects.create(timeslot=slot, session=mars_session, schedule=schedule)
64+
SchedTimeSessAssignment.objects.create(timeslot=slot1, session=mars_session, schedule=schedule)
65+
SchedTimeSessAssignment.objects.create(timeslot=slot2, session=mars_session, schedule=unofficial_schedule)
5866

5967
# ames WG
60-
slot = TimeSlot.objects.create(meeting=meeting, type_id="session", duration=30 * 60, location=room,
61-
time=datetime.datetime.combine(datetime.date.today(), datetime.time(10, 30)))
6268
ames_session = Session.objects.create(meeting=meeting, group=Group.objects.get(acronym="ames"),
6369
attendees=10, requested_by=system_person,
6470
requested_duration=20, status_id="schedw",
6571
scheduled=datetime.datetime.now(),type_id="session")
66-
SchedTimeSessAssignment.objects.create(timeslot=slot, session=ames_session, schedule=schedule)
72+
SchedTimeSessAssignment.objects.create(timeslot=slot2, session=ames_session, schedule=schedule)
73+
SchedTimeSessAssignment.objects.create(timeslot=slot1, session=ames_session, schedule=unofficial_schedule)
6774

6875
# IESG breakfast
69-
breakfast_slot = TimeSlot.objects.create(meeting=meeting, type_id="lead", duration=90 * 60,
70-
location=breakfast_room,
71-
time=datetime.datetime.combine(datetime.date.today(),datetime.time(7,0)))
7276
iesg_session = Session.objects.create(meeting=meeting, group=Group.objects.get(acronym="iesg"),
7377
name="IESG Breakfast",
7478
attendees=25, requested_by=system_person,
7579
requested_duration=20, status_id="schedw",
7680
scheduled=datetime.datetime.now(),type_id="lead")
7781
SchedTimeSessAssignment.objects.create(timeslot=breakfast_slot, session=iesg_session, schedule=schedule)
82+
# No breakfast on unofficial schedule
7883

7984
meeting.agenda = schedule
8085
meeting.save()
8186

87+
# Convenience for the tests
88+
meeting.unofficial_schedule = unofficial_schedule
89+
90+
8291
doc = Document.objects.create(name='agenda-mars-ietf-42', type_id='agenda', title="Agenda", external_url="agenda-mars.txt",group=mars,rev='00')
8392
doc.set_state(State.objects.get(type=doc.type_id, slug="active"))
8493
mars_session.sessionpresentation_set.add(SessionPresentation(session=mars_session,document=doc,rev=doc.rev))

ietf/meeting/tests_api.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ def test_update_agenda(self):
1919
mars_session = Session.objects.filter(meeting=meeting, group__acronym="mars").first()
2020
ames_session = Session.objects.filter(meeting=meeting, group__acronym="ames").first()
2121

22-
mars_scheduled = SchedTimeSessAssignment.objects.get(session=mars_session)
22+
mars_scheduled = SchedTimeSessAssignment.objects.get(session=mars_session,schedule__name='test-agenda')
2323
mars_slot = mars_scheduled.timeslot
2424

25-
ames_scheduled = SchedTimeSessAssignment.objects.get(session=ames_session)
25+
ames_scheduled = SchedTimeSessAssignment.objects.get(session=ames_session,schedule__name='test-agenda')
2626
ames_slot = ames_scheduled.timeslot
2727

2828
def do_unschedule(assignment):
@@ -88,16 +88,16 @@ def do_extend(schedule, assignment):
8888
r = do_extend(schedule,mars_scheduled)
8989
self.assertEqual(r.status_code, 201)
9090
self.assertTrue("error" not in json.loads(r.content))
91-
self.assertEqual(mars_session.timeslotassignments.count(),2)
91+
self.assertEqual(mars_session.timeslotassignments.filter(schedule__name='test-agenda').count(),2)
9292

9393
# Unschedule mars
9494
r = do_unschedule(mars_scheduled)
9595
self.assertEqual(r.status_code, 200)
9696
self.assertTrue("error" not in json.loads(r.content))
9797
# Make sure it got both the original and extended session
98-
self.assertEqual(mars_session.timeslotassignments.count(),0)
98+
self.assertEqual(mars_session.timeslotassignments.filter(schedule__name='test-agenda').count(),0)
9999

100-
self.assertEqual(SchedTimeSessAssignment.objects.get(session=ames_session).timeslot, mars_slot)
100+
self.assertEqual(SchedTimeSessAssignment.objects.get(session=ames_session,schedule__name='test-agenda').timeslot, mars_slot)
101101

102102

103103
def test_constraints_json(self):

ietf/meeting/tests_js.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ def login(self):
6969

7070
def testUnschedule(self):
7171

72-
self.assertEqual(SchedTimeSessAssignment.objects.filter(session__meeting__number=42,session__group__acronym='mars').count(),1)
72+
self.assertEqual(SchedTimeSessAssignment.objects.filter(session__meeting__number=42,session__group__acronym='mars',schedule__name='test-agenda').count(),1)
7373

7474
self.login()
7575
url = self.absreverse('ietf.meeting.views.edit_agenda',kwargs=dict(num='42',name='test-agenda',owner='plain@example.com'))
@@ -86,7 +86,7 @@ def testUnschedule(self):
8686
self.assertTrue(len(q('#sortable-list #session_1'))>0)
8787

8888
time.sleep(0.1) # The API that modifies the database runs async
89-
self.assertEqual(SchedTimeSessAssignment.objects.filter(session__meeting__number=42,session__group__acronym='mars').count(),0)
89+
self.assertEqual(SchedTimeSessAssignment.objects.filter(session__meeting__number=42,session__group__acronym='mars',schedule__name='test-agenda').count(),0)
9090

9191
# The following are useful debugging tools
9292

ietf/meeting/tests_views.py

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ def write_materials_files(self, meeting, session):
6868
def test_agenda(self):
6969
meeting = make_meeting_test_data()
7070
session = Session.objects.filter(meeting=meeting, group__acronym="mars").first()
71-
slot = TimeSlot.objects.get(sessionassignments__session=session)
71+
slot = TimeSlot.objects.get(sessionassignments__session=session,sessionassignments__schedule=meeting.agenda)
7272

7373
self.write_materials_files(meeting, session)
7474

@@ -106,6 +106,10 @@ def test_agenda(self):
106106

107107
self.assertTrue(time_interval in agenda_content)
108108

109+
r = self.client.get(urlreverse("ietf.meeting.views.agenda", kwargs=dict(num=meeting.number,name=meeting.unofficial_schedule.name,owner=meeting.unofficial_schedule.owner.email())))
110+
self.assertEqual(r.status_code, 200)
111+
self.assertTrue('not the official schedule' in unicontent(r))
112+
109113
# CSV
110114
r = self.client.get(urlreverse("ietf.meeting.views.agenda", kwargs=dict(num=meeting.number, ext=".csv")))
111115
self.assertEqual(r.status_code, 200)
@@ -149,6 +153,11 @@ def test_agenda_by_room(self):
149153
r = self.client.get(url)
150154
self.assertTrue(all([x in unicontent(r) for x in ['mars','IESG Breakfast','Test Room','Breakfast Room']]))
151155

156+
url = urlreverse("ietf.meeting.views.agenda_by_room",kwargs=dict(num=meeting.number,name=meeting.unofficial_schedule.name,owner=meeting.unofficial_schedule.owner.email()))
157+
r = self.client.get(url)
158+
self.assertTrue(all([x in unicontent(r) for x in ['mars','Test Room',]]))
159+
self.assertFalse('IESG Breakfast' in unicontent(r))
160+
152161
def test_agenda_by_type(self):
153162
meeting = make_meeting_test_data()
154163

@@ -157,6 +166,11 @@ def test_agenda_by_type(self):
157166
r = self.client.get(url)
158167
self.assertTrue(all([x in unicontent(r) for x in ['mars','IESG Breakfast','Test Room','Breakfast Room']]))
159168

169+
url = urlreverse("ietf.meeting.views.agenda_by_type",kwargs=dict(num=meeting.number,name=meeting.unofficial_schedule.name,owner=meeting.unofficial_schedule.owner.email()))
170+
r = self.client.get(url)
171+
self.assertTrue(all([x in unicontent(r) for x in ['mars','Test Room',]]))
172+
self.assertFalse('IESG Breakfast' in unicontent(r))
173+
160174
url = urlreverse("ietf.meeting.views.agenda_by_type",kwargs=dict(num=meeting.number,type='session'))
161175
r = self.client.get(url)
162176
self.assertTrue(all([x in unicontent(r) for x in ['mars','Test Room']]))
@@ -167,12 +181,23 @@ def test_agenda_by_type(self):
167181
self.assertFalse(any([x in unicontent(r) for x in ['mars','Test Room']]))
168182
self.assertTrue(all([x in unicontent(r) for x in ['IESG Breakfast','Breakfast Room']]))
169183

184+
url = urlreverse("ietf.meeting.views.agenda_by_type",kwargs=dict(num=meeting.number,type='lead',name=meeting.unofficial_schedule.name,owner=meeting.unofficial_schedule.owner.email()))
185+
r = self.client.get(url)
186+
self.assertFalse(any([x in unicontent(r) for x in ['IESG Breakfast','Breakfast Room']]))
187+
170188
def test_agenda_room_view(self):
171189
meeting = make_meeting_test_data()
172190
url = urlreverse("ietf.meeting.views.room_view",kwargs=dict(num=meeting.number))
173191
login_testing_unauthorized(self,"secretary",url)
174192
r = self.client.get(url)
193+
self.assertEqual(r.status_code,200)
175194
self.assertTrue(all([x in unicontent(r) for x in ['mars','IESG Breakfast','Test Room','Breakfast Room']]))
195+
url = urlreverse("ietf.meeting.views.room_view",kwargs=dict(num=meeting.number,name=meeting.unofficial_schedule.name,owner=meeting.unofficial_schedule.owner.email()))
196+
r = self.client.get(url)
197+
self.assertEqual(r.status_code,200)
198+
self.assertTrue(all([x in unicontent(r) for x in ['mars','Test Room','Breakfast Room']]))
199+
self.assertFalse('IESG Breakfast' in unicontent(r))
200+
176201

177202
def test_materials(self):
178203
meeting = make_meeting_test_data()
@@ -338,12 +363,12 @@ def test_edit_timeslots(self):
338363
def test_slot_to_the_right(self):
339364
meeting = make_meeting_test_data()
340365
session = Session.objects.filter(meeting=meeting, group__acronym="mars").first()
341-
mars_scheduled = session.timeslotassignments.get()
342-
mars_slot = TimeSlot.objects.get(sessionassignments__session=session)
366+
mars_scheduled = session.timeslotassignments.get(schedule__name='test-agenda')
367+
mars_slot = TimeSlot.objects.get(sessionassignments__session=session,sessionassignments__schedule__name='test-agenda')
343368
mars_ends = mars_slot.time + mars_slot.duration
344369

345370
session = Session.objects.filter(meeting=meeting, group__acronym="ames").first()
346-
ames_slot_qs = TimeSlot.objects.filter(sessionassignments__session=session)
371+
ames_slot_qs = TimeSlot.objects.filter(sessionassignments__session=session,sessionassignments__schedule__name='test-agenda')
347372

348373
ames_slot_qs.update(time=mars_ends + datetime.timedelta(seconds=11 * 60))
349374
self.assertTrue(not mars_slot.slot_to_the_right)

ietf/meeting/urls.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,12 @@
1616
url(r'^agenda/(?P<owner>[-A-Za-z0-9\'+._]+@[A-Za-z0-9-._]+)/(?P<name>[A-Za-z0-9-:_]+)/details$', views.edit_agenda_properties),
1717
url(r'^agenda/(?P<owner>[-A-Za-z0-9\'+._]+@[A-Za-z0-9-._]+)/(?P<name>[A-Za-z0-9-:_]+)/delete$', views.delete_schedule),
1818
url(r'^agenda/(?P<owner>[-A-Za-z0-9\'+._]+@[A-Za-z0-9-._]+)/(?P<name>[A-Za-z0-9-:_]+)/make_official$', views.make_schedule_official),
19-
# The following view is broken?
2019
url(r'^agenda/(?P<owner>[-A-Za-z0-9\'+._]+@[A-Za-z0-9-._]+)/(?P<name>[A-Za-z0-9-:_]+)(\.(?P<ext>.html))?/?$', views.agenda),
20+
url(r'^agenda/(?P<owner>[-A-Za-z0-9\'+._]+@[A-Za-z0-9-._]+)/(?P<name>[A-Za-z0-9-:_]+)/week-view(?:.html)?/?$', views.week_view),
21+
url(r'^agenda/(?P<owner>[-A-Za-z0-9\'+._]+@[A-Za-z0-9-._]+)/(?P<name>[A-Za-z0-9-:_]+)/room-view(?:.html)?/?$', views.room_view),
22+
url(r'^agenda/(?P<owner>[-A-Za-z0-9\'+._]+@[A-Za-z0-9-._]+)/(?P<name>[A-Za-z0-9-:_]+)/by-room/?$', views.agenda_by_room),
23+
url(r'^agenda/(?P<owner>[-A-Za-z0-9\'+._]+@[A-Za-z0-9-._]+)/(?P<name>[A-Za-z0-9-:_]+)/by-type/?$', views.agenda_by_type),
24+
url(r'^agenda/(?P<owner>[-A-Za-z0-9\'+._]+@[A-Za-z0-9-._]+)/(?P<name>[A-Za-z0-9-:_]+)/by-type/(?P<type>[a-z]+)$', views.agenda_by_type),
2125
url(r'^agenda/(?P<owner>[-A-Za-z0-9\'+._]+@[A-Za-z0-9-._]+)/(?P<name>[A-Za-z0-9-:_]+)/permissions$', ajax.agenda_permission_api),
2226
url(r'^agenda/(?P<owner>[-A-Za-z0-9\'+._]+@[A-Za-z0-9-._]+)/(?P<name>[A-Za-z0-9-:_]+)/session/(?P<assignment_id>\d+).json$', ajax.assignment_json),
2327
url(r'^agenda/(?P<owner>[-A-Za-z0-9\'+._]+@[A-Za-z0-9-._]+)/(?P<name>[A-Za-z0-9-:_]+)/sessions.json$', ajax.assignments_json),

ietf/meeting/views.py

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -545,25 +545,33 @@ def slides_field(item):
545545
return response
546546

547547
@role_required('Area Director','Secretariat','IAB')
548-
def agenda_by_room(request,num=None):
548+
def agenda_by_room(request, num=None, name=None, owner=None):
549549
meeting = get_meeting(num)
550-
schedule = get_schedule(meeting)
550+
if name is None:
551+
schedule = get_schedule(meeting)
552+
else:
553+
person = get_person_by_email(owner)
554+
schedule = get_schedule_by_name(meeting, person, name)
551555
ss_by_day = OrderedDict()
552556
for day in schedule.assignments.dates('timeslot__time','day'):
553557
ss_by_day[day]=[]
554558
for ss in schedule.assignments.order_by('timeslot__location__functional_name','timeslot__location__name','timeslot__time'):
555559
day = ss.timeslot.time.date()
556560
ss_by_day[day].append(ss)
557-
return render(request,"meeting/agenda_by_room.html",{"meeting":meeting,"ss_by_day":ss_by_day})
561+
return render(request,"meeting/agenda_by_room.html",{"meeting":meeting,"schedule":schedule,"ss_by_day":ss_by_day})
558562

559563
@role_required('Area Director','Secretariat','IAB')
560-
def agenda_by_type(request,num=None,type=None):
564+
def agenda_by_type(request, num=None, type=None, name=None, owner=None):
561565
meeting = get_meeting(num)
562-
schedule = get_schedule(meeting)
566+
if name is None:
567+
schedule = get_schedule(meeting)
568+
else:
569+
person = get_person_by_email(owner)
570+
schedule = get_schedule_by_name(meeting, person, name)
563571
assignments = schedule.assignments.order_by('session__type__slug','timeslot__time')
564572
if type:
565573
assignments = assignments.filter(session__type__slug=type)
566-
return render(request,"meeting/agenda_by_type.html",{"meeting":meeting,"assignments":assignments})
574+
return render(request,"meeting/agenda_by_type.html",{"meeting":meeting,"schedule":schedule,"assignments":assignments})
567575

568576
@role_required('Area Director','Secretariat','IAB')
569577
def agenda_by_type_ics(request,num=None,type=None):
@@ -712,9 +720,14 @@ def session_draft_pdf(request, num, session):
712720
os.unlink(pdfn)
713721
return HttpResponse(pdf_contents, content_type="application/pdf")
714722

715-
def week_view(request, num=None):
723+
def week_view(request, num=None, name=None, owner=None):
716724
meeting = get_meeting(num)
717-
schedule = get_schedule(meeting)
725+
726+
if name is None:
727+
schedule = get_schedule(meeting)
728+
else:
729+
person = get_person_by_email(owner)
730+
schedule = get_schedule_by_name(meeting, person, name)
718731

719732
if not schedule:
720733
raise Http404
@@ -772,14 +785,20 @@ def week_view(request, num=None):
772785
})
773786

774787
@role_required('Area Director','Secretariat','IAB')
775-
def room_view(request, num=None):
788+
def room_view(request, num=None, name=None, owner=None):
776789
meeting = get_meeting(num)
777790

778791
rooms = meeting.room_set.order_by('functional_name','name')
779792
if rooms.count() == 0:
780793
raise Http404
781794

782-
assignments = meeting.agenda.assignments.all()
795+
if name is None:
796+
schedule = get_schedule(meeting)
797+
else:
798+
person = get_person_by_email(owner)
799+
schedule = get_schedule_by_name(meeting, person, name)
800+
801+
assignments = schedule.assignments.all()
783802
unavailable = meeting.timeslot_set.filter(type__slug='unavail')
784803
if (unavailable.count() + assignments.count()) == 0 :
785804
raise Http404
@@ -822,7 +841,7 @@ def room_view(request, num=None):
822841
ss.day = (ss.timeslot.time-base_day).days
823842

824843
template = "meeting/room-view.html"
825-
return render(request, template,{"meeting":meeting,"unavailable":unavailable,"assignments":assignments,"rooms":rooms,"days":days})
844+
return render(request, template,{"meeting":meeting,"schedule":schedule,"unavailable":unavailable,"assignments":assignments,"rooms":rooms,"days":days})
826845

827846
def ical_agenda(request, num=None, name=None, ext=None):
828847
meeting = get_meeting(num)

ietf/secr/meetings/tests.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
from pyquery import PyQuery
55
from StringIO import StringIO
66

7+
import debug # pyflakes:ignore
8+
79
from django.conf import settings
810
from django.core.urlresolvers import reverse
911

@@ -13,7 +15,7 @@
1315
from ietf.person.models import Person
1416
from ietf.secr.meetings.forms import get_times
1517
from ietf.utils.mail import outbox
16-
from ietf.utils.test_utils import TestCase
18+
from ietf.utils.test_utils import TestCase
1719

1820

1921
class SecrMeetingTestCase(TestCase):
@@ -60,7 +62,7 @@ def test_view(self):
6062
response = self.client.get(url)
6163
self.assertEqual(response.status_code, 200)
6264
q = PyQuery(response.content)
63-
self.assertEqual(len(q('#id_schedule_selector option')),2)
65+
self.assertEqual(len(q('#id_schedule_selector option')),3)
6466

6567
def test_add_meeting(self):
6668
"Add Meeting"
@@ -181,6 +183,7 @@ def test_meetings_rooms(self):
181183
# test delete
182184
# first unschedule sessions so we can delete
183185
SchedTimeSessAssignment.objects.filter(schedule=meeting.agenda).delete()
186+
SchedTimeSessAssignment.objects.filter(schedule=meeting.unofficial_schedule).delete()
184187
self.client.login(username="secretary", password="secretary+password")
185188
post_dict = {
186189
'room-TOTAL_FORMS': q('input[name="room-TOTAL_FORMS"]').val(),

0 commit comments

Comments
 (0)