Merge pull request #12367 from edx/rc/2016-05-05
Patch Release 2016-05-05
This commit is contained in:
@@ -839,7 +839,7 @@ def _calculate_score_for_modules(user_id, course, modules):
|
||||
|
||||
# Iterate over all of the exam modules to get score percentage of user for each of them
|
||||
module_percentages = []
|
||||
ignore_categories = ['course', 'chapter', 'sequential', 'vertical', 'randomize']
|
||||
ignore_categories = ['course', 'chapter', 'sequential', 'vertical', 'randomize', 'library_content']
|
||||
for index, module in enumerate(modules):
|
||||
if module.category not in ignore_categories and (module.graded or module.has_score):
|
||||
module_score = scores_client.get(locations[index])
|
||||
|
||||
@@ -366,13 +366,19 @@ class TestGetModuleScore(LoginEnrollmentTestCase, SharedModuleStoreTestCase):
|
||||
cls.seq1 = ItemFactory.create(
|
||||
parent=cls.chapter,
|
||||
category='sequential',
|
||||
display_name="Test Sequential",
|
||||
display_name="Test Sequential 1",
|
||||
graded=True
|
||||
)
|
||||
cls.seq2 = ItemFactory.create(
|
||||
parent=cls.chapter,
|
||||
category='sequential',
|
||||
display_name="Test Sequential",
|
||||
display_name="Test Sequential 2",
|
||||
graded=True
|
||||
)
|
||||
cls.seq3 = ItemFactory.create(
|
||||
parent=cls.chapter,
|
||||
category='sequential',
|
||||
display_name="Test Sequential 3",
|
||||
graded=True
|
||||
)
|
||||
cls.vert1 = ItemFactory.create(
|
||||
@@ -385,11 +391,21 @@ class TestGetModuleScore(LoginEnrollmentTestCase, SharedModuleStoreTestCase):
|
||||
category='vertical',
|
||||
display_name='Test Vertical 2'
|
||||
)
|
||||
cls.vert3 = ItemFactory.create(
|
||||
parent=cls.seq3,
|
||||
category='vertical',
|
||||
display_name='Test Vertical 3'
|
||||
)
|
||||
cls.randomize = ItemFactory.create(
|
||||
parent=cls.vert2,
|
||||
category='randomize',
|
||||
display_name='Test Randomize'
|
||||
)
|
||||
cls.library_content = ItemFactory.create(
|
||||
parent=cls.vert3,
|
||||
category='library_content',
|
||||
display_name='Test Library Content'
|
||||
)
|
||||
problem_xml = MultipleChoiceResponseXMLFactory().build_xml(
|
||||
question_text='The correct answer is Choice 3',
|
||||
choices=[False, False, True, False],
|
||||
@@ -420,6 +436,19 @@ class TestGetModuleScore(LoginEnrollmentTestCase, SharedModuleStoreTestCase):
|
||||
data=problem_xml
|
||||
)
|
||||
|
||||
cls.problem5 = ItemFactory.create(
|
||||
parent=cls.library_content,
|
||||
category="problem",
|
||||
display_name="Test Problem 5",
|
||||
data=problem_xml
|
||||
)
|
||||
cls.problem6 = ItemFactory.create(
|
||||
parent=cls.library_content,
|
||||
category="problem",
|
||||
display_name="Test Problem 6",
|
||||
data=problem_xml
|
||||
)
|
||||
|
||||
def setUp(self):
|
||||
"""
|
||||
Set up test course
|
||||
@@ -485,6 +514,16 @@ class TestGetModuleScore(LoginEnrollmentTestCase, SharedModuleStoreTestCase):
|
||||
score = get_module_score(self.request.user, self.course, self.seq2)
|
||||
self.assertEqual(score, 1.0)
|
||||
|
||||
def test_get_module_score_with_library_content(self):
|
||||
"""
|
||||
Test test_get_module_score_with_library_content
|
||||
"""
|
||||
answer_problem(self.course, self.request, self.problem5)
|
||||
answer_problem(self.course, self.request, self.problem6)
|
||||
|
||||
score = get_module_score(self.request.user, self.course, self.seq3)
|
||||
self.assertEqual(score, 1.0)
|
||||
|
||||
|
||||
def answer_problem(course, request, problem, score=1):
|
||||
"""
|
||||
|
||||
@@ -38,6 +38,7 @@ import shoppingcart
|
||||
import survey.utils
|
||||
import survey.views
|
||||
from certificates import api as certs_api
|
||||
from openedx.core.djangoapps.models.course_details import CourseDetails
|
||||
from openedx.core.lib.gating import api as gating_api
|
||||
from commerce.utils import EcommerceService
|
||||
from course_modes.models import CourseMode
|
||||
@@ -883,6 +884,7 @@ def course_about(request, course_id):
|
||||
with modulestore().bulk_operations(course_key):
|
||||
permission = get_permission_for_course_about()
|
||||
course = get_course_with_access(request.user, permission, course_key)
|
||||
course_details = CourseDetails.populate(course)
|
||||
modes = CourseMode.modes_for_course_dict(course_key)
|
||||
|
||||
if theming_helpers.get_value('ENABLE_MKTG_SITE', settings.FEATURES.get('ENABLE_MKTG_SITE', False)):
|
||||
@@ -962,6 +964,7 @@ def course_about(request, course_id):
|
||||
|
||||
context = {
|
||||
'course': course,
|
||||
'course_details': course_details,
|
||||
'staff_access': staff_access,
|
||||
'studio_url': studio_url,
|
||||
'registered': registered,
|
||||
|
||||
@@ -20,7 +20,6 @@ from django.views.decorators.http import require_http_methods
|
||||
|
||||
from lang_pref.api import released_languages, all_languages
|
||||
from edxmako.shortcuts import render_to_response
|
||||
from microsite_configuration import microsite
|
||||
|
||||
from external_auth.login_and_register import (
|
||||
login as external_auth_login,
|
||||
@@ -37,6 +36,7 @@ from third_party_auth import pipeline
|
||||
from third_party_auth.decorators import xframe_allow_whitelisted
|
||||
from util.bad_request_rate_limiter import BadRequestRateLimiter
|
||||
|
||||
from openedx.core.djangoapps.theming.helpers import is_request_in_themed_site, get_value as get_themed_value
|
||||
from openedx.core.djangoapps.user_api.accounts.api import request_password_change
|
||||
from openedx.core.djangoapps.user_api.errors import UserNotFound
|
||||
|
||||
@@ -67,11 +67,12 @@ def login_and_registration_form(request, initial_mode="login"):
|
||||
# Retrieve the form descriptions from the user API
|
||||
form_descriptions = _get_form_descriptions(request)
|
||||
|
||||
# If this is a microsite, revert to the old login/registration pages.
|
||||
# If this is a themed site, revert to the old login/registration pages.
|
||||
# We need to do this for now to support existing themes.
|
||||
# Microsites can use the new logistration page by setting
|
||||
# 'ENABLE_COMBINED_LOGIN_REGISTRATION' in their microsites configuration file.
|
||||
if microsite.is_request_in_microsite() and not microsite.get_value('ENABLE_COMBINED_LOGIN_REGISTRATION', False):
|
||||
# Themed sites can use the new logistration page by setting
|
||||
# 'ENABLE_COMBINED_LOGIN_REGISTRATION' in their theme/microsite
|
||||
# configuration settings.
|
||||
if is_request_in_themed_site() and not get_themed_value('ENABLE_COMBINED_LOGIN_REGISTRATION', False):
|
||||
if initial_mode == "login":
|
||||
return old_login_view(request)
|
||||
elif initial_mode == "register":
|
||||
@@ -102,7 +103,7 @@ def login_and_registration_form(request, initial_mode="login"):
|
||||
'initial_mode': initial_mode,
|
||||
'third_party_auth': _third_party_auth_context(request, redirect_to),
|
||||
'third_party_auth_hint': third_party_auth_hint or '',
|
||||
'platform_name': settings.PLATFORM_NAME,
|
||||
'platform_name': get_themed_value('PLATFORM_NAME', settings.PLATFORM_NAME),
|
||||
|
||||
# Include form descriptions retrieved from the user API.
|
||||
# We could have the JS client make these requests directly,
|
||||
@@ -389,7 +390,7 @@ def account_settings_context(request):
|
||||
'options': all_languages(),
|
||||
}
|
||||
},
|
||||
'platform_name': settings.PLATFORM_NAME,
|
||||
'platform_name': get_themed_value('PLATFORM_NAME', settings.PLATFORM_NAME),
|
||||
'user_accounts_api_url': reverse("accounts_api", kwargs={'username': user.username}),
|
||||
'user_preferences_api_url': reverse('preferences_api', kwargs={'username': user.username}),
|
||||
'disable_courseware_js': True,
|
||||
|
||||
@@ -94,27 +94,33 @@ class CourseDetails(object):
|
||||
Fetch the course details for the given course from persistence
|
||||
and return a CourseDetails model.
|
||||
"""
|
||||
descriptor = modulestore().get_course(course_key)
|
||||
course_details = cls(course_key.org, course_key.course, course_key.run)
|
||||
return cls.populate(modulestore().get_course(course_key))
|
||||
|
||||
course_details.start_date = descriptor.start
|
||||
course_details.end_date = descriptor.end
|
||||
course_details.enrollment_start = descriptor.enrollment_start
|
||||
course_details.enrollment_end = descriptor.enrollment_end
|
||||
course_details.pre_requisite_courses = descriptor.pre_requisite_courses
|
||||
course_details.course_image_name = descriptor.course_image
|
||||
course_details.course_image_asset_path = course_image_url(descriptor, 'course_image')
|
||||
course_details.banner_image_name = descriptor.banner_image
|
||||
course_details.banner_image_asset_path = course_image_url(descriptor, 'banner_image')
|
||||
course_details.video_thumbnail_image_name = descriptor.video_thumbnail_image
|
||||
course_details.video_thumbnail_image_asset_path = course_image_url(descriptor, 'video_thumbnail_image')
|
||||
course_details.language = descriptor.language
|
||||
course_details.self_paced = descriptor.self_paced
|
||||
course_details.learning_info = descriptor.learning_info
|
||||
course_details.instructor_info = descriptor.instructor_info
|
||||
@classmethod
|
||||
def populate(cls, course_descriptor):
|
||||
"""
|
||||
Returns a fully populated CourseDetails model given the course descriptor
|
||||
"""
|
||||
course_key = course_descriptor.id
|
||||
course_details = cls(course_key.org, course_key.course, course_key.run)
|
||||
course_details.start_date = course_descriptor.start
|
||||
course_details.end_date = course_descriptor.end
|
||||
course_details.enrollment_start = course_descriptor.enrollment_start
|
||||
course_details.enrollment_end = course_descriptor.enrollment_end
|
||||
course_details.pre_requisite_courses = course_descriptor.pre_requisite_courses
|
||||
course_details.course_image_name = course_descriptor.course_image
|
||||
course_details.course_image_asset_path = course_image_url(course_descriptor, 'course_image')
|
||||
course_details.banner_image_name = course_descriptor.banner_image
|
||||
course_details.banner_image_asset_path = course_image_url(course_descriptor, 'banner_image')
|
||||
course_details.video_thumbnail_image_name = course_descriptor.video_thumbnail_image
|
||||
course_details.video_thumbnail_image_asset_path = course_image_url(course_descriptor, 'video_thumbnail_image')
|
||||
course_details.language = course_descriptor.language
|
||||
course_details.self_paced = course_descriptor.self_paced
|
||||
course_details.learning_info = course_descriptor.learning_info
|
||||
course_details.instructor_info = course_descriptor.instructor_info
|
||||
|
||||
# Default course license is "All Rights Reserved"
|
||||
course_details.license = getattr(descriptor, "license", "all-rights-reserved")
|
||||
course_details.license = getattr(course_descriptor, "license", "all-rights-reserved")
|
||||
|
||||
course_details.intro_video = cls.fetch_youtube_video_id(course_key)
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@ from rest_framework.views import APIView
|
||||
from rest_framework.exceptions import ParseError
|
||||
from django_countries import countries
|
||||
from opaque_keys.edx.locations import SlashSeparatedCourseKey
|
||||
from microsite_configuration import microsite
|
||||
|
||||
from openedx.core.lib.api.permissions import ApiKeyHeaderPermission
|
||||
import third_party_auth
|
||||
@@ -29,6 +28,7 @@ from edxmako.shortcuts import marketing_link
|
||||
from student.forms import get_registration_extension_form
|
||||
from student.views import create_account_with_params
|
||||
from student.cookies import set_logged_in_cookies
|
||||
from openedx.core.djangoapps.theming.helpers import get_value as get_themed_value
|
||||
from openedx.core.lib.api.authentication import SessionAuthenticationAllowInactiveUser
|
||||
from util.json_request import JsonResponse
|
||||
from .preferences.api import update_email_opt_in
|
||||
@@ -189,7 +189,7 @@ class RegistrationView(APIView):
|
||||
|
||||
# Backwards compatibility: Honor code is required by default, unless
|
||||
# explicitly set to "optional" in Django settings.
|
||||
self._extra_fields_setting = copy.deepcopy(microsite.get_value('REGISTRATION_EXTRA_FIELDS'))
|
||||
self._extra_fields_setting = copy.deepcopy(get_themed_value('REGISTRATION_EXTRA_FIELDS'))
|
||||
if not self._extra_fields_setting:
|
||||
self._extra_fields_setting = copy.deepcopy(settings.REGISTRATION_EXTRA_FIELDS)
|
||||
self._extra_fields_setting["honor_code"] = self._extra_fields_setting.get("honor_code", "required")
|
||||
@@ -687,14 +687,14 @@ class RegistrationView(APIView):
|
||||
# Translators: "Terms of Service" is a legal document users must agree to
|
||||
# in order to register a new account.
|
||||
label = _(u"I agree to the {platform_name} {terms_of_service}.").format(
|
||||
platform_name=settings.PLATFORM_NAME,
|
||||
platform_name=get_themed_value("PLATFORM_NAME", settings.PLATFORM_NAME),
|
||||
terms_of_service=terms_link
|
||||
)
|
||||
|
||||
# Translators: "Terms of Service" is a legal document users must agree to
|
||||
# in order to register a new account.
|
||||
error_msg = _(u"You must agree to the {platform_name} {terms_of_service}.").format(
|
||||
platform_name=settings.PLATFORM_NAME,
|
||||
platform_name=get_themed_value("PLATFORM_NAME", settings.PLATFORM_NAME),
|
||||
terms_of_service=terms_link
|
||||
)
|
||||
|
||||
@@ -730,14 +730,14 @@ class RegistrationView(APIView):
|
||||
# Translators: "Terms of service" is a legal document users must agree to
|
||||
# in order to register a new account.
|
||||
label = _(u"I agree to the {platform_name} {terms_of_service}.").format(
|
||||
platform_name=settings.PLATFORM_NAME,
|
||||
platform_name=get_themed_value("PLATFORM_NAME", settings.PLATFORM_NAME),
|
||||
terms_of_service=terms_link
|
||||
)
|
||||
|
||||
# Translators: "Terms of service" is a legal document users must agree to
|
||||
# in order to register a new account.
|
||||
error_msg = _(u"You must agree to the {platform_name} {terms_of_service}.").format(
|
||||
platform_name=settings.PLATFORM_NAME,
|
||||
platform_name=get_themed_value("PLATFORM_NAME", settings.PLATFORM_NAME),
|
||||
terms_of_service=terms_link
|
||||
)
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ git+https://github.com/edx/xblock-utils.git@v1.0.2#egg=xblock-utils==1.0.2
|
||||
-e git+https://github.com/edx/edx-reverification-block.git@0.0.5#egg=edx-reverification-block==0.0.5
|
||||
git+https://github.com/edx/edx-user-state-client.git@1.0.1#egg=edx-user-state-client==1.0.1
|
||||
git+https://github.com/edx/xblock-lti-consumer.git@v1.0.6#egg=xblock-lti-consumer==1.0.6
|
||||
git+https://github.com/edx/edx-proctoring.git@0.12.16#egg=edx-proctoring==0.12.16
|
||||
git+https://github.com/edx/edx-proctoring.git@0.12.17#egg=edx-proctoring==0.12.17
|
||||
|
||||
# Third Party XBlocks
|
||||
-e git+https://github.com/mitodl/edx-sga@172a90fd2738f8142c10478356b2d9ed3e55334a#egg=edx-sga
|
||||
|
||||
Reference in New Issue
Block a user