Commit e4ed23fa by Douglas Hall

Merge pull request #12367 from edx/rc/2016-05-05

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