diff --git a/common/djangoapps/student/tests/tests.py b/common/djangoapps/student/tests/tests.py
index 1a8c105c01..c28a54afe8 100644
--- a/common/djangoapps/student/tests/tests.py
+++ b/common/djangoapps/student/tests/tests.py
@@ -12,10 +12,11 @@ import pytz
from django.conf import settings
from django.test import TestCase
from django.test.utils import override_settings
-from django.test.client import RequestFactory
+from django.test.client import RequestFactory, Client
from django.contrib.auth.models import User, AnonymousUser
-from django.core.urlresolvers import reverse
+from django.core.urlresolvers import reverse, NoReverseMatch
from django.http import HttpResponse
+from unittest.case import SkipTest
from xmodule.modulestore.tests.factories import CourseFactory
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
@@ -146,12 +147,58 @@ class DashboardTest(TestCase):
def setUp(self):
self.course = CourseFactory.create(org=self.COURSE_ORG, display_name=self.COURSE_NAME, number=self.COURSE_SLUG)
self.assertIsNotNone(self.course)
- self.user = UserFactory.create(username="jack", email="jack@fake.edx.org")
+ self.user = UserFactory.create(username="jack", email="jack@fake.edx.org", password='test')
CourseModeFactory.create(
course_id=self.course.id,
mode_slug='honor',
mode_display_name='Honor Code',
)
+ self.client = Client()
+
+ def check_verification_status_on(self, mode, value):
+ """
+ Check that the css class and the status message are in the dashboard html.
+ """
+ CourseEnrollment.enroll(self.user, self.course.location.course_id, mode=mode)
+ try:
+ response = self.client.get(reverse('dashboard'))
+ except NoReverseMatch:
+ raise SkipTest("Skip this test if url cannot be found (ie running from CMS tests)")
+ self.assertContains(response, "class=\"course {0}\"".format(mode))
+ self.assertContains(response, value)
+
+ @patch.dict("django.conf.settings.FEATURES", {'ENABLE_VERIFIED_CERTIFICATES': True})
+ def test_verification_status_visible(self):
+ """
+ Test that the certificate verification status for courses is visible on the dashboard.
+ """
+ self.client.login(username="jack", password="test")
+ self.check_verification_status_on('verified', 'You\'re enrolled as a verified student')
+ self.check_verification_status_on('honor', 'You\'re enrolled as an honor code student')
+ self.check_verification_status_on('audit', 'You\'re auditing this course')
+
+ def check_verification_status_off(self, mode, value):
+ """
+ Check that the css class and the status message are not in the dashboard html.
+ """
+ CourseEnrollment.enroll(self.user, self.course.location.course_id, mode=mode)
+ try:
+ response = self.client.get(reverse('dashboard'))
+ except NoReverseMatch:
+ raise SkipTest("Skip this test if url cannot be found (ie running from CMS tests)")
+ self.assertNotContains(response, "class=\"course {0}\"".format(mode))
+ self.assertNotContains(response, value)
+
+ @patch.dict("django.conf.settings.FEATURES", {'ENABLE_VERIFIED_CERTIFICATES': False})
+ def test_verification_status_invisible(self):
+ """
+ Test that the certificate verification status for courses is not visible on the dashboard
+ if the verified certificates setting is off.
+ """
+ self.client.login(username="jack", password="test")
+ self.check_verification_status_off('verified', 'You\'re enrolled as a verified student')
+ self.check_verification_status_off('honor', 'You\'re enrolled as an honor code student')
+ self.check_verification_status_off('audit', 'You\'re auditing this course')
def test_course_mode_info(self):
verified_mode = CourseModeFactory.create(
diff --git a/lms/djangoapps/courseware/features/certificates.py b/lms/djangoapps/courseware/features/certificates.py
index 91e4f394c5..06d77e8008 100644
--- a/lms/djangoapps/courseware/features/certificates.py
+++ b/lms/djangoapps/courseware/features/certificates.py
@@ -6,6 +6,7 @@ from lettuce.django import django_url
from course_modes.models import CourseMode
from nose.tools import assert_equal
+
UPSELL_LINK_CSS = '.message-upsell a.action-upgrade[href*="edx/999/Certificates"]'
def create_cert_course():
diff --git a/lms/envs/common.py b/lms/envs/common.py
index c61db979d4..6287bfb5aa 100644
--- a/lms/envs/common.py
+++ b/lms/envs/common.py
@@ -172,6 +172,9 @@ FEATURES = {
# Enable instructor dash beta version link
'ENABLE_INSTRUCTOR_BETA_DASHBOARD': True,
+ # Toggle to enable certificates of courses on dashboard
+ 'ENABLE_VERIFIED_CERTIFICATES': False,
+
# Allow use of the hint managment instructor view.
'ENABLE_HINTER_INSTRUCTOR_VIEW': False,
diff --git a/lms/envs/test.py b/lms/envs/test.py
index b20a23c470..edaa4c7c45 100644
--- a/lms/envs/test.py
+++ b/lms/envs/test.py
@@ -37,6 +37,8 @@ FEATURES['ENABLE_INSTRUCTOR_BETA_DASHBOARD'] = True
FEATURES['ENABLE_SHOPPING_CART'] = True
+FEATURES['ENABLE_VERIFIED_CERTIFICATES'] = True
+
# Enable this feature for course staff grade downloads, to enable acceptance tests
FEATURES['ENABLE_S3_GRADE_DOWNLOADS'] = True
FEATURES['ALLOW_COURSE_STAFF_GRADE_DOWNLOADS'] = True
diff --git a/lms/static/sass/base/_variables.scss b/lms/static/sass/base/_variables.scss
index cb96c3f92f..21998b995e 100644
--- a/lms/static/sass/base/_variables.scss
+++ b/lms/static/sass/base/_variables.scss
@@ -227,6 +227,15 @@ $verified-color-lvl3: $m-green-l2;
$verified-color-lvl4: $m-green-l3;
$verified-color-lvl5: $m-green-l4;
+// STATE: honor code
+$honorcode-color-lvl1: rgb(50, 165, 217);
+$honorcode-color-lvl2: tint($honorcode-color-lvl1, 33%);
+
+// STATE: audit
+$audit-color-lvl1: $light-gray;
+$audit-color-lvl2: tint($audit-color-lvl1, 33%);
+
+
// ====================
// ACTIONS: general
@@ -307,6 +316,7 @@ $dashboard-profile-header-image: linear-gradient(-90deg, rgb(255,255,255), rgb(2
$dashboard-profile-header-color: transparent;
$dashboard-profile-color: rgb(252,252,252);
$dot-color: $light-gray;
+$dashboard-course-cover-border: $light-gray;
// MISC: course assets
$content-wrapper-bg: $white;
@@ -380,4 +390,3 @@ $f-monospace: 'Bitstream Vera Sans Mono', Consolas, Courier, monospace;
// SPLINT: colors
$msg-bg: $action-primary-bg;
-
diff --git a/lms/static/sass/elements/_typography.scss b/lms/static/sass/elements/_typography.scss
index 2d677700c6..8170ca4b88 100644
--- a/lms/static/sass/elements/_typography.scss
+++ b/lms/static/sass/elements/_typography.scss
@@ -277,7 +277,7 @@
}
%copy-badge {
- @extend %t-title8;
+ @extend %t-title9;
@extend %t-weight3;
border-radius: ($baseline/5);
padding: ($baseline/2) $baseline;
diff --git a/lms/static/sass/multicourse/_dashboard.scss b/lms/static/sass/multicourse/_dashboard.scss
index 8c987c9630..6991fba25b 100644
--- a/lms/static/sass/multicourse/_dashboard.scss
+++ b/lms/static/sass/multicourse/_dashboard.scss
@@ -374,15 +374,19 @@
.cover {
@include box-sizing(border-box);
+ @include transition(all 0.15s linear 0s);
+ overflow: hidden;
+ position: relative;
float: left;
height: 100%;
max-height: 100%;
- margin: 0px;
- overflow: hidden;
- position: relative;
- @include transition(all 0.15s linear 0s);
width: 200px;
height: 120px;
+ margin: 0px;
+ border-radius: ($baseline/10);
+ border: 1px solid $dashboard-course-cover-border;
+ border-bottom: 4px solid $dashboard-course-cover-border;
+ padding: ($baseline/10);
img {
width: 100%;
@@ -491,28 +495,43 @@
}
}
+ // "enrolled as" status
+ .sts-enrollment {
+ position: absolute;
+ top: 105px;
+ left: 0;
+ display: inline-block;
+ text-align: center;
+ width: 200px;
+
+ .label {
+ @extend %text-sr;
+ }
+
+ .sts-enrollment-value {
+ @extend %ui-depth1;
+ @extend %copy-badge;
+ border-radius: 0;
+ padding: ($baseline/4) ($baseline/2) ($baseline/4) ($baseline/2);
+ }
+ }
+
// ====================
- // STATE: course mode - verified
+ // CASE: "enrolled as" status - verified
&.verified {
- @extend %ui-depth2;
- position: relative;
+ // changes to cover
.cover {
- border-radius: ($baseline/10);
- border: 1px solid $verified-color-lvl3;
- border-bottom: 4px solid $verified-color-lvl3;
+ border-color: $verified-color-lvl3;
padding: ($baseline/10);
}
// course enrollment status message
.sts-enrollment {
- display: inline-block;
position: absolute;
- top: 105px;
left: 55px;
- bottom: ($baseline/2);
- text-align: center;
+ width: auto;
.label {
@extend %text-sr;
@@ -526,16 +545,46 @@
top: -10px;
}
+ // status message
.sts-enrollment-value {
- @extend %ui-depth1;
- @extend %copy-badge;
- border-radius: 0;
padding: ($baseline/4) ($baseline/2) ($baseline/4) $baseline;
background: $verified-color-lvl3;
- color: $white;
+ color: tint($verified-color-lvl1, 85%);
}
}
}
+
+ // CASE: "enrolled as" status - honor code
+ &.honor {
+
+ // changes to cover
+ .cover {
+ border-color: $honorcode-color-lvl2;
+ padding: ($baseline/10);
+ }
+
+ // status message
+ .sts-enrollment-value {
+ background: $honorcode-color-lvl1;
+ color: tint($honorcode-color-lvl1, 85%);
+ }
+ }
+
+ // CASE: "enrolled as" status - auditing
+ &.audit {
+
+ // changes to cover
+ .cover {
+ border-color: $audit-color-lvl2;
+ padding: ($baseline/10);
+ }
+
+ // status message
+ .sts-enrollment-value {
+ background: $audit-color-lvl1;
+ color: shade($audit-color-lvl1, 33%);
+ }
+ }
}
// ====================
diff --git a/lms/templates/dashboard/_dashboard_course_listing.html b/lms/templates/dashboard/_dashboard_course_listing.html
index f415830668..229fed81d4 100644
--- a/lms/templates/dashboard/_dashboard_course_listing.html
+++ b/lms/templates/dashboard/_dashboard_course_listing.html
@@ -11,7 +11,7 @@
cert_name_short = course.cert_name_short
if cert_name_short == "":
cert_name_short = settings.CERT_NAME_SHORT
-
+
cert_name_long = course.cert_name_long
if cert_name_long == "":
cert_name_long = settings.CERT_NAME_LONG
@@ -21,7 +21,11 @@
<%namespace name='static' file='../static_content.html'/>
-
+ % if settings.FEATURES.get('ENABLE_VERIFIED_CERTIFICATES'):
+
+ % else:
+
+ %endif
<%
course_target = reverse('info', args=[course.id])
%>
@@ -35,13 +39,24 @@
% endif
-
- % if enrollment.mode == "verified":
-
- ${_("Enrolled as: ")}
-
- ${_("ID Verified")}
-
+ % if settings.FEATURES.get('ENABLE_VERIFIED_CERTIFICATES'):
+ % if enrollment.mode == "verified":
+
+ ${_("Enrolled as: ")}
+
+ ${_("Verified")}
+
+ % elif enrollment.mode == "honor":
+
+ ${_("Enrolled as: ")}
+ ${_("Honor Code")}
+
+ % elif enrollment.mode == "audit":
+
+ ${_("Enrolled as: ")}
+ ${_("Auditing")}
+
+ % endif
% endif