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("'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.data(
|
||||
(True, 0.9, True),
|
||||
|
||||
@@ -81,6 +81,8 @@ class VerticalBlock(SequenceFields, XModuleFields, StudioEditableBlock, XmlParse
|
||||
|
||||
# pylint: disable=no-member
|
||||
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)
|
||||
if child in list(child_blocks_to_complete_on_view):
|
||||
child_block_context['wrap_xblock_data'] = {
|
||||
|
||||
@@ -175,8 +175,9 @@ class CourseRetrieveUpdateViewTests(CourseApiViewTestMixin, ModuleStoreTestCase)
|
||||
self.assertIsNone(VerificationDeadline.deadline_for_course(self.course.id))
|
||||
|
||||
# Generate the expected data
|
||||
verification_deadline = datetime(year=2030, month=12, day=31, tzinfo=pytz.utc)
|
||||
expiration_datetime = datetime.now(pytz.utc)
|
||||
now = 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)
|
||||
|
||||
# Sanity check: The API should return HTTP status 200 for updates
|
||||
|
||||
@@ -3,7 +3,6 @@ Module rendering
|
||||
"""
|
||||
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
import logging
|
||||
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)
|
||||
)
|
||||
if access or caller_will_handle_access_error:
|
||||
descriptor.has_access_error = bool(caller_will_handle_access_error)
|
||||
return descriptor
|
||||
return None
|
||||
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)
|
||||
|
||||
|
||||
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
|
||||
|
||||
@@ -1126,7 +1127,8 @@ def get_module_by_usage_id(request, course_id, usage_id, disable_staff_debug_inf
|
||||
field_data_cache,
|
||||
usage_key.course_key,
|
||||
disable_staff_debug_info=disable_staff_debug_info,
|
||||
course=course
|
||||
course=course,
|
||||
will_recheck_access=will_recheck_access,
|
||||
)
|
||||
if instance is None:
|
||||
# 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.")
|
||||
|
||||
# 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(
|
||||
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['show_bookmark_button'] = request.GET.get('show_bookmark_button', '0') == '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
|
||||
completion_service = block.runtime.service(block, 'completion')
|
||||
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]),
|
||||
'on_courseware_page': True,
|
||||
'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),
|
||||
'reset_deadlines_url': reverse(RESET_COURSE_DEADLINES_NAME),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user