Commit 241b4eb0 by David Ormsbee

Merge pull request #1196 from MITx/feature/rocha/change-courses-layout

New Layout for course listings with new course graphical overlay
parents 02151d39 8ac89c39
......@@ -40,7 +40,7 @@ from xmodule.modulestore.exceptions import ItemNotFoundError
from datetime import date
from collections import namedtuple
from courseware.courses import get_courses_by_university
from courseware.courses import get_courses_by_start_date
from courseware.access import has_access
from statsd import statsd
......@@ -74,16 +74,17 @@ def index(request, extra_context={}, user=None):
domain = settings.MITX_FEATURES.get('FORCE_UNIVERSITY_DOMAIN') # normally False
if domain==False: # do explicit check, because domain=None is valid
domain = request.META.get('HTTP_HOST')
universities = get_courses_by_university(None,
domain=domain)
courses = get_courses_by_start_date(None, domain=domain)
# Get the 3 most recent news
top_news = _get_news(top=3)
context = {'universities': universities, 'news': top_news}
context = {'courses': courses, 'news': top_news}
context.update(extra_context)
return render_to_response('index.html', context)
def course_from_id(course_id):
"""Return the CourseDescriptor corresponding to this course_id"""
course_loc = CourseDescriptor.id_to_location(course_id)
......
......@@ -217,11 +217,67 @@ def get_courses_by_university(user, domain=None):
'''
# TODO: Clean up how 'error' is done.
# filter out any courses that errored.
visible_courses = branding.get_visible_courses(domain)
visible_courses = get_courses(user, domain)
universities = defaultdict(list)
for course in visible_courses:
if not has_access(user, course, 'see_exists'):
continue
universities[course.org].append(course)
return universities
def get_courses(user, domain=None):
'''
Returns a list of courses available, sorted by course.number
'''
courses = branding.get_visible_courses(domain)
courses = [c for c in courses if has_access(user, c, 'see_exists')]
return courses
def get_courses_by_start_date(user, domain=None):
"""
Returns a list of courses available, sorted by start date
"""
visible_courses = get_courses(user, domain)
courses = _sort_courses_and_mark_new(visible_courses)
return courses
def _sort_courses_and_mark_new(courses):
"""Sort by course start date and mark which have not started yet"""
for course in courses:
days_to_start = _get_course_days_to_start(course)
metadata = course.metadata
metadata['days_to_start'] = days_to_start
metadata['is_new'] = course.metadata.get('is_new', days_to_start > 1)
key = lambda c: c.metadata['days_to_start']
courses = sorted(courses, key=key, reverse=True)
return courses
def _get_course_days_to_start(course):
from datetime import datetime as dt
from time import mktime, gmtime
convert_to_datetime = lambda ts: dt.fromtimestamp(mktime(ts))
start_date = convert_to_datetime(course.start)
# If the course has a valid advertised date, use that instead
advertised_start = course.metadata.get('advertised_start', None)
if advertised_start:
try:
start_date = dt.strptime(advertised_start, "%Y-%m-%dT%H:%M")
except ValueError:
pass # Invalid date, keep using course.start
now = convert_to_datetime(gmtime())
days_to_start = (start_date - now).days
return days_to_start
......@@ -17,7 +17,7 @@ from django.views.decorators.cache import cache_control
from courseware import grades
from courseware.access import has_access
from courseware.courses import (get_course_with_access, get_courses_by_university)
from courseware.courses import (get_course_with_access, get_courses_by_start_date)
import courseware.tabs as tabs
from courseware.models import StudentModuleCache
from module_render import toc_for_course, get_module, get_instance_module
......@@ -68,9 +68,9 @@ def courses(request):
'''
Render "find courses" page. The course selection work is done in courseware.courses.
'''
universities = get_courses_by_university(request.user,
courses = get_courses_by_start_date(request.user,
domain=request.META.get('HTTP_HOST'))
return render_to_response("courseware/courses.html", {'universities': universities})
return render_to_response("courseware/courses.html", {'courses': courses})
def render_accordion(request, course, chapter, section):
......@@ -317,7 +317,7 @@ def jump_to(request, course_id, location):
except NoPathToItem:
raise Http404("This location is not in any class: {0}".format(location))
# choose the appropriate view (and provide the necessary args) based on the
# choose the appropriate view (and provide the necessary args) based on the
# args provided by the redirect.
# Rely on index to do all error handling and access control.
if chapter is None:
......@@ -328,7 +328,7 @@ def jump_to(request, course_id, location):
return redirect('courseware_section', course_id=course_id, chapter=chapter, section=section)
else:
return redirect('courseware_position', course_id=course_id, chapter=chapter, section=section, position=position)
@ensure_csrf_cookie
def course_info(request, course_id):
"""
......
......@@ -13,6 +13,23 @@
}
}
.courses-listing {
@include clearfix();
margin: 0;
padding: 0;
list-style: none;
.courses-listing-item {
width: flex-grid(4);
margin-right: flex-gutter();
float: left;
&:nth-child(3n+3) {
margin-right: 0;
}
}
}
.course {
background: rgb(250,250,250);
border: 1px solid rgb(180,180,180);
......@@ -24,6 +41,31 @@
width: 100%;
@include transition(all, 0.15s, linear);
.status {
background: $blue;
color: white;
font-size: 10px;
left: 10px;
padding: 2px 10px;
@include border-radius(2px);
position: absolute;
text-transform: uppercase;
top: -6px;
z-index: 100;
}
.status:after {
border-bottom: 6px solid shade($blue, 50%);
border-right: 6px solid transparent;
content: "";
display: block;
height: 0;
position: absolute;
right: -6px;
top: 0;
width: 0;
}
a:hover {
text-decoration: none;
}
......
......@@ -5,6 +5,9 @@
%>
<%page args="course" />
<article id="${course.id}" class="course">
%if course.metadata['is_new']:
<span class="status">New</span>
%endif
<a href="${reverse('about_course', args=[course.id])}">
<div class="inner-wrapper">
<header class="course-preview">
......
......@@ -20,21 +20,13 @@
## I'm removing this for now since we aren't using it for the fall.
## <%include file="course_filter.html" />
<section class="courses">
<section class='university-column'>
%for course in universities['MITx']:
<ul class="courses-listing">
%for course in courses:
<li class="courses-listing-item">
<%include file="../course.html" args="course=course" />
</li>
%endfor
</section>
<section class='university-column'>
%for course in universities['HarvardX']:
<%include file="../course.html" args="course=course" />
%endfor
</section>
<section class='university-column last'>
%for course in universities['BerkeleyX']:
<%include file="../course.html" args="course=course" />
%endfor
</section>
</ul>
</section>
</section>
</section>
......@@ -106,21 +106,13 @@
</section>
<section class="courses">
<section class='university-column'>
%for course in universities['MITx']:
<%include file="course.html" args="course=course" />
<ul class="courses-listing">
%for course in courses:
<li class="courses-listing-item">
<%include file="course.html" args="course=course" />
</li>
%endfor
</section>
<section class='university-column'>
%for course in universities['HarvardX']:
<%include file="course.html" args="course=course" />
%endfor
</section>
<section class='university-column last'>
%for course in universities['BerkeleyX']:
<%include file="course.html" args="course=course" />
%endfor
</section>
</ul>
</section>
</section>
</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