Commit d9611dcd by Matt Drayer

Merge pull request #7382 from edx/mattdrayer/SOL-461

mattdrayer/SOL-461: Student dashboard clean-up
parents 2fea7b4c bd5b0b31
......@@ -40,9 +40,9 @@ class TestStudentDashboardEmailView(ModuleStoreTestCase):
self.url = reverse('dashboard')
# URL for email settings modal
self.email_modal_link = (
'<a href="#email-settings-modal" class="email-settings" rel="leanModal" '
'<a href="#email-settings-modal" class="action action-email-settings" rel="leanModal" '
'data-course-id="{org}/{num}/{name}" data-course-number="{num}" '
'data-optout="False">Email Settings</a>'
'data-dashboard-index="0" data-optout="False">Email Settings</a>'
).format(
org=self.course.org,
num=self.course.number,
......@@ -111,9 +111,9 @@ class TestStudentDashboardEmailViewXMLBacked(ModuleStoreTestCase):
# URL for email settings modal
self.email_modal_link = (
'<a href="#email-settings-modal" class="email-settings" rel="leanModal" '
'<a href="#email-settings-modal" class="action action-email-settings" rel="leanModal" '
'data-course-id="{org}/{num}/{name}" data-course-number="{num}" '
'data-optout="False">Email Settings</a>'
'data-dashboard-index="0" data-optout="False">Email Settings</a>'
).format(
org='edX',
num='toy',
......
......@@ -45,11 +45,9 @@ class DashboardPage(PageObject):
Return list of the names of available courses (e.g. "999 edX Demonstration Course")
"""
def _get_course_name(el):
# The first component in the link text is the course number
_, course_name = el.text.split(' ', 1)
return course_name
return el.text
return self.q(css='section.info > hgroup > h3 > a').map(_get_course_name).results
return self.q(css='h3.course-title > a').map(_get_course_name).results
@property
def full_name(self):
......@@ -64,7 +62,7 @@ class DashboardPage(PageObject):
@property
def username(self):
"""Return the displayed value for the user's username"""
return self.q(css='.user-name').text[0]
return self.q(css='.username-label').text[0]
def get_enrollment_mode(self, course_name):
"""Get the enrollment mode for a given course on the dashboard.
......@@ -113,7 +111,7 @@ class DashboardPage(PageObject):
el = course_listing[0]
# Expand the upsell copy and click the upgrade button
el.find_element_by_css_selector('.message-upsell').click()
el.find_element_by_css_selector('.message-upsell .ui-toggle-expansion').click()
el.find_element_by_css_selector('#upgrade-to-verified').click()
upgrade_page.wait_for_page()
......@@ -176,4 +174,4 @@ class DashboardPage(PageObject):
"""
Verify if pre-requisite course messages are being displayed.
"""
return self.q(css='section.prerequisites > .tip').visible
return self.q(css='li.prerequisites > .tip').visible
......@@ -47,7 +47,14 @@ def i_should_see_that_course_in_my_dashboard(_step, doesnt_appear, course):
@step(u'I unenroll from the course numbered "([^"]*)"')
def i_unenroll_from_that_course(_step, course):
unregister_css = 'section.info a[href*="#unenroll-modal"][data-course-number*="%s"]' % course
more_actions_dropdown_link_selector = '[id*=actions-dropdown-link-0]'
assert world.is_css_present(more_actions_dropdown_link_selector)
world.css_click(more_actions_dropdown_link_selector)
unregister_css = 'li.actions-item a.action-unenroll[data-course-number*="{course_number}"][href*=unenroll-modal]'.format(course_number=course)
assert world.is_css_present(unregister_css)
world.css_click(unregister_css)
button_css = 'section#unenroll-modal input[value="Unenroll"]'
assert world.is_css_present(button_css)
world.css_click(button_css)
......@@ -41,6 +41,7 @@
}
$('.message.is-expandable .wrapper-tip').bind('click', toggleExpandMessage);
$('.action-more').bind('click', toggleCourseActionsDropdown);
// Track clicks of the upgrade button. The `trackLink` method is a helper that makes
// a `track` call whenever a bound link is clicked. Usually the page would change before
......@@ -95,6 +96,29 @@
});
}
function toggleCourseActionsDropdown(event) {
var dashboard_index = $(this).data('dashboard-index');
// Toggle the visibility control for the selected element and set the focus
var dropdown_selector = 'div#actions-dropdown-' + dashboard_index;
var dropdown = $(dropdown_selector);
dropdown.toggleClass('is-visible');
if (dropdown.hasClass('is-visible')) {
dropdown.attr('tabindex', -1);
} else {
dropdown.removeAttr('tabindex');
}
// Inform the ARIA framework that the dropdown has been expanded
var anchor_selector = 'a#actions-dropdown-link-' + dashboard_index;
var anchor = $(anchor_selector);
var aria_expanded_state = (anchor.attr('aria-expanded') === 'true');
anchor.attr('aria-expanded', !aria_expanded_state);
// Suppress the actual click event from the browser
event.preventDefault();
}
$("#failed-verification-button-dismiss").click(function() {
$.ajax({
url: urls.verifyToggleBannerFailedOff,
......@@ -110,7 +134,7 @@
Logger.log('edx.course.enrollment.upgrade.clicked', [user, course], null);
});
$(".email-settings").click(function(event) {
$(".action-email-settings").click(function(event) {
$("#email_settings_course_id").val( $(event.target).data("course-id") );
$("#email_settings_course_number").text( $(event.target).data("course-number") );
if($(event.target).data("optout") === "False") {
......@@ -118,7 +142,7 @@
}
});
$(".unenroll").click(function(event) {
$(".action-unenroll").click(function(event) {
$("#unenroll_course_id").val( $(event.target).data("course-id") );
$("#unenroll_course_number").text( $(event.target).data("course-number") );
});
......@@ -235,8 +259,8 @@
"#dashboard-main"
);
$(".email-settings").each(function(index){
$(this).attr("id", "unenroll-" + index);
$(".action-email-settings").each(function(index){
$(this).attr("id", "email-settings-" + index);
// a bit of a hack, but gets the unique selector for the modal trigger
var trigger = "#" + $(this).attr("id");
accessibleModal(
......@@ -247,8 +271,8 @@
);
});
$(".unenroll").each(function(index){
$(this).attr("id", "email-settings-" + index);
$(".action-unenroll").each(function(index){
$(this).attr("id", "unenroll-" + index);
// a bit of a hack, but gets the unique selector for the modal trigger
var trigger = "#" + $(this).attr("id");
accessibleModal(
......
......@@ -258,13 +258,6 @@ footer .references {
// ====================
// poor cascade made worse by CSS splitting requires us to redefine the dashboard views' visual top padding
.dashboard {
padding-top: 60px;
}
// ====================
// poor definition/scope on ul elements inside .vert-mod element in courseware - override needed for inline discussion editing
.course-content .discussion-post.edit-post-form .topic-menu {
padding-left: 0;
......
......@@ -128,7 +128,7 @@ a:focus {
@include clearfix();
@include box-sizing(border-box);
margin: 0 auto 0;
padding: 0 ($baseline*1.5);
padding: ($baseline*2) 0;
max-width: grid-width(12);
min-width: 760px;
width: flex-grid(12);
......
......@@ -120,3 +120,11 @@
padding: ($baseline/5) ($baseline/2);
color: shade($warning-color, 45%);
}
// extends - content - text overflow by ellipsis
%cont-truncated {
@include box-sizing(border-box);
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
......@@ -133,6 +133,11 @@ $green-u1: desaturate($green,15%);
$green-u2: desaturate($green,30%);
$green-u3: desaturate($green,45%);
// COLORS: social platforms
$twitter-blue: #55ACEE;
$facebook-blue: #3B5998;
$linkedin-blue: #0077B5;
// TODO: both blue and yellow variables differ from CMS rgb value, need to confirm change to CMS variable is ok in current platform uses before switching.
$blue: rgb(29,157,217);
$yellow: rgb(255, 252, 221);
......
......@@ -41,6 +41,7 @@
}
%t-title3 {
@extend %t-title;
@include font-size(36);
@include line-height(36);
}
......
// lms - views - user/student dashboard
// ====================
// Table of Contents
// * +Dashboard - Sidebar
// * +Dashboard - Course Listing
// * +Dashboard - Course Item
// * +Misc - Uncategorized
// * +Dashboard - Banner
// +Dashboard - Sidebar
// ====================
.dashboard {
@include clearfix();
padding: ($baseline*2) 0 0 0;
.profile-sidebar {
background: transparent;
@include float(left);
@include margin-right(flex-gutter());
@include float(right);
@include margin-left(flex-gutter());
width: flex-grid(3);
background: transparent;
box-shadow: 0 0 1px $shadow-l1;
header.profile {
.profile {
@include box-sizing(border-box);
border: 1px solid $border-color-2;
border-radius: ($baseline/4) ($baseline/4) 0 0;
width: flex-grid(12);
background: $dashboard-profile-color;
.user-name {
.username-header {
margin-bottom: 0;
}
.username-label {
@extend %t-title7;
@extend %t-ultrastrong;
@extend %cont-truncated;
text-align: center;
display: block;
overflow: hidden;
margin: 0;
padding: ($baseline*0.75) ($baseline/2) 0;
padding: ($baseline*0.75) $baseline;
color: $base-font-color;
text-transform: none;
text-wrap: nowrap;
text-overflow: ellipsis;
text-align: center;
font-weight: 700;
line-height: 1.2em;
}
}
......@@ -185,121 +194,47 @@
}
}
}
}
.news-carousel {
@include clearfix();
margin: 30px 10px 0;
border: 1px solid $border-color-2;
background: $dashboard-profile-color;
box-shadow: inset 0 0 3px 0 rgba(0,0,0, 0.15);
* {
font-family: $sans-serif;
}
header {
@include clearfix();
height: 50px;
}
.page-dots {
float: right;
margin: 18px 15px 0 0;
li {
float: left;
margin-left: 6px;
}
}
.page-dot {
display: block;
width: 11px;
height: 11px;
border-radius: 11px;
background: $dot-color;
&:hover, &:focus {
background: $lighter-base-font-color;
}
&.current {
background: $link-color;
}
}
h4 {
float: left;
margin-left: ($baseline*0.75);
font-size: 15px;
line-height: 48px;
font-weight: 700;
text-transform: uppercase;
}
.pages {
position: relative;
}
.page {
display: none;
position: absolute;
top: 0;
left: 0;
&:first-child {
display: block;
}
}
section {
padding: 0 10px;
}
// status
.status {
.news-image {
height: 180px;
margin-bottom: ($baseline*0.75);
img {
width: 100%;
border: 1px solid $border-color-1;
.list--nav {
margin: ($baseline/2) 0 0 0;
padding: 0;
}
}
h5 {
margin-bottom: 8px;
margin-left: ($baseline/4);
a {
font-size: 16px;
font-weight: 700;
.nav__item {
@extend %t-weight4;
@include font-size(13);
margin-left: 26px;
}
}
.excerpt {
margin-left: ($baseline/4);
font-size: 13px;
padding-bottom: 40px;
}
}
}
}
// ====================
// course listings
// +Dashboard - Course Listing
// ====================
.dashboard {
.my-courses {
@include float(left);
margin: 0;
width: flex-grid(9);
> header {
border-bottom: 1px solid $border-color-2;
margin-bottom: ($baseline*1.5);
.wrapper-header-courses {
border-bottom: 4px solid $border-color-l4;
margin-bottom: $baseline;
.header-courses {
@extend %t-title5;
@include padding-right($baseline/2);
}
}
// CASE: empty dashboard
.empty-dashboard-message {
padding: 60px 0px;
padding: ($baseline*2) 0;
text-align: center;
p {
......@@ -339,9 +274,9 @@
@extend %ui-no-list;
.course-item {
margin-bottom: ($baseline*2.5);
margin-bottom: $baseline;
border-bottom: 4px solid $border-color-l4;
padding-bottom: ($baseline*2.5);
padding-bottom: $baseline;
&:last-child {
margin-bottom: 0;
......@@ -350,357 +285,401 @@
}
}
}
}
}
// ====================
// +Dashboard - Course
// ====================
.dashboard .my-courses {
// UI: individual course item
.course {
@include box-sizing(box);
@include transition(all 0.15s linear 0s);
// UI: individual course item
.course {
@include box-sizing(box);
@include transition(all 0.15s linear 0s);
@include clearfix();
@extend %ui-depth2;
position: relative;
margin: ($baseline/2);
.details {
@include clearfix();
@extend %ui-depth2;
position: relative;
.cover {
@include box-sizing(border-box);
@include transition(all 0.15s linear 0s);
overflow: hidden;
position: relative;
.wrapper-course-image {
@include float(left);
height: 100%;
max-height: 100%;
width: 200px;
height: 120px;
margin: 0;
border-radius: ($baseline/10);
border: 1px solid $dashboard-course-cover-border;
border-bottom: 4px solid $dashboard-course-cover-border;
padding: ($baseline/10);
@include margin-right(flex-gutter());
width: flex-grid(3);
img {
width: 100%;
min-height: 100%;
}
}
.cover {
@include box-sizing(border-box);
@include transition(all 0.15s linear 0s);
@include float(left);
overflow: hidden;
position: relative;
max-height: 120px;
border-radius: ($baseline/5);
border: 1px solid $dashboard-course-cover-border;
border-bottom: 4px solid $dashboard-course-cover-border;
.info {
@include clearfix();
@include padding(0, 10px, 0, 230px);
.course-image {
width: 100%;
}
}
> hgroup {
padding: 0;
// "enrolled as" status
.sts-enrollment {
@include float(left);
width: 100%;
position: relative;
bottom: 15px;
display: inline-block;
text-align: center;
.university {
color: $lighter-base-font-color;
font-family: $sans-serif;
font-size: 16px;
font-weight: 400;
margin: 0 0 6px;
text-transform: none;
letter-spacing: 0;
.label {
@extend %text-sr;
}
.date-block {
.deco-graphic {
position: absolute;
top: 0;
top: -5px;
@include right(0);
font-family: $sans-serif;
font-size: 13px;
font-style: italic;
color: $lighter-base-font-color;
}
h3 a, h3 span {
display: block;
margin-bottom: ($baseline/2);
font-family: $sans-serif;
font-size: 34px;
line-height: 42px;
font-weight: 300;
&:hover, &:focus {
text-decoration: none;
}
.sts-enrollment-value {
@extend %ui-depth1;
@extend %copy-badge;
@extend %t-demi-strong;
font-size: 0.6em;
line-height: 1.5em;
border-radius: 0;
padding: 1px ($baseline/4);
color: white;
}
}
}
.course-status {
background: $yellow;
border: 1px solid $border-color-2;
box-shadow: 0 1px 0 0 rgba(255,255,255, 0.6);
margin-top: 17px;
margin-right: flex-gutter();
padding: ($baseline/4);
width: flex-grid(8);
float: left;
@include box-sizing(border-box);
.wrapper-course-details {
display: block;
@include float(left);
width: flex-grid(9);
padding: 0;
}
p {
color: $lighter-base-font-color;
font-style: italic;
letter-spacing: 1px;
text-align: center;
.course-title {
a, span {
@extend %t-title3;
@extend %t-light;
display: inline-block;
margin-bottom: ($baseline/2);
&:hover, &:focus {
text-decoration: none;
}
}
}
.course-status-completed {
background: $gray-l3;
color: $very-light-text;
.course-info {
display: block;
@include float(left);
width: flex-grid(4);
padding: 0;
margin-top: ($baseline/2);
p {
color: #222;
[class*="info-"] {
color: $gray-d1;
@extend %t-title6;
display: inline-block;
}
span {
font-weight: bold;
}
}
.info-date-block {
@extend %t-title7;
color: $gray-l1;
display: block;
}
}
.wrapper-course-actions {
display: block;
@include float(right);
width: flex-grid(8);
padding: 0;
margin-top: ($baseline/2);
}
.course-actions {
.enter-course {
@include button(simple, $button-color);
// UI: course item actions
.action {
@include box-sizing(border-box);
@include margin-right($baseline/2);
@include float(right);
min-width: ($baseline*2);
color: $gray-l1;
border-radius: 3px;
display: block;
@include float(left);
font: normal 15px/1.6rem $sans-serif;
letter-spacing: 0;
padding: 6px 32px 7px;
text-align: center;
margin-top: 16px;
padding: 12px;
border: 1px solid $white;
&:hover, &:focus {
color: $gray-d3;
border: 1px solid $gray-l4;
}
&.archived {
@include button(simple, $button-archive-color);
font: normal 15px/1.6rem $sans-serif;
padding: 6px 32px 7px;
// STATE: is-disabled
&.is-disabled {
color: $gray-l4;
}
&:hover, &:focus {
text-decoration: none;
}
// TYPE: facebook share
&.action-facebook, {
color: $facebook-blue;
}
&:hover, &:focus {
text-decoration: none;
// TYPE: twitter share
&.action-twitter {
color: $twitter-blue;
}
}
}
.prerequisites {
@include clearfix;
// UI: general actions dropdown layout
.wrapper-action-more {
display: inline-block;
position: relative;
@include float(right);
.tip {
font-family: $sans-serif;
font-size: 1em;
color: $lighter-base-font-color;
margin-top: ($baseline/2);
}
}
// "enrolled as" status
.sts-enrollment {
position: absolute;
top: 105px;
@include left(0);
display: inline-block;
text-align: center;
width: 200px;
.actions-dropdown {
@extend %ui-no-list;
@extend %ui-depth1;
display: none;
position: absolute;
top: ($baseline*2);
right: 19px;
pointer-events: none;
min-width: ($baseline*7);
.label {
@extend %text-sr;
}
&.is-visible {
display: block;
pointer-events: auto;
}
.deco-graphic {
position: absolute;
top: -5px;
right: -8px;
}
.actions-dropdown-list {
@extend %ui-no-list;
@include box-sizing(border-box);
display: table;
box-shadow: 0 1px 1px $shadow-l1;
position: relative;
width: 100%;
border-radius: 3px;
margin: ($baseline/4) 0 0 0;
border: 1px solid $gray-l3;
padding: ($baseline/4) ($baseline/2);
background: $white;
// ui triangle/nub
&:after,
&:before {
bottom: 100%;
@include right(3px);
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
.sts-enrollment-value {
@extend %ui-depth1;
@extend %copy-badge;
font-size: 0.6em;
line-height: 1.5em;
font-weight: 600;
border-radius: 0;
padding: 1px ($baseline/2);
color: white;
}
}
&:after {
border-color: $transparent;
border-bottom-color: $white;
border-width: 6px;
@include margin-right(1px);
}
// ====================
&:before {
border-color: $transparent;
border-bottom-color: $gray-l3;
border-width: 7px;
}
}
// CASE: "enrolled as" status - professional ed
&.professional {
.actions-item {
@extend %t-title7;
display: block;
margin: 0;
// changes to cover
.cover {
border-color: $professional-color-lvl3;
padding: ($baseline/10);
}
&.is-hidden {
display: none;
}
// course enrollment status message
.sts-enrollment {
.label {
@extend %text-sr;
}
.action {
@include margin-right(0);
// status message
.sts-enrollment-value {
background: $professional-color-lvl3;
&:hover, &:focus {
border: 1px solid transparent;
}
}
}
}
}
}
// CASE: "enrolled as" status - verified
&.verified {
.course-status {
background: $yellow;
border: 1px solid $border-color-2;
box-shadow: 0 1px 0 0 rgba(255,255,255, 0.6);
margin-top: 17px;
margin-right: flex-gutter();
padding: ($baseline/4);
width: flex-grid(8);
@include float(left);
@include box-sizing(border-box);
// changes to cover
.cover {
border-color: $verified-color-lvl1;
padding: ($baseline/10);
p {
color: $lighter-base-font-color;
font-style: italic;
letter-spacing: 1px;
text-align: center;
}
}
// course enrollment status message
.sts-enrollment {
.label {
@extend %text-sr;
}
.course-status-completed {
background: $gray-l3;
color: $very-light-text;
.deco-graphic {
@extend %ui-depth3;
width: 40px;
position: absolute;
top: -4px;
right: -6px;
}
p {
color: $gray-d4;
// status message
.sts-enrollment-value {
background: $verified-color-lvl1;
span {
font-weight: bold;
}
}
}
// 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;
}
}
.enter-course {
@include button(simple, $button-color);
@include box-sizing(border-box);
border-radius: 3px;
@include float(right);
font: normal 15px/1.6rem $sans-serif;
letter-spacing: 0;
text-align: center;
// CASE: "enrolled as" status - auditing
&.audit {
&.archived {
@include button(simple, $button-archive-color);
font: normal 15px/1.6rem $sans-serif;
// changes to cover
.cover {
border-color: $audit-color-lvl2;
padding: ($baseline/10);
&:hover, &:focus {
text-decoration: none;
}
}
// status message
.sts-enrollment-value {
background: $audit-color-lvl1;
&:hover, &:focus {
text-decoration: none;
}
}
}
// ====================
// UI: message
.wrapper-message-primary {
// UI: messages
.wrapper-messages-primary {
@include clearfix();
}
.message {
border-radius: 3px;
display: none;
z-index: 10;
margin: $baseline 0 ($baseline/2) 0;
padding: ($baseline*0.5) $baseline;
font-family: $sans-serif;
background: tint($yellow,70%);
border: 1px solid $gray-l3;
// STATE: shown
&.is-shown {
display: block;
.messages-list {
margin: 0;
padding: 0;
}
a {
font-family: $sans-serif;
}
.message {
@extend %ui-depth1;
border-radius: 3px;
display: none;
margin: $baseline 0 ($baseline/2) 0;
padding: ($baseline/2) $baseline;
background: $gray-l5;
border: 1px solid $gray-l4;
strong {
font-weight: 700;
// STATE: shown
&.is-shown {
display: block;
}
a {
font-family: $sans-serif;
}
strong {
font-weight: 700;
a {
font-weight: 700;
}
}
}
.actions {
@include clearfix();
list-style: none;
margin: 0;
padding: 0;
}
.actions {
@include clearfix();
list-style: none;
margin: 0;
padding: 0;
}
.message-title,
.message-copy .title {
@extend %t-title6;
@extend %t-weight4;
line-height: 1em;
margin-bottom: ($baseline/4);
}
.message-title,
.message-copy .title {
@extend %t-title6;
@extend %t-weight4;
line-height: 1em;
margin-bottom: ($baseline/4);
}
.message-copy,
.message-copy .copy {
@extend %t-copy-sub1;
margin: 2px 0 0 0;
}
.message-copy,
.message-copy .copy {
@extend %t-copy-sub1;
margin: 2px 0 0 0;
}
// CASE: expandable
&.is-expandable {
// CASE: expandable
&.is-expandable {
.wrapper-tip {
.wrapper-tip {
.message-title, .message-copy {
margin-bottom: 0;
}
.message-title, .message-copy {
margin-bottom: 0;
display: inline-block;
}
.message-title .value, .message-copy {
@include transition(color $tmg-f2 ease-in-out 0s);
}
.message-title .value, .message-copy {
@include transition(color $tmg-f2 ease-in-out 0s);
}
// STATE: hover
&:hover {
cursor: pointer;
// STATE: hover
&:hover {
cursor: pointer;
.message-title .value, .message-copy, .ui-toggle-expansion {
color: $link-color;
.message-title .value, .message-copy, .ui-toggle-expansion {
color: $link-color;
}
}
}
}
.wrapper-extended {
@include transition(opacity $tmg-f2 ease-in-out 0);
display: none;
opacity: 0.0;
.wrapper-extended {
@include transition(opacity $tmg-f2 ease-in-out 0);
display: none;
opacity: 0.0;
}
}
// STATE: is expanded
&.is-expanded {
.ui-toggle-expansion {
@include transform(rotate(0));
@include rtl {
@include transform(rotate(-90deg));
}
@include ltr {
@include transform(rotate(90deg));
}
@include transform-origin(50% 50%);
}
......@@ -709,339 +688,389 @@
opacity: 1.0;
}
}
}
}
// TYPE: upsell
.message-upsell {
// TYPE: upsell
&.message-upsell {
.wrapper-tip {
@include clearfix();
.wrapper-tip {
@include clearfix();
.message-title {
float: left;
}
.message-title {
@include float(left);
}
.ui-toggle-expansion {
@include transition(all $tmg-f2 ease-in-out 0s);
@include transform-origin(50% 50%);
@include font-size(21);
display: inline-block;
vertical-align: middle;
margin-right: ($baseline/4);
.ui-toggle-expansion {
@include transition(all $tmg-f2 ease-in-out 0s);
@include font-size(18);
display: inline-block;
vertical-align: middle;
margin-right: ($baseline/4);
}
@include rtl {
@include transform(rotate(90deg));
.message-copy {
@include float(right);
}
}
@include ltr {
@include transform(rotate(-90deg));
.wrapper-extended {
padding: ($baseline/2) 0;
.message-copy {
margin-bottom: $baseline;
}
}
}
.message-copy {
float: right;
}
}
.action-upgrade {
@extend %btn-primary-green;
@include clearfix();
position: relative;
left: ($baseline/2);
padding: 8px $baseline 8px ($baseline*2);
.deco-graphic {
position: absolute;
top: -($baseline/4);
left: -($baseline*0.75);
width: ($baseline*2);
}
.wrapper-extended {
padding: ($baseline/2) 0;
span {
color: $white; // nasty but needed override for poor <span> styling
}
.message-copy {
margin-bottom: $baseline;
}
}
.copy, .copy-sub {
display: inline-block;
vertical-align: middle;
}
.action-upgrade {
@extend %btn-primary-green;
@include clearfix();
position: relative;
left: ($baseline/2);
padding: 8px $baseline 8px ($baseline*2);
.copy {
@extend %t-action3;
@extend %t-weight4;
margin-right: $baseline;
}
.deco-graphic {
position: absolute;
top: -($baseline/4);
left: -($baseline*0.75);
width: ($baseline*2);
.copy-sub {
@extend %t-action4;
opacity: 0.875;
}
}
}
span {
color: $white; // nasty but needed override for poor <span> styling
}
// TYPE: status
&.message-status {
background: tint($yellow,70%);
border-color: $gray-l3;
.copy, .copy-sub {
display: inline-block;
vertical-align: middle;
}
.message-copy {
@extend %t-copy-sub1;
margin: 0;
.copy {
@extend %t-action3;
@extend %t-weight4;
margin-right: $baseline;
}
.grade-value {
font-size: 1.2rem;
font-weight: bold;
}
}
.copy-sub {
@extend %t-action4;
opacity: 0.875;
}
}
}
.actions {
// TYPE: status
.message-status {
background: tint($yellow,70%);
border-color: $gray-l3;
.action {
@include float(left);
margin: 0 15px 0 0;
.message-copy {
@extend %t-copy-sub1;
margin: 0;
.btn, .cta {
display: inline-block;
}
.grade-value {
font-size: 1.2rem;
font-weight: bold;
}
}
.btn {
@include box-sizing(border-box);
@include float(left);
border-radius: 3px;
font: normal 0.8rem/1.2rem $sans-serif;
letter-spacing: 1px;
padding: 6px 12px;
text-align: center;
&.disabled {
cursor: default !important;
&:hover, &:focus {
@include background-image(linear-gradient(top, #EEE 0%, #C2C2C2 50%, #ABABAB 50%, #B0B0B0 100% ));
background: #eee;
}
}
}
.actions {
.cta {
@include float(left);
font: normal 0.8rem/1.2rem $sans-serif;
letter-spacing: 1px;
padding: 6px 12px;
text-align: center;
}
}
}
.action {
float: left;
margin: 0 15px 0 0;
.exam-registration-number {
font-family: $sans-serif;
font-size: 18px;
.btn, .cta {
display: inline-block;
a {
font-family: $sans-serif;
}
}
.btn {
@include box-sizing(border-box);
border-radius: 3px;
float: left;
font: normal 0.8rem/1.2rem $sans-serif;
letter-spacing: 1px;
padding: 6px 12px;
text-align: center;
&.disabled {
cursor: default !important;
&:hover, &:focus {
background: #eee;
background-image: -webkit-linear-gradient(top, #EEE 0%, #C2C2C2 50%, #ABABAB 50%, #B0B0B0 100%);
background-image: -moz-linear-gradient(top, #EEE 0%, #C2C2C2 50%, #ABABAB 50%, #B0B0B0 100%);
background-image: -ms-linear-gradient(top, #EEE 0%, #C2C2C2 50%, #ABABAB 50%, #B0B0B0 100%);
background-image: -o-linear-gradient(top, #EEE 0%, #C2C2C2 50%, #ABABAB 50%, #B0B0B0 100%);
background-image: linear-gradient(top, #EEE 0%, #C2C2C2 50%, #ABABAB 50%, #B0B0B0 100%);
}
&.exam-register {
.message-copy {
margin-top: ($baseline/4);
width: 55%;
}
}
.cta {
float: left;
font: normal 0.8rem/1.2rem $sans-serif;
letter-spacing: 1px;
padding: 6px 12px;
text-align: center;
&.exam-schedule {
.exam-button {
margin-top: ($baseline/4);
}
}
}
}
.exam-registration-number {
font-family: $sans-serif;
font-size: 18px;
a {
font-family: $sans-serif;
}
}
.exam-button {
@include button(simple, $pink);
@include float(right);
margin-top: 0;
}
&.exam-register {
.contact-button {
@include button(simple, $pink);
}
.message-copy {
margin-top: ($baseline/4);
width: 55%;
}
}
.button {
display: inline-block;
margin-top: ($baseline/2);
padding: 9px 18px 10px;
font-size: 13px;
font-weight: bold;
letter-spacing: 0;
&.exam-schedule {
.exam-button {
margin-top: ($baseline/4);
}
}
&:hover, &:focus {
text-decoration: none;
}
}
.exam-button {
@include button(simple, $pink);
margin-top: 0;
float: right;
}
&.course-status-processing {
background-color: $gray-l5;
border: 0;
}
.contact-button {
@include button(simple, $pink);
}
&.course-status-certnotavailable {
background-color: $gray-l5;
border: 0;
}
.button {
display: inline-block;
margin-top: ($baseline/2);
padding: 9px 18px 10px;
font-size: 13px;
font-weight: bold;
letter-spacing: 0;
&.course-status-certrendering {
background-color: $gray-l5;
border: 0;
&:hover, &:focus {
text-decoration: none;
}
}
.cta {
margin-top: 2px;
}
}
&.course-status-processing {
background-color: $gray-l5;
border: 0;
}
&.course-status-certavailable {
background-color: $gray-l5;
border: 0;
&.course-status-certnotavailable {
background-color: $gray-l5;
border: 0;
}
.message-copy {
width: flex-grid(6, 12);
position: relative;
@include float(left);
}
&.course-status-certrendering {
background-color: $gray-l5;
border: 0;
.actions-primary {
width: flex-grid(6, 12);
position: relative;
@include float(right);
.cta {
margin-top: 2px;
}
}
.action {
@include margin(0, 0, ($baseline/2), ($baseline*.75));
float: none;
text-align: center;
&.course-status-certavailable {
background-color: $gray-l5;
border: 0;
&:last-child {
margin-bottom: 0;
}
.message-copy {
width: flex-grid(6, 12);
position: relative;
@include float(left);
}
.btn {
float: none;
}
}
.actions-primary {
width: flex-grid(6, 12);
position: relative;
@include float(right);
.action-certificate .btn {
@extend %btn-inherited-primary;
@include box-sizing(border-box);
float: none;
border-radius: 3px;
display: block;
@include padding(7px, ($baseline*.75), 7px, ($baseline*.75));
text-align: center;
.action {
@include margin(0, 0, ($baseline/2), ($baseline*.75));
float: none;
text-align: center;
a:link, a:visited {
color: #fff;
}
}
&:last-child {
margin-bottom: 0;
.action-share .btn {
display: inline;
letter-spacing: 0;
}
}
}
.actions-secondary {
margin-top: ($baseline/2);
border-top: 1px solid $gray-l4;
padding-top: ($baseline/2);
.btn {
float: none;
.action-share {
@include float(right);
margin: 0;
}
}
.action-certificate .btn {
@extend %btn-inherited-primary;
@include box-sizing(border-box);
float: none;
border-radius: 3px;
display: block;
@include padding(7px, ($baseline*.75), 7px, ($baseline*.75));
text-align: center;
.certificate-explanation {
@extend %t-copy-sub1;
margin-top: ($baseline/2);
border-top: 1px solid $gray-l4;
padding-top: ($baseline/2);
}
a:link, a:visited {
color: #fff;
.verification-reminder {
width: flex-grid(8, 12);
@include float(left);
position: relative;
}
.verification-cta {
width: flex-grid(4, 12);
@include float(left);
position: relative;
.cta {
@include button(simple, $green-d1);
@include box-sizing(border-box);
@include float(right);
border-radius: 3px;
display: block;
font: normal 15px/1.6rem $sans-serif;
letter-spacing: 0;
padding: 6px 32px 7px;
text-align: center;
}
}
}
.action-share .btn {
display: inline;
letter-spacing: 0;
// TYPE: pre-requisites
.prerequisites {
@include clearfix;
.tip {
font-family: $sans-serif;
font-size: 1em;
color: $lighter-base-font-color;
margin-top: ($baseline/2);
}
}
}
}
.actions-secondary {
margin-top: ($baseline/2);
border-top: 1px solid $gray-l4;
padding-top: ($baseline/2);
// ====================
.action-share {
@include float(right);
margin: 0;
}
// CASE: "enrolled as" status - professional ed
&.professional {
// changes to cover
.wrapper-course-image .cover {
border-color: $professional-color-lvl3;
padding: ($baseline/10);
}
.certificate-explanation {
@extend %t-copy-sub1;
margin-top: ($baseline/2);
border-top: 1px solid $gray-l4;
padding-top: ($baseline/2);
// course enrollment status message
.sts-enrollment {
.label {
@extend %text-sr;
}
// status message
.sts-enrollment-value {
background: $professional-color-lvl3;
}
}
}
.verification-reminder {
width: flex-grid(8, 12);
position: relative;
float: left;
// CASE: "enrolled as" status - verified
&.verified {
// changes to cover
.wrapper-course-image .cover {
border-color: $verified-color-lvl1;
padding: ($baseline/10);
}
.verification-cta {
width: flex-grid(4, 12);
position: relative;
float: left;
// course enrollment status message
.sts-enrollment {
.label {
@extend %text-sr;
}
.cta {
@include button(simple, $green-d1);
@include box-sizing(border-box);
@include float(right);
border-radius: 3px;
display: block;
font: normal 15px/1.6rem $sans-serif;
letter-spacing: 0;
padding: 6px 32px 7px;
text-align: center;
.deco-graphic {
@extend %ui-depth3;
width: 40px;
position: absolute;
top: -5px;
@include right(0);
}
// status message
.sts-enrollment-value {
background: $verified-color-lvl1;
}
}
}
a.unenroll {
@include float(right);
display: block;
font-style: italic;
color: $lighter-base-font-color;
text-decoration: underline;
font-size: .8em;
margin-top: 32px;
// CASE: "enrolled as" status - honor code
&.honor {
&:hover, &:focus {
color: #333;
// changes to cover
.wrapper-course-image .cover {
border-color: $honorcode-color-lvl2;
padding: ($baseline/10);
}
}
a.email-settings {
@extend a.unenroll;
@include margin-right(10px);
// status message
.sts-enrollment-value {
background: $honorcode-color-lvl1;
}
}
}
// account-related
.user-info {
// CASE: "enrolled as" status - auditing
&.audit {
// status
.status {
.list--nav {
margin: ($baseline/2) 0 0 0;
padding: 0;
// changes to cover
.wrapper-course-image .cover {
border-color: $audit-color-lvl2;
padding: ($baseline/10);
}
.nav__item {
@extend %t-weight4;
@include font-size(13);
margin-left: 26px;
// status message
.sts-enrollment-value {
background: $audit-color-lvl1;
}
}
}
}
// +Misc - Uncategorized
// ====================
.dashboard .my-courses {
// status - language
.status-language {
......@@ -1215,8 +1244,8 @@
.enter-course-blocked{
@include box-sizing(border-box);
@include float(left);
display: block;
float: left;
font: normal 15px/1.6rem $sans-serif;
letter-spacing: 0;
padding: 6px 32px 7px;
......@@ -1227,113 +1256,103 @@
border:0;
color:white;
box-shadow:none;
&.archived {
@include button(simple, $button-archive-color);
font: normal 15px/1.6rem $sans-serif;
padding: 6px 32px 7px;
@include button(simple, $button-archive-color);
font: normal 15px/1.6rem $sans-serif;
padding: 6px 32px 7px;
&:hover, &:focus {
text-decoration: none;
}
}
&:hover, &:focus {
text-decoration: none;
}
}
}
a.disable-look{
color: #808080;
}
a.disable-look-unregister{
color: #808080;
float: right;
display: block;
font-style: italic;
color: $lighter-base-font-color;
text-decoration: underline;
font-size: .8em;
margin-top: 32px;
}
a.disable-look-settings{
@extend a.disable-look-unregister;
margin-right: ($baseline/2);
}
}
a.fade-cover{
@extend .cover;
opacity: 0.5;
}
}
.dashboard-banner {
&:empty {
display: none;
}
.wrapper-msg {
padding-bottom: 0;
// +Dashboard - Banner
// ====================
.dashboard .my-courses {
.dashboard-banner {
.msg {
@include clearfix();
font-family: $sans-serif;
padding-bottom: $baseline;
border-bottom: thin solid $gray;
&:empty {
display: none;
}
&.title {
@extend %t-title5;
@extend %t-weight4;
font-family: $f-sans-serif;
.wrapper-msg {
padding-bottom: 0;
// Overriding Platform h2 styles
text-transform: none;
letter-spacing: 0;
}
.msg {
@include clearfix();
font-family: $sans-serif;
padding-bottom: $baseline;
border-bottom: thin solid $gray;
&.has-actions {
&.title {
@extend %t-title5;
@extend %t-weight4;
font-family: $f-sans-serif;
.donate-content {
width: flex-grid(8, 12);
// Overriding Platform h2 styles
text-transform: none;
letter-spacing: 0;
}
.donate-actions {
width: flex-grid(4, 12);
vertical-align: bottom;
display: inline-block;
&.has-actions {
.monetary-symbol {
vertical-align: middle;
color: $white;
font-weight: 600;
.donate-content {
width: flex-grid(8, 12);
}
.amount {
height: 40px;
width: 80px;
vertical-align: middle;
text-align: left;
border: 2px solid $white;
.donate-actions {
width: flex-grid(4, 12);
vertical-align: bottom;
display: inline-block;
&.validation-error {
border: 2px solid $error-color;
.monetary-symbol {
vertical-align: middle;
color: $white;
font-weight: 600;
}
}
.action-donate {
@extend %btn-primary-blue;
vertical-align: middle;
padding-top: ($baseline/2);
padding-bottom: ($baseline/2);
text-shadow: none;
text-transform: none;
letter-spacing: 0;
color: $white;
font-weight: 600;
}
.amount {
height: 40px;
width: 80px;
vertical-align: middle;
text-align: left;
border: 2px solid $white;
.donation-error-msg {
padding: ($baseline/2) 0;
&.validation-error {
border: 2px solid $error-color;
}
}
.action-donate {
@extend %btn-primary-blue;
vertical-align: middle;
padding-top: ($baseline/2);
padding-bottom: ($baseline/2);
text-shadow: none;
text-transform: none;
letter-spacing: 0;
color: $white;
font-weight: 600;
}
.donation-error-msg {
padding: ($baseline/2) 0;
}
}
}
}
}
}
}
......@@ -117,7 +117,7 @@ header.global {
.user {
@include float(right);
margin-top: 4px;
margin-top: ($baseline/4);
> .primary {
display: block;
......@@ -135,7 +135,7 @@ header.global {
> a {
@include border-radius(0, 4px, 4px, 0);
@include border-left(none);
padding: 3px 8px 9px 8px;
padding: ($baseline/4) 8px 11px ($baseline/2);
&.shopping-cart {
border-radius: 4px;
......@@ -148,7 +148,7 @@ header.global {
}
a.user-link {
@include padding(3px, 12px, 8px, 8px);
@include padding(5px, 12px, 10px, 10px);
position: relative;
text-transform: none;
font-size: 14px;
......@@ -196,17 +196,17 @@ header.global {
}
.dropdown-menu {
background: $border-color-4;
background: $white;
border-radius: 4px;
box-shadow: 0 2px 24px 0 rgba(0,0,0, 0.3);
border: 1px solid $border-color-3;
box-shadow: 0 2px 2px 0 rgba(0,0,0, 0.3);
border: 1px solid $gray-l3;
display: none;
margin-top: 0;
padding: 5px 10px;
position: absolute;
@include right(0px);
top: 34px;
width: 170px;
top: 37px;
min-width: 120px;
z-index: 3;
&.expanded {
......@@ -221,14 +221,14 @@ header.global {
bottom: 6px solid transparent;
left: 6px solid transparent;
}
box-shadow: 1px 0 0 0 $border-color-3, 0 -1px 0 0 $border-color-3;
box-shadow: 1px 0 0 0 $gray-l3, 0 -1px 0 0 $gray-l3;
content: "";
display: block;
height: 0px;
position: absolute;
@include transform(rotate(-45deg));
@include right(7px);
top: -6px;
top: -5px;
width: 0px;
}
......@@ -579,7 +579,7 @@ header.global-new {
li {
display: block;
border-top: 1px dotted $border-color-2;
border-top: 1px solid $gray-l3;
box-shadow: inset 0 1px 0 0 rgba(255,255,255, 0.05);
&:first-child {
......
......@@ -74,10 +74,59 @@
</div>
<section class="container dashboard" id="dashboard-main">
<section class="my-courses" id="my-courses" role="main" aria-label="Content">
<header class="wrapper-header-courses">
<h2 class="header-courses">${_("Current Courses")}</h2>
</header>
% if len(course_enrollment_pairs) > 0:
<ul class="listing-courses">
% for dashboard_index, (course, enrollment) in enumerate(course_enrollment_pairs):
<% show_courseware_link = (course.id in show_courseware_links_for) %>
<% cert_status = cert_statuses.get(course.id) %>
<% show_email_settings = (course.id in show_email_settings_for) %>
<% course_mode_info = all_course_modes.get(course.id) %>
<% show_refund_option = (course.id in show_refund_option_for) %>
<% is_paid_course = (course.id in enrolled_courses_either_paid) %>
<% is_course_blocked = (course.id in block_courses) %>
<% course_verification_status = verification_status_by_course.get(course.id, {}) %>
<% course_requirements = courses_requirements_not_met.get(course.id) %>
<%include file='dashboard/_dashboard_course_listing.html' args="course=course, enrollment=enrollment, show_courseware_link=show_courseware_link, cert_status=cert_status, show_email_settings=show_email_settings, course_mode_info=course_mode_info, show_refund_option = show_refund_option, is_paid_course = is_paid_course, is_course_blocked = is_course_blocked, verification_status=course_verification_status, course_requirements=course_requirements, dashboard_index=dashboard_index" />
% endfor
</ul>
% else:
<section class="empty-dashboard-message">
% if settings.FEATURES.get('COURSES_ARE_BROWSABLE'):
<p>${_("Looks like you haven't enrolled in any courses yet.")}</p>
<a href="${marketing_link('COURSES')}">
${_("Find courses now!")}
</a>
% else:
<p>${_("Looks like you haven't enrolled in any courses yet.")}</p>
%endif
</section>
% endif
% if staff_access and len(errored_courses) > 0:
<div id="course-errors">
<h2>${_("Course-loading errors")}</h2>
<section class="profile-sidebar">
% for course_dir, errors in errored_courses.items():
<h3>${course_dir | h}</h3>
<ul>
% for (msg, err) in errors:
<li>${msg}
<ul><li><pre>${err}</pre></li></ul>
</li>
% endfor
</ul>
% endfor
</div>
% endif
</section>
<section class="profile-sidebar" role="region" aria-label="User info">
<header class="profile">
<h2><span class="sr">${_("Username")}: </span><span class="user-name">${ user.username }</span></h2>
<h2 class="username-header"><span class="sr">${_("Username")}: </span><span class="username-label">${ user.username }</span></h2>
</header>
<section class="user-info">
<ul>
......@@ -119,7 +168,6 @@
<span class="provider">${state.provider.NAME}</span>
<span class="control">
% if state.has_account:
<form
action="${pipeline.get_disconnect_url(state.provider.NAME)}"
......@@ -128,20 +176,21 @@
<input type="hidden" name="csrfmiddlewaretoken" value="${csrf_token}">
<a href="#" onclick="document.${state.get_unlink_form_name()}.submit()">
## Translators: clicking on this removes the link between a user's edX account and their account with an external authentication provider (like Google or LinkedIn).
${_("Unlink")}
## Translators: clicking on this removes the link between a user's edX account and their account with an external authentication provider (like Google or LinkedIn).
${_("Unlink")}
</a>
% else:
</form>
% else:
<a href="${pipeline.get_login_url(state.provider.NAME, pipeline.AUTH_ENTRY_DASHBOARD, redirect_url='/')}">
## Translators: clicking on this creates a link between a user's edX account and their account with an external authentication provider (like Google or LinkedIn).
${_("Link")}
## Translators: clicking on this creates a link between a user's edX account and their account with an external authentication provider (like Google or LinkedIn).
${_("Link")}
</a>
% endif
</form>
</span>
</div>
% endfor
</span>
</span>
</li>
% endif
......@@ -171,58 +220,6 @@
</ul>
</section>
</section>
<section id="my-courses" class="my-courses" role="main" aria-label="Content">
<header>
<h2>${_("Current Courses")}</h2>
</header>
% if len(course_enrollment_pairs) > 0:
<ul class="listing-courses">
% for course, enrollment in course_enrollment_pairs:
<% show_courseware_link = (course.id in show_courseware_links_for) %>
<% cert_status = cert_statuses.get(course.id) %>
<% show_email_settings = (course.id in show_email_settings_for) %>
<% course_mode_info = all_course_modes.get(course.id) %>
<% show_refund_option = (course.id in show_refund_option_for) %>
<% is_paid_course = (course.id in enrolled_courses_either_paid) %>
<% is_course_blocked = (course.id in block_courses) %>
<% course_verification_status = verification_status_by_course.get(course.id, {}) %>
<% course_requirements = courses_requirements_not_met.get(course.id) %>
<%include file='dashboard/_dashboard_course_listing.html' args="course=course, enrollment=enrollment, show_courseware_link=show_courseware_link, cert_status=cert_status, show_email_settings=show_email_settings, course_mode_info=course_mode_info, show_refund_option = show_refund_option, is_paid_course = is_paid_course, is_course_blocked = is_course_blocked, verification_status=course_verification_status, course_requirements=course_requirements" />
% endfor
</ul>
% else:
<section class="empty-dashboard-message">
% if settings.FEATURES.get('COURSES_ARE_BROWSABLE'):
<p>${_("Looks like you haven't enrolled in any courses yet.")}</p>
<a href="${marketing_link('COURSES')}">
${_("Find courses now!")}
</a>
% else:
<p>${_("Looks like you haven't enrolled in any courses yet.")}</p>
%endif
</section>
% endif
% if staff_access and len(errored_courses) > 0:
<div id="course-errors">
<h2>${_("Course-loading errors")}</h2>
% for course_dir, errors in errored_courses.items():
<h3>${course_dir | h}</h3>
<ul>
% for (msg, err) in errors:
<li>${msg}
<ul><li><pre>${err}</pre></li></ul>
</li>
% endfor
</ul>
% endfor
% endif
</section>
</section>
......@@ -257,8 +254,6 @@
</div>
</section>
<section id="password_reset_complete" class="modal" aria-hidden="true">
<div class="inner-wrapper" role="dialog" aria-labelledby="password-reset-email">
<button class="close-modal">
......
<%page args="course, enrollment, show_courseware_link, cert_status, show_email_settings, course_mode_info, show_refund_option, is_paid_course, is_course_blocked, verification_status, course_requirements" />
<%page args="course, enrollment, show_courseware_link, cert_status, show_email_settings, course_mode_info, show_refund_option, is_paid_course, is_course_blocked, verification_status, course_requirements, dashboard_index" />
<%!
from django.utils.translation import ugettext as _
......@@ -39,113 +39,217 @@ from student.helpers import (
%>
% else:
<% mode_class = '' %>
% endif
<article class="course${mode_class}">
<%
course_target = reverse('info', args=[course.id.to_deprecated_string()])
%>
% endif
% if show_courseware_link:
% if not is_course_blocked:
<a href="${course_target}" class="cover">
<img src="${course_image_url(course)}" alt="${_('{course_number} {course_name} Home Page').format(course_number=course.number, course_name=course.display_name_with_default) |h}" />
</a>
<article class="course${mode_class}">
<% course_target = reverse('info', args=[unicode(course.id)]) %>
<section class="details">
<div class="wrapper-course-image" aria-hidden="true">
% if show_courseware_link:
% if not is_course_blocked:
<a href="${course_target}" class="cover">
<img src="${course_image_url(course)}" class="course-image" alt="${_('{course_number} {course_name} Home Page').format(course_number=course.number, course_name=course.display_name_with_default) |h}" />
</a>
% else:
<a class="fade-cover">
<img src="${course_image_url(course)}" alt="${_('{course_number} {course_name} Cover Image').format(course_number=course.number, course_name=course.display_name_with_default) |h}" />
</a>
<a class="fade-cover">
<img src="${course_image_url(course)}" class="course-image" alt="${_('{course_number} {course_name} Cover Image').format(course_number=course.number, course_name=course.display_name_with_default) |h}" />
</a>
% endif
% else:
<div class="cover">
<img src="${course_image_url(course)}" alt="${_('{course_number} {course_name} Cover Image').format(course_number=course.number, course_name=course.display_name_with_default) | h}" />
</div>
% endif
% if settings.FEATURES.get('ENABLE_VERIFIED_CERTIFICATES'):
<span class="sts-enrollment" title="${course_verified_certs.get('enrollment_title')}">
<span class="label">${_("Enrolled as: ")}</span>
% if course_verified_certs.get('show_image'):
<img class="deco-graphic" src="${static.url('images/verified-ribbon.png')}" alt="${course_verified_certs.get('image_alt')}" />
% endif
<div class="sts-enrollment-value">${course_verified_certs.get('enrollment_value')}</div>
</span>
% endif
<section class="info">
<hgroup>
<p class="date-block">
% if course.has_ended():
${_("Course Completed - {end_date}").format(end_date=course.end_datetime_text("DATE_TIME"))}
% elif course.has_started():
${_("Course Started - {start_date}").format(start_date=course.start_datetime_text("DATE_TIME"))}
% elif course.start_date_is_still_default: # Course start date TBD
${_("Course has not yet started")}
% else: # hasn't started yet
${_("Course Starts - {start_date}").format(start_date=course.start_datetime_text("DATE_TIME"))}
% endif
</p>
<h2 class="university">${get_course_about_section(course, 'university')}</h2>
<h3>
% else:
<a class="cover">
<img src="${course_image_url(course)}" class="course-image" alt="${_('{course_number} {course_name} Cover Image').format(course_number=course.number, course_name=course.display_name_with_default) | h}" />
</a>
% endif
% if settings.FEATURES.get('ENABLE_VERIFIED_CERTIFICATES'):
<span class="sts-enrollment" title="${course_verified_certs.get('enrollment_title')}">
<span class="label">${_("Enrolled as: ")}</span>
% if course_verified_certs.get('show_image'):
<img class="deco-graphic" src="${static.url('images/verified-ribbon.png')}" alt="${course_verified_certs.get('image_alt')}" />
% endif
<div class="sts-enrollment-value">${course_verified_certs.get('enrollment_value')}</div>
</span>
% endif
</div>
<div class="wrapper-course-details">
<h3 class="course-title">
% if show_courseware_link:
% if not is_course_blocked:
<a href="${course_target}">${course.display_number_with_default | h} ${course.display_name_with_default}</a>
% if not is_course_blocked:
<a href="${course_target}">${course.display_name_with_default}</a>
% else:
<a class="disable-look">${course.display_number_with_default | h} ${course.display_name_with_default}</a>
<a class="disable-look">${course.display_name_with_default}</a>
% endif
% else:
<span>${course.display_number_with_default | h} ${course.display_name_with_default}</span>
<span>${course.display_name_with_default}</span>
% endif
</h3>
</hgroup>
<div class="course-info">
<span class="info-university">${get_course_about_section(course, 'university')} - </span>
<span class="info-course-id">${course.display_number_with_default | h}</span>
<span class="info-date-block" data-tooltip="Hi">
% if course.has_ended():
${_("Ended - {end_date}").format(end_date=course.end_datetime_text("SHORT_DATE"))}
% elif course.has_started():
${_("Started - {start_date}").format(start_date=course.start_datetime_text("SHORT_DATE"))}
% elif course.start_date_is_still_default: # Course start date TBD
${_("Coming Soon")}
% else: # hasn't started yet
${_("Starts - {start_date}").format(start_date=course.start_datetime_text("SHORT_DATE"))}
% endif
</span>
</div>
% if show_courseware_link:
<div class="wrapper-course-actions">
<div class="course-actions">
% if course.has_ended():
% if not is_course_blocked:
<a href="${course_target}" class="enter-course archived">${_('View Archived Course')}<span class="sr">&nbsp;${course.display_name_with_default}</span></a>
% else:
<a class="enter-course-blocked archived">${_('View Archived Course')}<span class="sr">&nbsp;${course.display_name_with_default}</span></a>
% endif
% else:
% if not is_course_blocked:
<a href="${course_target}" class="enter-course">${_('View Course')}<span class="sr">&nbsp;${course.display_name_with_default}</span></a>
% else:
<a class="enter-course-blocked">${_('View Course')}<span class="sr">&nbsp;${course.display_name_with_default}</span></a>
% endif
% endif
<div class="wrapper-action-more">
<a href="#actions-dropdown-${dashboard_index}" class="action action-more" id="actions-dropdown-link-${dashboard_index}" aria-haspopup="true" aria-expanded="false" data-course-number="${course.number | h}" data-dashboard-index="${dashboard_index}">
<span class="sr">${_('Course options dropdown')}</span>
<i class="fa fa-cog" aria-hidden="true"></i>
</a>
<div class="actions-dropdown" id="actions-dropdown-${dashboard_index}" aria-label="${_('Additional Actions Menu')}">
<ul class="actions-dropdown-list" id="actions-dropdown-list-${dashboard_index}" aria-label="${_('Available Actions')}" role="menu">
<li class="actions-item" id="actions-item-unenroll-${dashboard_index}">
% if is_paid_course and show_refund_option:
## Translators: The course name will be added to the end of this sentence.
% if not is_course_blocked:
<a href="#unenroll-modal" class="action action-unenroll" rel="leanModal" data-course-id="${course.id | h}" data-course-number="${course.number | h}" data-dashboard-index="${dashboard_index}" onclick="document.getElementById('track-info').innerHTML='${_("Are you sure you want to unenroll from the purchased course")}';
document.getElementById('refund-info').innerHTML=gettext('You will be refunded the amount you paid.')">
${_('Unenroll')}
</a>
% else:
<a class="action action-unenroll is-disabled" data-course-id="${course.id | h}" data-course-number="${course.number | h}" data-dashboard-index="${dashboard_index}" onclick="document.getElementById('track-info').innerHTML='${_("Are you sure you want to unenroll from the purchased course")}';
document.getElementById('refund-info').innerHTML=gettext('You will be refunded the amount you paid.')">
${_('Unenroll')}
</a>
% endif
% elif is_paid_course and not show_refund_option:
## Translators: The course's name will be added to the end of this sentence.
% if not is_course_blocked:
<a href="#unenroll-modal" class="action action-unenroll" rel="leanModal" data-course-id="${course.id | h}" data-course-number="${course.number | h}" data-dashboard-index="${dashboard_index}" onclick="document.getElementById('track-info').innerHTML='${_("Are you sure you want to unenroll from the purchased course")}';
document.getElementById('refund-info').innerHTML=gettext('You will not be refunded the amount you paid.')">
${_('Unenroll')}
</a>
% else:
<a class="action action-unenroll is-disabled" data-course-id="${course.id | h}" data-course-number="${course.number | h}" data-dashboard-index="${dashboard_index}" onclick="document.getElementById('track-info').innerHTML='${_("Are you sure you want to unenroll from the purchased course")}';
document.getElementById('refund-info').innerHTML=gettext('You will not be refunded the amount you paid.')">
${_('Unenroll')}
</a>
% endif
% elif enrollment.mode != "verified":
## Translators: The course's name will be added to the end of this sentence.
% if not is_course_blocked:
<a href="#unenroll-modal" class="action action-unenroll" rel="leanModal" data-course-id="${course.id | h}" data-course-number="${course.number | h}" data-dashboard-index="${dashboard_index}" onclick="document.getElementById('track-info').innerHTML='${_("Are you sure you want to unenroll from")}'; document.getElementById('refund-info').innerHTML=''">
${_('Unenroll')}
</a>
% else:
<a class="action action-unenroll is-disabled" data-course-id="${course.id | h}" data-course-number="${course.number | h}" data-dashboard-index="${dashboard_index}" onclick="document.getElementById('track-info').innerHTML='${_("Are you sure you want to unenroll from")}'; document.getElementById('refund-info').innerHTML=''">
${_('Unenroll')}
</a>
% endif
% elif show_refund_option:
## Translators: The course's name will be added to the end of this sentence.
% if not is_course_blocked:
<a href="#unenroll-modal" class="action action-unenroll" rel="leanModal" data-course-id="${course.id | h}" data-course-number="${course.number | h}" data-dashboard-index="${dashboard_index}" onclick="document.getElementById('track-info').innerHTML='${_("Are you sure you want to unenroll from the verified {cert_name_long} track of").format(cert_name_long=cert_name_long)}';
document.getElementById('refund-info').innerHTML=gettext('You will be refunded the amount you paid.')">
${_('Unenroll')}
</a>
% else:
<a class="action action-unenroll is-disabled" data-course-id="${course.id | h}" data-course-number="${course.number | h}" data-dashboard-index="${dashboard_index}" onclick="document.getElementById('track-info').innerHTML='${_("Are you sure you want to unenroll from the verified {cert_name_long} track of").format(cert_name_long=cert_name_long)}';
document.getElementById('refund-info').innerHTML=gettext('You will be refunded the amount you paid.')">
${_('Unenroll')}
</a>
% endif
% else:
## Translators: The course's name will be added to the end of this sentence.
% if not is_course_blocked:
<a href="#unenroll-modal" class="action action-unenroll" rel="leanModal" data-course-id="${course.id | h}" data-course-number="${course.number | h}" data-dashboard-index="${dashboard_index}" onclick="document.getElementById('track-info').innerHTML='${_("Are you sure you want to unenroll from the verified {cert_name_long} track of").format(cert_name_long=cert_name_long)}';
document.getElementById('refund-info').innerHTML=gettext('The refund deadline for this course has passed, so you will not receive a refund.')">
${_('Unenroll')}
</a>
% else:
<a class="action action-unenroll is-disabled" data-course-id="${course.id | h}" data-course-number="${course.number | h}" data-dashboard-index="${dashboard_index}" onclick="document.getElementById('track-info').innerHTML='${_("Are you sure you want to unenroll from the verified {cert_name_long} track of").format(cert_name_long=cert_name_long)}';
document.getElementById('refund-info').innerHTML=gettext('The refund deadline for this course has passed, so you will not receive a refund.')">
${_('Unenroll')}
</a>
% endif
% endif
</li>
<li class="actions-item" id="actions-item-email-settings-${dashboard_index}">
% if show_email_settings:
% if not is_course_blocked:
<a href="#email-settings-modal" class="action action-email-settings" rel="leanModal" data-course-id="${course.id | h}" data-course-number="${course.number | h}" data-dashboard-index="${dashboard_index}" data-optout="${unicode(course.id) in course_optouts}">${_('Email Settings')}</a>
% else:
<a class="action action-email-settings is-disabled" data-course-id="${course.id| h}" data-course-number="${course.number | h}" data-dashboard-index="${dashboard_index}" data-optout="${unicode(course.id) in course_optouts}">${_('Email Settings')}</a>
% endif
% endif
</li>
</ul>
</div>
</div>
</div>
</div>
% endif
</div>
</section>
<footer class="wrapper-messages-primary">
<ul class="messages-list">
% if course.may_certify() and cert_status:
<%include file='_dashboard_certificate_information.html' args='cert_status=cert_status,course=course, enrollment=enrollment'/>
% endif
<%include file='_dashboard_certificate_information.html' args='cert_status=cert_status,course=course, enrollment=enrollment'/>
% endif
% if verification_status.get('status') in [VERIFY_STATUS_NEED_TO_VERIFY, VERIFY_STATUS_SUBMITTED, VERIFY_STATUS_APPROVED, VERIFY_STATUS_NEED_TO_REVERIFY] and not is_course_blocked:
<div class="message message-status wrapper-message-primary is-shown">
% if verification_status['status'] == VERIFY_STATUS_NEED_TO_VERIFY:
<div class="verification-reminder">
% if verification_status['days_until_deadline'] is not None:
<h4 class="message-title">${_('Verification not yet complete.')}</h4>
<p class="message-copy">${ungettext(
'You only have {days} day left to verify for this course.',
'You only have {days} days left to verify for this course.',
verification_status['days_until_deadline']
).format(days=verification_status['days_until_deadline'])}</p>
% else:
<h4 class="message-title">${_('Almost there!')}</h4>
<p class="message-copy">${_('You still need to verify for this course.')}</p>
% if verification_status.get('status') in [VERIFY_STATUS_NEED_TO_VERIFY, VERIFY_STATUS_SUBMITTED, VERIFY_STATUS_APPROVED, VERIFY_STATUS_NEED_TO_REVERIFY] and not is_course_blocked:
<div class="message message-status wrapper-message-primary is-shown">
% if verification_status['status'] == VERIFY_STATUS_NEED_TO_VERIFY:
<div class="verification-reminder">
% if verification_status['days_until_deadline'] is not None:
<h4 class="message-title">${_('Verification not yet complete.')}</h4>
<p class="message-copy">${ungettext(
'You only have {days} day left to verify for this course.',
'You only have {days} days left to verify for this course.',
verification_status['days_until_deadline']
).format(days=verification_status['days_until_deadline'])}</p>
% else:
<h4 class="message-title">${_('Almost there!')}</h4>
<p class="message-copy">${_('You still need to verify for this course.')}</p>
% endif
</div>
<div class="verification-cta">
<a href="${reverse('verify_student_verify_later', kwargs={'course_id': unicode(course.id)})}" class="cta" data-course-id="${course.id | h}">${_('Verify Now')}</a>
</div>
% elif verification_status['status'] == VERIFY_STATUS_SUBMITTED:
<h4 class="message-title">${_('You have already verified your ID!')}</h4>
<p class="message-copy">${_('Thanks for your patience as we process your request.')}</p>
% elif verification_status['status'] == VERIFY_STATUS_APPROVED:
<h4 class="message-title">${_('You have already verified your ID!')}</h4>
% if verification_status['verification_good_until'] is not None:
<p class="message-copy">${_('Your verification status is good until {date}.').format(date=verification_status['verification_good_until'])}
% endif
</div>
<div class="verification-cta">
<a href="${reverse('verify_student_verify_later', kwargs={'course_id': unicode(course.id)})}" class="cta" data-course-id="${course.id | h}">${_('Verify Now')}</a>
</div>
% elif verification_status['status'] == VERIFY_STATUS_SUBMITTED:
<h4 class="message-title">${_('You have already verified your ID!')}</h4>
<p class="message-copy">${_('Thanks for your patience as we process your request.')}</p>
% elif verification_status['status'] == VERIFY_STATUS_APPROVED:
<h4 class="message-title">${_('You have already verified your ID!')}</h4>
% if verification_status['verification_good_until'] is not None:
<p class="message-copy">${_('Your verification status is good until {date}.').format(date=verification_status['verification_good_until'])}
% elif verification_status['status'] == VERIFY_STATUS_NEED_TO_REVERIFY:
<h4 class="message-title">${_('Your verification will expire soon!')}</h4>
## Translators: start_link and end_link will be replaced with HTML tags;
## please do not translate these.
<p class="message-copy">${_('Your current verification will expire before the verification deadline for this course. {start_link}Re-verify your identity now{end_link} using a webcam and a government-issued ID.').format(start_link='<a href="{href}">'.format(href=reverse('verify_student_reverify')), end_link='</a>')}</p>
% endif
% elif verification_status['status'] == VERIFY_STATUS_NEED_TO_REVERIFY:
<h4 class="message-title">${_('Your verification will expire soon!')}</h4>
## Translators: start_link and end_link will be replaced with HTML tags;
## please do not translate these.
<p class="message-copy">${_('Your current verification will expire before the verification deadline for this course. {start_link}Re-verify your identity now{end_link} using a webcam and a government-issued ID.').format(start_link='<a href="{href}">'.format(href=reverse('verify_student_reverify')), end_link='</a>')}</p>
</div>
% endif
</div>
% endif
% if course_mode_info['show_upsell'] and not is_course_blocked:
<div class="message message-upsell has-actions is-expandable is-shown">
% if course_mode_info['show_upsell'] and not is_course_blocked:
<div class="message message-upsell has-actions is-expandable is-shown">
<div class="wrapper-tip">
<h4 class="message-title">
<i class="icon fa fa-caret-down ui-toggle-expansion"></i>
<i class="icon fa fa-caret-right ui-toggle-expansion"></i>
<span class="value">${_("Challenge Yourself!")}</span>
</h4>
<p class="message-copy">${_("Take this course as an ID-verified student.")}</p>
......@@ -165,139 +269,50 @@ from student.helpers import (
</li>
</ul>
</div>
</div>
%endif
% if is_course_blocked:
<p id="block-course-msg" class="course-block">
${_("You can no longer access this course because payment has not yet been received. "
"You can {contact_link_start}contact the account holder{contact_link_end} "
"to request payment, or you can "
"{unenroll_link_start}unenroll{unenroll_link_end} "
"from this course").format(
contact_link_start='<a href="#">',
contact_link_end='</a>',
unenroll_link_start=(
'<a id="unregister_block_course" rel="leanModal" '
'data-course-id="{course_id}" data-course-number="{course_number}" '
'href="#unenroll-modal">'.format(
course_id=escape(course.id),
course_number=escape(course.number),
)
),
unenroll_link_end="</a>",
)}
</p>
%endif
</div>
%endif
% if show_courseware_link:
% if course.has_ended():
% if not is_course_blocked:
<a href="${course_target}" class="enter-course archived">${_('View Archived Course')}</a>
% else:
<a class="enter-course-blocked archived">${_('View Archived Course')}</a>
% endif
% else:
% if not is_course_blocked:
<a href="${course_target}" class="enter-course">${_('View Course')}</a>
% else:
<a class="enter-course-blocked">${_('View Course')}</a>
% endif
% endif
% endif
% if is_course_blocked:
<p id="block-course-msg" class="course-block">
${_("You can no longer access this course because payment has not yet been received. "
"You can {contact_link_start}contact the account holder{contact_link_end} "
"to request payment, or you can "
"{unenroll_link_start}unenroll{unenroll_link_end} "
"from this course").format(
contact_link_start='<a href="#">',
contact_link_end='</a>',
unenroll_link_start=(
'<a id="unregister_block_course" rel="leanModal" '
'data-course-id="{course_id}" data-course-number="{course_number}" '
'href="#unenroll-modal">'.format(
course_id=escape(course.id),
course_number=escape(course.number),
)
),
unenroll_link_end="</a>",
)}
</p>
%endif
% if is_paid_course and show_refund_option:
## Translators: The course's name will be added to the end of this sentence.
% if not is_course_blocked:
<a href="#unenroll-modal" class="unenroll" rel="leanModal" data-course-id="${course.id | h}" data-course-number="${course.number | h}" onclick="document.getElementById('track-info').innerHTML='${_("Are you sure you want to unenroll from the purchased course")}';
document.getElementById('refund-info').innerHTML=gettext('You will be refunded the amount you paid.')">
${_('Unenroll')}
</a>
% else:
<a class="disable-look-unregister" data-course-id="${course.id | h}" data-course-number="${course.number | h}" onclick="document.getElementById('track-info').innerHTML='${_("Are you sure you want to unenroll from the purchased course")}';
document.getElementById('refund-info').innerHTML=gettext('You will be refunded the amount you paid.')">
${_('Unenroll')}
</a>
% endif
% elif is_paid_course and not show_refund_option:
## Translators: The course's name will be added to the end of this sentence.
% if not is_course_blocked:
<a href="#unenroll-modal" class="unenroll" rel="leanModal" data-course-id="${course.id | h}" data-course-number="${course.number | h}" onclick="document.getElementById('track-info').innerHTML='${_("Are you sure you want to unenroll from the purchased course")}';
document.getElementById('refund-info').innerHTML=gettext('You will not be refunded the amount you paid.')">
${_('Unenroll')}
</a>
% else:
<a class="disable-look-unregister" data-course-id="${course.id | h}" data-course-number="${course.number | h}" onclick="document.getElementById('track-info').innerHTML='${_("Are you sure you want to unenroll from the purchased course")}';
document.getElementById('refund-info').innerHTML=gettext('You will not be refunded the amount you paid.')">
${_('Unenroll')}
</a>
% endif
% elif enrollment.mode != "verified":
## Translators: The course's name will be added to the end of this sentence.
% if not is_course_blocked:
<a href="#unenroll-modal" class="unenroll" rel="leanModal" data-course-id="${course.id | h}" data-course-number="${course.number | h}" onclick="document.getElementById('track-info').innerHTML='${_("Are you sure you want to unenroll from")}'; document.getElementById('refund-info').innerHTML=''">
${_('Unenroll')}
</a>
% else:
<a class="disable-look-unregister" data-course-id="${course.id | h}" data-course-number="${course.number | h}" onclick="document.getElementById('track-info').innerHTML='${_("Are you sure you want to unenroll from")}'; document.getElementById('refund-info').innerHTML=''">
${_('Unenroll')}
</a>
% endif
% elif show_refund_option:
## Translators: The course's name will be added to the end of this sentence.
% if not is_course_blocked:
<a href="#unenroll-modal" class="unenroll" rel="leanModal" data-course-id="${course.id | h}" data-course-number="${course.number | h}" onclick="document.getElementById('track-info').innerHTML='${_("Are you sure you want to unenroll from the verified {cert_name_long} track of").format(cert_name_long=cert_name_long)}';
document.getElementById('refund-info').innerHTML=gettext('You will be refunded the amount you paid.')">
${_('Unenroll')}
</a>
% else:
<a class="disable-look-unregister" data-course-id="${course.id | h}" data-course-number="${course.number | h}" onclick="document.getElementById('track-info').innerHTML='${_("Are you sure you want to unenroll from the verified {cert_name_long} track of").format(cert_name_long=cert_name_long)}';
document.getElementById('refund-info').innerHTML=gettext('You will be refunded the amount you paid.')">
${_('Unenroll')}
</a>
% endif
% else:
## Translators: The course's name will be added to the end of this sentence.
% if not is_course_blocked:
<a href="#unenroll-modal" class="unenroll" rel="leanModal" data-course-id="${course.id | h}" data-course-number="${course.number | h}" onclick="document.getElementById('track-info').innerHTML='${_("Are you sure you want to unenroll from the verified {cert_name_long} track of").format(cert_name_long=cert_name_long)}';
document.getElementById('refund-info').innerHTML=gettext('The refund deadline for this course has passed, so you will not receive a refund.')">
${_('Unenroll')}
</a>
% else:
<a class="disable-look-unregister" data-course-id="${course.id | h}" data-course-number="${course.number | h}" onclick="document.getElementById('track-info').innerHTML='${_("Are you sure you want to unenroll from the verified {cert_name_long} track of").format(cert_name_long=cert_name_long)}';
document.getElementById('refund-info').innerHTML=gettext('The refund deadline for this course has passed, so you will not receive a refund.')">
${_('Unenroll')}
</a>
% endif
% endif
% if show_email_settings:
% if not is_course_blocked:
<a href="#email-settings-modal" class="email-settings" rel="leanModal" data-course-id="${course.id | h}" data-course-number="${course.number | h}" data-optout="${unicode(course.id) in course_optouts}">${_('Email Settings')}</a>
% else:
<a class="disable-look-settings" data-course-id="${course.id| h}" data-course-number="${course.number | h}" data-optout="${unicode(course.id) in course_optouts}">${_('Email Settings')}</a>
% if course_requirements:
## Multiple pre-requisite courses are not supported on frontend that's why we are pulling first element
<% prc_target = reverse('about_course', args=[unicode(course_requirements['courses'][0]['key'])]) %>
<li class="prerequisites">
<p class="tip">
${_("You must successfully complete {link_start}{prc_display}{link_end} before you begin this course.").format(
link_start='<a href="{}">'.format(prc_target),
link_end='</a>',
prc_display=course_requirements['courses'][0]['display'],
)}
</p>
</li>
% endif
% endif
</section>
% if course_requirements:
## Multiple pre-requisite courses are not supported on frontend that's why we are pulling first element
<% prc_target = reverse('about_course', args=[unicode(course_requirements['courses'][0]['key'])]) %>
<section class="prerequisites">
<p class="tip">
${_("You must successfully complete {link_start}{prc_display}{link_end} before you begin this course.").format(
link_start='<a href="{}">'.format(prc_target),
link_end='</a>',
prc_display=course_requirements['courses'][0]['display'],
)}
</p>
</section>
% endif
</article>
</ul>
</footer>
</article>
</li>
<script>
<script>
$( document ).ready(function() {
if("${is_course_blocked}" == "True"){
......@@ -306,4 +321,4 @@ from student.helpers import (
});
}
});
</script>
</script>
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