diff --git a/ietf/meeting/test_data.py b/ietf/meeting/test_data.py index 66960f1f0..b5ed80574 100644 --- a/ietf/meeting/test_data.py +++ b/ietf/meeting/test_data.py @@ -37,6 +37,7 @@ def make_meeting_test_data(): meeting = Meeting.objects.get(number="42", type="ietf") schedule = Schedule.objects.create(meeting=meeting, owner=plainman, name="test-agenda", visible=True, public=True) + unofficial_schedule = Schedule.objects.create(meeting=meeting, owner=plainman, name="test-unofficial-agenda", visible=True, public=True) 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) @@ -45,40 +46,48 @@ def make_meeting_test_data(): breakfast_room.session_types.add("lead") room.resources = [projector] + # slots + slot1 = TimeSlot.objects.create(meeting=meeting, type_id="session", duration=30 * 60, location=room, + time=datetime.datetime.combine(datetime.date.today(), datetime.time(9, 30))) + slot2 = TimeSlot.objects.create(meeting=meeting, type_id="session", duration=30 * 60, location=room, + time=datetime.datetime.combine(datetime.date.today(), datetime.time(10, 30))) + 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))) # mars WG mars = Group.objects.get(acronym='mars') - slot = TimeSlot.objects.create(meeting=meeting, type_id="session", duration=30 * 60, location=room, - time=datetime.datetime.combine(datetime.date.today(), datetime.time(9, 30))) 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(),type_id="session") mars_session.resources = [projector] - SchedTimeSessAssignment.objects.create(timeslot=slot, session=mars_session, schedule=schedule) + SchedTimeSessAssignment.objects.create(timeslot=slot1, session=mars_session, schedule=schedule) + SchedTimeSessAssignment.objects.create(timeslot=slot2, session=mars_session, schedule=unofficial_schedule) # ames WG - slot = TimeSlot.objects.create(meeting=meeting, type_id="session", duration=30 * 60, location=room, - time=datetime.datetime.combine(datetime.date.today(), datetime.time(10, 30))) 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(),type_id="session") - SchedTimeSessAssignment.objects.create(timeslot=slot, session=ames_session, schedule=schedule) + SchedTimeSessAssignment.objects.create(timeslot=slot2, session=ames_session, schedule=schedule) + SchedTimeSessAssignment.objects.create(timeslot=slot1, session=ames_session, schedule=unofficial_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(),type_id="lead") SchedTimeSessAssignment.objects.create(timeslot=breakfast_slot, session=iesg_session, schedule=schedule) + # No breakfast on unofficial schedule meeting.agenda = schedule meeting.save() + # Convenience for the tests + meeting.unofficial_schedule = unofficial_schedule + + 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)) diff --git a/ietf/meeting/tests_api.py b/ietf/meeting/tests_api.py index 1c2990c60..ef6cbaf47 100644 --- a/ietf/meeting/tests_api.py +++ b/ietf/meeting/tests_api.py @@ -19,10 +19,10 @@ class ApiTests(TestCase): mars_session = Session.objects.filter(meeting=meeting, group__acronym="mars").first() ames_session = Session.objects.filter(meeting=meeting, group__acronym="ames").first() - mars_scheduled = SchedTimeSessAssignment.objects.get(session=mars_session) + mars_scheduled = SchedTimeSessAssignment.objects.get(session=mars_session,schedule__name='test-agenda') mars_slot = mars_scheduled.timeslot - ames_scheduled = SchedTimeSessAssignment.objects.get(session=ames_session) + ames_scheduled = SchedTimeSessAssignment.objects.get(session=ames_session,schedule__name='test-agenda') ames_slot = ames_scheduled.timeslot def do_unschedule(assignment): @@ -88,16 +88,16 @@ class ApiTests(TestCase): r = do_extend(schedule,mars_scheduled) self.assertEqual(r.status_code, 201) self.assertTrue("error" not in json.loads(r.content)) - self.assertEqual(mars_session.timeslotassignments.count(),2) + self.assertEqual(mars_session.timeslotassignments.filter(schedule__name='test-agenda').count(),2) # Unschedule mars r = do_unschedule(mars_scheduled) self.assertEqual(r.status_code, 200) self.assertTrue("error" not in json.loads(r.content)) # Make sure it got both the original and extended session - self.assertEqual(mars_session.timeslotassignments.count(),0) + self.assertEqual(mars_session.timeslotassignments.filter(schedule__name='test-agenda').count(),0) - self.assertEqual(SchedTimeSessAssignment.objects.get(session=ames_session).timeslot, mars_slot) + self.assertEqual(SchedTimeSessAssignment.objects.get(session=ames_session,schedule__name='test-agenda').timeslot, mars_slot) def test_constraints_json(self): diff --git a/ietf/meeting/tests_js.py b/ietf/meeting/tests_js.py index c5bc88b62..0e1b7221e 100644 --- a/ietf/meeting/tests_js.py +++ b/ietf/meeting/tests_js.py @@ -69,7 +69,7 @@ class ScheduleEditTests(StaticLiveServerTestCase): def testUnschedule(self): - self.assertEqual(SchedTimeSessAssignment.objects.filter(session__meeting__number=42,session__group__acronym='mars').count(),1) + self.assertEqual(SchedTimeSessAssignment.objects.filter(session__meeting__number=42,session__group__acronym='mars',schedule__name='test-agenda').count(),1) self.login() url = self.absreverse('ietf.meeting.views.edit_agenda',kwargs=dict(num='42',name='test-agenda',owner='plain@example.com')) @@ -86,7 +86,7 @@ class ScheduleEditTests(StaticLiveServerTestCase): self.assertTrue(len(q('#sortable-list #session_1'))>0) time.sleep(0.1) # The API that modifies the database runs async - self.assertEqual(SchedTimeSessAssignment.objects.filter(session__meeting__number=42,session__group__acronym='mars').count(),0) + self.assertEqual(SchedTimeSessAssignment.objects.filter(session__meeting__number=42,session__group__acronym='mars',schedule__name='test-agenda').count(),0) # The following are useful debugging tools diff --git a/ietf/meeting/tests_views.py b/ietf/meeting/tests_views.py index 36960fe54..1fe43fecc 100644 --- a/ietf/meeting/tests_views.py +++ b/ietf/meeting/tests_views.py @@ -68,7 +68,7 @@ class MeetingTests(TestCase): def test_agenda(self): meeting = make_meeting_test_data() session = Session.objects.filter(meeting=meeting, group__acronym="mars").first() - slot = TimeSlot.objects.get(sessionassignments__session=session) + slot = TimeSlot.objects.get(sessionassignments__session=session,sessionassignments__schedule=meeting.agenda) self.write_materials_files(meeting, session) @@ -106,6 +106,10 @@ class MeetingTests(TestCase): self.assertTrue(time_interval in agenda_content) + 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()))) + self.assertEqual(r.status_code, 200) + self.assertTrue('not the official schedule' in unicontent(r)) + # CSV r = self.client.get(urlreverse("ietf.meeting.views.agenda", kwargs=dict(num=meeting.number, ext=".csv"))) self.assertEqual(r.status_code, 200) @@ -149,6 +153,11 @@ class MeetingTests(TestCase): r = self.client.get(url) self.assertTrue(all([x in unicontent(r) for x in ['mars','IESG Breakfast','Test Room','Breakfast Room']])) + url = urlreverse("ietf.meeting.views.agenda_by_room",kwargs=dict(num=meeting.number,name=meeting.unofficial_schedule.name,owner=meeting.unofficial_schedule.owner.email())) + r = self.client.get(url) + self.assertTrue(all([x in unicontent(r) for x in ['mars','Test Room',]])) + self.assertFalse('IESG Breakfast' in unicontent(r)) + def test_agenda_by_type(self): meeting = make_meeting_test_data() @@ -157,6 +166,11 @@ class MeetingTests(TestCase): r = self.client.get(url) self.assertTrue(all([x in unicontent(r) for x in ['mars','IESG Breakfast','Test Room','Breakfast Room']])) + url = urlreverse("ietf.meeting.views.agenda_by_type",kwargs=dict(num=meeting.number,name=meeting.unofficial_schedule.name,owner=meeting.unofficial_schedule.owner.email())) + r = self.client.get(url) + self.assertTrue(all([x in unicontent(r) for x in ['mars','Test Room',]])) + self.assertFalse('IESG Breakfast' in unicontent(r)) + 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 unicontent(r) for x in ['mars','Test Room']])) @@ -167,12 +181,23 @@ class MeetingTests(TestCase): self.assertFalse(any([x in unicontent(r) for x in ['mars','Test Room']])) self.assertTrue(all([x in unicontent(r) for x in ['IESG Breakfast','Breakfast Room']])) + 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())) + r = self.client.get(url) + self.assertFalse(any([x in unicontent(r) for x in ['IESG Breakfast','Breakfast Room']])) + def test_agenda_room_view(self): meeting = make_meeting_test_data() url = urlreverse("ietf.meeting.views.room_view",kwargs=dict(num=meeting.number)) login_testing_unauthorized(self,"secretary",url) r = self.client.get(url) + self.assertEqual(r.status_code,200) self.assertTrue(all([x in unicontent(r) for x in ['mars','IESG Breakfast','Test Room','Breakfast Room']])) + url = urlreverse("ietf.meeting.views.room_view",kwargs=dict(num=meeting.number,name=meeting.unofficial_schedule.name,owner=meeting.unofficial_schedule.owner.email())) + r = self.client.get(url) + self.assertEqual(r.status_code,200) + self.assertTrue(all([x in unicontent(r) for x in ['mars','Test Room','Breakfast Room']])) + self.assertFalse('IESG Breakfast' in unicontent(r)) + def test_materials(self): meeting = make_meeting_test_data() @@ -338,12 +363,12 @@ class EditTests(TestCase): def test_slot_to_the_right(self): meeting = make_meeting_test_data() session = Session.objects.filter(meeting=meeting, group__acronym="mars").first() - mars_scheduled = session.timeslotassignments.get() - mars_slot = TimeSlot.objects.get(sessionassignments__session=session) + mars_scheduled = session.timeslotassignments.get(schedule__name='test-agenda') + mars_slot = TimeSlot.objects.get(sessionassignments__session=session,sessionassignments__schedule__name='test-agenda') mars_ends = mars_slot.time + mars_slot.duration session = Session.objects.filter(meeting=meeting, group__acronym="ames").first() - ames_slot_qs = TimeSlot.objects.filter(sessionassignments__session=session) + ames_slot_qs = TimeSlot.objects.filter(sessionassignments__session=session,sessionassignments__schedule__name='test-agenda') ames_slot_qs.update(time=mars_ends + datetime.timedelta(seconds=11 * 60)) self.assertTrue(not mars_slot.slot_to_the_right) diff --git a/ietf/meeting/urls.py b/ietf/meeting/urls.py index 9f836589f..03d3cdcf7 100644 --- a/ietf/meeting/urls.py +++ b/ietf/meeting/urls.py @@ -16,8 +16,12 @@ type_ietf_only_patterns = [ url(r'^agenda/(?P[-A-Za-z0-9\'+._]+@[A-Za-z0-9-._]+)/(?P[A-Za-z0-9-:_]+)/details$', views.edit_agenda_properties), url(r'^agenda/(?P[-A-Za-z0-9\'+._]+@[A-Za-z0-9-._]+)/(?P[A-Za-z0-9-:_]+)/delete$', views.delete_schedule), url(r'^agenda/(?P[-A-Za-z0-9\'+._]+@[A-Za-z0-9-._]+)/(?P[A-Za-z0-9-:_]+)/make_official$', views.make_schedule_official), -# The following view is broken? url(r'^agenda/(?P[-A-Za-z0-9\'+._]+@[A-Za-z0-9-._]+)/(?P[A-Za-z0-9-:_]+)(\.(?P.html))?/?$', views.agenda), + url(r'^agenda/(?P[-A-Za-z0-9\'+._]+@[A-Za-z0-9-._]+)/(?P[A-Za-z0-9-:_]+)/week-view(?:.html)?/?$', views.week_view), + url(r'^agenda/(?P[-A-Za-z0-9\'+._]+@[A-Za-z0-9-._]+)/(?P[A-Za-z0-9-:_]+)/room-view(?:.html)?/?$', views.room_view), + url(r'^agenda/(?P[-A-Za-z0-9\'+._]+@[A-Za-z0-9-._]+)/(?P[A-Za-z0-9-:_]+)/by-room/?$', views.agenda_by_room), + url(r'^agenda/(?P[-A-Za-z0-9\'+._]+@[A-Za-z0-9-._]+)/(?P[A-Za-z0-9-:_]+)/by-type/?$', views.agenda_by_type), + url(r'^agenda/(?P[-A-Za-z0-9\'+._]+@[A-Za-z0-9-._]+)/(?P[A-Za-z0-9-:_]+)/by-type/(?P[a-z]+)$', views.agenda_by_type), url(r'^agenda/(?P[-A-Za-z0-9\'+._]+@[A-Za-z0-9-._]+)/(?P[A-Za-z0-9-:_]+)/permissions$', ajax.agenda_permission_api), url(r'^agenda/(?P[-A-Za-z0-9\'+._]+@[A-Za-z0-9-._]+)/(?P[A-Za-z0-9-:_]+)/session/(?P\d+).json$', ajax.assignment_json), url(r'^agenda/(?P[-A-Za-z0-9\'+._]+@[A-Za-z0-9-._]+)/(?P[A-Za-z0-9-:_]+)/sessions.json$', ajax.assignments_json), diff --git a/ietf/meeting/views.py b/ietf/meeting/views.py index cd7754e6b..4288b9a22 100644 --- a/ietf/meeting/views.py +++ b/ietf/meeting/views.py @@ -545,25 +545,33 @@ def agenda_csv(schedule, filtered_assignments): return response @role_required('Area Director','Secretariat','IAB') -def agenda_by_room(request,num=None): +def agenda_by_room(request, num=None, name=None, owner=None): meeting = get_meeting(num) - schedule = get_schedule(meeting) + if name is None: + schedule = get_schedule(meeting) + else: + person = get_person_by_email(owner) + schedule = get_schedule_by_name(meeting, person, name) ss_by_day = OrderedDict() for day in schedule.assignments.dates('timeslot__time','day'): ss_by_day[day]=[] for ss in schedule.assignments.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}) + return render(request,"meeting/agenda_by_room.html",{"meeting":meeting,"schedule":schedule,"ss_by_day":ss_by_day}) @role_required('Area Director','Secretariat','IAB') -def agenda_by_type(request,num=None,type=None): +def agenda_by_type(request, num=None, type=None, name=None, owner=None): meeting = get_meeting(num) - schedule = get_schedule(meeting) + if name is None: + schedule = get_schedule(meeting) + else: + person = get_person_by_email(owner) + schedule = get_schedule_by_name(meeting, person, name) assignments = schedule.assignments.order_by('session__type__slug','timeslot__time') if type: assignments = assignments.filter(session__type__slug=type) - return render(request,"meeting/agenda_by_type.html",{"meeting":meeting,"assignments":assignments}) + return render(request,"meeting/agenda_by_type.html",{"meeting":meeting,"schedule":schedule,"assignments":assignments}) @role_required('Area Director','Secretariat','IAB') def agenda_by_type_ics(request,num=None,type=None): @@ -712,9 +720,14 @@ def session_draft_pdf(request, num, session): os.unlink(pdfn) return HttpResponse(pdf_contents, content_type="application/pdf") -def week_view(request, num=None): +def week_view(request, num=None, name=None, owner=None): meeting = get_meeting(num) - schedule = get_schedule(meeting) + + if name is None: + schedule = get_schedule(meeting) + else: + person = get_person_by_email(owner) + schedule = get_schedule_by_name(meeting, person, name) if not schedule: raise Http404 @@ -772,14 +785,20 @@ def week_view(request, num=None): }) @role_required('Area Director','Secretariat','IAB') -def room_view(request, num=None): +def room_view(request, num=None, name=None, owner=None): meeting = get_meeting(num) rooms = meeting.room_set.order_by('functional_name','name') if rooms.count() == 0: raise Http404 - assignments = meeting.agenda.assignments.all() + if name is None: + schedule = get_schedule(meeting) + else: + person = get_person_by_email(owner) + schedule = get_schedule_by_name(meeting, person, name) + + assignments = schedule.assignments.all() unavailable = meeting.timeslot_set.filter(type__slug='unavail') if (unavailable.count() + assignments.count()) == 0 : raise Http404 @@ -822,7 +841,7 @@ def room_view(request, num=None): ss.day = (ss.timeslot.time-base_day).days template = "meeting/room-view.html" - return render(request, template,{"meeting":meeting,"unavailable":unavailable,"assignments":assignments,"rooms":rooms,"days":days}) + return render(request, template,{"meeting":meeting,"schedule":schedule,"unavailable":unavailable,"assignments":assignments,"rooms":rooms,"days":days}) def ical_agenda(request, num=None, name=None, ext=None): meeting = get_meeting(num) diff --git a/ietf/secr/meetings/tests.py b/ietf/secr/meetings/tests.py index 034557fa2..8ff64df0e 100644 --- a/ietf/secr/meetings/tests.py +++ b/ietf/secr/meetings/tests.py @@ -4,6 +4,8 @@ import shutil from pyquery import PyQuery from StringIO import StringIO +import debug # pyflakes:ignore + from django.conf import settings from django.core.urlresolvers import reverse @@ -13,7 +15,7 @@ from ietf.meeting.test_data import make_meeting_test_data from ietf.person.models import Person from ietf.secr.meetings.forms import get_times from ietf.utils.mail import outbox -from ietf.utils.test_utils import TestCase +from ietf.utils.test_utils import TestCase class SecrMeetingTestCase(TestCase): @@ -60,7 +62,7 @@ class SecrMeetingTestCase(TestCase): response = self.client.get(url) self.assertEqual(response.status_code, 200) q = PyQuery(response.content) - self.assertEqual(len(q('#id_schedule_selector option')),2) + self.assertEqual(len(q('#id_schedule_selector option')),3) def test_add_meeting(self): "Add Meeting" @@ -181,6 +183,7 @@ class SecrMeetingTestCase(TestCase): # test delete # first unschedule sessions so we can delete SchedTimeSessAssignment.objects.filter(schedule=meeting.agenda).delete() + SchedTimeSessAssignment.objects.filter(schedule=meeting.unofficial_schedule).delete() self.client.login(username="secretary", password="secretary+password") post_dict = { 'room-TOTAL_FORMS': q('input[name="room-TOTAL_FORMS"]').val(), diff --git a/ietf/templates/meeting/agenda.html b/ietf/templates/meeting/agenda.html index 5354e4ccd..ce30296e3 100644 --- a/ietf/templates/meeting/agenda.html +++ b/ietf/templates/meeting/agenda.html @@ -46,9 +46,15 @@ Tools-style agenda {% if user|has_role:"Secretariat,Area Director,IAB" %} | - List by Room | - List by Type | - Room Grid + {% if schedule != meeting.agenda %} + List by Room | + List by Type | + Room Grid + {% else %} + List by Room | + List by Type | + Room Grid + {% endif %} {% endif %}

diff --git a/ietf/templates/meeting/agenda_by_room.html b/ietf/templates/meeting/agenda_by_room.html index 7871af1ab..344c25016 100644 --- a/ietf/templates/meeting/agenda_by_room.html +++ b/ietf/templates/meeting/agenda_by_room.html @@ -17,6 +17,7 @@ li.sessionlistentry { font-size:62%; } {% block title %}Agenda for {{meeting}} by Room{% endblock %} {% block content %} +{% include "meeting/meeting_heading.html" with meeting=schedule.meeting updated=meeting.updated %}

Agenda for {{meeting}} by Room

    {% for day,sessions in ss_by_day.items %} diff --git a/ietf/templates/meeting/agenda_by_type.html b/ietf/templates/meeting/agenda_by_type.html index b1560c27b..128cf1177 100644 --- a/ietf/templates/meeting/agenda_by_type.html +++ b/ietf/templates/meeting/agenda_by_type.html @@ -25,12 +25,13 @@ li.daylistentry { margin-left:2em; font-weight: 400; } {% block title %}Agenda for {{meeting}} by Session Type{% endblock %} {% block content %} +{% include "meeting/meeting_heading.html" with meeting=schedule.meeting updated=meeting.updated %}

    Agenda for {{meeting}} by Session Type

    {% regroup assignments by session.type.slug as type_list %}
      {% for type in type_list %}
    • - {{type.grouper}} Download to Calendar + {{type.grouper}} {% if schedule == meeting.agenda %}Download to Calendar{% endif %}
        {% regroup type.list by timeslot.time|date:"l Y-M-d" as daylist %} {% for day in daylist %} diff --git a/ietf/templates/meeting/room-view.html b/ietf/templates/meeting/room-view.html index d1d4ee835..647e8833d 100644 --- a/ietf/templates/meeting/room-view.html +++ b/ietf/templates/meeting/room-view.html @@ -169,7 +169,8 @@ var timelabel_width = width * 0.020; var header_height = height * 0.05; - var header_offset = $('#daytabs').height(); + var header_offset = $('#daytabs').outerHeight(true)+$('#mtgheader').outerHeight(true); + console.log($('#mtgheader').outerHeight(true)) var num_days = {{days|length}}; var num_minutes = day_end - day_start; @@ -581,6 +582,7 @@ +
        {% include "meeting/meeting_heading.html" with meeting=schedule.meeting updated=schedule.meeting.updated %}