Commit 939a3672 by marjev Committed by Marko Jevtic

(SOL-531)(SOL-532)Course Cards update; A link to course discovery page has been…

(SOL-531)(SOL-532)Course Cards update; A link to course discovery page has been added to the OpenEdX homepage
parent 4ec713e9
......@@ -202,9 +202,9 @@ class IndexPageCourseCardsSortingTests(ModuleStoreTestCase):
((template, context), _) = RENDER_MOCK.call_args # pylint: disable=unpacking-non-sequence
self.assertEqual(template, 'index.html')
# Now the courses will be stored in their announcement dates.
self.assertEqual(context['courses'][0].id, self.starting_later.id)
self.assertEqual(context['courses'][1].id, self.starting_earlier.id)
# by default the courses will be sorted by their creation dates, earliest first.
self.assertEqual(context['courses'][0].id, self.starting_earlier.id)
self.assertEqual(context['courses'][1].id, self.starting_later.id)
self.assertEqual(context['courses'][2].id, self.course_with_default_start_date.id)
# check the /courses view
......@@ -213,23 +213,23 @@ class IndexPageCourseCardsSortingTests(ModuleStoreTestCase):
((template, context), _) = RENDER_MOCK.call_args # pylint: disable=unpacking-non-sequence
self.assertEqual(template, 'courseware/courses.html')
# Now the courses will be stored in their announcement dates.
self.assertEqual(context['courses'][0].id, self.starting_later.id)
self.assertEqual(context['courses'][1].id, self.starting_earlier.id)
# by default the courses will be sorted by their creation dates, earliest first.
self.assertEqual(context['courses'][0].id, self.starting_earlier.id)
self.assertEqual(context['courses'][1].id, self.starting_later.id)
self.assertEqual(context['courses'][2].id, self.course_with_default_start_date.id)
@patch('student.views.render_to_response', RENDER_MOCK)
@patch('courseware.views.render_to_response', RENDER_MOCK)
@patch.dict('django.conf.settings.FEATURES', {'ENABLE_COURSE_SORTING_BY_START_DATE': True})
def test_course_cards_sorted_by_start_date_show_earliest_first(self):
@patch.dict('django.conf.settings.FEATURES', {'ENABLE_COURSE_SORTING_BY_START_DATE': False})
def test_course_cards_sorted_by_start_date_disabled(self):
response = self.client.get('/')
self.assertEqual(response.status_code, 200)
((template, context), _) = RENDER_MOCK.call_args # pylint: disable=unpacking-non-sequence
self.assertEqual(template, 'index.html')
# now the courses will be sorted by their creation dates, earliest first.
self.assertEqual(context['courses'][0].id, self.starting_earlier.id)
self.assertEqual(context['courses'][1].id, self.starting_later.id)
# now the courses will be sorted by their announcement dates.
self.assertEqual(context['courses'][0].id, self.starting_later.id)
self.assertEqual(context['courses'][1].id, self.starting_earlier.id)
self.assertEqual(context['courses'][2].id, self.course_with_default_start_date.id)
# check the /courses view as well
......@@ -238,7 +238,7 @@ class IndexPageCourseCardsSortingTests(ModuleStoreTestCase):
((template, context), _) = RENDER_MOCK.call_args # pylint: disable=unpacking-non-sequence
self.assertEqual(template, 'courseware/courses.html')
# now the courses will be sorted by their creation dates, earliest first.
self.assertEqual(context['courses'][0].id, self.starting_earlier.id)
self.assertEqual(context['courses'][1].id, self.starting_later.id)
# now the courses will be sorted by their announcement dates.
self.assertEqual(context['courses'][0].id, self.starting_later.id)
self.assertEqual(context['courses'][1].id, self.starting_earlier.id)
self.assertEqual(context['courses'][2].id, self.course_with_default_start_date.id)
......@@ -383,7 +383,11 @@ def sort_by_start_date(courses):
"""
Returns a list of courses sorted by their start date, latest first.
"""
courses = sorted(courses, key=lambda course: (course.start is None, course.start), reverse=False)
courses = sorted(
courses,
key=lambda course: (course.has_ended(), course.start is None, course.start),
reverse=False
)
return courses
......
......@@ -308,7 +308,7 @@ FEATURES = {
# When a user goes to the homepage ('/') the user see the
# courses listed in the announcement dates order - this is default Open edX behavior.
# Set to True to change the course sorting behavior by their start dates, latest first.
'ENABLE_COURSE_SORTING_BY_START_DATE': False,
'ENABLE_COURSE_SORTING_BY_START_DATE': True,
# Flag to enable new user account APIs.
'ENABLE_USER_REST_API': False,
......
......@@ -47,6 +47,7 @@
@import 'views/verification';
@import 'views/shoppingcart';
@import 'views/login-register';
@import 'views/homepage';
// applications
@import "discussion/utilities/variables";
......
......@@ -49,6 +49,7 @@
@import 'views/verification';
@import 'views/decoupled-verification';
@import 'views/shoppingcart';
@import 'views/homepage';
@import 'course/auto-cert';
// applications
......
......@@ -4,10 +4,13 @@
$max-width: 1200px;
/* Override the default global box-sizing */
$border-box-sizing: false;
/* Grid width variables */
$large-min-width: 769px;
/* Breakpoints */
$mobile: new-breakpoint(max-width 320px 4);
$tablet: new-breakpoint(min-width 321px max-width 768px, 8);
$desktop: new-breakpoint(min-width 769px 12);
$xl-desktop: new-breakpoint(min-width 980px 12);
$bp-tiny: new-breakpoint(max-width 320px 4);
$bp-small: new-breakpoint(min-width 321px max-width 540px, 4);
$bp-medium: new-breakpoint(min-width 541px max-width 768px, 8);
$bp-large: new-breakpoint(min-width $large-min-width max-width 979px, 12);
$bp-huge: new-breakpoint(min-width 980px 12);
......@@ -13,23 +13,6 @@
}
}
.courses-listing {
@include clearfix();
margin: 0;
padding: 0;
list-style: none;
.courses-listing-item {
width: flex-grid(4);
@include margin-right(flex-gutter());
@include float(left);
&:nth-child(3n+3) {
@include margin-right(0);
}
}
}
.course {
background: $body-bg;
border: 1px solid $border-color-1;
......
......@@ -446,10 +446,10 @@ $edx-footer-bg-color: rgb(252,252,252);
@include span-columns(12);
}
@include media( $tablet ) {
@include media( $bp-medium ) {
}
@include media( $desktop ) {
@include media( $bp-large ) {
.footer-about {
@include span-columns(6);
}
......
......@@ -765,7 +765,7 @@ header.global-new {
}
}
@include media( $desktop ) {
@include media( $bp-large ) {
.wrapper-header {
width: 100%;
min-width: 800px;
......@@ -828,7 +828,7 @@ header.global-new {
}
}
@include media( $xl-desktop ) {
@include media( $bp-huge ) {
.wrapper-header {
padding: 17px 0;
}
......
// lms - views - homepage view
// ====================
$course-card-height: ($baseline*18);
$course-image-height: ($baseline*8);
$course-info-height: ($baseline*10);
$course-title-height: ($baseline*3.6);
$learn-more-horizontal-position: calc(50% - 100px); // calculate the left position for "LEARN MORE" content
.courses-container {
@include outer-container;
padding: ($baseline*0.9) ($baseline/2) 0 ($baseline/2);
.courses {
@include row();
.courses-listing {
@extend %ui-no-list;
.courses-listing-item {
@include fill-parent();
max-height: $course-card-height;
margin: ($baseline*0.75) 0 ($baseline*1.5) 0;
@include media($bp-medium) {
@include span-columns(4); // 4 of 8
@include omega(2n);
}
@include media($bp-large) {
@include span-columns(4); // 4 of 12
@include omega(3n);
}
@include media($bp-huge) {
@include span-columns(3); // 3 of 12
@include omega(4n);
}
}
}
.course {
@include box-sizing(border-box);
@include transition(all $tmg-f3 linear 0s);
position: relative;
border-bottom: 3px solid $action-primary-bg;
box-shadow: 0 1px 10px 0 $black-t0, inset 0 0 0 1px $white-t3;
background: $body-bg;
width: 100%;
.course-image .cover-image {
height: $course-image-height;
overflow: hidden;
// places the shadow on top of the course image while hovering over the course card
&:before {
@include left(0);
@extend %ui-depth1;
position: absolute;
top: 0;
opacity: 0;
background: $black;
width: 100%;
height: $course-image-height;
content: '';
}
img {
width: 100%;
height: auto;
}
.learn-more {
@include left($learn-more-horizontal-position);
@include box-sizing(border-box);
@include line-height(28);
@extend %ui-depth2;
position: absolute;
top: ($baseline*2.75);
opacity: 0;
border: 3px solid $white;
border-radius: 3px;
padding: 0 $baseline;
width: ($baseline*10);
height: ($baseline*2.5);
text-align: center;
color: $white;
}
}
.course-info {
height: $course-info-height;
.course-organization, .course-code, .course-date {
@extend %t-icon6;
color: $black;
}
.course-organization, .course-code, .course-title {
display: block;
}
.course-organization {
@include line-height(11);
padding: ($baseline/2) ($baseline*0.75) ($baseline/10) ($baseline*0.75);
}
.course-code {
@include line-height(16);
padding: 0 ($baseline*0.75);
}
.course-title {
@include line-height(16);
@extend %t-icon4;
margin: ($baseline*0.25) 0 ($baseline*1.75) 0;
padding: 0 ($baseline*0.75);
height: $course-title-height;
color: $link-color;
}
.course-date {
@include line-height(14);
padding: ($baseline/10) ($baseline*0.75);
}
}
// STATE: hover and focus
&:hover,
&:focus {
.cover-image {
&:before {
@include transition(opacity $tmg-f2 ease-out $tmg-f2);
opacity: 0.6;
}
.learn-more {
@include transition(opacity $tmg-f2 ease-out $tmg-f2);
opacity: 1;
}
}
}
}
}
.courses-more {
@include margin-right(0);
text-align: center;
@include media($large-min-width) {
@include margin-right($baseline*0.5);
@include text-align(right);
}
.courses-more-cta {
font-weight: $font-semibold;
&:after {
content: " ›";
}
}
}
}
......@@ -1420,7 +1420,7 @@
}
}
@include media( $desktop ) {
@include media( $bp-large ) {
.contribution-options {
.field {
width: auto;
......@@ -1443,7 +1443,7 @@
}
}
@include media( $xl-desktop ) {
@include media( $bp-huge ) {
.register-choice {
.list-actions {
float: right;
......
......@@ -5,35 +5,28 @@ from django.core.urlresolvers import reverse
from courseware.courses import course_image_url, get_course_about_section
%>
<%page args="course" />
<article id="${course.id | h}" class="course">
%if course.is_newish:
<span class="status">${_("New")}</span>
%endif
<article class="course" id="${course.id | h}" role="region" aria-label="${get_course_about_section(course, 'title')}">
<a href="${reverse('about_course', args=[course.id.to_deprecated_string()])}">
<div class="inner-wrapper">
<header class="course-preview">
<hgroup>
<h2><span class="course-number">${course.display_number_with_default | h}</span> ${get_course_about_section(course, 'title')}</h2>
</hgroup>
<div class="info-link">&#x2794;</div>
</header>
<section class="info">
<div class="cover-image">
<img src="${course_image_url(course)}" alt="${course.display_number_with_default | h} ${get_course_about_section(course, 'title')} Cover Image" />
</div>
<div class="desc">
<p>${get_course_about_section(course, 'short_description')}</p>
</div>
<div class="bottom">
<span class="university">${get_course_about_section(course, 'university')}</span>
% if not course.start_date_is_still_default:
<span class="start-date">${course.start_datetime_text()}</span>
% endif
</div>
</section>
</div>
<div class="meta-info">
<p class="university">${get_course_about_section(course, 'university')}</p>
<header class="course-image">
<div class="cover-image">
<img src="${course_image_url(course)}" alt="${get_course_about_section(course, 'title')} ${course.display_number_with_default}" />
<div class="learn-more" aria-hidden=true>${_("LEARN MORE")}</div>
</div>
</header>
<section class="course-info" aria-hidden=true>
<h2 class="course-name">
<span class="course-organization">${get_course_about_section(course, 'university')}</span>
<span class="course-code">${course.display_number_with_default}</span>
<span class="course-title">${get_course_about_section(course, 'title')}</span>
</h2>
<div class="course-date" aria-hidden="true">${_("Starts")}: ${course.start_datetime_text()}</div>
</section>
<div class="sr">
<ul>
<li>${get_course_about_section(course, 'university')}</li>
<li>${course.display_number_with_default}</li>
<li>${_("Starts")}: <time itemprop="startDate" datetime="${course.start_datetime_text()}">${course.start_datetime_text()}</time></li>
</ul>
</div>
</a>
</article>
<%!
<%!
from django.utils.translation import ugettext as _
from microsite_configuration import microsite
%>
......@@ -44,7 +44,7 @@
</div>
</header>
<section class="container">
<section class="courses-container">
<section class="courses">
<ul class="courses-listing">
%for course in courses:
......
......@@ -48,19 +48,23 @@
% endif
</div>
</header>
<section class="container">
<section class="courses-container">
<section class="highlighted-courses">
% if settings.FEATURES.get('COURSES_ARE_BROWSABLE'):
<section class="courses">
<ul class="courses-listing">
%for course in courses:
## cap for showing 9 or less courses
%for course in courses[:9]:
<li class="courses-listing-item">
<%include file="course.html" args="course=course" />
</li>
%endfor
</ul>
</section>
<div class="courses-more">
<a class="courses-more-cta" href="${marketing_link('COURSES')}" > ${_("View all Courses")} </a>
</div>
% endif
</section>
......
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