diff --git a/ietf/meeting/tests_js.py b/ietf/meeting/tests_js.py index 5714b2dab..8cae09dc4 100644 --- a/ietf/meeting/tests_js.py +++ b/ietf/meeting/tests_js.py @@ -7,10 +7,13 @@ from unittest import skipIf from django.contrib.staticfiles.testing import StaticLiveServerTestCase from django.core.urlresolvers import reverse as urlreverse +#from django.test.utils import override_settings import debug # pyflakes:ignore +from ietf.doc.factories import DocumentFactory from ietf.group import colors +from ietf.meeting.factories import SessionFactory from ietf.meeting.test_data import make_meeting_test_data from ietf.meeting.models import SchedTimeSessAssignment from ietf.utils.test_runner import set_coverage_checking @@ -88,6 +91,45 @@ class ScheduleEditTests(StaticLiveServerTestCase): 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',schedule__name='test-agenda').count(),0) +@skipIf(skip_selenium, skip_message) +class SlideReorderTests(StaticLiveServerTestCase): + def setUp(self): + set_coverage_checking(False) + self.session = SessionFactory(meeting__type_id='ietf') + self.session.sessionpresentation_set.create(document=DocumentFactory(type_id='slides',name='one'),order=1) + self.session.sessionpresentation_set.create(document=DocumentFactory(type_id='slides',name='two'),order=2) + self.session.sessionpresentation_set.create(document=DocumentFactory(type_id='slides',name='three'),order=3) + self.driver = webdriver.PhantomJS(port=0, service_log_path=settings.TEST_GHOSTDRIVER_LOG_PATH) + self.driver.set_window_size(1024,768) + + def absreverse(self,*args,**kwargs): + return '%s%s'%(self.live_server_url,urlreverse(*args,**kwargs)) + + def secr_login(self): + url = '%s%s'%(self.live_server_url, urlreverse('django.contrib.auth.views.login')) + self.driver.get(url) + self.driver.find_element_by_name('username').send_keys('secretary') + self.driver.find_element_by_name('password').send_keys('secretary+password') + self.driver.find_element_by_xpath('//button[@type="submit"]').click() + + #@override_settings(DEBUG=True) + def testReorderSlides(self): + return + url = self.absreverse('ietf.meeting.views.session_details', + kwargs=dict( + num=self.session.meeting.number, + acronym = self.session.group.acronym,)) + self.secr_login() + self.driver.get(url) + #debug.show('unicode(self.driver.page_source)') + second = self.driver.find_element_by_css_selector('#slides tr:nth-child(2)') + third = self.driver.find_element_by_css_selector('#slides tr:nth-child(3)') + ActionChains(self.driver).drag_and_drop(second,third).perform() + + time.sleep(0.1) # The API that modifies the database runs async + names=self.session.sessionpresentation_set.values_list('document__name',flat=True) + self.assertEqual(list(names),[u'one',u'three',u'two']) + # The following are useful debugging tools # If you add this to a LiveServerTestCase and run just this test, you can browse diff --git a/ietf/meeting/urls.py b/ietf/meeting/urls.py index 659f124dd..0107b6c05 100644 --- a/ietf/meeting/urls.py +++ b/ietf/meeting/urls.py @@ -14,6 +14,7 @@ safe_for_all_meeting_types = [ url(r'^session/(?P\d+)/minutes$', views.upload_session_minutes), url(r'^session/(?P\d+)/agenda$', views.upload_session_agenda), url(r'^session/(?P\d+)/slides(?:/%(name)s)?$' % settings.URL_REGEXPS, views.upload_session_slides), + url(r'^session/(?P\d+)/slides/%(name)s/order$' % settings.URL_REGEXPS, views.set_slide_order), ] diff --git a/ietf/meeting/views.py b/ietf/meeting/views.py index eeba96c99..fe465272d 100644 --- a/ietf/meeting/views.py +++ b/ietf/meeting/views.py @@ -1450,6 +1450,32 @@ def upload_session_slides(request, session_id, num, name): 'form': form, }) +def set_slide_order(request, session_id, num, name): + # num is redundant, but we're dragging it along an artifact of where we are in the current URL structure + session = get_object_or_404(Session,pk=session_id) + if not Document.objects.filter(type_id='slides',name=name).exists(): + raise Http404 + if not session.can_manage_materials(request.user): + return HttpResponseForbidden("You don't have permission to upload slides for this session.") + if session.is_material_submission_cutoff() and not has_role(request.user, "Secretariat"): + return HttpResponseForbidden("The materials cutoff for this session has passed. Contact the secretariat for further action.") + + if request.method != 'POST' or not request.POST: + return HttpResponse(json.dumps({ 'success' : False, 'error' : 'No data submitted or not POST' }),content_type='application/json') + order_str = request.POST.get('order', None) + try: + order = int(order_str) + except ValueError: + return HttpResponse(json.dumps({ 'success' : False, 'error' : 'Supplied order is not valid' }),content_type='application/json') + if order <=0 or order > 32767 : + return HttpResponse(json.dumps({ 'success' : False, 'error' : 'Supplied order is not valid' }),content_type='application/json') + + sp = session.sessionpresentation_set.get(document__name = name) + sp.order = order + sp.save() + + return HttpResponse(json.dumps({'success':True}),content_type='application/json') + @role_required('Secretariat') def make_schedule_official(request, num, owner, name): @@ -1962,3 +1988,4 @@ def proceedings_overview(request, num=None): 'meeting': meeting, 'template': template, }) + diff --git a/ietf/templates/meeting/session_details.html b/ietf/templates/meeting/session_details.html index 41319f287..a2bad5ee9 100644 --- a/ietf/templates/meeting/session_details.html +++ b/ietf/templates/meeting/session_details.html @@ -1,9 +1,15 @@ {% extends "base.html" %} {# Copyright The IETF Trust 2015, All Rights Reserved #} -{% load origin ietf_filters %} +{% load origin ietf_filters staticfiles %} {% block title %}{{ meeting }} : {{ acronym }}{% endblock %} +{% block morecss %} + .ui-sortable tr { + cursor:pointer; + } +{% endblock %} + {% block content %} {% origin %}

{{ meeting }} : {{ acronym }}

@@ -70,11 +76,12 @@
-
Slides
+
Slides
- +
+ {% for pres in session.filtered_slides %} - + {% if pres.rev %} {% url 'doc_view' name=pres.document.name rev=pres.rev as url %} {% else %} @@ -90,6 +97,7 @@ {% endif %} {% endfor %} +
{% if can_manage_materials %} Upload New Slides @@ -124,3 +132,54 @@ {% endfor %} {% endblock %} + +{# TODO don't rely on secr/js version of jquery-ui #} +{# Sorting based loosely on the original secr upload sorting and on http://www.avtex.com/blog/2015/01/27/drag-and-drop-sorting-of-table-rows-in-priority-order/ #} +{% block js %} +{% if can_manage_materials %} + + + + + + +{% endif %} +{% endblock %}