diff --git a/common/static/sass/edx-pattern-library-shims/base/_variables.scss b/common/static/sass/edx-pattern-library-shims/base/_variables.scss index 7222357753..915d1129a3 100644 --- a/common/static/sass/edx-pattern-library-shims/base/_variables.scss +++ b/common/static/sass/edx-pattern-library-shims/base/_variables.scss @@ -191,7 +191,6 @@ $btn-border-radius: $component-border-radius !default; $btn-large-padding-vertical: spacing-vertical(small); $btn-large-padding-horizontal: spacing-horizontal(mid-large); - $btn-base-padding-vertical: spacing-vertical(x-small); $btn-base-padding-horizontal: spacing-horizontal(base); $btn-base-font-size: font-size(base); diff --git a/lms/djangoapps/courseware/tests/test_date_summary.py b/lms/djangoapps/courseware/tests/test_date_summary.py index edffea818d..2627fef09d 100644 --- a/lms/djangoapps/courseware/tests/test_date_summary.py +++ b/lms/djangoapps/courseware/tests/test_date_summary.py @@ -45,6 +45,7 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase): days_till_upgrade_deadline=4, enroll_user=True, enrollment_mode=CourseMode.VERIFIED, + user_enrollment_mode=None, course_min_price=100, days_till_verification_deadline=14, verification_status=None, @@ -72,8 +73,11 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase): ) if enroll_user: - enrollment_mode = enrollment_mode or CourseMode.DEFAULT_MODE_SLUG - CourseEnrollmentFactory.create(course_id=self.course.id, user=self.user, mode=enrollment_mode) + if user_enrollment_mode: + CourseEnrollmentFactory.create(course_id=self.course.id, user=self.user, mode=user_enrollment_mode) + else: + enrollment_mode = enrollment_mode or CourseMode.DEFAULT_MODE_SLUG + CourseEnrollmentFactory.create(course_id=self.course.id, user=self.user, mode=enrollment_mode) if days_till_verification_deadline is not None: VerificationDeadline.objects.create( @@ -274,18 +278,64 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase): ) self.assertEqual(block.title, 'Course End') - ## Tests Verified Upgrade Deadline Date Block + # Tests Verified Upgrade Deadline Date Block + + def check_upgrade_banner(self, banner_expected=True, include_url_parameter=True): + """ + Helper method to check for the presence of the Upgrade Banner + """ + url = reverse('info', args=[self.course.id.to_deprecated_string()]) + if include_url_parameter: + url += '?upgrade=true' + resp = self.client.get(url) + expected_banner_text = "Give yourself an additional incentive to complete" + if banner_expected: + self.assertIn(expected_banner_text, resp.content) + else: + self.assertNotIn(expected_banner_text, resp.content) + @freeze_time('2015-01-02') def test_verified_upgrade_deadline_date(self): - self.setup_course_and_user(days_till_upgrade_deadline=1) + self.setup_course_and_user(days_till_upgrade_deadline=1, user_enrollment_mode=CourseMode.AUDIT) + self.client.login(username='mrrobot', password='test') block = VerifiedUpgradeDeadlineDate(self.course, self.user) self.assertEqual(block.date, datetime.now(utc) + timedelta(days=1)) + self.assertTrue(block.is_enabled) self.assertEqual(block.link, reverse('verify_student_upgrade_and_verify', args=(self.course.id,))) + self.check_upgrade_banner() def test_without_upgrade_deadline(self): self.setup_course_and_user(enrollment_mode=None) + self.client.login(username='mrrobot', password='test') block = VerifiedUpgradeDeadlineDate(self.course, self.user) + self.assertFalse(block.is_enabled) self.assertIsNone(block.date) + self.check_upgrade_banner(banner_expected=False) + + @freeze_time('2015-01-02') + def test_verified_upgrade_banner_not_present_past_deadline(self): + self.setup_course_and_user(days_till_upgrade_deadline=-1, user_enrollment_mode=CourseMode.AUDIT) + self.client.login(username='mrrobot', password='test') + block = VerifiedUpgradeDeadlineDate(self.course, self.user) + self.assertFalse(block.is_enabled) + self.check_upgrade_banner(banner_expected=False) + + @freeze_time('2015-01-02') + def test_verified_upgrade_banner_cookie(self): + self.setup_course_and_user(days_till_upgrade_deadline=1, user_enrollment_mode=CourseMode.AUDIT) + self.client.login(username='mrrobot', password='test') + + # No URL parameter or cookie present, notification should not be shown. + self.check_upgrade_banner(include_url_parameter=False, banner_expected=False) + + # Now pass URL parameter-- notification should be shown. + self.check_upgrade_banner(include_url_parameter=True) + + # A cookie should be set in the previous call, so it is no longer necessary to pass + # the URL parameter in order to see the notification. + self.check_upgrade_banner(include_url_parameter=False) + + # Unfortunately (according to django doc), it is not possible to test expiration of the cookie. def test_ecommerce_checkout_redirect(self): """Verify the block link redirects to ecommerce checkout if it's enabled.""" diff --git a/lms/djangoapps/courseware/views/views.py b/lms/djangoapps/courseware/views/views.py index 5e235cac68..e2d448f462 100644 --- a/lms/djangoapps/courseware/views/views.py +++ b/lms/djangoapps/courseware/views/views.py @@ -65,6 +65,7 @@ from courseware.courses import ( sort_by_start_date, UserNotEnrolled ) +from courseware.date_summary import VerifiedUpgradeDeadlineDate from courseware.masquerade import setup_masquerade from courseware.model_data import FieldDataCache from courseware.models import StudentModule, BaseStudentModuleHistory @@ -343,6 +344,22 @@ def course_info(request, course_id): if settings.FEATURES.get('ENABLE_MKTG_SITE'): url_to_enroll = marketing_link('COURSES') + store_upgrade_cookie = False + upgrade_cookie_name = 'show_upgrade_notification' + upgrade_link = None + if request.user.is_authenticated(): + show_upgrade_notification = False + if request.GET.get('upgrade', 'false') == 'true': + store_upgrade_cookie = True + show_upgrade_notification = True + elif upgrade_cookie_name in request.COOKIES and bool(request.COOKIES[upgrade_cookie_name]): + show_upgrade_notification = True + + if show_upgrade_notification: + upgrade_data = VerifiedUpgradeDeadlineDate(course, user) + if upgrade_data.is_enabled: + upgrade_link = upgrade_data.link + context = { 'request': request, 'masquerade_user': user, @@ -354,6 +371,7 @@ def course_info(request, course_id): 'studio_url': studio_url, 'show_enroll_banner': show_enroll_banner, 'url_to_enroll': url_to_enroll, + 'upgrade_link': upgrade_link } # Get the URL of the user's last position in order to display the 'where you were last' message @@ -371,7 +389,17 @@ def course_info(request, course_id): if CourseEnrollment.is_enrolled(request.user, course.id): inject_coursetalk_keys_into_context(context, course_key) - return render_to_response('courseware/info.html', context) + response = render_to_response('courseware/info.html', context) + if store_upgrade_cookie: + response.set_cookie( + upgrade_cookie_name, + True, + max_age=10 * 24 * 60 * 60, # set for 10 days + domain=settings.SESSION_COOKIE_DOMAIN, + httponly=True # no use case for accessing from JavaScript + ) + + return response def get_last_accessed_courseware(course, request, user): diff --git a/lms/static/images/edx-verified-mini-cert.png b/lms/static/images/edx-verified-mini-cert.png new file mode 100644 index 0000000000..35b9b9f1dc Binary files /dev/null and b/lms/static/images/edx-verified-mini-cert.png differ diff --git a/lms/static/js/courseware/course_home_events.js b/lms/static/js/courseware/course_home_events.js index 28f49d06d6..9b9da6ca73 100644 --- a/lms/static/js/courseware/course_home_events.js +++ b/lms/static/js/courseware/course_home_events.js @@ -9,7 +9,13 @@ }); }); $('.date-summary-verified-upgrade-deadline .date-summary-link').on('click', function() { - Logger.log('edx.course.home.upgrade_verified.clicked', {}); + Logger.log('edx.course.home.upgrade_verified.clicked', {location: 'sidebar'}); + }); + $('.upgrade-banner-button').on('click', function() { + Logger.log('edx.course.home.upgrade_verified.clicked', {location: 'notification'}); + }); + $('.view-verified-info').on('click', function() { + Logger.log('edx.course.home.learn_about_verified.clicked', {location: 'notification'}); }); }; }); diff --git a/lms/static/js/fixtures/courseware/course_home_events.html b/lms/static/js/fixtures/courseware/course_home_events.html index e115db5f41..a86ab48b53 100644 --- a/lms/static/js/fixtures/courseware/course_home_events.html +++ b/lms/static/js/fixtures/courseware/course_home_events.html @@ -1,3 +1,21 @@ +
+