|
|
|
|
@@ -1,6 +1,8 @@
|
|
|
|
|
"""
|
|
|
|
|
Views related to the Custom Courses feature.
|
|
|
|
|
"""
|
|
|
|
|
from __future__ import absolute_import
|
|
|
|
|
|
|
|
|
|
import csv
|
|
|
|
|
import datetime
|
|
|
|
|
import functools
|
|
|
|
|
@@ -10,14 +12,15 @@ from copy import deepcopy
|
|
|
|
|
from cStringIO import StringIO
|
|
|
|
|
|
|
|
|
|
import pytz
|
|
|
|
|
import six
|
|
|
|
|
from ccx_keys.locator import CCXLocator
|
|
|
|
|
from django.conf import settings
|
|
|
|
|
from django.contrib import messages
|
|
|
|
|
from django.contrib.auth.models import User
|
|
|
|
|
from django.urls import reverse
|
|
|
|
|
from django.db import transaction
|
|
|
|
|
from django.http import Http404, HttpResponse, HttpResponseForbidden
|
|
|
|
|
from django.shortcuts import redirect
|
|
|
|
|
from django.urls import reverse
|
|
|
|
|
from django.utils.translation import ugettext as _
|
|
|
|
|
from django.views.decorators.cache import cache_control
|
|
|
|
|
from django.views.decorators.csrf import ensure_csrf_cookie
|
|
|
|
|
@@ -43,7 +46,7 @@ from lms.djangoapps.ccx.utils import (
|
|
|
|
|
get_ccx_for_coach,
|
|
|
|
|
get_date,
|
|
|
|
|
get_enrollment_action_and_identifiers,
|
|
|
|
|
parse_date,
|
|
|
|
|
parse_date
|
|
|
|
|
)
|
|
|
|
|
from lms.djangoapps.courseware.field_overrides import disable_overrides
|
|
|
|
|
from lms.djangoapps.grades.api import CourseGradeFactory
|
|
|
|
|
@@ -123,7 +126,7 @@ def dashboard(request, course, ccx=None):
|
|
|
|
|
if ccx:
|
|
|
|
|
url = reverse(
|
|
|
|
|
'ccx_coach_dashboard',
|
|
|
|
|
kwargs={'course_id': CCXLocator.from_course_locator(course.id, unicode(ccx.id))}
|
|
|
|
|
kwargs={'course_id': CCXLocator.from_course_locator(course.id, six.text_type(ccx.id))}
|
|
|
|
|
)
|
|
|
|
|
return redirect(url)
|
|
|
|
|
|
|
|
|
|
@@ -134,7 +137,7 @@ def dashboard(request, course, ccx=None):
|
|
|
|
|
context.update(get_ccx_creation_dict(course))
|
|
|
|
|
|
|
|
|
|
if ccx:
|
|
|
|
|
ccx_locator = CCXLocator.from_course_locator(course.id, unicode(ccx.id))
|
|
|
|
|
ccx_locator = CCXLocator.from_course_locator(course.id, six.text_type(ccx.id))
|
|
|
|
|
# At this point we are done with verification that current user is ccx coach.
|
|
|
|
|
assign_staff_role_to_ccx(ccx_locator, request.user, course.id)
|
|
|
|
|
schedule = get_ccx_schedule(course, ccx)
|
|
|
|
|
@@ -211,7 +214,7 @@ def create_ccx(request, course, ccx=None):
|
|
|
|
|
for vertical in sequential.get_children():
|
|
|
|
|
override_field_for_ccx(ccx, vertical, hidden, True)
|
|
|
|
|
|
|
|
|
|
ccx_id = CCXLocator.from_course_locator(course.id, unicode(ccx.id))
|
|
|
|
|
ccx_id = CCXLocator.from_course_locator(course.id, six.text_type(ccx.id))
|
|
|
|
|
|
|
|
|
|
# Create forum roles
|
|
|
|
|
seed_permissions_roles(ccx_id)
|
|
|
|
|
@@ -236,7 +239,7 @@ def create_ccx(request, course, ccx=None):
|
|
|
|
|
# using CCX object as sender here.
|
|
|
|
|
responses = SignalHandler.course_published.send(
|
|
|
|
|
sender=ccx,
|
|
|
|
|
course_key=CCXLocator.from_course_locator(course.id, unicode(ccx.id))
|
|
|
|
|
course_key=CCXLocator.from_course_locator(course.id, six.text_type(ccx.id))
|
|
|
|
|
)
|
|
|
|
|
for rec, response in responses:
|
|
|
|
|
log.info(u'Signal fired when course is published. Receiver: %s. Response: %s', rec, response)
|
|
|
|
|
@@ -335,7 +338,7 @@ def save_ccx(request, course, ccx=None):
|
|
|
|
|
# using CCX object as sender here.
|
|
|
|
|
responses = SignalHandler.course_published.send(
|
|
|
|
|
sender=ccx,
|
|
|
|
|
course_key=CCXLocator.from_course_locator(course.id, unicode(ccx.id))
|
|
|
|
|
course_key=CCXLocator.from_course_locator(course.id, six.text_type(ccx.id))
|
|
|
|
|
)
|
|
|
|
|
for rec, response in responses:
|
|
|
|
|
log.info(u'Signal fired when course is published. Receiver: %s. Response: %s', rec, response)
|
|
|
|
|
@@ -364,14 +367,14 @@ def set_grading_policy(request, course, ccx=None):
|
|
|
|
|
# using CCX object as sender here.
|
|
|
|
|
responses = SignalHandler.course_published.send(
|
|
|
|
|
sender=ccx,
|
|
|
|
|
course_key=CCXLocator.from_course_locator(course.id, unicode(ccx.id))
|
|
|
|
|
course_key=CCXLocator.from_course_locator(course.id, six.text_type(ccx.id))
|
|
|
|
|
)
|
|
|
|
|
for rec, response in responses:
|
|
|
|
|
log.info(u'Signal fired when course is published. Receiver: %s. Response: %s', rec, response)
|
|
|
|
|
|
|
|
|
|
url = reverse(
|
|
|
|
|
'ccx_coach_dashboard',
|
|
|
|
|
kwargs={'course_id': CCXLocator.from_course_locator(course.id, unicode(ccx.id))}
|
|
|
|
|
kwargs={'course_id': CCXLocator.from_course_locator(course.id, six.text_type(ccx.id))}
|
|
|
|
|
)
|
|
|
|
|
return redirect(url)
|
|
|
|
|
|
|
|
|
|
@@ -470,7 +473,7 @@ def ccx_students_management(request, course, ccx=None):
|
|
|
|
|
|
|
|
|
|
action, identifiers = get_enrollment_action_and_identifiers(request)
|
|
|
|
|
email_students = 'email-students' in request.POST
|
|
|
|
|
course_key = CCXLocator.from_course_locator(course.id, unicode(ccx.id))
|
|
|
|
|
course_key = CCXLocator.from_course_locator(course.id, six.text_type(ccx.id))
|
|
|
|
|
email_params = get_email_params(course, auto_enroll=True, course_key=course_key, display_name=ccx.display_name)
|
|
|
|
|
|
|
|
|
|
errors = ccx_students_enrolling_center(action, identifiers, email_students, course_key, email_params, ccx.coach)
|
|
|
|
|
@@ -493,7 +496,7 @@ def ccx_gradebook(request, course, ccx=None):
|
|
|
|
|
if not ccx:
|
|
|
|
|
raise Http404
|
|
|
|
|
|
|
|
|
|
ccx_key = CCXLocator.from_course_locator(course.id, unicode(ccx.id))
|
|
|
|
|
ccx_key = CCXLocator.from_course_locator(course.id, six.text_type(ccx.id))
|
|
|
|
|
with ccx_course(ccx_key) as course:
|
|
|
|
|
student_info, page = get_grade_book_page(request, course, course_key=ccx_key)
|
|
|
|
|
|
|
|
|
|
@@ -505,7 +508,7 @@ def ccx_gradebook(request, course, ccx=None):
|
|
|
|
|
'course_id': course.id,
|
|
|
|
|
'staff_access': request.user.is_staff,
|
|
|
|
|
'ordered_grades': sorted(
|
|
|
|
|
course.grade_cutoffs.items(), key=lambda i: i[1], reverse=True),
|
|
|
|
|
list(course.grade_cutoffs.items()), key=lambda i: i[1], reverse=True),
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -520,7 +523,7 @@ def ccx_grades_csv(request, course, ccx=None):
|
|
|
|
|
if not ccx:
|
|
|
|
|
raise Http404
|
|
|
|
|
|
|
|
|
|
ccx_key = CCXLocator.from_course_locator(course.id, unicode(ccx.id))
|
|
|
|
|
ccx_key = CCXLocator.from_course_locator(course.id, six.text_type(ccx.id))
|
|
|
|
|
with ccx_course(ccx_key) as course:
|
|
|
|
|
|
|
|
|
|
enrolled_students = User.objects.filter(
|
|
|
|
|
|