Merge pull request #25986 from edx/ddumesnil/aa-501

AA-501: Use hidden blocks to determine past due status
This commit is contained in:
Dillon Dumesnil
2021-01-06 06:49:32 -08:00
committed by GitHub
5 changed files with 37 additions and 7 deletions

View File

@@ -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),

View File

@@ -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'] = {

View File

@@ -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

View File

@@ -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

View File

@@ -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),
}