Merge pull request #23343 from edx/jlajoie/AA-51
AA-51: Adds in 'Up next' banner to course home
This commit is contained in:
@@ -75,6 +75,7 @@
|
||||
@import 'features/course-duration-limits';
|
||||
@import 'features/enterprise-learner-portal-banner';
|
||||
@import 'features/first-purchase-banner';
|
||||
@import 'features/next-up-banner';
|
||||
|
||||
// search
|
||||
@import 'search/search';
|
||||
|
||||
@@ -28,6 +28,7 @@ $static-path: '../..';
|
||||
@import 'features/course-duration-limits';
|
||||
@import 'features/enterprise-learner-portal-banner';
|
||||
@import 'features/first-purchase-banner';
|
||||
@import 'features/next-up-banner';
|
||||
|
||||
// Individual Pages
|
||||
@import "views/program-marketing-page";
|
||||
|
||||
29
lms/static/sass/features/_next-up-banner.scss
Normal file
29
lms/static/sass/features/_next-up-banner.scss
Normal file
@@ -0,0 +1,29 @@
|
||||
// Up next banner
|
||||
.next-up-banner {
|
||||
display: none; // Required to be none for Optimizely experiment in AA-29
|
||||
background-color: #d8edf8;
|
||||
color: #393f43;
|
||||
font-size: 16px;
|
||||
border: 1px solid #bbdff2;
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
line-height: 1.5;
|
||||
margin: $baseline auto;
|
||||
padding: 20px;
|
||||
|
||||
a:not(.btn) {
|
||||
font-weight: bold;
|
||||
text-decoration: underline;
|
||||
color: #006ea9;
|
||||
|
||||
&:hover {
|
||||
color: darken(#006ea9, 15%);
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
& + .page-content {
|
||||
margin-top: 0;
|
||||
padding-top: 0;
|
||||
}
|
||||
}
|
||||
@@ -63,6 +63,9 @@ from openedx.features.course_experience.course_tools import HttpMethod
|
||||
</header>
|
||||
<div class="page-content">
|
||||
<div class="page-content-main">
|
||||
% if next_up_banner_fragment:
|
||||
${HTML(next_up_banner_fragment.body_html())}
|
||||
% endif
|
||||
% if offer_banner_fragment:
|
||||
${HTML(offer_banner_fragment.content)}
|
||||
% endif
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
## mako
|
||||
|
||||
<%page expression_filter="h"/>
|
||||
|
||||
<%!
|
||||
from django.utils.translation import ugettext as _
|
||||
%>
|
||||
|
||||
<div class="next-up-banner">
|
||||
<b>${_("Get started on what's next: ")}</b>
|
||||
<a href="${resume_course_url}">${assignment_title}</a>
|
||||
(${assignment_duration})
|
||||
</div>
|
||||
@@ -48,6 +48,7 @@ from .course_home_messages import CourseHomeMessageFragmentView
|
||||
from .course_outline import CourseOutlineFragmentView
|
||||
from .course_sock import CourseSockFragmentView
|
||||
from .latest_update import LatestUpdateFragmentView
|
||||
from .next_up_banner import NextUpBannerFragmentView
|
||||
from .welcome_message import WelcomeMessageFragmentView
|
||||
|
||||
EMPTY_HANDOUTS_HTML = u'<ol></ol>'
|
||||
@@ -88,10 +89,11 @@ class CourseHomeFragmentView(EdxFragmentView):
|
||||
"""
|
||||
Returns information relevant to resume course functionality.
|
||||
|
||||
Returns a tuple: (has_visited_course, resume_course_url)
|
||||
has_visited_course: True if the user has ever visted the course, False otherwise.
|
||||
Returns a tuple: (has_visited_course, resume_course_url, resume_course_title)
|
||||
has_visited_course: True if the user has ever visited the course, False otherwise.
|
||||
resume_course_url: The URL of the 'resume course' block if the user has visited the course,
|
||||
otherwise the URL of the course root.
|
||||
resume_course_title: The display_name of the resume course block, otherwise the display_name of course root
|
||||
|
||||
"""
|
||||
course_outline_root_block = get_course_outline_block_tree(request, course_id, request.user)
|
||||
@@ -99,10 +101,12 @@ class CourseHomeFragmentView(EdxFragmentView):
|
||||
has_visited_course = bool(resume_block)
|
||||
if resume_block:
|
||||
resume_course_url = resume_block['lms_web_url']
|
||||
resume_course_title = resume_block['display_name']
|
||||
else:
|
||||
resume_course_url = course_outline_root_block['lms_web_url'] if course_outline_root_block else None
|
||||
resume_course_title = course_outline_root_block['display_name'] if course_outline_root_block else None
|
||||
|
||||
return has_visited_course, resume_course_url
|
||||
return has_visited_course, resume_course_url, resume_course_title
|
||||
|
||||
def _get_course_handouts(self, request, course):
|
||||
"""
|
||||
@@ -141,6 +145,7 @@ class CourseHomeFragmentView(EdxFragmentView):
|
||||
update_message_fragment = None
|
||||
course_sock_fragment = None
|
||||
offer_banner_fragment = None
|
||||
next_up_banner_fragment = None
|
||||
course_expiration_fragment = None
|
||||
has_visited_course = None
|
||||
resume_course_url = None
|
||||
@@ -162,8 +167,11 @@ class CourseHomeFragmentView(EdxFragmentView):
|
||||
course_sock_fragment = CourseSockFragmentView().render_to_fragment(
|
||||
request, course=course_overview, **kwargs
|
||||
)
|
||||
has_visited_course, resume_course_url = self._get_resume_course_info(request, course_id)
|
||||
has_visited_course, resume_course_url, resume_course_title = self._get_resume_course_info(
|
||||
request, course_id
|
||||
)
|
||||
handouts_html = self._get_course_handouts(request, course)
|
||||
|
||||
offer_banner_fragment = get_first_purchase_offer_banner_fragment(
|
||||
request.user,
|
||||
course_overview
|
||||
@@ -172,6 +180,11 @@ class CourseHomeFragmentView(EdxFragmentView):
|
||||
request.user,
|
||||
course_overview
|
||||
)
|
||||
|
||||
next_up_banner_fragment = NextUpBannerFragmentView().render_to_fragment(
|
||||
assignment_title=resume_course_title, resume_course_url=resume_course_url, assignment_duration='10 min'
|
||||
)
|
||||
|
||||
elif allow_public_outline or allow_public:
|
||||
outline_fragment = CourseOutlineFragmentView().render_to_fragment(
|
||||
request, course_id=course_id, user_is_enrolled=False, **kwargs
|
||||
@@ -228,6 +241,7 @@ class CourseHomeFragmentView(EdxFragmentView):
|
||||
'course_home_message_fragment': course_home_message_fragment,
|
||||
'offer_banner_fragment': offer_banner_fragment,
|
||||
'course_expiration_fragment': course_expiration_fragment,
|
||||
'next_up_banner_fragment': next_up_banner_fragment,
|
||||
'has_visited_course': has_visited_course,
|
||||
'resume_course_url': resume_course_url,
|
||||
'course_tools': course_tools,
|
||||
|
||||
27
openedx/features/course_experience/views/next_up_banner.py
Normal file
27
openedx/features/course_experience/views/next_up_banner.py
Normal file
@@ -0,0 +1,27 @@
|
||||
"""
|
||||
View logic for handling course messages.
|
||||
"""
|
||||
|
||||
from django.template.loader import render_to_string
|
||||
from web_fragments.fragment import Fragment
|
||||
|
||||
from openedx.core.djangoapps.plugin_api.views import EdxFragmentView
|
||||
|
||||
|
||||
class NextUpBannerFragmentView(EdxFragmentView):
|
||||
"""
|
||||
A fragment that displays an up next banner with a call to action to resume the course.
|
||||
"""
|
||||
|
||||
# pylint: disable=arguments-differ
|
||||
def render_to_fragment(self, assignment_title, resume_course_url, assignment_duration='10 mins'):
|
||||
"""
|
||||
Renders an up next banner fragment with the provided assignment title, duration, and a link to the URL.
|
||||
"""
|
||||
context = {
|
||||
'assignment_title': assignment_title,
|
||||
'resume_course_url': resume_course_url,
|
||||
'assignment_duration': assignment_duration,
|
||||
}
|
||||
html = render_to_string('course_experience/next-up-banner-fragment.html', context)
|
||||
return Fragment(html)
|
||||
Reference in New Issue
Block a user