@@ -93,6 +93,7 @@ source, template_path = Loader(engine).load_template_source(path)
|
||||
</%doc>
|
||||
<%
|
||||
from django.template import Template, Context
|
||||
from webpack_loader.exceptions import WebpackLoaderBadStatsError
|
||||
try:
|
||||
return Template("""
|
||||
{% load render_bundle from webpack_loader %}
|
||||
@@ -105,9 +106,9 @@ source, template_path = Loader(engine).load_template_source(path)
|
||||
'entry': entry,
|
||||
'body': capture(caller.body)
|
||||
}))
|
||||
except IOError as e:
|
||||
except (IOError, WebpackLoaderBadStatsError) as e:
|
||||
# Don't break Mako template rendering if the bundle or webpack-stats can't be found, but log it
|
||||
logger.error(e)
|
||||
logger.error('[LEARNER-1938] {error}'.format(error=e))
|
||||
%>
|
||||
</%def>
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"""
|
||||
Tests for the Bulk Enrollment views.
|
||||
"""
|
||||
import ddt
|
||||
import json
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import User
|
||||
@@ -25,6 +26,7 @@ from xmodule.modulestore.tests.factories import CourseFactory
|
||||
|
||||
|
||||
@override_settings(ENABLE_BULK_ENROLLMENT_VIEW=True)
|
||||
@ddt.ddt
|
||||
class BulkEnrollmentTest(ModuleStoreTestCase, LoginEnrollmentTestCase, APITestCase):
|
||||
"""
|
||||
Test the bulk enrollment endpoint
|
||||
@@ -67,9 +69,13 @@ class BulkEnrollmentTest(ModuleStoreTestCase, LoginEnrollmentTestCase, APITestCa
|
||||
self.about_path = '/courses/{}/about'.format(self.course.id)
|
||||
self.course_path = '/courses/{}/'.format(self.course.id)
|
||||
|
||||
def request_bulk_enroll(self, data=None, **extra):
|
||||
def request_bulk_enroll(self, data=None, use_json=False, **extra):
|
||||
""" Make an authenticated request to the bulk enrollment API. """
|
||||
request = self.request_factory.post(self.url, data=data, **extra)
|
||||
content_type = None
|
||||
if use_json:
|
||||
content_type = 'application/json'
|
||||
data = json.dumps(data)
|
||||
request = self.request_factory.post(self.url, data=data, content_type=content_type, **extra)
|
||||
force_authenticate(request, user=self.staff)
|
||||
response = self.view(request)
|
||||
response.render()
|
||||
@@ -221,14 +227,15 @@ class BulkEnrollmentTest(ModuleStoreTestCase, LoginEnrollmentTestCase, APITestCa
|
||||
res_json = json.loads(response.content)
|
||||
self.assertEqual(res_json, expected)
|
||||
|
||||
def test_enroll_with_email(self):
|
||||
@ddt.data(False, True)
|
||||
def test_enroll_with_email(self, use_json):
|
||||
""" Test enrolling using a username as the identifier. """
|
||||
response = self.request_bulk_enroll({
|
||||
'identifiers': self.notenrolled_student.email,
|
||||
'action': 'enroll',
|
||||
'email_students': False,
|
||||
'courses': self.course_key,
|
||||
})
|
||||
}, use_json=use_json)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
# test that the user is now enrolled
|
||||
@@ -274,10 +281,15 @@ class BulkEnrollmentTest(ModuleStoreTestCase, LoginEnrollmentTestCase, APITestCa
|
||||
# Check the outbox
|
||||
self.assertEqual(len(mail.outbox), 0)
|
||||
|
||||
def test_unenroll(self):
|
||||
@ddt.data(False, True)
|
||||
def test_unenroll(self, use_json):
|
||||
""" Test unenrolling a user. """
|
||||
response = self.request_bulk_enroll({'identifiers': self.enrolled_student.email, 'action': 'unenroll',
|
||||
'email_students': False, 'courses': self.course_key, })
|
||||
response = self.request_bulk_enroll({
|
||||
'identifiers': self.enrolled_student.email,
|
||||
'action': 'unenroll',
|
||||
'email_students': False,
|
||||
'courses': self.course_key,
|
||||
}, use_json=use_json)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
# test that the user is now unenrolled
|
||||
|
||||
@@ -60,6 +60,12 @@ class BulkEnrollView(APIView):
|
||||
def post(self, request):
|
||||
serializer = BulkEnrollmentSerializer(data=request.data)
|
||||
if serializer.is_valid():
|
||||
# Setting the content type to be form data makes Django Rest Framework v3.6.3 treat all passed JSON data as
|
||||
# POST parameters. This is necessary because this request is forwarded on to the student_update_enrollment
|
||||
# view, which requires all of the parameters to be passed in via POST parameters.
|
||||
metadata = request._request.META # pylint: disable=protected-access
|
||||
metadata['CONTENT_TYPE'] = 'application/x-www-form-urlencoded'
|
||||
|
||||
response_dict = {
|
||||
'auto_enroll': serializer.data.get('auto_enroll'),
|
||||
'email_students': serializer.data.get('email_students'),
|
||||
|
||||
@@ -21,7 +21,7 @@ class CourseGradeBase(object):
|
||||
"""
|
||||
Base class for Course Grades.
|
||||
"""
|
||||
def __init__(self, user, course_data, percent=0, letter_grade=None, passed=False):
|
||||
def __init__(self, user, course_data, percent=0, letter_grade=None, passed=False, force_update_subsections=False):
|
||||
self.user = user
|
||||
self.course_data = course_data
|
||||
|
||||
@@ -30,6 +30,7 @@ class CourseGradeBase(object):
|
||||
|
||||
# Convert empty strings to None when reading from the table
|
||||
self.letter_grade = letter_grade or None
|
||||
self.force_update_subsections = force_update_subsections
|
||||
|
||||
def __unicode__(self):
|
||||
return u'Course Grade: percent: {}, letter_grade: {}, passed: {}'.format(
|
||||
@@ -203,7 +204,9 @@ class CourseGrade(CourseGradeBase):
|
||||
|
||||
def update(self):
|
||||
"""
|
||||
Updates the grade for the course.
|
||||
Updates the grade for the course. Also updates subsection grades
|
||||
if self.force_update_subsections is true, via the lazy call
|
||||
to self.grader_result.
|
||||
"""
|
||||
grade_cutoffs = self.course_data.course.grade_cutoffs
|
||||
self.percent = self._compute_percent(self.grader_result)
|
||||
@@ -224,7 +227,10 @@ class CourseGrade(CourseGradeBase):
|
||||
|
||||
def _get_subsection_grade(self, subsection):
|
||||
# Pass read_only here so the subsection grades can be persisted in bulk at the end.
|
||||
return self._subsection_grade_factory.create(subsection, read_only=True)
|
||||
if self.force_update_subsections:
|
||||
return self._subsection_grade_factory.update(subsection)
|
||||
else:
|
||||
return self._subsection_grade_factory.create(subsection, read_only=True)
|
||||
|
||||
@staticmethod
|
||||
def _compute_percent(grader_result):
|
||||
|
||||
@@ -66,7 +66,15 @@ class CourseGradeFactory(object):
|
||||
else:
|
||||
return None
|
||||
|
||||
def update(self, user, course=None, collected_block_structure=None, course_structure=None, course_key=None):
|
||||
def update(
|
||||
self,
|
||||
user,
|
||||
course=None,
|
||||
collected_block_structure=None,
|
||||
course_structure=None,
|
||||
course_key=None,
|
||||
force_update_subsections=False,
|
||||
):
|
||||
"""
|
||||
Computes, updates, and returns the CourseGrade for the given
|
||||
user in the course.
|
||||
@@ -75,7 +83,7 @@ class CourseGradeFactory(object):
|
||||
or course_key should be provided.
|
||||
"""
|
||||
course_data = CourseData(user, course, collected_block_structure, course_structure, course_key)
|
||||
return self._update(user, course_data, read_only=False)
|
||||
return self._update(user, course_data, read_only=False, force_update_subsections=force_update_subsections)
|
||||
|
||||
@contextmanager
|
||||
def _course_transaction(self, course_key):
|
||||
@@ -118,10 +126,17 @@ class CourseGradeFactory(object):
|
||||
|
||||
def _iter_grade_result(self, user, course_data, force_update):
|
||||
try:
|
||||
kwargs = {
|
||||
'user': user,
|
||||
'course': course_data.course,
|
||||
'collected_block_structure': course_data.collected_structure,
|
||||
'course_key': course_data.course_key
|
||||
}
|
||||
if force_update:
|
||||
kwargs['force_update_subsections'] = True
|
||||
|
||||
method = CourseGradeFactory().update if force_update else CourseGradeFactory().create
|
||||
course_grade = method(
|
||||
user, course_data.course, course_data.collected_structure, course_key=course_data.course_key,
|
||||
)
|
||||
course_grade = method(**kwargs)
|
||||
return self.GradeResult(user, course_grade, None)
|
||||
except Exception as exc: # pylint: disable=broad-except
|
||||
# Keep marching on even if this student couldn't be graded for
|
||||
@@ -165,14 +180,14 @@ class CourseGradeFactory(object):
|
||||
return course_grade, persistent_grade.grading_policy_hash
|
||||
|
||||
@staticmethod
|
||||
def _update(user, course_data, read_only):
|
||||
def _update(user, course_data, read_only, force_update_subsections=False):
|
||||
"""
|
||||
Computes, saves, and returns a CourseGrade object for the
|
||||
given user and course.
|
||||
Sends a COURSE_GRADE_CHANGED signal to listeners and a
|
||||
COURSE_GRADE_NOW_PASSED if learner has passed course.
|
||||
"""
|
||||
course_grade = CourseGrade(user, course_data)
|
||||
course_grade = CourseGrade(user, course_data, force_update_subsections=force_update_subsections)
|
||||
course_grade.update()
|
||||
|
||||
should_persist = (
|
||||
|
||||
@@ -106,7 +106,7 @@ def compute_grades_for_course_v2(self, **kwargs):
|
||||
@task(base=_BaseTask)
|
||||
def compute_grades_for_course(course_key, offset, batch_size, **kwargs): # pylint: disable=unused-argument
|
||||
"""
|
||||
Compute grades for a set of students in the specified course.
|
||||
Compute and save grades for a set of students in the specified course.
|
||||
|
||||
The set of students will be determined by the order of enrollment date, and
|
||||
limited to at most <batch_size> students, starting from the specified
|
||||
|
||||
@@ -246,6 +246,20 @@ class TestCourseGradeFactory(GradeTestBase):
|
||||
else:
|
||||
self.assertIsNone(course_grade)
|
||||
|
||||
@ddt.data(True, False)
|
||||
def test_iter_force_update(self, force_update):
|
||||
base_string = 'lms.djangoapps.grades.new.subsection_grade_factory.SubsectionGradeFactory.{}'
|
||||
desired_method_name = base_string.format('update' if force_update else 'create')
|
||||
undesired_method_name = base_string.format('create' if force_update else 'update')
|
||||
with patch(desired_method_name) as desired_call:
|
||||
with patch(undesired_method_name) as undesired_call:
|
||||
set(CourseGradeFactory().iter(
|
||||
users=[self.request.user], course=self.course, force_update=force_update
|
||||
))
|
||||
|
||||
self.assertTrue(desired_call.called)
|
||||
self.assertFalse(undesired_call.called)
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class TestSubsectionGradeFactory(ProblemSubmissionTestMixin, GradeTestBase):
|
||||
|
||||
@@ -4,22 +4,26 @@
|
||||
// Please list the ticket number of the experiment
|
||||
|
||||
// --------------------
|
||||
// LEARNER-1312 Track Selection V2
|
||||
/* This css was added as part of the LEARNER-1312 experiment */
|
||||
// LEARNER-1726 Track Selection V3
|
||||
/* This css was added as part of the LEARNER-1726 experiment */
|
||||
.v2.register-choice {
|
||||
margin: 0 2% 20px 0 !important
|
||||
}
|
||||
|
||||
.v2.register-choice-certificate .list-actions {
|
||||
text-align: left !important;
|
||||
}
|
||||
|
||||
.v2.register-choice-donate .list-actions {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.v2.register-choice-donate .action-select {
|
||||
display: inline-block !important;
|
||||
list-style-type: none !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.v2.register-choice-donate .donation-link {
|
||||
display: inline-block !important;
|
||||
padding: 10px 15px !important;
|
||||
@@ -30,219 +34,361 @@
|
||||
text-align: center !important;
|
||||
color: #D7548E !important;
|
||||
float: left !important;
|
||||
font-size: 15px;
|
||||
font-weight: 500 !important;
|
||||
}
|
||||
|
||||
@media (min-width: 375px) {
|
||||
.donation-link {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.v2.register-choice-v2-audit {
|
||||
height: 250px !important;
|
||||
height: 300px;
|
||||
background: none !important;
|
||||
border-top-color: grey !important;
|
||||
border-top-width: 1px !important;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 375px) {
|
||||
.v2.register-choice-v2-audit {
|
||||
height: 250px;
|
||||
}
|
||||
}
|
||||
|
||||
.v2.register-choice-v2-audit .list-actions {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.v2.register-choice-v2-audit .list-actions input {
|
||||
background: transparent !important;
|
||||
color: #0075b4 !important;
|
||||
box-shadow: none !important;
|
||||
text-decoration: underline !important;
|
||||
border: none !important;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.v2.register-choice-v2-audit .wrapper-copy-inline {
|
||||
height: 70px !important;
|
||||
width: 100% !important;
|
||||
display: flex !important;
|
||||
}
|
||||
|
||||
.v2.register-choice-v2-audit .wrapper-copy {
|
||||
width: 70% !important;
|
||||
height: auto !important;
|
||||
}
|
||||
|
||||
.v2.page-header {
|
||||
padding-bottom: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.v2 img {
|
||||
margin-top: 20px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.v2 .donation-link {
|
||||
font-weight: bold !important;
|
||||
}
|
||||
@media (min-width: 320px) {
|
||||
.v2.register-choice-certificate,
|
||||
.v2.register-choice-donate,
|
||||
.v2.register-choice-view {
|
||||
width: 100%;
|
||||
}
|
||||
.v2 .wrapper-copy-inline {
|
||||
max-height: 115px;
|
||||
}
|
||||
.v2.register-choice-v2-audit .wrapper-copy-inline {
|
||||
display: block !important;
|
||||
}
|
||||
.v2.register-choice-v2-audit .copy-inline {
|
||||
width: 100% !important;
|
||||
}
|
||||
.v2.register-choice-v2-audit .list-actions {
|
||||
width: 100% !important;
|
||||
margin-top: 20px !important;
|
||||
text-align: center !important;
|
||||
}
|
||||
.v2 .wrapper-copy-inline .wrapper-copy {
|
||||
width: 100% !important;
|
||||
}
|
||||
.v2 .donation-link, .v2 input {
|
||||
width: 100% !important;
|
||||
font-size: 15px !important;
|
||||
}
|
||||
.v2 img {
|
||||
display: none;
|
||||
|
||||
.v2.register-choice-certificate,
|
||||
.v2.register-choice-donate,
|
||||
.v2.register-choice-view {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.v2.register-choice-donate {
|
||||
border-color: #D7548E !important;
|
||||
}
|
||||
|
||||
.v2 .wrapper-copy-inline {
|
||||
max-height: 115px;
|
||||
}
|
||||
|
||||
.v2.register-choice-v2-audit .wrapper-copy-inline {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.v2.register-choice-v2-audit .copy-inline {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.v2.register-choice-v2-audit .list-actions {
|
||||
width: 100% !important;
|
||||
margin-top: 20px !important;
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
.v2 .wrapper-copy-inline .wrapper-copy {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.v2 input{
|
||||
font-size: 15px !important;
|
||||
}
|
||||
|
||||
.v2 button {
|
||||
background-color: rgb(0, 103, 0);
|
||||
border-color: rgb(0, 103, 0);
|
||||
border-radius: 2px;
|
||||
box-shadow: rgb(0, 77, 0) 0px 2px 1px 0px;
|
||||
cursor: pointer;
|
||||
font-family: "Open Sans";
|
||||
height: auto;
|
||||
margin-right: 4px;
|
||||
margin-top: 0px;
|
||||
padding: 10px 15px;
|
||||
width: initial;
|
||||
background-image: none !important;
|
||||
font-size: 14px !important;
|
||||
font-weight: 500 !important;
|
||||
|
||||
&:hover, &:focus {
|
||||
background-color: #009b00 !important;
|
||||
border-color: #009b00;
|
||||
box-shadow: #004d00 0px 2px 1px 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.savings-message {
|
||||
margin-top: 10px;
|
||||
font-size: 11px;
|
||||
}
|
||||
@media screen and (min-width: 375px) {
|
||||
.savings-message {
|
||||
font-size: 13px;
|
||||
margin-left: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.v2 .donation-link, .v2 input, .v2 button {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.v2 img {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.v2 .deco-divider {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.v2 .visual-reference {
|
||||
width: 38%;
|
||||
}
|
||||
|
||||
@media (min-width: 420px) {
|
||||
.v2 button {
|
||||
height: 45px;
|
||||
font-size: 16px !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.v2.register-choice-certificate,
|
||||
.v2.register-choice-donate {
|
||||
width: 48% !important;
|
||||
width: 46.5% !important;
|
||||
display: inline-block;
|
||||
min-height: 250px;
|
||||
min-height: 270px;
|
||||
}
|
||||
|
||||
.v2.register-choice-v2-audit .wrapper-copy-inline {
|
||||
display: flex !important;
|
||||
}
|
||||
|
||||
.v2.register-choice-v2-audit .copy-inline {
|
||||
width: 40% !important;
|
||||
}
|
||||
|
||||
.v2.register-choice-v2-audit .list-actions {
|
||||
margin-top: 0 !important;
|
||||
text-align: right !important;
|
||||
}
|
||||
|
||||
.v2 .wrapper-copy-inline .wrapper-copy {
|
||||
width: 58% !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
.v2 .donation-link, .v2 input {
|
||||
|
||||
.v2 input {
|
||||
font-size: 15px !important;
|
||||
width: 55% !important;
|
||||
}
|
||||
|
||||
.v2 .donation-link, .v2.register-choice-certificate button {
|
||||
margin-top: 20px;
|
||||
width: initial;
|
||||
}
|
||||
|
||||
.v2.register-choice-v2-audit input {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.v2.register-choice-view {
|
||||
height: 250px;
|
||||
}
|
||||
|
||||
.v2 img {
|
||||
display: initial;
|
||||
}
|
||||
|
||||
.v2.register-choice {
|
||||
margin: 0 2% 20px 0;
|
||||
}
|
||||
|
||||
.v2.register-choice-donate .wrapper-copy-inline .wrapper-copy, .v2.register-choice-certificate .wrapper-copy-inline .wrapper-copy {
|
||||
width: 60%;
|
||||
}
|
||||
|
||||
.v2.register-choice-view .wrapper-copy-inline .wrapper-copy {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.v2.register-choice {
|
||||
padding: 15px !important;
|
||||
}
|
||||
|
||||
.v2.register-choice-donate .wrapper-copy-inline .wrapper-copy, .v2.register-choice-certificate .wrapper-copy-inline .wrapper-copy {
|
||||
width: 60%;
|
||||
}
|
||||
|
||||
.v2.register-choice {
|
||||
padding: 20px !important;
|
||||
}
|
||||
|
||||
.v2.register-choice.register-choice-view {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.v2.register-choice .list-actions:last-child {
|
||||
float: left;
|
||||
width: 100%;
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
.v2.register-choice .action-select {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.v2 .donation-link:hover,
|
||||
.v2 .donation-link:focus {
|
||||
background-color: #D7548E !important;
|
||||
color: white !important;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.v2 .donation-link:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.v2 .copy li {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.v2.register-choice .copy-inline {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.v2 .register-choice-view {
|
||||
border-color: #2991c3 !important;
|
||||
}
|
||||
|
||||
.v2 .visual-reference {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.v2 .wrapper-copy-inline .wrapper-copy ul {
|
||||
margin-top: 0px;
|
||||
padding-left: 30px;
|
||||
}
|
||||
|
||||
.v2 .img-certificate {
|
||||
border: 2px solid #009b00 !important;
|
||||
float: right;
|
||||
height: 120px;
|
||||
width: auto;
|
||||
margin-top: 0 !important;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.v2 .img-donate {
|
||||
margin-top: 0;
|
||||
float: right;
|
||||
border: 2px solid #D7548E !important;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.v2 .img-view {
|
||||
border: 2px solid #2991c3 !important;
|
||||
}
|
||||
|
||||
.v2.register-choice .title {
|
||||
width: 100%;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.v2.register-choice.register-choice-view .action-select {
|
||||
border: 1px solid transparent !important;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.v2.register-choice.register-choice-view .action-select button {
|
||||
border: 1px solid transparent !important;
|
||||
}
|
||||
|
||||
.v2.register-choice.register-choice-view .action-select:hover {
|
||||
border: 1px solid #0075b4 !important;
|
||||
}
|
||||
|
||||
.v2.deco-divider {
|
||||
width: 3% !important;
|
||||
box-sizing: border-box;
|
||||
float: left;
|
||||
display: inline-block;
|
||||
height: 400px;
|
||||
height: 250px;
|
||||
margin: 0px 0 40px 0 !important;
|
||||
border-left: 4px solid #f5f5f5 !important;
|
||||
border-top: none !important;
|
||||
border-left: 4px solid #f5f5f5 !important; border-top:none !important;
|
||||
|
||||
.copy {
|
||||
position: absolute;
|
||||
top: 110px !important;
|
||||
left: calc(50% - 40px) !important;
|
||||
margin-left: 20px;
|
||||
background: white;
|
||||
text-align: center;
|
||||
color: #474747;
|
||||
width: 10px;
|
||||
padding: 0 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 320px) {
|
||||
.v2 .visual-reference {
|
||||
width: 38%;
|
||||
}
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
|
||||
@media (min-width: 320px) {
|
||||
.v2.register-choice-donate .wrapper-copy-inline .wrapper-copy, .v2.register-choice-certificate .wrapper-copy-inline .wrapper-copy {
|
||||
width: 60%;
|
||||
}
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.v2.register-choice-donate .wrapper-copy-inline .wrapper-copy, .v2.register-choice-certificate .wrapper-copy-inline .wrapper-copy {
|
||||
width: 60%;
|
||||
}
|
||||
}
|
||||
@media (min-width: 320px) {
|
||||
.v2.register-choice-view .wrapper-copy-inline .wrapper-copy {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
@media (min-width: 320px) {
|
||||
.v2.register-choice {
|
||||
padding: 15px !important;
|
||||
}
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.v2.register-choice {
|
||||
padding: 20px !important;
|
||||
}
|
||||
.v2.register-choice.register-choice-view {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
@media screen and (min-width: 769px) {
|
||||
.v2.register-choice .list-actions:last-child {
|
||||
float: left;
|
||||
width: 100%;
|
||||
margin-top: 0px;
|
||||
}
|
||||
}
|
||||
@media screen and (min-width: 769px) {
|
||||
.v2.register-choice .action-select {
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
.v2 .donation-link:hover,
|
||||
.v2 .donation-link:focus {
|
||||
background-color: #D7548E !important;
|
||||
color: white !important;
|
||||
text-decoration: none;
|
||||
}
|
||||
.v2 .donation-link:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
.v2 .copy li {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.v2.register-choice .copy-inline {
|
||||
width: 100%;
|
||||
}
|
||||
@media (min-width: 835px) {
|
||||
.v2.register-choice-certificate,
|
||||
.v2.register-choice-donate {
|
||||
border-color: #D7548E !important;
|
||||
}
|
||||
.v2 .register-choice-view {
|
||||
border-color: #2991c3 !important;
|
||||
}
|
||||
.v2 .visual-reference {
|
||||
vertical-align: top;
|
||||
}
|
||||
.v2 .wrapper-copy-inline .wrapper-copy ul {
|
||||
margin-top: 0px;
|
||||
padding-left: 30px;
|
||||
}
|
||||
.v2 .img-certificate {
|
||||
border: 2px solid #009b00 !important;
|
||||
}
|
||||
.v2 .img-donate {
|
||||
border: 2px solid #D7548E !important;
|
||||
}
|
||||
.v2 .img-view {
|
||||
border: 2px solid #2991c3 !important;
|
||||
}
|
||||
.v2.register-choice .title {
|
||||
width: 100%;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.v2.register-choice.register-choice-view .action-select {
|
||||
border: 1px solid transparent !important;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.v2.register-choice.register-choice-view .action-select input {
|
||||
border: 1px solid transparent !important;
|
||||
}
|
||||
.v2.register-choice.register-choice-view .action-select:hover {
|
||||
border: 1px solid #0075b4 !important;
|
||||
}
|
||||
.v2.deco-divider {
|
||||
display: none !important;
|
||||
min-height: 250px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.v2 .donation-link {
|
||||
width: 55%;
|
||||
}
|
||||
.v2.deco-divider .copy {
|
||||
margin-left: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1064px) {
|
||||
.v2.register-choice-certificate,
|
||||
.v2.register-choice-donate {
|
||||
min-height: 260px;
|
||||
}
|
||||
.v2 .img-certificate, .v2 .img-donate {
|
||||
display: initial;
|
||||
}
|
||||
.v2 .donation-link, .v2.register-choice-certificate button {
|
||||
margin-top: -22px !important;
|
||||
}
|
||||
}
|
||||
@@ -50,6 +50,7 @@ class Command(BaseCommand):
|
||||
site_config = getattr(site, 'configuration', None)
|
||||
if site_config is None or not site_config.get_value('COURSE_CATALOG_API_URL'):
|
||||
logger.info('Skipping site {domain}. No configuration.'.format(domain=site.domain))
|
||||
cache.set(SITE_PROGRAM_UUIDS_CACHE_KEY_TPL.format(domain=site.domain), [], None)
|
||||
continue
|
||||
|
||||
client = create_catalog_api_client(user, site=site)
|
||||
|
||||
@@ -30,7 +30,7 @@ git+https://github.com/open-craft/problem-builder.git@v2.6.5#egg=xblock-problem-
|
||||
-e git+https://github.com/edx/AnimationXBlock.git@d2b551bb8f49a138088e10298576102164145b87#egg=animation-xblock
|
||||
|
||||
# Peer instruction XBlock
|
||||
ubcpi-xblock==0.6.2
|
||||
ubcpi-xblock==0.6.3
|
||||
|
||||
# Vector Drawing and ActiveTable XBlocks (Davidson)
|
||||
-e git+https://github.com/open-craft/xblock-vectordraw.git@v0.2.1#egg=xblock-vectordraw==0.2.1
|
||||
|
||||
@@ -75,7 +75,7 @@ from openedx.core.djangolib.markup import HTML, Text
|
||||
<h3 class="title v1">
|
||||
${title_content}
|
||||
</h3>
|
||||
<!-- This div was added as part of the LEARNER-1312 experiment. The v2 class should be removed if the experiment is implemented-->
|
||||
<!-- This div was added as part of the LEARNER-1726 experiment. The v2 class should be removed if the experiment is implemented-->
|
||||
<h3 class="title v2 hidden">
|
||||
Next, Select Your Learning Path
|
||||
</h3>
|
||||
@@ -86,7 +86,7 @@ from openedx.core.djangolib.markup import HTML, Text
|
||||
b_tag_kwargs = {'b_start': HTML('<b>'), 'b_end': HTML('</b>')}
|
||||
%>
|
||||
% if "verified" in modes:
|
||||
<!-- This div was added as part of the LEARNER-1312 experiment. The v2 class should be removed if the experiment is implemented-->
|
||||
<!-- This div was added as part of the LEARNER-1726 experiment. The v2 class should be removed if the experiment is implemented-->
|
||||
<div class="register-choice register-choice-certificate v2 hidden">
|
||||
<h4 class="title">Pursue a Verified Certificate</h4>
|
||||
<div class="wrapper-copy-inline">
|
||||
@@ -102,7 +102,14 @@ from openedx.core.djangolib.markup import HTML, Text
|
||||
<li class="action action-select">
|
||||
<input type="hidden" name="contribution" value="${min_price}" />
|
||||
<!-- The class verified_mode should be added to this selector if the experiment is implemented-->
|
||||
<input type="submit" name="verified_mode" value="Upgrade to a Certificate ($${min_price} USD)" />
|
||||
<div class="upgradev1">
|
||||
<input type="submit" name="verified_mode" value="Upgrade to a Certificate ($${min_price} USD)" />
|
||||
</div>
|
||||
<div class="upgradev2 hidden">
|
||||
<button type="submit" name="verified_mode">Upgrade to a Certificate (<del>$${min_price} USD</del>)</button>
|
||||
<br>
|
||||
<div class="savings-message">Save 5% if you upgrade now! ($${int(min_price * .95)} USD)</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -192,41 +199,41 @@ from openedx.core.djangolib.markup import HTML, Text
|
||||
<span class="deco-divider v1">
|
||||
<span class="copy">${_("or")}</span>
|
||||
</span>
|
||||
<!-- This div was added as part of the LEARNER-1312 experiment. The v2 class should be removed if the experiment is implemented-->
|
||||
<!-- This div was added as part of the LEARNER-1726 experiment. The v2 class should be removed if the experiment is implemented-->
|
||||
<span class="deco-divider v2 hidden">
|
||||
<span class="copy">${_("or")}</span>
|
||||
</span>
|
||||
|
||||
<!-- This div was added as part of the LEARNER-1312 experiment. The v2 class should be removed if the experiment is implemented-->
|
||||
<!-- This div was added as part of the LEARNER-1726 experiment. The v2 class should be removed if the experiment is implemented-->
|
||||
<div class="register-choice register-choice-donate v2 hidden">
|
||||
<h4 class="title">
|
||||
Donate to Support our Non-Profit Mission
|
||||
I Don't Want to Upgrade or Donate Today
|
||||
</h4>
|
||||
<div class="wrapper-copy-inline">
|
||||
<div class="wrapper-copy">
|
||||
Any amount will support our mission to make the world's best education more accessible.
|
||||
If you do not want to add a certificate or donate to edX's mission today, you can skip this step for now and continue to the course.
|
||||
</div>
|
||||
<img src="/static/images/edx-home-graphic.png" class="visual-reference img-donate" alt="Visual of two hands forming a heart shape" >
|
||||
</div>
|
||||
<div class="copy-inline">
|
||||
<ul class="list-actions">
|
||||
<li class="action action-select">
|
||||
<a class="donation-link" href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=MJUBGL54QTCTA">Donate and Continue to Course</a>
|
||||
<a class="donation-link" href="/dashboard">Continue to Course</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- This div was added as part of the LEARNER-1312 experiment. The v2 class should be removed if the experiment is implemented-->
|
||||
<!-- This div was added as part of the LEARNER-1726 experiment. The v2 class should be removed if the experiment is implemented-->
|
||||
<div class="register-choice register-choice-v2-audit register-choice-view v2 hidden">
|
||||
<h4 class="title">I Don't Want to Upgrade or Donate Today</h4>
|
||||
<h4 class="title">Donate to Support our Non-Profit Mission</h4>
|
||||
<div class="wrapper-copy-inline">
|
||||
<div class="wrapper-copy">
|
||||
If you do not want to buy a certificate or donate to edX's mission today, you can skip this step for now and continue to the course.
|
||||
Even if you are not interested in pursuing a Verified Certificate, a donation helps edX continue to work towards its non-profit mission of making the world's best education more accessible to learners everywhere.
|
||||
</div>
|
||||
<div class="copy-inline">
|
||||
<ul class="list-actions">
|
||||
<input type="submit" name="audit_mode" value="Continue to Course">
|
||||
<input type="submit" name="audit_mode" action="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=AG9VK2LC29L5Y" value="Donate and Continue to Course">
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user