Skip to content

Commit 393ee64

Browse files
committed
Add new view for editing meeting schedules. This is a preliminary
basic version with timeslots in a fixed grid and drag and drop for assigning and unassigning. Compared to the existing JS based view, it is missing session details (attendences etc.), conflicts and other warnings, toggling of sessions in areas, area coloring, extending to next timeslot and probably more. Add new auxiliary view to copy a schedule for the new schedule editor. - Legacy-Id: 17389
1 parent de99911 commit 393ee64

8 files changed

Lines changed: 668 additions & 4 deletions

File tree

ietf/meeting/tests_views.py

Lines changed: 96 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
from ietf.meeting.helpers import send_interim_approval_request
3535
from ietf.meeting.helpers import send_interim_cancellation_notice
3636
from ietf.meeting.helpers import send_interim_minutes_reminder, populate_important_dates, update_important_dates
37-
from ietf.meeting.models import Session, TimeSlot, Meeting, SchedTimeSessAssignment, Schedule, SessionPresentation, SlideSubmission, SchedulingEvent
37+
from ietf.meeting.models import Session, TimeSlot, Meeting, SchedTimeSessAssignment, Schedule, SessionPresentation, SlideSubmission, SchedulingEvent, Room
3838
from ietf.meeting.test_data import make_meeting_test_data, make_interim_meeting
3939
from ietf.meeting.utils import finalize, condition_slide_order
4040
from ietf.meeting.utils import add_event_info_to_session_qs
@@ -911,10 +911,104 @@ def setUp(self):
911911

912912
def test_edit_schedule(self):
913913
meeting = make_meeting_test_data()
914-
914+
915915
self.client.login(username="secretary", password="secretary+password")
916916
r = self.client.get(urlreverse("ietf.meeting.views.edit_schedule", kwargs=dict(num=meeting.number)))
917917
self.assertContains(r, "load_assignments")
918+
919+
def test_edit_meeting_schedule(self):
920+
meeting = make_meeting_test_data()
921+
922+
self.client.login(username="secretary", password="secretary+password")
923+
924+
# check we have the grid and everything set up
925+
url = urlreverse("ietf.meeting.views.edit_meeting_schedule", kwargs=dict(num=meeting.number))
926+
r = self.client.get(url)
927+
q = PyQuery(r.content)
928+
929+
room = Room.objects.get(meeting=meeting, session_types='regular')
930+
self.assertTrue(q("th:contains(\"{}\")".format(room.name)))
931+
self.assertTrue(q("th:contains(\"{}\")".format(room.capacity)))
932+
933+
timeslots = TimeSlot.objects.filter(meeting=meeting, type='regular')
934+
self.assertTrue(q("td:contains(\"{}\")".format(timeslots[0].time.strftime("%H:%M"))))
935+
self.assertTrue(q("td.timeslot[data-timeslot=\"{}\"]".format(timeslots[0].pk)))
936+
937+
sessions = Session.objects.filter(meeting=meeting, type='regular')
938+
for s in sessions:
939+
self.assertIn(s.group.acronym, q("#session{}".format(s.pk)).text())
940+
941+
self.assertIn("You can't edit this schedule", r.content)
942+
943+
# can't change anything
944+
r = self.client.post(url, {
945+
'action': 'assign',
946+
'timeslot': timeslots[0].pk,
947+
'session': sessions[0].pk,
948+
})
949+
self.assertEqual(r.status_code, 403)
950+
951+
# turn us into owner
952+
meeting.schedule.owner = Person.objects.get(user__username="secretary")
953+
meeting.schedule.save()
954+
955+
url = urlreverse("ietf.meeting.views.edit_meeting_schedule", kwargs=dict(num=meeting.number, owner=meeting.schedule.owner_email(), name=meeting.schedule.name))
956+
r = self.client.get(url)
957+
self.assertNotIn("You can't edit this schedule", r.content)
958+
959+
SchedTimeSessAssignment.objects.filter(session=sessions[0]).delete()
960+
961+
# assign
962+
r = self.client.post(url, {
963+
'action': 'assign',
964+
'timeslot': timeslots[0].pk,
965+
'session': sessions[0].pk,
966+
})
967+
self.assertEqual(r.content, "OK")
968+
self.assertEqual(SchedTimeSessAssignment.objects.get(schedule=meeting.schedule, session=sessions[0]).timeslot, timeslots[0])
969+
970+
# move assignment
971+
r = self.client.post(url, {
972+
'action': 'assign',
973+
'timeslot': timeslots[1].pk,
974+
'session': sessions[0].pk,
975+
})
976+
self.assertEqual(r.content, "OK")
977+
self.assertEqual(SchedTimeSessAssignment.objects.get(schedule=meeting.schedule, session=sessions[0]).timeslot, timeslots[1])
978+
979+
# unassign
980+
r = self.client.post(url, {
981+
'action': 'unassign',
982+
'session': sessions[0].pk,
983+
})
984+
self.assertEqual(r.content, "OK")
985+
self.assertEqual(list(SchedTimeSessAssignment.objects.filter(schedule=meeting.schedule, session=sessions[0])), [])
986+
987+
988+
def test_copy_meeting_schedule(self):
989+
meeting = make_meeting_test_data()
990+
991+
self.client.login(username="secretary", password="secretary+password")
992+
993+
url = urlreverse("ietf.meeting.views.copy_meeting_schedule", kwargs=dict(num=meeting.number, owner=meeting.schedule.owner_email(), name=meeting.schedule.name))
994+
r = self.client.get(url)
995+
self.assertEqual(r.status_code, 200)
996+
997+
# copy
998+
r = self.client.post(url, {
999+
'name': "newtest",
1000+
'public': "on",
1001+
})
1002+
self.assertNoFormPostErrors(r)
1003+
1004+
new_schedule = Schedule.objects.get(meeting=meeting, owner__user__username='secretary', name='newtest')
1005+
self.assertEqual(new_schedule.public, True)
1006+
self.assertEqual(new_schedule.visible, False)
1007+
1008+
old_assignments = {(a.session_id, a.timeslot_id) for a in SchedTimeSessAssignment.objects.filter(schedule=meeting.schedule)}
1009+
for a in SchedTimeSessAssignment.objects.filter(schedule=new_schedule):
1010+
self.assertIn((a.session_id, a.timeslot_id), old_assignments)
1011+
# FIXME: test extendedfrom is copied correctly
9181012

9191013
def test_save_agenda_as_and_read_permissions(self):
9201014
meeting = make_meeting_test_data()

ietf/meeting/urls.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright The IETF Trust 2007-2019, All Rights Reserved
1+
# Copyright The IETF Trust 2007-2020, All Rights Reserved
22

33
from django.conf.urls import include
44
from django.views.generic import RedirectView
@@ -27,6 +27,7 @@
2727

2828
type_ietf_only_patterns = [
2929
url(r'^agenda/%(owner)s/%(schedule_name)s/edit$' % settings.URL_REGEXPS, views.edit_schedule),
30+
url(r'^agenda/%(owner)s/%(schedule_name)s/edit/$' % settings.URL_REGEXPS, views.edit_meeting_schedule),
3031
url(r'^agenda/%(owner)s/%(schedule_name)s/details$' % settings.URL_REGEXPS, views.edit_schedule_properties),
3132
url(r'^agenda/%(owner)s/%(schedule_name)s/delete$' % settings.URL_REGEXPS, views.delete_schedule),
3233
url(r'^agenda/%(owner)s/%(schedule_name)s/make_official$' % settings.URL_REGEXPS, views.make_schedule_official),
@@ -40,6 +41,7 @@
4041
url(r'^agenda/%(owner)s/%(schedule_name)s/session/(?P<assignment_id>\d+).json$' % settings.URL_REGEXPS, ajax.assignment_json),
4142
url(r'^agenda/%(owner)s/%(schedule_name)s/sessions.json$' % settings.URL_REGEXPS, ajax.assignments_json),
4243
url(r'^agenda/%(owner)s/%(schedule_name)s.json$' % settings.URL_REGEXPS, ajax.schedule_infourl),
44+
url(r'^agenda/%(owner)s/%(schedule_name)s/copy/$' % settings.URL_REGEXPS, views.copy_meeting_schedule),
4345
url(r'^agenda/by-room$', views.agenda_by_room),
4446
url(r'^agenda/by-type$', views.agenda_by_type),
4547
url(r'^agenda/by-type/(?P<type>[a-z]+)$', views.agenda_by_type),
@@ -76,6 +78,7 @@
7678
url(r'^agenda(?P<ext>.txt)$', views.agenda),
7779
url(r'^agenda(?P<ext>.csv)$', views.agenda),
7880
url(r'^agenda/edit$', views.edit_schedule),
81+
url(r'^agenda/edit/$', views.edit_meeting_schedule),
7982
url(r'^requests$', views.meeting_requests),
8083
url(r'^agenda/agenda\.ics$', views.ical_agenda),
8184
url(r'^agenda\.ics$', views.ical_agenda),

0 commit comments

Comments
 (0)