diff --git a/lms/djangoapps/pocs/tests/test_views.py b/lms/djangoapps/pocs/tests/test_views.py index be5c830eb3..50045e7967 100644 --- a/lms/djangoapps/pocs/tests/test_views.py +++ b/lms/djangoapps/pocs/tests/test_views.py @@ -185,6 +185,8 @@ class TestCoachDashboard(ModuleStoreTestCase, LoginEnrollmentTestCase): self.assertEqual(str(course_start)[:-9], u'2014-11-20 00:00') def test_enroll_member_student(self): + """enroll a list of students who are members of the class + """ self.make_coach() poc = self.make_poc() enrollment = CourseEnrollmentFactory(course_id=self.course.id) @@ -213,6 +215,8 @@ class TestCoachDashboard(ModuleStoreTestCase, LoginEnrollmentTestCase): ) def test_unenroll_member_student(self): + """unenroll a list of students who are members of the class + """ self.make_coach() poc = self.make_poc() enrollment = CourseEnrollmentFactory(course_id=self.course.id) @@ -243,6 +247,8 @@ class TestCoachDashboard(ModuleStoreTestCase, LoginEnrollmentTestCase): ) def test_enroll_non_user_student(self): + """enroll a list of students who are not users yet + """ test_email = "nobody@nowhere.com" self.make_coach() poc = self.make_poc() @@ -271,6 +277,8 @@ class TestCoachDashboard(ModuleStoreTestCase, LoginEnrollmentTestCase): ) def test_unenroll_non_user_student(self): + """unenroll a list of students who are not users yet + """ test_email = "nobody@nowhere.com" self.make_coach() poc = self.make_poc() @@ -299,8 +307,71 @@ class TestCoachDashboard(ModuleStoreTestCase, LoginEnrollmentTestCase): ).exists() ) + def test_manage_add_single_student(self): + """enroll a single student who is a member of the class already + """ + self.make_coach() + poc = self.make_poc() + enrollment = CourseEnrollmentFactory(course_id=self.course.id) + student = enrollment.user + # no emails have been sent so far + outbox = self.get_outbox() + self.assertEqual(len(outbox), 0) + + url = reverse( + 'poc_manage_student', + kwargs={'course_id': self.course.id.to_deprecated_string()} + ) + data = { + 'student-action': 'add', + 'student-id': u','.join([student.email, ]), + } + response = self.client.post(url, data=data, follow=True) + self.assertEqual(response.status_code, 200) + # we were redirected to our current location + self.assertEqual(len(response.redirect_chain), 1) + self.assertTrue(302 in response.redirect_chain[0]) + self.assertEqual(len(outbox), 0) + # a PocMembership exists for this student + self.assertTrue( + PocMembership.objects.filter(poc=poc, student=student).exists() + ) + + def test_manage_remove_single_student(self): + """unenroll a single student who is a member of the class already + """ + self.make_coach() + poc = self.make_poc() + enrollment = CourseEnrollmentFactory(course_id=self.course.id) + student = enrollment.user + PocMembershipFactory(poc=poc, student=student) + # no emails have been sent so far + outbox = self.get_outbox() + self.assertEqual(len(outbox), 0) + + url = reverse( + 'poc_manage_student', + kwargs={'course_id': self.course.id.to_deprecated_string()} + ) + data = { + 'student-action': 'revoke', + 'student-id': u','.join([student.email, ]), + } + response = self.client.post(url, data=data, follow=True) + self.assertEqual(response.status_code, 200) + # we were redirected to our current location + self.assertEqual(len(response.redirect_chain), 1) + self.assertTrue(302 in response.redirect_chain[0]) + self.assertEqual(len(outbox), 0) + # a PocMembership exists for this student + self.assertFalse( + PocMembership.objects.filter(poc=poc, student=student).exists() + ) + + USER_COUNT = 2 + class TestPocGrades(ModuleStoreTestCase, LoginEnrollmentTestCase): """ Tests for Personal Online Courses views. diff --git a/lms/djangoapps/pocs/views.py b/lms/djangoapps/pocs/views.py index 30eba263a9..43127b7b87 100644 --- a/lms/djangoapps/pocs/views.py +++ b/lms/djangoapps/pocs/views.py @@ -253,6 +253,37 @@ def poc_invite(request, course): return redirect(url) +@ensure_csrf_cookie +@cache_control(no_cache=True, no_store=True, must_revalidate=True) +@coach_dashboard +def poc_student_management(request, course): + """Manage the enrollment of individual students in a POC + """ + poc = get_poc_for_coach(course, request.user) + action = request.POST.get('student-action', None) + student_id = request.POST.get('student-id', '') + user = email = None + try: + user = get_student_from_identifier(student_id) + except User.DoesNotExist: + email = student_id + else: + email = user.email + + try: + validate_email(email) + if action == 'add': + # by decree, no emails sent to students added this way + enroll_email(poc, email, email_students=False) + elif action == 'revoke': + unenroll_email(poc, email, email_students=False) + except ValidationError: + pass # XXX: log, report? + + url = reverse('poc_coach_dashboard', kwargs={'course_id': course.id}) + return redirect(url) + + @cache_control(no_cache=True, no_store=True, must_revalidate=True) @coach_dashboard def poc_gradebook(request, course): @@ -324,4 +355,3 @@ def poc_grades_csv(request, course): writer.writerow(row) return HttpResponse(buffer.getvalue(), content_type='text/csv') - diff --git a/lms/templates/pocs/coach_dashboard.html b/lms/templates/pocs/coach_dashboard.html index 547fb20280..ee8e13ddf4 100644 --- a/lms/templates/pocs/coach_dashboard.html +++ b/lms/templates/pocs/coach_dashboard.html @@ -81,7 +81,56 @@ } } + function setup_management_form() { + + $(".member-lists-management form").on("submit", function (event) { + var target, action; + target = $(event.target); + if (target.serialize().indexOf('student-action') < 0) { + action = $('', { + type: 'hidden', + name: 'student-action', + value: 'add' + }); + target.append(action); + } + }); + + $(".member-lists-management form .add, .member-lists-management form .revoke").on("click", function(event) { + var target, form, action, studentId, selectedStudent; + event.preventDefault(); + target = $(event.target); + form = target.parents('form').first(); + if (target.hasClass('add')) { + // adding a new student, add the student-action input and submit + action = $('', { + type: 'hidden', + name: 'student-action', + // this is untenable, tied to a translated value. Fix it. + value: 'add' + }); + form.append(action).submit(); + } else if (target.hasClass('revoke')) { + // revoking access for a student, get set form values and submit + // get the email address of the student, since they might not be 'enrolled' yet. + selectedStudent = target.parent('td').siblings().last().text(); + action = $('', { + type: 'hidden', + name: 'student-action', + value: 'revoke' + }); + studentId = $('', { + type: 'hidden', + name: 'student-id', + value: selectedStudent + }); + form.append(action, studentId).submit(); + } + }); + } + $(setup_tabs); + $(setup_management_form) diff --git a/lms/templates/pocs/enrollment.html b/lms/templates/pocs/enrollment.html index 01071f7116..15d8942a6a 100644 --- a/lms/templates/pocs/enrollment.html +++ b/lms/templates/pocs/enrollment.html @@ -46,6 +46,8 @@