Commit 7dfe12a1 by Andy Armstrong

Show course home messages for important course dates

LEARNER-2073
parent 1aff33dc
......@@ -121,3 +121,32 @@
color: $btn-brand-disabled-color;
}
}
// ----------------------------
// #UPGRADE
// ----------------------------
.btn-upgrade {
@extend %btn-shims;
border-color: $btn-upgrade-border-color;
background: $btn-upgrade-background;
color: $btn-upgrade-color;
// STATE: hover and focus
&:hover,
&.is-hovered,
&:focus,
&.is-focused {
border-color: $btn-upgrade-focus-border-color;
background-color: $btn-upgrade-focus-background;
color: $btn-upgrade-focus-color;
}
// STATE: is disabled
&:disabled,
&.is-disabled {
border-color: $btn-disabled-border-color;
background: $btn-brand-disabled-background;
color: $btn-upgrade-color;
}
}
......@@ -143,9 +143,8 @@ $error-color: rgb(203, 7, 18) !default;
$success-color: rgb(0, 155, 0) !default;
$warning-color: rgb(255, 192, 31) !default;
$warning-color-accent: rgb(255, 252, 221) !default;
$general-color: $uxpl-blue-base !default;;
$general-color-accent: $uxpl-blue-base !default
$general-color: $uxpl-blue-base !default;
$general-color-accent: $uxpl-blue-base !default;
// CAPA correctness color to be consistent with Alert styles above
$correct: $success-color !default;
......@@ -181,6 +180,16 @@ $btn-brand-active-background: $uxpl-blue-base !default;
$btn-brand-disabled-background: #f2f3f3 !default;
$btn-brand-disabled-color: #676666 !default;
// Upgrade button
$btn-upgrade-border-color: $uxpl-green-base !default;
$btn-upgrade-background: $uxpl-green-base !default;
$btn-upgrade-color: #fcfcfc !default;
$btn-upgrade-focus-color: $btn-upgrade-color !default;
$btn-upgrade-focus-border-color: rgb(0, 155, 0) !default;
$btn-upgrade-focus-background: rgb(0, 155, 0) !default;
$btn-upgrade-active-border-color: $uxpl-green-base !default;
$btn-upgrade-active-background: $uxpl-green-base !default;
// ----------------------------
// #SETTINGS
// ----------------------------
......
......@@ -4,6 +4,8 @@ from urlparse import urljoin
import waffle
from django.conf import settings
from django.core.urlresolvers import reverse
from student.models import CourseEnrollment
from commerce.models import CommerceConfiguration
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
......@@ -93,3 +95,16 @@ class EcommerceService(object):
checkout_page_path=self.get_absolute_ecommerce_url(self.config.MULTIPLE_ITEMS_BASKET_PAGE_URL),
skus=urlencode({'sku': skus}, doseq=True),
)
def upgrade_url(self, user, course_key):
"""
Returns the URL for the user to upgrade, or None if not applicable.
"""
enrollment = CourseEnrollment.get_enrollment(user, course_key)
verified_mode = enrollment.verified_mode if enrollment else None
if verified_mode:
if self.is_enabled(user):
return self.get_checkout_page_url(verified_mode.sku)
else:
return reverse('verify_student_upgrade_and_verify', args=(course_key,))
return None
......@@ -213,8 +213,8 @@ class IndexQueryTestCase(ModuleStoreTestCase):
NUM_PROBLEMS = 20
@ddt.data(
(ModuleStoreEnum.Type.mongo, 10, 145),
(ModuleStoreEnum.Type.split, 4, 145),
(ModuleStoreEnum.Type.mongo, 10, 147),
(ModuleStoreEnum.Type.split, 4, 147),
)
@ddt.unpack
def test_index_query_counts(self, store_type, expected_mongo_query_count, expected_mysql_query_count):
......
......@@ -431,6 +431,9 @@ XQUEUE_WAITTIME_BETWEEN_REQUESTS = 5 # seconds
RETRY_ACTIVATION_EMAIL_MAX_ATTEMPTS = 5
RETRY_ACTIVATION_EMAIL_TIMEOUT = 0.5
# Deadline message configurations
COURSE_MESSAGE_ALERT_DURATION_IN_DAYS = 14
############################# SET PATH INFORMATION #############################
PROJECT_ROOT = path(__file__).abspath().dirname().dirname() # /edx-platform/lms
REPO_ROOT = PROJECT_ROOT.dirname()
......@@ -2589,6 +2592,7 @@ MAX_FAILED_LOGIN_ATTEMPTS_LOCKOUT_PERIOD_SECS = 15 * 60
TIME_ZONE_DISPLAYED_FOR_DEADLINES = 'UTC'
########################## VIDEO IMAGE STORAGE ############################
VIDEO_IMAGE_SETTINGS = dict(
......
......@@ -7,3 +7,7 @@
@import 'base/variables';
@import 'base/mixins';
@import 'base/theme';
// Pattern Library shims
@import 'edx-pattern-library-shims/base/variables';
@import 'edx-pattern-library-shims/buttons';
......@@ -21,6 +21,7 @@
// Elements
@import 'notifications';
@import 'elements/controls';
@import 'elements-v2/buttons';
@import 'elements-v2/pagination';
// Features
......
// Upgrade button
$btn-upgrade-border-color: $uxpl-green-base !default;
$btn-upgrade-background: $uxpl-green-base !default;
$btn-upgrade-color: #fcfcfc !default;
$btn-upgrade-focus-color: $btn-upgrade-color !default;
$btn-upgrade-focus-border-color: rgb(0, 155, 0) !default;
$btn-upgrade-focus-background: rgb(0, 155, 0) !default;
$btn-upgrade-active-border-color: $uxpl-green-base !default;
$btn-upgrade-active-background: $uxpl-green-base !default;
//// Notifications
// Upgrade
......@@ -142,31 +132,6 @@ div.info-wrapper {
@include margin(0, 0, 0, auto);
padding: $baseline/2 $baseline;
}
.btn-upgrade {
@extend %btn-shims;
border-color: $btn-upgrade-border-color;
background: $btn-upgrade-background;
color: $btn-upgrade-color;
// STATE: hover and focus
&:hover,
&.is-hovered,
&:focus,
&.is-focused {
border-color: $btn-upgrade-focus-border-color;
background-color: $btn-upgrade-focus-background;
color: $btn-upgrade-focus-color;
}
// STATE: is disabled
&:disabled,
&.is-disabled {
border-color: $btn-disabled-border-color;
background: $btn-brand-disabled-background;
color: $btn-upgrade-color;
}
}
}
}
......
// ----------------------------
// #UPGRADE
// ----------------------------
$upgrade-color: #009b00 !default;
$upgrade-dark-color: #008100 !default;
.btn-upgrade {
@extend %btn;
border-color: $upgrade-color;
background: $upgrade-color;
color: palette(primary, x-back);
text-decoration: none;
// STATE: hover and focus
&:hover,
&.is-hovered,
&:focus,
&.is-focused {
border-color: $upgrade-dark-color;
background: $upgrade-dark-color;
text-decoration: none;
}
// STATE: is pressed or active
&:active,
&.is-pressed,
&.is-active {
border-color: $upgrade-dark-color;
background: $upgrade-dark-color;
text-decoration: none;
}
// STATE: is disabled
&:disabled,
&.is-disabled {
border-color: $btn-disabled-border-color;
background: $btn-disabled-background-color;
color: $btn-disabled-text-color;
text-decoration: none;
}
}
......@@ -16,6 +16,7 @@
.message-content {
@include margin(0, 0, $baseline, $baseline);
position: relative;
border: 1px solid $lms-border-color;
padding: $baseline;
......@@ -60,15 +61,17 @@
.message-header {
font-weight: $font-semibold;
margin-bottom: $baseline/2;
width: calc(100% - 40px)
width: calc(100% - 40px);
}
a {
a:not(.btn) {
font-weight: $font-semibold;
text-decoration: underline;
}
.dismiss {
@include right($baseline/4);
top: $baseline/4;
position: absolute;
cursor: pointer;
......@@ -90,6 +93,7 @@
&.dismissible {
@include right($baseline/4);
position: absolute;
top: $baseline/2;
font-size: font-size(small);
......@@ -103,6 +107,12 @@
}
}
}
.message-actions {
display: flex;
margin-top: $baseline/2;
justify-content: flex-end;
}
}
// Welcome message / Latest Update message
......
......@@ -111,10 +111,6 @@
.action-upgrade-certificate {
position: absolute;
right: $baseline;
background-color: $success-color;
border-color: $success-color;
background-image: none;
box-shadow: none;
@media (max-width: 960px) {
& {
......@@ -142,11 +138,6 @@
top: auto;
}
}
&:hover {
background-color: $success-color-hover;
border-color: $success-color-hover;
}
}
}
}
......
......@@ -70,13 +70,6 @@ $upgrade-message-background-color: $blue-d1;
color: $white;
}
// Upgrade Button
.btn-upgrade {
@extend %btn-primary-green;
background: $uxpl-green-base;
}
// Cert image
.vc-hero {
@include float(right);
......
......@@ -28,8 +28,12 @@ SHOW_REVIEWS_TOOL_FLAG = CourseWaffleFlag(WAFFLE_FLAG_NAMESPACE, 'show_reviews_t
# Waffle flag to enable the setting of course goals.
ENABLE_COURSE_GOALS = CourseWaffleFlag(WAFFLE_FLAG_NAMESPACE, 'enable_course_goals')
# Waffle flag to control the display of the hero
SHOW_UPGRADE_MSG_ON_COURSE_HOME = CourseWaffleFlag(WAFFLE_FLAG_NAMESPACE, 'show_upgrade_msg_on_course_home')
# Waffle flag to control the display of the upgrade deadline message
UPGRADE_DEADLINE_MESSAGE = CourseWaffleFlag(WAFFLE_FLAG_NAMESPACE, 'upgrade_deadline_message')
# Waffle flag to switch between the 'welcome message' and 'latest update' on the course home page.
# Important Admin Note: This is meant to be configured using waffle_utils course
# override only. Either do not create the actual waffle flag, or be sure to unset the
......
......@@ -82,7 +82,7 @@ from openedx.features.course_experience import UNIFIED_COURSE_TAB_FLAG, SHOW_REV
</ul>
<div class="vc-cta vc-fade vc-polite-only">
<a class="btn-upgrade" href="${ upgrade_url }">${_("Upgrade ({price})").format(price='$' + str(upgrade_price))}</a>
<a class="btn-upgrade" href="${ upgrade_url }">${_("Upgrade ({price})").format(price=upgrade_price)}</a>
</div>
</div>
</div>
......
......@@ -55,9 +55,9 @@ from openedx.features.course_experience import DISPLAY_COURSE_SOCK_FLAG
</div>
</div>
<img class="mini-cert" src="${static.url('course_experience/images/verified-cert.png')}"/>
<a href="/verify_student/upgrade/${course_id}/">
<button type="button" class="btn btn-brand stuck-top focusable action-upgrade-certificate">
Upgrade Now (${HTML(course_price)})
<a href="${upgrade_url}">
<button type="button" class="btn btn-upgrade stuck-top focusable action-upgrade-certificate">
Upgrade (${HTML(course_price)})
</button>
</a>
</div>
......
......@@ -173,7 +173,7 @@ class TestCourseHomePage(CourseHomePageTestCase):
course_home_url(self.course)
# Fetch the view and verify the query counts
with self.assertNumQueries(44, table_blacklist=QUERY_COUNT_TABLE_BLACKLIST):
with self.assertNumQueries(45, table_blacklist=QUERY_COUNT_TABLE_BLACKLIST):
with check_mongo_calls(4):
url = course_home_url(self.course)
self.client.get(url)
......@@ -477,11 +477,9 @@ class CourseHomeFragmentViewTests(ModuleStoreTestCase):
response = self.client.get(self.url)
self.assertIn('vc-message', response.content)
url = EcommerceService().get_checkout_page_url(self.verified_mode.sku)
expected = '<a class="btn-upgrade" href="{url}">Upgrade (${price})</a>'.format(
url=url,
price=self.verified_mode.min_price
)
self.assertIn(expected, response.content)
self.assertIn('<a class="btn-upgrade"', response.content)
self.assertIn(url, response.content)
self.assertIn('Upgrade (${price})</a>'.format(price=self.verified_mode.min_price), response.content)
def test_no_upgrade_message_if_logged_out(self):
self.client.logout()
......
......@@ -10,6 +10,7 @@ from django.views.decorators.cache import cache_control
from django.views.decorators.csrf import ensure_csrf_cookie
from commerce.utils import EcommerceService
from course_modes.models import get_cosmetic_verified_display_price
from courseware.access import has_access
from courseware.courses import (
can_self_enroll_in_course,
......@@ -165,15 +166,8 @@ class CourseHomeFragmentView(EdxFragmentView):
# TODO Add switch to control deployment
if SHOW_UPGRADE_MSG_ON_COURSE_HOME.is_enabled(course_key) and enrollment and enrollment.upgrade_deadline:
verified_mode = enrollment.verified_mode
if verified_mode:
upgrade_price = verified_mode.min_price
ecommerce_service = EcommerceService()
if ecommerce_service.is_enabled(request.user):
upgrade_url = ecommerce_service.get_checkout_page_url(verified_mode.sku)
else:
upgrade_url = reverse('verify_student_upgrade_and_verify', args=(course_key,))
upgrade_url = EcommerceService().upgrade_url(request.user, course_key)
upgrade_price = get_cosmetic_verified_display_price(course)
# Render the course home fragment
context = {
......
......@@ -6,10 +6,11 @@ from django.utils.translation import get_language
from opaque_keys.edx.keys import CourseKey
from web_fragments.fragment import Fragment
from student.models import CourseEnrollment
from commerce.utils import EcommerceService
from course_modes.models import CourseMode, get_cosmetic_verified_display_price
from courseware.date_summary import VerifiedUpgradeDeadlineDate
from openedx.core.djangoapps.plugin_api.views import EdxFragmentView
from student.models import CourseEnrollment
class CourseSockFragmentView(EdxFragmentView):
......@@ -44,13 +45,15 @@ class CourseSockFragmentView(EdxFragmentView):
not deadline_has_passed and get_language() == 'en'
)
# Get the price of the course and format correctly
# Get information about the upgrade
course_price = get_cosmetic_verified_display_price(course)
upgrade_url = EcommerceService().upgrade_url(request.user, course_key)
context = {
'show_course_sock': show_course_sock,
'course_price': course_price,
'course_id': course.id
'course_id': course.id,
'upgrade_url': upgrade_url,
}
return context
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