Commit 24045999 by Bridger Maxwell

Merge remote-tracking branch 'origin/master' into course_start

Conflicts:
	common/lib/xmodule/xmodule/course_module.py
	lms/urls.py
parents 9e16e85d 836f6df5
......@@ -4,45 +4,165 @@ from django.test import TestCase
from mock import patch, Mock
from override_settings import override_settings
from django.conf import settings
from django.core.urlresolvers import reverse
from student.models import Registration
from django.contrib.auth.models import User
def parse_json(response):
"""Parse response, which is assumed to be json"""
return json.loads(response.content)
def user(email):
'''look up a user by email'''
return User.objects.get(email=email)
def registration(email):
'''look up registration object by email'''
return Registration.objects.get(user__email=email)
class AuthTestCase(TestCase):
"""Check that various permissions-related things work"""
def test_index(self):
"""Make sure the main page loads."""
resp = self.client.get('/')
self.assertEqual(resp.status_code, 200)
def setUp(self):
self.email = 'a@b.com'
self.pw = 'xyz'
self.username = 'testuser'
def test_signup_load(self):
"""Make sure the signup page loads."""
resp = self.client.get('/signup')
self.assertEqual(resp.status_code, 200)
def check_page_get(self, url, expected):
resp = self.client.get(url)
self.assertEqual(resp.status_code, expected)
return resp
def test_public_pages_load(self):
"""Make sure pages that don't require login load without error."""
pages = (
reverse('login'),
reverse('signup'),
)
for page in pages:
print "Checking '{0}'".format(page)
self.check_page_get(page, 200)
def test_create_account(self):
def test_create_account_errors(self):
# No post data -- should fail
resp = self.client.post('/create_account', {})
self.assertEqual(resp.status_code, 200)
data = parse_json(resp)
self.assertEqual(data['success'], False)
# Should work
def _create_account(self, username, email, pw):
'''Try to create an account. No error checking'''
resp = self.client.post('/create_account', {
'username': 'user',
'email': 'a@b.com',
'password': 'xyz',
'username': username,
'email': email,
'password': pw,
'location' : 'home',
'language' : 'Franglish',
'name' : 'Fred Weasley',
'terms_of_service' : 'true',
'honor_code' : 'true'})
return resp
def create_account(self, username, email, pw):
'''Create the account and check that it worked'''
resp = self._create_account(username, email, pw)
self.assertEqual(resp.status_code, 200)
data = parse_json(resp)
self.assertEqual(data['success'], True)
# Check both that the user is created, and inactive
self.assertFalse(user(self.email).is_active)
return resp
def _activate_user(self, email):
'''look up the user's activation key in the db, then hit the activate view.
No error checking'''
activation_key = registration(email).activation_key
# and now we try to activate
resp = self.client.get(reverse('activate', kwargs={'key': activation_key}))
return resp
def activate_user(self, email):
resp = self._activate_user(email)
self.assertEqual(resp.status_code, 200)
# Now make sure that the user is now actually activated
self.assertTrue(user(self.email).is_active)
def test_create_account(self):
self.create_account(self.username, self.email, self.pw)
self.activate_user(self.email)
def _login(self, email, pw):
'''Login. View should always return 200. The success/fail is in the
returned json'''
resp = self.client.post(reverse('login_post'),
{'email': email, 'password': pw})
self.assertEqual(resp.status_code, 200)
return resp
def login(self, email, pw):
'''Login, check that it worked.'''
resp = self._login(self.email, self.pw)
data = parse_json(resp)
self.assertTrue(data['success'])
return resp
def test_login(self):
self.create_account(self.username, self.email, self.pw)
# Not activated yet. Login should fail.
resp = self._login(self.email, self.pw)
data = parse_json(resp)
self.assertFalse(data['success'])
self.activate_user(self.email)
# Now login should work
self.login(self.email, self.pw)
def test_private_pages_auth(self):
"""Make sure pages that do require login work."""
auth_pages = (
reverse('index'),
reverse('edit_item'),
reverse('save_item'),
)
# These are pages that should just load when the user is logged in
# (no data needed)
simple_auth_pages = (
reverse('index'),
)
# need an activated user
self.test_create_account()
# Not logged in. Should redirect to login.
print 'Not logged in'
for page in auth_pages:
print "Checking '{0}'".format(page)
self.check_page_get(page, expected=302)
# Logged in should work.
self.login(self.email, self.pw)
print 'Logged in'
for page in simple_auth_pages:
print "Checking '{0}'".format(page)
self.check_page_get(page, expected=200)
def test_index_auth(self):
# not logged in. Should return a redirect.
resp = self.client.get(reverse('index'))
self.assertEqual(resp.status_code, 302)
# Logged in should work.
......@@ -2,6 +2,7 @@ from util.json_request import expect_json
import json
from django.http import HttpResponse
from django.contrib.auth.decorators import login_required
from django.core.context_processors import csrf
from django_future.csrf import ensure_csrf_cookie
from django.core.urlresolvers import reverse
......@@ -13,8 +14,28 @@ from github_sync import export_to_github
from mitxmako.shortcuts import render_to_response
from xmodule.modulestore.django import modulestore
# ==== Public views ==================================================
@ensure_csrf_cookie
def signup(request):
"""
Display the signup form.
"""
csrf_token = csrf(request)['csrf_token']
return render_to_response('signup.html', {'csrf': csrf_token })
@ensure_csrf_cookie
def login_page(request):
"""
Display the login form.
"""
csrf_token = csrf(request)['csrf_token']
return render_to_response('login.html', {'csrf': csrf_token })
# ==== Views for any logged-in user ==================================
@login_required
@ensure_csrf_cookie
def index(request):
courses = modulestore().get_items(['i4x', None, None, 'course', None])
return render_to_response('index.html', {
......@@ -26,26 +47,34 @@ def index(request):
for course in courses]
})
# ==== Views with per-item permissions================================
@ensure_csrf_cookie
def signup(request):
"""
Display the signup form.
"""
csrf_token = csrf(request)['csrf_token']
return render_to_response('signup.html', {'csrf': csrf_token })
def has_access(user, location):
'''Return True if user allowed to access this piece of data'''
# TODO (vshnayder): actually check perms
return user.is_active and user.is_authenticated
@login_required
@ensure_csrf_cookie
def course_index(request, org, course, name):
location = ['i4x', org, course, 'course', name]
if not has_access(request.user, location):
raise Http404 # TODO (vshnayder): better error
# TODO (cpennington): These need to be read in from the active user
course = modulestore().get_item(['i4x', org, course, 'course', name])
course = modulestore().get_item(location)
weeks = course.get_children()
return render_to_response('course_index.html', {'weeks': weeks})
@login_required
def edit_item(request):
item_id = request.GET['id']
item = modulestore().get_item(item_id)
# TODO (vshnayder): change name from id to location in coffee+html as well.
item_location = request.GET['id']
print item_location, request.GET
if not has_access(request.user, item_location):
raise Http404 # TODO (vshnayder): better error
item = modulestore().get_item(item_location)
return render_to_response('unit.html', {
'contents': item.get_html(),
'js_module': item.js_module_name(),
......@@ -54,18 +83,39 @@ def edit_item(request):
})
def user_author_string(user):
'''Get an author string for commits by this user. Format:
first last <email@email.com>.
If the first and last names are blank, uses the username instead.
Assumes that the email is not blank.
'''
f = user.first_name
l = user.last_name
if f == '' and l == '':
f = user.username
return '{first} {last} <{email}>'.format(first=f,
last=l,
email=user.email)
@login_required
@expect_json
def save_item(request):
item_id = request.POST['id']
item_location = request.POST['id']
if not has_access(request.user, item_location):
raise Http404 # TODO (vshnayder): better error
data = json.loads(request.POST['data'])
modulestore().update_item(item_id, data)
modulestore().update_item(item_location, data)
# Export the course back to github
# This uses wildcarding to find the course, which requires handling
# multiple courses returned, but there should only ever be one
course_location = Location(item_id)._replace(category='course', name=None)
course_location = Location(item_location)._replace(
category='course', name=None)
courses = modulestore().get_items(course_location, depth=None)
for course in courses:
export_to_github(course, "CMS Edit")
author_string = user_author_string(request.user)
export_to_github(course, "CMS Edit", author_string)
return HttpResponse(json.dumps({}))
......@@ -38,7 +38,12 @@ def import_from_github(repo_settings):
return git_repo.head.commit.hexsha, module_store.courses[course_dir]
def export_to_github(course, commit_message):
def export_to_github(course, commit_message, author_str=None):
'''
Commit any changes to the specified course with given commit message,
and push to github (if MITX_FEATURES['GITHUB_PUSH'] is True).
If author_str is specified, uses it in the commit.
'''
repo_path = settings.DATA_DIR / course.metadata.get('course_dir', course.location.course)
fs = OSFS(repo_path)
xml = course.export_to_xml(fs)
......@@ -49,6 +54,9 @@ def export_to_github(course, commit_message):
git_repo = Repo(repo_path)
if git_repo.is_dirty():
git_repo.git.add(A=True)
if author_str is not None:
git_repo.git.commit(m=commit_message, author=author_str)
else:
git_repo.git.commit(m=commit_message)
origin = git_repo.remotes.origin
......
......@@ -49,4 +49,4 @@ def github_post_receive(request):
revision, course = import_from_github(repo)
export_to_github(course, repo['path'], "Changes from cms import of revision %s" % revision)
return HttpResponse('Push recieved')
return HttpResponse('Push received')
......@@ -70,6 +70,10 @@ TEMPLATE_DIRS = (
MITX_ROOT_URL = ''
LOGIN_REDIRECT_URL = MITX_ROOT_URL + '/login'
LOGIN_URL = MITX_ROOT_URL + '/login'
TEMPLATE_CONTEXT_PROCESSORS = (
'django.core.context_processors.request',
'django.core.context_processors.static',
......
......@@ -29,39 +29,37 @@ DATABASES = {
}
}
REPO_ROOT = ENV_ROOT / "content"
REPOS = {
'edx4edx': {
'path': REPO_ROOT / "edx4edx",
'path': DATA_DIR / "edx4edx",
'org': 'edx',
'course': 'edx4edx',
'branch': 'for_cms',
'origin': 'git@github.com:MITx/edx4edx.git',
},
'6002x-fall-2012': {
'path': REPO_ROOT / '6002x-fall-2012',
'path': DATA_DIR / '6002x-fall-2012',
'org': 'mit.edu',
'course': '6.002x',
'branch': 'for_cms',
'origin': 'git@github.com:MITx/6002x-fall-2012.git',
},
'6.00x': {
'path': REPO_ROOT / '6.00x',
'path': DATA_DIR / '6.00x',
'org': 'mit.edu',
'course': '6.00x',
'branch': 'for_cms',
'origin': 'git@github.com:MITx/6.00x.git',
},
'7.00x': {
'path': REPO_ROOT / '7.00x',
'path': DATA_DIR / '7.00x',
'org': 'mit.edu',
'course': '7.00x',
'branch': 'for_cms',
'origin': 'git@github.com:MITx/7.00x.git',
},
'3.091x': {
'path': REPO_ROOT / '3.091x',
'path': DATA_DIR / '3.091x',
'org': 'mit.edu',
'course': '3.091x',
'branch': 'for_cms',
......
<%inherit file="marketing.html" />
<%inherit file="base.html" />
<%block name="content">
......@@ -7,8 +7,7 @@
<section class="activation">
<h1>Account already active!</h1>
<p> This account has already been activated. You can log in at
the <a href="/">home page</a>.</p>
<p> This account has already been activated. <a href="/login">Log in here</a>.</p>
</div>
</section>
......
<%inherit file="marketing.html" />
<%inherit file="base.html" />
<%block name="content">
<section class="tos">
<div>
<h1>Activation Complete!</h1>
<p>Thanks for activating your account. You can log in at the <a href="/">home page</a>.</p>
<p>Thanks for activating your account. <a href="/login">Log in here</a>.</p>
</div>
</section>
......
<%inherit file="marketing.html" />
<%inherit file="base.html" />
<%block name="content">
<section class="tos">
......
<form name="login" action="login", method="post">
<input type="hidden" name="csrfmiddlewaretoken" value="${csrf_token}"/>
<%inherit file="base.html" />
<%! from django.core.urlresolvers import reverse %>
<%block name="title">Log in</%block>
% if next is not None:
<input type="hidden" name="next" value="${next}"/>
% endif
<%block name="content">
Username: <input type="text" name="username" />
Possword: <input type="password" name="password" />
<input type="submit" value="Submit" />
</form>
<section class="main-container">
<section class="main-content">
<header>
<h3>Log in</h3>
<hr>
</header>
<form id="login_form" action="login_post" method="post">
<label>E-mail</label>
<input name="email" type="email" placeholder="E-mail">
<label>Password</label>
<input name="password" type="password" placeholder="Password">
<label class="remember-me">
<input name="remember" type="checkbox">
Remember me
</label>
<div class="submit">
<input name="submit" type="submit" value="Submit">
</div>
</form>
<section class="login-extra">
<p>
<span>Not enrolled? <a href="${reverse('signup')}">Sign up.</a></span>
<a href="#" class="pwd-reset">Forgot password?</a>
</p>
</section>
</section>
</section>
<script type="text/javascript">
(function() {
function getCookie(name) {
return $.cookie(name);
}
function postJSON(url, data, callback) {
$.ajax({type:'POST',
url: url,
dataType: 'json',
data: data,
success: callback,
headers : {'X-CSRFToken':getCookie('csrftoken')}
});
}
$('form#login_form').submit(function(e) {
e.preventDefault();
var submit_data = $('#login_form').serialize();
postJSON('/login_post',
submit_data,
function(json) {
if(json.success) {
location.href="${reverse('index')}";
} else if($('#login_error').length == 0) {
$('#login_form').prepend('<div id="login_error">Email or password is incorrect.</div>');
} else {
$('#login_error').stop().css("background-color", "#933").animate({ backgroundColor: "#333"}, 2000);
}
}
);
});
})(this)
</script>
</%block>
<%inherit file="base.html" />
\ No newline at end of file
<h1>Check your email</h1>
<p>An activation link has been sent to ${ email }, along with
instructions for activating your account.</p>
<%! from django.core.urlresolvers import reverse %>
<header>
<nav>
<h2><a href="/">6.002x circuits and electronics</a></h2>
<h2><a href="/">edX CMS: TODO:-course-name-here</a></h2>
<ul>
<li>
<a href="#" class="new-module wip">New Module</a>
......@@ -13,6 +14,12 @@
<ul class="user-nav">
<li><a href="#" class="wip">Tasks</a></li>
<li><a href="#" class="wip">Settings</a></li>
% if user.is_authenticated():
<li><a href="${reverse('logout')}">Log out</a></li>
% else:
<li><a href="${reverse('login')}">Log in</a></li>
% endif
</ul>
</nav>
</header>
......@@ -11,16 +11,25 @@ urlpatterns = ('',
url(r'^$', 'contentstore.views.index', name='index'),
url(r'^edit_item$', 'contentstore.views.edit_item', name='edit_item'),
url(r'^save_item$', 'contentstore.views.save_item', name='save_item'),
url(r'^(?P<org>[^/]+)/(?P<course>[^/]+)/course/(?P<name>[^/]+)$', 'contentstore.views.course_index', name='course_index'),
url(r'^(?P<org>[^/]+)/(?P<course>[^/]+)/course/(?P<name>[^/]+)$',
'contentstore.views.course_index', name='course_index'),
url(r'^github_service_hook$', 'github_sync.views.github_post_receive'),
)
# User creation and updating views
urlpatterns += (
url(r'^signup$', 'contentstore.views.signup'),
url(r'^signup$', 'contentstore.views.signup', name='signup'),
url(r'^create_account$', 'student.views.create_account'),
url(r'^activate/(?P<key>[^/]*)$', 'student.views.activate_account'),
url(r'^activate/(?P<key>[^/]*)$', 'student.views.activate_account', name='activate'),
# form page
url(r'^login$', 'contentstore.views.login_page', name='login'),
# ajax view that actually does the work
url(r'^login_post$', 'student.views.login_user', name='login_post'),
url(r'^logout$', 'student.views.logout_user', name='logout'),
)
if settings.DEBUG:
......
......@@ -147,12 +147,12 @@ def create_account(request, post_override=None):
js['value'] = "Error (401 {field}). E-mail us.".format(field=a)
return HttpResponse(json.dumps(js))
if 'honor_code' not in post_vars or post_vars['honor_code'] != u'true':
if post_vars.get('honor_code', 'false') != u'true':
js['value']="To enroll, you must follow the honor code.".format(field=a)
return HttpResponse(json.dumps(js))
if 'terms_of_service' not in post_vars or post_vars['terms_of_service'] != u'true':
if post_vars.get('terms_of_service', 'false') != u'true':
js['value']="You must accept the terms of service.".format(field=a)
return HttpResponse(json.dumps(js))
......
......@@ -22,6 +22,7 @@ import random
import re
import scipy
import struct
import sys
from lxml import etree
from xml.sax.saxutils import unescape
......@@ -78,7 +79,7 @@ class LoncapaProblem(object):
- id (string): identifier for this problem; often a filename (no spaces)
- state (dict): student state
- seed (int): random number generator seed (int)
- system (I4xSystme): I4xSystem instance which provides OS, rendering, and user context
- system (I4xSystem): I4xSystem instance which provides OS, rendering, and user context
'''
......@@ -196,7 +197,7 @@ class LoncapaProblem(object):
Thus, for example, input_ID123 -> ID123, and input_fromjs_ID123 -> fromjs_ID123
Calles the Response for each question in this problem, to do the actual grading.
Calls the Response for each question in this problem, to do the actual grading.
'''
self.student_answers = answers
oldcmap = self.correct_map # old CorrectMap
......@@ -276,6 +277,34 @@ class LoncapaProblem(object):
parent.remove(inc)
log.debug('Included %s into %s' % (file, self.problem_id))
def _extract_system_path(self, script):
'''
Extracts and normalizes additional paths for code execution.
For now, there's a default path of data/course/code; this may be removed
at some point.
'''
DEFAULT_PATH = ['code']
# Separate paths by :, like the system path.
raw_path = script.get('system_path', '').split(":") + DEFAULT_PATH
# find additional comma-separated modules search path
path = []
for dir in raw_path:
if not dir:
continue
# path is an absolute path or a path relative to the data dir
dir = os.path.join(self.system.filestore.root_path, dir)
abs_dir = os.path.normpath(dir)
log.debug("appending to path: %s" % abs_dir)
path.append(abs_dir)
return path
def _extract_context(self, tree, seed=struct.unpack('i', os.urandom(4))[0]): # private
'''
Extract content of <script>...</script> from the problem.xml file, and exec it in the
......@@ -291,7 +320,20 @@ class LoncapaProblem(object):
context['the_lcp'] = self # pass instance of LoncapaProblem in
context['script_code'] = ''
for script in tree.findall('.//script'):
self._execute_scripts(tree.findall('.//script'), context)
return context
def _execute_scripts(self, scripts, context):
'''
Executes scripts in the given context.
'''
original_path = sys.path
for script in scripts:
sys.path = original_path + self._extract_system_path(script)
stype = script.get('type')
if stype:
if 'javascript' in stype:
......@@ -308,7 +350,8 @@ class LoncapaProblem(object):
except Exception:
log.exception("Error while execing script code: " + code)
raise responsetypes.LoncapaProblemError("Error while executing script code")
return context
finally:
sys.path = original_path
def _extract_html(self, problemtree): # private
'''
......
......@@ -44,6 +44,10 @@ class CourseDescriptor(SequenceDescriptor):
return self.metadata['display_name']
@property
def number(self):
return self.location.course
@property
def instructors(self):
return self.get_about_section("instructors").split("\n")
......@@ -79,7 +83,7 @@ class CourseDescriptor(SequenceDescriptor):
'requirements', 'syllabus', 'textbook', 'faq', 'more_info', 'number', 'instructors']:
try:
with self.system.resources_fs.open(path("about") / section_key + ".html") as htmlFile:
return htmlFile.read()
return htmlFile.read().decode('utf-8')
except ResourceNotFoundError:
log.exception("Missing about section {key} in course {url}".format(key=section_key, url=self.location.url()))
return "! About section missing !"
......@@ -108,7 +112,7 @@ class CourseDescriptor(SequenceDescriptor):
if section_key in ['handouts', 'guest_handouts', 'updates', 'guest_updates']:
try:
with self.system.resources_fs.open(path("info") / section_key + ".html") as htmlFile:
return htmlFile.read()
return htmlFile.read().decode('utf-8')
except ResourceNotFoundError:
log.exception("Missing info section {key} in course {url}".format(key=section_key, url=self.location.url()))
return "! Info section missing !"
......
# Running the CMS
One can start the CMS by running `rake cms`. This will run the server on localhost
port 8001.
However, the server also needs data to work from.
## Installing Mongodb
Please see http://www.mongodb.org/downloads for more detailed instructions.
### Ubuntu
sudo apt-get install mongodb
### OSX
Use the MacPorts package `mongodb` or the Homebrew formula `mongodb`
## Initializing Mongodb
Check out the course data directories that you want to work with into the
`GITHUB_REPO_ROOT` (by default, `../data`). Then run the following command:
rake django-admin[import,cms,dev,../data]
Replace `../data` with your `GITHUB_REPO_ROOT` if it's not the default value.
This will import all courses in your data directory into mongodb
......@@ -108,7 +108,7 @@ environments, defined in `cms/envs`.
- javascript -- we use coffeescript, which compiles to js, and is much nicer to work with. Look for `*.coffee` files. We use _jasmine_ for testing js.
- _mako_ -- we use this for templates, and have a fork called mitxmako (TODO: why did we have to fork mako?)
- _mako_ -- we use this for templates, and have wrapper called mitxmako that makes mako look like the django templating calls.
We use a fork of django-pipeline to make sure that the js and css always reflect the latest `*.coffee` and `*.sass` files (We're hoping to get our changes merged in the official version soon). This works differently in development and production. Test uses the production settings.
......
......@@ -95,7 +95,7 @@ for static_dir in STATICFILES_DIRS:
except ValueError:
data_dir = static_dir
if not data_dir.startswith(REPO_ROOT):
if data_dir.startswith(REPO_ROOT):
new_staticfiles_dirs.append(static_dir)
STATICFILES_DIRS = new_staticfiles_dirs
......
.container.about {
padding: 20px 0 120px;
padding: 20px 10px 120px;
> nav {
margin-bottom: 80px;
......@@ -51,6 +51,7 @@
}
.photo {
@include box-sizing(border-box);
background: rgb(255,255,255);
border: 1px solid rgb(210,210,210);
padding: 1px;
......@@ -64,6 +65,11 @@
}
}
> article {
float: left;
width: flex-grid(8);
}
&.left {
.photo {
float: left;
......
......@@ -24,8 +24,9 @@
@include clearfix;
margin: 0 auto;
max-width: 1200px;
padding: 0px 10px;
position: relative;
width: flex-grid(12);
width: grid-width(12);
z-index: 2;
......@@ -243,12 +244,12 @@
border: 1px solid rgb(200,200,200);
border-top: none;
float: left;
padding: 20px 20px 30px;
padding: 16px 20px 30px;
width: flex-grid(4);
header {
margin-bottom: 30px;
padding-bottom: 20px;
padding-bottom: 16px;
position: relative;
text-align: center;
......@@ -358,18 +359,42 @@
margin-bottom: 20px;
padding-bottom: 10px;
&:hover {
.icon {
opacity: 1;
}
}
p {
color: $lighter-base-font-color;
float: left;
font-family: $sans-serif;
}
img {
background: rgb(230,230,230);
.icon {
background-size: cover;
float: left;
height: 19px;
margin: 3px 10px 0 0;
margin: 2px 10px 0 0;
opacity: 0.6;
@include transition(all, 0.15s, linear);
width: 19px;
&.start-icon {
@include background-image(url('/static/images/portal-icons/calendar-icon.png'));
}
&.final-icon {
@include background-image(url('/static/images/portal-icons/pencil-icon.png'));
}
&.length-icon {
@include background-image(url('/static/images/portal-icons/chart-icon.png'));
}
&.number-icon {
@include background-image(url('/static/images/portal-icons/course-info-icon.png'));
}
}
span {
......
......@@ -4,7 +4,7 @@
header.search {
background: rgb(240,240,240);
@include background-image(url('/static/images/shot-2-large.jpg'));
//@include background-image(url('/static/images/shot-2-large.jpg'));
background-size: cover;
border-bottom: 1px solid rgb(100,100,100);
@include box-shadow(inset 0 -1px 8px 0 rgba(0,0,0, 0.2), inset 0 1px 12px 0 rgba(0,0,0, 0.3));
......
......@@ -30,30 +30,63 @@
> ul {
background: rgb(250,250,250);
border: 1px solid rgb(220,220,220);
border: 1px solid rgb(200,200,200);
border-top: none;
@include border-bottom-radius(4px);
@include box-sizing(border-box);
@include box-shadow(inset 0 0 3px 0 rgba(0,0,0, 0.15));
@include clearfix;
margin: 0px;
padding: 0px 10px 20px;
padding: 20px 10px 10px;
width: flex-grid(12);
li {
@include clearfix;
border-bottom: 1px dotted rgb(220,220,220);
list-style: none;
margin-bottom: 20px;
padding-bottom: 10px;
p {
&:hover {
.title .icon {
opacity: 1;
}
}
span.title {
color: $lighter-base-font-color;
float: left;
font-family: $sans-serif;
text-shadow: 0 1px rgba(255,255,255, 0.8);
span {
font-weight: 700;
margin-left: 10px;
text-transform: none;
.icon {
background-size: cover;
float: left;
height: 19px;
margin: 2px 8px 0 0;
opacity: 0.6;
@include transition(all, 0.15s, linear);
width: 19px;
&.email-icon {
@include background-image(url('/static/images/portal-icons/email-icon.png'));
}
&.location-icon {
@include background-image(url('/static/images/portal-icons/home-icon.png'));
}
&.language-icon {
@include background-image(url('/static/images/portal-icons/language-icon.png'));
}
}
}
span.data {
color: $lighter-base-font-color;
font-weight: 700;
margin-left: 12px;
}
}
}
}
}
......@@ -254,9 +287,11 @@
.course-work-icon {
background: rgb(200,200,200);
@include background-image(url('/static/images/portal-icons/pencil-icon.png'));
background-size: cover;
float: left;
height: 22px;
opacity: 0.7;
width: 22px;
}
......@@ -280,7 +315,7 @@
.progress {
@include box-shadow(0 1px 0 0 rgba(255,255,255, 0.6));
left: 40px;
left: 35px;
position: absolute;
right: 130px;
......
......@@ -17,6 +17,7 @@
@extend .animation-home-header-pop-up;
max-width: 1200px;
margin: 0 auto;
padding: 0 10px;
position: relative;
text-align: center;
......@@ -32,7 +33,7 @@
border: 1px solid rgb(100,100,100);
@include box-shadow(0 4px 25px 0 rgba(0,0,0, 0.5));
@include inline-block;
padding: 30px 50px 30px;
padding: 20px 30px 30px;
position: relative;
text-align: center;
z-index: 1;
......@@ -40,22 +41,10 @@
.title {
@include inline-block;
margin-right: 50px;
padding-right: 50px;
position: relative;
text-align: left;
vertical-align: middle;
&::before {
@extend .faded-vertical-divider;
content: "";
display: block;
height: 170px;
position: absolute;
right: 0px;
top: -20px;
}
&::after {
@extend .faded-vertical-divider-light;
content: "";
......@@ -99,10 +88,82 @@
}
}
.secondary-actions {
@include box-sizing(border-box);
@include clearfix;
float: left;
height: 47px;
width: flex-grid(6);
a.intro-video {
background: rgb(245,245,245);
@include background-image(linear-gradient(-90deg, rgb(250,250,250), rgb(235,235,235)));
border: 1px solid rgb(200,200,200);
@include border-radius(30px);
@include box-sizing(border-box);
@include box-shadow(inset 0 -1px 0 0 rgba(255,255,255, 0.8), inset 0 1px 0 0 rgba(255,255,255, 0.8));
@include clearfix;
display: block;
float: left;
height: 100%;
overflow: hidden;
text-align: middle;
width: flex-grid(6);
&:hover {
text-decoration: none;
p {
color: $base-font-color;
}
.video {
opacity: 1;
}
}
.video {
@include background-image(url('/static/images/shot-2-large.jpg'));
background-size: cover;
border-right: 1px solid rgb(200,200,200);
@include border-left-radius(30px);
@include box-shadow(1px 0 0 0 rgba(255,255,255, 0.6), inset 1px 0 0 0 rgba(255,255,255, 0.8), inset 0 0 0 1px rgba(255,255,255, 0.7));
float: left;
height: 100%;
opacity: 0.8;
position: relative;
@include transition(all, 0.15s, linear);
width: 60px;
vertical-align: middle;
.play {
@include background-image(url('/static/images/portal-icons/video-play-icon.png'));
background-size: cover;
height: 31px;
margin-left: -13px;
margin-top: -15px;
left: 50%;
position: absolute;
top: 50%;
width: 31px;
}
}
p {
color: $lighter-base-font-color;
font-style: italic;
padding-top: 10px;
text-align: center;
text-shadow: 0 1px rgba(255,255,255, 0.6);
@include transition(all, 0.15s, linear);
vertical-align: middle;
}
}
.social-sharing {
@include box-sizing(border-box);
float: left;
height: 44px;
margin-right: flex-gutter();
position: relative;
text-align: center;
width: flex-grid(6);
......@@ -163,20 +224,24 @@
}
}
}
}
.media {
background: #fff;
border: 1px solid rgb(200,200,200);
@include box-sizing(border-box);
float: left;
@include inline-block;
padding: 1px;
position: relative;
vertical-align: middle;
width: 210px;
//width: 210px;
width: flex-grid(3);
z-index: 2;
.hero {
height: 125px;
//height: 125px;
height: 100%;
overflow: hidden;
position: relative;
......
This source diff could not be displayed because it is too large. You can view the blob instead.
@import 'bourbon/bourbon';
@import 'base_styles/reset';
@import 'base_styles/font_face';
@import 'base_styles/base';
@import 'base_styles/base_mixins';
@import 'base_styles/base_extends';
@import 'base_styles/base_animations';
@import 'base/reset';
@import 'base/font_face';
@import 'base/variables';
@import 'base/base';
@import 'base/mixins';
@import 'base/extends';
@import 'base/animations';
// Courseware styles
@import 'sass_old/base/variables';
@import 'sass_old/base/extends';
@import 'sass_old/base/functions';
@import 'shared_styles/shared_forms';
@import 'shared_styles/shared_footer';
@import 'shared_styles/shared_header';
@import 'shared_styles/shared_list_of_courses';
@import 'shared_styles/shared_course_filter';
@import 'shared_styles/shared_modal';
// Multicourse styles
@import 'shared/forms';
@import 'shared/footer';
@import 'shared/header';
@import 'shared/course_object';
@import 'shared/course_filter';
@import 'shared/modal';
@import 'shared/activation_messages';
@import 'home';
@import 'dashboard';
@import 'course_object';
@import 'courseware_subnav';
@import 'courses';
@import 'course_about';
@import 'jobs';
@import 'about_pages';
@import 'press_release';
// Courseware styles
@import 'sass_old/courseware/courseware';
@import 'sass_old/courseware/sequence-nav';
@import 'sass_old/courseware/sidebar';
......
$gw-column: 60px;
$gw-gutter: 25px;
$fg-column: $gw-column;
$fg-gutter: $gw-gutter;
$fg-max-columns: 12;
$sans-serif: 'Open Sans', $verdana;
$serif: $georgia;
$base-font-color: rgb(60,60,60);
$lighter-base-font-color: rgb(160,160,160);
$blue: rgb(29,157,217);
$pink: rgb(182,37,104);
$yellow: rgb(255, 252, 221);
html, body {
background: rgb(250,250,250);
//background: rgb(77, 82, 99);
font-family: $sans-serif;
font-size: 1em;
line-height: 1em;
-webkit-font-smoothing: antialiased;
}
h1, h2, h3, h4, h5, h6 {
......@@ -99,8 +82,8 @@ a:link, a:visited {
.container {
@include clearfix;
margin: 0 auto 0;
max-width: 1200px;
width: flex-grid(12);
padding: 0px 10px;
width: grid-width(12);
}
.static-container {
......
......@@ -76,3 +76,16 @@
rgba(200,200,200, 0)));
border: none;
}
//Styles for Error messages
.error-message-colors {
background: $error-red;
border: 1px solid rgb(202, 17, 17);
color: rgb(143, 14, 14);
}
.success-message-colors {
background: rgb(99, 236, 137);
border: 1px solid rgb(17, 202, 54);
color: rgb(35, 143, 14);
}
$gw-column: 80px;
$gw-gutter: 20px;
$fg-column: $gw-column;
$fg-gutter: $gw-gutter;
$fg-max-columns: 12;
$sans-serif: 'Open Sans', $verdana;
$serif: $georgia;
$base-font-color: rgb(60,60,60);
$lighter-base-font-color: rgb(160,160,160);
$blue: rgb(29,157,217);
$pink: rgb(182,37,104);
$yellow: rgb(255, 252, 221);
$error-red: rgb(253, 87, 87);
.container.activation {
padding: 60px 0px 120px;
h1 {
margin-bottom: 20px;
padding: 10px;
&.invalid {
@extend .error-message-colors;
}
&.valid {
@extend .success-message-colors;
}
}
h1 + hr {
margin-bottom: 30px;
}
.message {
background: rgb(252,252,252);
border: 1px solid rgb(200,200,200);
@include box-shadow(0 3px 20px 0 rgba(0,0,0, 0.2));
@include border-radius(4px);
margin: 0 auto;
padding: 40px;
width: flex-grid(6);
}
}
.highlighted-courses, .find-courses {
.courses {
@include clearfix;
padding: 40px 15px 15px;
padding: 40px 0px 15px;
.course {
background: rgb(250,250,250);
......@@ -33,6 +33,7 @@
p {
color: rgb(255,255,255);
font-style: italic;
line-height: 1.2em;
padding: 4px 12px 5px;
}
......@@ -69,7 +70,11 @@
h2 {
color: $base-font-color;
font-family: $sans-serif;
font-size: 1em;
font-weight: 700;
margin-bottom: 0px;
overflow: hidden;
padding-top: 9px;
text-shadow: 0 1px rgba(255,255,255, 0.6);
text-overflow: ellipsis;
......
......@@ -12,11 +12,10 @@ footer {
}
nav {
@include box-sizing(border-box);
max-width: 1200px;
margin: 0 auto;
padding: 30px 10px 0;
width: flex-grid(12);
width: grid-width(12);
.top {
border-bottom: 1px solid rgb(200,200,200);
......
......@@ -42,5 +42,6 @@ form {
letter-spacing: 1px;
text-transform: uppercase;
vertical-align: top;
-webkit-font-smoothing: antialiased;
}
}
......@@ -9,12 +9,11 @@ header.global {
nav {
@include clearfix;
@include box-sizing(border-box);
height: 40px;
margin: 0 auto;
max-width: 1200px;
padding-top: 14px;
width: flex-grid(12);
padding: 14px 10px 0px;
width: grid-width(12);
}
h1.logo {
......@@ -136,57 +135,65 @@ header.global {
&.user {
float: right;
> li.primary {
display: block;
float: left;
margin: 0px;
> a {
margin: 0px;
@include border-right-radius(0px);
}
&:last-child {
> a {
@include border-radius(0 4px 4px 0);
border-left: none;
}
}
}
a.user-link {
padding: 10px 12px 10px 42px;
position: relative;
text-transform: none;
.avatar {
background: rgb(220,220,220);
@include border-radius(3px);
border: 1px solid rgb(80,80,80);
@include box-shadow(0 1px 0 0 rgba(255,255,255, 0.6));
height: 21px;
//background: rgb(220,220,220);
@include background-image(url('/static/images/portal-icons/home-icon.png'));
background-size: cover;
//@include border-radius(3px);
//border: 1px solid rgb(80,80,80);
//@include box-shadow(0 1px 0 0 rgba(255,255,255, 0.6));
height: 26px;
@include inline-block;
left: 8px;
opacity: 0.5;
overflow: hidden;
position: absolute;
top: 7px;
width: 21px;
&::after {
@include background-image(linear-gradient((-60deg), rgba(0,0,0, 0) 0%, rgba(0,0,0, 0.1) 50%, rgba(0,0,0, 0.2) 50%, rgba(0,0,0, 0.3) 100%));
content: "";
display: block;
height: 100%;
position: absolute;
right: 0px;
top: 0px;
width: 100%;
top: 4px;
@include transition(all, 0.15s, linear);
width: 26px;
}
img {
@include border-radius(4px);
display: block;
min-height: 100%;
min-width: 100%;
height: 100%;
&:hover {
.avatar {
opacity: 0.8;
}
}
}
ul.dropdown-menu {
background: rgb(252,252,252);
@include border-radius(4px);
@include box-shadow(0 1px 6px 0 rgba(0,0,0, 0.3));
border: 1px solid rgb(0,0,0);
@include background-image(linear-gradient(-90deg, rgba(0,0,0, 0.9) 0%,
rgba(0,0,0, 0.7) 100%));
@include box-shadow(0 2px 24px 0 rgba(0,0,0, 0.3));
border: 1px solid rgb(100,100,100);
display: none;
padding: 5px 10px;
position: absolute;
right: 4px;
right: 0px;
top: 50px;
width: 150px;
width: 170px;
z-index: 3;
&.expanded {
......@@ -196,8 +203,8 @@ header.global {
&::before {
background: transparent;
border: {
top: 6px solid rgba(0,0,0, 1);
right: 6px solid rgba(0,0,0, 1);
top: 6px solid rgba(252,252,252, 1);
right: 6px solid rgba(252,252,252, 1);
bottom: 6px solid transparent;
left: 6px solid transparent;
}
......@@ -214,7 +221,7 @@ header.global {
li {
display: block;
border-top: 1px solid rgba(0,0,0, 0.4);
border-top: 1px dotted rgba(200,200,200, 1);
@include box-shadow(inset 0 1px 0 0 rgba(255,255,255, 0.05));
&:first-child {
......@@ -223,31 +230,23 @@ header.global {
}
> a {
@include box-sizing(border-box);
border: 1px solid transparent;
@include border-radius(3px);
color: rgba(255,255,255, 0.9);
@include box-sizing(border-box);
color: $blue;
cursor: pointer;
display: block;
font-family: $serif;
height: auto;
line-height: 1em;
margin: 5px 0px;
overflow: hidden;
padding: 3px 5px 4px;
text-shadow: none;
text-overflow: ellipsis;
text-transform: none;
@include transition(padding, 0.1s, linear);
@include transition(padding, 0.15s, linear);
white-space: nowrap;
width: 100%;
&:hover {
background: $blue;
@include background-image(linear-gradient(-90deg, lighten($blue, 15%) 0%,
rgba($blue, 1) 100%));
border-color: rgba(0,0,0, 1);
@include box-shadow(none);
padding-left: 8px;
text-shadow: 0 -1px rgba(0,0,0, 0.2);
color: $base-font-color;
text-decoration: none;
}
}
}
......
......@@ -20,7 +20,7 @@
left: 50%;
padding: 8px;
position: absolute;
width: grid-width(6);
width: grid-width(5);
z-index: 12;
&.video-modal {
......@@ -107,7 +107,7 @@
}
#enroll_error, #login_error {
background: rgb(253, 87, 87);
background: $error-red;
border: 1px solid rgb(202, 17, 17);
color: rgb(143, 14, 14);
display: none;
......@@ -115,15 +115,9 @@
padding: 12px;
}
//#enroll {
//padding: 0 40px;
//h1 {
//font: normal 1em/1.6em $sans-serif;
//margin-bottom: 10px;
//text-align: left;
//}
//}
.activation-message {
padding: 0 40px 10px;
}
form {
margin-bottom: 12px;
......
......@@ -12,14 +12,16 @@
<section class="vision">
<section class="company-mission message left">
<div class="inner-wrapper">
<div class="photo">
<img src="">
</div>
<h2>Mission: Educate 1 billion people around the world</h2>
<p>“EdX represents a unique opportunity to improve education on our own campuses through online learning, while simultaneously creating a bold new educational path for millions of learners worldwide,” MIT President Susan Hockfield said.</p>
<p>Harvard President Drew Faust said, “edX gives Harvard and MIT an unprecedented opportunity to dramatically extend our collective reach by conducting groundbreaking research into effective education and by extending online access to quality higher education.”
</div>
<article>
<h2>About edX</h2>
<p>EdX is a joint partnership between The Massachusetts Institute of Technology (MIT) and Harvard University to offer online learning to millions of people around the world. EdX offer Harvard and MIT classes online for free. Through this partnership, with other partners to follow, the institutions aim to extend their collective reach to build a global community of online students.</p>
<p>MIT’s Director of the Computer Science and Artificial Intelligence Laboratory Anant Agarwal serves as the first president of edX, and Harvard’s Faculty of Arts and Sciences Dean Michael D. Smith leads faculty in developing courses. Along with offering online courses, the institutions will use edX to research how students learn and how technology can facilitate teaching—both on-campus and online.</p>
<p>EdX is based on an open-source technological platform that provides interactive educational materials designed specifically for the web, and is available to anyone in the world with an internet connection.</p>
<p>Harvard and MIT have created edX open-source software and invite interested institutions to join edX with their own educational content. EdX is a Cambridge-based not-for-profit, equally owned and funded by Harvard and MIT</p>
</article>
<hr class="fade-right-hr-divider">
</section>
......@@ -27,9 +29,11 @@
<div class="photo">
<img src="">
</div>
<h2>Mission: Educate 1 billion people around the world</h2>
<p>“EdX represents a unique opportunity to improve education on our own campuses through online learning, while simultaneously creating a bold new educational path for millions of learners worldwide,” MIT President Susan Hockfield said.</p>
<p>Harvard President Drew Faust said, “edX gives Harvard and MIT an unprecedented opportunity to dramatically extend our collective reach by conducting groundbreaking research into effective education and by extending online access to quality higher education.”
<article>
<h2>Harvard University</h2>
<p>Harvard University is devoted to excellence in teaching, learning, and research, and to developing leaders in many disciplines who make a difference globally. Harvard faculty are engaged with teaching and research to push the boundaries of human knowledge. For students who are excited to investigate the biggest issues of the 21st century, Harvard offers an unparalleled student experience and a generous financial aid program, with over $160 million awarded to more than 60% of our undergraduate students. The University has twelve degree-granting Schools in addition to the Radcliffe Institute for Advanced Study, offering a truly global education.</p>
<p>Established in 1636, Harvard is the oldest institution of higher education in the United States. The University, which is based in Cambridge and Boston, Massachusetts, has an enrollment of over 20,000 degree candidates, including undergraduate, graduate, and professional students. Harvard has more than 360,000 alumni around the world.</p>
</article>
<hr class="fade-left-hr-divider">
</section>
......@@ -37,9 +41,12 @@
<div class="photo">
<img src="">
</div>
<h2>Mission: Educate 1 billion people around the world</h2>
<p>“EdX represents a unique opportunity to improve education on our own campuses through online learning, while simultaneously creating a bold new educational path for millions of learners worldwide,” MIT President Susan Hockfield said.</p>
<p>Harvard President Drew Faust said, “edX gives Harvard and MIT an unprecedented opportunity to dramatically extend our collective reach by conducting groundbreaking research into effective education and by extending online access to quality higher education.”
<article>
<h2>Massachusetts Institute of Technology</h2>
<p>The Massachusetts Institute of Technology — a coeducational, privately endowed research university founded in 1861 — is dedicated to advancing knowledge and educating students in science, technology, and other areas of scholarship that will best serve the nation and the world in the 21st century. The Institute has close to 1,000 faculty and 10,000 undergraduate and graduate students. It is organized into five Schools: Architecture and Urban Planning; Engineering; Humanities, Arts, and Social Sciences; Sloan School of Management; and Science.</p>
<p>MIT's commitment to innovation has led to a host of scientific breakthroughs and technological advances. Seventy-eight MIT alumni, faculty, researchers and staff have won Nobel Prizes.</p>
<p>Current areas of research and education include neuroscience and the study of the brain and mind, bioengineering, cancer, energy, the environment and sustainable development, information sciences and technology, new media, financial technology, and entrepreneurship.</p>
</article>
</section>
</section>
</section>
......
<%inherit file="marketing.html" />
<%! from django.core.urlresolvers import reverse %>
<%inherit file="main.html" />
<section class="tos">
<div>
<%namespace name='static' file='static_content.html'/>
<section class="activation">
<section class="container activation">
<section class="message">
<h1>Account already active!</h1>
<!-- <p>Now go <a href="/">log in</a> and try the course!</a></p> -->
<p> This account has already been activated. You can log in at
the <a href="/">6.002x course page</a>.</p>
</div>
<hr class="horizontal-divider">
<p> This account has already been activated. You can now <a href="#login-modal" rel="leanModal">login</a>.</p>
</section>
</section>
<%inherit file="marketing.html" />
<section class="tos">
<div>
<h1>Activation Complete!</h1>
<!-- <p>Now go <a href="/">log in</a> and try the course!</a></p> -->
<p>Thanks for activating your account. You can log in at the <a href="/">6.002x course page</a>.</p>
</div>
<%! from django.core.urlresolvers import reverse %>
<%inherit file="main.html" />
<%namespace name='static' file='static_content.html'/>
<section class="container activation">
<section class="message">
<h1 class="valid">Activation Complete!</h1>
<hr class="horizontal-divider">
<p>Thanks for activating your account. You can now <a href="#login-modal" rel="leanModal">login</a>.</p>
</section>
</section>
<%inherit file="marketing.html" />
<%! from django.core.urlresolvers import reverse %>
<%inherit file="main.html" />
<section class="tos">
<div>
<h1>Activation Invalid</h1>
<%namespace name='static' file='static_content.html'/>
<p>Something went wrong. Check to make sure the URL you went to was
<section class="container activation">
<section class="message">
<h1 class="invalid">Activation Invalid</h1>
<hr class="horizontal-divider">
<p>Something went wrong. Check to make sure the URL you went to was
correct -- e-mail programs will sometimes split it into two
lines. If you still have issues, e-mail us to let us know what happened
at <a href="mailto:bugs@mitx.mit.edu">bugs@mitx.mit.edu</a>.</p>
at <a href="mailto:bugs@edx.org">bugs@edx.org</a>.</p>
<p>Or you can go back to the <a href="/">6.002x course page</a>.</p>
</div>
<p>Or you can go back to the <a href="/">home page</a>.</p>
</section>
</section>
......@@ -9,7 +9,7 @@
<header class="course-preview">
<a href="${reverse('about_course', args=[course.id])}">
<hgroup>
<h2>${course.get_about_section('title')}</h2>
<h2>${course.number} ${course.get_about_section('title')}</h2>
</hgroup>
<div class="info-link">&#x2794;</div>
</a>
......
......@@ -3,7 +3,7 @@
<%namespace name='static' file='static_content.html'/>
<section class="find-courses">
<header class="search">
<header class="search" style="background: url('/static/images/shot-2-large.jpg')">
<div class="inner-wrapper main-search">
<hgroup>
<div class="logo">
......@@ -16,7 +16,7 @@
<section class="container">
## I'm removing this for now since we aren't using it for the fall.
<%include file="course_filter.html" />
## <%include file="course_filter.html" />
<section class="courses">
%for course in courses:
<%include file="course.html" args="course=course" />
......
......@@ -11,13 +11,13 @@
<section class="user-info">
<ul>
<li>
<img src=""><p>Email<span>${ user.email }</span></p>
<span class="title"><div class="icon email-icon"></div>Email</span><span class="data">${ user.email }</span>
</li>
<li>
<img src=""><p>Location<span>${ user.profile.location }</span></p>
<span class="title"><div class="icon location-icon"></div>Location</span><span class="data">${ user.profile.location }</span>
</li>
<li>
<img src=""><p>Language<span>${ user.profile.language }</span></p>
<span class="title"><div class="icon language-icon"></div>Language</span><span class="data">${ user.profile.language }</span>
</li>
</ul>
</section>
......@@ -46,7 +46,7 @@
<p>Class Starts - <span>9/2/2012</span></div>
</section>
<section class="meta">
<div src="" class="course-work-icon"></div>
<div class="course-work-icon"></div>
<div class="progress">
<div class="meter">
<div class="meter-fill"></div>
......
......@@ -10,6 +10,7 @@
<a href="/t/about.html">About</a>
<a href="#">Blog</a>
<a href="/t/jobs.html">Jobs</a>
<a href="/t/contact.html">Contact</a>
</section>
<section class="social">
......
......@@ -7,11 +7,13 @@
<div class="outer-wrapper">
<div class="inner-wrapper">
<div class="title">
<h1>The Future of Online Education</h1>
<h1>Online education for anyone, anywhere, at anytime</h1>
<div class="main-cta">
<a href="${reverse('courses')}" class="find-courses">Find Courses</a>
<a href="#signup-modal" class="find-courses" rel="leanModal">Sign Up</a>
</div>
<div class="secondary-actions">
<div class="social-sharing">
<div class="sharing-message">Share with friends and family!</div>
<a href="#" class="share">
......@@ -24,16 +26,20 @@
<img src="${static.url('images/email-sharing.png')}">
</a>
</div>
</div>
<a href="#video-modal" class="media" rel="leanModal">
<div class="hero">
<img src="${static.url('images/courses/space1.jpg')}" />
<div class="play-intro"></div>
<a href="#video-modal" class="intro-video" rel="leanModal">
<!--
-<img src="${static.url('images/courses/space1.jpg')}" />
-->
<div class="video">
<div class="play"></div>
</div>
<p>Play intro video</p>
</a>
</div>
</div>
</div>
</div>
</header>
<section class="container">
......@@ -87,10 +93,10 @@
<section class="blog-posts">
<article>
<a href="#" class="post-graphics">
<img src="${static.url('images/courses/space1.jpg')}" />
<img src="${static.url('images/mongolia_post.jpeg')}" />
</a>
<div class="post-name">
<a href="">Online Classes Cut Costs, But Do They Dilute Brands?</a>
<a href="">Opening Doors For Exceptional Students: 6.002x in Mongolia.</a>
<p class="post-date">7/12/2012</p>
</div>
</article>
......
......@@ -22,6 +22,14 @@
<h2>We are currently looking for</h2>
<section class="jobs-listing">
<article id="technology-team" class="job">
<div class="inner-wrapper">
<h3>Technology Team</h3>
<p>[Looking for both back-end and front-end developers. Strong backgrounds in machine learning, education, user interaction design, big data, or social network analysis are desirable, but team members do wear many hats. Best candidate would be a masterful hacker who went and did startups after finishing their Ph.D. We should find a way to make some positions that parallel fellows, and can leverage MIT/Harvard prestige]</p>
<p>If you're interested in this position, send an e-mail to <a href="">content-engineer@edxonline.org</a></p>
</div>
</article>
<article id="edx-fellow" class="job">
<div class="inner-wrapper">
<h3>edX Fellow</h3>
......@@ -49,27 +57,20 @@
<p>If you're interested in this position, send an e-mail to <a href="">content-engineer@edxonline.org</a></p>
</div>
</article>
<article id="technology-team" class="job">
<div class="inner-wrapper">
<h3>Technology Team</h3>
<p>[Looking for both back-end and front-end developers. Strong backgrounds in machine learning, education, user interaction design, big data, or social network analysis are desirable, but team members do wear many hats. Best candidate would be a masterful hacker who went and did startups after finishing their Ph.D. We should find a way to make some positions that parallel fellows, and can leverage MIT/Harvard prestige]</p>
<p>If you're interested in this position, send an e-mail to <a href="">content-engineer@edxonline.org</a></p>
</div>
</article>
</section>
<section class="jobs-sidebar">
<h2>Positions</h2>
<nav>
<a href="#technology-team">Technology Team</a>
<a href="#edx-fellow">edX Fellow</a>
<a href="#content-engineer">Content Engineer</a>
<a href="#technology-team">Technology Team</a>
</nav>
<h2>How to Apply</h2>
<p>E-mail your resume, coverletter and any other materials to <a href="#">careers@edxonline.org</a></p>
<p>E-mail your resume, coverletter and any other materials to <a href="#">careers@edx.org</a></p>
<h2>Our Location</h2>
<p>11 Cambridge Center, Cambridge MA USA</p>
<p>11 Cambridge Center <br/>
Cambridge, MA 02142</p>
</section>
</section>
......
......@@ -17,7 +17,7 @@
<ol class="user">
<li class="primary">
<a href="${reverse('dashboard')}" class="user-link">
<span class="avatar"><img src="${static.url('images/profile.jpg')}" /></span>
<span class="avatar"></span>
${user.username}
</a>
</li>
......@@ -37,6 +37,7 @@
<a href="/t/about.html">About</a>
<a href="#">Blog</a>
<a href="${reverse('jobs')}">Jobs</a>
<a href="/t/contact.html">Contact</a>
<a href="#login-modal" id="login" rel="leanModal">Log In</a>
</li>
<li class="primary">
......
......@@ -11,7 +11,7 @@
<div class="intro-inner-wrapper">
<section class="intro">
<hgroup>
<h1>${course.get_about_section("title")}</h1><h2><a href="#">${course.get_about_section("university")}</a></h2>
<h1>${course.number}: ${course.get_about_section("title")}</h1><h2><a href="#">${course.get_about_section("university")}</a></h2>
</hgroup>
<div class="main-cta">
......@@ -47,6 +47,10 @@
<section class="course-staff">
<h2>Course staff</h3>
${course.get_about_section("instructors")}
<!--
<article class="teacher">
<div class="teacher-image">
<img src="${static.url('images/anant.jpg')}" />
......@@ -70,6 +74,7 @@
<h3>Piotr Mitros</h3>
<p>Research Scientist at MIT. His research focus is in finding ways to apply techniques from control systems to optimizing the learning process. Dr. Mitros has worked as an analog designer at Texas Instruments, Talking Lights, and most recently, designed the analog front end for a novel medical imaging modality for Rhythmia Medical.</p>
</article>
-->
</section>
<section class="requirements">
......@@ -98,9 +103,6 @@
<section class="course-sidebar">
<section class="course-summary">
<header>
<!--
-<a href="#" class="university-name">${course.get_about_section("university")}</a><span>${course.get_about_section("title")}</span>
-->
<div class="social-sharing">
<div class="sharing-message">Share with friends and family!</div>
<a href="#" class="share">
......@@ -116,10 +118,10 @@
</header>
<ol class="important-dates">
<li><img src=""><p>Classes Start</p><span class="start-date">7/12/12</span></li>
<li><img src=""><p>Final Exam</p><span class="final-date">12/09/12</span></li>
<li><img src=""><p>Course Length</p><span class="course-length">15 weeks</span></li>
<li><img src=""><p>Course Number</p><span class="course-number">${course.get_about_section("number")}</span></li>
<li><div class="icon start-icon"></div><p>Classes Start</p><span class="start-date">7/12/12</span></li>
<li><div class="icon final-icon"></div><p>Final Exam</p><span class="final-date">12/09/12</span></li>
<li><div class="icon length-icon"></div><p>Course Length</p><span class="course-length">15 weeks</span></li>
<li><div class="icon number-icon"></div><p>Course Number</p><span class="course-number">${course.get_about_section("number")}</span></li>
</ol>
</section>
</section>
......
<h1>Check your email</h1>
<p>An activation link has been sent to ${ email }, along with
<header>
<h2>Thanks For Registering!</h2>
<hr>
</header>
<p class='activation-message'>Please check your email. An activation link has been sent to <strong>${ email }</strong>, along with
instructions for activating your account.</p>
......@@ -2,13 +2,12 @@
<section id="signup-modal" class="modal signup-modal">
<div class="inner-wrapper">
<div id="enroll">
<header>
<h2>Sign Up for edX</h2>
<hr>
</header>
<div id="enroll">
<form id="enroll_form" method="post">
<div id="enroll_error" name="enroll_error"></div>
<label>E-mail</label>
......@@ -32,26 +31,27 @@
<input name="honor_code" type="checkbox" value="true">
I agree to the
<a href="/t/honor.html" target="blank">Honor Code</a>
, sumarized below as:
</label>
<div class="honor-code-summary">
<ul>
<li>
<p>Complete all mid-terms and final exams with only my own work.</p>
</li>
<li>
<p>Maintain only one account, and not share the username or password.</p>
</li>
<li>
<p>Not engage in any activity that would dishonestly improve my results, or improve or hurt those of others.</p>
</li>
<li>
<p>Not post answers to problems that are being used to assess student performance.</p>
</li>
</ul>
<hr>
</div>
<!--
-<div class="honor-code-summary">
- <ul>
- <li>
- <p>Complete all mid-terms and final exams with only my own work.</p>
- </li>
- <li>
- <p>Maintain only one account, and not share the username or password.</p>
- </li>
- <li>
- <p>Not engage in any activity that would dishonestly improve my results, or improve or hurt those of others.</p>
- </li>
- <li>
- <p>Not post answers to problems that are being used to assess student performance.</p>
- </li>
- </ul>
- <hr>
-</div>
-->
<div class="submit">
<input name="submit" type="submit" value="Create My Account">
......
......@@ -3,13 +3,13 @@
<%namespace name='static' file='static_content.html'/>
<section class="university-profile">
<header class="search">
<header class="search" style="background: url('/static/images/shot-5-large.jpg')">
<div class="inner-wrapper university-search">
<hgroup>
<div class="logo">
<img src="${static.url('images/harvard.png')}" />
<img src="${static.url('images/mit.png')}" />
</div>
<h1>HarvardX</h1>
<h1>MITx</h1>
</hgroup>
</div>
</header>
......
......@@ -88,9 +88,8 @@ end
# Per System tasks
desc "Run all django tests on our djangoapps for the #{system}"
task "test_#{system}" => [report_dir, :predjango, "#{system}:collectstatic:test"] do
run_tests(system, report_dir)
end
task "test_#{system}" => ["#{system}:collectstatic:test", "fasttest_#{system}"]
# Have a way to run the tests without running collectstatic -- useful when debugging without
# messing with static files.
task "fasttest_#{system}" => [report_dir, :predjango] do
......
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