Skip to content

Commit f34ae9c

Browse files
committed
Reworked the pages that manage all the possible schedules for a meeting. Removed a lot of custom javascript. Fixes ietf-tools#1921. Commit ready for merge.
- Legacy-Id: 11137
1 parent 62d3ac8 commit f34ae9c

12 files changed

Lines changed: 242 additions & 573 deletions

ietf/meeting/tests_views.py

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@
1111
from pyquery import PyQuery
1212

1313
from ietf.doc.models import Document
14-
from ietf.meeting.models import Session, TimeSlot
14+
from ietf.meeting.models import Session, TimeSlot, Meeting
1515
from ietf.meeting.test_data import make_meeting_test_data
1616
from ietf.utils.test_utils import TestCase, login_testing_unauthorized, unicontent
1717

1818
from ietf.person.factories import PersonFactory
1919
from ietf.group.factories import GroupFactory
20-
from ietf.meeting.factories import SessionFactory, SessionPresentationFactory
20+
from ietf.meeting.factories import SessionFactory, SessionPresentationFactory, ScheduleFactory, MeetingFactory
2121
from ietf.doc.factories import DocumentFactory
2222

2323
class MeetingTests(TestCase):
@@ -401,3 +401,48 @@ def test_add_session_drafts(self):
401401
q = PyQuery(r.content)
402402
self.assertEqual(1,len(q(".alert-warning:contains('may affect published proceedings')")))
403403

404+
class EditScheduleListTests(TestCase):
405+
def setUp(self):
406+
self.mtg = MeetingFactory(type_id='ietf')
407+
ScheduleFactory(meeting=self.mtg,name='Empty-Schedule')
408+
409+
def test_list_agendas(self):
410+
url = urlreverse('ietf.meeting.views.list_agendas',kwargs={'num':self.mtg.number})
411+
login_testing_unauthorized(self,"secretary",url)
412+
r = self.client.get(url)
413+
self.assertTrue(r.status_code, 200)
414+
415+
def test_delete_schedule(self):
416+
url = urlreverse('ietf.meeting.views.delete_schedule',
417+
kwargs={'num':self.mtg.number,
418+
'owner':self.mtg.agenda.owner.email_address(),
419+
'name':self.mtg.agenda.name,
420+
})
421+
login_testing_unauthorized(self,"secretary",url)
422+
r = self.client.get(url)
423+
self.assertTrue(r.status_code, 403)
424+
r = self.client.post(url,{'save':1})
425+
self.assertTrue(r.status_code, 403)
426+
self.assertEqual(self.mtg.schedule_set.count(),2)
427+
self.mtg.agenda=None
428+
self.mtg.save()
429+
r = self.client.get(url)
430+
self.assertTrue(r.status_code, 200)
431+
r = self.client.post(url,{'save':1})
432+
self.assertTrue(r.status_code, 302)
433+
self.assertEqual(self.mtg.schedule_set.count(),1)
434+
435+
def test_make_schedule_official(self):
436+
schedule = self.mtg.schedule_set.exclude(id=self.mtg.agenda.id).first()
437+
url = urlreverse('ietf.meeting.views.make_schedule_official',
438+
kwargs={'num':self.mtg.number,
439+
'owner':schedule.owner.email_address(),
440+
'name':schedule.name,
441+
})
442+
login_testing_unauthorized(self,"secretary",url)
443+
r = self.client.get(url)
444+
self.assertTrue(r.status_code, 200)
445+
r = self.client.post(url,{'save':1})
446+
self.assertTrue(r.status_code, 302)
447+
mtg = Meeting.objects.get(number=self.mtg.number)
448+
self.assertEqual(mtg.agenda,schedule)

ietf/meeting/urls.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,22 @@
1212
]
1313

1414
type_ietf_only_patterns = [
15-
url(r'^agenda/(?P<owner>[A-Za-z0-9-.+_]+@[A-Za-z0-9._]+)/(?P<name>[A-Za-z0-9-:_]+)/edit$', views.edit_agenda),
16-
url(r'^agenda/(?P<owner>[A-Za-z0-9-.+_]+@[A-Za-z0-9._]+)/(?P<name>[A-Za-z0-9-:_]+)/details$', views.edit_agenda_properties),
17-
url(r'^agenda/(?P<owner>[A-Za-z0-9-.+_]+@[A-Za-z0-9._]+)/(?P<name>[A-Za-z0-9-:_]+).(?P<ext>.html)?/?$', views.agenda),
18-
url(r'^agenda/(?P<owner>[A-Za-z0-9-.+_]+@[A-Za-z0-9._]+)/(?P<name>[A-Za-z0-9-:_]+)/permissions$', ajax.agenda_permission_api),
19-
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),
20-
url(r'^agenda/(?P<owner>[A-Za-z0-9-.+_]+@[A-Za-z0-9._]+)/(?P<name>[A-Za-z0-9-:_]+)/sessions.json$', ajax.assignments_json),
21-
url(r'^agenda/(?P<owner>[A-Za-z0-9-.+_]+@[A-Za-z0-9._]+)/(?P<name>[A-Za-z0-9-:_]+).json$', ajax.agenda_infourl),
15+
url(r'^agenda/(?P<owner>[A-Za-z0-9-.+_]+@[A-Za-z0-9-._]+)/(?P<name>[A-Za-z0-9-:_]+)/edit$', views.edit_agenda),
16+
url(r'^agenda/(?P<owner>[A-Za-z0-9-.+_]+@[A-Za-z0-9-._]+)/(?P<name>[A-Za-z0-9-:_]+)/details$', views.edit_agenda_properties),
17+
url(r'^agenda/(?P<owner>[A-Za-z0-9-.+_]+@[A-Za-z0-9-._]+)/(?P<name>[A-Za-z0-9-:_]+)/delete$', views.delete_schedule),
18+
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?
20+
url(r'^agenda/(?P<owner>[A-Za-z0-9-.+_]+@[A-Za-z0-9-._]+)/(?P<name>[A-Za-z0-9-:_]+).(?P<ext>.html)?/?$', views.agenda),
21+
url(r'^agenda/(?P<owner>[A-Za-z0-9-.+_]+@[A-Za-z0-9-._]+)/(?P<name>[A-Za-z0-9-:_]+)/permissions$', ajax.agenda_permission_api),
22+
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),
23+
url(r'^agenda/(?P<owner>[A-Za-z0-9-.+_]+@[A-Za-z0-9-._]+)/(?P<name>[A-Za-z0-9-:_]+)/sessions.json$', ajax.assignments_json),
24+
url(r'^agenda/(?P<owner>[A-Za-z0-9-.+_]+@[A-Za-z0-9-._]+)/(?P<name>[A-Za-z0-9-:_]+).json$', ajax.agenda_infourl),
2225
url(r'^agenda/by-room$', views.agenda_by_room),
2326
url(r'^agenda/by-type$', views.agenda_by_type),
2427
url(r'^agenda/by-type/(?P<type>[a-z]+)$', views.agenda_by_type),
2528
url(r'^agenda/by-type/(?P<type>[a-z]+)/ics$', views.agenda_by_type_ics),
26-
url(r'^agendas/edit$', views.edit_agendas),
29+
url(r'^agendas/list$', views.list_agendas, name='meeting_list_agendas'),
30+
url(r'^agendas/edit$', RedirectView.as_view(pattern_name='meeting_list_agendas', permanent=True)),
2731
url(r'^timeslots/edit$', views.edit_timeslots),
2832
url(r'^rooms$', ajax.timeslot_roomsurl),
2933
url(r'^room/(?P<roomid>\d+).json$', ajax.timeslot_roomurl),

ietf/meeting/views.py

Lines changed: 70 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -304,42 +304,41 @@ def edit_agenda(request, num=None, owner=None, name=None):
304304

305305
##############################################################################
306306
# show the properties associated with an agenda (visible, public)
307-
# this page uses ajax POST requests to the API
308307
#
309308
AgendaPropertiesForm = modelform_factory(Schedule, fields=('name','visible', 'public'))
310309

311310
@role_required('Area Director','Secretariat')
312-
@ensure_csrf_cookie
313311
def edit_agenda_properties(request, num=None, owner=None, name=None):
314312
meeting = get_meeting(num)
315313
person = get_person_by_email(owner)
316314
schedule = get_schedule_by_name(meeting, person, name)
317315
if schedule is None:
318316
raise Http404("No meeting information for meeting %s owner %s schedule %s available" % (num, owner, name))
319-
form = AgendaPropertiesForm(instance=schedule)
320317

321318
cansee, canedit, secretariat = agenda_permissions(meeting, schedule, request.user)
322319

323320
if not (canedit or has_role(request.user,'Secretariat')):
324321
return HttpResponseForbidden("You may not edit this agenda")
325322
else:
323+
if request.method == 'POST':
324+
form = AgendaPropertiesForm(instance=schedule,data=request.POST)
325+
if form.is_valid():
326+
form.save()
327+
return HttpResponseRedirect(reverse('ietf.meeting.views.list_agendas',kwargs={'num': num}))
328+
else:
329+
form = AgendaPropertiesForm(instance=schedule)
326330
return render(request, "meeting/properties_edit.html",
327331
{"schedule":schedule,
328332
"form":form,
329333
"meeting":meeting,
330-
"hide_menu": True,
331334
})
332335

333336
##############################################################################
334337
# show list of agendas.
335338
#
336339

337340
@role_required('Area Director','Secretariat')
338-
@ensure_csrf_cookie
339-
def edit_agendas(request, num=None, order=None):
340-
341-
#if request.method == 'POST':
342-
# return agenda_create(request, num, owner, name)
341+
def list_agendas(request, num=None ):
343342

344343
meeting = get_meeting(num)
345344
user = request.user
@@ -350,10 +349,11 @@ def edit_agendas(request, num=None, order=None):
350349

351350
schedules = schedules.order_by('owner', 'name')
352351

352+
schedules = sorted(list(schedules),key=lambda x:not x.is_official)
353+
353354
return render(request, "meeting/agenda_list.html",
354355
{"meeting": meeting,
355-
"schedules": schedules.all(),
356-
"hide_menu": True,
356+
"schedules": schedules,
357357
})
358358

359359
@ensure_csrf_cookie
@@ -927,3 +927,62 @@ def add_session_drafts(request, session_id, num):
927927
'already_linked': session.sessionpresentation_set.filter(document__type_id='draft'),
928928
'form': form,
929929
})
930+
931+
@role_required('Secretariat')
932+
def make_schedule_official(request, num, owner, name):
933+
934+
meeting = get_meeting(num)
935+
person = get_person_by_email(owner)
936+
schedule = get_schedule_by_name(meeting, person, name)
937+
938+
if schedule is None:
939+
raise Http404
940+
941+
if request.method == 'POST':
942+
if not (schedule.public and schedule.visible):
943+
schedule.public = True
944+
schedule.visible = True
945+
schedule.save()
946+
meeting.agenda = schedule
947+
meeting.save()
948+
return HttpResponseRedirect(reverse('ietf.meeting.views.list_agendas',kwargs={'num':num}))
949+
950+
if not schedule.public:
951+
messages.warning(request,"This schedule will be made public as it is made official.")
952+
953+
if not schedule.visible:
954+
messages.warning(request,"This schedule will be made visible as it is made official.")
955+
956+
return render(request, "meeting/make_schedule_official.html",
957+
{ 'schedule' : schedule,
958+
'meeting' : meeting,
959+
}
960+
)
961+
962+
963+
@role_required('Secretariat','Area Director')
964+
def delete_schedule(request, num, owner, name):
965+
966+
meeting = get_meeting(num)
967+
person = get_person_by_email(owner)
968+
schedule = get_schedule_by_name(meeting, person, name)
969+
970+
if schedule.name=='Empty-Schedule':
971+
return HttpResponseForbidden('You may not delete the default empty schedule')
972+
973+
if schedule == meeting.agenda:
974+
return HttpResponseForbidden('You may not delete the official agenda for %s'%meeting)
975+
976+
if not ( has_role(request.user, 'Secretariat') or person.user == request.user ):
977+
return HttpResponseForbidden("You may not delete other user's schedules")
978+
979+
if request.method == 'POST':
980+
schedule.delete()
981+
return HttpResponseRedirect(reverse('ietf.meeting.views.list_agendas',kwargs={'num':num}))
982+
983+
return render(request, "meeting/delete_schedule.html",
984+
{ 'schedule' : schedule,
985+
'meeting' : meeting,
986+
}
987+
)
988+

0 commit comments

Comments
 (0)