From ec279682d26dcac8ac201b8621845fd2c4ea23c8 Mon Sep 17 00:00:00 2001 From: Ryan Cross <rcross@amsl.com> Date: Sat, 14 Jul 2018 16:14:35 +0000 Subject: [PATCH] Give secretariat the ability to cancel non-working group sessions. Fixes #2537. Commit ready for merge. - Legacy-Id: 15328 --- ietf/secr/meetings/tests.py | 13 ++++++++++ ietf/secr/meetings/urls.py | 1 + ietf/secr/meetings/views.py | 19 ++++++++++++++ ietf/secr/static/secr/css/custom.css | 5 ++++ ietf/secr/templates/confirm_cancel.html | 26 +++++++++++++++++++ ietf/secr/templates/meetings/non_session.html | 6 +++-- 6 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 ietf/secr/templates/confirm_cancel.html diff --git a/ietf/secr/meetings/tests.py b/ietf/secr/meetings/tests.py index 9e1a23d4f..f09aa0304 100644 --- a/ietf/secr/meetings/tests.py +++ b/ietf/secr/meetings/tests.py @@ -335,6 +335,19 @@ class SecrMeetingTestCase(TestCase): self.assertRedirects(response, target) self.assertFalse(meeting.agenda.assignments.filter(timeslot=slot)) + def test_meetings_non_session_cancel(self): + meeting = make_meeting_test_data() + slot = meeting.agenda.assignments.filter(timeslot__type='reg').first().timeslot + url = reverse('ietf.secr.meetings.views.non_session_cancel', kwargs={'meeting_id':meeting.number,'schedule_name':meeting.agenda.name,'slot_id':slot.id}) + redirect_url = reverse('ietf.secr.meetings.views.non_session', kwargs={'meeting_id':meeting.number,'schedule_name':meeting.agenda.name}) + self.client.login(username="secretary", password="secretary+password") + response = self.client.get(url) + self.assertEqual(response.status_code, 200) + response = self.client.post(url, {'post':'yes'}) + self.assertRedirects(response, redirect_url) + session = slot.sessionassignments.filter(schedule=meeting.agenda).first().session + self.assertEqual(session.status_id, 'canceled') + def test_meetings_select_group(self): make_meeting_test_data() url = reverse('ietf.secr.meetings.views.select_group',kwargs={'meeting_id':42,'schedule_name':'test-agenda'}) diff --git a/ietf/secr/meetings/urls.py b/ietf/secr/meetings/urls.py index 8bd355f10..0b5993b2d 100644 --- a/ietf/secr/meetings/urls.py +++ b/ietf/secr/meetings/urls.py @@ -14,6 +14,7 @@ urlpatterns = [ url(r'^(?P<meeting_id>\d{1,6})/notifications/$', views.notifications), url(r'^(?P<meeting_id>\d{1,6})/(?P<schedule_name>[A-Za-z0-9_\-]+)/$', views.select), url(r'^(?P<meeting_id>\d{1,6})/(?P<schedule_name>[A-Za-z0-9_\-]+)/non_session/$', views.non_session), + url(r'^(?P<meeting_id>\d{1,6})/(?P<schedule_name>[A-Za-z0-9_\-]+)/non_session/cancel/(?P<slot_id>\d{1,6})/$', views.non_session_cancel), url(r'^(?P<meeting_id>\d{1,6})/(?P<schedule_name>[A-Za-z0-9_\-]+)/non_session/edit/(?P<slot_id>\d{1,6})/$', views.non_session_edit), url(r'^(?P<meeting_id>\d{1,6})/(?P<schedule_name>[A-Za-z0-9_\-]+)/non_session/delete/(?P<slot_id>\d{1,6})/$', views.non_session_delete), url(r'^(?P<meeting_id>\d{1,6})/(?P<schedule_name>[A-Za-z0-9_\-]+)/rooms/$', views.rooms), diff --git a/ietf/secr/meetings/views.py b/ietf/secr/meetings/views.py index e5b78f0e7..f342fd097 100644 --- a/ietf/secr/meetings/views.py +++ b/ietf/secr/meetings/views.py @@ -491,6 +491,25 @@ def non_session(request, meeting_id, schedule_name): 'schedule': schedule}, ) +@role_required('Secretariat') +def non_session_cancel(request, meeting_id, schedule_name, slot_id): + ''' + This function cancels the non-session TimeSlot. Check for uploaded + material first. SchedTimeSessAssignment objects get canceled as well. + ''' + slot = get_object_or_404(TimeSlot, id=slot_id) + meeting = get_object_or_404(Meeting, number=meeting_id) + schedule = get_object_or_404(Schedule, meeting=meeting, name=schedule_name) + + if request.method == 'POST' and request.POST['post'] == 'yes': + assignments = slot.sessionassignments.filter(schedule=schedule) + Session.objects.filter(pk__in=[x.session.pk for x in assignments]).update(status_id='canceled') + + messages.success(request, 'The session was canceled successfully') + return redirect('ietf.secr.meetings.views.non_session', meeting_id=meeting_id, schedule_name=schedule_name) + + return render(request, 'confirm_cancel.html', {'object': slot}) + @role_required('Secretariat') def non_session_delete(request, meeting_id, schedule_name, slot_id): ''' diff --git a/ietf/secr/static/secr/css/custom.css b/ietf/secr/static/secr/css/custom.css index 5d609f24b..3fe48ccc5 100644 --- a/ietf/secr/static/secr/css/custom.css +++ b/ietf/secr/static/secr/css/custom.css @@ -490,6 +490,11 @@ tr.break td { border-top: 2px solid black; } +tr.canceled { + background-color: #e12817; + color: white; +} + #id_schedule_selector { display: inline; } diff --git a/ietf/secr/templates/confirm_cancel.html b/ietf/secr/templates/confirm_cancel.html new file mode 100644 index 000000000..c4452a67a --- /dev/null +++ b/ietf/secr/templates/confirm_cancel.html @@ -0,0 +1,26 @@ +{% extends "base_site.html" %} +{% load staticfiles %} + +{% block title %}Confirm Cancel{% endblock %} + + +{% block content %} + +<div class="module draft-container"> + <h2>Confirm Cancel</h2> + <h3>Are you sure?</h3> + <p>You are about to cancel: {{ object }}</p> + {% if extra %}<p>{{ extra }}</p>{% endif %} + + <form action="" method="post">{% csrf_token %} + <div> + <p> + <input type="hidden" name="post" value="yes"> + <input type="submit" value="Yes, I'm sure"> + <a href="#" onclick="history.go(-1);return false;" class="button cancel-link">Take me back</a> + </p> + </div> + </form> +</div> <!-- module --> + +{% endblock %} diff --git a/ietf/secr/templates/meetings/non_session.html b/ietf/secr/templates/meetings/non_session.html index 69b499226..5d1acebe7 100644 --- a/ietf/secr/templates/meetings/non_session.html +++ b/ietf/secr/templates/meetings/non_session.html @@ -6,7 +6,7 @@ <h2>TimeSlots</h2> {% if slots %} - <table class="full-width"> + <table id="nonsessions" class="full-width"> <thead> <tr> <th>Day</th> @@ -19,11 +19,12 @@ <th>Type</th> <th></th> <th></th> + <th></th> </tr> </thead> <tbody> {% for item in slots %} - <tr class="{% cycle row1 row2 %}{% ifchanged item.type %} break{% endifchanged %}"> + <tr class="{% cycle row1 row2 %}{% ifchanged item.type %} break{% endifchanged %}{% if item.session.status.slug == "canceled" %} canceled{% endif %}"> <td>{{ item.time|date:"D" }}</td> <td>{{ item.time|date:"H:i" }}-{{ item.end_time|date:"H:i" }}</td> <td>{{ item.name }}</td> @@ -33,6 +34,7 @@ <td>{{ item.show_location }}</td> <td>{{ item.type }}</td> <td><a href="{% url "ietf.secr.meetings.views.non_session_edit" meeting_id=meeting.number schedule_name=schedule.name slot_id=item.id %}">Edit</a></td> + <td><a href="{% url "ietf.secr.meetings.views.non_session_cancel" meeting_id=meeting.number schedule_name=schedule.name slot_id=item.id %}">Cancel</a></td> <td><a href="{% url "ietf.secr.meetings.views.non_session_delete" meeting_id=meeting.number schedule_name=schedule.name slot_id=item.id %}">Delete</a></td> </tr> {% endfor %}