Merge pull request #23283 from edx/ndalfonso/AA-12-reset-deadlines

AA-12 reset self paced due dates
This commit is contained in:
Nick
2020-03-04 15:42:46 -05:00
committed by GitHub
13 changed files with 158 additions and 5 deletions

View File

@@ -6,8 +6,10 @@
<%!
import json
from datetime import date
import pytz
from datetime import date, datetime, timedelta
from django.utils import timezone
from django.utils.translation import ugettext as _
from openedx.core.djangolib.markup import HTML, Text
@@ -16,6 +18,7 @@ from openedx.core.djangolib.markup import HTML, Text
<%
course_sections = blocks.get('children')
self_paced = context.get('self_paced', False)
reset_deadlines_banner_displayed = False
%>
<main role="main" class="course-outline" id="main" tabindex="-1">
% if course_sections is not None:
@@ -56,6 +59,12 @@ self_paced = context.get('self_paced', False)
scored = 'scored' if subsection.get('scored', False) else ''
graded = 'graded' if subsection.get('graded') else ''
%>
% if not subsection.get('complete', True) and subsection.get('due', timezone.now() + timedelta(1)) < timezone.now() and not reset_deadlines_banner_displayed:
<% reset_deadlines_banner_displayed = True %>
<script type="text/javascript">
$('.reset-deadlines-banner').css('display', 'flex');
</script>
% endif
<li class="subsection accordion ${ 'current' if subsection.get('resume_block') else '' } ${graded} ${scored}">
<a
% if enable_links:

View File

@@ -51,6 +51,7 @@ from openedx.core.djangolib.markup import HTML
from openedx.features.course_duration_limits.models import CourseDurationLimitConfig
from openedx.features.course_experience import (
COURSE_ENABLE_UNENROLLED_ACCESS_FLAG,
RELATIVE_DATES_FLAG,
SHOW_REVIEWS_TOOL_FLAG,
SHOW_UPGRADE_MSG_ON_COURSE_HOME,
UNIFIED_COURSE_TAB_FLAG
@@ -948,6 +949,7 @@ class CourseHomeFragmentViewTests(ModuleStoreTestCase):
self.course = CourseFactory(
start=now() - timedelta(days=30),
end=end,
self_paced=True,
)
self.url = course_home_url(self.course)
@@ -1020,3 +1022,8 @@ class CourseHomeFragmentViewTests(ModuleStoreTestCase):
response = self.client.get(self.url)
self.assertContains(response, "<span>DISCOUNT_PRICE</span>")
@override_waffle_flag(RELATIVE_DATES_FLAG, active=True)
def test_reset_deadline_banner_is_present_on_course_tab(self):
response = self.client.get(self.url)
self.assertContains(response, '<div class="reset-deadlines-banner">')

View File

@@ -14,6 +14,7 @@ from completion.test_utils import CompletionWaffleTestMixin
from django.contrib.sites.models import Site
from django.test import override_settings
from django.urls import reverse
from django.utils import timezone
from milestones.tests.utils import MilestonesTestCaseMixin
from mock import Mock, patch
from opaque_keys.edx.keys import CourseKey, UsageKey
@@ -25,6 +26,8 @@ from waffle.testutils import override_switch
from lms.djangoapps.courseware.tests.factories import StaffFactory
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.lib.gating import api as gating_api
from openedx.features.course_experience.views.course_outline import (
DEFAULT_COMPLETION_TRACKING_START,
@@ -55,7 +58,7 @@ class TestCourseOutlinePage(SharedModuleStoreTestCase):
# pylint: disable=super-method-not-called
with super(TestCourseOutlinePage, cls).setUpClassAndTestData():
cls.courses = []
course = CourseFactory.create()
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)
@@ -132,6 +135,18 @@ class TestCourseOutlinePage(SharedModuleStoreTestCase):
self.assertContains(response, sequential.format)
self.assertTrue(sequential.children)
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
)
url = '{}{}'.format(course_home_url(course), 'reset_deadlines')
self.client.post(url)
updated_schedule = Schedule.objects.get(enrollment=enrollment)
self.assertEqual(updated_schedule.start_date.day, datetime.datetime.today().day)
class TestCourseOutlinePageWithPrerequisites(SharedModuleStoreTestCase, MilestonesTestCaseMixin):
"""

View File

@@ -7,7 +7,7 @@ from django.conf.urls import url
from .views.course_dates import CourseDatesFragmentMobileView
from .views.course_home import CourseHomeFragmentView, CourseHomeView
from .views.course_outline import CourseOutlineFragmentView
from .views.course_outline import CourseOutlineFragmentView, reset_course_deadlines
from .views.course_reviews import CourseReviewsView
from .views.course_sock import CourseSockFragmentView
from .views.course_updates import CourseUpdatesFragmentView, CourseUpdatesView
@@ -70,4 +70,9 @@ urlpatterns = [
CourseDatesFragmentMobileView.as_view(),
name='openedx.course_experience.mobile_dates_fragment_view',
),
url(
r'^reset_deadlines$',
reset_course_deadlines,
name='openedx.course_experience.reset_course_deadlines',
),
]

View File

@@ -5,11 +5,16 @@ Views to show a course outline.
import datetime
import re
import pytz
import six
from completion import waffle as completion_waffle
from django.contrib.auth.models import User
from django.shortcuts import redirect
from django.template.context_processors import csrf
from django.template.loader import render_to_string
from django.urls import reverse
from django.views.decorators.csrf import ensure_csrf_cookie
import edx_when.api as edx_when_api
from opaque_keys.edx.keys import CourseKey
from pytz import UTC
@@ -17,6 +22,7 @@ from waffle.models import Switch
from web_fragments.fragment import Fragment
from lms.djangoapps.courseware.courses import get_course_overview_with_access
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
from openedx.core.djangoapps.plugin_api.views import EdxFragmentView
from student.models import CourseEnrollment
from util.milestones_helpers import get_course_content_milestones
@@ -154,3 +160,19 @@ class CourseOutlineFragmentView(EdxFragmentView):
if children:
children[0]['resume_block'] = True
self.mark_first_unit_to_resume(children[0])
@ensure_csrf_cookie
def reset_course_deadlines(request, course_id):
"""
Set the start_date of a schedule to today, which in turn will adjust due dates for
sequentials belonging to a self paced course
"""
course = CourseOverview.objects.get(id=course_id)
if course.self_paced:
enrollment = CourseEnrollment.objects.get(user=request.user, course=course_id)
schedule = enrollment.schedule
if schedule:
schedule.start_date = datetime.datetime.now(pytz.utc)
schedule.save()
return redirect(reverse('openedx.course_experience.course_home', args=[six.text_type(course_id)]))