Merge pull request #23550 from edx/ndalfonso/AA-85-reset-dates-mobile

AA-85 mobile reset dates
This commit is contained in:
Nick
2020-04-02 09:53:50 -04:00
committed by GitHub
16 changed files with 245 additions and 69 deletions

View File

@@ -51,7 +51,9 @@ from openedx.features.course_experience import (
default_course_url_name,
RELATIVE_DATES_FLAG,
)
from openedx.features.course_experience.urls import COURSE_HOME_VIEW_NAME
from openedx.features.course_experience.utils import get_course_outline_block_tree
from openedx.features.course_experience.utils import reset_deadlines_banner_should_display
from openedx.features.course_experience.views.course_sock import CourseSockFragmentView
from openedx.features.enterprise_support.api import data_sharing_consent_required
from shoppingcart.models import CourseRegistrationCode
@@ -450,6 +452,8 @@ class CoursewareIndex(View):
Returns and creates the rendering context for the courseware.
Also returns the table of contents for the courseware.
"""
from lms.urls import RESET_COURSE_DEADLINES_NAME
course_url_name = default_course_url_name(self.course.id)
course_url = reverse(course_url_name, kwargs={'course_id': six.text_type(self.course.id)})
show_search = (
@@ -458,31 +462,14 @@ class CoursewareIndex(View):
)
staff_access = self.is_staff
reset_deadlines_url = reverse(
'openedx.course_experience.reset_course_deadlines', kwargs={'course_id': six.text_type(self.course.id)}
)
allow_anonymous = allow_public_access(self.course, [COURSE_VISIBILITY_PUBLIC])
display_reset_dates_banner = False
if not allow_anonymous and RELATIVE_DATES_FLAG.is_enabled(self.course.id): # pylint: disable=too-many-nested-blocks
course_overview = CourseOverview.objects.get(id=str(self.course_key))
end_date = getattr(course_overview, 'end_date')
if course_overview.self_paced and (not end_date or timezone.now() < end_date):
if (CourseEnrollment.objects.filter(
course=course_overview, user=request.user, mode=CourseMode.VERIFIED
).exists()):
course_block_tree = get_course_outline_block_tree(
request, str(self.course_key), request.user
)
course_sections = course_block_tree.get('children', [])
for section in course_sections:
if display_reset_dates_banner:
break
for subsection in section.get('children', []):
if (not subsection.get('complete', True)
and subsection.get('due', timezone.now() + timedelta(1)) < timezone.now()):
display_reset_dates_banner = True
break
if not allow_anonymous and RELATIVE_DATES_FLAG.is_enabled(self.course.id):
display_reset_dates_banner = reset_deadlines_banner_should_display(self.course_key, request)
reset_deadlines_url = reverse(RESET_COURSE_DEADLINES_NAME) if display_reset_dates_banner else None
reset_deadlines_redirect_url_base = COURSE_HOME_VIEW_NAME if reset_deadlines_url else None
courseware_context = {
'csrf': csrf(self.request)['csrf_token'],
@@ -506,8 +493,10 @@ class CoursewareIndex(View):
'disable_accordion': COURSE_OUTLINE_PAGE_FLAG.is_enabled(self.course.id),
'show_search': show_search,
'relative_dates_is_enabled': RELATIVE_DATES_FLAG.is_enabled(self.course.id),
'reset_deadlines_url': reset_deadlines_url,
'display_reset_dates_banner': display_reset_dates_banner,
'reset_deadlines_url': reset_deadlines_url,
'reset_deadlines_redirect_url_base': reset_deadlines_redirect_url_base,
'reset_deadlines_redirect_url_id_dict': {'course_id': str(self.course.id)},
}
courseware_context.update(
get_experiment_user_metadata_context(

View File

@@ -115,6 +115,7 @@ from openedx.features.course_experience import (
RELATIVE_DATES_FLAG,
)
from openedx.features.course_experience.course_tools import CourseToolsPluginManager
from openedx.features.course_experience.utils import reset_deadlines_banner_should_display
from openedx.features.course_experience.views.course_dates import CourseDatesFragmentView
from openedx.features.course_experience.waffle import ENABLE_COURSE_ABOUT_SIDEBAR_HTML
from openedx.features.course_experience.waffle import waffle as course_experience_waffle
@@ -717,6 +718,9 @@ class CourseTabView(EdxFragmentView):
"""
Creates the context for the fragment's template.
"""
from lms.urls import RESET_COURSE_DEADLINES_NAME
from openedx.features.course_experience.urls import COURSE_HOME_VIEW_NAME
can_masquerade = request.user.has_perm(MASQUERADE_AS_STUDENT, course)
supports_preview_menu = tab.get('supports_preview_menu', False)
uses_bootstrap = self.uses_bootstrap(request, course, tab=tab)
@@ -731,10 +735,6 @@ class CourseTabView(EdxFragmentView):
else:
masquerade = None
reset_deadlines_url = reverse(
'openedx.course_experience.reset_course_deadlines', kwargs={'course_id': text_type(course.id)}
)
display_reset_dates_banner = False
if RELATIVE_DATES_FLAG.is_enabled(course.id):
course_overview = CourseOverview.get_from_id(course.id)
@@ -744,6 +744,10 @@ class CourseTabView(EdxFragmentView):
).exists()):
display_reset_dates_banner = True
reset_deadlines_url = reverse(RESET_COURSE_DEADLINES_NAME) if display_reset_dates_banner else None
reset_deadlines_redirect_url_base = COURSE_HOME_VIEW_NAME if reset_deadlines_url else None
context = {
'course': course,
'tab': tab,
@@ -754,8 +758,10 @@ class CourseTabView(EdxFragmentView):
'uses_bootstrap': uses_bootstrap,
'uses_pattern_library': not uses_bootstrap,
'disable_courseware_js': True,
'reset_deadlines_url': reset_deadlines_url,
'display_reset_dates_banner': display_reset_dates_banner,
'reset_deadlines_url': reset_deadlines_url,
'reset_deadlines_redirect_url_base': reset_deadlines_redirect_url_base,
'reset_deadlines_redirect_url_id_dict': {'course_id': str(course.id)}
}
# Avoid Multiple Mathjax loading on the 'user_profile'
if 'profile_page_context' in kwargs:
@@ -1614,11 +1620,14 @@ def _track_successful_certificate_generation(user_id, course_id):
@ensure_valid_usage_key
@xframe_options_exempt
@transaction.non_atomic_requests
@ensure_csrf_cookie
def render_xblock(request, usage_key_string, check_if_enrolled=True):
"""
Returns an HttpResponse with HTML content for the xBlock with the given usage_key.
The returned HTML is a chromeless rendering of the xBlock (excluding content of the containing courseware).
"""
from lms.urls import RENDER_XBLOCK_NAME, RESET_COURSE_DEADLINES_NAME
usage_key = UsageKey.from_string(usage_key_string)
usage_key = usage_key.replace(course_key=modulestore().fill_in_run(usage_key.course_key))
@@ -1655,6 +1664,14 @@ 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()
}
display_reset_dates_banner = False
if RELATIVE_DATES_FLAG.is_enabled(course.id):
display_reset_dates_banner = reset_deadlines_banner_should_display(course_key, request)
reset_deadlines_url = reverse(RESET_COURSE_DEADLINES_NAME) if display_reset_dates_banner else None
reset_deadlines_redirect_url_base = RENDER_XBLOCK_NAME if reset_deadlines_url else None
context = {
'fragment': block.render('student_view', context=student_view_context),
'course': course,
@@ -1667,6 +1684,10 @@ def render_xblock(request, usage_key_string, check_if_enrolled=True):
'edx_notes_enabled': is_feature_enabled(course, request.user),
'staff_access': bool(request.user.has_perm(VIEW_XQA_INTERFACE, course)),
'xqa_server': settings.FEATURES.get('XQA_SERVER', 'http://your_xqa_server.com'),
'display_reset_dates_banner': display_reset_dates_banner,
'reset_deadlines_url': reset_deadlines_url,
'reset_deadlines_redirect_url_base': reset_deadlines_redirect_url_base,
'reset_deadlines_redirect_url_id_dict': {'course_id': str(course.id), 'usage_key_string': usage_key_string}
}
return render_to_response('courseware/courseware-chromeless.html', context)

View File

@@ -316,7 +316,7 @@ div.reset-deadlines-banner {
color: theme-color("inverse");
padding-top: 10px;
margin-right: 10px;
flex: 0 0 auto;
flex: 0 1 auto;
}
form {

View File

@@ -7,7 +7,7 @@ div.reset-deadlines-banner {
div,
button {
flex: 0 0 auto;
flex: 0 1 auto;
&.reset-deadlines-text {
color: theme-color("inverse");

View File

@@ -3,3 +3,28 @@
@import 'bourbon/bourbon';
@import 'vendor/bi-app/bi-app-rtl'; // set the layout for right to left languages
@import 'build-mobile';
.reset-deadlines-banner {
background-color: theme-color("primary");
display: flex;
flex-wrap: wrap;
padding: 15px 20px;
margin-top: 5px;
div,
button {
flex: 0 1 auto;
&.reset-deadlines-text {
color: theme-color("inverse");
padding-top: 10px;
margin-right: 10px;
}
&.reset-deadlines-button {
color: #0075b4;
background-color: theme-color("inverse");
cursor: pointer;
}
}
}

View File

@@ -3,3 +3,28 @@
@import 'bourbon/bourbon';
@import 'vendor/bi-app/bi-app-ltr'; // set the layout for left to right languages
@import 'build-mobile';
.reset-deadlines-banner {
background-color: theme-color("primary");
display: flex;
flex-wrap: wrap;
padding: 15px 20px;
margin-top: 5px;
div,
button {
flex: 0 1 auto;
&.reset-deadlines-text {
color: theme-color("inverse");
padding-top: 10px;
margin-right: 10px;
}
&.reset-deadlines-button {
color: #0075b4;
background-color: theme-color("inverse");
cursor: pointer;
}
}
}

View File

@@ -12,6 +12,13 @@ from openedx.core.djangolib.js_utils import js_escaped_string
<% return _("{course_number} Courseware").format(course_number=course.display_number_with_default) %>
</%def>
% if display_reset_dates_banner:
<%include file="/reset_deadlines_banner.html" />
<script type="text/javascript">
$('.reset-deadlines-banner').css('display', 'flex');
</script>
% endif
<%block name="bodyclass">view-in-course view-courseware courseware ${course.css_class or ''}</%block>
<%block name="title"><title>
% if section_title:

View File

@@ -8,6 +8,8 @@ from django.utils.translation import ugettext as _
<div class="reset-deadlines-text">${_("It looks like you've missed some important deadlines. Reset your deadlines and get started today.")}</div>
<form method="post" action="${reset_deadlines_url}">
<input type="hidden" id="csrf_token" name="csrfmiddlewaretoken" value="${csrf_token}">
<input type="hidden" name="reset_deadlines_redirect_url_base" value="${reset_deadlines_redirect_url_base}">
<input type="hidden" name="reset_deadlines_redirect_url_id_dict" value="${reset_deadlines_redirect_url_id_dict}">
<button class="btn reset-deadlines-button">${_("Reset my deadlines")}</button>
</form>
</div>

View File

@@ -55,6 +55,9 @@ from staticbook import views as staticbook_views
from student import views as student_views
from util import views as util_views
RESET_COURSE_DEADLINES_NAME = 'reset_course_deadlines'
RENDER_XBLOCK_NAME = 'render_xblock'
if settings.DEBUG or settings.FEATURES.get('ENABLE_DJANGO_ADMIN_SITE'):
django_autodiscover()
admin.site.site_header = _('LMS Administration')
@@ -237,6 +240,7 @@ COURSE_URLS = [
name='registration_code_details',
),
]
urlpatterns += [
# jump_to URLs for direct access to a location in the course
url(
@@ -291,7 +295,7 @@ urlpatterns += [
url(
r'^xblock/{usage_key_string}$'.format(usage_key_string=settings.USAGE_KEY_PATTERN),
courseware_views.render_xblock,
name='render_xblock',
name=RENDER_XBLOCK_NAME,
),
# xblock Resource URL
@@ -316,6 +320,12 @@ urlpatterns += [
# TODO: These views need to be updated before they work
url(r'^calculate$', util_views.calculate),
url(
r'^reset_deadlines$',
util_views.reset_course_deadlines,
name=RESET_COURSE_DEADLINES_NAME,
),
url(r'^courses/?$', branding_views.courses, name='courses'),
# About the course