Commit d58f2ac2 by Andy Armstrong Committed by GitHub

Merge pull request #15580 from edx/andya/course-home-messaging

Show page banner for anonymous and unenrolled users
parents 4370142a 3e786ec6
......@@ -17,12 +17,10 @@ from certificates.models import CertificateStatuses
from commerce.utils import EcommerceService
from course_modes.models import CourseMode
from courseware.access import has_access, has_ccx_coach_role
from courseware.access_response import StartDateError
from courseware.access_utils import in_preview_mode, check_course_open_for_learner
from courseware.access_utils import check_course_open_for_learner
from courseware.courses import (
can_self_enroll_in_course,
get_course,
get_course_by_id,
get_course_overview_with_access,
get_course_with_access,
get_courses,
......@@ -49,6 +47,7 @@ from django.db.models import Q
from django.http import Http404, HttpResponse, HttpResponseBadRequest, HttpResponseForbidden, QueryDict
from django.shortcuts import redirect
from django.utils.decorators import method_decorator
from django.utils.http import urlquote_plus
from django.utils.text import slugify
from django.utils.timezone import UTC
from django.utils.translation import ugettext as _
......@@ -83,17 +82,17 @@ from openedx.core.djangoapps.plugin_api.views import EdxFragmentView
from openedx.core.djangoapps.programs.utils import ProgramMarketingDataExtender
from openedx.core.djangoapps.self_paced.models import SelfPacedConfiguration
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
from openedx.core.djangoapps.util.user_messages import register_warning_message
from openedx.core.djangolib.markup import HTML, Text
from openedx.features.course_experience import UNIFIED_COURSE_TAB_FLAG, course_home_url_name
from openedx.features.course_experience.course_tools import CourseToolsPluginManager
from openedx.features.course_experience.views.course_dates import CourseDatesFragmentView
from openedx.features.enterprise_support.api import data_sharing_consent_required
from pytz import utc
from rest_framework import status
from shoppingcart.utils import is_shopping_cart_enabled
from student.models import CourseEnrollment, UserTestGroup
from survey.utils import must_answer_survey
from util.cache import cache, cache_if_anonymous
from util.date_utils import strftime_localized
from util.db import outer_atomic
from util.milestones_helpers import get_prerequisite_courses_display
from util.views import _record_feedback_in_zendesk, ensure_valid_course_key, ensure_valid_usage_key
......@@ -269,7 +268,7 @@ def course_info(request, course_id):
masquerade, user = setup_masquerade(request, course_key, staff_access, reset_masquerade_data=True)
# LEARNER-612: CCX redirect handled by new Course Home (DONE)
# TODO: LEARNER-1697: Transition banner messages to new Course Home.
# LEARNER-1697: Transition banner messages to new Course Home (DONE)
# if user is not enrolled in a course then app will show enroll/get register link inside course info page.
user_is_enrolled = CourseEnrollment.is_enrolled(user, course.id)
show_enroll_banner = request.user.is_authenticated() and not user_is_enrolled
......@@ -296,13 +295,6 @@ def course_info(request, course_id):
if course.bypass_home and is_from_dashboard:
return redirect(reverse('courseware', args=[course_id]))
# TODO: LEARNER-1697: Transition handling of enroll links in new Course Home.
# link to where the student should go to enroll in the course:
# about page if there is not marketing site, SITE_NAME if there is
url_to_enroll = reverse(course_about, args=[course_id])
if settings.FEATURES.get('ENABLE_MKTG_SITE'):
url_to_enroll = marketing_link('COURSES')
# Construct the dates fragment
dates_fragment = None
......@@ -334,7 +326,7 @@ def course_info(request, course_id):
'show_enroll_banner': show_enroll_banner,
'user_is_enrolled': user_is_enrolled,
'dates_fragment': dates_fragment,
'url_to_enroll': url_to_enroll,
'url_to_enroll': CourseTabView.url_to_enroll(course_key),
'course_tools': course_tools,
# TODO: (Experimental Code). See https://openedx.atlassian.net/wiki/display/RET/2.+In-course+Verification+Prompts
......@@ -391,6 +383,10 @@ class StaticCourseTabView(EdxFragmentView):
tab = CourseTabList.get_tab_by_slug(course.tabs, tab_slug)
if tab is None:
raise Http404
# Show warnings if the user has limited access
CourseTabView.register_user_access_warning_messages(request, course_key)
return super(StaticCourseTabView, self).get(request, course=course, tab=tab, **kwargs)
def render_to_fragment(self, request, course=None, tab=None, **kwargs):
......@@ -431,6 +427,9 @@ class CourseTabView(EdxFragmentView):
# Verify that the user has access to the course
check_access_to_course(request, course)
# Show warnings if the user has limited access
self.register_user_access_warning_messages(request, course_key)
# Render the page
tab = CourseTabList.get_tab_by_type(course.tabs, tab_type)
page_context = self.create_page_context(request, course=course, tab=tab, **kwargs)
......@@ -440,6 +439,48 @@ class CourseTabView(EdxFragmentView):
return CourseTabView.handle_exceptions(request, course, exception)
@staticmethod
def url_to_enroll(course_key):
"""
Returns the URL to use to enroll in the specified course.
"""
url_to_enroll = reverse('about_course', args=[unicode(course_key)])
if settings.FEATURES.get('ENABLE_MKTG_SITE'):
url_to_enroll = marketing_link('COURSES')
return url_to_enroll
@staticmethod
def register_user_access_warning_messages(request, course_key):
"""
Register messages to be shown to the user if they have limited access.
"""
is_enrolled = CourseEnrollment.is_enrolled(request.user, course_key)
is_staff = has_access(request.user, 'staff', course_key)
if request.user.is_anonymous():
register_warning_message(
request,
Text(_("To see course content, {sign_in_link} or {register_link}.")).format(
sign_in_link=HTML('<a href="/login?next={current_url}">{sign_in_label}</a>').format(
sign_in_label=_("sign in"),
current_url=urlquote_plus(request.path),
),
register_link=HTML('<a href="/register?next={current_url}">{register_label}</a>').format(
register_label=_("register"),
current_url=urlquote_plus(request.path),
),
)
)
elif not is_enrolled and not is_staff:
register_warning_message(
request,
Text(_('You must be enrolled in the course to see course content. {enroll_link}.')).format(
enroll_link=HTML('<a href="{url_to_enroll}">{enroll_link_label}</a>').format(
url_to_enroll=CourseTabView.url_to_enroll(course_key),
enroll_link_label=_("Enroll now"),
)
)
)
@staticmethod
def handle_exceptions(request, course, exception):
"""
Handle exceptions raised when rendering a view.
......
......@@ -51,6 +51,13 @@ $full-width-banner-margin: 20px;
.user-messages {
padding-top: $baseline;
// Hack: force override the global important rule
// that courseware links don't have an underline.
a:hover {
color: $link-color;
text-decoration: underline !important;
}
}
.alert {
......
......@@ -10,10 +10,14 @@ from openedx.core.djangolib.markup import HTML
from openedx.core.djangoapps.util.user_messages import user_messages
%>
% if user_messages:
<%
banner_messages = list(user_messages(request))
%>
% if banner_messages:
<div class="page-banner">
<div class="user-messages">
% for message in user_messages(request):
% for message in banner_messages:
<div class="alert ${message.css_class}" role="alert">
<span class="icon icon-alert fa ${message.icon_class}" aria-hidden="true"></span>
${HTML(message.message_html)}
......
......@@ -186,12 +186,13 @@ class TestCourseHomePageAccess(CourseHomePageTestCase):
@override_waffle_flag(UNIFIED_COURSE_TAB_FLAG, active=True)
@override_waffle_flag(SHOW_REVIEWS_TOOL_FLAG, active=True)
@ddt.data(
CourseUserType.ANONYMOUS,
CourseUserType.ENROLLED,
CourseUserType.UNENROLLED,
CourseUserType.UNENROLLED_STAFF,
[CourseUserType.ANONYMOUS, 'To see course content'],
[CourseUserType.ENROLLED, None],
[CourseUserType.UNENROLLED, 'You must be enrolled in the course to see course content.'],
[CourseUserType.UNENROLLED_STAFF, None],
)
def test_home_page(self, user_type):
@ddt.unpack
def test_home_page(self, user_type, expected_message):
self.user = self.create_user_for_course(self.course, user_type)
# Render the course home page
......@@ -212,15 +213,21 @@ class TestCourseHomePageAccess(CourseHomePageTestCase):
self.assertContains(response, 'Learn About Verified Certificate', count=expected_count)
self.assertContains(response, TEST_WELCOME_MESSAGE, count=expected_count)
# Verify that the expected message is shown to the user
self.assertContains(response, '<div class="user-messages">', count=1 if expected_message else 0)
if expected_message:
self.assertContains(response, expected_message)
@override_waffle_flag(UNIFIED_COURSE_TAB_FLAG, active=False)
@override_waffle_flag(SHOW_REVIEWS_TOOL_FLAG, active=True)
@ddt.data(
CourseUserType.ANONYMOUS,
CourseUserType.ENROLLED,
CourseUserType.UNENROLLED,
CourseUserType.UNENROLLED_STAFF,
[CourseUserType.ANONYMOUS, 'To see course content'],
[CourseUserType.ENROLLED, None],
[CourseUserType.UNENROLLED, 'You must be enrolled in the course to see course content.'],
[CourseUserType.UNENROLLED_STAFF, None],
)
def test_home_page_not_unified(self, user_type):
@ddt.unpack
def test_home_page_not_unified(self, user_type, expected_message):
"""
Verifies the course home tab when not unified.
"""
......@@ -246,6 +253,11 @@ class TestCourseHomePageAccess(CourseHomePageTestCase):
self.assertContains(response, 'Start Course', count=expected_count)
self.assertContains(response, 'Learn About Verified Certificate', count=expected_count)
# Verify that the expected message is shown to the user
self.assertContains(response, '<div class="user-messages">', count=1 if expected_message else 0)
if expected_message:
self.assertContains(response, expected_message)
def test_sign_in_button(self):
"""
Verify that the sign in button will return to this page.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment