Merge pull request #24142 from cpennington/allow-reset-for-visible-missed-dates
Allow reset for visible missed dates
This commit is contained in:
@@ -21,6 +21,7 @@ from six.moves import map
|
||||
from lms.djangoapps.courseware.access import has_access
|
||||
from lms.djangoapps.courseware.masquerade import setup_masquerade
|
||||
from openedx.core.djangoapps.schedules.utils import reset_self_paced_schedule
|
||||
from openedx.features.course_experience.utils import dates_banner_should_display
|
||||
|
||||
import track.views
|
||||
from edxmako.shortcuts import render_to_response
|
||||
@@ -218,7 +219,10 @@ def reset_course_deadlines(request):
|
||||
user = masquerade_user
|
||||
else:
|
||||
user = request.user
|
||||
reset_self_paced_schedule(user, course_key)
|
||||
|
||||
missed_deadlines, missed_gated_content = dates_banner_should_display(course_key, user)
|
||||
if missed_deadlines and not missed_gated_content:
|
||||
reset_self_paced_schedule(user, course_key)
|
||||
if redirect_url == RENDER_XBLOCK_NAME:
|
||||
detail_id_dict.pop('course_id')
|
||||
return redirect(reverse(redirect_url, kwargs=detail_id_dict))
|
||||
|
||||
@@ -38,7 +38,8 @@ class DatesTabSerializer(serializers.Serializer):
|
||||
Serializer for the Dates Tab
|
||||
"""
|
||||
course_date_blocks = DateSummarySerializer(many=True)
|
||||
display_reset_dates_text = serializers.BooleanField()
|
||||
missed_deadlines = serializers.BooleanField()
|
||||
missed_gated_content = serializers.BooleanField()
|
||||
learner_is_full_access = serializers.BooleanField()
|
||||
user_timezone = serializers.CharField()
|
||||
verified_upgrade_link = serializers.URLField()
|
||||
|
||||
@@ -43,8 +43,8 @@ class DatesTabView(RetrieveAPIView):
|
||||
link: (str) An absolute link to content related to the date event
|
||||
(ex. verified link or link to assignment)
|
||||
title: (str) The title of the date event
|
||||
display_reset_dates_text: (bool) Indicates whether the reset dates banner should be shown
|
||||
for the given user
|
||||
missed_deadlines: (bool) Indicates whether the user missed any graded content deadlines
|
||||
missed_gated_content: (bool) Indicates whether the user missed gated content
|
||||
learner_is_full_access: (bool) Indicates if the user is verified in the course
|
||||
user_timezone: (str) The user's preferred timezone
|
||||
verified_upgrade_link: (str) The link for upgrading to the Verified track in a course
|
||||
@@ -73,7 +73,7 @@ class DatesTabView(RetrieveAPIView):
|
||||
|
||||
course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=False)
|
||||
blocks = get_course_date_blocks(course, request.user, request, include_access=True, include_past_dates=True)
|
||||
display_reset_dates_text = dates_banner_should_display(course_key, request)
|
||||
missed_deadlines, missed_gated_content = dates_banner_should_display(course_key, request.user)
|
||||
|
||||
learner_is_full_access = not ContentTypeGatingConfig.enabled_for_enrollment(
|
||||
user=request.user,
|
||||
@@ -86,7 +86,8 @@ class DatesTabView(RetrieveAPIView):
|
||||
|
||||
data = {
|
||||
'course_date_blocks': [block for block in blocks if not isinstance(block, TodaysDate)],
|
||||
'display_reset_dates_text': display_reset_dates_text,
|
||||
'missed_deadlines': missed_deadlines,
|
||||
'missed_gated_content': missed_gated_content,
|
||||
'learner_is_full_access': learner_is_full_access,
|
||||
'user_timezone': user_timezone,
|
||||
'verified_upgrade_link': verified_upgrade_deadline_link(request.user, course=course),
|
||||
|
||||
@@ -1060,7 +1060,7 @@ def dates(request, course_id):
|
||||
user_timezone = user_timezone_locale['user_timezone']
|
||||
user_language = user_timezone_locale['user_language']
|
||||
|
||||
missed_deadlines = dates_banner_should_display(course_key, request)
|
||||
missed_deadlines, missed_gated_content = dates_banner_should_display(course_key, request.user)
|
||||
|
||||
context = {
|
||||
'course': course,
|
||||
@@ -1078,6 +1078,7 @@ def dates(request, course_id):
|
||||
course_key=course_key,
|
||||
),
|
||||
'missed_deadlines': missed_deadlines,
|
||||
'missed_gated_content': missed_gated_content,
|
||||
'reset_deadlines_url': reverse(RESET_COURSE_DEADLINES_NAME),
|
||||
'reset_deadlines_redirect_url_base': COURSE_DATES_NAME,
|
||||
'reset_deadlines_redirect_url_id_dict': {'course_id': str(course.id)}
|
||||
@@ -1663,7 +1664,7 @@ def render_xblock(request, usage_key_string, check_if_enrolled=True):
|
||||
'mark-completed-on-view-after-delay': completion_service.get_complete_on_view_delay_ms()
|
||||
}
|
||||
|
||||
missed_deadlines = dates_banner_should_display(course_key, request)
|
||||
missed_deadlines, missed_gated_content = dates_banner_should_display(course_key, request.user)
|
||||
|
||||
context = {
|
||||
'fragment': block.render('student_view', context=student_view_context),
|
||||
@@ -1678,12 +1679,9 @@ def render_xblock(request, usage_key_string, check_if_enrolled=True):
|
||||
'staff_access': bool(request.user.has_perm(VIEW_XQA_INTERFACE, course)),
|
||||
'xqa_server': settings.FEATURES.get('XQA_SERVER', 'http://your_xqa_server.com'),
|
||||
'missed_deadlines': missed_deadlines,
|
||||
'missed_gated_content': missed_gated_content,
|
||||
'web_app_course_url': reverse(COURSE_HOME_VIEW_NAME, args=[course.id]),
|
||||
'on_courseware_page': True,
|
||||
'content_type_gating_enabled': ContentTypeGatingConfig.enabled_for_enrollment(
|
||||
user=request.user,
|
||||
course_key=course_key,
|
||||
),
|
||||
'verified_upgrade_link': verified_upgrade_deadline_link(request.user, course=course),
|
||||
'is_learning_mfe': request.META.get('HTTP_REFERER', '').startswith(settings.LEARNING_MICROFRONTEND_URL),
|
||||
'is_mobile_app': is_request_from_mobile_app(request),
|
||||
|
||||
@@ -319,10 +319,6 @@
|
||||
|
||||
// Course outline for visual progress waffle switch
|
||||
.course-outline {
|
||||
.dates-banner-wrapper {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.block-tree {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
@@ -96,7 +96,7 @@ additional_styling_class = 'on-mobile' if is_mobile_app else 'has-button'
|
||||
% if on_dates_tab and content_type_gating_enabled and not missed_deadlines:
|
||||
${upgrade_to_complete_graded_banner()}
|
||||
% elif missed_deadlines:
|
||||
% if content_type_gating_enabled:
|
||||
% if missed_gated_content:
|
||||
${upgrade_to_reset_banner()}
|
||||
% else:
|
||||
${reset_dates_banner()}
|
||||
|
||||
@@ -482,7 +482,7 @@ class BlockStructureBlockData(BlockStructure):
|
||||
|
||||
override_data (object) - The data you want to set
|
||||
"""
|
||||
block_data = self._block_data_map.get(usage_key)
|
||||
block_data = self._get_or_create_block(usage_key)
|
||||
setattr(block_data, field_name, override_data)
|
||||
|
||||
def get_transformer_data(self, transformer, key, default=None):
|
||||
|
||||
@@ -26,11 +26,7 @@ is_course_staff = bool(user and course and has_access(user, 'staff', course, cou
|
||||
dates_banner_displayed = False
|
||||
%>
|
||||
<main role="main" class="course-outline" id="main" tabindex="-1">
|
||||
<div class="dates-banner-wrapper">
|
||||
% if relative_dates_flag_is_enabled and self_paced and not is_course_staff:
|
||||
<%include file="/dates_banner.html" />
|
||||
% endif
|
||||
</div>
|
||||
<%include file="/dates_banner.html" />
|
||||
% if course_sections is not None:
|
||||
<button class="btn btn-primary"
|
||||
id="expand-collapse-outline-all-button"
|
||||
@@ -69,15 +65,7 @@ dates_banner_displayed = False
|
||||
scored = 'scored' if subsection.get('scored', False) else ''
|
||||
graded = 'graded' if subsection.get('graded') else ''
|
||||
num_graded_problems = subsection.get('num_graded_problems', 0)
|
||||
due_date = subsection.get('due')
|
||||
overdue = due_date is not None and due_date < timezone.now() and not subsection.get('complete', True)
|
||||
%>
|
||||
% if graded and overdue and not dates_banner_displayed:
|
||||
<% dates_banner_displayed = True %>
|
||||
<script type="text/javascript">
|
||||
$('.dates-banner-wrapper').css('display', 'block');
|
||||
</script>
|
||||
% endif
|
||||
<li class="subsection accordion ${ 'current' if subsection.get('resume_block') else '' } ${graded} ${scored}">
|
||||
<a
|
||||
% if enable_links:
|
||||
|
||||
@@ -219,7 +219,7 @@ class TestCourseHomePage(CourseHomePageTestCase):
|
||||
|
||||
# Fetch the view and verify the query counts
|
||||
# TODO: decrease query count as part of REVO-28
|
||||
with self.assertNumQueries(75, table_blacklist=QUERY_COUNT_TABLE_BLACKLIST):
|
||||
with self.assertNumQueries(74, table_blacklist=QUERY_COUNT_TABLE_BLACKLIST):
|
||||
with check_mongo_calls(4):
|
||||
url = course_home_url(self.course)
|
||||
self.client.get(url)
|
||||
|
||||
@@ -13,7 +13,7 @@ from completion import waffle
|
||||
from completion.models import BlockCompletion
|
||||
from completion.test_utils import CompletionWaffleTestMixin
|
||||
from django.contrib.sites.models import Site
|
||||
from django.test import override_settings
|
||||
from django.test import override_settings, RequestFactory
|
||||
from django.urls import reverse
|
||||
from django.utils import timezone
|
||||
from milestones.tests.utils import MilestonesTestCaseMixin
|
||||
@@ -32,6 +32,7 @@ from gating import api as lms_gating_api
|
||||
from lms.djangoapps.course_api.blocks.transformers.milestones import MilestonesAndSpecialExamsTransformer
|
||||
from openedx.core.djangoapps.schedules.models import Schedule
|
||||
from openedx.core.djangoapps.schedules.tests.factories import ScheduleFactory
|
||||
from openedx.core.djangoapps.course_date_signals.models import SelfPacedRelativeDatesConfig
|
||||
from openedx.core.lib.gating import api as gating_api
|
||||
from openedx.features.course_experience import RELATIVE_DATES_FLAG
|
||||
from openedx.features.content_type_gating.models import ContentTypeGatingConfig
|
||||
@@ -45,6 +46,8 @@ from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
|
||||
|
||||
from ...utils import get_course_outline_block_tree
|
||||
|
||||
from .test_course_home import course_home_url
|
||||
|
||||
TEST_PASSWORD = 'test'
|
||||
@@ -56,11 +59,16 @@ class TestCourseOutlinePage(SharedModuleStoreTestCase):
|
||||
"""
|
||||
Test the course outline view.
|
||||
"""
|
||||
|
||||
ENABLED_SIGNALS = ['course_published']
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
"""
|
||||
Set up an array of various courses to be tested.
|
||||
"""
|
||||
SelfPacedRelativeDatesConfig.objects.create(enabled=True)
|
||||
|
||||
# setUpClassAndTestData() already calls setUpClass on SharedModuleStoreTestCase
|
||||
# pylint: disable=super-method-not-called
|
||||
with super(TestCourseOutlinePage, cls).setUpClassAndTestData():
|
||||
@@ -68,11 +76,13 @@ class TestCourseOutlinePage(SharedModuleStoreTestCase):
|
||||
course = CourseFactory.create(self_paced=True)
|
||||
with cls.store.bulk_operations(course.id):
|
||||
chapter = ItemFactory.create(category='chapter', parent_location=course.location)
|
||||
sequential = ItemFactory.create(category='sequential', parent_location=chapter.location)
|
||||
sequential = ItemFactory.create(category='sequential', parent_location=chapter.location, graded=True, format="Homework")
|
||||
vertical = ItemFactory.create(category='vertical', parent_location=sequential.location)
|
||||
problem = ItemFactory.create(category='problem', parent_location=vertical.location)
|
||||
course.children = [chapter]
|
||||
chapter.children = [sequential]
|
||||
sequential.children = [vertical]
|
||||
vertical.children = [problem]
|
||||
cls.courses.append(course)
|
||||
|
||||
course = CourseFactory.create()
|
||||
@@ -117,7 +127,11 @@ class TestCourseOutlinePage(SharedModuleStoreTestCase):
|
||||
"""Set up and enroll our fake user in the course."""
|
||||
cls.user = UserFactory(password=TEST_PASSWORD)
|
||||
for course in cls.courses:
|
||||
CourseEnrollment.enroll(cls.user, course.id)
|
||||
enrollment = CourseEnrollment.enroll(cls.user, course.id)
|
||||
ScheduleFactory.create(
|
||||
start_date=timezone.now() - datetime.timedelta(days=1),
|
||||
enrollment=enrollment
|
||||
)
|
||||
|
||||
def setUp(self):
|
||||
"""
|
||||
@@ -126,21 +140,32 @@ class TestCourseOutlinePage(SharedModuleStoreTestCase):
|
||||
super(TestCourseOutlinePage, self).setUp()
|
||||
self.client.login(username=self.user.username, password=TEST_PASSWORD)
|
||||
|
||||
@RELATIVE_DATES_FLAG.override(active=True)
|
||||
def test_outline_details(self):
|
||||
for course in self.courses:
|
||||
|
||||
url = course_home_url(course)
|
||||
|
||||
request_factory = RequestFactory()
|
||||
request = request_factory.get(url)
|
||||
request.user = self.user
|
||||
|
||||
course_block_tree = get_course_outline_block_tree(
|
||||
request, str(course.id), self.user
|
||||
)
|
||||
|
||||
response = self.client.get(url)
|
||||
self.assertTrue(course.children)
|
||||
for chapter in course.children:
|
||||
self.assertContains(response, chapter.display_name)
|
||||
self.assertTrue(chapter.children)
|
||||
for sequential in chapter.children:
|
||||
self.assertContains(response, sequential.display_name)
|
||||
if sequential.graded:
|
||||
self.assertContains(response, sequential.due.strftime(u'%Y-%m-%d %H:%M:%S'))
|
||||
self.assertContains(response, sequential.format)
|
||||
self.assertTrue(sequential.children)
|
||||
for chapter in course_block_tree['children']:
|
||||
self.assertContains(response, chapter['display_name'])
|
||||
self.assertTrue(chapter['children'])
|
||||
for sequential in chapter['children']:
|
||||
self.assertContains(response, sequential['display_name'])
|
||||
if sequential['graded']:
|
||||
print(sequential)
|
||||
self.assertContains(response, sequential['due'].strftime(u'%Y-%m-%d %H:%M:%S'))
|
||||
self.assertContains(response, sequential['format'])
|
||||
self.assertTrue(sequential['children'])
|
||||
|
||||
def test_num_graded_problems(self):
|
||||
course = CourseFactory.create()
|
||||
@@ -188,7 +213,7 @@ class TestCourseOutlinePage(SharedModuleStoreTestCase):
|
||||
):
|
||||
ContentTypeGatingConfig.objects.create(
|
||||
enabled=True,
|
||||
enabled_as_of=datetime.datetime(2018, 1, 1),
|
||||
enabled_as_of=datetime.datetime(2017, 1, 1),
|
||||
)
|
||||
course = self.courses[0]
|
||||
for mode in course_modes:
|
||||
@@ -197,6 +222,8 @@ class TestCourseOutlinePage(SharedModuleStoreTestCase):
|
||||
enrollment = CourseEnrollment.objects.get(course_id=course.id, user=self.user)
|
||||
enrollment.mode = enrollment_mode
|
||||
enrollment.save()
|
||||
enrollment.schedule.start_date = timezone.now() - datetime.timedelta(days=30)
|
||||
enrollment.schedule.save()
|
||||
self.user.is_staff = is_course_staff
|
||||
self.user.save()
|
||||
|
||||
@@ -208,28 +235,21 @@ class TestCourseOutlinePage(SharedModuleStoreTestCase):
|
||||
else:
|
||||
self.assertNotContains(response, '<div class="dates-banner-text"')
|
||||
|
||||
@RELATIVE_DATES_FLAG.override(active=True)
|
||||
def test_reset_course_deadlines(self):
|
||||
course = self.courses[0]
|
||||
enrollment = CourseEnrollment.objects.get(course_id=course.id)
|
||||
ScheduleFactory(
|
||||
start_date=timezone.now() - datetime.timedelta(1),
|
||||
enrollment=enrollment
|
||||
)
|
||||
enrollment.schedule.start_date = timezone.now() - datetime.timedelta(days=30)
|
||||
enrollment.schedule.save()
|
||||
post_dict = {'reset_deadlines_redirect_url_id_dict': json.dumps({'course_id': str(course.id)})}
|
||||
self.client.post(reverse(RESET_COURSE_DEADLINES_NAME), post_dict)
|
||||
updated_schedule = Schedule.objects.get(enrollment=enrollment)
|
||||
self.assertEqual(updated_schedule.start_date.date(), datetime.datetime.today().date())
|
||||
|
||||
def test_reset_course_deadlines_masquerade_specific_student(self):
|
||||
course = self.courses[0]
|
||||
|
||||
student_schedule = ScheduleFactory(
|
||||
start_date=timezone.now() - datetime.timedelta(1),
|
||||
enrollment=CourseEnrollment.objects.get(course_id=course.id, user=self.user),
|
||||
)
|
||||
student_schedule = CourseEnrollment.objects.get(course_id=course.id, user=self.user).schedule
|
||||
student_schedule.start_date = timezone.now() - datetime.timedelta(days=30)
|
||||
student_schedule.save()
|
||||
staff = StaffFactory(course_key=course.id)
|
||||
staff_schedule = ScheduleFactory(
|
||||
start_date=timezone.now() - datetime.timedelta(1),
|
||||
start_date=timezone.now() - datetime.timedelta(days=30),
|
||||
enrollment__course__id=course.id,
|
||||
enrollment__user=staff,
|
||||
)
|
||||
@@ -256,16 +276,17 @@ class TestCourseOutlinePage(SharedModuleStoreTestCase):
|
||||
updated_staff_schedule = Schedule.objects.get(id=staff_schedule.id)
|
||||
self.assertEqual(updated_staff_schedule.start_date, staff_schedule.start_date)
|
||||
|
||||
@RELATIVE_DATES_FLAG.override(active=True)
|
||||
def test_reset_course_deadlines_masquerade_generic_student(self):
|
||||
course = self.courses[0]
|
||||
|
||||
student_schedule = ScheduleFactory(
|
||||
start_date=timezone.now() - datetime.timedelta(1),
|
||||
enrollment=CourseEnrollment.objects.get(course_id=course.id, user=self.user),
|
||||
)
|
||||
student_schedule = CourseEnrollment.objects.get(course_id=course.id, user=self.user).schedule
|
||||
student_schedule.start_date = timezone.now() - datetime.timedelta(days=30)
|
||||
student_schedule.save()
|
||||
|
||||
staff = StaffFactory(course_key=course.id)
|
||||
staff_schedule = ScheduleFactory(
|
||||
start_date=timezone.now() - datetime.timedelta(1),
|
||||
start_date=timezone.now() - datetime.timedelta(days=30),
|
||||
enrollment__course__id=course.id,
|
||||
enrollment__user=staff,
|
||||
)
|
||||
@@ -290,7 +311,7 @@ class TestCourseOutlinePage(SharedModuleStoreTestCase):
|
||||
updated_student_schedule = Schedule.objects.get(id=student_schedule.id)
|
||||
self.assertEqual(updated_student_schedule.start_date, student_schedule.start_date)
|
||||
updated_staff_schedule = Schedule.objects.get(id=staff_schedule.id)
|
||||
self.assertEqual(updated_staff_schedule.start_date.date(), datetime.datetime.today().date())
|
||||
self.assertEqual(updated_staff_schedule.start_date.date(), datetime.date.today())
|
||||
|
||||
|
||||
class TestCourseOutlinePageWithPrerequisites(SharedModuleStoreTestCase, MilestonesTestCaseMixin):
|
||||
|
||||
@@ -202,7 +202,7 @@ def get_course_outline_block_tree(request, course_id, user=None, allow_start_dat
|
||||
all_blocks = get_blocks(
|
||||
request,
|
||||
course_usage_key,
|
||||
user=request.user,
|
||||
user=user,
|
||||
nav_depth=3,
|
||||
requested_fields=[
|
||||
'children',
|
||||
@@ -232,7 +232,7 @@ def get_course_outline_block_tree(request, course_id, user=None, allow_start_dat
|
||||
set_last_accessed_default(course_outline_root_block)
|
||||
mark_blocks_completed(
|
||||
block=course_outline_root_block,
|
||||
user=request.user,
|
||||
user=user,
|
||||
course_key=course_key
|
||||
)
|
||||
return course_outline_root_block
|
||||
@@ -255,15 +255,20 @@ def get_resume_block(block):
|
||||
return block
|
||||
|
||||
|
||||
def dates_banner_should_display(course_key, request):
|
||||
def dates_banner_should_display(course_key, user):
|
||||
"""
|
||||
Return whether or not the reset banner should display,
|
||||
determined by whether or not a course has any past-due,
|
||||
incomplete sequentials and which enrollment mode is being
|
||||
dealt with for the current user and course.
|
||||
|
||||
Returns:
|
||||
(missed_deadlines, missed_gated_content):
|
||||
missed_deadlines is True if the user has missed any graded content deadlines
|
||||
missed_gated_content is True if the first content that the user missed was gated content
|
||||
"""
|
||||
if not RELATIVE_DATES_FLAG.is_enabled(str(course_key)):
|
||||
return False
|
||||
if not RELATIVE_DATES_FLAG.is_enabled(course_key):
|
||||
return False, False
|
||||
|
||||
course_overview = CourseOverview.objects.get(id=str(course_key))
|
||||
course_end_date = getattr(course_overview, 'end_date', None)
|
||||
@@ -271,26 +276,26 @@ def dates_banner_should_display(course_key, request):
|
||||
|
||||
# Only display the banner for self-paced courses
|
||||
if not is_self_paced:
|
||||
return False
|
||||
return False, False
|
||||
|
||||
# Only display the banner for enrolled users
|
||||
if not CourseEnrollment.is_enrolled(request.user, course_key):
|
||||
return False
|
||||
if not CourseEnrollment.is_enrolled(user, course_key):
|
||||
return False, False
|
||||
|
||||
# Don't display the banner for course staff
|
||||
is_course_staff = bool(
|
||||
request.user and course_overview and has_access(request.user, 'staff', course_overview, course_overview.id)
|
||||
user and course_overview and has_access(user, 'staff', course_overview, course_overview.id)
|
||||
)
|
||||
if is_course_staff:
|
||||
return False
|
||||
return False, False
|
||||
|
||||
# Don't display the banner if the course has ended
|
||||
if course_end_date and course_end_date < timezone.now():
|
||||
return False
|
||||
return False, False
|
||||
|
||||
store = modulestore()
|
||||
course_usage_key = store.make_course_usage_key(course_key)
|
||||
block_data = get_course_blocks(request.user, course_usage_key, include_completion=True)
|
||||
block_data = get_course_blocks(user, course_usage_key, include_completion=True)
|
||||
for section_key in block_data.get_children(course_usage_key):
|
||||
for subsection_key in block_data.get_children(section_key):
|
||||
subsection_due_date = block_data.get_xblock_field(subsection_key, 'due', None)
|
||||
@@ -301,7 +306,7 @@ def dates_banner_should_display(course_key, request):
|
||||
):
|
||||
# Display the banner if the due date for an incomplete graded subsection
|
||||
# has passed
|
||||
return True
|
||||
return True, block_data.get_xblock_field(subsection_key, 'contains_gated_content', False)
|
||||
|
||||
# Don't display the banner if there were no missed deadlines
|
||||
return False
|
||||
return False, False
|
||||
|
||||
@@ -31,6 +31,7 @@ from openedx.core.djangoapps.content.course_overviews.models import CourseOvervi
|
||||
from openedx.core.djangoapps.plugin_api.views import EdxFragmentView
|
||||
from openedx.core.djangoapps.schedules.utils import reset_self_paced_schedule
|
||||
from openedx.features.course_experience import RELATIVE_DATES_FLAG
|
||||
from openedx.features.course_experience.utils import dates_banner_should_display
|
||||
from openedx.features.content_type_gating.models import ContentTypeGatingConfig
|
||||
from student.models import CourseEnrollment
|
||||
from util.milestones_helpers import get_course_content_milestones
|
||||
@@ -83,6 +84,8 @@ class CourseOutlineFragmentView(EdxFragmentView):
|
||||
xblock_display_names = self.create_xblock_id_and_name_dict(course_block_tree)
|
||||
gated_content = self.get_content_milestones(request, course_key)
|
||||
|
||||
missed_deadlines, missed_gated_content = dates_banner_should_display(course_key, request.user)
|
||||
|
||||
context['gated_content'] = gated_content
|
||||
context['xblock_display_names'] = xblock_display_names
|
||||
|
||||
@@ -102,13 +105,8 @@ class CourseOutlineFragmentView(EdxFragmentView):
|
||||
context['reset_deadlines_redirect_url_id_dict'] = {'course_id': str(course.id)}
|
||||
context['verified_upgrade_link'] = verified_upgrade_deadline_link(request.user, course=course)
|
||||
context['on_course_outline_page'] = True
|
||||
context['content_type_gating_enabled'] = ContentTypeGatingConfig.enabled_for_enrollment(
|
||||
user=request.user,
|
||||
course_key=course_key
|
||||
)
|
||||
# We use javascript to check whether to actually display this banner, so we let the banner assume
|
||||
# that deadlines have been missed.
|
||||
context['missed_deadlines'] = True
|
||||
context['missed_deadlines'] = missed_deadlines
|
||||
context['missed_gated_content'] = missed_gated_content
|
||||
|
||||
html = render_to_string('course_experience/course-outline-fragment.html', context)
|
||||
return Fragment(html)
|
||||
|
||||
Reference in New Issue
Block a user