Merge pull request #25986 from edx/ddumesnil/aa-501
AA-501: Use hidden blocks to determine past due status
This commit is contained in:
@@ -196,6 +196,22 @@ class VerticalBlockTestCase(BaseVerticalBlockTest):
|
|||||||
self.assertIn("'completed': None", html)
|
self.assertIn("'completed': None", html)
|
||||||
self.assertIn("'past_due': False", html)
|
self.assertIn("'past_due': False", html)
|
||||||
|
|
||||||
|
@ddt.data(True, False)
|
||||||
|
def test_render_access_denied_blocks(self, has_access_error):
|
||||||
|
""" Tests access denied blocks are not rendered when hide_access_error_blocks is True """
|
||||||
|
self.module_system._services['bookmarks'] = Mock()
|
||||||
|
self.module_system._services['user'] = StubUserService()
|
||||||
|
self.vertical.due = datetime.now(pytz.UTC) + timedelta(days=-1)
|
||||||
|
self.problem_block.has_access_error = has_access_error
|
||||||
|
|
||||||
|
context = {'username': self.username, 'hide_access_error_blocks': True}
|
||||||
|
html = self.module_system.render(self.vertical, STUDENT_VIEW, context).content
|
||||||
|
|
||||||
|
if has_access_error:
|
||||||
|
self.assertNotIn(self.test_problem, html)
|
||||||
|
else:
|
||||||
|
self.assertIn(self.test_problem, html)
|
||||||
|
|
||||||
@ddt.unpack
|
@ddt.unpack
|
||||||
@ddt.data(
|
@ddt.data(
|
||||||
(True, 0.9, True),
|
(True, 0.9, True),
|
||||||
|
|||||||
@@ -81,6 +81,8 @@ class VerticalBlock(SequenceFields, XModuleFields, StudioEditableBlock, XmlParse
|
|||||||
|
|
||||||
# pylint: disable=no-member
|
# pylint: disable=no-member
|
||||||
for child in child_blocks:
|
for child in child_blocks:
|
||||||
|
if context.get('hide_access_error_blocks') and getattr(child, 'has_access_error', False):
|
||||||
|
continue
|
||||||
child_block_context = copy(child_context)
|
child_block_context = copy(child_context)
|
||||||
if child in list(child_blocks_to_complete_on_view):
|
if child in list(child_blocks_to_complete_on_view):
|
||||||
child_block_context['wrap_xblock_data'] = {
|
child_block_context['wrap_xblock_data'] = {
|
||||||
|
|||||||
@@ -175,8 +175,9 @@ class CourseRetrieveUpdateViewTests(CourseApiViewTestMixin, ModuleStoreTestCase)
|
|||||||
self.assertIsNone(VerificationDeadline.deadline_for_course(self.course.id))
|
self.assertIsNone(VerificationDeadline.deadline_for_course(self.course.id))
|
||||||
|
|
||||||
# Generate the expected data
|
# Generate the expected data
|
||||||
verification_deadline = datetime(year=2030, month=12, day=31, tzinfo=pytz.utc)
|
now = datetime.now(pytz.utc)
|
||||||
expiration_datetime = datetime.now(pytz.utc)
|
verification_deadline = now + timedelta(days=1)
|
||||||
|
expiration_datetime = now
|
||||||
response, expected = self._get_update_response_and_expected_data(expiration_datetime, verification_deadline)
|
response, expected = self._get_update_response_and_expected_data(expiration_datetime, verification_deadline)
|
||||||
|
|
||||||
# Sanity check: The API should return HTTP status 200 for updates
|
# Sanity check: The API should return HTTP status 200 for updates
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ Module rendering
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
import hashlib
|
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import textwrap
|
import textwrap
|
||||||
@@ -917,6 +916,7 @@ def get_module_for_descriptor_internal(user, descriptor, student_data, course_id
|
|||||||
and (access.user_message or access.user_fragment)
|
and (access.user_message or access.user_fragment)
|
||||||
)
|
)
|
||||||
if access or caller_will_handle_access_error:
|
if access or caller_will_handle_access_error:
|
||||||
|
descriptor.has_access_error = bool(caller_will_handle_access_error)
|
||||||
return descriptor
|
return descriptor
|
||||||
return None
|
return None
|
||||||
return descriptor
|
return descriptor
|
||||||
@@ -1074,7 +1074,8 @@ def handle_xblock_callback(request, course_id, usage_id, handler, suffix=None):
|
|||||||
return _invoke_xblock_handler(request, course_id, usage_id, handler, suffix, course=course)
|
return _invoke_xblock_handler(request, course_id, usage_id, handler, suffix, course=course)
|
||||||
|
|
||||||
|
|
||||||
def get_module_by_usage_id(request, course_id, usage_id, disable_staff_debug_info=False, course=None):
|
def get_module_by_usage_id(request, course_id, usage_id, disable_staff_debug_info=False, course=None,
|
||||||
|
will_recheck_access=False):
|
||||||
"""
|
"""
|
||||||
Gets a module instance based on its `usage_id` in a course, for a given request/user
|
Gets a module instance based on its `usage_id` in a course, for a given request/user
|
||||||
|
|
||||||
@@ -1126,7 +1127,8 @@ def get_module_by_usage_id(request, course_id, usage_id, disable_staff_debug_inf
|
|||||||
field_data_cache,
|
field_data_cache,
|
||||||
usage_key.course_key,
|
usage_key.course_key,
|
||||||
disable_staff_debug_info=disable_staff_debug_info,
|
disable_staff_debug_info=disable_staff_debug_info,
|
||||||
course=course
|
course=course,
|
||||||
|
will_recheck_access=will_recheck_access,
|
||||||
)
|
)
|
||||||
if instance is None:
|
if instance is None:
|
||||||
# Either permissions just changed, or someone is trying to be clever
|
# Either permissions just changed, or someone is trying to be clever
|
||||||
|
|||||||
@@ -1647,14 +1647,23 @@ def render_xblock(request, usage_key_string, check_if_enrolled=True):
|
|||||||
raise Http404("Course not found.")
|
raise Http404("Course not found.")
|
||||||
|
|
||||||
# get the block, which verifies whether the user has access to the block.
|
# get the block, which verifies whether the user has access to the block.
|
||||||
|
recheck_access = request.GET.get('recheck_access') == '1'
|
||||||
block, _ = get_module_by_usage_id(
|
block, _ = get_module_by_usage_id(
|
||||||
request, text_type(course_key), text_type(usage_key), disable_staff_debug_info=True, course=course
|
request, str(course_key), str(usage_key), disable_staff_debug_info=True, course=course,
|
||||||
|
will_recheck_access=recheck_access
|
||||||
)
|
)
|
||||||
|
|
||||||
student_view_context = request.GET.dict()
|
student_view_context = request.GET.dict()
|
||||||
student_view_context['show_bookmark_button'] = request.GET.get('show_bookmark_button', '0') == '1'
|
student_view_context['show_bookmark_button'] = request.GET.get('show_bookmark_button', '0') == '1'
|
||||||
student_view_context['show_title'] = request.GET.get('show_title', '1') == '1'
|
student_view_context['show_title'] = request.GET.get('show_title', '1') == '1'
|
||||||
|
|
||||||
|
is_learning_mfe = is_request_from_learning_mfe(request)
|
||||||
|
# Right now, we only care about this in regards to the Learning MFE because it results
|
||||||
|
# in a bad UX if we display blocks with access errors (repeated upgrade messaging).
|
||||||
|
# If other use cases appear, consider removing the is_learning_mfe check or switching this
|
||||||
|
# to be its own query parameter that can toggle the behavior.
|
||||||
|
student_view_context['hide_access_error_blocks'] = is_learning_mfe and recheck_access
|
||||||
|
|
||||||
enable_completion_on_view_service = False
|
enable_completion_on_view_service = False
|
||||||
completion_service = block.runtime.service(block, 'completion')
|
completion_service = block.runtime.service(block, 'completion')
|
||||||
if completion_service and completion_service.completion_tracking_enabled():
|
if completion_service and completion_service.completion_tracking_enabled():
|
||||||
@@ -1684,7 +1693,7 @@ def render_xblock(request, usage_key_string, check_if_enrolled=True):
|
|||||||
'web_app_course_url': reverse(COURSE_HOME_VIEW_NAME, args=[course.id]),
|
'web_app_course_url': reverse(COURSE_HOME_VIEW_NAME, args=[course.id]),
|
||||||
'on_courseware_page': True,
|
'on_courseware_page': True,
|
||||||
'verified_upgrade_link': verified_upgrade_deadline_link(request.user, course=course),
|
'verified_upgrade_link': verified_upgrade_deadline_link(request.user, course=course),
|
||||||
'is_learning_mfe': is_request_from_learning_mfe(request),
|
'is_learning_mfe': is_learning_mfe,
|
||||||
'is_mobile_app': is_request_from_mobile_app(request),
|
'is_mobile_app': is_request_from_mobile_app(request),
|
||||||
'reset_deadlines_url': reverse(RESET_COURSE_DEADLINES_NAME),
|
'reset_deadlines_url': reverse(RESET_COURSE_DEADLINES_NAME),
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user