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): ...@@ -40,9 +40,9 @@ class TestStudentDashboardEmailView(ModuleStoreTestCase):
self.url = reverse('dashboard') self.url = reverse('dashboard')
# URL for email settings modal # URL for email settings modal
self.email_modal_link = ( 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-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( ).format(
org=self.course.org, org=self.course.org,
num=self.course.number, num=self.course.number,
...@@ -111,9 +111,9 @@ class TestStudentDashboardEmailViewXMLBacked(ModuleStoreTestCase): ...@@ -111,9 +111,9 @@ class TestStudentDashboardEmailViewXMLBacked(ModuleStoreTestCase):
# URL for email settings modal # URL for email settings modal
self.email_modal_link = ( 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-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( ).format(
org='edX', org='edX',
num='toy', num='toy',
......
...@@ -45,11 +45,9 @@ class DashboardPage(PageObject): ...@@ -45,11 +45,9 @@ class DashboardPage(PageObject):
Return list of the names of available courses (e.g. "999 edX Demonstration Course") Return list of the names of available courses (e.g. "999 edX Demonstration Course")
""" """
def _get_course_name(el): def _get_course_name(el):
# The first component in the link text is the course number return el.text
_, course_name = el.text.split(' ', 1)
return course_name
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 @property
def full_name(self): def full_name(self):
...@@ -64,7 +62,7 @@ class DashboardPage(PageObject): ...@@ -64,7 +62,7 @@ class DashboardPage(PageObject):
@property @property
def username(self): def username(self):
"""Return the displayed value for the user's username""" """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): def get_enrollment_mode(self, course_name):
"""Get the enrollment mode for a given course on the dashboard. """Get the enrollment mode for a given course on the dashboard.
...@@ -113,7 +111,7 @@ class DashboardPage(PageObject): ...@@ -113,7 +111,7 @@ class DashboardPage(PageObject):
el = course_listing[0] el = course_listing[0]
# Expand the upsell copy and click the upgrade button # 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() el.find_element_by_css_selector('#upgrade-to-verified').click()
upgrade_page.wait_for_page() upgrade_page.wait_for_page()
...@@ -176,4 +174,4 @@ class DashboardPage(PageObject): ...@@ -176,4 +174,4 @@ class DashboardPage(PageObject):
""" """
Verify if pre-requisite course messages are being displayed. 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): ...@@ -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 "([^"]*)"') @step(u'I unenroll from the course numbered "([^"]*)"')
def i_unenroll_from_that_course(_step, course): 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) world.css_click(unregister_css)
button_css = 'section#unenroll-modal input[value="Unenroll"]' button_css = 'section#unenroll-modal input[value="Unenroll"]'
assert world.is_css_present(button_css)
world.css_click(button_css) world.css_click(button_css)
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
} }
$('.message.is-expandable .wrapper-tip').bind('click', toggleExpandMessage); $('.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 // 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 // a `track` call whenever a bound link is clicked. Usually the page would change before
...@@ -95,6 +96,29 @@ ...@@ -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() { $("#failed-verification-button-dismiss").click(function() {
$.ajax({ $.ajax({
url: urls.verifyToggleBannerFailedOff, url: urls.verifyToggleBannerFailedOff,
...@@ -110,7 +134,7 @@ ...@@ -110,7 +134,7 @@
Logger.log('edx.course.enrollment.upgrade.clicked', [user, course], null); 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_id").val( $(event.target).data("course-id") );
$("#email_settings_course_number").text( $(event.target).data("course-number") ); $("#email_settings_course_number").text( $(event.target).data("course-number") );
if($(event.target).data("optout") === "False") { if($(event.target).data("optout") === "False") {
...@@ -118,7 +142,7 @@ ...@@ -118,7 +142,7 @@
} }
}); });
$(".unenroll").click(function(event) { $(".action-unenroll").click(function(event) {
$("#unenroll_course_id").val( $(event.target).data("course-id") ); $("#unenroll_course_id").val( $(event.target).data("course-id") );
$("#unenroll_course_number").text( $(event.target).data("course-number") ); $("#unenroll_course_number").text( $(event.target).data("course-number") );
}); });
...@@ -235,8 +259,8 @@ ...@@ -235,8 +259,8 @@
"#dashboard-main" "#dashboard-main"
); );
$(".email-settings").each(function(index){ $(".action-email-settings").each(function(index){
$(this).attr("id", "unenroll-" + index); $(this).attr("id", "email-settings-" + index);
// a bit of a hack, but gets the unique selector for the modal trigger // a bit of a hack, but gets the unique selector for the modal trigger
var trigger = "#" + $(this).attr("id"); var trigger = "#" + $(this).attr("id");
accessibleModal( accessibleModal(
...@@ -247,8 +271,8 @@ ...@@ -247,8 +271,8 @@
); );
}); });
$(".unenroll").each(function(index){ $(".action-unenroll").each(function(index){
$(this).attr("id", "email-settings-" + index); $(this).attr("id", "unenroll-" + index);
// a bit of a hack, but gets the unique selector for the modal trigger // a bit of a hack, but gets the unique selector for the modal trigger
var trigger = "#" + $(this).attr("id"); var trigger = "#" + $(this).attr("id");
accessibleModal( accessibleModal(
......
...@@ -258,13 +258,6 @@ footer .references { ...@@ -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 // 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 { .course-content .discussion-post.edit-post-form .topic-menu {
padding-left: 0; padding-left: 0;
......
...@@ -128,7 +128,7 @@ a:focus { ...@@ -128,7 +128,7 @@ a:focus {
@include clearfix(); @include clearfix();
@include box-sizing(border-box); @include box-sizing(border-box);
margin: 0 auto 0; margin: 0 auto 0;
padding: 0 ($baseline*1.5); padding: ($baseline*2) 0;
max-width: grid-width(12); max-width: grid-width(12);
min-width: 760px; min-width: 760px;
width: flex-grid(12); width: flex-grid(12);
......
...@@ -120,3 +120,11 @@ ...@@ -120,3 +120,11 @@
padding: ($baseline/5) ($baseline/2); padding: ($baseline/5) ($baseline/2);
color: shade($warning-color, 45%); 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%); ...@@ -133,6 +133,11 @@ $green-u1: desaturate($green,15%);
$green-u2: desaturate($green,30%); $green-u2: desaturate($green,30%);
$green-u3: desaturate($green,45%); $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. // 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); $blue: rgb(29,157,217);
$yellow: rgb(255, 252, 221); $yellow: rgb(255, 252, 221);
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
} }
%t-title3 { %t-title3 {
@extend %t-title;
@include font-size(36); @include font-size(36);
@include line-height(36); @include line-height(36);
} }
......
...@@ -117,7 +117,7 @@ header.global { ...@@ -117,7 +117,7 @@ header.global {
.user { .user {
@include float(right); @include float(right);
margin-top: 4px; margin-top: ($baseline/4);
> .primary { > .primary {
display: block; display: block;
...@@ -135,7 +135,7 @@ header.global { ...@@ -135,7 +135,7 @@ header.global {
> a { > a {
@include border-radius(0, 4px, 4px, 0); @include border-radius(0, 4px, 4px, 0);
@include border-left(none); @include border-left(none);
padding: 3px 8px 9px 8px; padding: ($baseline/4) 8px 11px ($baseline/2);
&.shopping-cart { &.shopping-cart {
border-radius: 4px; border-radius: 4px;
...@@ -148,7 +148,7 @@ header.global { ...@@ -148,7 +148,7 @@ header.global {
} }
a.user-link { a.user-link {
@include padding(3px, 12px, 8px, 8px); @include padding(5px, 12px, 10px, 10px);
position: relative; position: relative;
text-transform: none; text-transform: none;
font-size: 14px; font-size: 14px;
...@@ -196,17 +196,17 @@ header.global { ...@@ -196,17 +196,17 @@ header.global {
} }
.dropdown-menu { .dropdown-menu {
background: $border-color-4; background: $white;
border-radius: 4px; border-radius: 4px;
box-shadow: 0 2px 24px 0 rgba(0,0,0, 0.3); box-shadow: 0 2px 2px 0 rgba(0,0,0, 0.3);
border: 1px solid $border-color-3; border: 1px solid $gray-l3;
display: none; display: none;
margin-top: 0; margin-top: 0;
padding: 5px 10px; padding: 5px 10px;
position: absolute; position: absolute;
@include right(0px); @include right(0px);
top: 34px; top: 37px;
width: 170px; min-width: 120px;
z-index: 3; z-index: 3;
&.expanded { &.expanded {
...@@ -221,14 +221,14 @@ header.global { ...@@ -221,14 +221,14 @@ header.global {
bottom: 6px solid transparent; bottom: 6px solid transparent;
left: 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: ""; content: "";
display: block; display: block;
height: 0px; height: 0px;
position: absolute; position: absolute;
@include transform(rotate(-45deg)); @include transform(rotate(-45deg));
@include right(7px); @include right(7px);
top: -6px; top: -5px;
width: 0px; width: 0px;
} }
...@@ -579,7 +579,7 @@ header.global-new { ...@@ -579,7 +579,7 @@ header.global-new {
li { li {
display: block; 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); box-shadow: inset 0 1px 0 0 rgba(255,255,255, 0.05);
&:first-child { &:first-child {
......
...@@ -74,10 +74,59 @@ ...@@ -74,10 +74,59 @@
</div> </div>
<section class="container dashboard" id="dashboard-main"> <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"> <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> </header>
<section class="user-info"> <section class="user-info">
<ul> <ul>
...@@ -119,7 +168,6 @@ ...@@ -119,7 +168,6 @@
<span class="provider">${state.provider.NAME}</span> <span class="provider">${state.provider.NAME}</span>
<span class="control"> <span class="control">
% if state.has_account: % if state.has_account:
<form <form
action="${pipeline.get_disconnect_url(state.provider.NAME)}" action="${pipeline.get_disconnect_url(state.provider.NAME)}"
...@@ -128,20 +176,21 @@ ...@@ -128,20 +176,21 @@
<input type="hidden" name="csrfmiddlewaretoken" value="${csrf_token}"> <input type="hidden" name="csrfmiddlewaretoken" value="${csrf_token}">
<a href="#" onclick="document.${state.get_unlink_form_name()}.submit()"> <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). ## 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")} ${_("Unlink")}
</a> </a>
% else: </form>
% else:
<a href="${pipeline.get_login_url(state.provider.NAME, pipeline.AUTH_ENTRY_DASHBOARD, redirect_url='/')}"> <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). ## 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")} ${_("Link")}
</a> </a>
% endif % endif
</form>
</span> </span>
</div> </div>
% endfor % endfor
</span>
</span> </span>
</li> </li>
% endif % endif
...@@ -171,58 +220,6 @@ ...@@ -171,58 +220,6 @@
</ul> </ul>
</section> </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>
</section> </section>
...@@ -257,8 +254,6 @@ ...@@ -257,8 +254,6 @@
</div> </div>
</section> </section>
<section id="password_reset_complete" class="modal" aria-hidden="true"> <section id="password_reset_complete" class="modal" aria-hidden="true">
<div class="inner-wrapper" role="dialog" aria-labelledby="password-reset-email"> <div class="inner-wrapper" role="dialog" aria-labelledby="password-reset-email">
<button class="close-modal"> <button class="close-modal">
......
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